vault 0.10.0 → 0.16.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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"
@@ -19,7 +19,7 @@ module Vault
19
19
  end
20
20
 
21
21
  class Sys
22
- # List all audis for the vault.
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
@@ -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 = { type: type }
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