Created
May 14, 2025 13:02
-
-
Save tpaulshippy/1dd00f761a2f690ecd8ccacc9611b637 to your computer and use it in GitHub Desktop.
AWS credential provider example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # frozen_string_literal: true | |
| require 'aws-sdk-core' | |
| require_relative 'errors' | |
| module MyApp | |
| # Manages AWS credentials with automatic refresh capability | |
| class AwsCredentialProvider | |
| class << self | |
| def instance | |
| @instance ||= new | |
| end | |
| end | |
| def initialize | |
| refresh_credentials! | |
| end | |
| def access_key_id | |
| refresh_if_expired! | |
| @credentials&.access_key_id | |
| end | |
| def secret_access_key | |
| refresh_if_expired! | |
| @credentials&.secret_access_key | |
| end | |
| def session_token | |
| refresh_if_expired! | |
| @credentials&.session_token | |
| end | |
| attr_reader :expiration | |
| def refresh_credentials! | |
| fetch_and_set_credentials | |
| end | |
| def refresh_if_expired! | |
| return unless expired? | |
| refresh_credentials! | |
| end | |
| private | |
| def fetch_and_set_credentials | |
| if use_mock_credentials? | |
| set_mock_credentials | |
| else | |
| fetch_and_set_real_credentials | |
| end | |
| end | |
| def use_mock_credentials? | |
| ENV['RAILS_ENV'] == 'test' | |
| end | |
| def set_mock_credentials | |
| @credentials = Aws::Credentials.new( | |
| 'mock_access_key_id', | |
| 'mock_secret_access_key', | |
| 'mock_session_token' | |
| ) | |
| @expiration = Time.now + 3600 # 1 hour | |
| end | |
| def fetch_and_set_real_credentials | |
| ecs_credentials = Aws::CredentialProviderChain.new.resolve | |
| raise ConfigurationError, 'Could not resolve AWS credentials' if ecs_credentials.nil? | |
| refresh_if_supported(ecs_credentials) | |
| assign_credentials(ecs_credentials) | |
| end | |
| def refresh_if_supported(credentials) | |
| credentials.refresh! if credentials.respond_to?(:refresh!) | |
| end | |
| def assign_credentials(ecs_credentials) | |
| if ecs_credentials.respond_to?(:credentials) | |
| @credentials = ecs_credentials.credentials | |
| @expiration = ecs_credentials.expiration if ecs_credentials.respond_to?(:expiration) | |
| else | |
| @credentials = ecs_credentials | |
| @expiration = nil | |
| end | |
| end | |
| def expired? | |
| return false if @expiration.nil? | |
| return true if @credentials.nil? | |
| # Refresh if we're within 5 minutes of expiration | |
| @expiration < Time.now + 300 | |
| end | |
| end | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment