vault 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|