Can we overwrite SSM parameter from CloudFormation template? - aws-cloudformation

Let's say I have stack-1 as
AWSTemplateFormatVersion: 2010-09-09
Resources:
BasicParameter:
Type: "AWS::SSM::Parameter"
Properties:
Name: "commands"
Type: "StringList"
Value: "date,ls"
And then stack-2 as :
AWSTemplateFormatVersion: 2010-09-09
Resources:
BasicParameter:
Type: "AWS::SSM::Parameter"
Properties:
Name: "commands"
Type: "StringList"
Value: "pwd"
On creating a new stack, I am getting an error that parameter already exists. We can overwrite parameters using aws cli 'put-parameter --overwrite'. Can we do something similar with CloudFormation template?

Related

What is the format to specify an external EDGE Gateway ApiId in CloudFormation templates?

I'm trying to create or update a stack with the following CloudFormation Template:
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
ApiGatewayId:
Type: String
ApiLayerArn:
Type: String
JarLocation:
Type: String
Resources:
Function:
Type: 'AWS::Lambda::Function'
Properties:
Handler: net.bitsandpaper.api.kiosk.PlatformChecker
Runtime: java11
Code:
S3Bucket: bnp-build-artifacts
S3Key: !Ref JarLocation
Description: ''
MemorySize: 128
Timeout: 5
Role: arn:aws:iam::479832603967:role/bnp-api-lambda-execution-role
Layers:
- !Ref ApiLayerArn
ApiIntegration:
Type: AWS::ApiGatewayV2::Integration
Properties:
ApiId: !Ref ApiGatewayId
IntegrationType: AWS_PROXY
IntegrationUri: !Join
- ''
- - 'arn:'
- !Ref 'AWS::Partition'
- ':apigateway:'
- !Ref 'AWS::Region'
- ':lambda:path/2015-03-31/functions/'
- !Ref Function
- /invocations
TimeoutInMillis: 6000
ApiRoute:
Type: AWS::ApiGatewayV2::Route
Properties:
ApiId: !Ref ApiGatewayId
RouteKey: 'GET /kiosk/platform-check'
Target: !Join
- /
- - integrations
- !Ref ApiIntegration
The parameters are correctly passed by an external file, they look good in the Web Console, notably parameter ApiGatewayId has value 8548rqrsm5. Yet during deployment I have a CREATE_FAILED for ApiIntegration, with the message:
Invalid API identifier specified 479832603967:8548rqrsm5 (Service:
AmazonApiGatewayV2; Status Code: 404; Error Code: NotFoundException;
Request ID: 84918a83-cf9d-48d2-acf7-18d9d2e4d330; Proxy: null)
The API is an EDGE Rest API, in the same region than the CloudFormation stack. The ID is retrieved by the CLI with aws apigateway get-rest-apis.
Am I missing something in the ApiId format? The litterature is very scarce when not referencing an API in the same stack...
AWS::ApiGatewayV2 is only for WEBSOCKTES and HTTP types. From docs:
The API protocol. Valid values are WEBSOCKET or HTTP.
But since you are writing about Edge-optimized (not supported by HTTP api) it seems to that you are using REST API, rather then HTTP API. So you should be using AWS::ApiGateway resources, not AWS::ApiGatewayV2.
It seem's like the AWS::ApiGatewayV2::Route is created before the AWS::ApiGatewayV2::Integration. So When it trying to refer ApiIntegration it is not yet created.
So you should try to use DependsOn attribute.
With the DependsOn attribute you can specify that the creation of a
specific resource follows another. When you add a DependsOn attribute
to a resource, that resource is created only after the creation of the
resource specified in the DependsOn attribute.
Try this below CloudFormation code:
ApiRoute:
Type: AWS::ApiGatewayV2::Route
DependsOn: ApiIntegration
Properties:
ApiId: !Ref ApiGatewayId
RouteKey: 'GET /kiosk/platform-check'
Target: !Join
- /
- - integrations
- !Ref ApiIntegration
I hope this will help you out to resolve your problem.
Link: DependsOn Attribute UserGuide

How to call a resource from one yaml template to another yaml template using cloudformation

I need some guidance on cloudformation templates.
I have a stack called test1.yaml, there i created an IAM role called S3Role.
Now I have another stack called test2.yaml, there i created a managed policy to attach to existing iam role.
Now i want to call test1.yml file S3Role in test2.yml file of managed policy.
Can anyone help me with the script?
Can anyone help me with the script.
Obviously due to lack of details in your question, its not possible to provide any script. But I can provide general psudo-code.
test1.yaml
You will have to export the S3Role Arn or Name
Resources:
S3Role:
Type: IAM::ROLE
<rest of role definition>
Outputs:
RoleArn:
Value: !GetAtt S3Role.Arn
Exports:
Name: RoleArn
test2.yml
You will have to import the role exported Arn (or name) from test1.yaml:
Resources:
SomeResouce:
Properties:
Role: !ImportValue RoleArn
Hope this helps.
You need export the role from stack 1 and then import it in stack 2
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-stack-exports.html
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html
Providing the complete script for cross-referencing an AWS resource in CloudFormation template.
test1.yaml has an IAM role (logical ID: IAMRole) which we export through the Outputs block. Also notice that the indentation of Outputs block is same as that of Resources block.
The Outputs block serves many purposes. From the AWS Documentation
The optional Outputs section declares output values that you can
import into other stacks (to create cross-stack references), return in
response (to describe stack calls), or view on the AWS CloudFormation
console.
test1.yaml
Resources:
IAMRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Sid: TrustPolicy
Effect: Allow
Principal:
Service:
- ec2.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonS3FullAccess
Path: /
RoleName: IAMRole
Outputs:
ExportIAMRole:
Description: Export the IAMRole to use in test2.yaml
Value: !Ref IAMRole
Export:
Name: IAMRole
In test2.yaml we import the value by referencing the name we have given under Export in Outputs block.
test2.yaml
Resources:
IAMPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
ManagedPolicyName: IAMPolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- kms:ListAliases
- kms:Encrypt
- kms:Decrypt
Resource: "*"
Roles:
- !ImportValue IAMRole

Cloudformation build stuck at "create in progress" - trying to add it to use specific SG

So the last item I added to this template was the attempt to have it use a particular SecurityGroup. I did not want it to create a new one. When I do the validate check that comes back ok but apparently my code is still not correct. Other that the template was working ok.
I have tried all I can think of. there is no error when i finally times out other than "internal error" so I am at a loss here.
Parameters:
VPC:
Description: Testing using this VPC
Type: String
Default: vpc-02765
SecGroup:
Description: Name of security group
Type: AWS::EC2::SecurityGroup
KeyName:
Description: Name of an existing EC2 key pair for SSH access to the EC2 instance.
Type: AWS::EC2::KeyPair::KeyName
InstanceType:
Description: EC2 instance type.
Type: String
Default: t2.micro
...
...
...
Resources:
EC2Instance:
Type: AWS::EC2::Instance
Properties:
InstanceType: !Ref 'InstanceType'
SubnetId: subnet-08b
KeyName: !Ref 'KeyName'
SecurityGroupIds:
- !Ref SecGroup
ImageId: !FindInMap
- AWSRegionArch2AMI
- !Ref 'AWS::Region'
- HVM64
'''
all I am trying to do is use the items I listed in the template. the vpc,securitygroup. The last time this worked was when I had the code in the template that builds a new SG. I than changed my mind and want to use an existing SG. so somewhere I messed up
This works in my templates:
Parameters:
SecGroup:
Type: AWS::EC2::SecurityGroup::Id
...
Resources:
MyInstance:
Properties:
SecurityGroupIds:
- !Ref SecGroup

Cannot access restApiId & restApiRootResourceId for cross stack reference in serverless yml

Since I had an issue of 200 resource error, I found a way of using cross stack reference by dividing into different services. I managed to do that by using the cross-stack reference. The issue is I cannot give the restApiId & restApiRootResourceId dynamically. Right now, am statically setting ids into the service-2.
Basically the service-1 looks like,
provider:
name: aws
runtime: nodejs8.10
apiGateway:
restApiId:
Ref: ApiGatewayRestApi
restApiResources:
Fn::GetAtt:
- ApiGatewayRestApi
- RootResourceId
custom:
stage: "${opt:stage, self:provider.stage}"
resources:
Resources:
ApiGatewayRestApi:
Type: AWS::ApiGateway::RestApi
Properties:
Name: ${self:service}-${self:custom.stage}-1
Outputs:
ApiGatewayRestApiId:
Value:
Ref: ApiGatewayRestApi
Export:
Name: ApiGatewayRestApi-restApiId
ApiGatewayRestApiRootResourceId:
Value:
Fn::GetAtt:
- ApiGatewayRestApi
- RootResourceId
Export:
Name: ApiGatewayRestApi-rootResourceId
And the service-2 looks like this,
provider:
name: aws
runtime: nodejs8.10
apiGateway-shared:
restApiId:
'Fn::ImportValue': ApiGatewayRestApi-restApiId
restApiRootResourceId:
'Fn::ImportValue': ApiGatewayRestApi-rootResourceId
As the above service-2 config, I cannot reference the Ids.
FYI: Both services are in different files.
So How what's wrong with this approach?
Serverless has special syntax on how to access stack output variables: {cf:stackName.outputKey}.
Note that using the Fn::ImportValue would work inside the resources section.

Share Values upstream in a nested cloudformation stack possible?

Is there some way to pass on Values form a child stack to a parent stack? All I found was to pass values down, but never up, that would unfortunately not correspond with my stack architecture. I could use cross-referencing with eXport/Import but would rather keep the nested stack if possible.
You can definitely gather outputed values from a child stack and use them in the parent stack.
For example:
# parent stack
AWSTemplateFormatVersion: 2010-09-09
Resources:
SomeChildStack:
Type: AWS::CloudFormation::Stack
Properties:
Parameters:
AWS CloudFormation Stack Parameters
TemplateURL: !Ref SomeTemplateUrl
SomeOtherResource:
Type: AWS::AnyOther::Resources
Properties:
SomeProperty: !Ref SomeChildStack.Outputs.MyOutput
And in SomeChildStack:
# The template used for SomeChildStack
AWSTemplateFormatVersion: 2010-09-09
Resources:
S3Bucket:
Type: AWS::S3::Bucket
Properties:
AccessControl: PublicRead
LoggingConfiguration:
DestinationBucketName: !Ref 'LoggingBucket'
LogFilePrefix: testing-logs
Outputs:
MyOutput:
Value: !Ref 'S3Bucket'
Description: Name of the sample Amazon S3 bucket.
The tricky thing to remember is adding the Outputs when referencing the AWS::CloudFormation::Stack.
Note that this will make SomeOtherResource depend on SomeChildStack, so SomeOtherResource won't be created until SomeChildStack has been created.
We had the same issue and the accepted answer (using !Ref) didn't work. CloudFormation wouldn't deploy the stack.
What did work for us is:
!GetAtt [NestedStack, Outputs.MyOutput]
Parent stack:
AWSTemplateFormatVersion: 2010-09-09
Resources:
NestedStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: !Ref NestedStackTemplateUrl
ResourceInParentStack:
Type: AWS::AnyOther::Resources
Properties:
SomeProperty: !GetAtt [NestedStack, Outputs.MyOutput]
Nested stack:
AWSTemplateFormatVersion: 2010-09-09
Resources:
S3Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: 'MyBucketName'
...
Outputs:
MyOutput:
Value: !Ref S3Bucket
Description: Name of the sample Amazon S3 bucket.