dbeaver/cloudbeaver#4564 change db user password - #4586
Conversation
Signed-off-by: Tobias Harnickell <tobias.harnickell@bedag.ch>
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 14 |
| Duplication | 0 |
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
|
Hello @TobyTheHutt Thanks for the contribution. |
There was a problem hiding this comment.
Pull request overview
Adds database-user password changes for editable connections, gated by server configuration.
Changes:
- Adds the connection security menu and password dialog.
- Adds the GraphQL mutation, driver-adapter dispatch, persistence, and audit events.
- Adds an administrator-controlled feature flag.
Reviewed changes
Copilot reviewed 26 out of 28 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
webapp/yarn.lock |
Updates a local package checksum. |
webapp/packages/plugin-connections/src/locales/en.ts |
Adds password-dialog strings. |
webapp/packages/plugin-connections/src/ContextMenu/MENU_CONNECTION_SECURITY.ts |
Defines the Security submenu. |
webapp/packages/plugin-connections/src/ContextMenu/ConnectionMenuBootstrap.ts |
Registers the menu action and dialog. |
webapp/packages/plugin-connections/src/ContextMenu/ChangeDatabasePasswordDialog/ChangeDatabasePasswordDialog.tsx |
Implements the password form and mutation call. |
webapp/packages/plugin-connections/src/ContextMenu/Actions/ACTION_CONNECTION_CHANGE_DB_PASSWORD.ts |
Defines the password-change action. |
webapp/packages/plugin-administration/src/locales/en.ts |
Adds administration labels. |
webapp/packages/plugin-administration/src/ConfigurationWizard/ServerConfiguration/ServerConfigurationFormPart.ts |
Loads the feature flag state. |
webapp/packages/plugin-administration/src/ConfigurationWizard/ServerConfiguration/IServerConfigurationFormPartState.ts |
Extends configuration validation. |
webapp/packages/plugin-administration/src/ConfigurationWizard/ServerConfiguration/Form/ServerConfigurationSecurityForm.tsx |
Adds the security toggle. |
webapp/packages/core-sdk/src/queries/fragments/ServerConfig/ServerConfig.gql |
Queries the feature flag. |
webapp/packages/core-sdk/src/queries/connections/changeConnectionUserPassword.gql |
Defines the client mutation. |
webapp/packages/core-root/src/ServerConfigResource.ts |
Exposes the feature flag. |
server/bundles/io.cloudbeaver.service.admin/schema/service.admin.graphqls |
Extends admin configuration input. |
server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/core/WebServiceBindingCore.java |
Binds the mutation resolver. |
server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/core/impl/WebServiceCore.java |
Implements password changes and auditing. |
server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/core/DBWServiceCore.java |
Declares the secured service method. |
server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/events/WSSecurityAuditEventHandler.java |
Logs audit events. |
server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/events/WSSecurityAuditEvent.java |
Defines audit payloads. |
server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/model/WebServerConfig.java |
Publishes the feature flag. |
server/bundles/io.cloudbeaver.server/schema/service.core.graphqls |
Adds the flag and mutation schema. |
server/bundles/io.cloudbeaver.server/plugin.xml |
Registers the audit handler. |
server/bundles/io.cloudbeaver.server.ce/src/io/cloudbeaver/server/CBServerConfigurationMapper.java |
Maps the flag into application configuration. |
server/bundles/io.cloudbeaver.server.ce/src/io/cloudbeaver/server/CBServerConfigurationController.java |
Persists the flag. |
server/bundles/io.cloudbeaver.server.ce/src/io/cloudbeaver/model/config/AdminServerConfig.java |
Models the admin flag. |
server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/WebConnectionInfo.java |
Removes trailing whitespace. |
server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/config/CBAppConfig.java |
Stores the feature flag. |
server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/app/WebAppConfiguration.java |
Adds the configuration interface default. |
Suppressed comments (1)
server/bundles/io.cloudbeaver.server/schema/service.core.graphqls:918
- This new public mutation is missing the required
@sincedirective.
): Boolean!
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| @NotNull Map<String, Object> connectionConfig | ||
| ) throws DBWebException; | ||
|
|
||
| @WebProjectAction(requireProjectPermissions = {RMConstants.PERMISSION_PROJECT_DATASOURCES_EDIT}) |
There was a problem hiding this comment.
Yes it does contradict the issue. I started implementing the shape and realized that it doesn't make sense to have a per-team pw-reset block if the user can just proceed to change their password through an SQL prompt. Reasons to block PW-Resets are for shared-connections which use service accounts (when the user doesn't have edit permission on the connection object), or when an external authentication mechanism like RADIUS or OIDC are in-use.
If the user has permission to run statements, they usually have permission to change their passwords on the DB technologies known to me.
The only narrow use-case in which this change would expose an undesired credential change is, if the database was set up with PERMISSION_PROJECT_DATASOURCES_EDIT or an analogue setting, while having no SQL execution rights. This would allow the user to change the password through the GUI while they couldn't through an SQL worksheet. However, this is extremely specific and the only rationale I could think of to have per-team PW-update settings.
I did generally not treat the issue as a hard policy or contract and deviated for these reasons. But I can change it, if that's desired.
| ) throws DBWebException { | ||
| DBPDataSourceContainer container = null; | ||
| try { | ||
| requireServerFlagEnabled(webSession, projectId, connectionId); |
There was a problem hiding this comment.
This is identical to the old @WebAction shape and not something I introduced. I can fix this with my PR, if that's desired. Framework-level permission denials appear in the server request log.
| String userName = container.getConnectionConfiguration().getUserName(); | ||
| if (!CommonUtils.isEmpty(userName)) { | ||
| return userName; | ||
| } |
| container.getConnectionConfiguration().setUserPassword(newPassword); | ||
| container.getActualConnectionConfiguration().setUserPassword(newPassword); | ||
| persisted = container.isTemporary() || container.persistConfiguration(); |
| if (newPassword.length() > MAX_PASSWORD_LENGTH) { | ||
| emitPasswordChangeAudit(webSession, container, projectId, connectionId, | ||
| WSSecurityAuditEvent.Kind.GATE_REJECTED, "PASSWORD_TOO_LONG", null); | ||
| throw new DBWebException( | ||
| "Password exceeds the maximum length of " + MAX_PASSWORD_LENGTH + " characters."); | ||
| } | ||
| if (containsBlockedPasswordChar(newPassword)) { |
There was a problem hiding this comment.
PasswordPolicyConfig governs CloudBeaver user account passwords, not DB user passwords. DB user password policy is the DB's concern. In this PR, I surface DB policy rejections verbatim via DBWebException. Applying the CB policy here would enforce the wrong layer.
| applyPasswordChange(webSession, container, projectId, connectionId, manager, userName, oldPassword, newPassword); | ||
| persistNewPassword(webSession, container, projectId, connectionId, newPassword); | ||
| safeDisconnect(webSession, container); |
| adminCredentialsSaveEnabled: Boolean! | ||
|
|
||
| "Defines if the change-DB-password mutation is enabled server-wide" | ||
| dbUserPasswordChangeEnabled: Boolean! |
| "Whether saving credentials is allowed" | ||
| adminCredentialsSaveEnabled: Boolean | ||
| "Whether the change-DB-password mutation is enabled server-wide" | ||
| dbUserPasswordChangeEnabled: Boolean |
| @Override | ||
| public boolean changeConnectionUserPassword( |
|
I looked at the Copilot feedback and commented or reacted to it based on my personal judgement. I'll provide a follow-up commit after the human maintainer review and further instructions. This PR should not directly close the linked issue. It only covers the DB user password change. It does not yet cover the password-change prompt upon an expired DB user password, which was the original intent of the linked issue. If any rephrasing or re-specification of the issue is desired, let me know and I'll be on it. |
Summary
Relates to #4564
Adds a
Security > Change database passwordcontext-menu action on connections. The action opens a modal dialog and calls a new GraphQL mutation that invokes the DBeaver coreDBAUserPasswordManageradapter of the connected driver.Design
dbUserPasswordChangeEnabledgates the mutation server-wide. Default isfalse. Persistence goes throughCBAppConfig,AdminServerConfig,CBServerConfigurationController,CBServerConfigurationMapper, andWebServerConfig. Admin toggle lives in Configuration Wizard > Security.changeConnectionUserPassword(projectId: ID, connectionId: ID!, oldPassword: String!, newPassword: String!): Boolean!. Guard:@WebProjectAction(requireProjectPermissions = {PERMISSION_PROJECT_DATASOURCES_EDIT}). Both password parameters carry@WebParameterSecureto keep them out of logs.DBWebExceptionwrapping the driver's exception. Callers receive the original SQL state, message, and cause chain.connection.canEditis true. Backend re-checks the project permission on every call.cb_security_audittopic with kindsATTEMPTED,SUCCEEDED,FAILED, andGATE_REJECTED. Payload carriessessionId,userId,projectId,connectionId,driverId,kind,reasonCode,errorClass. No plaintext passwords.Screenshots:
Details
PW-Reset Flag:
PW-Change navigation:
PW-Change dialog:
PW-Change confirmation:

Engine coverage
Dispatch runs through the DBeaver core
DBAUserPasswordManageradapter. Verified against Oracle 21c XE, PostgreSQL 16, and SQL Server 2022. Engines whose driver ships an adapter (Greenplum, CockroachDB, Exasol, Vertica) inherit support without further code changes. Drivers without an adapter (H2, MySQL) returnGATE_REJECTED reasonCode=DIALECT_UNSUPPORTEDin the audit trail andThis driver does not support password change from CloudBeaver.in the notification.Out of scope
ORA-28001, MySQL1820, SQL Server18488).Test plan
Enable database user password changein Configuration Wizard or Server Administration > Security.Security > Change database password. Submitoldpw,newpw,newpw. Reconnect withnewpwsucceeds. Reconnect witholdpwreturnsSQLSTATE 28P01or technology equivalent.Securitysubmenu is absent.datasources-editon the project sees no menu. Direct GraphQL mutation returns a permission-denied response.ORA-28008: invalid old password. On SQL Server:Msg 15116.This driver does not support password change from CloudBeaver.. Audit linekind=GATE_REJECTED reasonCode=DIALECT_UNSUPPORTED.docker logs cloudbeaver-dev | grep cb_security_auditshows oneATTEMPTED+ oneSUCCEEDEDper successful change,ATTEMPTED+FAILEDwitherrorClasson driver rejection, and no plaintext passwords.