diff --git a/packages/aws-cdk-lib/aws-secretsmanager/lib/secret-rotation.ts b/packages/aws-cdk-lib/aws-secretsmanager/lib/secret-rotation.ts index 0da676a2e8d74..9a1ba31e110f1 100644 --- a/packages/aws-cdk-lib/aws-secretsmanager/lib/secret-rotation.ts +++ b/packages/aws-cdk-lib/aws-secretsmanager/lib/secret-rotation.ts @@ -164,7 +164,7 @@ export class SecretRotationApplication { } else if (partition === 'aws-cn') { return '1.1.237'; } else if (partition === 'aws-us-gov') { - return '1.1.213'; + return '1.1.319'; } else { throw new UnscopedValidationError(`unsupported partition: ${partition}`); } diff --git a/packages/aws-cdk-lib/aws-secretsmanager/test/secret-rotation.test.ts b/packages/aws-cdk-lib/aws-secretsmanager/test/secret-rotation.test.ts index 72f559bf7a265..72e0fbfb4a49a 100644 --- a/packages/aws-cdk-lib/aws-secretsmanager/test/secret-rotation.test.ts +++ b/packages/aws-cdk-lib/aws-secretsmanager/test/secret-rotation.test.ts @@ -397,3 +397,156 @@ test('with interface vpc endpoint', () => { }, }); }); + +const expectedVersions = { + 'aws': '1.1.618', + 'aws-cn': '1.1.237', + 'aws-us-gov': '1.1.319', +}; + +const expectedPartitionDetails = { + 'aws': 'arn:aws:serverlessrepo:us-east-1:297356227824', + 'aws-cn': 'arn:aws-cn:serverlessrepo:cn-north-1:193023089310', + 'aws-us-gov': 'arn:aws-us-gov:serverlessrepo:us-gov-west-1:023102451235', +}; + +describe('SecretRotationApplication partition version', () => { + test('returns correct version for aws partition', () => { + // WHEN + const version = secretsmanager.SecretRotationApplication.MYSQL_ROTATION_SINGLE_USER.semanticVersionForPartition('aws'); + + // THEN + expect(version).toBe(expectedVersions.aws); + }); + + test('returns correct version for aws-cn partition', () => { + // WHEN + const version = secretsmanager.SecretRotationApplication.MYSQL_ROTATION_SINGLE_USER.semanticVersionForPartition('aws-cn'); + + // THEN + expect(version).toBe(expectedVersions['aws-cn']); + }); + + test('returns correct version for aws-us-gov partition', () => { + // WHEN + const version = secretsmanager.SecretRotationApplication.MYSQL_ROTATION_SINGLE_USER.semanticVersionForPartition('aws-us-gov'); + + // THEN + expect(version).toBe(expectedVersions['aws-us-gov']); + }); + + test('throws for unsupported partition', () => { + // WHEN/THEN + expect(() => secretsmanager.SecretRotationApplication.MYSQL_ROTATION_SINGLE_USER.semanticVersionForPartition('aws-iso')) + .toThrow(/unsupported partition: aws-iso/); + }); + + test('returns correct ARN for aws-us-gov partition', () => { + // WHEN + const arn = secretsmanager.SecretRotationApplication.MYSQL_ROTATION_SINGLE_USER.applicationArnForPartition('aws-us-gov'); + + // THEN + expect(arn).toBe('arn:aws-us-gov:serverlessrepo:us-gov-west-1:023102451235:applications/SecretsManagerRDSMySQLRotationSingleUser'); + }); +}); + +describe('CloudFormation mapping for all partitions', () => { + test('includes correct versions for all cloud types', () => { + // WHEN + new secretsmanager.SecretRotation(stack, 'Rotation', { + application: secretsmanager.SecretRotationApplication.MYSQL_ROTATION_SINGLE_USER, + secret, + target, + vpc, + }); + + // THEN + // Verify the SAR mapping includes the correct version for all partitions + const template = Template.fromStack(stack); + const cfnTemplate = template.toJSON(); + + // Find the SAR mapping (it will have a hash suffix) + const mappingKey = Object.keys(cfnTemplate.Mappings).find(key => key.startsWith('RotationSARMapping')); + expect(mappingKey).toBeDefined(); + + const mapping = cfnTemplate.Mappings[mappingKey!]; + + // Verify all partition versions + expect(mapping.aws.semanticVersion).toBe(expectedVersions.aws); + expect(mapping['aws-cn'].semanticVersion).toBe(expectedVersions['aws-cn']); + expect(mapping['aws-us-gov'].semanticVersion).toBe(expectedVersions['aws-us-gov']); + + // Verify application ARNs for all partitions + expect(mapping.aws.applicationId).toBe('arn:aws:serverlessrepo:us-east-1:297356227824:applications/SecretsManagerRDSMySQLRotationSingleUser'); + expect(mapping['aws-cn'].applicationId).toBe('arn:aws-cn:serverlessrepo:cn-north-1:193023089310:applications/SecretsManagerRDSMySQLRotationSingleUser'); + expect(mapping['aws-us-gov'].applicationId).toBe('arn:aws-us-gov:serverlessrepo:us-gov-west-1:023102451235:applications/SecretsManagerRDSMySQLRotationSingleUser'); + }); + + test('includes correct mapping for all rotation applications', () => { + // Test a few different rotation applications to ensure mapping works universally + const applications = [ + { + app: secretsmanager.SecretRotationApplication.MARIADB_ROTATION_SINGLE_USER, + name: 'SecretsManagerRDSMariaDBRotationSingleUser', + id: 'MariaDB', + }, + { + app: secretsmanager.SecretRotationApplication.POSTGRES_ROTATION_SINGLE_USER, + name: 'SecretsManagerRDSPostgreSQLRotationSingleUser', + id: 'Postgres', + }, + { + app: secretsmanager.SecretRotationApplication.ORACLE_ROTATION_SINGLE_USER, + name: 'SecretsManagerRDSOracleRotationSingleUser', + id: 'Oracle', + }, + ]; + + applications.forEach(({ app, name, id }) => { + const testStack = new cdk.Stack(); + const testVpc = new ec2.Vpc(testStack, 'VPC'); + const testSecret = new secretsmanager.Secret(testStack, 'Secret'); + const testSecurityGroup = new ec2.SecurityGroup(testStack, 'SecurityGroup', { vpc: testVpc }); + const testTarget = new ec2.Connections({ + defaultPort: ec2.Port.tcp(3306), + securityGroups: [testSecurityGroup], + }); + + new secretsmanager.SecretRotation(testStack, `${id}Rotation`, { + application: app, + secret: testSecret, + target: testTarget, + vpc: testVpc, + }); + + const template = Template.fromStack(testStack); + const cfnTemplate = template.toJSON(); + + // Find the SAR mapping + const mappingKey = Object.keys(cfnTemplate.Mappings).find(key => key.includes('SARMapping')); + expect(mappingKey).toBeDefined(); + + const mapping = cfnTemplate.Mappings[mappingKey!]; + + // Verify all partitions exist in the mapping + expect(mapping.aws).toBeDefined(); + expect(mapping['aws-cn']).toBeDefined(); + expect(mapping['aws-us-gov']).toBeDefined(); + + // Verify versions for all partitions + expect(mapping.aws.semanticVersion).toBe(expectedVersions.aws); + expect(mapping['aws-cn'].semanticVersion).toBe(expectedVersions['aws-cn']); + expect(mapping['aws-us-gov'].semanticVersion).toBe(expectedVersions['aws-us-gov']); + + // Verify application ARNs contain the correct application name + expect(mapping.aws.applicationId).toContain(name); + expect(mapping['aws-cn'].applicationId).toContain(name); + expect(mapping['aws-us-gov'].applicationId).toContain(name); + + // Verify partition-specific details + expect(mapping.aws.applicationId).toContain(expectedPartitionDetails.aws); + expect(mapping['aws-cn'].applicationId).toContain(expectedPartitionDetails['aws-cn']); + expect(mapping['aws-us-gov'].applicationId).toContain(expectedPartitionDetails['aws-us-gov']); + }); + }); +});