vault_ruby_client 0.18.2
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 +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
|