vault 0.1.0 → 0.1.1

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