Skip to content

Instantly share code, notes, and snippets.

@tc
Created October 7, 2011 18:52
Show Gist options
  • Save tc/1271074 to your computer and use it in GitHub Desktop.
Save tc/1271074 to your computer and use it in GitHub Desktop.
Cloudfront invalidate script
require 'openssl'
require 'uri'
require 'net/http'
require 'net/https'
require 'base64'
require 'optparse'
class CloudfrontDistribution
def initialize(aws_account, aws_secret, distribution, verbose=false)
@aws_account = aws_account
@aws_secret = aws_secret
@distribution = distribution
@verbose = verbose
end
def invalidate_objects(paths)
date = Time.now.strftime("%a, %d %b %Y %H:%M:%S %Z")
digest = Base64.encode64(OpenSSL::HMAC.digest(OpenSSL::Digest::Digest.new('sha1'), @aws_secret, date)).strip
uri = URI.parse("https://cloudfront.amazonaws.com/2010-08-01/distribution/#{@distribution}/invalidation")
req = Net::HTTP::Post.new(uri.path)
req.initialize_http_header({
'x-amz-date' => date,
'Content-Type' => 'text/xml',
'Authorization' => "AWS %s:%s" % [@aws_account, digest]
})
xml_paths = paths.map{|p| "<Path>#{p}</Path>"}.join("")
req.body = %|<InvalidationBatch>#{xml_paths}<CallerReference>#{date.to_s.gsub(/\s+/, '_')}</CallerReference></InvalidationBatch>|
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
res = http.request(req)
if @verbose
puts req.body
puts "------"
puts res.body
end
# it was successful if response code was a 201
return res.code == '201'
end
end
class CloudfrontConfig
# Access Credentials
def self.aws_account; ""; end
def self.aws_secret; ""; end
# Distributions
@@distributions = { "BUCKETNAME" => "DIST_ID" }
def self.get_dist_id(bucket); @@distributions[bucket]; end
end
if __FILE__ == $0
options = {}
OptionParser.new do |opts|
opts.banner = "Usage: #{$0} [options]"
opts.on("-v", "--verbose", "Run verbosely") { |o| options[:verbose] = o }
opts.on("-b", "--bucket BUCKET_NAME", String, "s3 bucket") { |o| options[:bucket] = o }
opts.on("-f", "--files a,b,c", Array, "list of s3 files, should start with /") { |o| options[:files] = o }
end.parse!(ARGV)
dist_id = CloudfrontConfig.get_dist_id(options[:bucket])
raise "Could not find dist_id for #{options[:bucket]}" unless dist_id
files = options[:files]
raise "Empty file list" if files.nil? || files.empty?
distribution = CloudfrontDistribution.new(CloudfrontConfig.aws_account,
CloudfrontConfig.aws_secret,
dist_id,
options[:verbose])
distribution.invalidate_objects(files)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment