سؤال

Assume I already have purchased a domain example.com with IP address 203.0.113.2. Using C# and the The Amazon Web Services SDK for .NET 2.0.2.2, I'd like to create a static website using a custom domain using Amazon S3 and Route 53. The manual process is described in the Amazon documentation.

When trying to create an alias, I get an exception with the message:

Invalid XML ; cvc-complex-type.2.4.a: Invalid content was found starting with element 'AliasTarget'.
One of '{"https://route53.amazonaws.com/doc/2012-12-12/":ResourceRecords}' is expected.

First, I created or updated a bucket (e.g. "example.com") in Amazon S3. If it already existed, content is deleted.

using (var client = AWSClientFactory.CreateAmazonS3Client(RegionEndpoint.USWest1))
{
    if (!S3BucketExists(name, client))
    {
        client.PutBucket(new PutBucketRequest
        {
            BucketName = name,
            BucketRegion = S3Region.USW1,
            CannedACL = S3CannedACL.PublicRead
        });
    }
    else
    {
        var request = new ListObjectsRequest
        {
            BucketName = name
        };
        var objects = client.ListObjects(request).S3Objects;
        foreach (var o in objects)
        {
            client.DeleteObject(new DeleteObjectRequest
            {
                BucketName = name,
                Key = o.Key
            });
        }
        client.PutACL(new PutACLRequest
        {
            CannedACL = S3CannedACL.PublicRead, 
            BucketName = name
        });
    }

    client.PutBucketWebsite(new PutBucketWebsiteRequest
    {
        BucketName = name,
        WebsiteConfiguration = new WebsiteConfiguration
        {
            ErrorDocument = "404.html",
            IndexDocumentSuffix = "index.html"
        }
    });

    CreateObject(name, client, "index.html", "text/html", "<p>The site is under maintenance</p>");
    CreateObject(name, client, "404.html", "text/html", "<p>Not Found</p>");
}

S3BucketExists returns whether a bucket exist or not, and CreateObject creates a simple page and uploads it to the bucket. Its omitted for brevity sake. I'm able to connect to the S3 hosted site without any problems.

Then I use the Route 53 API to update an existing hosted zone or create one for "example.com". All resources, except for the SOA and NS entries are deleted.

using (var client = AWSClientFactory.CreateAmazonRoute53Client())
{
    var hostedZone = FindHostedZoneByName(client, domainName);
    if (hostedZone != null)
    {
        var resourceRecordSets = client.ListResourceRecordSets(new ListResourceRecordSetsRequest
        {
            HostedZoneId = hostedZone.Id,
        });

        bool hasElements = false;
        var request1 = new ChangeResourceRecordSetsRequest
        {
            HostedZoneId = hostedZone.Id,
            ChangeBatch = new ChangeBatch
            {
                Changes = new List<Change>()
            }
        };
        foreach (var resourceRecordSet in resourceRecordSets.ResourceRecordSets)
        {
            switch (resourceRecordSet.Type)
            {
                case "SOA":
                case "NS":
                    continue;
            }

            var change = new Change
            {
                Action = "DELETE",
                ResourceRecordSet = resourceRecordSet
            };
            request1.ChangeBatch.Changes.Add(change);
            hasElements = true;
        }

        if (hasElements)
        {
            var response = client.ChangeResourceRecordSets(request1);
        }
    }
    else
    {
        hostedZone = CreateHostedZone(client, domainName);
    }

    var hostedZoneId = hostedZone.Id;
    var request = new ChangeResourceRecordSetsRequest
    {
        HostedZoneId = hostedZoneId,
        ChangeBatch = new ChangeBatch
        {
            Changes = new List<Change>
            {
                new Change
                {
                    Action = ChangeAction.CREATE,
                    ResourceRecordSet = new ResourceRecordSet
                    {
                        Name = GetQualifiedName(domainName),
                        Type = RRType.A,
                        TTL = 300,
                        AliasTarget = new AliasTarget()
                        {
                            HostedZoneId = "Z2F56UZL2M1ACD",
                            DNSName = "s3-website-us-west-1.amazonaws.com.",
                        },
                    },
                },
            }
        }
    };
    client.ChangeResourceRecordSets(request);
}

The hosted zone id ("Z2F56UZL2M1ACD") and DNS names ("s3-website-us-west-1.amazonaws.com.") are public knowledge and documented on Amazon's website.

The call to ChangeResourceRecordSets throws the exception. I created an empty ResourceRecords list, with a A record of "203.0.113.2", but have not had any luck creating an alias.

That said, I can manually create the alias to the Amazon S3 site afterwards using the "Route 53 Management Console". I'm sure it's something small I'm missing.

هل كانت مفيدة؟

المحلول

After re-reading the documentation, it turns out that one cannot specify the TTL when specifying an alias. The following change works. Replace the code that creates an instance of ChangeResourceRecordSetsRequest to the following:

var request = new ChangeResourceRecordSetsRequest
{
    HostedZoneId = hostedZoneId,
    ChangeBatch = new ChangeBatch
    {
        Changes = new List<Change>
        {
            new Change
            {
                Action = ChangeAction.CREATE,
                ResourceRecordSet = new ResourceRecordSet
                {
                    Name = GetQualifiedName(domainName),
                    Type = RRType.A,
                    AliasTarget = new AliasTarget
                    {
                        HostedZoneId = "Z2F56UZL2M1ACD",
                        DNSName = "s3-website-us-west-1.amazonaws.com.",
                        EvaluateTargetHealth = false,
                    },
                },
            },
        }
    }
};

The difference was evident when the output produced by System.Net tracing was compared to the request specified in the Amazon example.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top