From 1b9808d7b588d82d8aaca0b4d7265467a5f33eb8 Mon Sep 17 00:00:00 2001 From: Reginald Alfret Date: Fri, 25 Sep 2026 10:22:22 +0530 Subject: [PATCH 1/2] feat(policy-templates): add SSMParameterWritePolicy and SSMParameterWithSlashPrefixWritePolicy Add policy templates for writing/updating parameters in AWS Systems Manager Parameter Store, complementing the existing read policy templates. Fixes #1673 --- .../policy_templates.json | 70 +++++++++++++++++++ .../input/all_policy_templates.yaml | 6 ++ .../output/all_policy_templates.json | 56 +++++++++++++++ .../output/aws-cn/all_policy_templates.json | 56 +++++++++++++++ .../aws-us-gov/all_policy_templates.json | 56 +++++++++++++++ 5 files changed, 244 insertions(+) diff --git a/samtranslator/policy_templates_data/policy_templates.json b/samtranslator/policy_templates_data/policy_templates.json index e50f447923..a56194da28 100644 --- a/samtranslator/policy_templates_data/policy_templates.json +++ b/samtranslator/policy_templates_data/policy_templates.json @@ -2280,6 +2280,76 @@ } } }, + "SSMParameterWritePolicy": { + "Definition": { + "Statement": [ + { + "Action": [ + "ssm:DescribeParameters" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ssm:PutParameter" + ], + "Effect": "Allow", + "Resource": { + "Fn::Sub": [ + "arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter/${parameterName}", + { + "parameterName": { + "Ref": "ParameterName" + } + } + ] + } + } + ] + }, + "Description": "Gives access to write a parameter to store secrets in this account. If not using default key, KMSEncryptPolicy will also be needed.", + "Parameters": { + "ParameterName": { + "Description": "The name of the secret stored in SSM in your account. Name shouldn't contain a leading slash." + } + } + }, + "SSMParameterWithSlashPrefixWritePolicy": { + "Definition": { + "Statement": [ + { + "Action": [ + "ssm:DescribeParameters" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ssm:PutParameter" + ], + "Effect": "Allow", + "Resource": { + "Fn::Sub": [ + "arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter${parameterName}", + { + "parameterName": { + "Ref": "ParameterName" + } + } + ] + } + } + ] + }, + "Description": "Gives access to write a parameter to store secrets in this account. If not using default key, KMSEncryptPolicy will also be needed.", + "Parameters": { + "ParameterName": { + "Description": "The name of the secret stored in SSM in your account. Name should contain a leading slash." + } + } + }, "SageMakerCreateEndpointConfigPolicy": { "Definition": { "Statement": [ diff --git a/tests/translator/input/all_policy_templates.yaml b/tests/translator/input/all_policy_templates.yaml index ab1f8d596b..5a529d247a 100644 --- a/tests/translator/input/all_policy_templates.yaml +++ b/tests/translator/input/all_policy_templates.yaml @@ -190,3 +190,9 @@ Resources: - KMSEncryptPolicy_v2: KeyId: keyId + + - SSMParameterWritePolicy: + ParameterName: name + + - SSMParameterWithSlashPrefixWritePolicy: + ParameterName: /name diff --git a/tests/translator/output/all_policy_templates.json b/tests/translator/output/all_policy_templates.json index c42a0314ad..512af0553b 100644 --- a/tests/translator/output/all_policy_templates.json +++ b/tests/translator/output/all_policy_templates.json @@ -1751,6 +1751,62 @@ ] }, "PolicyName": "KitchenSinkFunctionRolePolicy64" + }, + { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "ssm:DescribeParameters" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ssm:PutParameter" + ], + "Effect": "Allow", + "Resource": { + "Fn::Sub": [ + "arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter/${parameterName}", + { + "parameterName": "name" + } + ] + } + } + ] + }, + "PolicyName": "KitchenSinkFunctionRolePolicy65" + }, + { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "ssm:DescribeParameters" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ssm:PutParameter" + ], + "Effect": "Allow", + "Resource": { + "Fn::Sub": [ + "arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter${parameterName}", + { + "parameterName": "/name" + } + ] + } + } + ] + }, + "PolicyName": "KitchenSinkFunctionRolePolicy66" } ], "Tags": [ diff --git a/tests/translator/output/aws-cn/all_policy_templates.json b/tests/translator/output/aws-cn/all_policy_templates.json index 7a6f70009e..a864570053 100644 --- a/tests/translator/output/aws-cn/all_policy_templates.json +++ b/tests/translator/output/aws-cn/all_policy_templates.json @@ -1751,6 +1751,62 @@ ] }, "PolicyName": "KitchenSinkFunctionRolePolicy64" + }, + { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "ssm:DescribeParameters" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ssm:PutParameter" + ], + "Effect": "Allow", + "Resource": { + "Fn::Sub": [ + "arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter/${parameterName}", + { + "parameterName": "name" + } + ] + } + } + ] + }, + "PolicyName": "KitchenSinkFunctionRolePolicy65" + }, + { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "ssm:DescribeParameters" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ssm:PutParameter" + ], + "Effect": "Allow", + "Resource": { + "Fn::Sub": [ + "arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter${parameterName}", + { + "parameterName": "/name" + } + ] + } + } + ] + }, + "PolicyName": "KitchenSinkFunctionRolePolicy66" } ], "Tags": [ diff --git a/tests/translator/output/aws-us-gov/all_policy_templates.json b/tests/translator/output/aws-us-gov/all_policy_templates.json index bc6e666d95..ed55585311 100644 --- a/tests/translator/output/aws-us-gov/all_policy_templates.json +++ b/tests/translator/output/aws-us-gov/all_policy_templates.json @@ -1751,6 +1751,62 @@ ] }, "PolicyName": "KitchenSinkFunctionRolePolicy64" + }, + { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "ssm:DescribeParameters" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ssm:PutParameter" + ], + "Effect": "Allow", + "Resource": { + "Fn::Sub": [ + "arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter/${parameterName}", + { + "parameterName": "name" + } + ] + } + } + ] + }, + "PolicyName": "KitchenSinkFunctionRolePolicy65" + }, + { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "ssm:DescribeParameters" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ssm:PutParameter" + ], + "Effect": "Allow", + "Resource": { + "Fn::Sub": [ + "arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter${parameterName}", + { + "parameterName": "/name" + } + ] + } + } + ] + }, + "PolicyName": "KitchenSinkFunctionRolePolicy66" } ], "Tags": [ From 401b8d0ca8bad2fd0cfcf20c20561d53ac001e56 Mon Sep 17 00:00:00 2001 From: Reginald Alfret Date: Fri, 25 Sep 2026 11:38:32 +0530 Subject: [PATCH 2/2] fix(policy-templates): tighten SSM write policy permissions - Remove ssm:DescribeParameters on Resource: '*' from SSMParameterWritePolicy and SSMParameterWithSlashPrefixWritePolicy to adhere to least-privilege principles. - Fix key ordering in policy_templates.json so SSMParameterWithSlashPrefixWritePolicy precedes SSMParameterWritePolicy lexicographically. - Update expected transformed template outputs in tests for aws, aws-cn, and aws-us-gov partitions. --- .../policy_templates.json | 26 +++++-------------- .../output/all_policy_templates.json | 14 ---------- .../output/aws-cn/all_policy_templates.json | 14 ---------- .../aws-us-gov/all_policy_templates.json | 14 ---------- 4 files changed, 6 insertions(+), 62 deletions(-) diff --git a/samtranslator/policy_templates_data/policy_templates.json b/samtranslator/policy_templates_data/policy_templates.json index a56194da28..d324c5fe7e 100644 --- a/samtranslator/policy_templates_data/policy_templates.json +++ b/samtranslator/policy_templates_data/policy_templates.json @@ -2280,16 +2280,9 @@ } } }, - "SSMParameterWritePolicy": { + "SSMParameterWithSlashPrefixWritePolicy": { "Definition": { "Statement": [ - { - "Action": [ - "ssm:DescribeParameters" - ], - "Effect": "Allow", - "Resource": "*" - }, { "Action": [ "ssm:PutParameter" @@ -2297,7 +2290,7 @@ "Effect": "Allow", "Resource": { "Fn::Sub": [ - "arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter/${parameterName}", + "arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter${parameterName}", { "parameterName": { "Ref": "ParameterName" @@ -2311,20 +2304,13 @@ "Description": "Gives access to write a parameter to store secrets in this account. If not using default key, KMSEncryptPolicy will also be needed.", "Parameters": { "ParameterName": { - "Description": "The name of the secret stored in SSM in your account. Name shouldn't contain a leading slash." + "Description": "The name of the secret stored in SSM in your account. Name should contain a leading slash." } } }, - "SSMParameterWithSlashPrefixWritePolicy": { + "SSMParameterWritePolicy": { "Definition": { "Statement": [ - { - "Action": [ - "ssm:DescribeParameters" - ], - "Effect": "Allow", - "Resource": "*" - }, { "Action": [ "ssm:PutParameter" @@ -2332,7 +2318,7 @@ "Effect": "Allow", "Resource": { "Fn::Sub": [ - "arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter${parameterName}", + "arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter/${parameterName}", { "parameterName": { "Ref": "ParameterName" @@ -2346,7 +2332,7 @@ "Description": "Gives access to write a parameter to store secrets in this account. If not using default key, KMSEncryptPolicy will also be needed.", "Parameters": { "ParameterName": { - "Description": "The name of the secret stored in SSM in your account. Name should contain a leading slash." + "Description": "The name of the secret stored in SSM in your account. Name shouldn't contain a leading slash." } } }, diff --git a/tests/translator/output/all_policy_templates.json b/tests/translator/output/all_policy_templates.json index 512af0553b..e69b0809f7 100644 --- a/tests/translator/output/all_policy_templates.json +++ b/tests/translator/output/all_policy_templates.json @@ -1755,13 +1755,6 @@ { "PolicyDocument": { "Statement": [ - { - "Action": [ - "ssm:DescribeParameters" - ], - "Effect": "Allow", - "Resource": "*" - }, { "Action": [ "ssm:PutParameter" @@ -1783,13 +1776,6 @@ { "PolicyDocument": { "Statement": [ - { - "Action": [ - "ssm:DescribeParameters" - ], - "Effect": "Allow", - "Resource": "*" - }, { "Action": [ "ssm:PutParameter" diff --git a/tests/translator/output/aws-cn/all_policy_templates.json b/tests/translator/output/aws-cn/all_policy_templates.json index a864570053..2142076422 100644 --- a/tests/translator/output/aws-cn/all_policy_templates.json +++ b/tests/translator/output/aws-cn/all_policy_templates.json @@ -1755,13 +1755,6 @@ { "PolicyDocument": { "Statement": [ - { - "Action": [ - "ssm:DescribeParameters" - ], - "Effect": "Allow", - "Resource": "*" - }, { "Action": [ "ssm:PutParameter" @@ -1783,13 +1776,6 @@ { "PolicyDocument": { "Statement": [ - { - "Action": [ - "ssm:DescribeParameters" - ], - "Effect": "Allow", - "Resource": "*" - }, { "Action": [ "ssm:PutParameter" diff --git a/tests/translator/output/aws-us-gov/all_policy_templates.json b/tests/translator/output/aws-us-gov/all_policy_templates.json index ed55585311..8d30a0d83d 100644 --- a/tests/translator/output/aws-us-gov/all_policy_templates.json +++ b/tests/translator/output/aws-us-gov/all_policy_templates.json @@ -1755,13 +1755,6 @@ { "PolicyDocument": { "Statement": [ - { - "Action": [ - "ssm:DescribeParameters" - ], - "Effect": "Allow", - "Resource": "*" - }, { "Action": [ "ssm:PutParameter" @@ -1783,13 +1776,6 @@ { "PolicyDocument": { "Statement": [ - { - "Action": [ - "ssm:DescribeParameters" - ], - "Effect": "Allow", - "Resource": "*" - }, { "Action": [ "ssm:PutParameter"