-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support SecretValue for DatabaseCluster masterUser.username #7927
Comments
Hey @asnaseer-resilient , thanks for opening the issue, but I'm not sure what you're asking for here. The code you show for how you're achieving that today is exactly how I would do it. What's your ask here? Thanks, |
The current code uses the secrets differently for the username vs the password, e.g. in here:
notice that the username needs a .toString() (i.e. as a String data type in Typescript) before it is passed into the masterUser structure whereas the password value can be passed in as-is (i.e. as SecretValue data type in Typescript). It would be nice to have them both consistent - something like this:
|
So here's a quick overview of the options as they exist today: DatabaseInstanceProps {
masterUsername: string;
masterUserPassword?: secretsmanager.SecretValue;
masterUserPasswordEncryptionKey?: kms.Key;
}
DatabaseInstanceFromSnapshotProps {
masterUsername: string; // Can only be specified if generateMasterUserPassword is true
masterUserPassword?: secretsmanager.SecretValue; // Can only be specified if generateMasterUserPassword is false
masterUserPasswordEncryptionKey?: kms.Key; // Only applies if generateMasterUserPassword is true
generateMasterUserPassword?: boolean;
}
DatabaseClusterProps {
masterUser: Login;
}
Login {
username: string;
password?: secretsmanager.SecretValue;
encryptionKey?: kms.Key;
}
DatabaseClusterFromSnapshotProps {
// No login-related props
} Certainly, the inconsistency between the individual properties (on Instances) and the Login interface (for Clusters) is something that could be addressed. As far as this feature request itself, I see four options: Option 1: Introduce a new optional property to Login {
username?: string;
usernameSecretValue?: secretsmanager.SecretValue;
password?: secretsmanager.SecretValue;
encryptionKey?: kms.Key;
} This places the burden on the instance & cluster classes to validate everything's ok, and doesn't really seem to add to the aesthetics/usability of the API as a whole (IMO). Option 2: Introduce a new optional property to Login {
username?: string;
password?: secretsmanager.SecretValue;
encryptionKey?: kms.Key;
secret?: secretsmanager.Secret; // Must have a "username" and "password" field in the secret body.
} The usage here would be to either specify one (or more) of the existing fields, or just the new Option 3: Replace the current class Login {
public static fromSecret(secret: Secret): Login // Assumes secret with "username" and "password" fields.
public static fromUsername(username: string, password?: SecretValue, key?: Key): Login
public readonly secret: Secret;
}
DatabaseInstanceProps {
masterUser?: Login;
}
DatabaseClusterProps {
masterUser?: Login;
} This is perhaps the most structured/modeled, but is also a definite breaking change for every CDK RDS customer. It's not clear that the value here is worth the breaking change. Option 4: Do nothing; decide that this consistency for applying existing secrets isn't worth the extra (potentially confusing) props or breaking changes. Open to feedback from the community here; I'll also be conferring internally to see what the team thinks. |
I vote for option 3, and including a nice message in the Changelog explaining how to migrate. I don't think it will be very intrusive 🙂. |
See #7927 (comment) for motivation and design. The current way of specifying master user logins for `DatabaseInstance` and `DatabaseCluster` is inconsistent between the two and introduces some awkward usage when creating a login from an existing `Secret`. This change converts the existing `Login` interface (used by the `DatabaseCluster`) into a class with factory methods for username/password or secret-based logins. This also then re-uses that same interface for `DatabaseInstance`. The one exception now will be `DatabaseInstanceFromSnapshot`, which has specific requirements that deserved its own interface (`SnapshotLogin`). As a side effect of this approach, existing `DatabaseCluster` users -- in Typescript at least -- will not be broken. For example, the following are equivalent: ```ts new rds.DatabaseCluster(this, 'Cluster1', { // Existing usage masterUser: { username: 'admin', }, // New usage masterUser: Login.fromUsername('admin'), }); ``` fixes #7927 BREAKING CHANGE: `DatabaseInstanceProps` and `DatabaseInstanceFromSnapshotProps` - `masterUsername`, `masterUserPassword` and `masterUserPasswordEncryptionKey` moved to `masterUser` as a new `Login` class. * **rds:** `Login` converted from interface to class with factory methods. Use `Login.fromUsername` to replace existing usage.
See #7927 (comment) for motivation and design. The current way of specifying master user logins for `DatabaseInstance` and `DatabaseCluster` is inconsistent between the two and introduces some awkward usage when creating a login from an existing `Secret`. This change converts the existing `Login` interface (used by the `DatabaseCluster`) into a class with factory methods for username/password or secret-based logins. This also then re-uses that same interface for `DatabaseInstance`. The one exception now will be `DatabaseInstanceFromSnapshot`, which has specific requirements that deserved its own interface (`SnapshotLogin`). As a side effect of this approach, existing `DatabaseCluster` users -- in Typescript at least -- will not be broken. For example, the following are equivalent: ```ts new rds.DatabaseCluster(this, 'Cluster1', { // Existing usage masterUser: { username: 'admin', }, // New usage masterUser: Login.fromUsername('admin'), }); ``` fixes #7927 BREAKING CHANGE: `DatabaseInstanceProps` and `DatabaseInstanceFromSnapshotProps` - `masterUsername`, `masterUserPassword` and `masterUserPasswordEncryptionKey` moved to `masterUser` as a new `Login` class. * **rds:** `Login` converted from interface to class with factory methods. Use `Login.fromUsername` to replace existing usage.
#10458) See #7927 (comment) for motivation and design. The current way of specifying master user logins for `DatabaseInstance` and `DatabaseCluster` is inconsistent between the two and introduces some awkward usage when creating a login from an existing `Secret`. This change converts the existing `Login` interface (used by the `DatabaseCluster`) into a class with factory methods for username/password or secret-based logins. This also then re-uses that same interface for `DatabaseInstance`. The one exception now will be `DatabaseInstanceFromSnapshot`, which has specific requirements that deserved its own interface (`SnapshotLogin`). As a side effect of this approach, existing `DatabaseCluster` users -- in Typescript at least -- will not be broken. For example, the following are equivalent: ```ts new rds.DatabaseCluster(this, 'Cluster1', { // Existing usage masterUser: { username: 'admin', }, // New usage masterUser: Login.fromUsername('admin'), }); ``` Lastly, this change makes the whole `masterUser` prop optional, as there's no good reason why we can't default a username. fixes #7927 BREAKING CHANGE: `DatabaseInstanceProps` and `DatabaseInstanceFromSnapshotProps` - `masterUsername`, `masterUserPassword` and `masterUserPasswordEncryptionKey` moved to `credentials` as a new `Credentials` class. * **rds:** `Login` renamed to `Credentials`. Use `Credentials.fromUsername` to replace existing usage. * **rds:** `DatabaseClusterProps` `masterUser` renamed to `credentials`. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
When we used Cloudformation directly, we used to set the master username and password for our DB cluster like this:
With the CDK, it seems like the credentials are defined as:
So only the password can be secure.
It would be nice to be able to set both the username and password based on a JSON secret value of the form:
I am currently using this workaround to achieve what I want:
Use Case
For improved security.
Proposed Solution
In the Login data type, define the username field as string | SecretValue. This might make it more obvious to others that they can also secure the username but, at the same time, keep this backwards compatible.
This is a 🚀 Feature Request
The text was updated successfully, but these errors were encountered: