vault 0.6.0 → 0.7.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: 7c5b5358811dba9b5864bc118f19b2cb0c9b7925
4
- data.tar.gz: 41acb15b4a2148910f3c7fb8a01f7b51ce31e8aa
3
+ metadata.gz: 59a8ecc9e18c8112104e721f65e10cd56377803c
4
+ data.tar.gz: 28937a7a2360736b70cbae0f53c7103659a6ade0
5
5
  SHA512:
6
- metadata.gz: d6ec85927a497e7dcef985d8b32b59db6c5169c1c95820e311c3f3c6617c893e520c592b411806cf81a18d03d5a1dfab9988fb319a43330a4137d18dee7b61d0
7
- data.tar.gz: 787597e6f6315e2620c766d5f83e625f520401399221bc0774d9f76b6a08d342baea5fe09d061fa6dc892876167af750800b7660dc6afff99abb15b025d6c33d
6
+ metadata.gz: 91b7a092f7dc019da3b410c744351686f146bd8c72d57f1a096f20e107df19ec9ef34b36125131d993d8539899713cdd014cfc98ac6b7e69a1f64729f1f982fb
7
+ data.tar.gz: 292bfa0003747c1e02cbe6ab3332e6a05b449db6d4f812d440864927f7c4f3b3dcd6ace36adc7574e9ac9849a32091c43d0b236765ed03e70c178a266677d961
@@ -3,11 +3,10 @@ cache: bundler
3
3
  sudo: false
4
4
 
5
5
  env:
6
+ - VAULT_VERSION=0.6.2
6
7
  - VAULT_VERSION=0.6.1
7
8
  - VAULT_VERSION=0.6.0
8
9
  - VAULT_VERSION=0.5.3
9
- - VAULT_VERSION=0.4.1
10
- - VAULT_VERSION=0.3.1
11
10
 
12
11
  before_install:
13
12
  - wget -O vault.zip -q https://releases.hashicorp.com/vault/${VAULT_VERSION}/vault_${VAULT_VERSION}_linux_amd64.zip
@@ -1,6 +1,22 @@
1
1
  # Vault Ruby Changelog
2
2
 
3
- ## v0.6.0.dev (Unreleased)
3
+ ## v0.7.0 (October 18, 2016)
4
+
5
+ DEPRECATIONS
6
+
7
+ - Vault versions older than 0.5.3 are no longer tested
8
+
9
+ NEW FEATURES
10
+
11
+ - Add support for AppRole
12
+ - Expose the auth/tune API
13
+ - Add support for leader step down
14
+ - Use persistent connections to Vault to speed up requests
15
+ - Add support for a custom ssl certificate store
16
+
17
+ BUG FIXES
18
+
19
+ - Allow for spaces in secret names properly
4
20
 
5
21
  ## v0.6.0 (August 30, 2016)
6
22
 
@@ -1,5 +1,6 @@
1
1
  module Vault
2
2
  module API
3
+ require_relative "api/approle"
3
4
  require_relative "api/auth_token"
4
5
  require_relative "api/auth_tls"
5
6
  require_relative "api/auth"
@@ -0,0 +1,218 @@
1
+ require "json"
2
+
3
+ require_relative "secret"
4
+ require_relative "../client"
5
+ require_relative "../request"
6
+ require_relative "../response"
7
+
8
+ module Vault
9
+ class Client
10
+ # A proxy to the {AppRole} methods.
11
+ # @return [AppRole]
12
+ def approle
13
+ @approle ||= AppRole.new(self)
14
+ end
15
+ end
16
+
17
+ class AppRole < Request
18
+ # Creates a new AppRole or update an existing AppRole with the given name
19
+ # and attributes.
20
+ #
21
+ # @example
22
+ # Vault.approle.set_role("testrole", {
23
+ # secret_id_ttl: "10m",
24
+ # token_ttl: "20m",
25
+ # policies: "default",
26
+ # period: 3600,
27
+ # }) #=> true
28
+ #
29
+ # @param [String] name
30
+ # The name of the AppRole
31
+ # @param [Hash] options
32
+ # @option options [Boolean] :bind_secret_id
33
+ # Require secret_id to be presented when logging in using this AppRole.
34
+ # @option options [String] :bound_cidr_list
35
+ # Comma-separated list of CIDR blocks. Specifies blocks of IP addresses
36
+ # which can perform the login operation.
37
+ # @option options [String] :policies
38
+ # Comma-separated list of policies set on tokens issued via this AppRole.
39
+ # @option options [String] :secret_id_num_uses
40
+ # Number of times any particular SecretID can be used to fetch a token
41
+ # from this AppRole, after which the SecretID will expire.
42
+ # @option options [Fixnum, String] :secret_id_ttl
43
+ # The number of seconds or a golang-formatted timestamp like "60m" after
44
+ # which any SecretID expires.
45
+ # @option options [Fixnum, String] :token_ttl
46
+ # The number of seconds or a golang-formatted timestamp like "60m" to set
47
+ # as the TTL for issued tokens and at renewal time.
48
+ # @option options [Fixnum, String] :token_max_ttl
49
+ # The number of seconds or a golang-formatted timestamp like "60m" after
50
+ # which the issued token can no longer be renewed.
51
+ # @option options [Fixnum, String] :period
52
+ # The number of seconds or a golang-formatted timestamp like "60m".
53
+ # If set, the token generated using this AppRole is a periodic token.
54
+ # So long as it is renewed it never expires, but the TTL set on the token
55
+ # at each renewal is fixed to the value specified here. If this value is
56
+ # modified, the token will pick up the new value at its next renewal.
57
+ #
58
+ # @return [true]
59
+ def set_role(name, options = {})
60
+ headers = extract_headers!(options)
61
+ client.post("/v1/auth/approle/role/#{encode_path(name)}", JSON.fast_generate(options), headers)
62
+ return true
63
+ end
64
+
65
+ # Gets the AppRole by the given name. If an AppRole does not exist by that
66
+ # name, +nil+ is returned.
67
+ #
68
+ # @example
69
+ # Vault.approle.role("testrole") #=> #<Vault::Secret lease_id="...">
70
+ #
71
+ # @return [Secret, nil]
72
+ def role(name)
73
+ json = client.get("/v1/auth/approle/role/#{encode_path(name)}")
74
+ return Secret.decode(json)
75
+ rescue HTTPError => e
76
+ return nil if e.code == 404
77
+ raise
78
+ end
79
+
80
+ # Gets the list of AppRoles in vault auth backend.
81
+ #
82
+ # @example
83
+ # Vault.approle.roles #=> ["testrole"]
84
+ #
85
+ # @return [Array<String>]
86
+ def roles(options = {})
87
+ headers = extract_headers!(options)
88
+ json = client.list("/v1/auth/approle/role", options, headers)
89
+ return Secret.decode(json).data[:keys] || []
90
+ rescue HTTPError => e
91
+ return [] if e.code == 404
92
+ raise
93
+ end
94
+
95
+ # Reads the RoleID of an existing AppRole. If an AppRole does not exist by
96
+ # that name, +nil+ is returned.
97
+ #
98
+ # @example
99
+ # Vault.approle.role_id("testrole") #=> #<Vault::Secret lease_id="...">
100
+ #
101
+ # @return [Secret, nil]
102
+ def role_id(name)
103
+ json = client.get("/v1/auth/approle/role/#{encode_path(name)}/role-id")
104
+ return Secret.decode(json).data[:role_id]
105
+ rescue HTTPError => e
106
+ return nil if e.code == 404
107
+ raise
108
+ end
109
+
110
+ # Updates the RoleID of an existing AppRole to a custom value.
111
+ #
112
+ # @example
113
+ # Vault.approle.set_role_id("testrole") #=> true
114
+ #
115
+ # @return [true]
116
+ def set_role_id(name, role_id)
117
+ options = { role_id: role_id }
118
+ client.post("/v1/auth/approle/role/#{encode_path(name)}/role-id", JSON.fast_generate(options))
119
+ return true
120
+ end
121
+
122
+ # Deletes the AppRole with the given name. If an AppRole does not exist,
123
+ # vault will not return an error.
124
+ #
125
+ # @example
126
+ # Vault.approle.delete_role("testrole") #=> true
127
+ #
128
+ # @param [String] name
129
+ # the name of the certificate
130
+ def delete_role(name)
131
+ client.delete("/v1/auth/approle/role/#{encode_path(name)}")
132
+ return true
133
+ end
134
+
135
+ # Generates and issues a new SecretID on an existing AppRole.
136
+ #
137
+ # @example Generate a new SecretID
138
+ # result = Vault.approle.create_secret_id("testrole") #=> #<Vault::Secret lease_id="...">
139
+ # result.data[:secret_id] #=> "841771dc-11c9-bbc7-bcac-6a3945a69cd9"
140
+ #
141
+ # @example Assign a custom SecretID
142
+ # result = Vault.approle.create_secret_id("testrole", {
143
+ # secret_id: "testsecretid"
144
+ # }) #=> #<Vault::Secret lease_id="...">
145
+ # result.data[:secret_id] #=> "testsecretid"
146
+ #
147
+ # @param [String] role_name
148
+ # The name of the AppRole
149
+ # @param [Hash] options
150
+ # @option options [String] :secret_id
151
+ # SecretID to be attached to the Role. If not set, then the new SecretID
152
+ # will be generated
153
+ # @option options [Hash<String, String>] :metadata
154
+ # Metadata to be tied to the SecretID. This should be a JSON-formatted
155
+ # string containing the metadata in key-value pairs. It will be set on
156
+ # tokens issued with this SecretID, and is logged in audit logs in
157
+ # plaintext.
158
+ #
159
+ # @return [true]
160
+ def create_secret_id(role_name, options = {})
161
+ headers = extract_headers!(options)
162
+ if options[:secret_id]
163
+ json = client.post("/v1/auth/approle/role/#{encode_path(role_name)}/custom-secret-id", JSON.fast_generate(options), headers)
164
+ else
165
+ json = client.post("/v1/auth/approle/role/#{encode_path(role_name)}/secret-id", JSON.fast_generate(options), headers)
166
+ end
167
+ return Secret.decode(json)
168
+ end
169
+
170
+ # Reads out the properties of a SecretID assigned to an AppRole.
171
+ # If the specified SecretID don't exist, +nil+ is returned.
172
+ #
173
+ # @example
174
+ # Vault.approle.role("testrole", "841771dc-11c9-...") #=> #<Vault::Secret lease_id="...">
175
+ #
176
+ # @param [String] role_name
177
+ # The name of the AppRole
178
+ # @param [String] secret_id
179
+ # SecretID belonging to AppRole
180
+ #
181
+ # @return [Secret, nil]
182
+ def secret_id(role_name, secret_id)
183
+ opts = { secret_id: secret_id }
184
+ json = client.post("/v1/auth/approle/role/#{encode_path(role_name)}/secret-id/lookup", JSON.fast_generate(opts), {})
185
+ return nil unless json
186
+ return Secret.decode(json)
187
+ rescue HTTPError => e
188
+ if e.code == 404 || e.code == 405
189
+ begin
190
+ json = client.get("/v1/auth/approle/role/#{encode_path(role_name)}/secret-id/#{encode_path(secret_id)}")
191
+ return Secret.decode(json)
192
+ rescue HTTPError => e
193
+ return nil if e.code == 404
194
+ raise e
195
+ end
196
+ end
197
+
198
+ raise
199
+ end
200
+
201
+ # Lists the accessors of all the SecretIDs issued against the AppRole.
202
+ # This includes the accessors for "custom" SecretIDs as well. If there are
203
+ # no SecretIDs against this role, an empty array will be returned.
204
+ #
205
+ # @example
206
+ # Vault.approle.secret_ids("testrole") #=> ["ce102d2a-...", "a1c8dee4-..."]
207
+ #
208
+ # @return [Array<String>]
209
+ def secret_id_accessors(role_name, options = {})
210
+ headers = extract_headers!(options)
211
+ json = client.list("/v1/auth/approle/role/#{encode_path(role_name)}/secret-id", options, headers)
212
+ return Secret.decode(json).data[:keys] || []
213
+ rescue HTTPError => e
214
+ return [] if e.code == 404
215
+ raise
216
+ end
217
+ end
218
+ end
@@ -74,6 +74,30 @@ module Vault
74
74
  return secret
75
75
  end
76
76
 
77
+ # Authenticate via the "approle" authentication method. If authentication is
78
+ # successful, the resulting token will be stored on the client and used for
79
+ # future requests.
80
+ #
81
+ # @example
82
+ # Vault.auth.approle(
83
+ # "db02de05-fa39-4855-059b-67221c5c2f63",
84
+ # "6a174c20-f6de-a53c-74d2-6018fcceff64",
85
+ # ) #=> #<Vault::Secret lease_id="">
86
+ #
87
+ # @param [String] role_id
88
+ # @param [String] secret_id (default: nil)
89
+ # It is required when `bind_secret_id` is enabled for the specified role_id
90
+ #
91
+ # @return [Secret]
92
+ def approle(role_id, secret_id=nil)
93
+ payload = { role_id: role_id }
94
+ payload[:secret_id] = secret_id if secret_id
95
+ json = client.post("/v1/auth/approle/login", JSON.fast_generate(payload))
96
+ secret = Secret.decode(json)
97
+ client.token = secret.auth.client_token
98
+ return secret
99
+ end
100
+
77
101
  # Authenticate via the "userpass" authentication method. If authentication
78
102
  # is successful, the resulting token will be stored on the client and used
79
103
  # for future requests.
@@ -93,7 +117,7 @@ module Vault
93
117
  # @return [Secret]
94
118
  def userpass(username, password, options = {})
95
119
  payload = { password: password }.merge(options)
96
- json = client.post("/v1/auth/userpass/login/#{CGI.escape(username)}", JSON.fast_generate(payload))
120
+ json = client.post("/v1/auth/userpass/login/#{encode_path(username)}", JSON.fast_generate(payload))
97
121
  secret = Secret.decode(json)
98
122
  client.token = secret.auth.client_token
99
123
  return secret
@@ -115,7 +139,7 @@ module Vault
115
139
  # @return [Secret]
116
140
  def ldap(username, password, options = {})
117
141
  payload = { password: password }.merge(options)
118
- json = client.post("/v1/auth/ldap/login/#{CGI.escape(username)}", JSON.fast_generate(payload))
142
+ json = client.post("/v1/auth/ldap/login/#{encode_path(username)}", JSON.fast_generate(payload))
119
143
  secret = Secret.decode(json)
120
144
  client.token = secret.auth.client_token
121
145
  return secret
@@ -42,7 +42,7 @@ module Vault
42
42
  # @return [true]
43
43
  def set_certificate(name, options = {})
44
44
  headers = extract_headers!(options)
45
- client.post("/v1/auth/cert/certs/#{CGI.escape(name)}", JSON.fast_generate(options), headers)
45
+ client.post("/v1/auth/cert/certs/#{encode_path(name)}", JSON.fast_generate(options), headers)
46
46
  return true
47
47
  end
48
48
 
@@ -54,7 +54,7 @@ module Vault
54
54
  #
55
55
  # @return [Secret, nil]
56
56
  def certificate(name)
57
- json = client.get("/v1/auth/cert/certs/#{CGI.escape(name)}")
57
+ json = client.get("/v1/auth/cert/certs/#{encode_path(name)}")
58
58
  return Secret.decode(json)
59
59
  rescue HTTPError => e
60
60
  return nil if e.code == 404
@@ -85,7 +85,7 @@ module Vault
85
85
  # @param [String] name
86
86
  # the name of the certificate
87
87
  def delete_certificate(name)
88
- client.delete("/v1/auth/cert/certs/#{CGI.escape(name)}")
88
+ client.delete("/v1/auth/cert/certs/#{encode_path(name)}")
89
89
  return true
90
90
  end
91
91
  end
@@ -95,7 +95,7 @@ module Vault
95
95
  # @return [Secret]
96
96
  def create_with_role(name, options = {})
97
97
  headers = extract_headers!(options)
98
- json = client.post("/v1/auth/token/create/#{CGI.escape(name)}", JSON.fast_generate(options), headers)
98
+ json = client.post("/v1/auth/token/create/#{encode_path(name)}", JSON.fast_generate(options), headers)
99
99
  return Secret.decode(json)
100
100
  end
101
101
 
@@ -108,7 +108,7 @@ module Vault
108
108
  #
109
109
  # @return [Secret]
110
110
  def lookup(token)
111
- json = client.get("/v1/auth/token/lookup/#{CGI.escape(token)}")
111
+ json = client.get("/v1/auth/token/lookup/#{encode_path(token)}")
112
112
  return Secret.decode(json)
113
113
  end
114
114
 
@@ -26,7 +26,7 @@ module Vault
26
26
  #
27
27
  # @return [Help]
28
28
  def help(path)
29
- json = self.get("/v1/#{CGI.escape(path)}", help: 1)
29
+ json = self.get("/v1/#{EncodePath.encode_path(path)}", help: 1)
30
30
  return Help.decode(json)
31
31
  end
32
32
  end
@@ -25,7 +25,7 @@ module Vault
25
25
  # @return [Array<String>]
26
26
  def list(path, options = {})
27
27
  headers = extract_headers!(options)
28
- json = client.list("/v1/#{CGI.escape(path)}", {}, headers)
28
+ json = client.list("/v1/#{encode_path(path)}", {}, headers)
29
29
  json[:data][:keys] || []
30
30
  rescue HTTPError => e
31
31
  return [] if e.code == 404
@@ -44,7 +44,7 @@ module Vault
44
44
  # @return [Secret, nil]
45
45
  def read(path, options = {})
46
46
  headers = extract_headers!(options)
47
- json = client.get("/v1/#{CGI.escape(path)}", {}, headers)
47
+ json = client.get("/v1/#{encode_path(path)}", {}, headers)
48
48
  return Secret.decode(json)
49
49
  rescue HTTPError => e
50
50
  return nil if e.code == 404
@@ -65,7 +65,7 @@ module Vault
65
65
  # @return [Secret]
66
66
  def write(path, data = {}, options = {})
67
67
  headers = extract_headers!(options)
68
- json = client.put("/v1/#{CGI.escape(path)}", JSON.fast_generate(data), headers)
68
+ json = client.put("/v1/#{encode_path(path)}", JSON.fast_generate(data), headers)
69
69
  if json.nil?
70
70
  return true
71
71
  else
@@ -84,7 +84,7 @@ module Vault
84
84
  #
85
85
  # @return [true]
86
86
  def delete(path)
87
- client.delete("/v1/#{CGI.escape(path)}")
87
+ client.delete("/v1/#{encode_path(path)}")
88
88
  return true
89
89
  end
90
90
 
@@ -51,7 +51,7 @@ module Vault
51
51
  #
52
52
  # @return [true]
53
53
  def enable_audit(path, type, description, options = {})
54
- client.put("/v1/sys/audit/#{CGI.escape(path)}", JSON.fast_generate(
54
+ client.put("/v1/sys/audit/#{encode_path(path)}", JSON.fast_generate(
55
55
  type: type,
56
56
  description: description,
57
57
  options: options,
@@ -67,7 +67,7 @@ module Vault
67
67
  #
68
68
  # @return [true]
69
69
  def disable_audit(path)
70
- client.delete("/v1/sys/audit/#{CGI.escape(path)}")
70
+ client.delete("/v1/sys/audit/#{encode_path(path)}")
71
71
  return true
72
72
  end
73
73
  end
@@ -13,6 +13,18 @@ module Vault
13
13
  field :type
14
14
  end
15
15
 
16
+ class AuthConfig < Response
17
+ # @!attribute [r] default_lease_ttl
18
+ # The default time-to-live.
19
+ # @return [String]
20
+ field :default_lease_ttl
21
+
22
+ # @!attribute [r] max_lease_ttl
23
+ # The maximum time-to-live.
24
+ # @return [String]
25
+ field :max_lease_ttl
26
+ end
27
+
16
28
  class Sys
17
29
  # List all auths in Vault.
18
30
  #
@@ -45,7 +57,7 @@ module Vault
45
57
  payload = { type: type }
46
58
  payload[:description] = description if !description.nil?
47
59
 
48
- client.post("/v1/sys/auth/#{CGI.escape(path)}", JSON.fast_generate(payload))
60
+ client.post("/v1/sys/auth/#{encode_path(path)}", JSON.fast_generate(payload))
49
61
  return true
50
62
  end
51
63
 
@@ -60,8 +72,45 @@ module Vault
60
72
  #
61
73
  # @return [true]
62
74
  def disable_auth(path)
63
- client.delete("/v1/sys/auth/#{CGI.escape(path)}")
75
+ client.delete("/v1/sys/auth/#{encode_path(path)}")
64
76
  return true
65
77
  end
78
+
79
+ # Read the given auth path's configuration.
80
+ #
81
+ # @example
82
+ # Vault.sys.auth_tune("github") #=> #<Vault::AuthConfig "default_lease_ttl"=3600, "max_lease_ttl"=7200>
83
+ #
84
+ # @param [String] path
85
+ # the path to retrieve configuration for
86
+ #
87
+ # @return [AuthConfig]
88
+ # configuration of the given auth path
89
+ def auth_tune(path)
90
+ json = client.get("/v1/sys/auth/#{encode_path(path)}/tune")
91
+ return AuthConfig.decode(json)
92
+ rescue HTTPError => e
93
+ return nil if e.code == 404
94
+ raise
95
+ end
96
+
97
+ # Write the given auth path's configuration.
98
+ #
99
+ # @example
100
+ # Vault.sys.auth_tune("github", "default_lease_ttl" => 600, "max_lease_ttl" => 1200 ) #=> true
101
+ #
102
+ # @param [String] path
103
+ # the path to retrieve configuration for
104
+ #
105
+ # @return [AuthConfig]
106
+ # configuration of the given auth path
107
+ def put_auth_tune(path, config = {})
108
+ json = client.put("/v1/sys/auth/#{encode_path(path)}/tune", JSON.fast_generate(config))
109
+ if json.nil?
110
+ return true
111
+ else
112
+ return Secret.decode(json)
113
+ end
114
+ end
66
115
  end
67
116
  end