Skip to content

Commit

Permalink
fix(rds): default username 'admin' doesn't work for PostgreSQL
Browse files Browse the repository at this point in the history
In aws#10458, we started to default the master user name to 'admin'.
As it turns out, that actually doesn't work with PostgreSQL,
as 'admin' is a reserved word there.
Add a new optional property to IEngine called defaultUsername
that allows overriding the global 'admin' default on a per-Engine basis.
Set it to 'adminuser' for the Aurora Postgres Cluster engine and the Instance engine.

Fixes aws#10579
  • Loading branch information
skinny85 committed Sep 29, 2020
1 parent ee0db39 commit ce42e7b
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 4 deletions.
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-rds/lib/cluster-engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,7 @@ class AuroraPostgresClusterEngine extends ClusterEngineBase {
private static readonly S3_EXPORT_FEATURE_NAME = 's3Export';

public readonly engineFamily = 'POSTGRESQL';
public readonly defaultUsername = 'adminuser';
public readonly supportedLogTypes: string[] = ['postgresql'];

constructor(version?: AuroraPostgresEngineVersion) {
Expand Down
4 changes: 2 additions & 2 deletions packages/@aws-cdk/aws-rds/lib/cluster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ export interface DatabaseClusterProps extends DatabaseClusterBaseProps {
/**
* Credentials for the administrative user
*
* @default - A username of 'admin' and SecretsManager-generated password
* @default - A username of 'admin' (except for Postgres, which uses 'adminuser') and SecretsManager-generated password
*/
readonly credentials?: Credentials;

Expand Down Expand Up @@ -488,7 +488,7 @@ export class DatabaseCluster extends DatabaseClusterNew {
this.singleUserRotationApplication = props.engine.singleUserRotationApplication;
this.multiUserRotationApplication = props.engine.multiUserRotationApplication;

let credentials = props.credentials ?? Credentials.fromUsername('admin');
let credentials = props.credentials ?? Credentials.fromUsername(props.engine.defaultUsername ?? 'admin');
if (!credentials.secret && !credentials.password) {
credentials = Credentials.fromSecret(new DatabaseSecret(this, 'Secret', {
username: credentials.username,
Expand Down
9 changes: 9 additions & 0 deletions packages/@aws-cdk/aws-rds/lib/engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,13 @@ export interface IEngine {
* @default - the engine doesn't belong to any family
*/
readonly engineFamily?: string;

/**
* The default name of the master database user if one was not provided explicitly.
* If this is `undefined`,
* the global default of 'admin' will be used,
* but that does not work for all the database engines -
* most notably, it's a reserved word in PostgreSQL.
*/
readonly defaultUsername?: string;
}
2 changes: 2 additions & 0 deletions packages/@aws-cdk/aws-rds/lib/instance-engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,8 @@ export interface PostgresInstanceEngineProps {
* The instance engine for PostgreSQL.
*/
class PostgresInstanceEngine extends InstanceEngineBase {
public readonly defaultUsername = 'adminuser';

constructor(version?: PostgresEngineVersion) {
super({
engineType: 'postgres',
Expand Down
4 changes: 2 additions & 2 deletions packages/@aws-cdk/aws-rds/lib/instance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -902,7 +902,7 @@ export interface DatabaseInstanceProps extends DatabaseInstanceSourceProps {
/**
* Credentials for the administrative user
*
* @default - A username of 'admin' and SecretsManager-generated password
* @default - A username of 'admin' (except for Postgres, which uses 'adminuser') and SecretsManager-generated password
*/
readonly credentials?: Credentials;

Expand Down Expand Up @@ -944,7 +944,7 @@ export class DatabaseInstance extends DatabaseInstanceSource implements IDatabas
constructor(scope: Construct, id: string, props: DatabaseInstanceProps) {
super(scope, id, props);

let credentials = props.credentials ?? Credentials.fromUsername('admin');
let credentials = props.credentials ?? Credentials.fromUsername(props.engine.defaultUsername ?? 'admin');
if (!credentials.secret && !credentials.password) {
credentials = Credentials.fromSecret(new DatabaseSecret(this, 'Secret', {
username: credentials.username,
Expand Down
23 changes: 23 additions & 0 deletions packages/@aws-cdk/aws-rds/test/test.cluster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1394,6 +1394,29 @@ export = {
test.done();
},

"Aurora PostgreSQL cluster uses a different default master username than 'admin', which is a reserved word"(test: Test) {
// GIVEN
const stack = testStack();
const vpc = new ec2.Vpc(stack, 'VPC');

// WHEN
new DatabaseCluster(stack, 'Database', {
engine: DatabaseClusterEngine.auroraPostgres({
version: AuroraPostgresEngineVersion.VER_9_6_12,
}),
instanceProps: { vpc },
});

// THEN
expect(stack).to(haveResourceLike('AWS::SecretsManager::Secret', {
GenerateSecretString: {
SecretStringTemplate: '{"username":"adminuser"}',
},
}));

test.done();
},

'MySQL cluster without S3 exports or imports references the correct default ParameterGroup'(test: Test) {
// GIVEN
const stack = testStack();
Expand Down
19 changes: 19 additions & 0 deletions packages/@aws-cdk/aws-rds/test/test.instance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -997,6 +997,25 @@ export = {

test.done();
},

"PostgreSQL database instance uses a different default master username than 'admin', which is a reserved word"(test: Test) {
new rds.DatabaseInstance(stack, 'Instance', {
vpc,
engine: rds.DatabaseInstanceEngine.postgres({
version: rds.PostgresEngineVersion.VER_9_5_7,
}),
});

// THEN
expect(stack).to(haveResourceLike('AWS::SecretsManager::Secret', {
GenerateSecretString: {
SecretStringTemplate: '{"username":"adminuser"}',
},
}));

test.done();
},

'S3 Import/Export': {
'instance with s3 import and export buckets'(test: Test) {
new rds.DatabaseInstance(stack, 'DB', {
Expand Down

0 comments on commit ce42e7b

Please sign in to comment.