Terraform-provider-aws: Feature Request - support custom domain in aws_cognito_user_pool_domain

Created on 29 Jun 2018  ·  23Comments  ·  Source: hashicorp/terraform-provider-aws

Community Note

  • Please vote on this issue by adding a 👍 reaction to the original issue to help the community and maintainers prioritize this request
  • Please do not leave "+1" or "me too" comments, they generate extra noise for issue followers and do not help prioritize the request
  • If you are interested in working on this issue or have submitted a pull request, please leave a comment

Description

Custom domain support was launced by AWS in June 2018 but not supported by Terraform. There is a new arn param for a certificate and if there is a certificate provided then the domain param will be the full domain. Right now validateCognitoUserPoolDomain function won't accept that.

New or Affected Resource(s)

  • aws_cognito_user_pool_domain

Potential Terraform Configuration

resource "aws_cognito_user_pool_domain" "main" {
  domain          = "auth.example.com"
  certificate_arn = "${aws_acm_certificate_validation.cert.certificate_arn}"
  user_pool_id    = "${aws_cognito_user_pool.pool.id}"
}

References

enhancement serviccognito

Most helpful comment

Just wanted to leave a note as the AWS Go SDK and Cognito API's have been updated to support this functionality. Would anyone be kind enough to pick up this effort?

Go SDK Docs for Cognito Identity Provider

Cognito API for Create User Pool Domain

All 23 comments

@eigilsagafos have you found any way to do this pragmatically (without using the AWS Console)? I have not been able to find the functionality exposed in any of their APIs or via the CLI.

Would be awesome to see this as a functionality of terraform.

@ajb3ck The AWS documentation is not updated as far as I know, but I inspected the traffic from the web dashboard and the only difference is that you pass the arn for the certificate.

Just wanted to leave a note as the AWS Go SDK and Cognito API's have been updated to support this functionality. Would anyone be kind enough to pick up this effort?

Go SDK Docs for Cognito Identity Provider

Cognito API for Create User Pool Domain

Support for a new certificate_arn argument has been merged and will release with version 1.42.0 of the AWS provider, likely later today. 👍

This has been released in version 1.42.0 of the AWS provider. Please see the Terraform documentation on provider versioning or reach out if you need any assistance upgrading.

When creating a custom Cognito domain, the CloudFront distribution's DNS domain name is needed to create an alias record in Route 53. Looking at the docs, though, it doesn't appear that there is a data source for a aws_cloudfront_distribution.

Does anyone know if the domain name can be retrieved using the ARN in the output of this resource? For example, will the resource attribute for an aws_arn data source provide the DNS domain name?

I stumbled upon the same problem as @myedibleenso. It would be great to have the configuration of the aws_route53_record be part of the Custom Cognito domain example on https://www.terraform.io/docs/providers/aws/r/cognito_user_pool_domain.html.

I was able to get my Cognito custom auth domain registered in Route53 with the following:

resource "aws_route53_record" "cognito_auth" {
  zone_id = "${data.aws_route53_zone.myzone.zone_id}"
  name    = "auth.${data.aws_route53_zone.myzone.name}"
  type    = "A"
  alias {
    name = "${aws_cognito_user_pool_domain.mydomain.cloudfront_distribution_arn}"
    // The following zone id is CloudFront.
    // See https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53-aliastarget.html
    zone_id = "Z2FDTNDATAQYW2"
    evaluate_target_health = false
  }
}

Thanks, @skehlet. Hardcoding the zone_id isn't really an option for me though...

@mastertinner Just for my own understanding, why can't you hardcode the zone id for CloudFront? Is there a case where the cloudfront_distribution_arn attribute exported by aws_cognito_user_pool_domain isn't CloudFront?

Thanks, @skehlet. Based on the link you shared, it looks like CloudFront's Zone ID is always Z2FDTNDATAQYW2, so it might make sense for the configuration of such an alias record to be folded into aws_cognito_user_pool_domain.

Curious to hear what others think of this proposal...

@skehlet, sorry I didn't properly read the link you added. In that case, hardcoding the zone_id is fine.

@skehlet, sorry for bothering you again. I stumbled upon another problem. When creating the two resources, there seems to be a circular dependency:

resource "aws_route53_record" "auth" {
  zone_id = "${aws_route53_zone.main.id}"
  name    = "auth"
  type    = "A"

  alias {
    name                   = "${aws_cognito_user_pool_domain.main.cloudfront_distribution_arn}"
    zone_id                = "Z2FDTNDATAQYW2"                                                   // See https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53-aliastarget.html
    evaluate_target_health = true
  }
}

resource "aws_cognito_user_pool_domain" "main" {
  domain          = "auth${var.resource_suffix}.${substr(aws_route53_zone.main.name, 0, length(aws_route53_zone.main.name) - 1)}"
  certificate_arn = "${aws_acm_certificate_validation.cert.certificate_arn}"
  user_pool_id    = "${aws_cognito_user_pool.main.id}"
}

If specified like that, Terraform will try to create the aws_cognito_user_pool_domain first because aws_route53_record references it as a variable. However, it won't succeed because, from the AWS API's perspective, the creation of the domain only succeeds if there is a valid alias record for the FQDN. How have you solved that problem?

@mastertinner No worries, I think you're almost there, the issue is the parent domain (aws_route53_zone.main.name in your example) needs to already exist and be an A record, so you need to point it to something, for example your website.

I put a not-a-fully-working-app but hopefully good enough PoC up on github which creates the custom domain. Let me know if it helps. One thing relevant to what you pointed out, I had to add a depends_on to make the aws_cognito_user_pool_domain wait for the parent domain to be created.

I have the same problem as @mastertinner . It seems like my aws_cognito_user_pool_domain deployment is stuck waiting for it to complete (I assume because it expects the cname record to be created). Which terraform will not do until after the pool domain is finished successful.

And yes I do have an A record for my base domain.

Well, after struggling for a long time trying to setup a cognito user pool using custom domain I came to the conclusion that this feature is incomplete. Because of the nature of how AWS handle the custom domain creation, aws_cognito_user_pool_domain will wait until the DNS being proper configured on Route53. But, I would only use aws_route53_record to create an alias when I had the aws_cognito_user_pool_domain.my-custom-domain.cloudfront_distribution_arn available. Well, it's clear a deadlock situation which should be handled internally by terraform and not on my source code.

I have a working example here. Can you compare it to what you have?

My custom cognito domain for the example is auth.aws.stevekehlet.com and here is the URL that starts the oauth2 flow with Cognito. If you mouse over that link you can see the custom domain, and if you click it you'll land on the Cognito login page and see the custom domain in your browser's URL box.

Hi @skehlet, thanks for your reply.

I'm afraid I still didn't manage to fix the problem. Actually, my source code is quite similar to yours and I can't figure out the reason it doesn't work. Do you mind to take a look into my source code and the output log? Maybe a second pair of eyes would be great to figure out what is happening...

https://gist.github.com/miere/4f2c7c253216f771e8dc63b9c6ae88b3

Hi @miere, I didn't finish looking through everything, but I saw your log (thank you for including!) and you ctrl-c'd after 17min, is this the problem you're seeing? When I was trying it, it really does take 30-45 minutes to finish.

When I was trying it, it really does take 30-45 minutes to finish.

Unfortunately, 45 is a lot of time. I wonder how it would behave when I have to update my _log in_ page, or need to change the Cognito's Pool configuration. Would my users face issues due to stale configuration? I'm not sure if I would have such a long _maintenance window_ to apply these changes.

you ctrl-c'd after 17min, is this the problem you're seeing?

Not really, but let me share my thoughts with you:

  • The AWS Console states that it would take up to 15minutes to have the domain properly applied. And indeed, if you do it manually, or by using the AWS CLI, it take less than 15m to have the domain properly setup.
  • It was stuck at the aws_cognito_user_pool_domain.default execution. Although the docs doesn't state for how long it would take to change from the CREATING to ACTIVE state, in my local experiments it won't change if we don't update the DNS record to point to the correct CloudFront distribution.
  • That said I started to dig into the aws_cognito_user_pool_domain's source code to better understand how it works. To me it's clear that it waits until the status changes again to _ACTIVE_, what would never happen until the DNS register is updated.

I'll put a little more effort into this. Maybe, despite of my skepticism, I should wait more time to get it done.

@skehlet As you've stated before, it took time (almost one hour) but it changed its status from CREATING to ACTIVE and therefore was able to assign a subdomain to it. I've also simulated a few changes on my User Pool and most of them were quite quick.

That said, it is obvious that I was wrong about this issue being unfinished. Despite of that I'd like to leave a few suggestions in order to improve the developer experience whilst using this particular resource:

  • It should clearly state that this would take a long time to finished. That could save me hours of trial and error.
  • The docs about this particular resource should definitely be update and include more examples. Luckily, I was capable to use Intellij's auto complete feature, AWS docs and few snippets found in the internet to move forward with this task. @skehlet working example would be a great start point, indeed.
  • I'm still a bit concerned about the time it takes to accomplish the first deployment. Most of CI/CD tools got used to impose low build times and encourage the build to be split into smaller pieces. In these cases, terraform would be restricted by this and the build would fail.
  • The validation strategy that checks if the status changed from CREATING to ACTIVE, in my opinion, could be optional. That would allow terraform to execute other tasks while the domain is being created, drastically lowering the build time and imposing a smaller the maintenance window in which users would experience stale configuration during upgrades.

Hey @miere I'm glad you got it working! I think those are some valid points and would help people in the future. Related, there is one other big issue with Cognito custom domains for me, and that's the current hard limit of 4 custom domains per AWS account. I was originally planning on having one for each customer, but between that and the long time to provision, I have to figure out something else. AWS support told me to look into using API Gateway to reverse proxy Cognito's login page, which would avoid this limit, and might be faster to deploy too. Sounds unpleasant but doable. I haven't looked into it yet.

I'm going to lock this issue because it has been closed for _30 days_ ⏳. This helps our maintainers find and focus on the active issues.

If you feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. Thanks!

Was this page helpful?
0 / 5 - 0 ratings