miasma-aws 0.2.4 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +3 -0
- data/lib/miasma/contrib/aws/storage.rb +21 -0
- data/lib/miasma/contrib/aws.rb +79 -23
- data/lib/miasma-aws/api/iam.rb +49 -0
- data/lib/miasma-aws/api/sts.rb +41 -3
- data/lib/miasma-aws/api.rb +1 -0
- data/lib/miasma-aws/version.rb +1 -1
- data/miasma-aws.gemspec +1 -1
- metadata +12 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9221ddb29c7683d78498567b552c6295078a97aa
|
4
|
+
data.tar.gz: e83a397c308eb038fdbaa14a0cc65da3b7da5441
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3e5f23aba1e47e832362638e817d66d6763b0422453fc78a8ec3814afd43130aa0762b8326b7111657d85d4106daf4791dfd20b93f8e596ccb836f7fe9ed0ee7
|
7
|
+
data.tar.gz: eeafe49ac5867ae0f24960ad25e7cb8a173bf0e5054535b5ec40efedd4700da84fa19aa1ab3aa96656d0be37d3fa5bbe2a27481628e63a0479ef737a26055721
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
# v0.3.0
|
2
|
+
* [feature] Add sts session token support (MFA #35)
|
3
|
+
* [enhancement] Load single bucket directly (remove bucket list permission requirement #33)
|
4
|
+
|
1
5
|
# v0.2.4
|
2
6
|
* [enhancement] Add aws credential file mappings for token value (#31)
|
3
7
|
* [fix] Support quoted values within aws credentials/configuration files (#31)
|
data/README.md
CHANGED
@@ -39,6 +39,9 @@ Miasma.api(
|
|
39
39
|
* `aws_sts_role_arn` - Assume role
|
40
40
|
* `aws_external_id` - Provide an external ID when assuming role
|
41
41
|
* `aws_sts_role_session_name` - Provide custom session name when assuming role
|
42
|
+
* `aws_sts_session_token` - MFA related session token
|
43
|
+
* `aws_sts_session_token_code` - Six digit code from MFA device
|
44
|
+
* `aws_sts_mfa_serial_number` - Serial number or ARN of MFA device
|
42
45
|
|
43
46
|
### S3 related attributes
|
44
47
|
|
@@ -92,6 +92,27 @@ module Miasma
|
|
92
92
|
bucket
|
93
93
|
end
|
94
94
|
|
95
|
+
# Directly fetch bucket
|
96
|
+
#
|
97
|
+
# @param ident [String] identifier
|
98
|
+
# @return [Models::Storage::Bucket, NilClass]
|
99
|
+
def bucket_get(ident)
|
100
|
+
bucket = Bucket.new(self,
|
101
|
+
:id => ident,
|
102
|
+
:name => ident
|
103
|
+
)
|
104
|
+
begin
|
105
|
+
bucket.reload
|
106
|
+
bucket
|
107
|
+
rescue Error::ApiError::RequestError => e
|
108
|
+
if(e.response.status == 404)
|
109
|
+
nil
|
110
|
+
else
|
111
|
+
raise
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
95
116
|
# Destroy bucket
|
96
117
|
#
|
97
118
|
# @param bucket [Models::Storage::Bucket]
|
data/lib/miasma/contrib/aws.rb
CHANGED
@@ -337,6 +337,9 @@ module Miasma
|
|
337
337
|
attribute :aws_sts_role_session_name, String
|
338
338
|
attribute :aws_sts_region, String
|
339
339
|
attribute :aws_sts_host, String
|
340
|
+
attribute :aws_sts_session_token, String
|
341
|
+
attribute :aws_sts_session_token_code, [String, Proc, Method]
|
342
|
+
attribute :aws_sts_mfa_serial_number, [String]
|
340
343
|
attribute :aws_credentials_file, String, :required => true, :default => File.join(Dir.home, '.aws/credentials')
|
341
344
|
attribute :aws_config_file, String, :required => true, :default => File.join(Dir.home, '.aws/config')
|
342
345
|
attribute :aws_access_key_id, String, :required => true
|
@@ -349,9 +352,6 @@ module Miasma
|
|
349
352
|
attribute :euca_compat, Symbol, :allowed_values => [:path, :dns], :coerce => lambda{|v| v.is_a?(String) ? v.to_sym : v}
|
350
353
|
attribute :euca_dns_map, Smash, :coerce => lambda{|v| v.to_smash}, :default => Smash.new
|
351
354
|
attribute :ssl_enabled, [TrueClass, FalseClass], :default => true
|
352
|
-
|
353
|
-
# @return [Contrib::AwsApiCore::SignatureV4]
|
354
|
-
attr_reader :signer
|
355
355
|
end
|
356
356
|
|
357
357
|
# AWS config file key remapping
|
@@ -360,7 +360,7 @@ module Miasma
|
|
360
360
|
'region' => 'aws_region',
|
361
361
|
'role_arn' => 'aws_sts_role_arn',
|
362
362
|
'aws_security_token' => 'aws_sts_token',
|
363
|
-
'aws_session_token' => '
|
363
|
+
'aws_session_token' => 'aws_sts_session_token'
|
364
364
|
)
|
365
365
|
)
|
366
366
|
klass.const_set(:INSTANCE_PROFILE_HOST, 'http://169.254.169.254')
|
@@ -405,9 +405,6 @@ module Miasma
|
|
405
405
|
).merge(creds)
|
406
406
|
)
|
407
407
|
end
|
408
|
-
if(creds[:aws_sts_role_arn])
|
409
|
-
sts_assume_role!(creds)
|
410
|
-
end
|
411
408
|
if(creds[:aws_iam_instance_profile])
|
412
409
|
load_instance_credentials!(creds)
|
413
410
|
end
|
@@ -472,24 +469,42 @@ module Miasma
|
|
472
469
|
true
|
473
470
|
end
|
474
471
|
|
472
|
+
def sts_mfa_session!(creds)
|
473
|
+
if(sts_mfa_session_update_required?(creds))
|
474
|
+
sts = Miasma::Contrib::Aws::Api::Sts.new(
|
475
|
+
:aws_access_key_id => creds[:aws_access_key_id],
|
476
|
+
:aws_secret_access_key => creds[:aws_secret_access_key],
|
477
|
+
:aws_region => creds.fetch(:aws_sts_region, 'us-east-1'),
|
478
|
+
:aws_credentials_file => creds.fetch(:aws_credentials_file, aws_credentials_file),
|
479
|
+
:aws_config_file => creds.fetch(:aws_config_file, aws_config_file),
|
480
|
+
:aws_profile_name => creds[:aws_profile_name],
|
481
|
+
:aws_host => creds[:aws_sts_host],
|
482
|
+
)
|
483
|
+
creds.merge!(
|
484
|
+
sts.mfa_session(
|
485
|
+
creds[:aws_sts_session_token_code],
|
486
|
+
:mfa_serial => creds[:aws_sts_mfa_serial_number]
|
487
|
+
)
|
488
|
+
)
|
489
|
+
end
|
490
|
+
true
|
491
|
+
end
|
492
|
+
|
475
493
|
# Assume requested role and replace key id and secret
|
476
494
|
#
|
477
495
|
# @param creds [Hash]
|
478
496
|
# @return [TrueClass]
|
479
497
|
def sts_assume_role!(creds)
|
480
|
-
|
481
|
-
creds[:aws_access_key_id_original] = creds[:aws_access_key_id]
|
482
|
-
creds[:aws_secret_access_key_original] = creds[:aws_secret_access_key]
|
483
|
-
end
|
484
|
-
if(sts_update_required?(creds))
|
498
|
+
if(sts_assume_role_update_required?(creds))
|
485
499
|
sts = Miasma::Contrib::Aws::Api::Sts.new(
|
486
|
-
:aws_access_key_id =>
|
487
|
-
:aws_secret_access_key =>
|
500
|
+
:aws_access_key_id => get_credential(:access_key_id, creds),
|
501
|
+
:aws_secret_access_key => get_credential(:secret_access_key, creds),
|
488
502
|
:aws_region => creds.fetch(:aws_sts_region, 'us-east-1'),
|
489
503
|
:aws_credentials_file => creds.fetch(:aws_credentials_file, aws_credentials_file),
|
490
504
|
:aws_config_file => creds.fetch(:aws_config_file, aws_config_file),
|
491
505
|
:aws_profile_name => creds[:aws_profile_name],
|
492
|
-
:aws_host => creds[:aws_sts_host]
|
506
|
+
:aws_host => creds[:aws_sts_host],
|
507
|
+
:aws_sts_token => creds[:aws_sts_session_token]
|
493
508
|
)
|
494
509
|
role_info = sts.assume_role(
|
495
510
|
creds[:aws_sts_role_arn],
|
@@ -590,11 +605,33 @@ module Miasma
|
|
590
605
|
].join('.')
|
591
606
|
end
|
592
607
|
end
|
593
|
-
|
594
|
-
|
608
|
+
end
|
609
|
+
|
610
|
+
# @return [Contrib::AwsApiCore::SignatureV4]
|
611
|
+
def signer
|
612
|
+
Contrib::AwsApiCore::SignatureV4.new(
|
613
|
+
get_credential(:access_key_id),
|
614
|
+
get_credential(:secret_access_key),
|
615
|
+
aws_region,
|
616
|
+
self.class::API_SERVICE
|
595
617
|
)
|
596
618
|
end
|
597
619
|
|
620
|
+
# Return correct credential value based on STS context
|
621
|
+
#
|
622
|
+
# @param key [String, Symbol] credential suffix
|
623
|
+
# @return [Object]
|
624
|
+
def get_credential(key, data_hash=nil)
|
625
|
+
data_hash = attributes if data_hash.nil?
|
626
|
+
if(data_hash[:aws_sts_token])
|
627
|
+
data_hash.fetch("aws_sts_#{key}", data_hash["aws_#{key}"])
|
628
|
+
elsif(data_hash[:aws_sts_session_token])
|
629
|
+
data_hash.fetch("aws_sts_session_#{key}", data_hash["aws_#{key}"])
|
630
|
+
else
|
631
|
+
data_hash["aws_#{key}"]
|
632
|
+
end
|
633
|
+
end
|
634
|
+
|
598
635
|
# @return [String] custom escape for aws compat
|
599
636
|
def uri_escape(string)
|
600
637
|
signer.safe_escape(string)
|
@@ -637,8 +674,16 @@ module Miasma
|
|
637
674
|
)
|
638
675
|
end
|
639
676
|
end
|
640
|
-
if(
|
641
|
-
|
677
|
+
if(aws_sts_session_token || aws_sts_session_token_code)
|
678
|
+
if(sts_mfa_session_update_required?)
|
679
|
+
sts_mfa_session!(data)
|
680
|
+
end
|
681
|
+
options.set(:headers, 'X-Amz-Security-Token', aws_sts_session_token)
|
682
|
+
end
|
683
|
+
if(aws_sts_token || aws_sts_role_arn)
|
684
|
+
if(sts_assume_role_update_required?)
|
685
|
+
sts_assume_role!(data)
|
686
|
+
end
|
642
687
|
options.set(:headers, 'X-Amz-Security-Token', aws_sts_token)
|
643
688
|
end
|
644
689
|
signature = signer.generate(http_method, path, options)
|
@@ -649,10 +694,21 @@ module Miasma
|
|
649
694
|
|
650
695
|
# @return [TrueClass, FalseClass]
|
651
696
|
# @note update check only applied if assuming role
|
652
|
-
def
|
653
|
-
if(args.fetch(:aws_sts_role_arn,
|
654
|
-
expiry = args.fetch(:aws_sts_token_expires,
|
655
|
-
expiry.nil? || expiry <= Time.now -
|
697
|
+
def sts_assume_role_update_required?(args={})
|
698
|
+
if(args.fetch(:aws_sts_role_arn, attributes[:aws_sts_role_arn]))
|
699
|
+
expiry = args.fetch(:aws_sts_token_expires, attributes[:aws_sts_token_expires])
|
700
|
+
expiry.nil? || expiry <= Time.now - 15
|
701
|
+
else
|
702
|
+
false
|
703
|
+
end
|
704
|
+
end
|
705
|
+
|
706
|
+
# @return [TrueClass, FalseClass]
|
707
|
+
# @note update check only applied if assuming role
|
708
|
+
def sts_mfa_session_update_required?(args={})
|
709
|
+
if(args.fetch(:aws_sts_session_token_code, attributes[:aws_sts_session_token_code]))
|
710
|
+
expiry = args.fetch(:aws_sts_session_token_expires, attributes[:aws_sts_session_token_expires])
|
711
|
+
expiry.nil? || expiry <= Time.now - 15
|
656
712
|
else
|
657
713
|
false
|
658
714
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'miasma'
|
2
|
+
|
3
|
+
module Miasma
|
4
|
+
module Contrib
|
5
|
+
module Aws
|
6
|
+
module Api
|
7
|
+
class Iam < Miasma::Types::Api
|
8
|
+
|
9
|
+
# Service name of the API
|
10
|
+
API_SERVICE = 'iam'
|
11
|
+
# Supported version of the IAM API
|
12
|
+
API_VERSION = '2010-05-08'
|
13
|
+
|
14
|
+
include Contrib::AwsApiCore::ApiCommon
|
15
|
+
include Contrib::AwsApiCore::RequestUtils
|
16
|
+
|
17
|
+
def connect
|
18
|
+
super
|
19
|
+
service_name = self.class::API_SERVICE.downcase
|
20
|
+
self.aws_host = [
|
21
|
+
service_name,
|
22
|
+
api_endpoint
|
23
|
+
].join('.')
|
24
|
+
end
|
25
|
+
|
26
|
+
# Fetch current user information
|
27
|
+
def user_info
|
28
|
+
result = request(
|
29
|
+
:path => '/',
|
30
|
+
:params => {
|
31
|
+
'Action' => 'GetUser'
|
32
|
+
}
|
33
|
+
).get(:body, 'GetUserResponse', 'GetUserResult', 'User')
|
34
|
+
Smash.new(
|
35
|
+
:user_id => result['UserId'],
|
36
|
+
:path => result['Path'],
|
37
|
+
:username => result['UserName'],
|
38
|
+
:arn => result['Arn'],
|
39
|
+
:created => result['CreateDate'],
|
40
|
+
:password_last_used => result['PasswordLastUsed'],
|
41
|
+
:account_id => result['Arn'].split(':')[4]
|
42
|
+
)
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/miasma-aws/api/sts.rb
CHANGED
@@ -8,12 +8,38 @@ module Miasma
|
|
8
8
|
|
9
9
|
# Service name of the API
|
10
10
|
API_SERVICE = 'sts'
|
11
|
-
# Supported version of the
|
11
|
+
# Supported version of the STS API
|
12
12
|
API_VERSION = '2011-06-15'
|
13
13
|
|
14
14
|
include Contrib::AwsApiCore::ApiCommon
|
15
15
|
include Contrib::AwsApiCore::RequestUtils
|
16
16
|
|
17
|
+
# Generate MFA session credentials
|
18
|
+
#
|
19
|
+
# @param token_code [String, Proc] Code from MFA device
|
20
|
+
# @param args [Hash]
|
21
|
+
# @option args [Integer] :duration life of session in seconds
|
22
|
+
# @option args [String] :mfa_serial MFA device identification number
|
23
|
+
# @return [Hash]
|
24
|
+
def mfa_session(token_code, args={})
|
25
|
+
req_params = Smash.new.tap do |params|
|
26
|
+
params['Action'] = 'GetSessionToken'
|
27
|
+
params['TokenCode'] = token_code.respond_to?(:call) ? token_code.call : token_code
|
28
|
+
params['DurationSeconds'] = args[:duration] if args[:duration]
|
29
|
+
params['SerialNumber'] = args[:mfa_serial].to_s.empty? ? default_mfa_serial : args[:mfa_serial]
|
30
|
+
end
|
31
|
+
result = request(
|
32
|
+
:path => '/',
|
33
|
+
:params => req_params
|
34
|
+
).get(:body, 'GetSessionTokenResponse', 'GetSessionTokenResult', 'Credentials')
|
35
|
+
Smash.new(
|
36
|
+
:aws_sts_session_token => result['SessionToken'],
|
37
|
+
:aws_sts_session_secret_access_key => result['SecretAccessKey'],
|
38
|
+
:aws_sts_session_access_key_id => result['AccessKeyId'],
|
39
|
+
:aws_sts_session_token_expires => Time.parse(result['Expiration'])
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
17
43
|
# Assume new role
|
18
44
|
#
|
19
45
|
# @param role_arn [String] IAM Role ARN
|
@@ -34,14 +60,26 @@ module Miasma
|
|
34
60
|
).get(:body, 'AssumeRoleResponse', 'AssumeRoleResult')
|
35
61
|
Smash.new(
|
36
62
|
:aws_sts_token => result.get('Credentials', 'SessionToken'),
|
37
|
-
:
|
38
|
-
:
|
63
|
+
:aws_sts_secret_access_key => result.get('Credentials', 'SecretAccessKey'),
|
64
|
+
:aws_sts_access_key_id => result.get('Credentials', 'AccessKeyId'),
|
39
65
|
:aws_sts_token_expires => Time.parse(result.get('Credentials', 'Expiration')),
|
40
66
|
:aws_sts_assumed_role_arn => result.get('AssumedRoleUser', 'Arn'),
|
41
67
|
:aws_sts_assumed_role_id => result.get('AssumedRoleUser', 'AssumedRoleId')
|
42
68
|
)
|
43
69
|
end
|
44
70
|
|
71
|
+
# @return [String]
|
72
|
+
def default_mfa_serial
|
73
|
+
user_data = Iam.new(
|
74
|
+
Smash[
|
75
|
+
[:aws_access_key_id, :aws_secret_access_key, :aws_region].map do |key|
|
76
|
+
[key, attributes[key]]
|
77
|
+
end
|
78
|
+
]
|
79
|
+
).user_info
|
80
|
+
"arn:aws:iam::#{user_data[:account_id]}:mfa/#{user_data[:username]}"
|
81
|
+
end
|
82
|
+
|
45
83
|
end
|
46
84
|
end
|
47
85
|
end
|
data/lib/miasma-aws/api.rb
CHANGED
data/lib/miasma-aws/version.rb
CHANGED
data/miasma-aws.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |s|
|
|
10
10
|
s.description = 'Smoggy AWS API'
|
11
11
|
s.license = 'Apache 2.0'
|
12
12
|
s.require_path = 'lib'
|
13
|
-
s.
|
13
|
+
s.add_runtime_dependency 'miasma', '>= 0.2.39', '< 0.5'
|
14
14
|
s.add_development_dependency 'rake'
|
15
15
|
s.add_development_dependency 'rubocop'
|
16
16
|
s.add_development_dependency 'pry'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: miasma-aws
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Roberts
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-02-
|
11
|
+
date: 2016-02-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: miasma
|
@@ -16,14 +16,20 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.2.
|
20
|
-
|
19
|
+
version: 0.2.39
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0.5'
|
23
|
+
type: :runtime
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
23
26
|
requirements:
|
24
27
|
- - ">="
|
25
28
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.2.
|
29
|
+
version: 0.2.39
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0.5'
|
27
33
|
- !ruby/object:Gem::Dependency
|
28
34
|
name: rake
|
29
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -147,6 +153,7 @@ files:
|
|
147
153
|
- README.md
|
148
154
|
- lib/miasma-aws.rb
|
149
155
|
- lib/miasma-aws/api.rb
|
156
|
+
- lib/miasma-aws/api/iam.rb
|
150
157
|
- lib/miasma-aws/api/sts.rb
|
151
158
|
- lib/miasma-aws/version.rb
|
152
159
|
- lib/miasma/contrib/aws.rb
|