Is it possible to override AWS SAM policy template placeholder variables - amazon-web-services

I am currently trying to add both the AWS SAM policy templates KMSDecryptPolicy & KMSEnecryptPolicy to my config yml but the KMS key is in a different account and I would need cross account access to do this.
However when using the above mentioned policy templates I can only pass the KeyId and not the AWS account number which is a placeholder variable.
I am trying to do this using the AWS SAM policy templates.
Would appreciate any support on this.
This is an example of how my current policies look like.
Policies:
- arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole
- DynamoDBCrudPolicy:
TableName: !Ref InvoiceFeaturesTable
- S3CrudPolicy:
BucketName: !Ref InvoiceFeaturesBucket
example code

Both KMSDecryptPolicy and KMSEnecryptPolicy uses ${AWS::AccountId} which defaults to the current AWS account and you cannot override it via policy templates. You ONLY can pass KeyId: Reference
What you can simply do is to copy the policy template into your SAM template as inline policy and modify it as required. Reference

Related

How to run CloudFormation for a specific AWS Account

I am trying to create a CloudFormation template for a custom-managed policy where whenever I run the template, it'll create the policy in the account I specified.
For example, I have 10 AWS accounts and I want to create a template in our main account where you just need to enter the accountID and the JSON and CloudFormation will create it for you. This is what I have so far (which dosen't work)
AWSTemplateFormatVersion: "2010-09-09"
Description: "This cloudformation template will create a managed policy in a perticular account"
#####################
# Define Parameters
#####################
Parameters:
PolicyName:
Type: String
Description: The name that will be applied to the custom policy.
PolicyDescription:
Type: String
Description: Type a description for this policy. This can NOT be changed after initial assignment.
PolicyJson:
Type: Json
Description: Type permission for this policy in JSON format
AccountID:
Type: String
Description: Enter the account ID where you want to create this policy
#####################
# Define Resources
#####################
Resources:
# ---------------------
# Define Policy Resource
# ---------------------
ManagedPolicy:
Type: "AWS::IAM::ManagedPolicy"
Properties:
ManagedPolicyName: !Ref PolicyName
Description: !Ref PolicyDescription
Path: "/"
PolicyDocument: !RefPolicyJson
#####################
# Define Outputs:
#####################
Outputs:
PolicyName:
Description: The name of the newly created managed policy
Value: !Ref PolicyName
Issues:
It's not allowed to pass whole JSON object as a variable ( Template format error: Unrecognized parameter type: Json). I thought of passing Resources: in parameter but I don't know how to do it as permissions will vary based on use case. So If possible, I want empty box where people can give their own JSON for the permission and I pass that as a value.
I am not sure how to use accountID. How can I tell my template to go to spcific account (as defined in the parameter), assume this role and create this policy with the given Json
I am following https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-managedpolicy.html documentation in order to solve my problem.
We want whenever someone runs the template, they are provided with input fields where they can write policy name, Description, Account where to create the policy and Json of the permission. And Cloudformation should create it for them and return the policy ARN as output
You have to use stacksets for multi-account deployments of templates:
AWS CloudFormation StackSets extends the capability of stacks by enabling you to create, update, or delete stacks across multiple accounts and AWS Regions with a single operation.

AWS Codepipeline deploy cloudformation to Dev account and use output stack to create Parameter store in Central account . Posible?

I want to build a cross account Codepiepline the Codepipeline stay on Central Account so i assume role to DEV Account and create stack but at the same time i want to create parameter store in Central Account with output stack from Dev account
for example
Codepipeline in Central account will assume role to Dev Account for deploy s3bucket
and !GetAtt mydemo.DomainName to create parameter store in Central account
** My all pipeline with stay on Central account and keep all parameter store from DEV Account so my codebuild, another codepipeline can read the value
so any idea for me ?
#This s3 will be deploy to dev account
Resources:
DeployDevAccountBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: "dev-bucket"
AccessControl: Private
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
VersioningConfiguration:
Status: "Enabled"
#This parameter store will be deploy to Central account
BucketNameParameter:
Type: AWS::SSM::Parameter
Properties:
Name: !Sub "dev-account-s3-domainname"
Type: String
Value: !GetAtt DeployDevAccountBucket.DomainName
You can't do this with CloudFormation (CFN) and a single stack. CFN is region and account specific, and does not support cross-account deployments.
You would have to re-architect your pipeline to use CFN StackSets, which requires you to split your template to different ones, depending on the account or region.
But probably the easiest way is to use CodeBuild where you explicitly assume cross-account roles to deploy stacks in different accounts.
#This parameter store will be deploy to Central account
there isn't any way to use the AWS::SSM::Parameter resource within your dev account to create a parameter in a different account.
My all pipeline with stay on Central account and keep all parameter store from DEV Account so my codebuild, another codepipeline can read the value
But, if the pipeline is in the central account, and you're using the cloudformation action type in code pipeline, you can still access stack outputs via Code Pipeline Cloudformation Action Output Variables . A downstream pipeline task could put those outputs into a parameter - in the Central account ,wehre the pipeline is already running, or really in any account, via role assumption.
There is another method: you could define a custom cloudformation resource that would assume a role in a different account and manage the parameter there. You'd have to manage the roles and the lambda (or whatever implementation) for that resource all separately, though. I think the stack outputs approach is better.

Use already existing KMS key in Lambda functions that are managed through SAM/CloudFormation

The situation is:
A lambda function is created using a SAM/CloudFormation. A policy is attached to allow this function to access an existing bucket (in the same region). This looks somehow like this:
MyFunction:
Type: AWS::Serverless::Function
Properties:
.....
Policies:
- Statement:
- Effect: Allow
Action:
- "s3:ListBucket"
- "s3:PutObject"
- "s3:GetObject"
Resource:
- "arn:aws:s3:::my-great-existing-bucket"
- "arn:aws:s3:::my-great-existing-bucket/*"
This means: Without modifying the policy of the existing bucket, the newly created lambda-function will now have access to that bucket.
But in this case this already existing bucket is additionally encrypted with an existing customer managed KMS key (again in the same region) so access will still be denied to the Lambda function. The goal would be to add the policy to use that existing key also directly to cloud-formation template.
I found this link:
https://docs.aws.amazon.com/kms/latest/developerguide/iam-policies.html
My interpretation would be, that the named goal would usually be achieved only the other way round:
You need to modify the policy of the KMS-key. But they Key is of course not managed via the Cloud Formation Stack and therefore not manageable here (or am I wrong about that?).
So the only way to achieve it would be to activate general IAM Policies for the KMS-key?
https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html#key-policy-default-allow-root-enable-iam
Is that understanding correct?
So the only way to achieve it would be to activate general IAM Policies for the KMS-key?
Yes. That's correct. If your customer managed KMS key does not have it, you have to modify KMS policy to allow lambda role. If you activate general IAM Policies, then you can just modify the lambda execution role with permissions to the KMS key.

Finding AWS KMS ID by alias in CloudFormation

I'm creating a AWS::Timestream::Database service and I want to use one of our KMS keys that's been created externally of the CloudFormation template.
I want to use the alias of the key, but I can't find any good way to get the reference of the key into the template.
I've found some references to use !Sub to be able to get the ARN, but how to get ID from there?
I have used the following code in my S3 cross account replication CF template for collecting the KMS alias. You can try the same approach.
ReplicaKmsKeyID: !Join ['',['arn:aws:kms:', !Ref BucketRegion, ':', !Ref AWS::AccountId, ':alias/aws/s3']]
#ReplicaKmsKeyID: arn:aws:kms:us-west-2:111111111111:alias/aws/s3
You can use alias with your kms id like arn:<partition>:kms:<region>:<account-id>:alias/<alias-name>
AWSTemplateFormatVersion: 2010-09-09
Resources:
DB:
Type: AWS::Timestream::Database
Properties:
DatabaseName: <DB_NAME>
KmsKeyId: arn:aws:kms:<REGION>:<ACCOUNT_ID>:alias/<ALIAS>

AWS CloudFormation - Attach existing managed policy to existing role through a template

I am deploying a CloudFormation template to AWS. A role for my Lambda invocation is being created by a template that I am importing, and I cannot modify it directly. I wish to modify that role to attach the AWS managed policy AWSLambdaVPCAccessExecutionRole that already exists in my AWS account. So far, all of my searches have come up empty.
I have found instructions for how to create a new role with an existing managed policy
I have found instructions for how to create a new policy and attach it to an existing role.
I have found instructions for how to Update a Stack using the AWS console or the CLI, but not via a template (YAML or JSON)
I have found instructions for calling something called aws_iam_role_policy_attachment in something called Terraform, but that is not available to me
I am hoping for something like the following but I cannot find any evidence of this existing anywhere. Is there anything that can do what I am trying to do?
---
Resources:
AdditionalRolePermissions:
Type: "AWS::IAM::RolePolicyAttachment"
Properties:
Roles:
- Ref: ExistingRole
PolicyName:
- Ref: ExistingPolicy
The best solution I have come up with so far is to create a new policy that has a manually created PolicyDocument that is the same as the existing one for AWSLambdaVPCAccessExecutionRole and attach it to the role upon creation. I would prefer not to do that though because it will be harder to maintain.
Unfortunately, you can not do this in pure CloudFormation unless you create a custom resource but this isn't really pure CloudFormation at that point as you'd need to create a lambda and other resources to implement the custom resource. There is no concept of a policy attachment in CloudFormation presently and these attachments only happen when you define a policy or role resource.
The simplest thing would be to go with your solution of creating a policy that duplicates AWSLambdaVPCAccessExecutionRole. That policy is fairly simple and shouldn't clutter up your CloudFormation template too much compared to some other complicated policies.
It is possible as of 2021. Please see: https://aws.amazon.com/premiumsupport/knowledge-center/cloudformation-attach-managed-policy/
Example:
AWSTemplateFormatVersion: '2010-09-09'
Description: something cool
Resources:
IAM:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- 'sts:AssumeRole'
RoleName: some_role_name
Policies:
['arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole']