vault 0.10.0 → 0.16.0
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 +5 -5
- data/CHANGELOG.md +68 -0
- data/README.md +31 -7
- data/lib/vault/api.rb +2 -0
- data/lib/vault/api/auth.rb +113 -8
- data/lib/vault/api/auth_token.rb +2 -2
- data/lib/vault/api/kv.rb +207 -0
- data/lib/vault/api/secret.rb +12 -0
- data/lib/vault/api/sys.rb +3 -0
- data/lib/vault/api/sys/audit.rb +18 -1
- data/lib/vault/api/sys/health.rb +63 -0
- data/lib/vault/api/sys/mount.rb +7 -2
- data/lib/vault/api/sys/namespace.rb +83 -0
- data/lib/vault/api/sys/quota.rb +107 -0
- data/lib/vault/api/transform.rb +29 -0
- data/lib/vault/api/transform/alphabet.rb +43 -0
- data/lib/vault/api/transform/role.rb +42 -0
- data/lib/vault/api/transform/template.rb +54 -0
- data/lib/vault/api/transform/transformation.rb +61 -0
- data/lib/vault/client.rb +19 -5
- data/lib/vault/configurable.rb +2 -0
- data/lib/vault/defaults.rb +27 -2
- data/lib/vault/persistent.rb +2 -7
- data/lib/vault/persistent/pool.rb +1 -1
- data/lib/vault/request.rb +1 -0
- data/lib/vault/version.rb +1 -1
- metadata +40 -24
- data/.gitignore +0 -41
- data/.rspec +0 -2
- data/.travis.yml +0 -24
- data/Gemfile +0 -3
- data/Rakefile +0 -6
- data/vault.gemspec +0 -28
data/lib/vault/api/secret.rb
CHANGED
@@ -32,6 +32,18 @@ module Vault
|
|
32
32
|
# @return [Hash<Symbol, Object>]
|
33
33
|
field :data, freeze: true
|
34
34
|
|
35
|
+
# @!attribute [r] metadata
|
36
|
+
# Read-only metadata information related to the secret.
|
37
|
+
#
|
38
|
+
# @example Reading metadata
|
39
|
+
# secret = Vault.logical(:versioned).read("secret", "foo")
|
40
|
+
# secret.metadata[:created_time] #=> "2018-12-08T04:22:54.168065Z"
|
41
|
+
# secret.metadata[:version] #=> 1
|
42
|
+
# secret.metadata[:destroyed] #=> false
|
43
|
+
#
|
44
|
+
# @return [Hash<Symbol, Object>]
|
45
|
+
field :metadata, freeze: true
|
46
|
+
|
35
47
|
# @!attribute [r] lease_duration
|
36
48
|
# The number of seconds this lease is valid. If this number is 0 or nil,
|
37
49
|
# the secret does not expire.
|
data/lib/vault/api/sys.rb
CHANGED
@@ -16,9 +16,12 @@ end
|
|
16
16
|
|
17
17
|
require_relative "sys/audit"
|
18
18
|
require_relative "sys/auth"
|
19
|
+
require_relative "sys/health"
|
19
20
|
require_relative "sys/init"
|
20
21
|
require_relative "sys/leader"
|
21
22
|
require_relative "sys/lease"
|
22
23
|
require_relative "sys/mount"
|
24
|
+
require_relative "sys/namespace"
|
23
25
|
require_relative "sys/policy"
|
26
|
+
require_relative "sys/quota"
|
24
27
|
require_relative "sys/seal"
|
data/lib/vault/api/sys/audit.rb
CHANGED
@@ -19,7 +19,7 @@ module Vault
|
|
19
19
|
end
|
20
20
|
|
21
21
|
class Sys
|
22
|
-
# List all
|
22
|
+
# List all audits for the vault.
|
23
23
|
#
|
24
24
|
# @example
|
25
25
|
# Vault.sys.audits #=> { :file => #<Audit> }
|
@@ -70,5 +70,22 @@ module Vault
|
|
70
70
|
client.delete("/v1/sys/audit/#{encode_path(path)}")
|
71
71
|
return true
|
72
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
|
73
90
|
end
|
74
91
|
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
|
data/lib/vault/api/sys/mount.rb
CHANGED
@@ -16,6 +16,11 @@ module Vault
|
|
16
16
|
# Type of the mount.
|
17
17
|
# @return [String]
|
18
18
|
field :type
|
19
|
+
|
20
|
+
# @!attribute [r] type
|
21
|
+
# Options given to the mount.
|
22
|
+
# @return [Hash<Symbol, Object>]
|
23
|
+
field :options
|
19
24
|
end
|
20
25
|
|
21
26
|
class Sys < Request
|
@@ -44,8 +49,8 @@ module Vault
|
|
44
49
|
# the type of mount
|
45
50
|
# @param [String] description
|
46
51
|
# a human-friendly description (optional)
|
47
|
-
def mount(path, type, description = nil)
|
48
|
-
payload =
|
52
|
+
def mount(path, type, description = nil, options = {})
|
53
|
+
payload = options.merge type: type
|
49
54
|
payload[:description] = description if !description.nil?
|
50
55
|
|
51
56
|
client.post("/v1/sys/mounts/#{encode_path(path)}", JSON.fast_generate(payload))
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module Vault
|
2
|
+
class Namespace < Response
|
3
|
+
# @!attribute [r] id
|
4
|
+
# ID of the namespace
|
5
|
+
# @return [String]
|
6
|
+
field :id
|
7
|
+
|
8
|
+
# @!attribute [r] path
|
9
|
+
# Path of the namespace, includes parent paths if nested.
|
10
|
+
# @return [String]
|
11
|
+
field :path
|
12
|
+
end
|
13
|
+
|
14
|
+
class Sys
|
15
|
+
# List all namespaces in a given scope. Ignores nested namespaces.
|
16
|
+
#
|
17
|
+
# @example
|
18
|
+
# Vault.sys.namespaces #=> { :foo => #<struct Vault::Namespace id="xxxx1", path="foo/" }
|
19
|
+
#
|
20
|
+
# @return [Hash<Symbol, Namespace>]
|
21
|
+
def namespaces(scoped=nil)
|
22
|
+
path = ["v1", scoped, "sys", "namespaces"].compact
|
23
|
+
json = client.list(path.join("/"))
|
24
|
+
json = json[:data] if json[:data]
|
25
|
+
if json[:key_info]
|
26
|
+
json = json[:key_info]
|
27
|
+
hash = {}
|
28
|
+
json.each do |k,v|
|
29
|
+
hash[k.to_s.chomp("/").to_sym] = Namespace.decode(v)
|
30
|
+
end
|
31
|
+
hash
|
32
|
+
else
|
33
|
+
json
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Create a namespace. Nests the namespace if a namespace header is provided.
|
38
|
+
#
|
39
|
+
# @example
|
40
|
+
# Vault.sys.create_namespace("foo")
|
41
|
+
#
|
42
|
+
# @param [String] namespace
|
43
|
+
# the potential path of the namespace, without any parent path provided
|
44
|
+
#
|
45
|
+
# @return [true]
|
46
|
+
def create_namespace(namespace)
|
47
|
+
client.put("/v1/sys/namespaces/#{namespace}", {})
|
48
|
+
return true
|
49
|
+
end
|
50
|
+
|
51
|
+
# Delete a namespace. Raises an error if the namespace provided is not empty.
|
52
|
+
#
|
53
|
+
# @example
|
54
|
+
# Vault.sys.delete_namespace("foo")
|
55
|
+
#
|
56
|
+
# @param [String] namespace
|
57
|
+
# the path of the namespace to be deleted
|
58
|
+
#
|
59
|
+
# @return [true]
|
60
|
+
def delete_namespace(namespace)
|
61
|
+
client.delete("/v1/sys/namespaces/#{namespace}")
|
62
|
+
return true
|
63
|
+
end
|
64
|
+
|
65
|
+
# Retrieve a namespace by path.
|
66
|
+
#
|
67
|
+
# @example
|
68
|
+
# Vault.sys.get_namespace("foo")
|
69
|
+
#
|
70
|
+
# @param [String] namespace
|
71
|
+
# the path of the namespace ot be retrieved
|
72
|
+
#
|
73
|
+
# @return [Namespace]
|
74
|
+
def get_namespace(namespace)
|
75
|
+
json = client.get("/v1/sys/namespaces/#{namespace}")
|
76
|
+
if data = json.dig(:data)
|
77
|
+
Namespace.decode(data)
|
78
|
+
else
|
79
|
+
json
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
module Vault
|
2
|
+
class Quota < Response
|
3
|
+
# @!attribute [r] name
|
4
|
+
# Name of the quota rule.
|
5
|
+
# @return [String]
|
6
|
+
field :name
|
7
|
+
|
8
|
+
# @!attribute [r] path
|
9
|
+
# Namespace/Path combination the quota applies to.
|
10
|
+
# @return [String]
|
11
|
+
field :path
|
12
|
+
|
13
|
+
# @!attribute [r] type
|
14
|
+
# Type of the quota rule, must be one of "lease-count" or "rate-limit"
|
15
|
+
# @return [String]
|
16
|
+
field :type
|
17
|
+
end
|
18
|
+
|
19
|
+
class RateLimitQuota < Quota
|
20
|
+
# @!attribute [r] rate
|
21
|
+
# The rate at which allowed requests are refilled per second by the quota
|
22
|
+
# rule.
|
23
|
+
# @return [Float]
|
24
|
+
field :rate
|
25
|
+
|
26
|
+
# @!attribute [r] burst
|
27
|
+
# The maximum number of requests at any given second allowed by the quota
|
28
|
+
# rule.
|
29
|
+
# @return [Int]
|
30
|
+
field :burst
|
31
|
+
end
|
32
|
+
|
33
|
+
class LeaseCountQuota < Quota
|
34
|
+
# @!attribute [r] counter
|
35
|
+
# Number of currently active leases for the quota.
|
36
|
+
# @return [Int]
|
37
|
+
field :counter
|
38
|
+
|
39
|
+
# @!attribute [r] max_leases
|
40
|
+
# The maximum number of allowed leases for this quota.
|
41
|
+
# @return [Int]
|
42
|
+
field :max_leases
|
43
|
+
end
|
44
|
+
|
45
|
+
class Sys
|
46
|
+
def quotas(type)
|
47
|
+
path = generate_path(type)
|
48
|
+
json = client.list(path)
|
49
|
+
if data = json.dig(:data, :key_info)
|
50
|
+
data.map do |item|
|
51
|
+
type_class(type).decode(item)
|
52
|
+
end
|
53
|
+
else
|
54
|
+
json
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def create_quota(type, name, opts={})
|
59
|
+
path = generate_path(type, name)
|
60
|
+
client.post(path, JSON.fast_generate(opts))
|
61
|
+
return true
|
62
|
+
end
|
63
|
+
|
64
|
+
def delete_quota(type, name)
|
65
|
+
path = generate_path(type, name)
|
66
|
+
client.delete(path)
|
67
|
+
return true
|
68
|
+
end
|
69
|
+
|
70
|
+
def get_quota(type, name)
|
71
|
+
path = generate_path(type, name)
|
72
|
+
response = client.get(path)
|
73
|
+
if data = response[:data]
|
74
|
+
type_class(type).decode(data)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def get_quota_config
|
79
|
+
client.get("v1/sys/quotas/config")
|
80
|
+
end
|
81
|
+
|
82
|
+
def update_quota_config(opts={})
|
83
|
+
client.post("v1/sys/quotas/config", JSON.fast_generate(opts))
|
84
|
+
return true
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def generate_path(type, name=nil)
|
90
|
+
verify_type(type)
|
91
|
+
path = ["v1", "sys", "quotas", type, name].compact
|
92
|
+
path.join("/")
|
93
|
+
end
|
94
|
+
|
95
|
+
def verify_type(type)
|
96
|
+
return if ["rate-limit", "lease-count"].include?(type)
|
97
|
+
raise ArgumentError, "type must be one of \"rate-limit\" or \"lease-count\""
|
98
|
+
end
|
99
|
+
|
100
|
+
def type_class(type)
|
101
|
+
case type
|
102
|
+
when "lease-count" then LeaseCountQuota
|
103
|
+
when "rate-limit" then RateLimitQuota
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative '../client'
|
2
|
+
require_relative '../request'
|
3
|
+
|
4
|
+
module Vault
|
5
|
+
class Client
|
6
|
+
# A proxy to the {Transform} methods.
|
7
|
+
# @return [Transform]
|
8
|
+
def transform
|
9
|
+
@transform ||= Transform.new(self)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Transform < Request
|
14
|
+
def encode(role_name:, **opts)
|
15
|
+
opts ||= {}
|
16
|
+
client.post("/v1/transform/encode/#{encode_path(role_name)}", JSON.fast_generate(opts))
|
17
|
+
end
|
18
|
+
|
19
|
+
def decode(role_name:, **opts)
|
20
|
+
opts ||= {}
|
21
|
+
client.post("/v1/transform/decode/#{encode_path(role_name)}", JSON.fast_generate(opts))
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require_relative 'transform/alphabet'
|
27
|
+
require_relative 'transform/role'
|
28
|
+
require_relative 'transform/template'
|
29
|
+
require_relative 'transform/transformation'
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require_relative '../../request'
|
2
|
+
require_relative '../../response'
|
3
|
+
|
4
|
+
module Vault
|
5
|
+
class Transform < Request
|
6
|
+
class Alphabet < Response
|
7
|
+
# @!attribute [r] id
|
8
|
+
# String listing all possible characters of the alphabet
|
9
|
+
# @return [String]
|
10
|
+
field :alphabet
|
11
|
+
end
|
12
|
+
|
13
|
+
def create_alphabet(name, alphabet:, **opts)
|
14
|
+
opts ||= {}
|
15
|
+
opts[:alphabet] = alphabet
|
16
|
+
client.post("/v1/transform/alphabet/#{encode_path(name)}", JSON.fast_generate(opts))
|
17
|
+
return true
|
18
|
+
end
|
19
|
+
|
20
|
+
def get_alphabet(name)
|
21
|
+
json = client.get("/v1/transform/alphabet/#{encode_path(name)}")
|
22
|
+
if data = json.dig(:data)
|
23
|
+
Alphabet.decode(data)
|
24
|
+
else
|
25
|
+
json
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def delete_alphabet(name)
|
30
|
+
client.delete("/v1/transform/alphabet/#{encode_path(name)}")
|
31
|
+
true
|
32
|
+
end
|
33
|
+
|
34
|
+
def alphabets
|
35
|
+
json = client.list("/v1/transform/alphabet")
|
36
|
+
if keys = json.dig(:data, :keys)
|
37
|
+
keys
|
38
|
+
else
|
39
|
+
json
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require_relative '../../request'
|
2
|
+
require_relative '../../response'
|
3
|
+
|
4
|
+
module Vault
|
5
|
+
class Transform < Request
|
6
|
+
class Role < Response
|
7
|
+
# @!attribute [r] transformations
|
8
|
+
# Array of all transformations the role has access to
|
9
|
+
# @return [Array<String>]
|
10
|
+
field :transformations
|
11
|
+
end
|
12
|
+
|
13
|
+
def create_role(name, **opts)
|
14
|
+
opts ||= {}
|
15
|
+
client.post("/v1/transform/role/#{encode_path(name)}", JSON.fast_generate(opts))
|
16
|
+
return true
|
17
|
+
end
|
18
|
+
|
19
|
+
def get_role(name)
|
20
|
+
json = client.get("/v1/transform/role/#{encode_path(name)}")
|
21
|
+
if data = json.dig(:data)
|
22
|
+
Role.decode(data)
|
23
|
+
else
|
24
|
+
json
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def delete_role(name)
|
29
|
+
client.delete("/v1/transform/role/#{encode_path(name)}")
|
30
|
+
true
|
31
|
+
end
|
32
|
+
|
33
|
+
def roles
|
34
|
+
json = client.list("/v1/transform/role")
|
35
|
+
if keys = json.dig(:data, :keys)
|
36
|
+
keys
|
37
|
+
else
|
38
|
+
json
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|