-
Notifications
You must be signed in to change notification settings - Fork 3
Add basic Credentials wrapper + ManagedNative mixin #20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 7 commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
b306424
Add basic Credentials wrapper + Sigv base interface
alextwoods 33158d0
Rubocop cleanups
alextwoods 5356c0f
Clang format
alextwoods 1f64ed8
Fix cleanup issues (use correct function...)
alextwoods a7a1acf
Fix Jruby issue with UINT64 out of range for Time
alextwoods 63577a5
WIP signing config
alextwoods ac50ada
Ensure strings are copied and cleaned up
alextwoods 110459c
Clang cleanup
alextwoods 3e8c886
WIP - Signable impl
alextwoods 0cbdd18
Clean up PR - only include credentials binding
alextwoods 86ce4e7
Add a ManagedNative mixin module to add some generic functionality.
alextwoods 477f093
Merge branch 'master' into signer
alextwoods a16f86c
Use a ByteCursor struct for return types instead of :string
alextwoods 4a23229
Fix jruby failures from missing FFI methods...
alextwoods 6ff266f
Extend attach_function to add error wrapping + custom naming
alextwoods 13fb4f7
Remove credential SDK interface methods
alextwoods 5db602e
Cleanups from PR - remove signer interface
alextwoods 73ec9f3
Rubocop cleanup
alextwoods File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
# frozen_string_literal: true | ||
|
||
module Aws | ||
module Crt | ||
module Auth | ||
# Utility class for Credentials. | ||
# @api private | ||
class Credentials | ||
UINT64_MAX = 18_446_744_073_709_551_615 | ||
|
||
# @param [String] access_key_id | ||
# @param [String] secret_access_key | ||
# @param [String] session_token (nil) | ||
# @param [Time|int] expiration (nil) | ||
graebm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
def initialize(access_key_id, secret_access_key, | ||
session_token = nil, expiration = nil) | ||
if !access_key_id || access_key_id.empty? | ||
raise ArgumentError, 'access_key_id must be set' | ||
end | ||
|
||
if !secret_access_key || secret_access_key.empty? | ||
raise ArgumentError, 'secret_access_key must be set' | ||
end | ||
|
||
native = Aws::Crt.call do | ||
Aws::Crt::Native.credentials_new( | ||
access_key_id, | ||
secret_access_key, | ||
session_token, | ||
expiration&.to_i || UINT64_MAX | ||
) | ||
end | ||
|
||
@native = FFI::AutoPointer.new(native, self.class.method(:on_release)) | ||
end | ||
|
||
# @return [FFI:Pointer] | ||
attr_reader :native | ||
|
||
# @return [String, nil] | ||
def access_key_id | ||
Aws::Crt::Native.credentials_get_access_key_id(@native) if @native | ||
graebm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
end | ||
|
||
# @return [String, nil] | ||
def secret_access_key | ||
Aws::Crt::Native.credentials_get_secret_access_key(@native) if @native | ||
end | ||
|
||
# @return [String, nil] | ||
def session_token | ||
Aws::Crt::Native.credentials_get_session_token(@native) if @native | ||
end | ||
|
||
# @return [Time,nil] | ||
def expiration | ||
return unless @native | ||
|
||
exp = Aws::Crt::Native.credentials_get_expiration(@native) | ||
return if exp == UINT64_MAX | ||
|
||
Time.at(exp) | ||
end | ||
|
||
# @return [Credentials] | ||
def credentials | ||
self | ||
graebm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
end | ||
|
||
# @return [Boolean] Returns `true` if the access key id and secret | ||
# access key are both set. | ||
def set? | ||
!@native.nil? && | ||
alextwoods marked this conversation as resolved.
Show resolved
Hide resolved
|
||
!access_key_id.nil? && | ||
!access_key_id.empty? && | ||
!secret_access_key.nil? && | ||
!secret_access_key.empty? | ||
end | ||
|
||
# Removing the secret access key from the default inspect string. | ||
# @api private | ||
def inspect | ||
"#<#{self.class.name} access_key_id=#{access_key_id.inspect}>" | ||
graebm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
end | ||
|
||
# Immediately release this instance's attachment to the underlying | ||
# resources, without waiting for the garbage collector. | ||
# Note that underlying resources will remain alive until nothing | ||
# else is using them. | ||
def release | ||
return unless @native | ||
|
||
@native.free | ||
@native = nil | ||
end | ||
|
||
def self.on_release(native) | ||
Aws::Crt::Native.credentials_release(native) | ||
end | ||
end | ||
end | ||
end | ||
end |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# frozen_string_literal: true | ||
|
||
module Aws | ||
module Crt | ||
module Auth | ||
# Utility class for creating AWS signature version 4 signature. | ||
class Signer | ||
alextwoods marked this conversation as resolved.
Show resolved
Hide resolved
|
||
def initialize(options = {}) | ||
@service = extract_service(options) | ||
@region = extract_region(options) | ||
@credentials_provider = extract_credentials_provider(options) | ||
@unsigned_headers = Set.new((options.fetch(:unsigned_headers, [])) | ||
.map(&:downcase)) | ||
@unsigned_headers << 'authorization' | ||
@unsigned_headers << 'x-amzn-trace-id' | ||
@unsigned_headers << 'expect' | ||
alextwoods marked this conversation as resolved.
Show resolved
Hide resolved
|
||
%i[uri_escape_path apply_checksum_header].each do |opt| | ||
instance_variable_set("@#{opt}", | ||
options.key?(opt) ? options[:opt] : true) | ||
end | ||
end | ||
|
||
def sign_request(request) | ||
# TODO | ||
end | ||
|
||
def sign_event(prior_signature, payload, encoder) | ||
# TODO | ||
end | ||
|
||
def presign_url(options) | ||
# TODO | ||
end | ||
end | ||
end | ||
end | ||
end |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
# frozen_string_literal: true | ||
|
||
module Aws | ||
module Crt | ||
module Auth | ||
# Signing Config | ||
# @api private | ||
class SigningConfig | ||
# @param [Hash] options | ||
# @option options [required, Aws::Crt::Native::signing_algorithm] | ||
# :algorithm | ||
# @option options [required, Aws::Crt::Native::signature_type] | ||
# :signature_type | ||
# @option options [required, Credentials] :credentials | ||
# @option options [required, String] :region | ||
# @option options [required, String] :service | ||
# @option options [Time] :date (Time.now) | ||
# @option options [Array<String>|Proc(String->Boolean)] | ||
# :unsigned_headers ([]) | ||
# @option options [Boolean] :uri_escape_path (true) | ||
# @option options [Boolean] :apply_checksum_header (true) | ||
def initialize(options = {}) | ||
# validation of parameters is handled in signing_config_new | ||
|
||
# create a callback function for aws_should_sign_header_fn | ||
sign_header_fn = extract_unsigned_header_fn( | ||
options[:unsigned_headers] | ||
) | ||
puts "TODO: imp #{sign_header_fn}" if sign_header_fn | ||
|
||
# ensure we retain a reference to the credentials to avoid GC | ||
@credentials = options[:credentials] | ||
native = Aws::Crt.call do | ||
Aws::Crt::Native.signing_config_new( | ||
options[:algorithm], | ||
options[:signature_type], | ||
options[:region], | ||
options[:service], | ||
extract_date(options), | ||
@credentials&.native | ||
) | ||
end | ||
|
||
@native = FFI::AutoPointer.new(native, self.class.method(:on_release)) | ||
end | ||
|
||
# Immediately release this instance's attachment to the underlying | ||
# resources, without waiting for the garbage collector. | ||
# Note that underlying resources will remain alive until nothing | ||
# else is using them. | ||
def release | ||
return unless @native | ||
|
||
@native.free | ||
@native = nil | ||
end | ||
|
||
def self.on_release(native) | ||
Aws::Crt::Native.signing_config_release(native) | ||
end | ||
|
||
private | ||
|
||
def extract_date(options) | ||
(options[:date] || Time.now).to_i | ||
end | ||
|
||
def extract_unsigned_header_fn(unsigned_headers) | ||
if unsigned_headers && !unsigned_headers.respond_to?(:call) | ||
unsigned_headers = Set.new(unsigned_headers) | ||
sign_header_fn = proc { |param| unsigned_headers.include? param } | ||
end | ||
sign_header_fn | ||
end | ||
end | ||
end | ||
end | ||
end |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
# frozen_string_literal: true | ||
|
||
require_relative 'spec_helper' | ||
require 'weakref' | ||
|
||
module Aws | ||
module Crt | ||
module Auth #:nodoc: | ||
UINT64_MAX = 18_446_744_073_709_551_615 | ||
|
||
describe Credentials do | ||
describe '#initilize' do | ||
it 'raises an ArgumentError when missing access_key_id' do | ||
expect { Credentials.new(nil, 'secret') } | ||
.to raise_error(ArgumentError) | ||
end | ||
|
||
it 'raises an ArgumentError when missing secret_access_key' do | ||
expect { Credentials.new('akid', nil) } | ||
.to raise_error(ArgumentError) | ||
end | ||
|
||
it 'defaults the session token to nil' do | ||
expect(Credentials.new('akid', 'secret').session_token).to be nil | ||
end | ||
|
||
it 'defaults the expiration to nil' do | ||
expect(Credentials.new('akid', 'secret').expiration) | ||
.to be_nil | ||
end | ||
|
||
it 'accepts a Time for expiration' do | ||
exp = Time.now | ||
creds = Credentials.new('akid', 'secret', 'token', exp) | ||
expect(creds.expiration.to_i).to eq exp.to_i | ||
end | ||
|
||
it 'accepts an epoch (integer) for expiration' do | ||
exp = Time.now | ||
creds = Credentials.new('akid', 'secret', 'token', exp.to_i) | ||
expect(creds.expiration.to_i).to eq exp.to_i | ||
end | ||
end | ||
|
||
describe 'accessors' do | ||
let(:exp) { Time.now } | ||
let(:creds) { Credentials.new('akid', 'secret', 'token', exp) } | ||
|
||
it 'provides access to the access key id' do | ||
expect(creds.access_key_id).to eq('akid') | ||
end | ||
|
||
it 'provides access to the secret access key' do | ||
expect(creds.secret_access_key).to eq('secret') | ||
end | ||
|
||
it 'provides access to the session token' do | ||
expect(creds.session_token).to eq('token') | ||
end | ||
|
||
it 'provides access to the expiration' do | ||
expect(creds.expiration.to_i).to eq exp.to_i | ||
end | ||
end | ||
|
||
describe '#set?' do | ||
it 'returns true when the key and secret are both non nil values' do | ||
expect(Credentials.new('akid', 'secret').set?).to be(true) | ||
end | ||
|
||
it 'returns false after the credentials have been released' do | ||
creds = Credentials.new('akid', 'secret') | ||
creds.release | ||
expect(creds.set?).to be(false) | ||
end | ||
end | ||
|
||
describe '#inspect' do | ||
let(:creds) { Credentials.new('akid', 'secret', 'token') } | ||
|
||
it 'does not include the secret_access_key' do | ||
expect(creds.inspect).not_to include 'secret' | ||
end | ||
end | ||
|
||
describe '.on_release' do | ||
it 'cleans up with release' do | ||
creds = Credentials.new('akid', 'secret') | ||
expect(creds).to_not be_nil | ||
|
||
creds.release | ||
check_for_clean_shutdown | ||
end | ||
|
||
if garbage_collect_is_immediate? | ||
it 'cleans up with GC' do | ||
creds = Credentials.new('akid', 'secret', 'session') | ||
weakref = WeakRef.new(creds) | ||
expect(weakref.weakref_alive?).to be true | ||
|
||
# force cleanup via GC | ||
creds = nil # rubocop:disable Lint/UselessAssignment | ||
ObjectSpace.garbage_collect | ||
expect(weakref.weakref_alive?).to be_falsey | ||
check_for_clean_shutdown | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# frozen_string_literal: true | ||
|
||
require_relative 'spec_helper' | ||
|
||
require 'tempfile' | ||
require 'base64' | ||
|
||
describe Aws::Crt::Auth::Signer do | ||
end |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.