Skip to content

Commit

Permalink
Support extracting STS host region from authorization header
Browse files Browse the repository at this point in the history
  • Loading branch information
gl-johnson committed Jun 23, 2023
1 parent 631d745 commit 4432fe7
Show file tree
Hide file tree
Showing 8 changed files with 225 additions and 8 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Nothing should go in this section, please add to the latest unreleased version
(and update the corresponding date), or add a new version.

## [1.19.5] - 2023-05-16
## [1.19.5] - 2023-06-21

### Security
- Update bundler to 2.2.33 to remove CVE-2021-43809
[cyberark/conjur#2804](https://github.com/cyberark/conjur/pull/2804/files)

### Fixed
- Support Authn-IAM case where host value is missing from signed headers.
[cyberark/conjur#2827](https://github.com/cyberark/conjur/pull/2827)
- AuthnJWT now supports claims that include hyphens and inline namespaces.
[cyberark/conjur#2792](https://github.com/cyberark/conjur/pull/2792)
- Authn-IAM now uses the host in the signed headers to determine which STS endpoint
Expand Down
33 changes: 32 additions & 1 deletion app/domain/authentication/authn_iam/authenticator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,27 @@ def extract_relevant_data(response)

# Call to AWS STS endpoint using the provided authentication header
def attempt_signed_request(signed_headers)
aws_request = URI("https://#{signed_headers['host']}/?Action=GetCallerIdentity&Version=2011-06-15")
sts_host = extract_sts_host(signed_headers)
aws_request = URI("https://#{sts_host}/?Action=GetCallerIdentity&Version=2011-06-15")
begin
response = @client.get_response(aws_request, signed_headers)
return response unless response.code.to_i == 403 && sts_host.include?('us-east-1')

# If the request to `us-east-1` failed with a 403, retry on the global endpoint
retry_signed_request_on_global(signed_headers)

# Handle any network failures with a generic verification error
rescue StandardError => e
raise(Errors::Authentication::AuthnIam::VerificationError.new(e))
end
end

# Retry request on AWS STS global endpoint
def retry_signed_request_on_global(signed_headers)
@logger.debug(
LogMessages::Authentication::AuthnIam::RetryWithGlobalEndpoint.new
)
aws_request = URI('https://sts.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15')
begin
@client.get_response(aws_request, signed_headers)

Expand All @@ -76,6 +96,17 @@ def response_from_signed_request(aws_headers)
body.dig('ErrorResponse', 'Error', 'Message').to_s.strip
)
end

# Extract AWS region from the authorization header's credential string, i.e.:
# Credential=AKIAIOSFODNN7EXAMPLE/20220830/us-east-1/sts/aws4_request
def extract_sts_host(signed_headers)
return signed_headers['host'] if signed_headers['host'].present?

region = signed_headers['authorization'].match(%r{Credential=[^/]+/[^/]+/([^/]+)/})&.captures&.first
raise(Errors::Authentication::AuthnIam::InvalidAWSHeaders, 'Failed to extract AWS region from authorization header') unless region

"sts.#{region}.amazonaws.com"
end
end
end
end
5 changes: 5 additions & 0 deletions app/domain/logs.rb
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,11 @@ module AuthnIam
code: "CONJ00036D"
)

RetryWithGlobalEndpoint = ::Util::TrackableLogMessageClass.new(
msg: "Retrying IAM request signed in 'us-east-1' region with global STS endpoint.",
code: "CONJ00043D"
)

end

module AuthnAzure
Expand Down
2 changes: 1 addition & 1 deletion config/environments/development.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
# https://guides.rubyonrails.org/configuring.html#actiondispatch-hostauthorization

# Accept multiple hosts for parallel tests
config.hosts << /^conjur[0-9]*$/
config.hosts << /conjur[0-9]*/

# eager_load needed to make authentication work without the hacky
# loading code...
Expand Down
13 changes: 8 additions & 5 deletions dev/start
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@
set -ex
set -o pipefail

# CC servers can't find it for some reason. Local shellcheck is fine.
# shellcheck disable=SC1091
source "../ci/oauth/keycloak/keycloak_functions.sh"

# SCRIPT GLOBAL STATE

# Set up VERSION file for local development
Expand Down Expand Up @@ -229,7 +225,14 @@ configure_oidc_authenticators() {
}

setup_keycloak() {
# Start keycloak docker compose service

pushd "../ci"
# CC servers can't find it for some reason. Local shellcheck is fine.
# shellcheck disable=SC1091
source "oauth/keycloak/keycloak_functions.sh"
popd

# Start keycloak docker-compose service
services+=(keycloak)
docker compose up -d --no-deps "${services[@]}"

Expand Down
31 changes: 31 additions & 0 deletions spec/app/domain/authentication/authn_iam/authenticator_spec.rb

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 4432fe7

Please sign in to comment.