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.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +41 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +6 -0
  5. data/CHANGELOG.md +5 -0
  6. data/Gemfile +3 -0
  7. data/Gemfile.lock +32 -0
  8. data/LICENSE +362 -0
  9. data/README.md +80 -54
  10. data/Rakefile +4 -40
  11. data/lib/vault.rb +33 -46
  12. data/lib/vault/api.rb +9 -0
  13. data/lib/vault/api/auth_token.rb +90 -0
  14. data/lib/vault/api/help.rb +23 -0
  15. data/lib/vault/api/logical.rb +66 -0
  16. data/lib/vault/api/secret.rb +23 -0
  17. data/lib/vault/api/sys.rb +24 -0
  18. data/lib/vault/api/sys/audit.rb +60 -0
  19. data/lib/vault/api/sys/auth.rb +58 -0
  20. data/lib/vault/api/sys/init.rb +46 -0
  21. data/lib/vault/api/sys/leader.rb +25 -0
  22. data/lib/vault/api/sys/lease.rb +51 -0
  23. data/lib/vault/api/sys/mount.rb +75 -0
  24. data/lib/vault/api/sys/policy.rb +76 -0
  25. data/lib/vault/api/sys/seal.rb +49 -0
  26. data/lib/vault/client.rb +285 -0
  27. data/lib/vault/configurable.rb +48 -0
  28. data/lib/vault/defaults.rb +68 -0
  29. data/lib/vault/errors.rb +48 -0
  30. data/lib/vault/request.rb +19 -0
  31. data/lib/vault/response.rb +20 -0
  32. data/lib/vault/version.rb +1 -6
  33. data/vault.gemspec +25 -0
  34. metadata +97 -98
  35. data/MIT-LICENSE +0 -20
  36. data/lib/vault/associations.rb +0 -39
  37. data/lib/vault/attribute_accessors.rb +0 -29
  38. data/lib/vault/bulk_attributes.rb +0 -17
  39. data/lib/vault/dirty.rb +0 -37
  40. data/lib/vault/finders.rb +0 -24
  41. data/lib/vault/persistance.rb +0 -47
  42. data/lib/vault/properties.rb +0 -68
  43. data/lib/vault/scoping.rb +0 -64
  44. data/lib/vault/storage.rb +0 -4
  45. data/lib/vault/storage/in_memory_store.rb +0 -14
  46. data/lib/vault/storage/yaml_store.rb +0 -52
  47. data/lib/vault/validations.rb +0 -13
  48. data/spec/active_model_compliance_spec.rb +0 -33
  49. data/spec/spec_helper.rb +0 -8
  50. data/spec/support/helpers.rb +0 -16
  51. data/spec/support/storage_api.rb +0 -14
  52. data/spec/vault/associations_spec.rb +0 -73
  53. data/spec/vault/finders_spec.rb +0 -69
  54. data/spec/vault/persistance_spec.rb +0 -126
  55. data/spec/vault/properties_spec.rb +0 -59
  56. data/spec/vault/scoping_spec.rb +0 -53
  57. data/spec/vault/storage/in_memory_store_spec.rb +0 -5
  58. data/spec/vault/storage/yaml_store_spec.rb +0 -29
  59. 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