Unverified Commit 3798977a authored by Tim Smith's avatar Tim Smith Committed by GitHub
Browse files

Merge pull request #927 from chef/snappj/add-aws-iam-auth

Add AWS IAM authentication for S3 caching and publishing
parents 0baf021d 426bca4d
......@@ -84,11 +84,19 @@ use_git_caching false
# Enable S3 asset caching
# ------------------------------
use_s3_caching true
s3_bucket ENV['S3_BUCKET']
# There are three ways to authenticate to the S3 bucket
# 1. set `s3_access_key` and `s3_secret_key`
s3_access_key ENV['S3_ACCESS_KEY']
s3_secret_key ENV['S3_SECRET_KEY']
# You can use the Shared Credentials files in place of the s3_access_key and s3_secret_key.
# 2. set `s3_profile` to use an AWS profile in the Shared Credentials files
#s3_profile ENV['S3_PROFILE']
s3_bucket ENV['S3_BUCKET']
# 3. set `s3_iam_role_arn` to use an AWS IAM role
#s3_iam_role_arn ENV['S3_IAM_ROLE_ARN']
```
For more information, please see the [`Config` documentation](http://www.rubydoc.info/github/chef/omnibus/Omnibus/Config).
......
......@@ -285,7 +285,7 @@ module Omnibus
#
# @return [String, nil]
default(:s3_access_key) do
if s3_profile
if s3_profile || s3_iam_role_arn
nil
else
raise MissingRequiredAttribute.new(self, :s3_access_key, "'ABCD1234'")
......@@ -296,7 +296,7 @@ module Omnibus
#
# @return [String, nil]
default(:s3_secret_key) do
if s3_profile
if s3_profile || s3_iam_role_arn
nil
else
raise MissingRequiredAttribute.new(self, :s3_secret_key, "'EFGH5678'")
......@@ -308,6 +308,11 @@ module Omnibus
# @return [String, nil]
default(:s3_profile, nil)
# The AWS IAM role arn to use with S3 caching.
#
# @return [String, nil]
default(:s3_iam_role_arn, nil)
# The region of the S3 bucket you want to cache software artifacts in.
# Defaults to 'us-east-1'
#
......@@ -455,6 +460,11 @@ module Omnibus
# @return [String, nil]
default(:publish_s3_profile, nil)
# The AWS IAM role arn to use with S3 publisher.
#
# @return [String, nil]
default(:publish_s3_iam_role_arn, nil)
# Directory pattern for the S3 publisher.
# Interpolation of metadata keys is supported.
#
......
......@@ -31,10 +31,11 @@
# Enable S3 asset caching
# ------------------------------
# use_s3_caching true
# s3_access_key ENV['AWS_ACCESS_KEY_ID']
# s3_secret_key ENV['AWS_SECRET_ACCESS_KEY']
# s3_profile ENV['AWS_S3_PROFILE']
# s3_bucket ENV['AWS_S3_BUCKET']
# s3_access_key ENV['AWS_ACCESS_KEY_ID']
# s3_secret_key ENV['AWS_SECRET_ACCESS_KEY']
# s3_profile ENV['AWS_S3_PROFILE']
# s3_iam_role_arn ENV['S3_IAM_ROLE_ARN']
# s3_bucket ENV['AWS_S3_BUCKET']
# Customize compiler bits
# ------------------------------
......
......@@ -65,11 +65,13 @@ module Omnibus
bucket_name: @options[:bucket],
}
if Config.publish_s3_profile
config[:profile] = Config.publish_s3_profile
if Config.publish_s3_iam_role_arn
config[:publish_s3_iam_role_arn] = Config.publish_s3_iam_role_arn
elsif Config.publish_s3_profile
config[:profile] = Config.publish_s3_profile
else
config[:access_key_id] = Config.publish_s3_access_key
config[:secret_access_key] = Config.publish_s3_secret_key
config[:access_key_id] = Config.publish_s3_access_key
config[:secret_access_key] = Config.publish_s3_secret_key
end
config
......
......@@ -147,7 +147,9 @@ module Omnibus
force_path_style: Config.s3_force_path_style,
}
if Config.s3_profile
if Config.s3_iam_role_arn
config[:iam_role_arn] = Config.s3_iam_role_arn
elsif Config.s3_profile
config[:profile] = Config.s3_profile
else
config[:access_key_id] = Config.s3_access_key
......
......@@ -53,10 +53,7 @@ module Omnibus
# @return [Aws::S3::Resource]
#
def client
Aws.config.update(
region: s3_configuration[:region],
credentials: get_credentials
)
Aws.config.update(region: s3_configuration[:region])
@s3_client ||= Aws::S3::Resource.new(resource_params)
end
......@@ -70,6 +67,7 @@ module Omnibus
params = {
use_accelerate_endpoint: s3_configuration[:use_accelerate_endpoint],
force_path_style: s3_configuration[:force_path_style],
credentials: get_credentials,
}
if s3_configuration[:use_accelerate_endpoint]
......@@ -84,12 +82,14 @@ module Omnibus
end
#
# Create credentials object based on credential profile or access key
# Create credentials object based on AWS IAM role arn, credential profile or access key
# parameters for use by the client object.
#
# @return [Aws::SharedCredentials, Aws::Credentials]
def get_credentials
if s3_configuration[:profile]
if s3_configuration[:iam_role_arn]
Aws::AssumeRoleCredentials.new(role_arn: s3_configuration[:iam_role_arn], role_session_name: "omnibus-assume-role-s3-access")
elsif s3_configuration[:profile]
Aws::SharedCredentials.new(profile_name: s3_configuration[:profile])
elsif s3_configuration[:access_key_id] && s3_configuration[:secret_access_key]
Aws::Credentials.new(s3_configuration[:access_key_id], s3_configuration[:secret_access_key])
......
......@@ -109,10 +109,12 @@ module Omnibus
let (:s3_access_key) { nil }
let (:s3_secret_key) { nil }
let (:s3_profile) { nil }
let (:s3_iam_role_arn) { nil }
before do
Config.s3_bucket s3_bucket
Config.s3_region s3_region
Config.s3_iam_role_arn s3_iam_role_arn
Config.s3_profile s3_profile
Config.s3_access_key s3_access_key
Config.s3_secret_key s3_secret_key
......@@ -148,6 +150,21 @@ module Omnibus
expect(config[:secret_access_key]).to eq(nil)
end
end
context "s3_iam_role_arn is configured" do
let(:s3_iam_role_arn) { "S3_IAM_ROLE_ARN" }
let(:s3_profile) { "SHAREDPROFILE" }
let(:s3_access_key) { "ACCESS_KEY_ID" }
let(:s3_secret_key) { "SECRET_ACCESS_KEY" }
it "sets s3_iam_role_arn only" do
config = S3Cache.send(:s3_configuration)
expect(config[:iam_role_arn]).to eq(s3_iam_role_arn)
expect(config[:profile]).to eq(nil)
expect(config[:access_key_id]).to eq(nil)
expect(config[:secret_access_key]).to eq(nil)
end
end
end
end
end
......@@ -40,6 +40,8 @@ module Omnibus
let(:instance) { klass.new }
let(:key_pair) { { access_key_id: "key_id", secret_access_key: "access_key" } }
let(:profile) { "my-profile" }
let(:iam_role_arn) { "my-iam-role-arn" }
let(:role_session_name) { "omnibus-assume-role-s3-access" }
let(:config) { { bucket_name: "foo", region: "us-east-1" } }
it "uses configured key pairs" do
......@@ -52,19 +54,36 @@ module Omnibus
instance.send(:get_credentials)
end
it "preferrs shared credentials profiles over key pairs" do
it "prefers shared credentials profiles over key pairs" do
allow_any_instance_of(klass).to receive(:s3_configuration).and_return(
{
**config,
**key_pair,
iam_role_arn: nil,
profile: profile,
}
)
expect(Aws::Credentials).to_not receive(:new)
expect(Aws::AssumeRoleCredentials).to_not receive(:new)
allow(Aws::SharedCredentials).to receive(:new).with(profile_name: profile)
instance.send(:get_credentials)
end
it "prefers AWS IAM role arn over profiles and key pairs" do
allow_any_instance_of(klass).to receive(:s3_configuration).and_return(
{
**config,
**key_pair,
profile: profile,
iam_role_arn: iam_role_arn,
}
)
expect(Aws::Credentials).to_not receive(:new)
expect(Aws::SharedCredentials).to_not receive(:new)
allow(Aws::AssumeRoleCredentials).to receive(:new).with(role_arn: iam_role_arn, role_session_name: role_session_name)
instance.send(:get_credentials)
end
end
end
end
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment