When trying to create an AWS::ApiGateway::BasePathMapping through CloudFormation, I am given the following error:
Invalid domain name identifier specified
Below is the portion(s) of my CloudFormation template that should create the AWS::ApiGateway::BasePathMapping:
{
"Parameters": {
"ApiDomainName": {
"Description": "The domain name for the API",
"Type": "String"
}
},
"Resources": {
"ApiBasePathMapping": {
"Type": "AWS::ApiGateway::BasePathMapping",
"Properties": {
"DomainName": {
"Ref": "ApiDomainName"
},
"RestApiId": {
"Ref": "RepositoryApi"
},
"Stage": {
"Ref": "ApiProductionStage"
}
},
"DependsOn": [
"ApiProductionStage"
]
}
}
}
The documentation makes no mention that it needs to be anything special for the DomainName, but the documentation for this resource seems to be lacking some information (It doesn't list outputs for example even though there is a Distribution Domain Name created as an example).
The remainder of the stack works as expected. I am trying to add this resource in as a Change Set. I do own the domain I am trying to use, and I have created a certificate in ACM for this domain.
Quoting from AWS forums:
You can only create or modify base path mappings after the domain name
has been added to API Gateway. This "Invalid domain name identifier
specified" error message is returned when the domain name given in the
base path mapping is not found, indicating that it has not been added
yet.
Also, as of March 2017, the only way to add domain name to the API Gateway via CloudFormation is via custom resources that CloudFormation offers.
Ref: https://forums.aws.amazon.com/message.jspa?messageID=769627
It is now possible to just do that. You just have to explicit state on your CFN template that there is a dependency (DependsOn):
...
ApiDevMapping:
Type: 'AWS::ApiGateway::BasePathMapping'
Properties:
BasePath: v1.0
Stage: dev
DomainName: my-api.example.com
RestApiId: !Ref MobileApiDev
DependsOn:
- MobileApiDevDomain
...
Related
My goal is to enable logging for a regional WebAcl via AWS CDK. This seems to be possible over Cloud Formation and there are the appropriate constructs in CDK. But when using the following code to create a Log Group and linking it in a LoggingConfiguration ...
const webAclLogGroup = new LogGroup(scope, "awsWafLogs", {
logGroupName: `aws-waf-logs`
});
// Create logging configuration with log group as destination
new CfnLoggingConfiguration(scope, "webAclLoggingConfiguration", {
logDestinationConfigs: webAclLogGroup.logGroupArn, // Arn of LogGroup
resourceArn: aclArn // Arn of Acl
});
... I get an exception during cdk deploy, stating that the string in the LogdestinationConfig is not a correct Arn (some parts of the Arn in the log messages have been removed):
Resource handler returned message: "Error reason: The ARN isn't valid. A valid ARN begins with arn: and includes other information separated by colons or slashes., field: LOG_DESTINATION, parameter: arn:aws:logs:xxx:xxx:xxx-awswaflogsF99ED1BA-PAeH9Lt2Y3fi:* (Service: Wafv2, Status Code: 400, Request ID: xxx, Extended Request ID: null)"
I cannot see an error in the generated Cloud Formation code after cdk synth:
"webAclLoggingConfiguration": {
"id": "webAclLoggingConfiguration",
"path": "xxx/xxx/webAclLoggingConfiguration",
"attributes": {
"aws:cdk:cloudformation:type": "AWS::WAFv2::LoggingConfiguration",
"aws:cdk:cloudformation:props": {
"logDestinationConfigs": [
{
"Fn::GetAtt": [
{
"Ref": "awsWafLogs58D3FD01"
},
"Arn"
]
}
],
"resourceArn": {
"Fn::GetAtt": [
"webACL",
"Arn"
]
}
}
},
"constructInfo": {
"fqn": "aws-cdk-lib.aws_wafv2.CfnLoggingConfiguration",
"version": "2.37.1"
}
},
I'm using Cdk with Typescript and the Cdk version is currently set to 2.37.1 but it also did not work with 2.16.0.
WAF has particular requirements to the naming and format of Logging Destination configs as described and shown in their docs.
Specifically, the ARN of the Log Group cannot end in :* which unfortunately is the return value for a Log Group ARN in Cloudformation.
A workaround would be to construct the required ARN format manually like this, which will omit the :* suffix. Also note that logDestinationConfigs takes a List of Strings, though only with exactly 1 element in it.
const webAclLogGroup = new LogGroup(scope, "awsWafLogs", {
logGroupName: `aws-waf-logs`
});
// Create logging configuration with log group as destination
new CfnLoggingConfiguration(scope, "webAclLoggingConfiguration", {
logDestinationConfigs: [
// Construct the different ARN format from the logGroupName
Stack.of(this).formatArn({
arnFormat: ArnFormat.COLON_RESOURCE_NAME,
service: "logs",
resource: "log-group",
resourceName: webAclLogGroup.logGroupName,
})
],
resourceArn: aclArn // Arn of Acl
});
PS: I work for AWS on the CDK team.
I am able to create an SFTP Server (AWS Transfer Family) inside a VPC with an internet-facing Endpoint on AWS console as described here: https://docs.aws.amazon.com/transfer/latest/userguide/create-server-in-vpc.html
VPC endpoint type access selection
Now, I need to replicate that very same creation in a CloudFormation template and don't know how to do it (if possible). According to what I see in https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-transfer-server-endpointdetails.html and in the corresponding CDK docs https://docs.aws.amazon.com/cdk/api/latest/docs/#aws-cdk_aws-transfer.CfnServer.EndpointDetailsProperty.html, there seems not to be a was to set the "access" property value.
All the examples I've come across use a PUBLIC endpoint (in contrast to a VPC one). Here's the snipped I'm working on:
"Resources": {
"ftpserver": {
"Type": "AWS::Transfer::Server",
"DependsOn": "sftpEIP1",
"Properties": {
"EndpointDetails": {
"SubnetIds": [
{
"Ref": "sftpSubnet1"
}
],
"VpcId": {
"Ref": "sftpVPC"
}
},
"EndpointType": "VPC",
"Protocols": [
"SFTP"
],
"Tags": [
{
"Key": "KeyName",
"Value": "ValueName"
}
]
}
}
},
...
}
Since there is no way to set the access type in CloudFormation, the endpoint ends up created as "Internal" instead of "Internet-facing" which is what I need.
Is there any way around this or should I just change it manually (AWS console) after every deployment?
You need to associate Elastic IPs and define the security group.
Notice because the Elastic IPs can only be added after the server is created, it takes sometime to complete, CloudFormation actually creates the server with internal only, stops the server, adds the Elastic IPs, it starts again with elastic IPs and internet facing and then stack is completed.
Example with the CF template below works as expected.
Description: Test CF with FTP server
Resources:
ElasticIP1:
Type: AWS::EC2::EIP
ElasticIP2:
Type: AWS::EC2::EIP
ElasticIP3:
Type: AWS::EC2::EIP
FTPServer:
Type: AWS::Transfer::Server
Properties:
EndpointDetails:
AddressAllocationIds:
- !GetAtt ElasticIP1.AllocationId
- !GetAtt ElasticIP2.AllocationId
- !GetAtt ElasticIP3.AllocationId
SecurityGroupIds:
- sg-0c4184c3f5da91d4a
SubnetIds:
- subnet-0546e2c78cebd0a60
- subnet-0114560b841c91de7
- subnet-0af8fb5fae5472862
VpcId: vpc-07daf77a355f5a8e8
EndpointType: VPC
Protocols:
- SFTP
According the AWS docs at here and here I should be able to automate a certificate creation and validation using cloudformation. Apparently when you specify a HostedZoneId in the DomainValidationOptions, it is supposed to create the required DNS record to complete the validation (at least that is what it seems from the very vague documentation). My CF template for the cert looks like this:
Resources:
MyAPICert:
Type: AWS::CertificateManager::Certificate
Properties:
DomainName: xxxx.dev.mydomain.io
DomainValidationOptions:
- DomainName: mydomain.io
HostedZoneId: /hostedzone/Z03XXXXXXXXXXXX
ValidationMethod: DNS
'mydomain.io' (changed of course) was registered using AWS as registrar as the documents say must be the case for automated validation to work.
This template above is included in a serverless.yml as a resource. However, when I deploy, the stack creation is just stuck waiting for the DNS record - i.e. it does not add the required CNAME entry as I understand it is supposed to do and as such the stack is stuck.
Has anyone gotten this feature to work?
And, yes, I know about the 3rd party custom resources that try to do the same thing, I don't want to use them if CF is supposed to do this natively now.
I hit the same issue. You need to specify the full domain name including the host in the DomainValidationOptions DomainName parameter, and just specify the hosted zone id:
Resources:
MyAPICert:
Type: AWS::CertificateManager::Certificate
Properties:
DomainName: xxxx.dev.mydomain.io
DomainValidationOptions:
- DomainName: xxxx.dev.mydomain.io
HostedZoneId: Z03XXXXXXXXXXXX
ValidationMethod: DNS
In my testing, the Route53 validation record was added about a minute after running the stack, and the domain successfully validated itslef after about 15 minutes.
If this is stuck as in progress for a long time, it could be that you are using a Private Hosted Zone when you need to use the Public one. Probably you don't use a private CA.
That process should take 2-3 minutes, not more than that.
I just deployed the below template to CloudFormation and it successfully created the validation DNS records and authorised the certificate.
If you were to pass the parameters SiteDnsZoneName=mydomain.io. and SiteDnsZoneId=ABCDEFGHIJKLMNOPQRSTU it would create a SAN cert that covers both mydomain.io and *.mydomain.io
{
"Description": "Deploy wildcard SAN cert inc bare domain. (Must deploy cert to us-east-1 for CloudFront)",
"Parameters": {
"SiteDnsZoneName": {
"Type": "String",
"MinLength": 4,
"Description": "DNS Zone",
"Default": "example.com"
},
"SiteDnsZoneId": {
"Type": "String",
"MinLength": 8,
"Description": "DNS Zone Id",
"Default": "ABCDEFGHIJKLMNOPQRSTU"
}
},
"Resources": {
"SiteCertificate": {
"Type": "AWS::CertificateManager::Certificate",
"Properties": {
"DomainName": {
"Fn::Join": [
".",
[
"*",
{
"Ref": "SiteDnsZoneName"
}
]
]
},
"SubjectAlternativeNames": [
{
"Ref": "SiteDnsZoneName"
}
],
"DomainValidationOptions": [
{
"DomainName": {
"Ref": "SiteDnsZoneName"
},
"HostedZoneId": {
"Ref": "SiteDnsZoneId"
}
}
],
"ValidationMethod": "DNS"
}
}
}
}
Note: If you want to use a cert in CloudFront you have to deploy the cert in us-east-1.
Note 2: Route53 needs to be hosting your DNS Zone, but theres no requirement on AWS being the registrar. Your domain can be registered with any provider, so long as you use the AWS name servers provided by Route53 when you add the zone.
I have been trying to create endpoints for my two vpc's, it is creating the vpc's, but it is not working with the Tags property which i require to name the vpc endpoint created.
Error: "Encountered unsupported property Tags"
{
"Resources": {
"VPCEndpoint1": {
"Type" : "AWS::EC2::VPCEndpoint",
"Properties" : {
"PrivateDnsEnabled" : "True",
"RouteTableIds" : ["rtb-1"],
"ServiceName" : "com.amazonaws.eu-west-1.s3",
"VpcEndpointType" : "Gateway",
"VpcId" : "vpc-id1",
"Tags": [
{
"Key": "Name",
"Value": "name1"
}
]
}
},
"VPCEndpoint2": {
"Type" : "AWS::EC2::VPCEndpoint",
"Properties" : {
"PrivateDnsEnabled" : "True",
"RouteTableIds" : ["rtb-2"],
"ServiceName" : "com.amazonaws.eu-west-1.s3",
"VpcEndpointType" : "Gateway",
"VpcId" : "vpc-id2",
"Tags": [
{
"Key": "Name",
"Value": "name2"
}
]
}
}
}
}
Cloudformation do not support Tags property.
Refer cloudformation document => https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpcendpoint.html
Tags are supported for AWS::EC2::VPC, But not for AWS::EC2::VPCEndpoint.
If, you need tags, create tags on vpc level, not on endpoints.
VPC Level Tags - https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc.html
CloudFormation does not support tagging VPC Endpoints yet.
See https://github.com/aws-cloudformation/cloudformation-coverage-roadmap/issues/196
Here is a workaround to tag your VPCE in CloudFormation:
You can setup the custom resource and macro from https://github.com/awslabs/aws-cloudformation-templates/tree/55ebf9f7129e87530e68c242d7e46167e6a798b8/aws/services/CloudFormation/MacrosExamples/Boto3
The code is 4 years old, so it needs to be updated:
Use python3.9
Move lambda code to InlineCode in template to replace urllib2 with cfnresponse
Remove calls to json.dumps
Remove property case lowering
Then you should be able to add a tag using CloudFormation like this:
VpceTagName:
Type: Boto3::ec2.create_tags
Properties:
Resources:
- !Ref VpcEndpoint
Tags:
- Key: Name
Value: My VPCE
Trying to create a cloud formation template to configure WAF with geo location condition. Couldnt find the right template yet. Any pointers would be appreciated.
http://docs.aws.amazon.com/waf/latest/developerguide/web-acl-geo-conditions.html
Unfortunately, the actual answer (as of this writing, July 2018) is that you cannot create geo match sets directly in CloudFormation. You can create them via the CLI or SDK, then reference them in the DataId field of a WAFRule's Predicates property.
Creating a GeoMatchSet with one constraint via CLI:
aws waf-regional get-change-token
aws waf-regional create-geo-match-set --name my-geo-set --change-token <token>
aws waf-regional get-change-token
aws waf-regional update-geo-match-set --change-token <new_token> --geo-match-set-id <id> --updates '[ { "Action": "INSERT", "GeoMatchConstraint": { "Type": "Country", "Value": "US" } } ]'
Now reference that GeoMatchSet id in the CloudFormation:
"WebAclGeoRule": {
"Type": "AWS::WAFRegional::Rule",
"Properties": {
...
"Predicates": [
{
"DataId": "00000000-1111-2222-3333-123412341234" // id from create-geo-match-set
"Negated": false,
"Type": "GeoMatch"
}
]
}
}
There is no documentation for it, but it is possible to create the Geo Match in serverless/cloudformation.
Used the following in serverless:
Resources:
Geos:
Type: "AWS::WAFRegional::GeoMatchSet"
Properties:
Name: geo
GeoMatchConstraints:
- Type: "Country"
Value: "IE"
Which translated to the following in cloudformation:
"Geos": {
"Type": "AWS::WAFRegional::GeoMatchSet",
"Properties": {
"Name": "geo",
"GeoMatchConstraints": [
{
"Type": "Country",
"Value": "IE"
}
]
}
}
That can then be referenced when creating a rule:
(serverless) :
Resources:
MyRule:
Type: "AWS::WAFRegional::Rule"
Properties:
Name: waf
Predicates:
- DataId:
Ref: "Geos"
Negated: false
Type: "GeoMatch"
(cloudformation) :
"MyRule": {
"Type": "AWS::WAFRegional::Rule",
"Properties": {
"Name": "waf",
"Predicates": [
{
"DataId": {
"Ref": "Geos"
},
"Negated": false,
"Type": "GeoMatch"
}
]
}
}
I'm afraid that your question is too vague to solicit a helpful response. The CloudFormation User Guide (pdf) defines many different WAF / CloudFront / R53 resources that will perform various forms of geo match / geo blocking capabilities. The link you provide seems a subset of Web Access Control Lists (Web ACL) - see AWS::WAF::WebACL on page 2540.
I suggest you have a look and if you are still stuck, actually describe what it is you are trying to achieve.
Note that the term you used: "geo location condition" doesn't directly relate to an AWS capability that I'm aware of.
Finally, if you are referring to https://aws.amazon.com/about-aws/whats-new/2017/10/aws-waf-now-supports-geographic-match/, then the latest Cloudformation User Guide doesn't seem to have been updated yet to reflect this.