rcredstash 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8a93b119dd169d80cf8ffaee1b098f153b0c7f5b
4
- data.tar.gz: 37722f3b8674110281a0c292120a4a58a0629252
3
+ metadata.gz: 54924cbb3ef0b7e9e664afc6fe17bf2ed7f8b083
4
+ data.tar.gz: d97592afae4bb20e1bc0550275ae35866ab35c46
5
5
  SHA512:
6
- metadata.gz: 9e2940ee12917db050ce6b5cdaa9c951c8a4d92d54d5c1be8a868dd6695681ba006f1f4bfa711b0837deab1e9ac3eaccc8c512af3531420d925f82ce922bd853
7
- data.tar.gz: d319431cc1f5f7f357602485b972bb1d66deff5639d4a327efb6f2b1790023d9e915dd97692f7a647eb23ed7e9e4e686c0a9eb235aeb4a9fca5be0a4730bc850
6
+ metadata.gz: b07368c741370d224b0027fecf4dddd63d9dcf87785f0ff3c2eb5e2d9c819da7cfdc6b8c4f6178252379816f751e0d6a0022c091d1d005d1b4d911ada29c4bcd
7
+ data.tar.gz: 259753ebbadb4e6e6c0c49819e68b5f78b250e1074b77dd459cf39788f6882a83e513cf95ace9ff9b764f338a848c43fa2a3b94e7b18663aa0a58068b803d45c
@@ -1,3 +1,3 @@
1
1
  module CredStash
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.0"
3
3
  end
data/lib/cred_stash.rb CHANGED
@@ -1,36 +1,127 @@
1
1
  require 'aws-sdk'
2
+
2
3
  module CredStash
3
- def self.get(name)
4
- dynamodb = Aws::DynamoDB::Client.new
5
- res = dynamodb.query(
6
- table_name: 'credential-store',
7
- limit: 1,
8
- consistent_read: true,
9
- scan_index_forward: false,
10
- key_condition_expression: "#name = :name",
11
- expression_attribute_names: { "#name" => "name"},
12
- expression_attribute_values: { ":name" => name }
13
- )
14
- material = res.items.first
15
- data = Base64.decode64(material["key"])
16
- contents = Base64.decode64(material["contents"])
17
-
18
- kms = Aws::KMS::Client.new
19
- kms_res = kms.decrypt(ciphertext_blob: data)
20
-
21
- key = kms_res.plaintext[0..32]
22
- hmackey = kms_res.plaintext[32..-1]
23
-
24
- unless OpenSSL::HMAC.hexdigest("sha256", hmackey, contents) == material["hmac"]
25
- raise "invalid"
4
+ class << self
5
+ def get(name)
6
+ dynamodb = Aws::DynamoDB::Client.new
7
+ res = dynamodb.query(
8
+ table_name: 'credential-store',
9
+ limit: 1,
10
+ consistent_read: true,
11
+ scan_index_forward: false,
12
+ key_condition_expression: "#name = :name",
13
+ expression_attribute_names: { "#name" => "name"},
14
+ expression_attribute_values: { ":name" => name }
15
+ )
16
+ material = res.items.first
17
+ data = Base64.decode64(material["key"])
18
+ contents = Base64.decode64(material["contents"])
19
+
20
+ kms = Aws::KMS::Client.new
21
+ kms_res = kms.decrypt(ciphertext_blob: data)
22
+
23
+ key = kms_res.plaintext[0..32]
24
+ hmackey = kms_res.plaintext[32..-1]
25
+
26
+ unless OpenSSL::HMAC.hexdigest("sha256", hmackey, contents) == material["hmac"]
27
+ raise "invalid"
28
+ end
29
+
30
+ cipher = OpenSSL::Cipher::AES.new(256, "CTR")
31
+ cipher.decrypt
32
+ cipher.key = key
33
+ # FIXME It is better to generate and store initial counter
34
+ cipher.iv = %w(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1).map(&:hex).pack('C' * 16)
35
+ value = cipher.update(contents) + cipher.final
36
+ value.force_encoding("UTF-8")
37
+ end
38
+
39
+ def put(name, value)
40
+ kms = Aws::KMS::Client.new
41
+ kms_res = kms.generate_data_key(key_id: 'alias/credstash', number_of_bytes: 64)
42
+ data_key = kms_res.plaintext[0..32]
43
+ hmac_key = kms_res.plaintext[32..-1]
44
+ wrapped_key = kms_res.ciphertext_blob
45
+
46
+ cipher = OpenSSL::Cipher::AES.new(256, "CTR")
47
+ cipher.encrypt
48
+ cipher.key = data_key
49
+ # FIXME It is better to generate and store initial counter
50
+ cipher.iv = %w(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1).map(&:hex).pack('C' * 16)
51
+ contents = cipher.update(value) + cipher.final
52
+
53
+ hmac = OpenSSL::HMAC.hexdigest("sha256", hmac_key, contents)
54
+
55
+ version = get_highest_version(name) + 1
56
+
57
+ dynamodb = Aws::DynamoDB::Client.new
58
+ dynamodb.put_item(
59
+ table_name: 'credential-store',
60
+ item: {
61
+ name: name,
62
+ version: "%019d" % version,
63
+ key: Base64.encode64(wrapped_key),
64
+ contents: Base64.encode64(contents),
65
+ hmac: hmac
66
+ },
67
+ condition_expression: "attribute_not_exists(#name)",
68
+ expression_attribute_names: { "#name" => "name" },
69
+ )
70
+ end
71
+
72
+ def list
73
+ dynamodb = Aws::DynamoDB::Client.new
74
+ res = dynamodb.scan(
75
+ table_name: 'credential-store',
76
+ projection_expression: '#name, version',
77
+ expression_attribute_names: { "#name" => "name" },
78
+ )
79
+ res.items.inject({}) {|h, i| h[i['name']] = i['version']; h }
80
+ end
81
+
82
+ def delete(name)
83
+ dynamodb = Aws::DynamoDB::Client.new
84
+ res = dynamodb.query(
85
+ table_name: 'credential-store',
86
+ consistent_read: true,
87
+ key_condition_expression: "#name = :name",
88
+ expression_attribute_names: { "#name" => "name"},
89
+ expression_attribute_values: { ":name" => name }
90
+ )
91
+ # TODO needs delete target version option
92
+
93
+ item = res.items.first
94
+ dynamodb.delete_item(
95
+ table_name: 'credential-store',
96
+ key: {
97
+ name: item['name'],
98
+ version: item['version'],
99
+ }
100
+ )
26
101
  end
27
102
 
28
- cipher = OpenSSL::Cipher::AES.new(256, "CTR")
29
- cipher.decrypt
30
- cipher.key = key
31
- # FIXME It is better to generate and store initial counter
32
- cipher.iv = %w(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1).map(&:hex).pack('C' * 16)
33
- value = cipher.update(contents) + cipher.final
34
- value.force_encoding("UTF-8")
103
+ private
104
+
105
+ def get_highest_version(name)
106
+ dynamodb = Aws::DynamoDB::Client.new
107
+ res = dynamodb.query(
108
+ table_name: 'credential-store',
109
+ limit: 1,
110
+ consistent_read: true,
111
+ scan_index_forward: false,
112
+ key_condition_expression: "#name = :name",
113
+ expression_attribute_names: { "#name" => "name"},
114
+ expression_attribute_values: { ":name" => name },
115
+ projection_expression: 'version',
116
+ )
117
+
118
+ item = res.items.first
119
+
120
+ if item
121
+ item['version'].to_i
122
+ else
123
+ 0
124
+ end
125
+ end
35
126
  end
36
127
  end
data/rcredstash.gemspec CHANGED
@@ -8,6 +8,7 @@ Gem::Specification.new do |spec|
8
8
  spec.version = CredStash::VERSION
9
9
  spec.authors = ["adorechic"]
10
10
  spec.email = ["adorechic@gmail.com"]
11
+ spec.homepage = 'https://github.com/adorechic/rcredstash'
11
12
 
12
13
  spec.summary = %q{A Ruby port of CredStash}
13
14
  spec.description = %q{A Ruby port of CredStash}
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rcredstash
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - adorechic
@@ -88,7 +88,7 @@ files:
88
88
  - lib/rcredstash.rb
89
89
  - lib/rcredstash/version.rb
90
90
  - rcredstash.gemspec
91
- homepage:
91
+ homepage: https://github.com/adorechic/rcredstash
92
92
  licenses:
93
93
  - MIT
94
94
  metadata: {}