From ba79788621494120672150a5976c81d709c1fa8a Mon Sep 17 00:00:00 2001 From: ahmadalguydi Date: Fri, 31 Jul 2026 04:54:27 +0300 Subject: [PATCH 1/2] feat(secretsmanager): support block public policy in L2 Signed-off-by: ahmadalguydi --- .../aws-secretsmanager/lib/policy.ts | 8 ++++++++ .../aws-secretsmanager/lib/secret.ts | 18 +++++++++++++++--- .../aws-secretsmanager/test/policy.test.ts | 15 +++++++++++++++ .../aws-secretsmanager/test/secret.test.ts | 16 ++++++++++++++++ 4 files changed, 54 insertions(+), 3 deletions(-) diff --git a/packages/aws-cdk-lib/aws-secretsmanager/lib/policy.ts b/packages/aws-cdk-lib/aws-secretsmanager/lib/policy.ts index 2d654e7a472fd..ec98093081fff 100644 --- a/packages/aws-cdk-lib/aws-secretsmanager/lib/policy.ts +++ b/packages/aws-cdk-lib/aws-secretsmanager/lib/policy.ts @@ -14,6 +14,13 @@ export interface ResourcePolicyProps { * The secret to attach a resource-based permissions policy */ readonly secret: ISecret; + + /** + * Specifies whether to block resource-based policies that allow broad access to the secret. + * + * @default - AWS Secrets Manager default + */ + readonly blockPublicPolicy?: boolean; } /** @@ -47,6 +54,7 @@ export class ResourcePolicy extends Resource { new CfnResourcePolicy(this, 'Resource', { resourcePolicy: this.document, secretId: props.secret.secretArn, + blockPublicPolicy: props.blockPublicPolicy, }); } } diff --git a/packages/aws-cdk-lib/aws-secretsmanager/lib/secret.ts b/packages/aws-cdk-lib/aws-secretsmanager/lib/secret.ts index 07892045d34cc..ea5c7d9355078 100644 --- a/packages/aws-cdk-lib/aws-secretsmanager/lib/secret.ts +++ b/packages/aws-cdk-lib/aws-secretsmanager/lib/secret.ts @@ -126,6 +126,13 @@ export interface SecretProps { */ readonly description?: string; + /** + * Specifies whether to block resource-based policies that allow broad access to the secret. + * + * @default - AWS Secrets Manager default + */ + readonly blockPublicPolicy?: boolean; + /** * The customer-managed encryption key to use for encrypting the secret value. * @@ -359,9 +366,11 @@ abstract class SecretBase extends Resource implements ISecret { private policy?: ResourcePolicy; private _arnForPolicies: string; + private readonly blockPublicPolicy?: boolean; - constructor(scope: Construct, id: string, props: ResourceProps = {}) { + constructor(scope: Construct, id: string, props: ResourceProps = {}, blockPublicPolicy?: boolean) { super(scope, id, props); + this.blockPublicPolicy = blockPublicPolicy; // eslint-disable-next-line no-restricted-syntax this._arnForPolicies = Lazy.uncachedString({ produce: (context: IResolveContext) => { @@ -484,7 +493,10 @@ abstract class SecretBase extends Resource implements ISecret { public addToResourcePolicy(statement: iam.PolicyStatement): iam.AddToResourcePolicyResult { if (!this.policy && this.autoCreatePolicy) { - this.policy = new ResourcePolicy(this, 'Policy', { secret: this }); + this.policy = new ResourcePolicy(this, 'Policy', { + secret: this, + blockPublicPolicy: this.blockPublicPolicy, + }); } if (this.policy) { @@ -676,7 +688,7 @@ export class Secret extends SecretBase { constructor(scope: Construct, id: string, props: SecretProps = {}) { super(scope, id, { physicalName: props.secretName, - }); + }, props.blockPublicPolicy); // Enhanced CDK Analytics Telemetry addConstructMetadata(this, props); diff --git a/packages/aws-cdk-lib/aws-secretsmanager/test/policy.test.ts b/packages/aws-cdk-lib/aws-secretsmanager/test/policy.test.ts index 58da8fa2aa2cf..e3c020b32bed0 100644 --- a/packages/aws-cdk-lib/aws-secretsmanager/test/policy.test.ts +++ b/packages/aws-cdk-lib/aws-secretsmanager/test/policy.test.ts @@ -42,3 +42,18 @@ describe.each([ Template.fromStack(stack).resourceCountIs('AWS::SecretsManager::ResourcePolicy', expectedResourcePolicyCount); }); }); + +test('passes blockPublicPolicy to the L1 resource policy', () => { + const app = new cdk.App(); + const stack = new cdk.Stack(app); + const secret = new secretsmanager.Secret(stack, 'Secret'); + + new secretsmanager.ResourcePolicy(stack, 'Policy', { + secret, + blockPublicPolicy: true, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::SecretsManager::ResourcePolicy', { + BlockPublicPolicy: true, + }); +}); diff --git a/packages/aws-cdk-lib/aws-secretsmanager/test/secret.test.ts b/packages/aws-cdk-lib/aws-secretsmanager/test/secret.test.ts index 4b07319b4b586..1526d0517ee85 100644 --- a/packages/aws-cdk-lib/aws-secretsmanager/test/secret.test.ts +++ b/packages/aws-cdk-lib/aws-secretsmanager/test/secret.test.ts @@ -23,6 +23,22 @@ test('default secret', () => { }); }); +test('secret with blockPublicPolicy passes it to the resource policy', () => { + const secret = new secretsmanager.Secret(stack, 'Secret', { + blockPublicPolicy: true, + }); + + secret.addToResourcePolicy(new iam.PolicyStatement({ + actions: ['secretsmanager:GetSecretValue'], + principals: [new iam.AccountRootPrincipal()], + resources: ['*'], + })); + + Template.fromStack(stack).hasResourceProperties('AWS::SecretsManager::ResourcePolicy', { + BlockPublicPolicy: true, + }); +}); + test('secret without replica regions omits ReplicaRegions', () => { // WHEN new secretsmanager.Secret(stack, 'Secret'); From 70194aeac6bd9b939d40d633804072579983842b Mon Sep 17 00:00:00 2001 From: ahmadalguydi Date: Fri, 31 Jul 2026 05:14:06 +0300 Subject: [PATCH 2/2] docs(secretsmanager): document block public policy Signed-off-by: ahmadalguydi --- .../aws-secretsmanager/test/integ.secret.lit.ts | 9 ++++++++- packages/aws-cdk-lib/aws-secretsmanager/README.md | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-secretsmanager/test/integ.secret.lit.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-secretsmanager/test/integ.secret.lit.ts index 16661b50ec542..bb87cdf7b44f8 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-secretsmanager/test/integ.secret.lit.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-secretsmanager/test/integ.secret.lit.ts @@ -11,7 +11,14 @@ class SecretsManagerStack extends cdk.Stack { /// !show // Default secret - const secret = new secretsmanager.Secret(this, 'Secret'); + const secret = new secretsmanager.Secret(this, 'Secret', { + blockPublicPolicy: true, + }); + secret.addToResourcePolicy(new iam.PolicyStatement({ + actions: ['secretsmanager:GetSecretValue'], + principals: [new iam.AnyPrincipal()], + resources: ['*'], + })); secret.grantRead(role); const user = new iam.User(this, 'User', { diff --git a/packages/aws-cdk-lib/aws-secretsmanager/README.md b/packages/aws-cdk-lib/aws-secretsmanager/README.md index 2c14fc6b0bd97..128e9a56b025f 100644 --- a/packages/aws-cdk-lib/aws-secretsmanager/README.md +++ b/packages/aws-cdk-lib/aws-secretsmanager/README.md @@ -70,6 +70,20 @@ secret.grantRead(role); secret.grantWrite(role); ``` +## Block public resource policies + +To ask Secrets Manager to reject resource policies that grant public access, +set `blockPublicPolicy` when creating a secret or a standalone resource policy: + +```ts +const secret = new secretsmanager.Secret(this, 'Secret', { + blockPublicPolicy: true, +}); +``` + +When the secret creates its resource policy lazily, the setting is forwarded to +`AWS::SecretsManager::ResourcePolicy`. + If, as in the following example, your secret was created with a KMS key: ```ts