{"id":21261372,"url":"https://github.com/dflook/cloudformation-dns-certificate","last_synced_at":"2025-03-04T04:04:36.020Z","repository":{"id":54861264,"uuid":"134950038","full_name":"dflook/cloudformation-dns-certificate","owner":"dflook","description":"Cloudformation DNS Validated Certificate Resource","archived":false,"fork":false,"pushed_at":"2024-09-04T08:40:47.000Z","size":201,"stargazers_count":48,"open_issues_count":1,"forks_count":13,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-02-25T03:04:30.958Z","etag":null,"topics":["aws-acm","aws-cloudformation","aws-route53","certificate","cloudformation","route53","troposphere"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dflook.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-05-26T10:02:18.000Z","updated_at":"2024-03-06T19:12:13.000Z","dependencies_parsed_at":"2023-02-19T11:40:20.117Z","dependency_job_id":"af431a5b-a72d-421c-ab99-7d71a65b85e9","html_url":"https://github.com/dflook/cloudformation-dns-certificate","commit_stats":{"total_commits":66,"total_committers":6,"mean_commits":11.0,"dds":"0.25757575757575757","last_synced_commit":"7ba6c6c22677ed0d19ef8a4b62f463ae132ab627"},"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dflook%2Fcloudformation-dns-certificate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dflook%2Fcloudformation-dns-certificate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dflook%2Fcloudformation-dns-certificate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dflook%2Fcloudformation-dns-certificate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dflook","download_url":"https://codeload.github.com/dflook/cloudformation-dns-certificate/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241780506,"owners_count":20019061,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws-acm","aws-cloudformation","aws-route53","certificate","cloudformation","route53","troposphere"],"created_at":"2024-11-21T04:29:11.619Z","updated_at":"2025-03-04T04:04:35.994Z","avatar_url":"https://github.com/dflook.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Cloudformation DNS Validated Certificate Resource\n\nThis is a cloudformation custom resource which is an enhancement of the [AWS::CertificateManager::Certificate](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-certificatemanager-certificate.html) resource.\n\nIt allows creating a certificate in a region different from the stack's region (e.g. `us-east-1` for cloudfront),\nand allows for creating a certificate for a Route 53 hosted zone in another AWS account.\nIt also allows for setting the key algorithm.\n\n## Usage\n\nTo use this custom resource, copy the CustomAcmCertificateLambda and CustomAcmCertificateLambdaExecutionRole resources\ninto your template. You can then create certificate resources of Type: `Custom::DNSCertificate`.\n\nThis resource is also available as troposphere extension, in the [troposphere-dns-certificate](https://pypi.org/project/troposphere-dns-certificate/) package\n\nRemember to add a ServiceToken property to the resource which references the CustomAcmCertificateLambda arn.\nCertificates may take up to 30 minutes to be issued, but typically takes ~3 minutes. The Certificate resource remains as \nCREATE_IN_PROGRESS until the certificate is issued.\n\n### Differences from AWS::CertificateManager::Certificate\nIt should behave similarly to [AWS::CertificateManager::Certificate](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-certificatemanager-certificate.html), \nexcept for the differences described here.\n\nThe additional `Region` property can be used to set the region to create the certificate in.\n\nThe [DomainValidationOption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-certificatemanager-certificate-domainvalidationoption.html) has a additional properties `Route53RoleArn` and `Route53RoleExternalId` which allow assuming a role before creating DNS validation records.\nThis lets you create a certificate for a hosted zone in another account.\n\nThe additional `KeyAlgorithm` property allows setting the key algorithm used to generate the key pair used by the certificate.\n\n### Certificate Resource\n\n#### Syntax\n\n```yaml\nType: Custom::DNSCertificate\nProperties: \n  DomainName: String\n  DomainValidationOptions:\n    - DomainValidationOption\n  SubjectAlternativeNames:\n    - String\n  Tags:\n    - Resource Tag\n  ValidationMethod: String\n  Region: String\n  CertificateTransparencyLoggingPreference: String\n  KeyAlgorithm: String\n  ServiceToken: !GetAtt 'CustomAcmCertificateLambda.Arn'  \n```\n\n#### Properties\n\n* `DomainName`\n\n  Fully qualified domain name (FQDN) to issue the certificate for. Use an asterisk as a wildcard.\n\n  - Required: Yes\n  - Type: String\n  - Update requires: [Replacement](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-replacement)\n  \n* `DomainValidationOptions`\n\n  Information for validating domain ownership. A DomainValidationOption should be present for the DomainName and all \n  SubjectAlternativeNames to create validation records. A DomainValidationOption for a parent domain can be used for names that have the same HostedZoneId.\n  \n  If a DomainValidationOption is not present for a domain, validation records for that domain will not be created. They must be created through other means.\n  The resource will remain in the `CREATE_IN_PROGRESS` state until the records can be validated.\n\n  - Required: Yes\n  - Type: List of `DomainValidationOption`\n  - Update requires: [Replacement](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-replacement) if a HostedZoneId changes\n\n* `SubjectAlternativeNames`\n\n  FQDNs to include in the Subject Alternative Name of the certificate.\n\n  - Required: No\n  - Type: List of String values\n  - Update requires: [Replacement](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-replacement)  \n\n* `Tags`\n\n  Tags for this certificate\n\n  - Required: No\n  - Type: [Resource Tag](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-resource-tags.html)\n  - Update requires: [No interruption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-no-interrupt)  \n\n* `ValidationMethod`\n\n  Method to use to validate domain ownership. This should be `DNS`.\n\n  - Required: No\n  - Default: `EMAIL`\n  - Type: String\n  - Update requires: [Replacement](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-replacement) \n\n* `Region`\n\n  The region to create the certificate in.\n\n  - Required: No\n  - Default: The Stack's region\n  - Type: String\n  - Update requires: [Replacement](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-replacement) \n\n* `CertificateTransparencyLoggingPreference`\n\n  Certificate Transparency Logging Preference. This may be 'ENABLED' or 'DISABLED'.\n    \n  - Required: No\n  - Default: `ENABLED`\n  - Type: String\n  - Update requires: [No interruption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-no-interrupt)  \n\n* `KeyAlgorithm`\n\n  The algorithm that will be used to generate the key pair used by the certificate.\n  Currently, this may be `RSA_2048`, `EC_prime256v1`, or `EC_secp384r1` for new certificates.\n\n  :warning: Not all algorithms are supported by all clients, AWS services or regions.\n\n  - Required: No\n  - Default: `RSA_2048`\n  - Type: String\n  - Update requires: [Replacement](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-replacement)\n\n#### Return value\n\n* Ref\n\n  When the [`Ref`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html) \n  function is used on the logical ID of a Certificate resource the certificate ARN is returned.\n\n### DomainValidationOption\n\n#### Syntax\n\n```yaml\nDomainName: String\nHostedZoneId: String\nRoute53RoleArn: String\nRoute53RoleExternalId: String\n```\n\n#### Properties\n\n* `DomainName`\n\n  Fully qualified domain name of the validation request.\n\n  - Required: Yes\n  - Type: String\n  - Update requires: [Replacement](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-replacement)\n  \n* `HostedZoneId`\n\n  The Route53 Hosted Zone to create validation records in.\n\n  - Required: Yes\n  - Type: String\n  - Update requires: [Replacement](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-replacement) \n  \n* `Route53RoleArn`\n\n  The arn of an IAM Role to assume when creating DNS validation records. This can be used to create the records for a\n  Hosted Zone in another AWS account.\n\n  - Required: No\n  - Type: String\n  - Update requires: [No interruption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-no-interrupt)  \n\n* `Route53RoleExternalId`\n\n  An External ID to use when assuming the Route53RoleArn. This can be set if required by the trust policy of the role. \n  See https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-user_externalid.html for details of using ExternalIds.\n\n  - Required: No\n  - Type: String\n  - Update requires: [No interruption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-no-interrupt)\n\n## Troposphere\n\nIf you are using troposphere you can install this resource as an extension using pip:\n\n    $ pip install troposphere_dns_certificate\n\nYou can then import the Certificate resource from troposphere_dns_certificate.certificatemanager instead of troposphere.certificatemanager. \n\ncloudformation.py is an example of using troposphere to create a template with a Certificate resource. \n\nIf you are not using troposphere, you can simply copy the CustomAcmCertificateLambda and CustomAcmCertificateLambdaExecutionRole\nresources from the cloudformation.json or cloudformation.yaml files.\n\n## Examples\n\nThe certificate resource looks like:\n\n```yaml\nExampleCertificate:\n  Properties:\n    DomainName: test.example.com\n    ValidationMethod: DNS\n    DomainValidationOptions:\n      - DomainName: test.example.com\n        HostedZoneId: Z2KZ5YTUFZNC7H\n    Tags:\n      - Key: Name\n        Value: Example Certificate\n    ServiceToken: !GetAtt 'CustomAcmCertificateLambda.Arn'\n  Type: Custom::DNSCertificate\n```\n\n\nAs with AWS::CertificateManager::Certificate providing the logical ID of the resource to the Ref function returns the certificate ARN.\n\nFor example (in yaml): `!Ref 'ExampleCertificate'`\n\n### SubjectAlternativeNames\n\nAdditional names can be added to the certificate using the SubjectAlternativeNames property.\n\n```yaml\nExampleCertificate:\n  Properties:\n    DomainName: example.com\n    SubjectAlternativeNames:\n      - additional.example.com\n      - another.example.com\n    ValidationMethod: DNS\n    DomainValidationOptions:\n      - DomainName: example.com\n        HostedZoneId: Z2KZ5YTUFZNC7H\n    Tags:\n      - Key: Name\n        Value: Example Certificate\n    ServiceToken: !GetAtt 'CustomAcmCertificateLambda.Arn'\nType: Custom::DNSCertificate\n```\n\n### Multiple Hosted Zones\n\nNames from multiple hosted zones can be used by adding DomainValidationOptions for each of the hosted zones.\nFor example:\n\n```yaml\nExampleCertificate:\n  Properties:\n    DomainName: example.com\n    SubjectAlternativeNames:\n      - additional.example.org\n    ValidationMethod: DNS\n    DomainValidationOptions:\n      - DomainName: example.com\n        HostedZoneId: Z2KZ5YTUFZNC7H\n      - DomainName: example.org\n        HostedZoneId: ZEJZ9DIN47IQN\n    Tags:\n      - Key: Name\n        Value: Example Certificate\n    ServiceToken: !GetAtt 'CustomAcmCertificateLambda.Arn'\nType: Custom::DNSCertificate\n```\n\n### Wildcards\n\nWildcards can be used normally. A certificate for a name and all subdomains for example:\n\n```yaml\nExampleCertificate:\n  Properties:\n    DomainName: example.com\n    SubjectAlternativeNames:\n      - *.example.com\n    ValidationMethod: DNS\n    DomainValidationOptions:\n      - DomainName: example.com\n        HostedZoneId: Z2KZ5YTUFZNC7H\n    Tags:\n      - Key: Name\n        Value: Example Certificate\n    ServiceToken: !GetAtt 'CustomAcmCertificateLambda.Arn'\n  Type: Custom::DNSCertificate\n```\n\n### Specifying a region\n\nThis example uses the Region property to create the certificate in us-east-1, for use with cloudfront:\n\n```yaml\nExampleCertificate:\n  Properties:\n    DomainName: example.com\n    ValidationMethod: DNS\n    DomainValidationOptions:\n      - DomainName: example.com\n        HostedZoneId: Z2KZ5YTUFZNC7H\n    Region: us-east-1\n    Tags:\n      - Key: Name\n        Value: Example Certificate\n    ServiceToken: !GetAtt 'CustomAcmCertificateLambda.Arn'\n  Type: Custom::DNSCertificate\n```\n\n### Assuming a role for Route 53 record creation\n\nIn some cases the account owning the hosted zone might be a different one than the one you are generating the certificate in.\nTo support this you can specify the domain validation option property `Route53RoleArn` with a role-ARN that should be \nassumed before creating the records required for certificate validation.\n\nOptionally, you can also specify a `Route53RoleExternalId` that will be used when assuming the role specified by `Route53RoleArn`.\nThis would be required if the trust policy of the role requires an external ID.\n\nIf a top-level Route53RoleArn property is specified it will be assumed when validating domains that don't contain a\nRoute53RoleArn domain validation option property.\n\n```yaml\nExampleCertificate:\n  Properties:\n    DomainName: test.example.com\n    ValidationMethod: DNS\n    DomainValidationOptions:\n      - DomainName: test.example.com\n        HostedZoneId: Z2KZ5YTUFZNC7H\n        Route53RoleArn: arn:aws:iam::TRUSTING-ACCOUNT-ID:role/ACMRecordCreationRole\n        Route53RoleExternalId: EXTERNAL-ID\n    Tags:\n      - Key: Name\n        Value: Example Certificate\n    ServiceToken: !GetAtt 'CustomAcmCertificateLambda.Arn'\n  Type: Custom::DNSCertificate\n```\n\nAdditionally you have to allow the assumption of this role by adding this statement to the CustomAcmCertificateLambdaExecutionRole:\n\n```yaml\n- Action:\n    - sts:AssumeRole\n  Resource:\n    - arn:aws:iam::TRUSTING-ACCOUNT-ID:role/ACMRecordCreationRole\n  Effect: Allow\n```\n\nIf you are using the troposphere extension, this statement is added automatically. The full CustomAcmCertificateLambdaExecutionRole\nfor this example would look like:\n\n```yaml\nCustomAcmCertificateLambdaExecutionRole:\n  Properties:\n    AssumeRolePolicyDocument:\n      Statement:\n        - Action:\n            - sts:AssumeRole\n          Effect: Allow\n          Principal:\n            Service: lambda.amazonaws.com\n      Version: '2012-10-17'\n    ManagedPolicyArns:\n      - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole\n      - arn:aws:iam::aws:policy/service-role/AWSLambdaRole\n    Policies:\n      - PolicyDocument:\n          Statement:\n            - Action:\n                - acm:AddTagsToCertificate\n                - acm:DeleteCertificate\n                - acm:DescribeCertificate\n                - acm:RemoveTagsFromCertificate\n                - acm:UpdateCertificateOptions\n              Effect: Allow\n              Resource:\n                - !Sub 'arn:${AWS::Partition}:acm:*:${AWS::AccountId}:certificate/*'\n            - Action:\n                - acm:RequestCertificate\n                - acm:ListTagsForCertificate\n                - acm:ListCertificates\n              Effect: Allow\n              Resource:\n                - '*'\n            - Action:\n                - route53:ChangeResourceRecordSets\n              Effect: Allow\n              Resource:\n                - arn:aws:route53:::hostedzone/*\n            - Action:\n                - sts:AssumeRole\n              Effect: Allow\n              Resource:\n                - arn:aws:iam::TRUSTING-ACCOUNT-ID:role/ACMRecordCreationRole\n          Version: '2012-10-17'\n        PolicyName: !Sub '${AWS::StackName}CustomAcmCertificateLambdaExecutionPolicy'\n```\n\nThe IAM role in the account with the hosted zone would look something like:\n\n```yaml\nACMRecordCreationRole:\n  Type: AWS::IAM::Role\n  Properties:\n    AssumeRolePolicyDocument:\n      Statement:\n        - Action:\n            - sts:AssumeRole\n          Principal:\n            AWS:\n              - arn:aws:iam::TRUSTED-ACCOUNT-ID:root\n          Effect: Allow\n          Condition:\n            StringEquals:\n              'sts:ExternalId': EXTERNAL-ID\n      Version: '2012-10-17'\n    Policies:\n      - PolicyName: 'ACMRecordCreation'\n        PolicyDocument:\n          Version: '2012-10-17'\n          Statement:\n            - Action:\n                - route53:ChangeResourceRecordSets\n              Resource:\n                - arn:aws:route53:::hostedzone/Z2KZ5YTUFZNC7H\n              Effect: Allow\n    RoleName: ACMRecordCreationRole\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdflook%2Fcloudformation-dns-certificate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdflook%2Fcloudformation-dns-certificate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdflook%2Fcloudformation-dns-certificate/lists"}