Cannot create AWS ServiceCatalogProduct using cloudformation - amazon-web-services

I am trying to create a ServiceCatalogProduct using a cloudformation json file like below:
> aws cloudformation create-stack --stack-name hmm --template-body file:///tmp/1.json
My cfn template file (1.json) looks like shown below. I have confirmed that the template file is valid. When I try to create the stack I get a generic error message "Failed to create following Provisioning Artifacts: [ pa-jas39ah3a1d ]". What am I missing?
{
"Resources": {
"Product": {
"Properties": {
"Description": "",
"Name": "redis-DEV-shu-cluster",
"Owner": "shubham",
"ProvisioningArtifactParameters": [
{
"Description": "Time created (UTC): 2020-11-04T04:13:42.897954",
"DisableTemplateValidation": "true",
"Info": {
"LoadTemplateFromURL": "https://s3:amazonaws.com/my-artifact-bucket-name/ag28ajo1-1ef1-47c9-80dc-7tuha718"
},
"Name": "1.0.0"
}
],
"SupportEmail": ""
},
"Type": "AWS::ServiceCatalog::CloudFormationProduct"
}
}
}
Here is the error in the "events" tab in cloudformation console:

A likely reason is spelling mistake:
https://s3:amazonaws.com/my-artifact-bucket-name/ag28ajo1-1ef1-47c9-80dc-7tuha718
it should be (note s3., not s3:):
https://s3.amazonaws.com/my-artifact-bucket-name/ag28ajo1-1ef1-47c9-80dc-7tuha718

Related

Use env variables inside cloudformation templates

i have an amplify app with multiple branches.
I have added an custom cloudformation template with amplify add custom
It looks like:
{
"AWSTemplateFormatVersion": "2010-09-09",
"Parameters": { "env": { "Type": "String" } },
"Resources": {
"db": {
"Type": "AWS::Timestream::Database",
"Properties": { "DatabaseName": "dev_db" }
},
"timestreamtable": {
"DependsOn": "db",
"Type": "AWS::Timestream::Table",
"Properties": {
"DatabaseName": "dev_db",
"TableName": "avg_16_4h",
"MagneticStoreWriteProperties": { "EnableMagneticStoreWrites": true },
"RetentionProperties": {
"MemoryStoreRetentionPeriodInHours": "8640",
"MagneticStoreRetentionPeriodInDays": "1825"
}
}
}
},
"Outputs": {},
"Description": "{\"createdOn\":\"Windows\",\"createdBy\":\"Amplify\",\"createdWith\":\"8.3.1\",\"stackType\":\"custom-customCloudformation\",\"metadata\":{}}"
}
You can see there is a field called DatabaseName. In my amplify app i have written an env variable named TIMESTREAM_DB and i want to use it inside of this cloudformation file.
Is this possible or do i need to write it all by hand in it?
Templates cannot access arbitrary env vars. Instead, CloudFormation injects deploy-time values into a template with Parameters.
Amplify helpfully adds the env variable as a parameter. A la the Amplify docs, use the env value as the AWS::Timestream::Database name suffix:
"DatabaseName": "Fn::Join": [ "", [ "my-timestream-db-name-", { "Ref": "env" } ] ]
The AWS::Timestream::Table resource also requires a DatabaseName parameter. You could repeat the above, but it's more DRY to get the name via the Database's Ref:
"DatabaseName": { "Ref" : "db" }

Use S3 target in cloudformation for a codepipeline deploy

In CodePipeline in the AWS console its possible to specify a S3 deploy step https://docs.aws.amazon.com/codepipeline/latest/userguide/tutorials-s3deploy.html I'd like to be able to do this exactly, but in cloudformation. I'm missing something obvious here. Any help appreciated.
I was able to get a source and build step in cloudformation for the pipeline, but not the deploy step. The provider for that step I would think would be s3, but I can't seem to get it to work.
Here is a sample deploy step for S3
{
"Name": "Deploy",
"Actions": [
{
"Name":"Push-Lambda-Artifacts",
"ActionTypeId": {
"Category": "Deploy",
"Owner": "AWS",
"Provider": "S3",
"Version": "1"
},
"InputArtifacts": [
{
"Name": "lambda"
}
],
"Configuration":{
"BucketName": {
"Ref": "BucketName"
},
"Extract": true
},
"RunOrder": 1
}
]
}
I think that will get you most of the way there. InputArtifacts is from an output from my codebuild step.

How can I instruct an AWS CloudFormation template to create resources in a specific region?

I am new to CloudFormation templates. I have basic template in yaml that creates an EC2 Instance. Every time I create a stack and use this template, the EC2 Instance is ALWAYS created on US East N. Virginia region. I am trying to change this so that the EC2 Instance resides in US-WEST-2 region. After some research, it appears that this is something that is not specified within the template. Instead, I need to change the region to us-west-2 in AWS console and then create a new stack. Is my understanding correct?
Unfortunately, you can't specify the region in a cloudformation template.
You should either pass region as a command line argument
aws --region eu-west-1 cloudformation create-stack --stack-name ...
or, specify the default region in aws cli config file ~/.aws/config
[default]
region=eu-west-1
What am I missing here? I am sure we can specify region where the stack is created in CFN template using parameters and we do have active templates which creates our stack in respective region based on the parameter value.
The AWS::Region pseudo parameter is a value that AWS CloudFormation resolves as the region where the stack is created.
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/gettingstarted.templatebasics.html
Here is a sub-section of sample template
{
"AWSTemplateFormatVersion": "2010-09-09",
"Parameters": {
"InstanceType": {
"Description": "Instance Type",
"Type": "String",
"Default": "t2.xlarge"
},
"SubnetUSEAST1": {
"Description": "Subnet on which Ec2 instance needs to be created",
"Type": "String",
"Default": "subnet-xxxxxxxx"
},
"SubnetUSWEST2": {
"Description": "Subnet on which Ec2 instance needs to be created",
"Type": "String",
"Default": "subnet-yyyyyyyy"
}
},
"Conditions": {
"useast1": {
"Fn::Equals": [
{
"Ref": "AWS::Region"
},
"us-east-1"
]
},
"uswest2": {
"Fn::Equals": [
{
"Ref": "AWS::Region"
},
"us-west-2"
]
}
},
"Resources": {
"EC2Instance": {
"Type": "AWS::EC2::Instance",
"Properties": {
"InstanceType": {
"Ref": "InstanceType"
},
"NetworkInterfaces": [
{
"SubnetId": {
"Fn::If": [
"useast1",
{
"Ref": "SubnetUSEAST1"
},
{
"Ref": "SubnetUSWEST2"
}
]
},
"AssociatePublicIpAddress": "false",
"DeviceIndex": "0"
}
]
}
}
}
}
If you are able to split your template into parts, you could deploy to different regions at once via some orchestration and StackSets.

Stack is hung using CloudFormation with SNS-backed CustomResources

I'm trying to learn working of CustomResources in CloudFormation Template. Created simple template to create s3 bucket. But on creating stack, it remains in Create in progress state for long time and no bucket is created.
Is there anything, I'm missing in below validated template:
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "Building A bucket With customeResources in CloudFormation",
"Parameters" : {
"NewBucket": {
"Default": "",
"Description": "S3 bucket containing customer assets",
"Type": "String"
}
},
"Conditions": {
"NewBucket": {
"Fn::Not": [
{
"Fn::Equals": [
{
"Ref": "NewBucket"
},
""
]
}
]
}
},
"Resources" : {
"CustomResource": {
"Properties": {
"S3Bucket": {
"Ref": "NewBucket"
},
"ServiceToken": "SNS topic ARN"
},
"Type": "AWS::CloudFormation::CustomResource"
}
},
"Outputs": {
"BucketName": {
"Value": {
"Fn::GetAtt": [ "CustomResource", {"Ref": "NewBucket"} ]
}
}
}
}
It would appear that your SNS-backed custom resource is not sending a response back to cloud formation, and it is stuck waiting for that response.
From Amazon Simple Notification Service-backed Custom Resources:
The custom resource provider processes the data sent by the template
developer and determines whether the Create request was successful.
The resource provider then uses the S3 URL sent by AWS CloudFormation
to send a response of either SUCCESS or FAILED.
When the request is made to the SNS service provider, it include the following object:
{
"RequestType": "Create",
"ServiceToken": "arn:aws:sns:us-west-2:2342342342:Critical-Alerts-development",
"ResponseURL": "https:\/\/cloudformation-custom-resource-response-uswest2.s3-us-west-2.amazonaws.com\/arn%3Aaws%3Acloudformation%3Aus-west-2%3A497903502641%3Astack\/custom-resource\/6bf07a80-d44a-11e7-84df-503aca41a029%7CCustomResource%7C5a695f41-61d7-475b-9110-cdbaec04ee55?AWSAccessKeyId=AKIAI4KYMPPRGIACET5Q&Expires=1511887381&Signature=WmHQVqIDCBwQSfcBMpzTfiWHz9I%3D",
"StackId": "arn:aws:cloudformation:us-west-2:asdasdasd:stack\/custom-resource\/6bf07a80-d44a-11e7-84df-503aca41a029",
"RequestId": "5a695f41-61d7-475b-9110-cdbaec04ee55",
"LogicalResourceId": "CustomResource",
"ResourceType": "AWS::CloudFormation::CustomResource",
"ResourceProperties": {
"ServiceToken": "arn:aws:sns:us-west-2:234234234:Critical-Alerts-development",
"S3Bucket": "test-example-com"
}
}
You will need to send a success/fail response to the ResponseURL provided in the event for Cloud Formation to continue processing.
I would also note that the bucket will not be created unless your custom service provider creates it. The Custom Resource function is only sending the request to the provider.

Ask-cli lambda command uses wrong region setting

I am trying to set up a workflow via the ask-cli for developing an Amazon skill with an Amazon lambda backend. I have created a skill and it works fine when using "ask api ..." commands, but when I use an "ask lambda ..." command, such as "ask lambda download -f MySkill", it uses the wrong region setting. I get the error:
ResourceNotFoundException: Function not found: arn:aws:lambda:us-east-1:123456789:function:MySkill
As you can see, it is looking for the lambda instance in us-east-1. But My lambda instance is in eu-west-1, as specified in my skill.json file below. This questions is pretty much a duplicate of https://forums.developer.amazon.com/questions/87922/ask-cli-does-not-use-region-setting-from-aws-confi.html. The answer in that question implies that you can add a region field somewhere in one of the json files, but I can't figure out where. Any help would be appreciated.
This is my ~/.ask/cli_config
{
"profiles": {
"default": {
"aws_profile": "default",
"token": {
"access_token": "My_access_token",
"refresh_token": "My_refresh_token",
"token_type": "bearer",
"expires_in": 3600,
"expires_at": "2017-10-06T14:12:26.171Z"
},
"vendor_id": "My_vendor_id"
}
}
}
this is my ~/.aws/config
[default]
output = text
region = eu-west-1
This is my skill.json, that i get when i call: "ask api get-skill -s skill_id > skill.json"
{
"skillManifest": {
"publishingInformation": {
"locales": {
"en-GB": {
"name": "My Skill"
}
},
"isAvailableWorldwide": true,
"category": "PUBLIC_TRANSPORTATION",
"distributionCountries": []
},
"apis": {
"custom": {
"endpoint": {
"uri": "arn:aws:lambda:eu-west-1:123456789:function:MySkill"
},
"interfaces": []
}
},
"manifestVersion": "1.0"
}
}
for me it works if I edit the following file:
~/.aws/credentials (Linux, macOS, or Unix)
C:\Users\USERNAME\.aws\credentials (Windows)
[ask_cli_default]
aws_access_key_id=YOUR_AWS_ACCESS_KEY
aws_secret_access_key=YOUR_AWS_SECRET_KEY
region=eu-west-1
The region os specified in the lambda section of .ask/config. Example:
"lambda": [
{
"alexaUsage": [
"custom/default"
],
"arn": "arn:aws:lambda:eu-west-1:XXXXXXXXX:function:ask-premium-hello-world",
"awsRegion": "eu-west-1",
"codeUri": "lambda/custom",
"functionName": "ask-premium-hello-world",
"handler": "index.handler",
"revisionId": "XXXXXXXXXXXXXXXXXX",
"runtime": "nodejs8.10"
}
]