aws / aws/aws-cdk

(secretsmanager): secret_full_arn not returning text after dash

Open
#33,489 22 comments 0 reactions 0 assignees View on GitHub
@aws-cdk/aws-secretsmanager bug effort/medium p2
Dominant language
TypeScript
Stars
12.9k
Forks
4.6k
Avg merge
2d 3h
Merged PRs (30d)
83

Description

### Describe the bug

I am using Python and AWS CDK to deploy:
- RDS Instance
- Secret
- DMS Instance
- DMS Endpoints
- DMS Replication Task

The secret is used in the RDS Instance.

My DMS Source Endpoint is the RDS Instance, the DMS IAM Role needs access to the secret and I am using this statement:

{
"actions": [
"secretsmanager:DescribeSecret",
"secretsmanager:GetSecretValue"
],
"resources": [
f"{self.secret.secret_full_arn}"
]
}

This statement fails because the secret_full_arn is not returning text after dash. For example:

The secret ARN is "arn:aws:secretsmanager:us-east-1:131578276461:secret:secret-for-data-platform-catalyst-Vg66GP". After the end of all CDK deployment, the IAM Role has secretsmanager permissions for "arn:aws:secretsmanager:us-east-1:131578276461:secret:secret-for-data-platform-catalyst". Note that "-Vg66GP" is missing.

I think this issue might be related to https://github.com/aws/aws-cdk/issues/11727

Image

Image

### Regression Issue

- [ ] Select this option if this issue appears to be a regression.

### Last Known Working CDK Version

_No response_

### Expected Behavior

I need the IAM role to have permissions for the real secret_arn

### Current Behavior

When I use the statement below, secret_full_arn is not returning text after dash

{
"actions": [
"secretsmanager:DescribeSecret",
"secretsmanager:GetSecretValue"
],
"resources": [
f"{self.secret.secret_full_arn}"
]
}

### Reproduction Steps

My secret is created here:

secret = secretsmanager.Secret(
scope=stack,
id="RdsDatabaseSecret",
description="Secret used for data catalyst modules",
secret_name=config.secret_name,
removal_policy=config.removal_policy,
generate_secret_string=secretsmanager.SecretStringGenerator(
secret_string_template='{"username":"rds_cdk_user"}',
generate_string_key="password",
exclude_punctuation=True,
exclude_characters='!@#$%^&*()[]{};:,.<>?/~`\\|'
)
)

I use this secret as a class attribute:

source_endpoint_iam_role_stack = IamRoleStack(
scope=stack,
construct_id="DmsSourceEnpointIamRole",
account_id=config.account_id,
deployment_environment=config.deployment_environment,
aws_region=config.aws_region,
aws_stack=f"dms.{config.aws_region}",
policy_name="cdk-iam-policy-dms-source-endpoint",
role_name="cdk-iam-role-dms-source-endpoint",
secret=secret
)

My class has this method to create iam statements:

class IamRoleStack(cdk.Stack):
"""
A stack that creates an AWS IAM Role with the necessary permissions.
"""
def __init__(self,
scope: Construct,
construct_id: str,
account_id: str,
deployment_environment: str,
aws_region: str,
aws_stack: str,
effect: iam.Effect = iam.Effect.ALLOW,
policy_name: Optional[str] = None,
role_name: Optional[str] = None,
s3_bucket: s3.Bucket = None,
secret: secretsmanager.Secret = None,
**kwargs
) -> None:
"""
Initializes the IAMRoleStack.

:param scope: Scope in which this construct is defined.
:param construct_id: Identifier for this stack.
:param account_id: AWS account ID.
:param deployment_environment: Deployment environment (e.g., "dev", "prod").
:param aws_region: AWS region for resources.
:param aws_stack: Stack name for naming convention.
:param iam_permission_statements: A list of dictionaries containing "actions" and "resources".
:param effect: Default effect for policy statements (default: ALLOW).
:param policy_name: Default name used for IAM Policy (default: None).
:param role_name: Default name used for IAM Role (default: None).
:param s3_bucket: s3.Bucket resource (default: None).
:param secret: secretsmanager.Secret resource (default: None).
"""

super().__init__(scope, construct_id, **kwargs)

# Instantiate class variables

self.account_id = account_id
self.deployment_environment = deployment_environment
self.aws_region = aws_region
self.aws_stack = aws_stack
self.effect = effect
self.policy_name = policy_name
self.role_name = role_name
self.s3_bucket = s3_bucket
self.secret = secret
self.generic_suffix = create_name(self.account_id, self.deployment_environment, self.aws_region)

def create_iam_permission_statements(self) -> List[Dict]:
"""
Creates a List with permissions (actions, resources) used in create_iam_policy_statements() function.

:return iam_permissions (List[Dict]): A list of IAM permissions.
"""

if self.s3_bucket:
return [
{
"actions": [
"s3:GetObject",
"s3:GetObjectAcl",
"s3:GetObjectVersion",
"s3:GetObjectVersionAcl",
"s3:PutObject",
"s3:ListBucket",
"s3:DeleteObject"
],
"resources": [
self.s3_bucket.bucket_arn,
f"{self.s3_bucket.bucket_arn}/*"
]
}
]

elif self.secret:
return [
{
"actions": [
"secretsmanager:DescribeSecret",
"secretsmanager:GetSecretValue"
],
"resources": [
f"{self.secret.secret_full_arn}",
f"{self.secret.secret_full_arn}-??????"
]
}
]

### Possible Solution

_No response_

### Additional Information/Context

_No response_

### CDK CLI Version

2.141.0

### Framework Version

_No response_

### Node.js Version

v22.1.0

### OS

macOS 15.0 24A335

### Language

Python

### Language Version

3.13.0

### Other information

_No response_

Contributor guide

Open the contributing guide

Research direction

Start at the AWS CDK Secrets Manager Secret.secret_full_arn entry point and trace how the ARN is rendered into the IAM policy shown in the reproduction. Compare the generated policy with the actual Secrets Manager ARN, then look for or add focused coverage for suffix preservation. Done means the policy resource matches the real secret ARN or the expected wildcard behavior is clearly established.

Written by the indexing model from the issue text.

Assessment

Tech stack
aws, python, typescript
Domain
authorization, cloud, security
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.