Commit 917e3ec5 authored by Changzheng Liu's avatar Changzheng Liu Committed by Dylan Griffith

Support AWS IAM role for ECS tasks in elastic search client

Note, this change is copied from a community contribution https://gitlab.com/gitlab-org/gitlab/-/merge_requests/24926
parent e0e69938
---
title: Support AWS IAM role for ECS tasks in Elasticsearch client
merge_request: 33456
author:
type: added
...@@ -32,10 +32,12 @@ module Gitlab ...@@ -32,10 +32,12 @@ module Gitlab
return static_credentials if static_credentials&.set? return static_credentials if static_credentials&.set?
# Instantiating this will perform an API call, so only do so if the # When static credentials are not configured, Aws::CredentialProviderChain API
# static credentials did not work # will be used to retrieve credentials. It will check AWS access credential environment
instance_credentials = Aws::InstanceProfileCredentials.new # variables, AWS credential profile, ECS credential service and EC2 credential service.
# Please see aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb for details of
# the possible providers and order of the providers.
instance_credentials = Aws::CredentialProviderChain.new.resolve
instance_credentials if instance_credentials&.set? instance_credentials if instance_credentials&.set?
end end
end end
......
...@@ -109,8 +109,9 @@ module Gitlab ...@@ -109,8 +109,9 @@ module Gitlab
'SSL_CERT_DIR' => OpenSSL::X509::DEFAULT_CERT_DIR 'SSL_CERT_DIR' => OpenSSL::X509::DEFAULT_CERT_DIR
} }
# Users can override default SSL certificate path via these envs # Users can override default SSL certificate path via SSL_CERT_FILE SSL_CERT_DIR
%w(SSL_CERT_FILE SSL_CERT_DIR).each_with_object(vars) do |key, hash| # AWS_CONTAINER_CREDENTIALS_RELATIVE_URI is used in AWS ECS to get credentials when making AWS API calls
%w(SSL_CERT_FILE SSL_CERT_DIR AWS_CONTAINER_CREDENTIALS_RELATIVE_URI).each_with_object(vars) do |key, hash|
hash[key] = ENV[key] if ENV.key?(key) hash[key] = ENV[key] if ENV.key?(key)
end end
end end
......
...@@ -3,33 +3,6 @@ ...@@ -3,33 +3,6 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Gitlab::Elastic::Client do RSpec.describe Gitlab::Elastic::Client do
let(:creds_valid_response) do
'{
"Code": "Success",
"Type": "AWS-HMAC",
"AccessKeyId": "0",
"SecretAccessKey": "0",
"Token": "token",
"Expiration": "2018-12-16T01:51:37Z",
"LastUpdated": "2009-11-23T0:00:00Z"
}'
end
let(:creds_fail_response) do
'{
"Code": "ErrorCode",
"Message": "ErrorMsg",
"LastUpdated": "2009-11-23T0:00:00Z"
}'
end
def stub_instance_credentials(creds_response)
stub_request(:get, "http://169.254.169.254/latest/meta-data/iam/security-credentials/")
.to_return(status: 200, body: "RoleName", headers: {})
stub_request(:get, "http://169.254.169.254/latest/meta-data/iam/security-credentials/RoleName")
.to_return(status: 200, body: creds_response, headers: {})
end
describe '.build' do describe '.build' do
let(:client) { described_class.build(params) } let(:client) { described_class.build(params) }
...@@ -60,7 +33,6 @@ RSpec.describe Gitlab::Elastic::Client do ...@@ -60,7 +33,6 @@ RSpec.describe Gitlab::Elastic::Client do
# Mock the correlation ID (passed as header) to have deterministic signature # Mock the correlation ID (passed as header) to have deterministic signature
allow(Labkit::Correlation::CorrelationId).to receive(:current_or_new_id).and_return('new-correlation-id') allow(Labkit::Correlation::CorrelationId).to receive(:current_or_new_id).and_return('new-correlation-id')
stub_instance_credentials(creds_fail_response)
travel_to(Time.parse('20170303T133952Z')) do travel_to(Time.parse('20170303T133952Z')) do
stub_request(:get, 'http://example-elastic:9200/foo/_all/1') stub_request(:get, 'http://example-elastic:9200/foo/_all/1')
.with( .with(
...@@ -99,7 +71,6 @@ RSpec.describe Gitlab::Elastic::Client do ...@@ -99,7 +71,6 @@ RSpec.describe Gitlab::Elastic::Client do
end end
context 'when the AWS IAM static credentials are invalid' do context 'when the AWS IAM static credentials are invalid' do
context 'with AWS ec2 instance profile' do
let(:params) do let(:params) do
{ {
url: 'http://example-elastic:9200', url: 'http://example-elastic:9200',
...@@ -107,27 +78,30 @@ RSpec.describe Gitlab::Elastic::Client do ...@@ -107,27 +78,30 @@ RSpec.describe Gitlab::Elastic::Client do
aws_region: 'us-east-1' aws_region: 'us-east-1'
} }
end end
let(:credentials) { double(:aws_credentials, set?: true) }
it 'returns credentials from ec2 instance profile' do before do
stub_instance_credentials(creds_valid_response) allow_next_instance_of(Aws::CredentialProviderChain) do |instance|
allow(instance).to receive(:resolve).and_return(credentials)
expect(creds.credentials.access_key_id).to eq '0'
expect(creds.credentials.secret_access_key).to eq '0'
end end
end end
context 'with AWS no credentials' do it 'returns credentials from Aws::CredentialProviderChain' do
let(:params) do expect(creds).to eq credentials
{
url: 'http://example-elastic:9200',
aws: true,
aws_region: 'us-east-1'
}
end end
context 'when Aws::CredentialProviderChain returns unset credentials' do
let(:credentials) { double(:aws_credentials, set?: false) }
it 'returns nil' do it 'returns nil' do
stub_instance_credentials(creds_fail_response) expect(creds).to be_nil
end
end
context 'when Aws::CredentialProviderChain returns nil' do
let(:credentials) { nil }
it 'returns nil' do
expect(creds).to be_nil expect(creds).to be_nil
end end
end end
......
...@@ -317,6 +317,22 @@ RSpec.describe Gitlab::Elastic::Indexer do ...@@ -317,6 +317,22 @@ RSpec.describe Gitlab::Elastic::Indexer do
end end
end end
context 'when AWS_CONTAINER_CREDENTIALS_RELATIVE_URI is set' do
let(:aws_cred_relative_uri) { '/ecs/relative/cred/uri'}
before do
stub_env('AWS_CONTAINER_CREDENTIALS_RELATIVE_URI', aws_cred_relative_uri)
end
context 'when building env vars for child process' do
subject { envvars }
it 'AWS_CONTAINER_CREDENTIALS_RELATIVE_URI env vars will be included' do
expect(subject).to include('AWS_CONTAINER_CREDENTIALS_RELATIVE_URI' => aws_cred_relative_uri)
end
end
end
def expect_popen def expect_popen
expect(Gitlab::Popen).to receive(:popen) expect(Gitlab::Popen).to receive(:popen)
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