Skip to content

Commit

Permalink
Merge branch 'devel' into CB-4382-anonymous-access-restricted-error
Browse files Browse the repository at this point in the history
  • Loading branch information
Wroud authored Jan 18, 2024
2 parents 4941d4a + 10c1b37 commit c74143e
Show file tree
Hide file tree
Showing 68 changed files with 963 additions and 312 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,13 @@
enableBruteForceProtection: "${CLOUDBEAVER_BRUTE_FORCE_PROTECTION_ENABLED:true}",
maxFailedLogin: "${CLOUDBEAVER_MAX_FAILED_LOGINS:10}",
minimumLoginTimeout: "${CLOUDBEAVER_MINIMUM_LOGIN_TIMEOUT:1}",
blockLoginPeriod: "${CLOUDBEAVER_BLOCK_PERIOD:300}"
blockLoginPeriod: "${CLOUDBEAVER_BLOCK_PERIOD:300}",
passwordPolicy: {
minLength: "${CLOUDBEAVER_POLICY_MIN_LENGTH:8}",
requireMixedCase: "${CLOUDBEAVER_POLICY_REQUIRE_MIXED_CASE:true}",
minNumberCount: "${CLOUDBEAVER_POLICY_MIN_NUMBER_COUNT:1}",
minSymbolCount: "${CLOUDBEAVER_POLICY_MIN_SYMBOL_COUNT:0}"
}
},

database: {
Expand Down
12 changes: 12 additions & 0 deletions config/sample-databases/SQLiteConfiguration/cloudbeaver.conf
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,18 @@
maxConnections: 100,
validationQuery: "SELECT 1"
}
},
sm: {
enableBruteForceProtection: "${CLOUDBEAVER_BRUTE_FORCE_PROTECTION_ENABLED:true}",
maxFailedLogin: "${CLOUDBEAVER_MAX_FAILED_LOGINS:10}",
minimumLoginTimeout: "${CLOUDBEAVER_MINIMUM_LOGIN_TIMEOUT:1}",
blockLoginPeriod: "${CLOUDBEAVER_BLOCK_PERIOD:300}",
passwordPolicy: {
minLength: "${CLOUDBEAVER_POLICY_MIN_LENGTH:8}",
requireMixedCase: "${CLOUDBEAVER_POLICY_REQUIRE_MIXED_CASE:true}",
minNumberCount: "${CLOUDBEAVER_POLICY_MIN_NUMBER_COUNT:1}",
minSymbolCount: "${CLOUDBEAVER_POLICY_MIN_SYMBOL_COUNT:0}"
}
}

},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.model.security.SMAuthProviderCustomConfiguration;

import java.util.Map;

Expand All @@ -28,15 +29,21 @@
*/
public interface SMAuthProviderFederated {

/**
* Returns new identifying credentials which can be used to find/create user in database
*/
@NotNull
String getSignInLink(String id, @NotNull Map<String, Object> providerConfig) throws DBException;


/**
* @return a common link for logout, not related with the user context
*/
@NotNull
String getSignOutLink(String id, @NotNull Map<String, Object> providerConfig) throws DBException;
String getCommonSignOutLink(String id, @NotNull Map<String, Object> providerConfig) throws DBException;

default String getUserSignOutLink(
@NotNull SMAuthProviderCustomConfiguration providerConfig,
@NotNull Map<String, Object> userCredentials
) throws DBException {
return getCommonSignOutLink(providerConfig.getId(), providerConfig.getParameters());
}

@Nullable
String getMetadataLink(String id, @NotNull Map<String, Object> providerConfig) throws DBException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,6 @@ void closeAuth() {
authProviderInstance.closeSession(session, authSession);
} catch (Exception e) {
log.error(e);
} finally {
authSession = null;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,7 @@ public void close() {
super.close();
}

private void clearAuthTokens() throws DBException {
private List<WebAuthInfo> clearAuthTokens() throws DBException {
ArrayList<WebAuthInfo> tokensCopy;
synchronized (authTokens) {
tokensCopy = new ArrayList<>(this.authTokens);
Expand All @@ -623,6 +623,7 @@ private void clearAuthTokens() throws DBException {
removeAuthInfo(ai);
}
resetAuthToken();
return tokensCopy;
}

public DBRProgressMonitor getProgressMonitor() {
Expand Down Expand Up @@ -873,18 +874,23 @@ private void removeAuthInfo(WebAuthInfo oldAuthInfo) {
}
}

public void removeAuthInfo(String providerId) throws DBException {
public List<WebAuthInfo> removeAuthInfo(String providerId) throws DBException {
List<WebAuthInfo> oldInfo;
if (providerId == null) {
clearAuthTokens();
oldInfo = clearAuthTokens();
} else {
WebAuthInfo authInfo = getAuthInfo(providerId);
if (authInfo != null) {
removeAuthInfo(authInfo);
oldInfo = List.of(authInfo);
} else {
oldInfo = List.of();
}
}
if (authTokens.isEmpty()) {
resetUserState();
}
return oldInfo;
}

public List<DBACredentialsProvider> getContextCredentialsProviders() {
Expand Down Expand Up @@ -921,7 +927,7 @@ public boolean provideAuthParameters(
.create();

credGson.fromJson(credGson.toJsonTree(configuration.getAuthProperties()), credentials.getClass());
configuration.getAuthModel().saveCredentials(dataSourceContainer, configuration, credentials);
configuration.getAuthModel().provideCredentials(dataSourceContainer, configuration, credentials);
} catch (DBException e) {
addSessionError(e);
log.error(e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ private String buildRedirectUrl(String baseUrl) {
public String getSignOutLink() throws DBException {
SMAuthProvider<?> instance = providerDescriptor.getInstance();
return instance instanceof SMAuthProviderFederated
? ((SMAuthProviderFederated) instance).getSignOutLink(getId(), config.getParameters())
? ((SMAuthProviderFederated) instance).getCommonSignOutLink(getId(), config.getParameters())
: null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,13 @@ type WebServiceConfig {
bundleVersion: String!
}

type PasswordPolicyConfig @since(version: "23.3.3") {
minLength: Int!
minNumberCount: Int!
minSymbolCount: Int!
requireMixedCase: Boolean!
}

type ProductInfo {
id: ID!
version: String!
Expand Down Expand Up @@ -152,6 +159,7 @@ type ServerConfig {
defaultNavigatorSettings: NavigatorSettings!
disabledDrivers: [ID!]!
resourceQuotas: Object!
passwordPolicyConfiguration: PasswordPolicyConfig! @since(version: "23.3.3")
}

type SessionInfo {
Expand Down
24 changes: 23 additions & 1 deletion server/bundles/io.cloudbeaver.server/schema/service.sql.graphqls
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,8 @@ extend type Mutation {
addedRows: [ SQLResultRow! ],
): String!

#Return BLOB name
# Returns BLOB name
@deprecated(reason: "23.3.3") # use sqlReadLobValue
readLobValue(
projectId: ID,
connectionId: ID!,
Expand All @@ -341,6 +342,27 @@ extend type Mutation {
row: [ SQLResultRow! ]!
): String!

@since(version: "23.3.3")
sqlReadLobValue(
projectId: ID,
connectionId: ID!,
contextId: ID!,
resultsId: ID!,
lobColumnIndex: Int!,
row: SQLResultRow!
): String!

# Returns full string value ignoring any limits
@since(version: "23.3.3")
sqlReadStringValue(
projectId: ID,
connectionId: ID!,
contextId: ID!,
resultsId: ID!,
columnIndex: Int!,
row: SQLResultRow!
): String!

# Returns SQLExecuteInfo
asyncSqlExecuteResults(taskId: ID!): SQLExecuteInfo !

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import io.cloudbeaver.registry.WebServiceRegistry;
import io.cloudbeaver.server.CBApplication;
import io.cloudbeaver.server.CBPlatform;
import io.cloudbeaver.service.security.PasswordPolicyConfiguration;
import org.jkiss.dbeaver.model.meta.Property;
import org.jkiss.dbeaver.model.navigator.DBNBrowseSettings;
import org.jkiss.dbeaver.registry.language.PlatformLanguageDescriptor;
Expand Down Expand Up @@ -217,4 +218,9 @@ public String getDefaultAuthRole() {
public String getDefaultUserTeam() {
return application.getAppConfiguration().getDefaultUserTeam();
}

@Property
public PasswordPolicyConfiguration getPasswordPolicyConfiguration() {
return application.getSecurityManagerConfiguration().getPasswordPolicyConfiguration();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import io.cloudbeaver.WebServiceUtils;
import io.cloudbeaver.auth.CBAuthConstants;
import io.cloudbeaver.auth.NoAuthCredentialsProvider;
import io.cloudbeaver.service.security.PasswordPolicyConfiguration;
import io.cloudbeaver.model.app.BaseWebApplication;
import io.cloudbeaver.model.app.WebAuthApplication;
import io.cloudbeaver.model.app.WebAuthConfiguration;
Expand Down Expand Up @@ -231,6 +232,10 @@ public Map<String, Object> getProductConfiguration() {
return productConfiguration;
}

public SMControllerConfiguration getSecurityManagerConfiguration() {
return securityManagerConfiguration;
}

public SMAdminController getSecurityController() {
return securityController;
}
Expand Down Expand Up @@ -592,7 +597,7 @@ protected void parseConfiguration(Map<String, Object> configProps) throws DBExce
enableSecurityManager);
//SM config
gson.fromJson(
gson.toJsonTree(JSONUtils.getObject(serverConfig, CBConstants.PARAM_SM_CONFIGURATION)),
gson.toJson(JSONUtils.getObject(serverConfig, CBConstants.PARAM_SM_CONFIGURATION)),
SMControllerConfiguration.class
);
// App config
Expand Down Expand Up @@ -772,11 +777,14 @@ protected GsonBuilder getGsonBuilder() {
InstanceCreator<CBAppConfig> appConfigCreator = type -> appConfiguration;
InstanceCreator<DataSourceNavigatorSettings> navSettingsCreator = type -> (DataSourceNavigatorSettings) appConfiguration.getDefaultNavigatorSettings();
InstanceCreator<SMControllerConfiguration> smConfigCreator = type -> securityManagerConfiguration;
InstanceCreator<PasswordPolicyConfiguration> smPasswordPoliceConfigCreator =
type -> securityManagerConfiguration.getPasswordPolicyConfiguration();
return new GsonBuilder()
.setLenient()
.registerTypeAdapter(CBAppConfig.class, appConfigCreator)
.registerTypeAdapter(DataSourceNavigatorSettings.class, navSettingsCreator)
.registerTypeAdapter(SMControllerConfiguration.class, smConfigCreator);
.registerTypeAdapter(SMControllerConfiguration.class, smConfigCreator)
.registerTypeAdapter(PasswordPolicyConfiguration.class, smPasswordPoliceConfigCreator);
}

protected void readAdditionalConfiguration(Map<String, Object> rootConfig) throws DBException {
Expand Down Expand Up @@ -1042,6 +1050,7 @@ protected Map<String, Object> collectConfigurationProperties(
}
serverConfigProperties.put(CBConstants.PARAM_DB_CONFIGURATION, databaseConfigProperties);
}
savePasswordPolicyConfig(originServerConfig, serverConfigProperties);
}
{
var appConfigProperties = new LinkedHashMap<String, Object>();
Expand Down Expand Up @@ -1151,6 +1160,30 @@ protected Map<String, Object> collectConfigurationProperties(
return rootConfig;
}

private void savePasswordPolicyConfig(Map<String, Object> originServerConfig, LinkedHashMap<String, Object> serverConfigProperties) {
// save password policy configuration
var passwordPolicyProperties = new LinkedHashMap<String, Object>();

var oldRuntimePasswordPolicyConfig = JSONUtils.getObject(
JSONUtils.getObject(originServerConfig, CBConstants.PARAM_SM_CONFIGURATION),
CBConstants.PARAM_PASSWORD_POLICY_CONFIGURATION
);
Gson gson = getGson();
Map<String, Object> passwordPolicyConfig = gson.fromJson(
gson.toJsonTree(securityManagerConfiguration.getPasswordPolicyConfiguration()),
JSONUtils.MAP_TYPE_TOKEN
);
if (!CommonUtils.isEmpty(passwordPolicyConfig) && !isDistributed()) {
for (Map.Entry<String, Object> mp : passwordPolicyConfig.entrySet()) {
copyConfigValue(oldRuntimePasswordPolicyConfig, passwordPolicyProperties, mp.getKey(), mp.getValue());
}
serverConfigProperties.put(
CBConstants.PARAM_SM_CONFIGURATION,
Map.of(CBConstants.PARAM_PASSWORD_POLICY_CONFIGURATION, passwordPolicyProperties)
);
}
}

////////////////////////////////////////////////////////////////////////
// License management

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public class CBConstants {
public static final String PARAM_DEVEL_MODE = "develMode";
public static final String PARAM_SECURITY_MANAGER = "enableSecurityManager";
public static final String PARAM_SM_CONFIGURATION = "sm";
public static final String PARAM_PASSWORD_POLICY_CONFIGURATION = "passwordPolicy";

public static final int DEFAULT_SERVER_PORT = 8080;
//public static final String DEFAULT_SERVER_NAME = "CloudBeaver Web Server";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,18 @@ WebSQLExecuteInfo updateResultsDataBatch(

@WebAction
String readLobValue(
@NotNull WebSQLContextInfo contextInfo,
@NotNull String resultsId,
@NotNull Integer lobColumnIndex,
@Nullable List<WebSQLResultsRow> row) throws DBWebException;
@NotNull WebSQLContextInfo contextInfo,
@NotNull String resultsId,
@NotNull Integer lobColumnIndex,
@NotNull WebSQLResultsRow row) throws DBWebException;

@NotNull
@WebAction
String getCellValue(
@NotNull WebSQLContextInfo contextInfo,
@NotNull String resultsId,
@NotNull Integer lobColumnIndex,
@NotNull WebSQLResultsRow row) throws DBWebException;

@WebAction
String updateResultsDataBatchScript(
Expand Down
Loading

0 comments on commit c74143e

Please sign in to comment.