Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[aws-certificatemanager] Create certificate in us-east-1 and use it in a different region #9274

Open
dbartholomae opened this issue Jul 27, 2020 · 33 comments
Labels
@aws-cdk/aws-certificatemanager Related to Amazon Certificate Manager effort/medium Medium work item – several days of effort feature-request A feature should be added or improved. guidance Question that needs advice or information. p2

Comments

@dbartholomae
Copy link
Contributor

❓ General Issue

The Question

I'm currently setting up AWS Cognito with a custom domain via AWS CDK. Our stack lives in eu-central-1, but as I understand the certificate for the custom domain has to live in us-east-1. How can I share the certificate to the AWS Cognito setup?

Environment

  • CDK CLI Version: 1.54.0
  • Module Version: 1.54.0
  • Node.js Version: v12.16.0
  • OS: Windows 10
  • Language (Version): TypeScript (3.9.7)

Other information

There's a discussion around this already which indicates there might not be a solution to this?

@dbartholomae dbartholomae added guidance Question that needs advice or information. needs-triage This issue or PR still needs to be triaged. labels Jul 27, 2020
@github-actions github-actions bot added the @aws-cdk/aws-certificatemanager Related to Amazon Certificate Manager label Jul 27, 2020
@njlynch
Copy link
Contributor

njlynch commented Jul 28, 2020

Hi @dbartholomae,

You generally have two different options for using a certificate cross-region.

  1. Create a dedicated stack for the certificate in us-east-1, and import the certificate in your Cognito stack (in eu-central-1).

  2. Use the DnsValidatedCertificate construct in your Cognito stack, which is a custom resource that can request a certificate cross-region.

Let me know if that helps!

@njlynch njlynch added response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days. and removed needs-triage This issue or PR still needs to be triaged. labels Jul 28, 2020
@dbartholomae
Copy link
Contributor Author

Thanks for the answer! It is good to know that DnsValidatedCertificate is able to request cross-region. Unfortunately the domain in question is not managed by Route53.
For 1: How would I do this import in CDK, given that both stacks are defined in CDK? Do I need to change the CI setup to run multiple times for multiple stacks and somehow pass around the result from one call to the other?

@njlynch
Copy link
Contributor

njlynch commented Jul 28, 2020

If you already have a Certificate created and defined, you can skip the second stack and just import it directly in your Cognito stack.

const certificate = acm.Certificate.fromCertificateArn(this, 'MyImportedCert', 'arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123...');

If you are creating the certificate in one stack (and validating via email or manually with another DNS provider), then you can pass a reference from one stack to another. Something like this:

class MyCertStack extends cdk.Stack {
  public readonly certificate: acm.Certificate;

  constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
    super(scope, id, props);
    certificate = new acm.Certificate(...);
  }
}

interface MyCognitoStackProps extends cdk.StackProps {
  certificate: acm.Certificate;
}

class MyCognitoStack extends cdk.Stack {
  constructor(scope: cdk.App, id: string, props: MyCognitoStackProps) {
    const certificate = props.certificate;
    // Define your Cognito pool here, using the above certificate
  }
}

const certStack = new MyCertificateStack(app, 'MyCerts');
new MyCognitoStack(app, 'MyCognito', { certificate: certStack.certificate });

@dbartholomae
Copy link
Contributor Author

I'm trying the second solution, but so far I always get a cross-stack reference error because the certificate is in us-east-1, but the other stack in eu-central-1.

@github-actions github-actions bot removed the response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days. label Jul 29, 2020
@njlynch
Copy link
Contributor

njlynch commented Jul 29, 2020

Ah, that's correct. Sorry for the misinformation earlier.

Unfortunately, we currently only support cross-environment (region/account) references in instances where we can assign the physical names to the resources; in cases like certificates, where there is only the ARN, we don't currently have a solution.

See #8232 (comment) for one work-around suggestion of creating a custom resource to do the heavy lifting for you. It looks like there are various community-owned solutions to this; I found https://www.npmjs.com/package/@henrist/cdk-cross-region-params as one example. I haven't tested this and can't support it, but it looks like it could be used to pass the certificate ARN cross-stack. YMMV. :)

@dbartholomae
Copy link
Contributor Author

Thanks! Using SSM is actually quite a smart solution. I'll look deeper into it.

@robertofd1995
Copy link

Did aws cdk added officially support for this? I am also struggling with the same problem.

@lenfree
Copy link

lenfree commented Jul 4, 2021

@robertofd1995 not sure if are still stuck with this. If you still are, I think you might be looking for create cross region ACM.

@A-ndy-git
Copy link

+1 for this feature. I know there are some suggested workaround above, but would be nice to see an easier method to implement this.

My scenario is an Edge API in eu-west-2 with a custom domain. The certificate for the custom domain has to be created in us-east-1. Attempting to import the certificate via ARN outputs the cannot find ARN in eu-west-2 error.

@Booligoosh
Copy link
Contributor

Thank you @lenfree, you just saved me hours of headaches 🤗

@jedrekdomanski
Copy link
Contributor

@robertofd1995 not sure if are still stuck with this. If you still are, I think you might be looking for create cross region ACM.

You saved my day ❤️

@Jaftem
Copy link

Jaftem commented Jan 6, 2023

@robertofd1995 not sure if are still stuck with this. If you still are, I think you might be looking for create cross region ACM.

Using cross-region certificate, HostedZone is a required attribute. For our purposes, we have our HostedZone in another AWS account so using this method will not work. This seems like an odd limitation as I can create a certificate in another region through the AWS console.

@salihoglu87
Copy link

The "acm.DnsValidatedCertificate" is now deprecated. Is there any movement so we can create cross-region certificate using "acm.Certificate"?
What is the difference between "acm.DnsValidatedCertificate" and "acm.Certificate" so that we can't set region by "acm.Certificate"?

@peterfranzen
Copy link

I'm also struggling with this. I'm trying to deploy a S3/CloudFront stack in us-west-2 with a certificate that was created in another stack in us-east-1. Short of writing a custom resource lambda to go hunt for the certificate and put its info into SSM Parameter Store, what is the best way to accomplish this?

@mostafafarzaneh
Copy link

mostafafarzaneh commented Feb 8, 2023

The problem becomes a real nightmare when using a custom domain for Cognito UserPool. The UserPool CustomDomain needs an ICertificate, not a Certificate ARN. So there is no solution besides DnsValidatedCertificate which is deprecated.
The CloudFront accepts the Certificate ARN, which you can somehow work around with a custom resource. But not in the Cognito Custom domain case.

This issue should not be closed!

@LukaHedt
Copy link

LukaHedt commented Feb 9, 2023

Yeah this is going to become a real problem using certs for Cloudfront too.
Requiring downtime for playing with cloudformation stack regions (because of a construct deprecation) is not very fun DevOps.
Also makes for some very, very annoying CDK infrastructure dependencies, which drives me insane.

@Brian-Azizi
Copy link

Why has DnsValidatedCertificate been deprecated? How is it's usecase solved with Certificate (which is the suggested alternative)?

@vincent-milia
Copy link

Why has DnsValidatedCertificate been deprecated? How is it's usecase solved with Certificate (which is the suggested alternative)?

y I just came across the same problem. I believe one option to solve this is to create the certificate in a separate stack (with env.region: us-east-1). Then reference the certificate in the other stack and use lookup. Don't know if there is a better way.

@mostafafarzaneh
Copy link

Why has DnsValidatedCertificate been deprecated? How is it's usecase solved with Certificate (which is the suggested alternative)?

y I just came across the same problem. I believe one option to solve this is to create the certificate in a separate stack (with env.region: us-east-1). Then reference the certificate in the other stack and use lookup. Don't know if there is a better way.

Is there a function for lookup in Certificate construct? there is fromCertificateArn, but you cannot use it with cross-region certificates.

@JavierMendozaGomez
Copy link

JavierMendozaGomez commented Apr 13, 2023

I had to write everything in the same app. Defining the two stacks in the same file.


const app = new App();

// Certificate Stack

// The certificate needs to deployed in us-east-1 and using it in index.ts as it needs to be used in the other stack, this is the reason why we put the two stacks here as its impossible to share references between stacks cross regions
// https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_certificatemanager-readme.html

const certificateStack = new Stack(
  app,
  `CertificateStack`,
  {
    env: {
      account: process.env.AWS_ACCOUNT_ID || process.env.CDK_DEFAULT_ACCOUNT,
      region: 'us-east-1',
    },
    crossRegionReferences: true,
  }
);

const yourHostedZone = HostedZone.fromHostedZoneAttributes(
  CertificateStack,
  'YourHostedZone',
  {
    hostedZoneId: yourHostedZoneId
    zoneName: yourHostedZoneName,
  }
);

// Create a certificate for the custom domain in us-east-1 as it is mandatory for Cognito
const yourCertificate = new Certificate(
  certificateStack,
  'YourCertificateStack',
  {
    domainName: YourAPIDomain,
    validation: CertificateValidation.fromDns(yourHostedZone),
  }
);

/// / USER POOL STACK
const userPoolStack = new Stack(app, `UserPoolStack`, {
  env: {
    account: process.env.AWS_ACCOUNT_ID || process.env.CDK_DEFAULT_ACCOUNT,
    region: process.env.AWS_REGION || process.env.CDK_DEFAULT_REGION,
  },
  crossRegionReferences: true,
});

const yourUserPool = new UserPool(userPoolStack, 'UserPool', {
  userPoolName: `yourUserPoolName`,
});

// Using the UserPoolDomain
const userPoolDomain = new UserPoolDomain(userPoolStack, 'UserPoolDomain', {
  userPool: yourUserPool,
  customDomain: {
    domainName: yourAPIDomainURL,
    certificate: yourCertificate,
  },
});

// Creation of ARecord
new ARecord(userPoolStack, 'UserPoolARecord', {
  zone: yourHostedZone,
  recordName: yourAPIDomainURL,
  target: RecordTarget.fromAlias(new UserPoolDomainTarget(userPoolDomain)),
});

And as everything is in the same App and not separated in different stacks, I unit tested it using the cdk out of executingcdk synth`

@sensedata1
Copy link

We now also have a lot of refactoring to do as it appears that the deprecated construct will no longer create the resources defined in our stacks. If one of the certificates gets deleted, we're currently unable to just re-deploy to replace it. Not best pleased.

@mhkafadar
Copy link

Hello,

I've successfully implemented a cross-region deployment, positioning the S3-Cloudfront stack in Europe and the certificate in the us-east-1 region. I've detailed my approach in a blog post. https://medium.com/@mhkafadar/a-practical-aws-cdk-walkthrough-deploying-multiple-websites-to-s3-and-cloudfront-7caaabc9c327

@epiphone
Copy link

Why has DnsValidatedCertificate been deprecated? How is it's usecase solved with Certificate (which is the suggested alternative)?

y I just came across the same problem. I believe one option to solve this is to create the certificate in a separate stack (with env.region: us-east-1). Then reference the certificate in the other stack and use lookup. Don't know if there is a better way.

This is now documented in https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_certificatemanager-readme.html#cross-region-certificates.

@DanielLaberge
Copy link

DanielLaberge commented Jan 22, 2024

This is quite an annoying pitfall that everyone gets into when using CloudFront with ACM and not deploying resources in us-east-1.
Shouldn't solving this kind of headache be CDK's raison d'être?

@rredpoppy
Copy link

this is just downrigth awful..

@case303
Copy link

case303 commented Mar 27, 2024

Thanks @JavierMendozaGomez and @epiphone
This provided good insight around: scope, stacks, and regions.
Specify the desired region in a new Stack, then pass that stack into the Construct's scope. As best illustrated in the docs: Cross-region Certificates

const certificateStack = new cdk.Stack(this, CERTIFICATE_STACK_ID,
      {
        env: {
          account: process.env.AWS_ACCOUNT_ID || process.env.CDK_DEFAULT_ACCOUNT,
          region: 'us-east-1'
        },
        crossRegionReferences: true,
      });
      
const certificate = new acm.Certificate(certificateStack, CERTIFICATE_ID, {
      certificateName: CERTIFICATE_ID,
      domainName: DOMAIN_NAME,
      subjectAlternativeNames: [`*.${DOMAIN_NAME}`],
      validation: acm.CertificateValidation.fromDns(hostedZone),
    });

@pqnet
Copy link

pqnet commented Mar 30, 2024

Unfortunately having a cross-stack reference has the limitation of having to hard-code the zone for all other stacks in the app because Cross stack/region references are only supported for stacks with an explicit region defined.. It would be great if any of this would be true:

  • we could have the certificate in us-east-1 while its stack is deployed somewhere else (as it is for DnsValidatedCertificate). Why has this possibility been dropped?
  • CloudFront didn't require us to host the certificate in us-east-1.
  • cross-stack references wouldn't require to explicitly specify the stack at synth time

@quantfreedom
Copy link

quantfreedom commented Apr 21, 2024

be sure to upvote this or thumbs up it or mark it as an answer so others know it works ... only if it works for you of course ... this way we can save others weeks of trying to figure this out

I have finally figured out how to actually do this ... i am using cdk 2.128.0

This actually works because i am in ca-central-1 and i was able to do it in one stack and created a us-east-1 cert

you can checkout the github code here https://github.com/quantfreedom/aws_cdk_testing/blob/main/amazon_cdk/frontend/www.py

if that doesn't work here is a gist of the current working version https://gist.github.com/quantfreedom/e71267553edc8e0760e88d48ad8b45a7

I watched this youtube video to get an understanding of what is going on and why i am doing the things i am doing
https://www.youtube.com/watch?v=p6Os-_t0gEs

and here is their gh code https://github.com/Durgaprasad-Budhwani/hands-on-aws-cdk-lab/blob/main/ts/cloudfront/lib/cloudfront-stack.ts

also here is a link to my github repo where i am just testing out different aws stacks
https://github.com/quantfreedom/aws_cdk_testing/tree/main

@lucashfreitas
Copy link

This is an example of a really bad experience from with AWS certificate manager.

Got over this issue a number of times which might have costed us AWS developers hundred of hours.

Ended up creating the certificate manually via CLI/console and use the ARN to reference it.

@pahud pahud reopened this Jan 23, 2025
@pahud
Copy link
Contributor

pahud commented Jan 23, 2025

Hi,

I am reopening this issue as a feature request as we've seen the concerns still outstanding. Let me clarify this and we welcome any further thoughts to make the CDK experience even better.

Major complaints about current experience

  1. Cross-Region Certificate Management Difficulties:
  • Struggle with creating certificates in us-east-1 while using them in different regions
  • Particularly problematic for services like CloudFront and Cognito that require certificates to be in us-east-1
  • Cross-stack references don't work well across regions
  1. Deprecation of DnsValidatedCertificate:
  • The DnsValidatedCertificate construct was deprecated without a clear alternative solution
  • Being frustrated that the replacement (Certificate construct) doesn't handle cross-region cases as well
  • This has forced teams to refactor their existing infrastructure code
  1. Limited Solutions:
  • No straightforward "CDK way" to handle cross-region certificates
  • Have to resort to workarounds like:
    • Creating separate stacks
    • Using SSM Parameter Store
    • Manual certificate creation
    • Custom resources
  1. Specific Service Integration Issues:
  • Cognito UserPool CustomDomain requires an ICertificate, not just a Certificate ARN, making workarounds more difficult
  • CloudFront deployments requiring certificates from us-east-1 create unnecessary complexity
  1. Developer Experience:
  • Many users express that this should be a core functionality of CDK
  • The current situation forces developers to spend significant time finding workarounds

Thank you for raising this important concern about cross-region certificate management. We understand this has been a pain point for many of our customers, and we appreciate the detailed feedback.

Current Recommended Solution

For cross-region certificate usage (such as with CloudFront and Cognito), we currently recommend using a multi-stack deployment pattern with the crossRegionReferences feature. Here's the recommended approach:

const stack1 = new Stack(app, 'CertStack', {
  env: { region: 'us-east-1' }, // Certificate must be in us-east-1 for CloudFront
  crossRegionReferences: true
});

const cert = new acm.Certificate(stack1, 'Cert', {
  domainName: '*.example.com',
  validation: acm.CertificateValidation.fromDns() 
});

const stack2 = new Stack(app, 'DistributionStack', {
  env: { region: 'us-east-2' }, // Your app can be in any region
  crossRegionReferences: true
});

// Reference the certificate from stack1 in stack2
new cloudfront.Distribution(stack2, 'Distribution', {
  defaultBehavior: { origin: new origins.HttpOrigin('example.com') },
  domainNames: ['dev.example.com'],
  certificate: cert
});

The reason you need to specify the region code in env is because this demo code is deploying two stacks in different regions in a shared CDK app. You can separate them into two different CDK apps for different region and use process.env.CDK_DEFAULT_REGION for the region env so you don't have to explicitly specify the region code.

Important Notes

  1. While this feature is marked as experimental, it represents our current best practice for handling cross-region certificates
  2. We acknowledge that the deprecation of DnsValidatedCertificate has caused friction, and we're working to improve the experience
  3. The crossRegionReferences feature aims to provide a more maintainable solution compared to previous workarounds

Moving Forward

We understand that the current solution might not cover all use cases perfectly, and we're actively working on improvements. Your feedback helps us prioritize enhancements to the CDK's certificate management capabilities.

If you encounter specific issues with this approach or have additional use cases not covered by the current solution, please let us know. We're committed to improving the developer experience and making cross-region certificate management more straightforward.

Additional Resources

Also, as this thread has been very lengthy and could be very difficult to help users focus on the latest solution. If you are still having any issue or feature request around this use case, please kindly create a new issue. We will be happy to look into your case or any new idea about the API design.

Please don't hesitate to provide additional feedback or ask for clarification. We're here to help!

@pahud pahud added p2 effort/medium Medium work item – several days of effort feature-request A feature should be added or improved. labels Jan 23, 2025
@jk2l
Copy link

jk2l commented Jan 28, 2025

@pahud do this cross stack reference work if there requirement of replacement of ACM?

e.g. domain name expanded and added a new subdomain. using DnsValidatedCertificate will allow us follow Cfn flow (Update with replacement, update dependency, clean up old resource)

i don't see how cross stack reference can handle this well

Also do the CDK team had chatted with Cfn team regarding implementing it officially? aws-cloudformation/cloudformation-coverage-roadmap#523

@pahud
Copy link
Contributor

pahud commented Jan 30, 2025

@jk2l

Thank you for sharing your use case. I think before CFN has native cross-region support, any workaround in CDK would never have the best developer experience. I see 120 upvotes on aws-cloudformation/cloudformation-coverage-roadmap#523 and I believe CFN team definitely would consider that but I can't see any further details from there. Yes, I'd submit an internal ticket to CFN team about this for better visibility but I can't guarantee any timelines about its ETA of that CFN support. I'll add internal ticket reference here and I'll update here as soon as I have any news I can share.

Meanwhile, please help us click 👍 on this issue(not this comment). I am seeing 10 upvotes now. Having more upvotes would definitely help the team prioritize. Thank you.

@pahud
Copy link
Contributor

pahud commented Jan 30, 2025

internal tracking - V1660274068

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
@aws-cdk/aws-certificatemanager Related to Amazon Certificate Manager effort/medium Medium work item – several days of effort feature-request A feature should be added or improved. guidance Question that needs advice or information. p2
Projects
None yet
Development

No branches or pull requests