Skip to content

Commit

Permalink
Add an RBS signature for sigv4 (#3152)
Browse files Browse the repository at this point in the history
  • Loading branch information
kazuyainoue0124 authored Jan 10, 2025
1 parent 9b7d84b commit c038125
Show file tree
Hide file tree
Showing 14 changed files with 170 additions and 13 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ jobs:
bundle config set --local with 'build rbs'
bundle install
- name: Install rbs collection
run: rbs collection install

- name: Build SDK
run: bundle exec rake build

Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

/.byebug_history
/.bundle
/.gem_rbs_collection
/.yardoc
/api-docs
/Gemfile.lock
/coverage
/rbs_collection.lock.yaml
*.gem
benchmark_report.json

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

* Feature - Add RBS signature files to support static type checking

1.10.1 (2024-10-21)
------------------

Expand Down
6 changes: 3 additions & 3 deletions gems/aws-sigv4/lib/aws-sigv4/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ module Sigv4
class Request

# @option options [required, String] :http_method
# @option options [required, HTTP::URI, HTTPS::URI, String] :endpoint
# @option options [required, String, URI::HTTP, URI::HTTPS] :endpoint
# @option options [Hash<String,String>] :headers ({})
# @option options [String, IO] :body ('')
def initialize(options = {})
Expand All @@ -30,12 +30,12 @@ def http_method
@http_method
end

# @param [String, HTTP::URI, HTTPS::URI] endpoint
# @param [String, URI::HTTP, URI::HTTPS] endpoint
def endpoint=(endpoint)
@endpoint = URI.parse(endpoint.to_s)
end

# @return [HTTP::URI, HTTPS::URI]
# @return [URI::HTTP, URI::HTTPS]
def endpoint
@endpoint
end
Expand Down
4 changes: 2 additions & 2 deletions gems/aws-sigv4/lib/aws-sigv4/signer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ def initialize(options = {})
# @option request [required, String] :http_method One of
# 'GET', 'HEAD', 'PUT', 'POST', 'PATCH', or 'DELETE'
#
# @option request [required, String, URI::HTTPS, URI::HTTP] :url
# @option request [required, String, URI::HTTP, URI::HTTPS] :url
# The request URI. Must be a valid HTTP or HTTPS URI.
#
# @option request [optional, Hash] :headers ({}) A hash of headers
Expand Down Expand Up @@ -383,7 +383,7 @@ def sign_event(prior_signature, payload, encoder)
# @option options [required, String] :http_method The HTTP request method,
# e.g. 'GET', 'HEAD', 'PUT', 'POST', 'PATCH', or 'DELETE'.
#
# @option options [required, String, HTTPS::URI, HTTP::URI] :url
# @option options [required, String, URI::HTTP, URI::HTTPS] :url
# The URI to sign.
#
# @option options [Hash] :headers ({}) Headers that should
Expand Down
13 changes: 13 additions & 0 deletions gems/aws-sigv4/sig/errors.rbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module Aws
module Sigv4
module Errors
class MissingCredentialsError < ArgumentError
def initialize: (?String msg) -> void
end

class MissingRegionError < ArgumentError
def initialize: (*untyped) -> void
end
end
end
end
15 changes: 15 additions & 0 deletions gems/aws-sigv4/sig/interfaces.rbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module Aws
module Sigv4
interface _Credentials
def access_key_id: () -> String
def secret_access_key: () -> String
def session_token: () -> String?
def set?: () -> bool
end

interface _CredentialsProvider
def credentials: () -> _Credentials
def set?: () -> bool
end
end
end
4 changes: 4 additions & 0 deletions gems/aws-sigv4/sig/manifest.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
dependencies:
- name: tempfile
- name: stringio
- name: uri
25 changes: 25 additions & 0 deletions gems/aws-sigv4/sig/request.rbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module Aws
module Sigv4
class Request
def initialize: (
http_method: String,
endpoint: String | URI::HTTP | URI::HTTPS,
?headers: Hash[String, String],
?body: String | IO
) -> void
| (?Hash[Symbol, untyped]) -> void

def http_method=: (String http_method) -> void
def http_method: () -> String

def endpoint: () -> (URI::HTTP | URI::HTTPS)
def endpoint=: (String | URI::HTTP | URI::HTTPS endpoint) -> void

def headers=: (Hash[String, String] headers) -> void
def headers: () -> Hash[String, String]

def body=: (String | IO body) -> void
def body: () -> (String | IO)
end
end
end
12 changes: 12 additions & 0 deletions gems/aws-sigv4/sig/signature.rbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module Aws
module Sigv4
class Signature
attr_accessor headers: Hash[String, String]
attr_accessor canonical_request: String
attr_accessor string_to_sign: String
attr_accessor content_sha256: String
attr_accessor signature: String
attr_accessor extra: Hash[untyped, untyped]
end
end
end
51 changes: 51 additions & 0 deletions gems/aws-sigv4/sig/signer.rbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
module Aws
module Sigv4
class Signer
def initialize: (
service: String,
region: String,
?access_key_id: String,
?secret_access_key: String,
?session_token: String,
?credentials: _Credentials,
?credentials_provider: _CredentialsProvider,
?unsigned_headers: Array[String],
?uri_escape_path: bool,
?apply_checksum_header: bool,
?signing_algorithm: :sigv4 | :sigv4a | :'sigv4-s3express',
?omit_session_token: bool,
?normalize_path: bool,
) -> void
| (?Hash[Symbol, untyped]) -> void

attr_reader service: String
attr_reader region: String
attr_reader credentials_provider: _CredentialsProvider
attr_reader unsigned_headers: Array[String]
attr_reader apply_checksum_header: bool

def sign_request: (
http_method: String,
url: String | URI::HTTPS | URI::HTTP,
?headers: Hash[String, String],
?body: String | IO | StringIO | Tempfile,
) -> Signature

def sign_event: (
String,
String,
untyped
) -> [Hash[String, untyped], String]

def presign_url: (
http_method: String,
url: String | URI::HTTP | URI::HTTPS,
?headers: Hash[String, String],
?expires_in: Integer,
?body: String | IO,
?body_digest: String,
?time: Time,
) -> (URI::HTTP | URI::HTTPS)
end
end
end
5 changes: 3 additions & 2 deletions gems/aws-sigv4/spec/signer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ module Sigv4
body: body
)
expect(signature.headers['x-amz-content-sha256']).to eq(Digest::SHA256.hexdigest('abc'))
body.unlink
end

it 'reads non-file IO objects into memory to compute checksusm' do
Expand All @@ -313,7 +314,7 @@ module Sigv4
end

it 'does not read the body if X-Amz-Content-Sha256 if already present' do
body = double('http-payload')
body = StringIO.new('body')
expect(body).to_not receive(:read)
expect(body).to_not receive(:rewind)
signature = Signer.new(options).sign_request(
Expand Down Expand Up @@ -348,7 +349,7 @@ module Sigv4
'Foo' => 'foo',
'Bar' => 'bar bar',
'Bar2' => '"bar bar"',
'Content-Length' => 9,
'Content-Length' => '9',
'X-Amz-Date' => '20120101T112233Z',
},
body: StringIO.new('http-body')
Expand Down
30 changes: 30 additions & 0 deletions rbs_collection.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
sources:
- type: git
name: ruby/gem_rbs_collection
remote: https://github.com/ruby/gem_rbs_collection.git
revision: main
repo_dir: gems

path: .gem_rbs_collection

gems:
- name: stringio
ignore: false
- name: tempfile
ignore: false
- name: uri
ignore: false
- name: addressable
ignore: true
- name: diff-lcs
ignore: true
- name: rake
ignore: true
- name: rbs
ignore: true
- name: rubocop
ignore: true
- name: webmock
ignore: true
- name: yard
ignore: true
11 changes: 5 additions & 6 deletions tasks/rbs.rake
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,17 @@ namespace :rbs do
task :spytest do
failures = []
# Just test s3 for most type coverage
%w[core s3].each do |identifier|
sdk_gem = "aws-sdk-#{identifier}"
puts "Run rspec with RBS::Test on `#{sdk_gem}`"
%w[aws-sigv4 aws-sdk-core aws-sdk-s3].each do |gem_name|
puts "Run rspec with RBS::Test on `#{gem_name}`"
env = {
'RUBYOPT' => '-r bundler/setup -r rbs/test/setup',
'RBS_TEST_RAISE' => 'true',
'RBS_TEST_LOGLEVEL' => 'error',
'RBS_TEST_OPT' => "-I gems/aws-sdk-core/sig -I gems/#{sdk_gem}/sig",
'RBS_TEST_OPT' => "-I gems/aws-sdk-core/sig -I gems/#{gem_name}/sig",
'RBS_TEST_TARGET' => "\"Aws,Aws::*,Seahorse,Seahorse::*\"",
}
sh(env, "bundle exec rspec gems/#{sdk_gem}/spec --tag '~rbs_test:skip'") do |ok, _|
failures << File.basename(File.dirname("gems/#{sdk_gem}/sig")) unless ok
sh(env, "bundle exec rspec gems/#{gem_name}/spec --tag '~rbs_test:skip'") do |ok, _|
failures << File.basename(File.dirname("gems/#{gem_name}/sig")) unless ok
end
end
abort('one or more rspec with RBS::Test failed: %s' % [failures.join(', ')]) unless failures.empty?
Expand Down

0 comments on commit c038125

Please sign in to comment.