vault 0.1.0 → 0.1.1
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/.gitignore +41 -0
- data/.rspec +2 -0
- data/.travis.yml +6 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +32 -0
- data/LICENSE +362 -0
- data/README.md +80 -54
- data/Rakefile +4 -40
- data/lib/vault.rb +33 -46
- data/lib/vault/api.rb +9 -0
- data/lib/vault/api/auth_token.rb +90 -0
- data/lib/vault/api/help.rb +23 -0
- data/lib/vault/api/logical.rb +66 -0
- data/lib/vault/api/secret.rb +23 -0
- data/lib/vault/api/sys.rb +24 -0
- data/lib/vault/api/sys/audit.rb +60 -0
- data/lib/vault/api/sys/auth.rb +58 -0
- data/lib/vault/api/sys/init.rb +46 -0
- data/lib/vault/api/sys/leader.rb +25 -0
- data/lib/vault/api/sys/lease.rb +51 -0
- data/lib/vault/api/sys/mount.rb +75 -0
- data/lib/vault/api/sys/policy.rb +76 -0
- data/lib/vault/api/sys/seal.rb +49 -0
- data/lib/vault/client.rb +285 -0
- data/lib/vault/configurable.rb +48 -0
- data/lib/vault/defaults.rb +68 -0
- data/lib/vault/errors.rb +48 -0
- data/lib/vault/request.rb +19 -0
- data/lib/vault/response.rb +20 -0
- data/lib/vault/version.rb +1 -6
- data/vault.gemspec +25 -0
- metadata +97 -98
- data/MIT-LICENSE +0 -20
- data/lib/vault/associations.rb +0 -39
- data/lib/vault/attribute_accessors.rb +0 -29
- data/lib/vault/bulk_attributes.rb +0 -17
- data/lib/vault/dirty.rb +0 -37
- data/lib/vault/finders.rb +0 -24
- data/lib/vault/persistance.rb +0 -47
- data/lib/vault/properties.rb +0 -68
- data/lib/vault/scoping.rb +0 -64
- data/lib/vault/storage.rb +0 -4
- data/lib/vault/storage/in_memory_store.rb +0 -14
- data/lib/vault/storage/yaml_store.rb +0 -52
- data/lib/vault/validations.rb +0 -13
- data/spec/active_model_compliance_spec.rb +0 -33
- data/spec/spec_helper.rb +0 -8
- data/spec/support/helpers.rb +0 -16
- data/spec/support/storage_api.rb +0 -14
- data/spec/vault/associations_spec.rb +0 -73
- data/spec/vault/finders_spec.rb +0 -69
- data/spec/vault/persistance_spec.rb +0 -126
- data/spec/vault/properties_spec.rb +0 -59
- data/spec/vault/scoping_spec.rb +0 -53
- data/spec/vault/storage/in_memory_store_spec.rb +0 -5
- data/spec/vault/storage/yaml_store_spec.rb +0 -29
- data/spec/vault_spec.rb +0 -33
@@ -0,0 +1,23 @@
|
|
1
|
+
require_relative "../response"
|
2
|
+
|
3
|
+
module Vault
|
4
|
+
# Secret is a representation of a secret.
|
5
|
+
class Secret < Response.new(:lease_id, :lease_duration, :renewable, :data, :auth)
|
6
|
+
alias_method :renewable?, :renewable
|
7
|
+
|
8
|
+
alias_method :raw_auth, :auth
|
9
|
+
def auth
|
10
|
+
return @auth if defined?(@auth)
|
11
|
+
if raw_auth.nil?
|
12
|
+
@auth = nil
|
13
|
+
else
|
14
|
+
@auth = SecretAuth.decode(raw_auth)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# SecretAuth is a struct that contains the information about auth data if present.
|
20
|
+
class SecretAuth < Response.new(:client_token, :policies, :metadata, :lease_duration, :renewable)
|
21
|
+
alias_method :renewable?, :renewable
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,24 @@
|
|
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/init"
|
20
|
+
require_relative "sys/leader"
|
21
|
+
require_relative "sys/lease"
|
22
|
+
require_relative "sys/mount"
|
23
|
+
require_relative "sys/policy"
|
24
|
+
require_relative "sys/seal"
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require "json"
|
2
|
+
|
3
|
+
require_relative "../sys"
|
4
|
+
|
5
|
+
module Vault
|
6
|
+
class Audit < Response.new(:type, :description, :options); end
|
7
|
+
|
8
|
+
class Sys
|
9
|
+
# List all audis for the vault.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# Vault.sys.audits #=> { :file => #<Audit> }
|
13
|
+
#
|
14
|
+
# @return [Hash<Symbol, Audit>]
|
15
|
+
def audits
|
16
|
+
json = client.get("/v1/sys/audit")
|
17
|
+
return Hash[*json.map do |k,v|
|
18
|
+
[k.to_s.chomp("/").to_sym, Audit.decode(v)]
|
19
|
+
end.flatten]
|
20
|
+
end
|
21
|
+
|
22
|
+
# Enable a particular audit. Note: the +options+ depend heavily on the
|
23
|
+
# type of audit being enabled. Please refer to audit-specific documentation
|
24
|
+
# for which need to be enabled.
|
25
|
+
#
|
26
|
+
# @example
|
27
|
+
# Vault.sys.enable_audit("/file-audit", "file", "File audit", path: "/path/on/disk") #=> true
|
28
|
+
#
|
29
|
+
# @param [String] path
|
30
|
+
# the path to mount the audit
|
31
|
+
# @param [String] type
|
32
|
+
# the type of audit to enable
|
33
|
+
# @param [String] description
|
34
|
+
# a human-friendly description of the audit backend
|
35
|
+
# @param [Hash] options
|
36
|
+
# audit-specific options
|
37
|
+
#
|
38
|
+
# @return [true]
|
39
|
+
def enable_audit(path, type, description, options = {})
|
40
|
+
client.put("/v1/sys/audit/#{path}", JSON.fast_generate(
|
41
|
+
type: type,
|
42
|
+
description: description,
|
43
|
+
options: options,
|
44
|
+
))
|
45
|
+
return true
|
46
|
+
end
|
47
|
+
|
48
|
+
# Disable a particular audit. If an audit does not exist, and error will be
|
49
|
+
# raised.
|
50
|
+
#
|
51
|
+
# @param [String] path
|
52
|
+
# the path of the audit to disable
|
53
|
+
#
|
54
|
+
# @return [true]
|
55
|
+
def disable_audit(path)
|
56
|
+
client.delete("/v1/sys/audit/#{path}")
|
57
|
+
return true
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require "json"
|
2
|
+
|
3
|
+
require_relative "../sys"
|
4
|
+
|
5
|
+
module Vault
|
6
|
+
class Auth < Response.new(:type, :description); end
|
7
|
+
|
8
|
+
class Sys
|
9
|
+
# List all auths in Vault.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# Vault.sys.auths #=> {:token => #<Vault::Auth type="token", description="token based credentials">}
|
13
|
+
#
|
14
|
+
# @return [Hash<Symbol, Auth>]
|
15
|
+
def auths
|
16
|
+
json = client.get("/v1/sys/auth")
|
17
|
+
return Hash[*json.map do |k,v|
|
18
|
+
[k.to_s.chomp("/").to_sym, Auth.decode(v)]
|
19
|
+
end.flatten]
|
20
|
+
end
|
21
|
+
|
22
|
+
# Enable a particular authentication at the given path.
|
23
|
+
#
|
24
|
+
# @example
|
25
|
+
# Vault.sys.enable_auth("github", "github") #=> true
|
26
|
+
#
|
27
|
+
# @param [String] path
|
28
|
+
# the path to mount the auth
|
29
|
+
# @param [String] type
|
30
|
+
# the type of authentication
|
31
|
+
# @param [String] description
|
32
|
+
# a human-friendly description (optional)
|
33
|
+
#
|
34
|
+
# @return [true]
|
35
|
+
def enable_auth(path, type, description = nil)
|
36
|
+
payload = { type: type }
|
37
|
+
payload[:description] = description if !description.nil?
|
38
|
+
|
39
|
+
client.post("/v1/sys/auth/#{path}", JSON.fast_generate(payload))
|
40
|
+
return true
|
41
|
+
end
|
42
|
+
|
43
|
+
# Disable a particular authentication at the given path. If not auth
|
44
|
+
# exists at that path, an error will be raised.
|
45
|
+
#
|
46
|
+
# @example
|
47
|
+
# Vault.sys.disable_auth("github") #=> true
|
48
|
+
#
|
49
|
+
# @param [String] path
|
50
|
+
# the path to disable
|
51
|
+
#
|
52
|
+
# @return [true]
|
53
|
+
def disable_auth(path)
|
54
|
+
client.delete("/v1/sys/auth/#{path}")
|
55
|
+
return true
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require "json"
|
2
|
+
|
3
|
+
require_relative "../sys"
|
4
|
+
|
5
|
+
module Vault
|
6
|
+
class InitResponse < Response.new(:keys, :root_token); end
|
7
|
+
|
8
|
+
class InitStatus < Response.new(:initialized)
|
9
|
+
alias_method :initialized?, :initialized
|
10
|
+
end
|
11
|
+
|
12
|
+
class Sys
|
13
|
+
# Show the initialization status for this vault.
|
14
|
+
#
|
15
|
+
# @example
|
16
|
+
# Vault.sys.init_status #=> #<Vault::InitStatus initialized=true>
|
17
|
+
#
|
18
|
+
# @return [InitStatus]
|
19
|
+
def init_status
|
20
|
+
json = client.get("/v1/sys/init")
|
21
|
+
return InitStatus.decode(json)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Initialize a new vault.
|
25
|
+
#
|
26
|
+
# @example
|
27
|
+
# Vault.sys.init #=> #<Vault::InitResponse keys=["..."] root_token="...">
|
28
|
+
#
|
29
|
+
# @param [Hash] options
|
30
|
+
# the list of init options
|
31
|
+
#
|
32
|
+
# @option options [Fixnum] :shares
|
33
|
+
# the number of shares
|
34
|
+
# @option options [Fixnum] :threshold
|
35
|
+
# the number of keys needed to unlock
|
36
|
+
#
|
37
|
+
# @return [InitResponse]
|
38
|
+
def init(options = {})
|
39
|
+
json = client.put("/v1/sys/init", JSON.fast_generate(
|
40
|
+
secret_shares: options.fetch(:shares, 5),
|
41
|
+
secret_threshold: options.fetch(:threshold, 3),
|
42
|
+
))
|
43
|
+
return InitResponse.decode(json)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require_relative "../sys"
|
2
|
+
|
3
|
+
module Vault
|
4
|
+
class LeaderStatus < Response.new(:ha_enabled, :is_self, :leader_address)
|
5
|
+
alias_method :ha_enabled?, :ha_enabled
|
6
|
+
alias_method :ha?, :ha_enabled
|
7
|
+
alias_method :is_self?, :is_self
|
8
|
+
alias_method :is_leader?, :is_self
|
9
|
+
alias_method :leader?, :is_self
|
10
|
+
alias_method :address, :leader_address
|
11
|
+
end
|
12
|
+
|
13
|
+
class Sys
|
14
|
+
# Determine the leader status for this vault.
|
15
|
+
#
|
16
|
+
# @example
|
17
|
+
# Vault.sys.leader #=> #<Vault::LeaderStatus ha_enabled=false, is_self=false, leader_address="">
|
18
|
+
#
|
19
|
+
# @return [LeaderStatus]
|
20
|
+
def leader
|
21
|
+
json = client.get("/v1/sys/leader")
|
22
|
+
return LeaderStatus.decode(json)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require_relative "../sys"
|
2
|
+
|
3
|
+
module Vault
|
4
|
+
class Sys
|
5
|
+
# Renew a lease with the given ID.
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# Vault.sys.renew("aws/username") #=> #<Vault::Secret ...>
|
9
|
+
#
|
10
|
+
# @param [String] id
|
11
|
+
# the lease ID
|
12
|
+
# @param [Fixnum] increment
|
13
|
+
#
|
14
|
+
# @return [Secret]
|
15
|
+
def renew(id, increment = 0)
|
16
|
+
json = client.put("/v1/sys/renew/#{id}", JSON.fast_generate(
|
17
|
+
increment: increment,
|
18
|
+
))
|
19
|
+
return Secret.decode(json)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Revoke the secret at the given id. If the secret does not exist, an error
|
23
|
+
# will be raised.
|
24
|
+
#
|
25
|
+
# @example
|
26
|
+
# Vault.sys.revoke("aws/username") #=> true
|
27
|
+
#
|
28
|
+
# @param [String] id
|
29
|
+
# the lease ID
|
30
|
+
#
|
31
|
+
# @return [true]
|
32
|
+
def revoke(id)
|
33
|
+
client.put("/v1/sys/revoke/#{id}", nil)
|
34
|
+
return true
|
35
|
+
end
|
36
|
+
|
37
|
+
# Revoke all secrets under the given prefix.
|
38
|
+
#
|
39
|
+
# @example
|
40
|
+
# Vault.sys.revoke_prefix("aws") #=> true
|
41
|
+
#
|
42
|
+
# @param [String] id
|
43
|
+
# the lease ID
|
44
|
+
#
|
45
|
+
# @return [true]
|
46
|
+
def revoke_prefix(id)
|
47
|
+
client.put("/v1/sys/revoke-prefix/#{id}", nil)
|
48
|
+
return true
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require "json"
|
2
|
+
|
3
|
+
require_relative "../sys"
|
4
|
+
|
5
|
+
module Vault
|
6
|
+
class Mount < Response.new(:type, :description); end
|
7
|
+
|
8
|
+
class Sys < Request
|
9
|
+
# List all mounts in the vault.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# Vault.sys.mounts #=> { :secret => #<struct Vault::Mount type="generic", description="generic secret storage"> }
|
13
|
+
#
|
14
|
+
# @return [Hash<Symbol, Mount>]
|
15
|
+
def mounts
|
16
|
+
json = client.get("/v1/sys/mounts")
|
17
|
+
return Hash[*json.map do |k,v|
|
18
|
+
[k.to_s.chomp("/").to_sym, Mount.decode(v)]
|
19
|
+
end.flatten]
|
20
|
+
end
|
21
|
+
|
22
|
+
# Create a mount at the given path.
|
23
|
+
#
|
24
|
+
# @example
|
25
|
+
# Vault.sys.mount("pg", "postgresql", "Postgres user management") #=> true
|
26
|
+
#
|
27
|
+
# @param [String] path
|
28
|
+
# the path to mount at
|
29
|
+
# @param [String] type
|
30
|
+
# the type of mount
|
31
|
+
# @param [String] description
|
32
|
+
# a human-friendly description (optional)
|
33
|
+
def mount(path, type, description = nil)
|
34
|
+
payload = { type: type }
|
35
|
+
payload[:description] = description if !description.nil?
|
36
|
+
|
37
|
+
client.post("/v1/sys/mounts/#{path}", JSON.fast_generate(payload))
|
38
|
+
return true
|
39
|
+
end
|
40
|
+
|
41
|
+
# Unmount the thing at the given path. If the mount does not exist, an error
|
42
|
+
# will be raised.
|
43
|
+
#
|
44
|
+
# @example
|
45
|
+
# Vault.sys.unmount("pg") #=> true
|
46
|
+
#
|
47
|
+
# @param [String] path
|
48
|
+
# the path to unmount
|
49
|
+
#
|
50
|
+
# @return [true]
|
51
|
+
def unmount(path)
|
52
|
+
client.delete("/v1/sys/mounts/#{path}")
|
53
|
+
return true
|
54
|
+
end
|
55
|
+
|
56
|
+
# Change the name of the mount
|
57
|
+
#
|
58
|
+
# @example
|
59
|
+
# Vault.sys.remount("pg", "postgres") #=> true
|
60
|
+
#
|
61
|
+
# @param [String] from
|
62
|
+
# the origin mount path
|
63
|
+
# @param [String] to
|
64
|
+
# the new mount path
|
65
|
+
#
|
66
|
+
# @return [true]
|
67
|
+
def remount(from, to)
|
68
|
+
client.post("/v1/sys/remount", JSON.fast_generate(
|
69
|
+
from: from,
|
70
|
+
to: to,
|
71
|
+
))
|
72
|
+
return true
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require "json"
|
2
|
+
|
3
|
+
require_relative "../sys"
|
4
|
+
|
5
|
+
module Vault
|
6
|
+
class Policy < Response.new(:rules); end
|
7
|
+
|
8
|
+
class Sys
|
9
|
+
# The list of policies in vault.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# Vault.sys.policies #=> ["root"]
|
13
|
+
#
|
14
|
+
# @return [Array<String>]
|
15
|
+
def policies
|
16
|
+
client.get("/v1/sys/policy")[:policies]
|
17
|
+
end
|
18
|
+
|
19
|
+
# Get the policy by the given name. If a policy does not exist by that name,
|
20
|
+
# +nil+ is returned.
|
21
|
+
#
|
22
|
+
# @example
|
23
|
+
# Vault.sys.policy("root") #=> #<Vault::Policy rules="">
|
24
|
+
#
|
25
|
+
# @return [Policy, nil]
|
26
|
+
def policy(name)
|
27
|
+
json = client.get("/v1/sys/policy/#{name}")
|
28
|
+
return Policy.decode(json)
|
29
|
+
rescue HTTPError => e
|
30
|
+
return nil if e.code == 404
|
31
|
+
raise
|
32
|
+
end
|
33
|
+
|
34
|
+
# Create a new policy with the given name and rules.
|
35
|
+
#
|
36
|
+
# @example
|
37
|
+
# policy = <<-EOH
|
38
|
+
# path "sys" {
|
39
|
+
# policy = "deny"
|
40
|
+
# }
|
41
|
+
# EOH
|
42
|
+
# Vault.sys.put_policy("dev", policy) #=> true
|
43
|
+
#
|
44
|
+
# It is recommend that you load policy rules from a file:
|
45
|
+
#
|
46
|
+
# @example
|
47
|
+
# policy = File.read("/path/to/my/policy.hcl")
|
48
|
+
# Vault.sys.put_policy("dev", policy)
|
49
|
+
#
|
50
|
+
# @param [String] name
|
51
|
+
# the name of the policy
|
52
|
+
# @param [String] rules
|
53
|
+
# the policy rules
|
54
|
+
#
|
55
|
+
# @return [true]
|
56
|
+
def put_policy(name, rules)
|
57
|
+
client.put("/v1/sys/policy/#{name}", JSON.fast_generate(
|
58
|
+
rules: rules,
|
59
|
+
))
|
60
|
+
return true
|
61
|
+
end
|
62
|
+
|
63
|
+
# Delete the policy with the given name. If a policy does not exist, vault
|
64
|
+
# will not return an error.
|
65
|
+
#
|
66
|
+
# @example
|
67
|
+
# Vault.sys.delete_policy("dev") #=> true
|
68
|
+
#
|
69
|
+
# @param [String] name
|
70
|
+
# the name of the policy
|
71
|
+
def delete_policy(name)
|
72
|
+
client.delete("/v1/sys/policy/#{name}")
|
73
|
+
return true
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|