(secretsmanager): secret_full_arn not returning text after dash
- 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
### 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
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