github.com/pachyderm/pachyderm@v1.13.4/etc/deploy/cloudfront/secure-cloudfront.sh (about)

     1  #!/bin/bash
     2  
     3  CLOUDFRONT_OAI_ID=
     4  set -euxo pipefail
     5  
     6  parse_flags() {
     7    # Check prereqs
     8    command -v aws
     9    command -v jq
    10    command -v uuid
    11    # Common config
    12    export AWS_REGION=us-east-1
    13    export AWS_AVAILABILITY_ZONE=us-east-1a
    14  
    15    # Parse flags
    16    eval "set -- $( getopt -l "state:,region:,zone:,bucket:,cloudfront-distribution-id:,cloudfront-keypair-id:,cloudfront-private-key-file:" "--" "${0}" "${@}" )"
    17    while true; do
    18        case "${1}" in
    19            --region)
    20              export AWS_REGION="${2}"
    21              shift 2
    22              ;;
    23            --zone)
    24              export AWS_AVAILABILITY_ZONE="${2}"
    25              shift 2
    26              ;;
    27            --bucket)
    28              export BUCKET="${2}"
    29              shift 2
    30              ;;
    31            --cloudfront-distribution-id)
    32              export CLOUDFRONT_DISTRIBUTION_ID="${2}"
    33              shift 2
    34              ;;
    35            --cloudfront-keypair-id)
    36              export CLOUDFRONT_KEYPAIR_ID="${2}"
    37              shift 2
    38              ;;
    39            --cloudfront-private-key-file)
    40              export CLOUDFRONT_PRIVATE_KEY_FILE="${2}"
    41              shift 2
    42              ;;
    43            --)
    44              shift
    45              break
    46              ;;
    47        esac
    48    done
    49  
    50  
    51    set +euxo pipefail
    52  
    53    if [ -z "$CLOUDFRONT_KEYPAIR_ID" ]; then
    54  	echo "--cloudfront-keypair-id must be set"
    55  	exit 1	
    56    fi
    57  
    58    if [ -z "$CLOUDFRONT_PRIVATE_KEY_FILE" ]; then
    59  	echo "--cloudfront-private-key-file must be set"
    60  	exit 1	
    61    fi
    62  
    63    if [ -z "$BUCKET" ]; then
    64  	echo "--bucket must be set"
    65  	exit 1	
    66    fi
    67  
    68    if [ -z "$CLOUDFRONT_DISTRIBUTION_ID" ]; then
    69  	echo "--cloudfront-distribution-id must be set"
    70  	exit 1	
    71    fi
    72  
    73    set -euxo pipefail
    74  
    75    echo "Region: ${AWS_REGION}"
    76    zone_suffix=${AWS_AVAILABILITY_ZONE#$AWS_REGION}
    77    if [[ ${#zone_suffix} -gt 3 ]]; then
    78      echo "Availability zone \"${AWS_AVAILABILITY_ZONE}\" may not be in region \"${AWS_REGION}\""
    79      echo "Try setting both --region and --zone"
    80      echo "Exiting to be safe..."
    81      exit 1
    82    fi
    83  }
    84  
    85  
    86  # Update bucket access policy
    87  
    88  update_bucket_policy() {
    89      aws s3api delete-bucket-policy --bucket "$BUCKET" --region "$AWS_REGION"
    90     
    91      # Create Origin Access Identity
    92      someuuid=$(uuid | cut -f 1 -d-)
    93      mkdir -p tmp
    94      jq ".CallerReference = \"$someuuid\" | .Comment = \"$BUCKET auto generated OAI\"" < etc/deploy/cloudfront/origin-access-identity.json.template > tmp/cloudfront-origin-access-identity.json
    95      aws cloudfront create-cloud-front-origin-access-identity --cloud-front-origin-access-identity-config file://tmp/cloudfront-origin-access-identity.json > tmp/cloudfront-origin-access-identity-info.json
    96      CLOUDFRONT_OAI_CANONICAL=$(jq -r ".CloudFrontOriginAccessIdentity.S3CanonicalUserId" < tmp/cloudfront-origin-access-identity-info.json)
    97      echo "Got Cloudfront Origin Access Identity Canonical user id : ${CLOUDFRONT_OAI_CANONICAL}"
    98      CLOUDFRONT_OAI_ID=$(jq -r ".CloudFrontOriginAccessIdentity.Id" < tmp/cloudfront-origin-access-identity-info.json)
    99      echo "Got Cloudfront Origin Access Identity ID : ${CLOUDFRONT_OAI_ID}"
   100    
   101      # Create secure bucket policy w the new OAI
   102      jq ".Statement[0].Resource = \"arn:aws:s3:::$BUCKET/*\" | .Statement[0].Principal.CanonicalUser = \"$CLOUDFRONT_OAI_CANONICAL\"" < etc/deploy/cloudfront/bucket-policy-secure.json.template > tmp/bucket-policy-secure.json
   103      aws s3api put-bucket-policy --bucket "$BUCKET" --policy file://tmp/bucket-policy-secure.json --region="${AWS_REGION}"
   104  
   105  }
   106  
   107  # Update cloudfront distribution
   108  
   109  update_cloudfront_distribution() {
   110  
   111      # Get the ETAG (required to update)
   112      mkdir -p tmp
   113      aws cloudfront get-distribution --id "$CLOUDFRONT_DISTRIBUTION_ID" > tmp/existing-cloudfront-distribution.json
   114      ETAG=$(jq -r .ETag < tmp/existing-cloudfront-distribution.json)
   115      # Update the fields we need
   116      jq ".Distribution.DistributionConfig.Origins.Items[0].S3OriginConfig.OriginAccessIdentity = \"origin-access-identity/cloudfront/${CLOUDFRONT_OAI_ID}\"" < tmp/existing-cloudfront-distribution.json > tmp-result.json
   117      # There doesn't seem to be a way to use jq to replace 'in place':
   118      mv tmp-result.json tmp/updated-cloudfront-distribution.json
   119      jq '.Distribution.DistributionConfig.DefaultCacheBehavior.TrustedSigners = {"Enabled": true,"Items": ["self"],"Quantity":1}' < tmp/updated-cloudfront-distribution.json > tmp-result.json
   120      mv tmp-result.json tmp/updated-cloudfront-distribution.json
   121  
   122      jq .Distribution.DistributionConfig < tmp/updated-cloudfront-distribution.json > tmp/updated-cloudfront-distribution-config.json
   123      aws cloudfront update-distribution --id "$CLOUDFRONT_DISTRIBUTION_ID" --if-match "$ETAG" --distribution-config file://tmp/updated-cloudfront-distribution-config.json > tmp/updated-cloudfront-distribution-info.json
   124      # This isn't used anywhere in this script, but still is good to report to the user
   125      CLOUDFRONT_DOMAIN=$(jq -r ".Distribution.DomainName" < tmp/updated-cloudfront-distribution-info.json | cut -f 1 -d .)
   126      echo "Setup cloudfront distribution with domain ${CLOUDFRONT_DOMAIN}"
   127  }
   128  
   129  deploy_secrets() {
   130      # Update the amazon secret to include: cloudfront-keypair-id and cloudfront-private-key
   131      echo "Updating secrets for cluster:"
   132      kubectl cluster-info
   133      mkdir -p tmp
   134      kubectl get secrets/pachyderm-storage-secret -o json > tmp/existing-amazon-secrets.json
   135      ENCODED_KEYPAIR=$(echo "$CLOUDFRONT_KEYPAIR_ID" | base64 -w0)
   136      jq ".data.cloudfrontKeyPairId = \"$ENCODED_KEYPAIR\"" < tmp/existing-amazon-secrets.json > tmp-result.json
   137      mv tmp-result.json tmp/updated-amazon-secrets.json
   138      CLOUDFRONT_PRIVATE_KEY=$(base64 -w0 < "$CLOUDFRONT_PRIVATE_KEY_FILE")
   139      jq ".data.cloudfrontPrivateKey = \"$CLOUDFRONT_PRIVATE_KEY\"" < tmp/updated-amazon-secrets.json > tmp-result.json
   140      mv tmp-result.json tmp/updated-amazon-secrets.json
   141      kubectl replace -f tmp/updated-amazon-secrets.json
   142  }
   143  
   144  parse_flags "${@}"
   145  update_bucket_policy
   146  update_cloudfront_distribution
   147  deploy_secrets
   148  
   149  
   150  echo "Waiting on distribution to enter 'deployed' state"
   151  echo "This is the last step of the script ... if it times out, thats ok. Just make sure that your CF distribution's status is 'Deployed' on the UI before you run anything on pachyderm"
   152  date
   153  # We need to wait for this, otherwise if you try and access objects while it's 'pending' CF redirects you to S3 and it'll cache the 307 redirect responses
   154  aws cloudfront wait distribution-deployed --id "$CLOUDFRONT_DISTRIBUTION_ID"
   155  echo "Cloudfront distribution ($CLOUDFRONT_DISTRIBUTION_ID) deployed"
   156  date
   157