class AwsRotate::Key
Constants
- MAX_KEYS
Check if there are 2 keys, cannot rotate if there are 2 keys already. Raise error if there are 2 keys. Returns false if not at max limit
Public Instance Methods
aws_environment_variables_warning()
click to toggle source
# File lib/aws_rotate/key.rb, line 145 def aws_environment_variables_warning return unless ENV['AWS_ACCESS_KEY_ID'] || ENV['AWS_SECRET_ACCESS_KEY'] puts <<~EOL WARN: The AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables are also set in your shell. You must update those yourself. This tool only updates thethe keys in ~/.aws. EOL end
cache_access_key()
click to toggle source
# File lib/aws_rotate/key.rb, line 96 def cache_access_key old_key_id = aws_configure_get(:aws_access_key_id) return unless old_key_id @@cache[old_key_id] end
check_max_keys_limit()
click to toggle source
Check if there are 2 keys, cannot rotate if there are 2 keys already. Display info message for user to reduce it to 1 key. Returns false if not at max limit Returns true if at max limit
# File lib/aws_rotate/key.rb, line 85 def check_max_keys_limit check_max_keys_limit! rescue MaxKeysError puts <<~EOL.color(:red) This user #{@user} in the AWS_PROFILE=#{@profile} has 2 access keys. This is the max number of keys allowed. Please remove at least one of the keys so aws-rotate can rotate the key. EOL true # at max limit end
check_max_keys_limit!()
click to toggle source
# File lib/aws_rotate/key.rb, line 75 def check_max_keys_limit! resp = iam.list_access_keys(user_name: @user) return false if resp.access_key_metadata.size < MAX_KEYS # not at max limit raise MaxKeysError end
create_access_key()
click to toggle source
Returns:
#<struct Aws::IAM::Types::AccessKey user_name="tung", access_key_id="AKIAXZ6ODJLQUU6O3FD2", status="Active", secret_access_key="8eEnLLdR7gQE9fkFiDVuemi3qPf3mBMXxEXAMPLE", create_date=2019-08-13 21:14:35 UTC>>
# File lib/aws_rotate/key.rb, line 111 def create_access_key resp = iam.create_access_key key = resp.access_key # store in cache to help with multiple profiles using the same aws access key old_key_id = aws_configure_get(:aws_access_key_id) @@cache[old_key_id] = OldKey.new(old_key_id, key.access_key_id, key.secret_access_key) puts "Created new access key: #{key.access_key_id}" key end
delete_old_access_key()
click to toggle source
# File lib/aws_rotate/key.rb, line 129 def delete_old_access_key resp = iam.list_access_keys access_keys = resp.access_key_metadata # Important: only delete if there are keys 2. The reason this is possible is because multiple profiles can use # the same aws_access_key_id. In this case, an additional key is not created but we use the key from the @@cache return if access_keys.size <= 1 old_key = access_keys.sort_by(&:create_date).first iam.delete_access_key(access_key_id: old_key.access_key_id) puts "Old access key deleted: #{old_key.access_key_id}" end
get_iam_user()
click to toggle source
# File lib/aws_rotate/key.rb, line 31 def get_iam_user get_iam_user! rescue GetIamUserError message = @options[:noop] ? "Will not be able to update key" : "Unable to update key" puts "WARN: #{message} for AWS_PROFILE=#{@profile}".color(:yellow) return false end
get_iam_user!()
click to toggle source
Returns IAM username. Returns nil unless this profile is actually associated with an user. Skips assume role profiles.
# File lib/aws_rotate/key.rb, line 42 def get_iam_user! resp = sts.get_caller_identity arn = resp.arn # Example arns: # # arn:aws:iam::112233445566:user/tung - iam user # arn arn:aws:sts::112233445566:assumed-role/Admin/default_session - assume role # if arn.include?(':user/') arn.split('/').last end rescue Aws::Errors::MissingRegionError => e puts "The AWS_PROFILE=#{@profile} may not exist. Please double check it.".color(:red) puts "#{e.class} #{e.message}" raise GetIamUserError rescue Aws::STS::Errors::InvalidClientTokenId => e puts "The AWS_PROFILE=#{@profile} profile does not have access to IAM. Please double check it.".color(:red) puts "#{e.class} #{e.message}" raise GetIamUserError rescue Aws::STS::Errors::SignatureDoesNotMatch => e puts "The AWS_PROFILE=#{@profile} profile seems to have invalid secret keys. Please double check it.".color(:red) puts "#{e.class} #{e.message}" raise GetIamUserError rescue Aws::Errors::NoSourceProfileError => e puts "WARN: The AWS_PROFILE=#{@profile} profile does not have have access keys.".color(:yellow) puts "#{e.class} #{e.message}" raise GetIamUserError end
patience_message()
click to toggle source
# File lib/aws_rotate/key.rb, line 141 def patience_message puts "Please note, it sometimes take a few seconds or even minutes before the new IAM access key is usable." end
run()
click to toggle source
# File lib/aws_rotate/key.rb, line 6 def run # Note: It is nice to always call get_iam_user first as it'll check access. We rescue exceptions # and report errors early on. The noop check happens after this initial check. # Also with this we can filter for only the keys thats that have associated users and will be updated. # Only the profiles with IAM users will be shown as "Updating..." puts "AWS_PROFILE=#{ENV['AWS_PROFILE']}" @user = get_iam_user # will only rotate keys that belong to an actual IAM user return unless @user at_max = check_max_keys_limit return false if at_max message = "Updating access key for AWS_PROFILE=#{@profile}" message = "NOOP: #{message}" if @options[:noop] puts message.color(:green) return false if @options[:noop] key = cache_access_key || create_access_key update_aws_credentials_file(key.access_key_id, key.secret_access_key) delete_old_access_key patience_message aws_environment_variables_warning true end
update_aws_credentials_file(aws_access_key_id, aws_secret_access_key)
click to toggle source
# File lib/aws_rotate/key.rb, line 123 def update_aws_credentials_file(aws_access_key_id, aws_secret_access_key) aws_configure_set(aws_access_key_id: aws_access_key_id) aws_configure_set(aws_secret_access_key: aws_secret_access_key) puts "Updated profile #{@profile} in #{@credentials_path} with new key: #{aws_access_key_id}" end
Private Instance Methods
aws_configure_get(k)
click to toggle source
# File lib/aws_rotate/key.rb, line 162 def aws_configure_get(k) out = `aws configure get #{k} --profile #{@profile}` # use backtick to grab output out.strip! out == '' ? nil : out end
aws_configure_set(options={})
click to toggle source
Use the aws cli to spare coding work from parsing it.
# File lib/aws_rotate/key.rb, line 157 def aws_configure_set(options={}) k, v = options.keys.first, options.values.first sh "aws configure set #{k} #{v} --profile #{@profile}" end