Skip to content

Commit

Permalink
S3 Access Grants (#2975)
Browse files Browse the repository at this point in the history
  • Loading branch information
mullermp committed Apr 29, 2024
1 parent fd7984d commit 9d55e1f
Show file tree
Hide file tree
Showing 30 changed files with 1,245 additions and 71 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ module {{module_name}}
expiration: Time.now + 60 * 5
})
expect_auth({"name"=>"sigv4", "signingName"=>"s3express"})
EXPRESS_CREDENTIALS_CACHE.clear
Aws::S3.express_credentials_cache.clear
{{/s3_express_auth?}}
expect_auth({{{expected_auth}}})
{{/expect_auth?}}
Expand Down
2 changes: 1 addition & 1 deletion build_tools/services.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class ServiceEnumerator
MINIMUM_CORE_VERSION = "3.193.0"

# Minimum `aws-sdk-core` version for new S3 gem builds
MINIMUM_CORE_VERSION_S3 = "3.193.0"
MINIMUM_CORE_VERSION_S3 = "3.194.0"

EVENTSTREAM_PLUGIN = "Aws::Plugins::EventStreamConfiguration"

Expand Down
2 changes: 2 additions & 0 deletions gems/aws-sdk-core/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
Unreleased Changes
------------------

* Feature - Add an API private cache for S3 Express and Access Grants.

3.193.0 (2024-04-25)
------------------

Expand Down
1 change: 1 addition & 0 deletions gems/aws-sdk-core/lib/aws-sdk-core.rb
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
require_relative 'aws-sdk-core/arn'
require_relative 'aws-sdk-core/arn_parser'
require_relative 'aws-sdk-core/ec2_metadata'
require_relative 'aws-sdk-core/lru_cache'

# dynamic endpoints
require_relative 'aws-sdk-core/endpoints'
Expand Down
75 changes: 75 additions & 0 deletions gems/aws-sdk-core/lib/aws-sdk-core/lru_cache.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# frozen_string_literal: true

module Aws
# @api private
# A simple thread safe LRU cache
class LRUCache
# @param [Hash] options
# @option options [Integer] :max_entries (100) Maximum number of entries
# @option options [Integer] :expiration (nil) Expiration time in seconds
def initialize(options = {})
@max_entries = options[:max_entries] || 100
@expiration = options[:expiration]
@entries = {}
@mutex = Mutex.new
end

# @param [String] key
# @return [Object]
def [](key)
@mutex.synchronize do
value = @entries[key]
if value
@entries.delete(key)
@entries[key] = value unless value.expired?
end
@entries[key]&.value
end
end

# @param [String] key
# @param [Object] value
def []=(key, value)
@mutex.synchronize do
@entries.shift unless @entries.size < @max_entries
# delete old value if exists
@entries.delete(key)
@entries[key] = Entry.new(value: value, expiration: @expiration)
@entries[key].value
end
end

# @param [String] key
# @return [Boolean]
def key?(key)
@mutex.synchronize do
@entries.delete(key) if @entries.key?(key) && @entries[key].expired?
@entries.key?(key)
end
end

def clear
@mutex.synchronize do
@entries.clear
end
end

# @api private
class Entry
def initialize(options = {})
@value = options[:value]
@expiration = options[:expiration]
@created_time = Time.now
end

# @return [Object]
attr_reader :value

def expired?
return false unless @expiration

Time.now - @created_time > @expiration
end
end
end
end
3 changes: 2 additions & 1 deletion gems/aws-sdk-s3/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
Unreleased Changes
------------------

* Feature - Support S3 Access Grants authentication. Access Grants can be enabled with the `access_grants` option, and custom options can be passed into the `access_grants_credentials_provider` option. This feature requires `aws-sdk-s3control` to be installed.

1.148.0 (2024-04-25)
------------------

Expand Down Expand Up @@ -38,7 +40,6 @@ Unreleased Changes

* Issue - Include original part errors in message when aborting multipart upload fails (#2990).


1.143.0 (2024-01-26)
------------------

Expand Down
2 changes: 1 addition & 1 deletion gems/aws-sdk-s3/aws-sdk-s3.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Gem::Specification.new do |spec|

spec.add_dependency('aws-sdk-kms', '~> 1')
spec.add_dependency('aws-sigv4', '~> 1.8')
spec.add_dependency('aws-sdk-core', '~> 3', '>= 3.193.0')
spec.add_dependency('aws-sdk-core', '~> 3', '>= 3.194.0')

spec.required_ruby_version = '>= 2.5'
end
57 changes: 57 additions & 0 deletions gems/aws-sdk-s3/lib/aws-sdk-s3/access_grants_credentials.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# frozen_string_literal: true

require 'set'

module Aws
module S3
# @api private
class AccessGrantsCredentials
include CredentialProvider
include RefreshingCredentials

def initialize(options = {})
@client = options[:client]
@get_data_access_params = {}
options.each_pair do |key, value|
if self.class.get_data_access_options.include?(key)
@get_data_access_params[key] = value
end
end
@async_refresh = true
super
end

# @return [S3Control::Client]
attr_reader :client

# @return [String]
attr_reader :matched_grant_target

private

def refresh
c = @client.get_data_access(@get_data_access_params)
credentials = c.credentials
@matched_grant_target = c.matched_grant_target
@credentials = Credentials.new(
credentials.access_key_id,
credentials.secret_access_key,
credentials.session_token
)
@expiration = credentials.expiration
end

class << self

# @api private
def get_data_access_options
@gdao ||= begin
input = Aws::S3Control::Client.api.operation(:get_data_access).input
Set.new(input.shape.member_names)
end
end

end
end
end
end

0 comments on commit 9d55e1f

Please sign in to comment.