-
Notifications
You must be signed in to change notification settings - Fork 57
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::Cognito::UserPoolDomain missing return value for the CloudFront target #356
Comments
Yeah need this one too. |
i am glad i am not the only need this feature... back to write my Cfn custom resources for now |
Please share it here....until AWS provides proper resolution :) |
sorry, as contractor my works are IP of my client. can't share it out |
Edit 2: See this comment for the modern AWS CDK version of this. For those that end up here like I did, as a workaround it's possible to get the
Edit: My personal workaround using https://github.com/aws/aws-cdk and const cdk = require('@aws-cdk/core')
const cognito = require('@aws-cdk/aws-cognito')
const cr = require('@aws-cdk/custom-resources')
const route53 = require('@aws-cdk/aws-route53')
// The userPool was defined earlier in the code (not shown here)
// This creates the user pool domain resource
const userPoolDomain = new cognito.CfnUserPoolDomain(
this,
'UserPoolDomain',
{
userPoolId: userPool.userPoolId,
domain: authDomain,
customDomainConfig: {
certificateArn,
},
}
)
userPoolDomain.node.addDependency(userPool)
// This allows us to get the cloudfront distribution using a custom resource that calls the AWS SDK
const describeCognitoUserPoolDomain = new cr.AwsCustomResource(
this,
'DescribeCognitoUserPoolDomain',
{
resourceType: 'Custom::DescribeCognitoUserPoolDomain',
onCreate: {
region: 'us-east-1',
service: 'CognitoIdentityServiceProvider',
action: 'describeUserPoolDomain',
parameters: {
Domain: userPoolDomain.domain,
},
physicalResourceId: cr.PhysicalResourceId.of(userPoolDomain.domain),
},
// TODO: can we restrict this policy more? Get the ARN for the user pool domain? Or the user pool maybe?
policy: cr.AwsCustomResourcePolicy.fromSdkCalls({
resources: cr.AwsCustomResourcePolicy.ANY_RESOURCE,
}),
}
)
describeCognitoUserPoolDomain.node.addDependency(userPoolDomain)
const userPoolDomainDistribution = describeCognitoUserPoolDomain.getResponseField(
'DomainDescription.CloudFrontDistribution'
) |
I recently threw together a Custom Resource to do this and released it in AWS SAR: https://serverlessrepo.aws.amazon.com/applications/arn:aws:serverlessrepo:us-east-1:273450712882:applications~amazon-cognito-domain-distribution Happy to iterate on any improvement ideas |
Here's how to get around it. Assuming you have a THE_STACK_NAME="my-cognito-stack"
THE_DOMAIN_NAME="auth.yourveryowndomain.org"
# get the alias target
# notice that it will be empty upon first launch (chicken and the egg problem)
ALIAS_TARGET=$(aws cognito-idp describe-user-pool-domain --domain ${THE_DOMAIN_NAME} | grep CloudFrontDistribution | cut -d \" -f4)
# create/update the deployment CloudFormation stack
# notice the AliasTarget parameter (which can be empty, it's okay!)
aws cloudformation deploy --stack-name ${THE_STACK_NAME} --template-file stack.yaml --parameter-overrides AliasTarget=${ALIAS_TARGET} DomainName=${THE_DOMAIN_NAME} The ---
AWSTemplateFormatVersion: 2010-09-09
Parameters:
DomainName:
Type: String
Default: auth.yourveryowndomain.org
Description: The domain name to use to serve this project.
ZoneName:
Type: String
Default: yourveryowndomain.org
Description: The hosted zone name coming along with the DomainName used.
AliasTarget: # no default value, can be empty
Type: String
Description: The UserPoolDomain alias target.
Conditions: # here's "the trick"
HasAliasTarget: !Not [!Equals ['', !Ref AliasTarget]]
Resources:
Certificate:
Type: "AWS::CertificateManager::Certificate"
Properties:
DomainName: !Ref ZoneName
DomainValidationOptions:
- DomainName: !Ref ZoneName
ValidationDomain: !Ref ZoneName
SubjectAlternativeNames:
- !Ref DomainName
UserPool:
Type: AWS::Cognito::UserPool
Properties:
[... fill that with your configuration! ...]
UserPoolDomain:
Type: AWS::Cognito::UserPoolDomain
Properties:
UserPoolId: !Ref UserPool
Domain: !Ref DomainName
CustomDomainConfig:
CertificateArn: !Ref Certificate
DnsRecord: # if AliasTarget parameter is empty, well we just can't do that one!
Condition: HasAliasTarget # and here's how we don't do it when we can't
Type: AWS::Route53::RecordSet
Properties:
HostedZoneName: !Sub "${ZoneName}."
AliasTarget:
DNSName: !Ref AliasTarget
EvaluateTargetHealth: false
# HostedZoneId value for CloudFront is always this one
# see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53-aliastarget.html
HostedZoneId: Z2FDTNDATAQYW2
Name: !Ref DomainName
Type: A Be aware CloudFormation conditions are not "a trick" at all: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/conditions-section-structure.html. We simply use it as a trick along with the "first launch won't do it all" to get around our scenario. Kinda weird, but only for the first run! Launch it again: everything is fine 👌 PS: can't wait to avoid all that by simply having the CloudFrontDistribution alias target directly in the |
CDK recently added constructs for this. In CDK, all you need to do is: const userPoolDomain = new cognito.UserPoolDomain(this, 'UserPoolDomain', {
userPool,
customDomain: {
domainName: `auth.${domainName}`,
certificate,
},
});
new route53.ARecord(this, 'UserPoolDomainAliasRecord', {
zone: hostedZone,
recordName: `auth.${domainName}`,
target: route53.RecordTarget.fromAlias(new route53_targets.UserPoolDomainTarget(userPoolDomain)),
}); CDK API reference for UserPoolDomainTarget. |
Nice to see it solved in the CDK. But we need that for simple Cloudformation templates as well. |
duplicate of #241 ? |
I will probably utilize this custom resource, and forget (next year or after) when the attribute is built in. |
@swoldemi Just tried your custom resource SAR, and it worked a treat. Thanks for sharing! |
This may have been fixed recently? I initially hit this and came across this article, then I noticed I managed to successfully deploy a Using the original example posted the CloudFormation Template looks like this: AuthDomain:
Type: AWS::Route53::RecordSet
Properties:
HostedZoneId: !Ref HostedZoneId
Domain: !Ref AuthDomainName
Type: 'A'
AliasTarget:
DNSName: !GetAtt UserPoolDomain.CloudFrontDistribution
HostedZoneId: Z2FDTNDATAQYW2 # For CloudFront, HostedZoneId is always Z2FDTNDATAQYW2
EvaluateTargetHealth: false
UserPoolDomain:
Type: AWS::Cognito::UserPoolDomain
Properties:
UserPoolId: !Ref UserPool
Domain: !Ref AuthDomainName
CustomDomainConfig:
CertificateArn: !Ref DomainCertificateArn I needed to give my user |
Yup, looks like it was added here in February |
I am missing the return value for the CloudFront target so that you could create a DNS record in the same template so that you could do this:
Originally posted by @Nr18 in #58 (comment)
The text was updated successfully, but these errors were encountered: