Skip to content

Instantly share code, notes, and snippets.

@kainam00
Last active August 29, 2015 14:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kainam00/351ed61fad0a891810c0 to your computer and use it in GitHub Desktop.
Save kainam00/351ed61fad0a891810c0 to your computer and use it in GitHub Desktop.
Remove Everyone / public permissions from S3 bucket objects
#!/usr/bin/env ruby
require 'aws-sdk'
require 'yaml'
# Check args
if ARGV[0].nil? || ARGV[1].nil?
puts "Usage: securey-s3-bucket.rb bucket_name path-to-config-file.yml dryrun(optional)"
puts " Where the config file is a YAML formatted file with the following data:"
puts " access_key_id: xxx"
puts " secret_access_key: yyy"
puts " region: us-east-1"
exit 1
end
if ARGV[2]
dryrun = true
end
#### Utility functions ####
def secure_object(client, bucket, key, dryrun)
resp = client.get_object_acl({
bucket: bucket,
key: key,
})
changed = false
newgrants = Array.new()
# Go through all the grants, creating a new grants array without the "Everyone" grant
resp.grants.each do | grant |
# Check to see if there is an "Everyone" grant in the grants array
if grant.grantee.uri == "http://acs.amazonaws.com/groups/global/AllUsers"
puts "#{key} has 'Everyone' permissions. Fixing."
# Mark as insecure so we can fix below
changed = true
else
# If not, copy the grant to the new grants array to be applied to the object if needed
# Set the "type" field to CanonicalUserId or Group manually, since it comes from amazon as "nil" for some reason
# Damn you Amazon!
if grant.grantee.uri.nil?
grant.grantee.type = "CanonicalUser"
else
grant.grantee.type = "Group"
end
# Copy
newgrants << grant
end
end
# Apply changes if needed
if changed == true && dryrun != true
puts "Applying new grants to #{key}"
resp2 = client.put_object_acl ({
access_control_policy: {
grants: newgrants,
owner: {
display_name: resp.owner.display_name,
id: resp.owner.id
},
},
bucket: bucket,
key: key
})
@numfixed = @numfixed+1
return true
elsif changed == true && dryrun == true
puts "*dryrun* is set, not applying new grants to #{key}!"
return true
else
return true
end
end
# Load config file
config = YAML.load(File.read(ARGV[1]))
# Create AWS client. Slightly different depending on whether we're using roles or not
if config["access_key_id"].nil?
# Don't pass credentials, we're using roles given to this box
client = Aws::S3::Client.new(
region: config["region"],
)
else
client = Aws::S3::Client.new(
# Pass credentials
region: config["region"],
credentials: Aws::Credentials.new(config["access_key_id"], config["secret_access_key"]),
)
end
# Loop through all of the objects in the bucket
done = false
marker = ""
numobjects = 0
@numfixed = 0
while done == false
resp = client.list_objects( {
bucket: ARGV[0],
max_keys: 1000,
marker: marker
})
if resp.is_truncated == false
done = true
else
marker = resp.contents[resp.contents.count - 1].key
end
resp.contents.each do | object |
numobjects = numobjects+1
secure_object(client, ARGV[0], object.key, dryrun)
end
puts "Working... Checked #{numobjects} objects. Fixed #{@numfixed}"
end
puts "Done. Checked #{numobjects} objects. Fixed #{@numfixed}"
@kainam00
Copy link
Author

kainam00 commented Aug 6, 2015

Simple script that loops through an S3 bucket looking for any objects that have Everyone permissions, and removes them (the permissions, not the objects), while keeping all other permissions intact.

Some relevant documentation here: http://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html

Usage is simple enough:
securey-s3-bucket.rb bucket_name path-to-config-file.yml dryrun(optional)
Where the config file is a YAML formatted file with the following data:
access_key_id: xxx
secret_access_key: yyy
region: us-east-1

The script will output anything it's fixing, otherwise it will stay pretty quiet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment