vault-kv 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +42 -0
- data/.rspec +2 -0
- data/.travis.yml +29 -0
- data/CHANGELOG.md +228 -0
- data/Gemfile +3 -0
- data/LICENSE +362 -0
- data/README.md +212 -0
- data/Rakefile +6 -0
- data/lib/vault.rb +49 -0
- data/lib/vault/api.rb +13 -0
- data/lib/vault/api/approle.rb +218 -0
- data/lib/vault/api/auth.rb +316 -0
- data/lib/vault/api/auth_tls.rb +92 -0
- data/lib/vault/api/auth_token.rb +242 -0
- data/lib/vault/api/help.rb +33 -0
- data/lib/vault/api/kv.rb +207 -0
- data/lib/vault/api/logical.rb +150 -0
- data/lib/vault/api/secret.rb +168 -0
- data/lib/vault/api/sys.rb +25 -0
- data/lib/vault/api/sys/audit.rb +91 -0
- data/lib/vault/api/sys/auth.rb +116 -0
- data/lib/vault/api/sys/health.rb +63 -0
- data/lib/vault/api/sys/init.rb +83 -0
- data/lib/vault/api/sys/leader.rb +48 -0
- data/lib/vault/api/sys/lease.rb +49 -0
- data/lib/vault/api/sys/mount.rb +103 -0
- data/lib/vault/api/sys/policy.rb +92 -0
- data/lib/vault/api/sys/seal.rb +81 -0
- data/lib/vault/client.rb +447 -0
- data/lib/vault/configurable.rb +48 -0
- data/lib/vault/defaults.rb +197 -0
- data/lib/vault/encode.rb +19 -0
- data/lib/vault/errors.rb +72 -0
- data/lib/vault/persistent.rb +1158 -0
- data/lib/vault/persistent/connection.rb +42 -0
- data/lib/vault/persistent/pool.rb +48 -0
- data/lib/vault/persistent/timed_stack_multi.rb +70 -0
- data/lib/vault/request.rb +43 -0
- data/lib/vault/response.rb +89 -0
- data/lib/vault/vendor/connection_pool.rb +150 -0
- data/lib/vault/vendor/connection_pool/timed_stack.rb +178 -0
- data/lib/vault/vendor/connection_pool/version.rb +5 -0
- data/lib/vault/version.rb +3 -0
- data/vault.gemspec +30 -0
- metadata +186 -0
@@ -0,0 +1,25 @@
|
|
1
|
+
require_relative "../client"
|
2
|
+
require_relative "../request"
|
3
|
+
require_relative "../response"
|
4
|
+
|
5
|
+
module Vault
|
6
|
+
class Client
|
7
|
+
# A proxy to the {Sys} methods.
|
8
|
+
# @return [Sys]
|
9
|
+
def sys
|
10
|
+
@sys ||= Sys.new(self)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Sys < Request; end
|
15
|
+
end
|
16
|
+
|
17
|
+
require_relative "sys/audit"
|
18
|
+
require_relative "sys/auth"
|
19
|
+
require_relative "sys/health"
|
20
|
+
require_relative "sys/init"
|
21
|
+
require_relative "sys/leader"
|
22
|
+
require_relative "sys/lease"
|
23
|
+
require_relative "sys/mount"
|
24
|
+
require_relative "sys/policy"
|
25
|
+
require_relative "sys/seal"
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require "json"
|
2
|
+
|
3
|
+
module Vault
|
4
|
+
class Audit < Response
|
5
|
+
# @!attribute [r] description
|
6
|
+
# Description of the audit backend.
|
7
|
+
# @return [String]
|
8
|
+
field :description
|
9
|
+
|
10
|
+
# @!attribute [r] options
|
11
|
+
# Map of options configured to the audit backend.
|
12
|
+
# @return [Hash<Symbol, Object>]
|
13
|
+
field :options
|
14
|
+
|
15
|
+
# @!attribute [r] type
|
16
|
+
# Name of the audit backend.
|
17
|
+
# @return [String]
|
18
|
+
field :type
|
19
|
+
end
|
20
|
+
|
21
|
+
class Sys
|
22
|
+
# List all audits for the vault.
|
23
|
+
#
|
24
|
+
# @example
|
25
|
+
# Vault.sys.audits #=> { :file => #<Audit> }
|
26
|
+
#
|
27
|
+
# @return [Hash<Symbol, Audit>]
|
28
|
+
def audits
|
29
|
+
json = client.get("/v1/sys/audit")
|
30
|
+
json = json[:data] if json[:data]
|
31
|
+
return Hash[*json.map do |k,v|
|
32
|
+
[k.to_s.chomp("/").to_sym, Audit.decode(v)]
|
33
|
+
end.flatten]
|
34
|
+
end
|
35
|
+
|
36
|
+
# Enable a particular audit. Note: the +options+ depend heavily on the
|
37
|
+
# type of audit being enabled. Please refer to audit-specific documentation
|
38
|
+
# for which need to be enabled.
|
39
|
+
#
|
40
|
+
# @example
|
41
|
+
# Vault.sys.enable_audit("/file-audit", "file", "File audit", path: "/path/on/disk") #=> true
|
42
|
+
#
|
43
|
+
# @param [String] path
|
44
|
+
# the path to mount the audit
|
45
|
+
# @param [String] type
|
46
|
+
# the type of audit to enable
|
47
|
+
# @param [String] description
|
48
|
+
# a human-friendly description of the audit backend
|
49
|
+
# @param [Hash] options
|
50
|
+
# audit-specific options
|
51
|
+
#
|
52
|
+
# @return [true]
|
53
|
+
def enable_audit(path, type, description, options = {})
|
54
|
+
client.put("/v1/sys/audit/#{encode_path(path)}", JSON.fast_generate(
|
55
|
+
type: type,
|
56
|
+
description: description,
|
57
|
+
options: options,
|
58
|
+
))
|
59
|
+
return true
|
60
|
+
end
|
61
|
+
|
62
|
+
# Disable a particular audit. If an audit does not exist, and error will be
|
63
|
+
# raised.
|
64
|
+
#
|
65
|
+
# @param [String] path
|
66
|
+
# the path of the audit to disable
|
67
|
+
#
|
68
|
+
# @return [true]
|
69
|
+
def disable_audit(path)
|
70
|
+
client.delete("/v1/sys/audit/#{encode_path(path)}")
|
71
|
+
return true
|
72
|
+
end
|
73
|
+
|
74
|
+
# Generates a HMAC verifier for a given input.
|
75
|
+
#
|
76
|
+
# @example
|
77
|
+
# Vault.sys.audit_hash("file-audit", "my input") #=> "hmac-sha256:30aa7de18a5e90bbc1063db91e7c387b32b9fa895977eb8c177bbc91e7d7c542"
|
78
|
+
#
|
79
|
+
# @param [String] path
|
80
|
+
# the path of the audit backend
|
81
|
+
# @param [String] input
|
82
|
+
# the input to generate a HMAC for
|
83
|
+
#
|
84
|
+
# @return [String]
|
85
|
+
def audit_hash(path, input)
|
86
|
+
json = client.post("/v1/sys/audit-hash/#{encode_path(path)}", JSON.fast_generate(input: input))
|
87
|
+
json = json[:data] if json[:data]
|
88
|
+
json[:hash]
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require "json"
|
2
|
+
|
3
|
+
module Vault
|
4
|
+
class Auth < Response
|
5
|
+
# @!attribute [r] description
|
6
|
+
# Description of the auth backend.
|
7
|
+
# @return [String]
|
8
|
+
field :description
|
9
|
+
|
10
|
+
# @!attribute [r] type
|
11
|
+
# Name of the auth backend.
|
12
|
+
# @return [String]
|
13
|
+
field :type
|
14
|
+
end
|
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
|
+
|
28
|
+
class Sys
|
29
|
+
# List all auths in Vault.
|
30
|
+
#
|
31
|
+
# @example
|
32
|
+
# Vault.sys.auths #=> {:token => #<Vault::Auth type="token", description="token based credentials">}
|
33
|
+
#
|
34
|
+
# @return [Hash<Symbol, Auth>]
|
35
|
+
def auths
|
36
|
+
json = client.get("/v1/sys/auth")
|
37
|
+
json = json[:data] if json[:data]
|
38
|
+
return Hash[*json.map do |k,v|
|
39
|
+
[k.to_s.chomp("/").to_sym, Auth.decode(v)]
|
40
|
+
end.flatten]
|
41
|
+
end
|
42
|
+
|
43
|
+
# Enable a particular authentication at the given path.
|
44
|
+
#
|
45
|
+
# @example
|
46
|
+
# Vault.sys.enable_auth("github", "github") #=> true
|
47
|
+
#
|
48
|
+
# @param [String] path
|
49
|
+
# the path to mount the auth
|
50
|
+
# @param [String] type
|
51
|
+
# the type of authentication
|
52
|
+
# @param [String] description
|
53
|
+
# a human-friendly description (optional)
|
54
|
+
#
|
55
|
+
# @return [true]
|
56
|
+
def enable_auth(path, type, description = nil)
|
57
|
+
payload = { type: type }
|
58
|
+
payload[:description] = description if !description.nil?
|
59
|
+
|
60
|
+
client.post("/v1/sys/auth/#{encode_path(path)}", JSON.fast_generate(payload))
|
61
|
+
return true
|
62
|
+
end
|
63
|
+
|
64
|
+
# Disable a particular authentication at the given path. If not auth
|
65
|
+
# exists at that path, an error will be raised.
|
66
|
+
#
|
67
|
+
# @example
|
68
|
+
# Vault.sys.disable_auth("github") #=> true
|
69
|
+
#
|
70
|
+
# @param [String] path
|
71
|
+
# the path to disable
|
72
|
+
#
|
73
|
+
# @return [true]
|
74
|
+
def disable_auth(path)
|
75
|
+
client.delete("/v1/sys/auth/#{encode_path(path)}")
|
76
|
+
return true
|
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
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require "json"
|
2
|
+
|
3
|
+
module Vault
|
4
|
+
class HealthStatus < Response
|
5
|
+
# @!attribute [r] initialized
|
6
|
+
# Whether the Vault server is Initialized.
|
7
|
+
# @return [Boolean]
|
8
|
+
field :initialized, as: :initialized?
|
9
|
+
|
10
|
+
# @!attribute [r] sealed
|
11
|
+
# Whether the Vault server is Sealed.
|
12
|
+
# @return [Boolean]
|
13
|
+
field :sealed, as: :sealed?
|
14
|
+
|
15
|
+
# @!attribute [r] standby
|
16
|
+
# Whether the Vault server is in Standby mode.
|
17
|
+
# @return [Boolean]
|
18
|
+
field :standby, as: :standby?
|
19
|
+
|
20
|
+
# @!attribute [r] replication_performance_mode
|
21
|
+
# Verbose description of DR mode (added in 0.9.2)
|
22
|
+
# @return [String]
|
23
|
+
field :replication_performance_mode
|
24
|
+
|
25
|
+
# @!attribute [r] replication_dr_mode
|
26
|
+
# Verbose description of DR mode (added in 0.9.2)
|
27
|
+
# @return [String]
|
28
|
+
field :replication_dr_mode
|
29
|
+
|
30
|
+
# @!attribute [r] server_time_utc
|
31
|
+
# Server time in Unix seconds, UTC
|
32
|
+
# @return [Fixnum]
|
33
|
+
field :server_time_utc
|
34
|
+
|
35
|
+
# @!attribute [r] version
|
36
|
+
# Server Vault version string (added in 0.6.1)
|
37
|
+
# @return [String]
|
38
|
+
field :version
|
39
|
+
|
40
|
+
# @!attribute [r] cluster_name
|
41
|
+
# Server cluster name
|
42
|
+
# @return [String]
|
43
|
+
field :cluster_name
|
44
|
+
|
45
|
+
# @!attribute [r] cluster_id
|
46
|
+
# Server cluster UUID
|
47
|
+
# @return [String]
|
48
|
+
field :cluster_id
|
49
|
+
end
|
50
|
+
|
51
|
+
class Sys
|
52
|
+
# Show the health status for this vault.
|
53
|
+
#
|
54
|
+
# @example
|
55
|
+
# Vault.sys.health_status #=> #Vault::HealthStatus @initialized=true, @sealed=false, @standby=false, @replication_performance_mode="disabled", @replication_dr_mode="disabled", @server_time_utc=1519776728, @version="0.9.3", @cluster_name="vault-cluster-997f514e", @cluster_id="c2dad70a-6d88-a06d-69f6-9ae7f5485998">
|
56
|
+
#
|
57
|
+
# @return [HealthStatus]
|
58
|
+
def health_status
|
59
|
+
json = client.get("/v1/sys/health", {:sealedcode => 200, :uninitcode => 200, :standbycode => 200})
|
60
|
+
return HealthStatus.decode(json)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require "json"
|
2
|
+
|
3
|
+
module Vault
|
4
|
+
class InitResponse < Response
|
5
|
+
# @!attribute [r] keys
|
6
|
+
# List of unseal keys.
|
7
|
+
# @return [Array<String>]
|
8
|
+
field :keys
|
9
|
+
|
10
|
+
# @!attribute [r] keys_base64
|
11
|
+
# List of unseal keys, base64-encoded
|
12
|
+
# @return [Array<String>]
|
13
|
+
field :keys_base64
|
14
|
+
|
15
|
+
# @!attribute [r] root_token
|
16
|
+
# Initial root token.
|
17
|
+
# @return [String]
|
18
|
+
field :root_token
|
19
|
+
end
|
20
|
+
|
21
|
+
class InitStatus < Response
|
22
|
+
# @!method initialized?
|
23
|
+
# Returns whether the Vault server is initialized.
|
24
|
+
# @return [Boolean]
|
25
|
+
field :initialized, as: :initialized?
|
26
|
+
end
|
27
|
+
|
28
|
+
class Sys
|
29
|
+
# Show the initialization status for this vault.
|
30
|
+
#
|
31
|
+
# @example
|
32
|
+
# Vault.sys.init_status #=> #<Vault::InitStatus initialized=true>
|
33
|
+
#
|
34
|
+
# @return [InitStatus]
|
35
|
+
def init_status
|
36
|
+
json = client.get("/v1/sys/init")
|
37
|
+
return InitStatus.decode(json)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Initialize a new vault.
|
41
|
+
#
|
42
|
+
# @example
|
43
|
+
# Vault.sys.init #=> #<Vault::InitResponse keys=["..."] root_token="...">
|
44
|
+
#
|
45
|
+
# @param [Hash] options
|
46
|
+
# the list of init options
|
47
|
+
#
|
48
|
+
# @option options [String] :root_token_pgp_key
|
49
|
+
# optional base64-encoded PGP public key used to encrypt the initial root
|
50
|
+
# token.
|
51
|
+
# @option options [Fixnum] :secret_shares
|
52
|
+
# the number of shares
|
53
|
+
# @option options [Fixnum] :secret_threshold
|
54
|
+
# the number of keys needed to unlock
|
55
|
+
# @option options [Array<String>] :pgp_keys
|
56
|
+
# an optional Array of base64-encoded PGP public keys to encrypt sharees
|
57
|
+
# @option options [Fixnum] :stored_shares
|
58
|
+
# the number of shares that should be encrypted by the HSM for
|
59
|
+
# auto-unsealing
|
60
|
+
# @option options [Fixnum] :recovery_shares
|
61
|
+
# the number of shares to split the recovery key into
|
62
|
+
# @option options [Fixnum] :recovery_threshold
|
63
|
+
# the number of shares required to reconstruct the recovery key
|
64
|
+
# @option options [Array<String>] :recovery_pgp_keys
|
65
|
+
# an array of PGP public keys used to encrypt the output for the recovery
|
66
|
+
# keys
|
67
|
+
#
|
68
|
+
# @return [InitResponse]
|
69
|
+
def init(options = {})
|
70
|
+
json = client.put("/v1/sys/init", JSON.fast_generate(
|
71
|
+
root_token_pgp_key: options.fetch(:root_token_pgp_key, nil),
|
72
|
+
secret_shares: options.fetch(:secret_shares, options.fetch(:shares, 5)),
|
73
|
+
secret_threshold: options.fetch(:secret_threshold, options.fetch(:threshold, 3)),
|
74
|
+
pgp_keys: options.fetch(:pgp_keys, nil),
|
75
|
+
stored_shares: options.fetch(:stored_shares, nil),
|
76
|
+
recovery_shares: options.fetch(:recovery_shares, nil),
|
77
|
+
recovery_threshold: options.fetch(:recovery_threshold, nil),
|
78
|
+
recovery_pgp_keys: options.fetch(:recovery_pgp_keys, nil),
|
79
|
+
))
|
80
|
+
return InitResponse.decode(json)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Vault
|
2
|
+
class LeaderStatus < Response
|
3
|
+
# @!method ha_enabled?
|
4
|
+
# Returns whether the high-availability mode is enabled.
|
5
|
+
# @return [Boolean]
|
6
|
+
field :ha_enabled, as: :ha_enabled?
|
7
|
+
|
8
|
+
# @!method leader?
|
9
|
+
# Returns whether the Vault server queried is the leader.
|
10
|
+
# @return [Boolean]
|
11
|
+
field :is_self, as: :leader?
|
12
|
+
|
13
|
+
# @!attribute [r] address
|
14
|
+
# URL where the server is running.
|
15
|
+
# @return [String]
|
16
|
+
field :leader_address, as: :address
|
17
|
+
|
18
|
+
# @deprecated Use {#ha_enabled?} instead
|
19
|
+
def ha?; ha_enabled?; end
|
20
|
+
|
21
|
+
# @deprecated Use {#leader?} instead
|
22
|
+
def is_leader?; leader?; end
|
23
|
+
|
24
|
+
# @deprecated Use {#leader?} instead
|
25
|
+
def is_self?; leader?; end
|
26
|
+
|
27
|
+
# @deprecated Use {#leader?} instead
|
28
|
+
def self?; leader?; end
|
29
|
+
end
|
30
|
+
|
31
|
+
class Sys
|
32
|
+
# Determine the leader status for this vault.
|
33
|
+
#
|
34
|
+
# @example
|
35
|
+
# Vault.sys.leader #=> #<Vault::LeaderStatus ha_enabled=false, is_self=false, leader_address="">
|
36
|
+
#
|
37
|
+
# @return [LeaderStatus]
|
38
|
+
def leader
|
39
|
+
json = client.get("/v1/sys/leader")
|
40
|
+
return LeaderStatus.decode(json)
|
41
|
+
end
|
42
|
+
|
43
|
+
def step_down
|
44
|
+
client.put("/v1/sys/step-down", nil)
|
45
|
+
return true
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Vault
|
2
|
+
class Sys
|
3
|
+
# Renew a lease with the given ID.
|
4
|
+
#
|
5
|
+
# @example
|
6
|
+
# Vault.sys.renew("aws/username") #=> #<Vault::Secret ...>
|
7
|
+
#
|
8
|
+
# @param [String] id
|
9
|
+
# the lease ID
|
10
|
+
# @param [Fixnum] increment
|
11
|
+
#
|
12
|
+
# @return [Secret]
|
13
|
+
def renew(id, increment = 0)
|
14
|
+
json = client.put("/v1/sys/renew/#{id}", JSON.fast_generate(
|
15
|
+
increment: increment,
|
16
|
+
))
|
17
|
+
return Secret.decode(json)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Revoke the secret at the given id. If the secret does not exist, an error
|
21
|
+
# will be raised.
|
22
|
+
#
|
23
|
+
# @example
|
24
|
+
# Vault.sys.revoke("aws/username") #=> true
|
25
|
+
#
|
26
|
+
# @param [String] id
|
27
|
+
# the lease ID
|
28
|
+
#
|
29
|
+
# @return [true]
|
30
|
+
def revoke(id)
|
31
|
+
client.put("/v1/sys/revoke/#{id}", nil)
|
32
|
+
return true
|
33
|
+
end
|
34
|
+
|
35
|
+
# Revoke all secrets under the given prefix.
|
36
|
+
#
|
37
|
+
# @example
|
38
|
+
# Vault.sys.revoke_prefix("aws") #=> true
|
39
|
+
#
|
40
|
+
# @param [String] id
|
41
|
+
# the lease ID
|
42
|
+
#
|
43
|
+
# @return [true]
|
44
|
+
def revoke_prefix(id)
|
45
|
+
client.put("/v1/sys/revoke-prefix/#{id}", nil)
|
46
|
+
return true
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|