From e61433649fbc9dc8350784e5b97a38f07ad70046 Mon Sep 17 00:00:00 2001 From: Aaron Walker Date: Wed, 3 Aug 2022 15:03:26 +0000 Subject: [PATCH] supports overriding the dns_name for the hosted zone --- route53-zone.cfndsl.rb | 10 +- route53-zone.config.yaml | 2 - spec/override_dns_domain_spec.rb | 164 ++++++++++++++++++++++++++++ tests/override_dns_domain.test.yaml | 13 +++ 4 files changed, 182 insertions(+), 7 deletions(-) create mode 100644 spec/override_dns_domain_spec.rb create mode 100644 tests/override_dns_domain.test.yaml diff --git a/route53-zone.cfndsl.rb b/route53-zone.cfndsl.rb index f288ff2..ee502b5 100644 --- a/route53-zone.cfndsl.rb +++ b/route53-zone.cfndsl.rb @@ -18,11 +18,11 @@ tags << { Key: 'EnvironmentType', Value: Ref(:EnvironmentType) } extra_tags = external_parameters.fetch(:extra_tags, {}) extra_tags.each { |key,value| tags << { Key: key, Value: value } } - - dns_domain = external_parameters[:dns_domain] + dns_domain_default = FnSub('${EnvironmentName}.${RootDomainName}') + dns_domain = external_parameters.fetch(:dns_domain, dns_domain_default) Route53_HostedZone('HostedZone') do Condition 'CreateZone' - Name FnSub(dns_domain) + Name dns_domain HostedZoneConfig ({ Comment: FnSub("Hosted Zone for ${EnvironmentName}") }) @@ -35,7 +35,7 @@ Property 'ServiceToken',FnGetAtt('Route53ZoneCR','Arn') Property 'AwsRegion', Ref('AWS::Region') Property 'RootDomainName', Ref('RootDomainName') - Property 'DomainName', FnSub(dns_domain) + Property 'DomainName', dns_domain Property 'NSRecords', FnGetAtt('HostedZone', 'NameServers') Property 'ParentIAMRole', Ref('ParentIAMRole') end @@ -44,7 +44,7 @@ Condition 'LocalNSRecords' HostedZoneName Ref('RootDomainName') Comment FnJoin('',[FnSub('${EnvironmentName} - NS Records for ${EnvironmentName}.'), Ref('RootDomainName')]) - Name FnSub(dns_domain) + Name dns_domain Type 'NS' TTL 60 ResourceRecords FnGetAtt('HostedZone', 'NameServers') diff --git a/route53-zone.config.yaml b/route53-zone.config.yaml index 20efff1..279094d 100644 --- a/route53-zone.config.yaml +++ b/route53-zone.config.yaml @@ -1,5 +1,3 @@ -dns_domain: ${EnvironmentName}.${RootDomainName} - route53_custom_resources: custom_policies: route53: diff --git a/spec/override_dns_domain_spec.rb b/spec/override_dns_domain_spec.rb new file mode 100644 index 0000000..13e297a --- /dev/null +++ b/spec/override_dns_domain_spec.rb @@ -0,0 +1,164 @@ +require 'yaml' + +describe 'compiled component route53-zone' do + + context 'cftest' do + it 'compiles test' do + expect(system("cfhighlander cftest #{@validate} --tests tests/override_dns_domain.test.yaml")).to be_truthy + end + end + + let(:template) { YAML.load_file("#{File.dirname(__FILE__)}/../out/tests/override_dns_domain/route53-zone.compiled.yaml") } + + context "Resource" do + + + context "HostedZone" do + let(:resource) { template["Resources"]["HostedZone"] } + + it "is of type AWS::Route53::HostedZone" do + expect(resource["Type"]).to eq("AWS::Route53::HostedZone") + end + + it "to have property Name" do + expect(resource["Properties"]["Name"]).to eq("Fn::Join" => [".", [{"Ref"=>"EnvironmentName"}, {"Ref"=>"DnsDomain"}]]) + end + + it "to have property HostedZoneConfig" do + expect(resource["Properties"]["HostedZoneConfig"]).to eq({"Comment"=>{"Fn::Sub"=>"Hosted Zone for ${EnvironmentName}"}}) + end + + it "to have property HostedZoneTags" do + expect(resource["Properties"]["HostedZoneTags"]).to eq([{"Key"=>"Environment", "Value"=>{"Ref"=>"EnvironmentName"}}, {"Key"=>"EnvironmentType", "Value"=>{"Ref"=>"EnvironmentType"}}]) + end + + end + + context "DomainNameZoneNSRecords" do + let(:resource) { template["Resources"]["DomainNameZoneNSRecords"] } + + it "is of type Custom::Route53ZoneNSRecords" do + expect(resource["Type"]).to eq("Custom::Route53ZoneNSRecords") + end + + it "to have property ServiceToken" do + expect(resource["Properties"]["ServiceToken"]).to eq({"Fn::GetAtt"=>["Route53ZoneCR", "Arn"]}) + end + + it "to have property AwsRegion" do + expect(resource["Properties"]["AwsRegion"]).to eq({"Ref"=>"AWS::Region"}) + end + + it "to have property RootDomainName" do + expect(resource["Properties"]["RootDomainName"]).to eq({"Ref"=>"RootDomainName"}) + end + + it "to have property DomainName" do + expect(resource["Properties"]["DomainName"]).to eq("Fn::Join" => [".", [{"Ref"=>"EnvironmentName"}, {"Ref"=>"DnsDomain"}]]) + end + + it "to have property NSRecords" do + expect(resource["Properties"]["NSRecords"]).to eq({"Fn::GetAtt"=>["HostedZone", "NameServers"]}) + end + + it "to have property ParentIAMRole" do + expect(resource["Properties"]["ParentIAMRole"]).to eq({"Ref"=>"ParentIAMRole"}) + end + + end + + context "NSRecords" do + let(:resource) { template["Resources"]["NSRecords"] } + + it "is of type AWS::Route53::RecordSet" do + expect(resource["Type"]).to eq("AWS::Route53::RecordSet") + end + + it "to have property HostedZoneName" do + expect(resource["Properties"]["HostedZoneName"]).to eq({"Ref"=>"RootDomainName"}) + end + + it "to have property Comment" do + expect(resource["Properties"]["Comment"]).to eq({"Fn::Join"=>["", [{"Fn::Sub"=>"${EnvironmentName} - NS Records for ${EnvironmentName}."}, {"Ref"=>"RootDomainName"}]]}) + end + + it "to have property Name" do + expect(resource["Properties"]["Name"]).to eq("Fn::Join" => [".", [{"Ref"=>"EnvironmentName"}, {"Ref"=>"DnsDomain"}]]) + end + + it "to have property Type" do + expect(resource["Properties"]["Type"]).to eq("NS") + end + + it "to have property TTL" do + expect(resource["Properties"]["TTL"]).to eq(60) + end + + it "to have property ResourceRecords" do + expect(resource["Properties"]["ResourceRecords"]).to eq({"Fn::GetAtt"=>["HostedZone", "NameServers"]}) + end + + end + + context "LambdaRoleRoute53ZoneResource" do + let(:resource) { template["Resources"]["LambdaRoleRoute53ZoneResource"] } + + it "is of type AWS::IAM::Role" do + expect(resource["Type"]).to eq("AWS::IAM::Role") + end + + it "to have property AssumeRolePolicyDocument" do + expect(resource["Properties"]["AssumeRolePolicyDocument"]).to eq({"Version"=>"2012-10-17", "Statement"=>[{"Effect"=>"Allow", "Principal"=>{"Service"=>"lambda.amazonaws.com"}, "Action"=>"sts:AssumeRole"}]}) + end + + it "to have property Path" do + expect(resource["Properties"]["Path"]).to eq("/") + end + + it "to have property Policies" do + expect(resource["Properties"]["Policies"]).to eq([{"PolicyName"=>"cloudwatch-logs", "PolicyDocument"=>{"Statement"=>[{"Effect"=>"Allow", "Action"=>["logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents", "logs:DescribeLogStreams", "logs:DescribeLogGroups"], "Resource"=>["arn:aws:logs:*:*:*"]}]}}, {"PolicyName"=>"route53", "PolicyDocument"=>{"Statement"=>[{"Effect"=>"Allow", "Action"=>["route53:*"], "Resource"=>"*"}]}}, {"PolicyName"=>"opsdns", "PolicyDocument"=>{"Statement"=>[{"Effect"=>"Allow", "Action"=>["sts:AssumeRole"], "Resource"=>[{"Fn::If"=>["RemoteNSRecords", {"Ref"=>"ParentIAMRole"}, "arn:aws:iam::123456789012:user/noaccess"]}]}]}}]) + end + + end + + context "Route53ZoneCR" do + let(:resource) { template["Resources"]["Route53ZoneCR"] } + + it "is of type AWS::Lambda::Function" do + expect(resource["Type"]).to eq("AWS::Lambda::Function") + end + + it "to have property Code" do + expect(resource["Properties"]["Code"]["S3Bucket"]).to eq("") + expect(resource["Properties"]["Code"]["S3Key"]).to start_with("/latest/Route53ZoneCR.route53-zone.latest") + end + + it "to have property Environment" do + expect(resource["Properties"]["Environment"]).to eq({"Variables"=>{"ENVIRONMENT_NAME"=>{"Ref"=>"EnvironmentName"}}}) + end + + it "to have property Handler" do + expect(resource["Properties"]["Handler"]).to eq("route53_zone_cr.handler") + end + + it "to have property MemorySize" do + expect(resource["Properties"]["MemorySize"]).to eq(128) + end + + it "to have property Role" do + expect(resource["Properties"]["Role"]).to eq({"Fn::GetAtt"=>["LambdaRoleRoute53ZoneResource", "Arn"]}) + end + + it "to have property Runtime" do + expect(resource["Properties"]["Runtime"]).to eq("python3.7") + end + + it "to have property Timeout" do + expect(resource["Properties"]["Timeout"]).to eq(600) + end + + end + + end + +end \ No newline at end of file diff --git a/tests/override_dns_domain.test.yaml b/tests/override_dns_domain.test.yaml new file mode 100644 index 0000000..9f1412a --- /dev/null +++ b/tests/override_dns_domain.test.yaml @@ -0,0 +1,13 @@ +test_metadata: + type: config + name: override_dns_domain + description: set the description for your test + +test_parameters: + DnsDomain: example.com + +dns_domain: + Fn::Join: + - '.' + - - Ref: EnvironmentName + - Ref: DnsDomain