Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class HttpApiKeyProvider

# @param [String] key
def initialize(key)
@identity = Identities::HttpApiKey.new(key: key)
@identity = Identities::ApiKey.new(key: key)
end
end
end
Expand Down
4 changes: 2 additions & 2 deletions gems/smithy-client/lib/smithy-client/http_bearer_provider.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

module Smithy
module Client
# Returns an HTTP Bearer identity
# Returns a Token identity
class HttpBearerProvider
include IdentityProvider

# @param [String] token
def initialize(token)
@identity = Identities::HttpBearer.new(token: token)
@identity = Identities::Token.new(token: token)
end
end
end
Expand Down
24 changes: 24 additions & 0 deletions gems/smithy-client/lib/smithy-client/identities/api_key.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# frozen_string_literal: true

module Smithy
module Client
module Identities
# Identity class for API Key authentication.
class ApiKey < Identity
def initialize(key:, **)
@key = key
super(**)
end

# @return [String, nil]
attr_reader :key

# Removing the key from the default inspect string.
# @api private
def inspect
super.gsub(/@key="(\\"|[^"])*"/, '@key=[FILTERED]')
end
end
end
end
end
18 changes: 0 additions & 18 deletions gems/smithy-client/lib/smithy-client/identities/http_api_key.rb

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,21 @@
module Smithy
module Client
module Identities
# Identity class for HTTP Bearer token authentication.
class HttpBearer < Identity
# Identity class for token authentication.
class Token < Identity
def initialize(token:, **)
@token = token
super(**)
end

# @return [String, nil]
attr_reader :token

# Removing the token from the default inspect string.
# @api private
def inspect
super.gsub(/@token="(\\"|[^"])*"/, '@token=[FILTERED]')
end
end
end
end
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

require_relative '../http_api_key_provider'
require_relative '../identities/http_api_key'
require_relative '../identities/api_key'

module Smithy
module Client
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

require_relative '../http_bearer_provider'
require_relative '../identities/http_bearer'
require_relative '../identities/token'

module Smithy
module Client
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module Smithy
module Client
module Identities
class HttpBearer < Identity
class Token < Identity
def initialize: (token: String, **untyped options) -> void
attr_reader token: String
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ module Plugins
client_class.add_plugin(HttpApiKeyAuth)
resp = client.operation
expect(resp.context.auth[:scheme_id]).to equal('smithy.api#httpApiKeyAuth')
expect(resp.context.auth[:identity]).to be_a(Identities::HttpApiKey)
expect(resp.context.auth[:identity]).to be_a(Identities::ApiKey)
end

it 'resolves auth for http basic auth' do
Expand All @@ -52,7 +52,7 @@ module Plugins
client_class.add_plugin(HttpBearerAuth)
resp = client.operation
expect(resp.context.auth[:scheme_id]).to equal('smithy.api#httpBearerAuth')
expect(resp.context.auth[:identity]).to be_a(Identities::HttpBearer)
expect(resp.context.auth[:identity]).to be_a(Identities::Token)
end

it 'resolves auth for http digest auth' do
Expand Down
70 changes: 45 additions & 25 deletions gems/smithy/lib/smithy/views/client/auth_resolver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,39 +18,45 @@ def module_name
@plan.module_name
end

# rubocop:disable Metrics/AbcSize
# rubocop:disable Metrics/MethodLength
def auth_rules_code
lines = []
lines << 'options = []'
auth_operations = operations_with_auth_traits
if auth_operations.empty?
service_auth_schemes.each do |auth_scheme|
lines << "options << '#{auth_scheme}'"
end
add_service_auth_schemes_to_code(lines)
else
lines << 'case parameters.operation_name'
auth_operations.each do |id, operation|
operation_name = Model::Shape.name(id).underscore
lines << "when :#{operation_name}"
operation_auth_schemes(operation).each do |auth_scheme|
lines << " options << '#{auth_scheme}'"
end
end
lines << 'else'
service_auth_schemes.each do |auth_scheme|
lines << " options << '#{auth_scheme}'"
end
lines << 'end'
add_operation_case_to_code(lines, auth_operations)
end
lines << 'options'
lines
end
# rubocop:enable Metrics/MethodLength
# rubocop:enable Metrics/AbcSize

private

def add_service_auth_schemes_to_code(lines)
service_auth_schemes.each do |auth_scheme|
lines << "options << '#{auth_scheme}'"
end
end

def add_operation_case_to_code(lines, auth_operations)
lines << 'case parameters.operation_name'
auth_operations.each do |id, operation|
operation_name = Model::Shape.name(id).underscore
lines << "when :#{operation_name}"
add_operation_auth_options_to_code(lines, operation)
end
lines << 'else'
add_service_auth_schemes_to_code(lines)
lines << 'end'
end

def add_operation_auth_options_to_code(lines, operation)
operation_auth_schemes(operation).each do |auth_scheme|
lines << " options << '#{auth_scheme}'"
end
end

def auth_schemes(welds)
weld_auth_schemes = welds.map(&:add_auth_schemes).reduce([], :+)
weld_auth_schemes -= welds.map(&:remove_auth_schemes).reduce([], :+)
Expand Down Expand Up @@ -89,18 +95,32 @@ def optional_operation_auth?(operation)

def operation_auth_schemes(operation)
operation_traits = operation.fetch('traits', {})
auth_schemes = build_operation_auth_schemes(operation, operation_traits)
auth_schemes << 'smithy.api#noAuth' if auth_schemes.empty? || optional_operation_auth?(operation)
auth_schemes
end

def build_operation_auth_schemes(operation, operation_traits)
auth_schemes = []
if operation_auth?(operation)
operation_auth = operation_traits.fetch('smithy.api#auth', [])
add_auth_schemes_from_auth_trait(auth_schemes, operation_auth)
add_explicit_operation_auth_schemes(auth_schemes, operation_traits)
else
add_registered_auth_schemes(auth_schemes, operation_traits)
add_service_auth_schemes_for_operation(auth_schemes)
end
auth_schemes << 'smithy.api#optionalAuth' if operation_traits.key?('smithy.api#optionalAuth')
auth_schemes << 'smithy.api#noAuth' if auth_schemes.empty?
auth_schemes
end

def add_explicit_operation_auth_schemes(auth_schemes, operation_traits)
operation_auth = operation_traits.fetch('smithy.api#auth', [])
add_auth_schemes_from_auth_trait(auth_schemes, operation_auth)
end

def add_service_auth_schemes_for_operation(auth_schemes)
service_auth_schemes.each do |auth_scheme|
auth_schemes << auth_scheme unless auth_scheme == 'smithy.api#noAuth'
end
end

def add_auth_schemes_from_auth_trait(auth_schemes, auth_trait)
auth_trait.each do |auth_scheme|
auth_schemes << auth_scheme if @auth_schemes.include?(auth_scheme)
Expand Down
15 changes: 15 additions & 0 deletions gems/smithy/spec/fixtures/auth/auth_trait/model.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,18 @@
"smithy.api#auth": []
}
},
"smithy.ruby.tests#OperationF": {
"type": "operation",
"input": {
"target": "smithy.api#Unit"
},
"output": {
"target": "smithy.api#Unit"
},
"traits": {
"smithy.api#optionalAuth": {}
}
},
"smithy.ruby.tests#ServiceWithAuthTrait": {
"type": "service",
"version": "2020-01-29",
Expand All @@ -48,6 +60,9 @@
},
{
"target": "smithy.ruby.tests#OperationE"
},
{
"target": "smithy.ruby.tests#OperationF"
}
],
"traits": {
Expand Down
9 changes: 8 additions & 1 deletion gems/smithy/spec/fixtures/auth/auth_trait/model.smithy
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ service ServiceWithAuthTrait {
OperationC
OperationD
OperationE
OperationF
]
}

Expand All @@ -29,4 +30,10 @@ operation OperationD {}
// This operation has the @auth trait and is bound to a service with the
// @auth trait. This operation does not support any authentication schemes.
@auth([])
operation OperationE {}
operation OperationE {}

// This operation has the @optionalAuth trait and is bound to a service
// with the @auth trait. The effective set of authentication schemes it
// supports are: httpBasicAuth, httpDigestAuth, and noAuth
@optionalAuth
operation OperationF {}
38 changes: 38 additions & 0 deletions gems/smithy/spec/fixtures/auth/no_auth/model.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"smithy": "2.0",
"shapes": {
"smithy.ruby.tests#OperationH": {
"type": "operation",
"input": {
"target": "smithy.api#Unit"
},
"output": {
"target": "smithy.api#Unit"
}
},
"smithy.ruby.tests#OperationI": {
"type": "operation",
"input": {
"target": "smithy.api#Unit"
},
"output": {
"target": "smithy.api#Unit"
},
"traits": {
"smithy.api#optionalAuth": {}
}
},
"smithy.ruby.tests#ServiceWithNoAuth": {
"type": "service",
"version": "2020-01-29",
"operations": [
{
"target": "smithy.ruby.tests#OperationH"
},
{
"target": "smithy.ruby.tests#OperationI"
}
]
}
}
}
20 changes: 20 additions & 0 deletions gems/smithy/spec/fixtures/auth/no_auth/model.smithy
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
$version: "2.0"

namespace smithy.ruby.tests

service ServiceWithNoAuth {
version: "2020-01-29"
operations: [
OperationH
OperationI
]
}

// This operation does not have the @auth trait and is bound to a service
// without auth. This operation does not support any authentication schemes.
operation OperationH {}

// This operation has the @optionalAuth trait and is bound to a service
// without auth. This operation does not support any authentication schemes.
@optionalAuth
operation OperationI {}
15 changes: 15 additions & 0 deletions gems/smithy/spec/fixtures/auth/no_auth_trait/model.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,18 @@
]
}
},
"smithy.ruby.tests#OperationG": {
"type": "operation",
"input": {
"target": "smithy.api#Unit"
},
"output": {
"target": "smithy.api#Unit"
},
"traits": {
"smithy.api#optionalAuth": {}
}
},
"smithy.ruby.tests#ServiceWithNoAuthTrait": {
"type": "service",
"version": "2020-01-29",
Expand All @@ -33,6 +45,9 @@
},
{
"target": "smithy.ruby.tests#OperationB"
},
{
"target": "smithy.ruby.tests#OperationG"
}
],
"traits": {
Expand Down
Loading