Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AWS Policy: Allow update specific record in route53 hosted zone

Assume the documentation, I should use policy, like this:

{
   "Version": "2017-11-27",
   "Statement":[
      {   
         "Effect":"Allow",
         "Action": [
           "route53:ChangeResourceRecordSets"
         ],  
         "Resource": [
          "arn:aws:route53:::hostedzone/<ZONE_ID>"
         ]
   ]   
}

I need a very safe policy.

I cannot add specific resource record set (one record in zone) in arn. I can use Condition to check what record should be changed with ChangeResourceRecordSets API call. If I'm not mistaken.

This is necessary for automatic update only one record in public domain zone. Updates _acme-challenge.ldap.example.com. record for automatically update let's encrypt certificates. I know that acme.sh is available to achive my goal. But I want to write my own custom and simple script to do this.

like image 625
vskubriev Avatar asked Nov 28 '17 09:11

vskubriev


People also ask

What is policy record in AWS Route 53?

To route internet traffic to the resources that you specified when you created a traffic policy, you create one or more policy records. Each policy record identifies the hosted zone where you want to create the policy record and the domain or subdomain name that you want to route traffic for.

How do you edit a Route 53 record?

In the navigation pane, choose Hosted zones. On the Hosted Zones page, choose the row for the hosted zone that contains the records that you want to edit. Select the row for the record that you want to edit, and then enter your changes in the Edit record pane. Enter the applicable values.

How do I add a DS record to Route 53?

To insert the DS record by using the console, Open the Route 53 console at https://console.aws.amazon.com/route53/ . In the navigation pane, choose Hosted zones, the name of your hosted zone and then Create record button.

What is weighted routing policy in AWS?

Weighted routing lets you associate multiple resources with a single domain name (example.com) or subdomain name (acme.example.com) and choose how much traffic is routed to each resource. This can be useful for a variety of purposes, including load balancing and testing new versions of software.


2 Answers

I can use Condition to check what record should be changed with ChangeResourceRecordSets API call. If I'm not mistaken.

I believe you may be mistaken.

Amazon Route 53 has no service-specific [condition] context keys that can be used in an IAM policy.

http://docs.aws.amazon.com/IAM/latest/UserGuide/list_route53.html

Additionally, none of the global condition keys seem applicable.

However, I believe there's a workaround for this.

Create a second public hosted zone for the domain _acme-challenge.ldap.example.com. I know you're probably thinking "but that's not a domain!" but in the relevant sense, it actually is still a domain.

Route 53 will assign 4 new nameservers to this new hosted zone. Make a note of those servers.

Back in your original hosted zone, create a record for _acme-challenge.ldap.example.com of type NS. The value you will use to create this record will be the 4 nameservers that Route 53 assigned to the new hosted zone, one per line. Do not change any of the existing NS records in either of the zones.

This is called a delegation -- you're delegating authority for this particular subdomain to a different hosted zone, which you will notice was automatically assigned a completely different set of 4 Route 53 servers from those that handle your parent domain.

You can now create a new record in the root of the new hosted zone, and when you do a DNS query for _acme-challenge.ldap.example.com, the answer returned will be the answer from the new hosted zone.

Now, you can give your script permission only to modify records in the new zone, and it will be unable to modify anything in the parent zone, because you gave it no permissions, there.

like image 60
Michael - sqlbot Avatar answered Sep 28 '22 11:09

Michael - sqlbot


In the scenario of allowing starting EC2 instances with a script to add/remove record set of a domain programmatically, but limit the access to specific record safely without harming example.com.

Create another public hosted zone (without purchasing another domain from anyone), just use a subdomain like delegate.example.com. Copy the name server assigned to delegate.example.com by AWS like:

ns-1143.awsdns-14.org. 
ns-1686.awsdns-18.co.uk. 
ns-133.awsdns-16.com. 
ns-965.awsdns-56.net.

And for example, the created zone is ZONEABCD

The goal of created domain will be instance-xxx.delegate.example.com without harming example.com

Create a record set of NS Type in the hosted zone under your root example.com. Create a record set of type NS and paste the 4 name servers copied from delegate.example.com.

The you can create a IAM user (copy the accesskey/secretkey for script) with the following policy attached. Limit resource to the created arn:aws:route53:::hostedzone/{ZONEABCD}.

{
"Version": "2012-10-17",
"Statement": [
    {
        "Effect": "Allow",
        "Action": [
            "route53:ChangeResourceRecordSets"
        ],
        "Resource": [
            "arn:aws:route53:::hostedzone/{ZONEABCD}"
        ]
    },
    {
        "Effect": "Allow",
        "Action": [
            "route53:ListHostedZonesByName"
        ],
        "Resource": [
            "*"
        ]
    }
]}

Launch a VM with name instance-xxx and run script with aws-cli

$aws route53 change-resource-record-sets --cli-input-json '{
"HostedZoneId": "ZONEABCD",
"ChangeBatch": {
    "Comment": "This is a test and may be deleted.",
    "Changes": [
        {
            "Action": "CREATE",
            "ResourceRecordSet": {
                "Name": "instance-xxx.delegate.example.com",
                "Type": "A",
                "TTL": 600,
              "ResourceRecords": [
                {
                  "Value": "some.ip.v4.address"
                }
              ]
            }
        }
    ]
}}'

$nslookup instance-xxx.delegate.example.com 

Returning {some.ip.v4.address} for instance-xxx.delegate.example.com proves the above is working.

like image 34
shooding Avatar answered Sep 28 '22 12:09

shooding