1
votes

Trying to automate the deployment of a static website using boto3. I have a static website (angular/javascript/html) sitting in a bucket, and need to use the aws cloudfront CDN.

Anyway, looks like making the s3 bucket and copying in the html/js is working fine.

import boto3
cf = boto3.client('cloudfront')

cf.create_distribution(DistributionConfig=dict(CallerReference='firstOne',
            Aliases = dict(Quantity=1, Items=['mydomain.com']),
            DefaultRootObject='index.html',
            Comment='Test distribution',
            Enabled=True,
            Origins = dict(
                Quantity = 1, 
                Items = [dict(
                    Id = '1',
                    DomainName='mydomain.com.s3.amazonaws.com')
                ]),
            DefaultCacheBehavior = dict(
                TargetOriginId = '1',
                ViewerProtocolPolicy= 'redirect-to-https',
                TrustedSigners = dict(Quantity=0, Enabled=False),
                ForwardedValues=dict(
                    Cookies = {'Forward':'all'},
                    Headers = dict(Quantity=0),
                    QueryString=False,
                    QueryStringCacheKeys= dict(Quantity=0),
                    ),
                MinTTL=1000)
            )
)

When I try to create the cloudfront distribution, I get the following error:

InvalidOrigin: An error occurred (InvalidOrigin) when calling the CreateDistribution operation: The specified origin server does not exist or is not valid. An error occurred (InvalidOrigin) when calling the CreateDistribution operation: The specified origin server does not exist or is not valid.

Interestingly, it looks to be complaining about the origin, mydomain.com.s3.amazonaws.com, however when I create a distribution for the s3 bucket in the web console, it has no problem with the same origin domain name.

Update: I can get this to work with boto with the following, but would rather use boto3:

import boto
c = boto.connect_cloudfront()
origin = boto.cloudfront.origin.S3Origin('mydomain.com.s3.amazonaws.com')
distro = c.create_distribution(origin=origin, enabled=False, comment='My new Distribution')
1
hmmm... shouldn't the mydomain.com be the bucket name? didn't think dots are allowed in bucket names... ? - gsaslis
Dots and dashes are allowed. I did try a bucket name with no '.' characters though, and I got the same error. Literally using the same Origin Domain Name string in the aws web console works. - Atifm
Does it exist though? I mean.. is the domain you're using actually valid? - gsaslis
Turn on some debugging or whatever is necessary to capture the generated request body XML? The InvalidOrigin error does seem to mean one of the following: no such bucket, bucket name > 63 characters, uppercase character in bucket name, adjacent dots in bucket name, invalid characters in bucket name, or bucket hostname specified without .s3.amazonaws.com added to the end. - Michael - sqlbot
@gsaslis Yes the bucket exists. I can make a valid distribution for it in the web console. Waiting to hear back from Amazon support - Atifm

1 Answers

3
votes

Turns out their is a required parameter that is not documented properly.

Since the Origin is a S3 bucket, you must have S3OriginConfig = dict(OriginAccessIdentity = '') defined even if OriginAccessIdentity not used, and is an empty string.

The following command works. Note, you still need a bucket policy to make the objects accessible, and a route53 entry to alias the cname we want to cloudfront generated hostname.

cf.create_distribution(DistributionConfig=dict(CallerReference='firstOne',
            Aliases = dict(Quantity=1, Items=['mydomain.com']),
            DefaultRootObject='index.html',
            Comment='Test distribution',
            Enabled=True,
            Origins = dict(
                Quantity = 1, 
                Items = [dict(
                    Id = '1',
                    DomainName='mydomain.com.s3.amazonaws.com',
                    S3OriginConfig = dict(OriginAccessIdentity = ''))
                ]),
            DefaultCacheBehavior = dict(
                TargetOriginId = '1',
                ViewerProtocolPolicy= 'redirect-to-https',
                TrustedSigners = dict(Quantity=0, Enabled=False),
                ForwardedValues=dict(
                    Cookies = {'Forward':'all'},
                    Headers = dict(Quantity=0),
                    QueryString=False,
                    QueryStringCacheKeys= dict(Quantity=0),
                    ),
                MinTTL=1000)
            )
)