Describe the bug
When creating a new ses.EmailIdentity construct, the names of the DKIM records that get created in Route53 are incorrect.
Expected Behavior
If the DKIM record name is x.y.example.com, and the hosted zone is y.example.com, the name of the record that gets set in Route53 should be x.y.example.com
Current Behavior
If the DKIM record name is x.y.example.com, and the hosted zone is y.example.com, the name of the record that gets set in Route53 should is x.y.example.com.y.example.com
Reproduction Steps
Here is a simple reproduction case:
const myHostedZone = ...; // However you're grabbing or creating your hosted zone
const sesIdentity = new ses.EmailIdentity(this, "ses-identity", {
identity: ses.Identity.publicHostedZone(hostedZone),
mailFromDomain: `mail.${hostedZoneDomain}`,
});
Possible Solution
The reason for the incorrect record names is because of the function here in the source code:.
|
if (hostedZone) { |
|
new route53.CnameRecord(emailIdentity, 'DkimDnsToken1', { |
|
zone: hostedZone, |
|
recordName: Lazy.string({ produce: () => emailIdentity.dkimDnsTokenName1 }), |
|
domainName: Lazy.string({ produce: () => emailIdentity.dkimDnsTokenValue1 }), |
|
}); |
|
|
|
new route53.CnameRecord(hostedZone, 'DkimDnsToken2', { |
|
zone: hostedZone, |
|
recordName: Lazy.string({ produce: () => emailIdentity.dkimDnsTokenName2 }), |
|
domainName: Lazy.string({ produce: () => emailIdentity.dkimDnsTokenValue2 }), |
|
}); |
|
|
|
new route53.CnameRecord(hostedZone, 'DkimDnsToken3', { |
|
zone: hostedZone, |
|
recordName: Lazy.string({ produce: () => emailIdentity.dkimDnsTokenName3 }), |
|
domainName: Lazy.string({ produce: () => emailIdentity.dkimDnsTokenValue3 }), |
|
}); |
It calls route53.CnameRecord, which accepts a record name excluding the hosted zone suffix - eg. for x.y.example.com where the hosted zone is y.example.com, the record name should just be x.
However, it's passing in dkimDnsTokenName1 etc, which according to the Cloudformation docs, is the entire host for the record, including the hosted zone.
This means that route53.CnameRecord tried to append the hosted zone name onto the end of the record name which already includes the hosted zone name, leading to the duplication.
This can be seen in a cdk synth:
...
Type: AWS::Route53::RecordSet
Properties:
Name:
Fn::Join:
- ""
- - Fn::GetAtt:
- <Our SES Entity ID>
- DkimDNSTokenName1
- .y.example.com.
Type: CNAME
...
There are 2 fixes that I can think of:
- Call
CfnRecordSet rather than CnameRecord - eg:
new route53.CfnRecordSet(emailIdentity, "DkimDnsToken1", {
hostedZoneName: hostedZone.zoneName + ".",
name: Lazy.string({ produce: () => emailIdentity.dkimDnsTokenName1 }),
type: "CNAME",
resourceRecords: [Lazy.string({ produce: () => emailIdentity.dkimDnsTokenValue1 })],
ttl: "1800",
})
- Use a hacky workaround to lop off the suffix before passing to
CnameRecord - by combining cdk.Fn.select and cdk.Fn.split to remove the last part of the string. Here's how that would look:
// This function removes a string from the end of another string using Cfn functions.
// For example, calling it on "abcd" with suffix "cd" would return "ab".
// We accomplish this by splitting by the suffix (which gives ["ab"]), then selecting the 0th value.
const hackyCfnRemoveSuffix = (sourceString: string, suffixToRemove: string) =>
cdk.Fn.select(0, cdk.Fn.split(suffixToRemove, sourceString));
// Then use it in the bind function
new route53.CnameRecord(emailIdentity, 'DkimDnsToken1', {
zone: hostedZone,
recordName: hackyCfnRemoveSuffix(Lazy.string({ produce: () => emailIdentity.dkimDnsTokenName1 }), "." + hostedZone.zoneName),
domainName: Lazy.string({ produce: () => emailIdentity.dkimDnsTokenValue1 }),
});
Additional Information/Context
No response
CDK CLI Version
2.29.0 (build 47d7ec4)
Framework Version
2.33.0
Node.js Version
v16.15.1
OS
MacOS
Language
Typescript
Language Version
No response
Other information
Workaround
For anyone else experiencing this issue - we've opted to go with the CfnRecordSet option as it's a bit simpler to see what's going on. Simply map through each of the dkimRecords after creating the EmailIdentity and create the correct records - note that this won't remove the incorrect ones unfortunately.
Code below:
// Create SES email identity based on Route53 hosted zone
const sesIdentity = new ses.EmailIdentity(this, "ses-identity", {
identity: ses.Identity.publicHostedZone(hostedZone),
mailFromDomain: `mail.${hostedZone.zoneName}`,
});
// Temporary workaround: There is a bug with the EmailIdentity construct where if the DKIM record is x.y.example.com,
// and the hosted zone is y.example.com, the record that gets set is x.y.example.com.y.example.com. For now, we are
// manually creating the correct records.
const dkimCnameRecords = sesIdentity.dkimRecords.map(
(dkimRecord, index) =>
new route53.CfnRecordSet(this, `dkim-record-${index}`, {
hostedZoneName: hostedZone.zoneName + ".",
name: dkimRecord.name,
type: "CNAME",
resourceRecords: [dkimRecord.value],
ttl: "1800",
})
);
Describe the bug
When creating a new
ses.EmailIdentityconstruct, the names of the DKIM records that get created in Route53 are incorrect.Expected Behavior
If the DKIM record name is
x.y.example.com, and the hosted zone isy.example.com, the name of the record that gets set in Route53 should bex.y.example.comCurrent Behavior
If the DKIM record name is
x.y.example.com, and the hosted zone isy.example.com, the name of the record that gets set in Route53 should isx.y.example.com.y.example.comReproduction Steps
Here is a simple reproduction case:
Possible Solution
The reason for the incorrect record names is because of the function here in the source code:.
aws-cdk/packages/@aws-cdk/aws-ses/lib/email-identity.ts
Lines 220 to 237 in ac32340
It calls
route53.CnameRecord, which accepts a record name excluding the hosted zone suffix - eg. forx.y.example.comwhere the hosted zone isy.example.com, the record name should just bex.However, it's passing in
dkimDnsTokenName1etc, which according to the Cloudformation docs, is the entire host for the record, including the hosted zone.This means that
route53.CnameRecordtried to append the hosted zone name onto the end of the record name which already includes the hosted zone name, leading to the duplication.This can be seen in a
cdk synth:... Type: AWS::Route53::RecordSet Properties: Name: Fn::Join: - "" - - Fn::GetAtt: - <Our SES Entity ID> - DkimDNSTokenName1 - .y.example.com. Type: CNAME ...There are 2 fixes that I can think of:
CfnRecordSetrather thanCnameRecord- eg:CnameRecord- by combiningcdk.Fn.selectandcdk.Fn.splitto remove the last part of the string. Here's how that would look:Additional Information/Context
No response
CDK CLI Version
2.29.0 (build 47d7ec4)
Framework Version
2.33.0
Node.js Version
v16.15.1
OS
MacOS
Language
Typescript
Language Version
No response
Other information
Workaround
For anyone else experiencing this issue - we've opted to go with the
CfnRecordSetoption as it's a bit simpler to see what's going on. Simply map through each of thedkimRecordsafter creating theEmailIdentityand create the correct records - note that this won't remove the incorrect ones unfortunately.Code below: