vault_ruby_client 0.18.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +287 -0
- data/LICENSE +364 -0
- data/README.md +223 -0
- data/lib/vault/api/approle.rb +221 -0
- data/lib/vault/api/auth.rb +324 -0
- data/lib/vault/api/auth_tls.rb +95 -0
- data/lib/vault/api/auth_token.rb +245 -0
- data/lib/vault/api/help.rb +36 -0
- data/lib/vault/api/kv.rb +230 -0
- data/lib/vault/api/logical.rb +153 -0
- data/lib/vault/api/secret.rb +171 -0
- data/lib/vault/api/sys/audit.rb +94 -0
- data/lib/vault/api/sys/auth.rb +119 -0
- data/lib/vault/api/sys/health.rb +66 -0
- data/lib/vault/api/sys/init.rb +86 -0
- data/lib/vault/api/sys/leader.rb +51 -0
- data/lib/vault/api/sys/lease.rb +52 -0
- data/lib/vault/api/sys/mount.rb +165 -0
- data/lib/vault/api/sys/namespace.rb +86 -0
- data/lib/vault/api/sys/policy.rb +95 -0
- data/lib/vault/api/sys/quota.rb +110 -0
- data/lib/vault/api/sys/seal.rb +84 -0
- data/lib/vault/api/sys.rb +30 -0
- data/lib/vault/api/transform/alphabet.rb +46 -0
- data/lib/vault/api/transform/role.rb +45 -0
- data/lib/vault/api/transform/template.rb +57 -0
- data/lib/vault/api/transform/transformation.rb +64 -0
- data/lib/vault/api/transform.rb +32 -0
- data/lib/vault/api.rb +17 -0
- data/lib/vault/client.rb +460 -0
- data/lib/vault/configurable.rb +53 -0
- data/lib/vault/defaults.rb +218 -0
- data/lib/vault/encode.rb +22 -0
- data/lib/vault/errors.rb +87 -0
- data/lib/vault/persistent/connection.rb +45 -0
- data/lib/vault/persistent/pool.rb +51 -0
- data/lib/vault/persistent/timed_stack_multi.rb +73 -0
- data/lib/vault/persistent.rb +1161 -0
- data/lib/vault/request.rb +47 -0
- data/lib/vault/response.rb +92 -0
- data/lib/vault/vendor/connection_pool/timed_stack.rb +181 -0
- data/lib/vault/vendor/connection_pool/version.rb +8 -0
- data/lib/vault/vendor/connection_pool.rb +153 -0
- data/lib/vault/version.rb +6 -0
- data/lib/vault_ruby_client.rb +53 -0
- metadata +158 -0
data/lib/vault/api/kv.rb
ADDED
@@ -0,0 +1,230 @@
|
|
1
|
+
# Copyright (c) HashiCorp, Inc.
|
2
|
+
# SPDX-License-Identifier: MPL-2.0
|
3
|
+
|
4
|
+
require_relative "secret"
|
5
|
+
require_relative "../client"
|
6
|
+
require_relative "../request"
|
7
|
+
require_relative "../response"
|
8
|
+
|
9
|
+
module Vault
|
10
|
+
class Client
|
11
|
+
# A proxy to the {KV} methods.
|
12
|
+
# @return [KV]
|
13
|
+
def kv(mount)
|
14
|
+
KV.new(self, mount)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class KV < Request
|
19
|
+
attr_reader :mount
|
20
|
+
|
21
|
+
def initialize(client, mount)
|
22
|
+
super client
|
23
|
+
|
24
|
+
@mount = mount
|
25
|
+
end
|
26
|
+
|
27
|
+
# List the names of secrets at the given path, if the path supports
|
28
|
+
# listing. If the the path does not exist, an empty array will be returned.
|
29
|
+
#
|
30
|
+
# @example
|
31
|
+
# Vault.kv("secret").list("foo") #=> ["bar", "baz"]
|
32
|
+
#
|
33
|
+
# @param [String] path
|
34
|
+
# the path to list
|
35
|
+
#
|
36
|
+
# @return [Array<String>]
|
37
|
+
def list(path = "", options = {})
|
38
|
+
headers = extract_headers!(options)
|
39
|
+
json = client.list("/v1/#{mount}/metadata/#{encode_path(path)}", {}, headers)
|
40
|
+
json[:data][:keys] || []
|
41
|
+
rescue HTTPError => e
|
42
|
+
return [] if e.code == 404
|
43
|
+
raise
|
44
|
+
end
|
45
|
+
|
46
|
+
# Read the secret at the given path. If the secret does not exist, +nil+
|
47
|
+
# will be returned. The latest version is returned by default, but you
|
48
|
+
# can request a specific version.
|
49
|
+
#
|
50
|
+
# @example
|
51
|
+
# Vault.kv("secret").read("password") #=> #<Vault::Secret lease_id="">
|
52
|
+
#
|
53
|
+
# @param [String] path
|
54
|
+
# the path to read
|
55
|
+
# @param [Integer] version
|
56
|
+
# the version of the secret
|
57
|
+
#
|
58
|
+
# @return [Secret, nil]
|
59
|
+
def read(path, version = nil, options = {})
|
60
|
+
headers = extract_headers!(options)
|
61
|
+
params = {}
|
62
|
+
params[:version] = version unless version.nil?
|
63
|
+
|
64
|
+
json = client.get("/v1/#{mount}/data/#{encode_path(path)}", params, headers)
|
65
|
+
return Secret.decode(json[:data])
|
66
|
+
rescue HTTPError => e
|
67
|
+
return nil if e.code == 404
|
68
|
+
raise
|
69
|
+
end
|
70
|
+
|
71
|
+
# Read the metadata of a secret at the given path. If the secret does not
|
72
|
+
# exist, nil will be returned.
|
73
|
+
#
|
74
|
+
# @example
|
75
|
+
# Vault.kv("secret").read_metadata("password") => {...}
|
76
|
+
#
|
77
|
+
# @param [String] path
|
78
|
+
# the path to read
|
79
|
+
#
|
80
|
+
# @return [Hash, nil]
|
81
|
+
def read_metadata(path)
|
82
|
+
client.get("/v1/#{mount}/metadata/#{encode_path(path)}")[:data]
|
83
|
+
rescue HTTPError => e
|
84
|
+
return nil if e.code == 404
|
85
|
+
raise
|
86
|
+
end
|
87
|
+
|
88
|
+
# Write the secret at the given path with the given data. Note that the
|
89
|
+
# data must be a {Hash}!
|
90
|
+
#
|
91
|
+
# @example
|
92
|
+
# Vault.logical.write("secret/password", value: "secret") #=> #<Vault::Secret lease_id="">
|
93
|
+
#
|
94
|
+
# @param [String] path
|
95
|
+
# the path to write
|
96
|
+
# @param [Hash] data
|
97
|
+
# the data to write
|
98
|
+
#
|
99
|
+
# @return [Secret]
|
100
|
+
def write(path, data = {}, options = {})
|
101
|
+
headers = extract_headers!(options)
|
102
|
+
json = client.post("/v1/#{mount}/data/#{encode_path(path)}", JSON.fast_generate(:data => data), headers)
|
103
|
+
if json.nil?
|
104
|
+
return true
|
105
|
+
else
|
106
|
+
return Secret.decode(json)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# Write the metadata of a secret at the given path. Note that the data must
|
111
|
+
# be a {Hash}.
|
112
|
+
#
|
113
|
+
# @example
|
114
|
+
# Vault.kv("secret").write_metadata("password", max_versions => 3)
|
115
|
+
#
|
116
|
+
# @param [String] path
|
117
|
+
# the path to write
|
118
|
+
# @param [Hash] metadata
|
119
|
+
# the metadata to write
|
120
|
+
#
|
121
|
+
# @return [true]
|
122
|
+
def write_metadata(path, metadata = {})
|
123
|
+
client.post("/v1/#{mount}/metadata/#{encode_path(path)}", JSON.fast_generate(metadata))
|
124
|
+
|
125
|
+
true
|
126
|
+
end
|
127
|
+
|
128
|
+
# Patch the metadata of a secret at the given path. Note that the data must
|
129
|
+
# be a {Hash}.
|
130
|
+
#
|
131
|
+
# @example
|
132
|
+
# Vault.kv("secret").patch_metadata("password", custom_metadata: { my_custom_key: "my_value" }, max_versions: 3)
|
133
|
+
#
|
134
|
+
# @param [String] path
|
135
|
+
# the path to patch
|
136
|
+
# @param [Hash] metadata
|
137
|
+
# the metadata to patch
|
138
|
+
#
|
139
|
+
# @return [true]
|
140
|
+
def patch_metadata(path, metadata = {}, options = {})
|
141
|
+
headers = extract_headers!(options)
|
142
|
+
headers["Content-Type"] = "application/merge-patch+json"
|
143
|
+
client.patch("/v1/#{mount}/metadata/#{encode_path(path)}", JSON.fast_generate(metadata), headers)
|
144
|
+
|
145
|
+
true
|
146
|
+
end
|
147
|
+
|
148
|
+
# Delete the secret at the given path. If the secret does not exist, vault
|
149
|
+
# will still return true.
|
150
|
+
#
|
151
|
+
# @example
|
152
|
+
# Vault.logical.delete("secret/password") #=> true
|
153
|
+
#
|
154
|
+
# @param [String] path
|
155
|
+
# the path to delete
|
156
|
+
#
|
157
|
+
# @return [true]
|
158
|
+
def delete(path)
|
159
|
+
client.delete("/v1/#{mount}/data/#{encode_path(path)}")
|
160
|
+
|
161
|
+
true
|
162
|
+
end
|
163
|
+
|
164
|
+
# Mark specific versions of a secret as deleted.
|
165
|
+
#
|
166
|
+
# @example
|
167
|
+
# Vault.kv("secret").delete_versions("password", [1, 2])
|
168
|
+
#
|
169
|
+
# @param [String] path
|
170
|
+
# the path to remove versions from
|
171
|
+
# @param [Array<Integer>] versions
|
172
|
+
# an array of versions to remove
|
173
|
+
#
|
174
|
+
# @return [true]
|
175
|
+
def delete_versions(path, versions)
|
176
|
+
client.post("/v1/#{mount}/delete/#{encode_path(path)}", JSON.fast_generate(versions: versions))
|
177
|
+
|
178
|
+
true
|
179
|
+
end
|
180
|
+
|
181
|
+
# Mark specific versions of a secret as active.
|
182
|
+
#
|
183
|
+
# @example
|
184
|
+
# Vault.kv("secret").undelete_versions("password", [1, 2])
|
185
|
+
#
|
186
|
+
# @param [String] path
|
187
|
+
# the path to enable versions for
|
188
|
+
# @param [Array<Integer>] versions
|
189
|
+
# an array of versions to mark as undeleted
|
190
|
+
#
|
191
|
+
# @return [true]
|
192
|
+
def undelete_versions(path, versions)
|
193
|
+
client.post("/v1/#{mount}/undelete/#{encode_path(path)}", JSON.fast_generate(versions: versions))
|
194
|
+
|
195
|
+
true
|
196
|
+
end
|
197
|
+
|
198
|
+
# Completely remove a secret and its metadata.
|
199
|
+
#
|
200
|
+
# @example
|
201
|
+
# Vault.kv("secret").destroy("password")
|
202
|
+
#
|
203
|
+
# @param [String] path
|
204
|
+
# the path to remove
|
205
|
+
#
|
206
|
+
# @return [true]
|
207
|
+
def destroy(path)
|
208
|
+
client.delete("/v1/#{mount}/metadata/#{encode_path(path)}")
|
209
|
+
|
210
|
+
true
|
211
|
+
end
|
212
|
+
|
213
|
+
# Completely remove specific versions of a secret.
|
214
|
+
#
|
215
|
+
# @example
|
216
|
+
# Vault.kv("secret").destroy_versions("password", [1, 2])
|
217
|
+
#
|
218
|
+
# @param [String] path
|
219
|
+
# the path to remove versions from
|
220
|
+
# @param [Array<Integer>] versions
|
221
|
+
# an array of versions to destroy
|
222
|
+
#
|
223
|
+
# @return [true]
|
224
|
+
def destroy_versions(path, versions)
|
225
|
+
client.post("/v1/#{mount}/destroy/#{encode_path(path)}", JSON.fast_generate(versions: versions))
|
226
|
+
|
227
|
+
true
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
@@ -0,0 +1,153 @@
|
|
1
|
+
# Copyright (c) HashiCorp, Inc.
|
2
|
+
# SPDX-License-Identifier: MPL-2.0
|
3
|
+
|
4
|
+
require_relative "secret"
|
5
|
+
require_relative "../client"
|
6
|
+
require_relative "../request"
|
7
|
+
require_relative "../response"
|
8
|
+
|
9
|
+
module Vault
|
10
|
+
class Client
|
11
|
+
# A proxy to the {Logical} methods.
|
12
|
+
# @return [Logical]
|
13
|
+
def logical
|
14
|
+
@logical ||= Logical.new(self)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class Logical < Request
|
19
|
+
# List the secrets at the given path, if the path supports listing. If the
|
20
|
+
# the path does not exist, an exception will be raised.
|
21
|
+
#
|
22
|
+
# @example
|
23
|
+
# Vault.logical.list("secret") #=> [#<Vault::Secret>, #<Vault::Secret>, ...]
|
24
|
+
#
|
25
|
+
# @param [String] path
|
26
|
+
# the path to list
|
27
|
+
#
|
28
|
+
# @return [Array<String>]
|
29
|
+
def list(path, options = {})
|
30
|
+
headers = extract_headers!(options)
|
31
|
+
json = client.list("/v1/#{encode_path(path)}", {}, headers)
|
32
|
+
json[:data][:keys] || []
|
33
|
+
rescue HTTPError => e
|
34
|
+
return [] if e.code == 404
|
35
|
+
raise
|
36
|
+
end
|
37
|
+
|
38
|
+
# Read the secret at the given path. If the secret does not exist, +nil+
|
39
|
+
# will be returned.
|
40
|
+
#
|
41
|
+
# @example
|
42
|
+
# Vault.logical.read("secret/password") #=> #<Vault::Secret lease_id="">
|
43
|
+
#
|
44
|
+
# @param [String] path
|
45
|
+
# the path to read
|
46
|
+
#
|
47
|
+
# @return [Secret, nil]
|
48
|
+
def read(path, options = {})
|
49
|
+
headers = extract_headers!(options)
|
50
|
+
json = client.get("/v1/#{encode_path(path)}", {}, headers)
|
51
|
+
return Secret.decode(json)
|
52
|
+
rescue HTTPError => e
|
53
|
+
return nil if e.code == 404
|
54
|
+
raise
|
55
|
+
end
|
56
|
+
|
57
|
+
# Write the secret at the given path with the given data. Note that the
|
58
|
+
# data must be a {Hash}!
|
59
|
+
#
|
60
|
+
# @example
|
61
|
+
# Vault.logical.write("secret/password", value: "secret") #=> #<Vault::Secret lease_id="">
|
62
|
+
#
|
63
|
+
# @param [String] path
|
64
|
+
# the path to write
|
65
|
+
# @param [Hash] data
|
66
|
+
# the data to write
|
67
|
+
#
|
68
|
+
# @return [Secret]
|
69
|
+
def write(path, data = {}, options = {})
|
70
|
+
headers = extract_headers!(options)
|
71
|
+
json = client.put("/v1/#{encode_path(path)}", JSON.fast_generate(data), headers)
|
72
|
+
if json.nil?
|
73
|
+
return true
|
74
|
+
else
|
75
|
+
return Secret.decode(json)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# Delete the secret at the given path. If the secret does not exist, vault
|
80
|
+
# will still return true.
|
81
|
+
#
|
82
|
+
# @example
|
83
|
+
# Vault.logical.delete("secret/password") #=> true
|
84
|
+
#
|
85
|
+
# @param [String] path
|
86
|
+
# the path to delete
|
87
|
+
#
|
88
|
+
# @return [true]
|
89
|
+
def delete(path)
|
90
|
+
client.delete("/v1/#{encode_path(path)}")
|
91
|
+
return true
|
92
|
+
end
|
93
|
+
|
94
|
+
# Unwrap the data stored against the given token. If the secret does not
|
95
|
+
# exist, `nil` will be returned.
|
96
|
+
#
|
97
|
+
# @example
|
98
|
+
# Vault.logical.unwrap("f363dba8-25a7-08c5-430c-00b2367124e6") #=> #<Vault::Secret lease_id="">
|
99
|
+
#
|
100
|
+
# @param [String] wrapper
|
101
|
+
# the token to use when unwrapping the value
|
102
|
+
#
|
103
|
+
# @return [Secret, nil]
|
104
|
+
def unwrap(wrapper)
|
105
|
+
client.with_token(wrapper) do |client|
|
106
|
+
json = client.get("/v1/cubbyhole/response")
|
107
|
+
secret = Secret.decode(json)
|
108
|
+
|
109
|
+
# If there is nothing in the cubbyhole, return early.
|
110
|
+
if secret.nil? || secret.data.nil? || secret.data[:response].nil?
|
111
|
+
return nil
|
112
|
+
end
|
113
|
+
|
114
|
+
# Extract the response and parse it into a new secret.
|
115
|
+
json = JSON.parse(secret.data[:response], symbolize_names: true)
|
116
|
+
secret = Secret.decode(json)
|
117
|
+
return secret
|
118
|
+
end
|
119
|
+
rescue HTTPError => e
|
120
|
+
return nil if e.code == 404
|
121
|
+
raise
|
122
|
+
end
|
123
|
+
|
124
|
+
# Unwrap a token in a wrapped response given the temporary token.
|
125
|
+
#
|
126
|
+
# @example
|
127
|
+
# Vault.logical.unwrap("f363dba8-25a7-08c5-430c-00b2367124e6") #=> "0f0f40fd-06ce-4af1-61cb-cdc12796f42b"
|
128
|
+
#
|
129
|
+
# @param [String, Secret] wrapper
|
130
|
+
# the token to unwrap
|
131
|
+
#
|
132
|
+
# @return [String, nil]
|
133
|
+
def unwrap_token(wrapper)
|
134
|
+
# If provided a secret, grab the token. This is really just to make the
|
135
|
+
# API a bit nicer.
|
136
|
+
if wrapper.is_a?(Secret)
|
137
|
+
wrapper = wrapper.wrap_info.token
|
138
|
+
end
|
139
|
+
|
140
|
+
# Unwrap
|
141
|
+
response = unwrap(wrapper)
|
142
|
+
|
143
|
+
# If nothing was there, return nil
|
144
|
+
if response.nil? || response.auth.nil?
|
145
|
+
return nil
|
146
|
+
end
|
147
|
+
|
148
|
+
return response.auth.client_token
|
149
|
+
rescue HTTPError => e
|
150
|
+
raise
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
# Copyright (c) HashiCorp, Inc.
|
2
|
+
# SPDX-License-Identifier: MPL-2.0
|
3
|
+
|
4
|
+
require "time"
|
5
|
+
|
6
|
+
require_relative "../response"
|
7
|
+
|
8
|
+
module Vault
|
9
|
+
# Secret is a representation of a secret from Vault. Almost all data returned
|
10
|
+
# from Vault is represented as a secret.
|
11
|
+
class Secret < Response
|
12
|
+
# @!attribute [r] auth
|
13
|
+
# Authentication information for this secret, if any. Most secrets will
|
14
|
+
# contain this field, but it may also be `nil`. When authenticating to
|
15
|
+
# Vault, the resulting Vault token will be included in this embedded
|
16
|
+
# field.
|
17
|
+
#
|
18
|
+
# @example Authenticating to Vault
|
19
|
+
# secret = Vault.auth.userpass("username", "password")
|
20
|
+
# secret.auth.client_token #=> "fdb29070-6379-70c9-ca3a-46152fb66de1"
|
21
|
+
#
|
22
|
+
# @return [SecretAuth, nil]
|
23
|
+
field :auth, load: ->(v) { SecretAuth.decode(v) }
|
24
|
+
|
25
|
+
# @!attribute [r] data
|
26
|
+
# Arbitrary data returned by the secret. The keys returned are dependent
|
27
|
+
# upon the request made. For more information on the names of the keys
|
28
|
+
# that may be returned, please see the Vault documentation.
|
29
|
+
#
|
30
|
+
# @example Reading data
|
31
|
+
# secret = Vault.auth.token("abcd1234")
|
32
|
+
# secret.data[:id] #=> "abcd1234"
|
33
|
+
# secret.data[:ttl] #=> 0
|
34
|
+
#
|
35
|
+
# @return [Hash<Symbol, Object>]
|
36
|
+
field :data, freeze: true
|
37
|
+
|
38
|
+
# @!attribute [r] metadata
|
39
|
+
# Read-only metadata information related to the secret.
|
40
|
+
#
|
41
|
+
# @example Reading metadata
|
42
|
+
# secret = Vault.logical(:versioned).read("secret", "foo")
|
43
|
+
# secret.metadata[:created_time] #=> "2018-12-08T04:22:54.168065Z"
|
44
|
+
# secret.metadata[:version] #=> 1
|
45
|
+
# secret.metadata[:destroyed] #=> false
|
46
|
+
#
|
47
|
+
# @return [Hash<Symbol, Object>]
|
48
|
+
field :metadata, freeze: true
|
49
|
+
|
50
|
+
# @!attribute [r] lease_duration
|
51
|
+
# The number of seconds this lease is valid. If this number is 0 or nil,
|
52
|
+
# the secret does not expire.
|
53
|
+
#
|
54
|
+
# @example Getting lease duration
|
55
|
+
# secret = Vault.logical.read("secret/foo")
|
56
|
+
# secret.lease_duration #=> 2592000 # 30 days
|
57
|
+
#
|
58
|
+
# @return [Fixnum]
|
59
|
+
field :lease_duration
|
60
|
+
|
61
|
+
# @!attribute [r] lease_id
|
62
|
+
# Unique ID for the lease associated with this secret. The `lease_id` is a
|
63
|
+
# path and UUID that uniquely represents the secret. This may be used for
|
64
|
+
# renewing and revoking the secret, if permitted.
|
65
|
+
#
|
66
|
+
# @example Getting lease ID
|
67
|
+
# secret = Vault.logical.read("postgresql/creds/readonly")
|
68
|
+
# secret.lease_id #=> "postgresql/readonly/fdb29070-6379-70c9-ca3a-46152fb66de1"
|
69
|
+
#
|
70
|
+
# @return [String]
|
71
|
+
field :lease_id
|
72
|
+
|
73
|
+
# @!method [r] renewable?
|
74
|
+
# Returns whether this lease is renewable.
|
75
|
+
#
|
76
|
+
# @example Checking if a lease is renewable
|
77
|
+
# secret = Vault.logical.read("secret/foo")
|
78
|
+
# secret.renewable? #=> false
|
79
|
+
#
|
80
|
+
# @return [Boolean]
|
81
|
+
field :renewable, as: :renewable?
|
82
|
+
|
83
|
+
# @!attribute [r] warnings
|
84
|
+
# List of warnings returned by the Vault server. These are returned by the
|
85
|
+
# Vault server and may include deprecation information, new APIs, or
|
86
|
+
# request using the API differently in the future.
|
87
|
+
#
|
88
|
+
# @example Display warnings
|
89
|
+
# result = Vault.logical.read("secret/foo")
|
90
|
+
# result.warnings #=> ["This path has been deprecated"]
|
91
|
+
#
|
92
|
+
# @return [Array<String>, nil]
|
93
|
+
field :warnings, freeze: true
|
94
|
+
|
95
|
+
# @!attribute [r] wrap_info
|
96
|
+
# Wrapped information sent with the request (only present in Vault 0.6+).
|
97
|
+
# @return [WrapInfo, nil]
|
98
|
+
field :wrap_info, load: ->(v) { WrapInfo.decode(v) }
|
99
|
+
end
|
100
|
+
|
101
|
+
# SecretAuth is a struct that contains the information about auth data, if
|
102
|
+
# present. This is never returned alone and is usually embededded in a
|
103
|
+
# {Secret}.
|
104
|
+
class SecretAuth < Response
|
105
|
+
# @!attribute [r] accessor
|
106
|
+
# Accessor for the token. This is like a `lease_id`, but for a token.
|
107
|
+
# @return [String]
|
108
|
+
field :accessor
|
109
|
+
|
110
|
+
# @!attribute [r] client_token
|
111
|
+
# The client token for this authentication.
|
112
|
+
# @return [String]
|
113
|
+
field :client_token
|
114
|
+
|
115
|
+
# @!attribute [r] lease_duration
|
116
|
+
# Number of seconds the token is valid.
|
117
|
+
# @return [Fixnum]
|
118
|
+
field :lease_duration
|
119
|
+
|
120
|
+
# @!attribute [r] metadata
|
121
|
+
# Arbitrary metadata from the authentication.
|
122
|
+
#
|
123
|
+
# @example Listing metadata attached to an authentication
|
124
|
+
# auth.metadata #=> { :username => "sethvargo" }
|
125
|
+
#
|
126
|
+
# @return [Hash<Symbol, Object>, nil]
|
127
|
+
field :metadata, freeze: true
|
128
|
+
|
129
|
+
# @!attribute [r] policies
|
130
|
+
# List of policies attached to this authentication.
|
131
|
+
#
|
132
|
+
# @example Listing policies attached to an authentication
|
133
|
+
# auth.policies #=> ["default"]
|
134
|
+
#
|
135
|
+
# @return [Array<String>, nil]
|
136
|
+
field :policies, freeze: true
|
137
|
+
|
138
|
+
# @!attribute [r] renewable
|
139
|
+
# Returns whether this authentication is renewable.
|
140
|
+
#
|
141
|
+
# @example Checking if an authentication is renewable
|
142
|
+
# auth.renewable? #=> false
|
143
|
+
#
|
144
|
+
# @return [Boolean]
|
145
|
+
field :renewable, as: :renewable?
|
146
|
+
end
|
147
|
+
|
148
|
+
# WrapInfo is the information returned by a wrapped response. This is almost
|
149
|
+
# always embedded as part of a {Secret}.
|
150
|
+
class WrapInfo < Response
|
151
|
+
# @!attribute [r] token
|
152
|
+
# Wrapped response token. This token may be used to unwrap the response.
|
153
|
+
# @return [String]
|
154
|
+
field :token
|
155
|
+
|
156
|
+
# @!attribute [r] wrapped_accessor
|
157
|
+
# Accessor for the wrapped token. This is like a `lease_id`, but for a token.
|
158
|
+
# @return [String]
|
159
|
+
field :wrapped_accessor
|
160
|
+
|
161
|
+
# @!attribute [r] creation_time
|
162
|
+
# Date & time when the wrapped token was created
|
163
|
+
# @return [Time]
|
164
|
+
field :creation_time, load: ->(v) { Time.parse(v) }
|
165
|
+
|
166
|
+
# @!attribute [r] ttl
|
167
|
+
# The TTL on the token returned in seconds.
|
168
|
+
# @return [Fixnum]
|
169
|
+
field :ttl
|
170
|
+
end
|
171
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# Copyright (c) HashiCorp, Inc.
|
2
|
+
# SPDX-License-Identifier: MPL-2.0
|
3
|
+
|
4
|
+
require "json"
|
5
|
+
|
6
|
+
module Vault
|
7
|
+
class Audit < Response
|
8
|
+
# @!attribute [r] description
|
9
|
+
# Description of the audit backend.
|
10
|
+
# @return [String]
|
11
|
+
field :description
|
12
|
+
|
13
|
+
# @!attribute [r] options
|
14
|
+
# Map of options configured to the audit backend.
|
15
|
+
# @return [Hash<Symbol, Object>]
|
16
|
+
field :options
|
17
|
+
|
18
|
+
# @!attribute [r] type
|
19
|
+
# Name of the audit backend.
|
20
|
+
# @return [String]
|
21
|
+
field :type
|
22
|
+
end
|
23
|
+
|
24
|
+
class Sys
|
25
|
+
# List all audits for the vault.
|
26
|
+
#
|
27
|
+
# @example
|
28
|
+
# Vault.sys.audits #=> { :file => #<Audit> }
|
29
|
+
#
|
30
|
+
# @return [Hash<Symbol, Audit>]
|
31
|
+
def audits
|
32
|
+
json = client.get("/v1/sys/audit")
|
33
|
+
json = json[:data] if json[:data]
|
34
|
+
return Hash[*json.map do |k,v|
|
35
|
+
[k.to_s.chomp("/").to_sym, Audit.decode(v)]
|
36
|
+
end.flatten]
|
37
|
+
end
|
38
|
+
|
39
|
+
# Enable a particular audit. Note: the +options+ depend heavily on the
|
40
|
+
# type of audit being enabled. Please refer to audit-specific documentation
|
41
|
+
# for which need to be enabled.
|
42
|
+
#
|
43
|
+
# @example
|
44
|
+
# Vault.sys.enable_audit("/file-audit", "file", "File audit", path: "/path/on/disk") #=> true
|
45
|
+
#
|
46
|
+
# @param [String] path
|
47
|
+
# the path to mount the audit
|
48
|
+
# @param [String] type
|
49
|
+
# the type of audit to enable
|
50
|
+
# @param [String] description
|
51
|
+
# a human-friendly description of the audit backend
|
52
|
+
# @param [Hash] options
|
53
|
+
# audit-specific options
|
54
|
+
#
|
55
|
+
# @return [true]
|
56
|
+
def enable_audit(path, type, description, options = {})
|
57
|
+
client.put("/v1/sys/audit/#{encode_path(path)}", JSON.fast_generate(
|
58
|
+
type: type,
|
59
|
+
description: description,
|
60
|
+
options: options,
|
61
|
+
))
|
62
|
+
return true
|
63
|
+
end
|
64
|
+
|
65
|
+
# Disable a particular audit. If an audit does not exist, and error will be
|
66
|
+
# raised.
|
67
|
+
#
|
68
|
+
# @param [String] path
|
69
|
+
# the path of the audit to disable
|
70
|
+
#
|
71
|
+
# @return [true]
|
72
|
+
def disable_audit(path)
|
73
|
+
client.delete("/v1/sys/audit/#{encode_path(path)}")
|
74
|
+
return true
|
75
|
+
end
|
76
|
+
|
77
|
+
# Generates a HMAC verifier for a given input.
|
78
|
+
#
|
79
|
+
# @example
|
80
|
+
# Vault.sys.audit_hash("file-audit", "my input") #=> "hmac-sha256:30aa7de18a5e90bbc1063db91e7c387b32b9fa895977eb8c177bbc91e7d7c542"
|
81
|
+
#
|
82
|
+
# @param [String] path
|
83
|
+
# the path of the audit backend
|
84
|
+
# @param [String] input
|
85
|
+
# the input to generate a HMAC for
|
86
|
+
#
|
87
|
+
# @return [String]
|
88
|
+
def audit_hash(path, input)
|
89
|
+
json = client.post("/v1/sys/audit-hash/#{encode_path(path)}", JSON.fast_generate(input: input))
|
90
|
+
json = json[:data] if json[:data]
|
91
|
+
json[:hash]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|