sanctum 0.8.5.rc1 → 0.8.5.rc2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7669c1c9dff3c31915cef379c1d95ce55a58e21a8c785f4b543d7a8b55dff42f
4
- data.tar.gz: 9d87df11f2f28a3ae833271c6ea35329f82d4f08767765bc3383ef5ae66fccba
3
+ metadata.gz: 6dc55aef33e0ba6113e5577b80799818e64a8953d0643d6b029335b84a5edc23
4
+ data.tar.gz: 52638d7d39ccb21cb830288081d9ca23017e3582e991603ec8f084175f0f3034
5
5
  SHA512:
6
- metadata.gz: 144efff039e4dead3c2d14c7557aef22cde70972b9d2130ef7f94acc8dd1f7a28349382e51d81ca927d40d8e434d8a2cf1d366c52d0394a6a5246296151deef0
7
- data.tar.gz: 216aedadda62921b7941b52aab144a57a3152dce5f23db1e5febe19d001c4af679c46f53c6c91b2d24b966ca27cb0eeb1a858b01fc56d6582755bcda9ae5fbf8
6
+ metadata.gz: 475976714b4229cd2e9a4dce401ed6aada1decbb2da6e73f55e7de3ba95e8ea17ef0aa0e4b84be9225713d8cacfe2260236b75cc75e21d396bcb6d63403463f5
7
+ data.tar.gz: 16b9465d78eeceb1580c8203eb8c21096d6a398d3b2c6c023f8c4e68bbfbe698c21be2cc9f52daf81175d35706f2a95b89a07214ccba1f4dde38ed7ef4303e8e
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- sanctum (0.8.5.rc1)
4
+ sanctum (0.8.5.rc2)
5
5
  gli (~> 2.18)
6
6
  hashdiff (~> 0.3)
7
7
  vault (~> 0.12)
data/README.md CHANGED
@@ -63,7 +63,7 @@ VAULT_TOKEN=
63
63
  ```
64
64
 
65
65
  **Variables order of precedence**
66
- The higher the number the higher the precedence.(Command line arguments will always win).
66
+ The higher the number the higher the precedence.(1 is the lowest precedence, 4 is the highest, Command line arguments will always win).
67
67
 
68
68
  1. Default variables (Documented in sanctum.yaml)
69
69
  2. Config file
@@ -0,0 +1,54 @@
1
+ # Helpful documentation can be found
2
+ # https://www.vaultproject.io/guides/identity/policies
3
+ # https://www.vaultproject.io/docs/concepts/policies.html
4
+ # https://learn.hashicorp.com/vault/getting-started/policies
5
+ #
6
+ # You can make permissions more granular or limited by specifying deeper paths
7
+ # Example: `path "sanctum-test/data/dev/*"`, etc.
8
+ #
9
+ ################# Read/Write v2 api example #################################################
10
+ path "sanctum-test/data/*" { capabilities = ["list","read","create","update","delete"] }
11
+ path "sanctum-test/metadata/*" { capabilities = ["list","read","create","update","delete"] }
12
+ path "sanctum-test/destroy/*" { capabilities = ["update"] }
13
+ path "sanctum-test/delete/*" { capabilities = ["update"] }
14
+ path "sanctum-test/undelete/*" { capabilities = ["update"] }
15
+ #############################################################################################
16
+
17
+ ################# Read/Write v1/generic example ###################################
18
+ path "sanctum-test/*" { capabilities = ["list","read","create","update","delete"] }
19
+ ###################################################################################
20
+
21
+ ################## Additional sys/ and sys/mount permissions ############################################
22
+ # Grant access to tune existing mount
23
+ # Required to upgrade from v1/generic to v2
24
+ path "sys/mounts/sanctum-test/tune" { capabilities = ["read", "update"] }
25
+ # Grant broader permission to specific mount
26
+ path "sys/mounts/sanctum-test" { capabilities = ["create", "read", "update", "delete", "list", "sudo"] }
27
+ # Read health checks
28
+ path "sys/health" { capabilities = ["read", "sudo"] }
29
+ # View capabilities of token
30
+ path "sys/capabilities" { capabilities = ["create", "update"] }
31
+ # View capabilities of token
32
+ path "sys/capabilities-self" { capabilities = ["create", "update"] }
33
+ # View mount info for mounts that you have permissions on
34
+ path "sys/internal/ui/mounts" { capabilities = ["read"] }
35
+ #########################################################################################################
36
+
37
+ ################### Transit permissions###########################################################
38
+ # General permission on key
39
+ path "transit/keys/sanctum-test" { capabilities = ["list","read","create","update", "delete"] }
40
+ # Permission to rotate keys
41
+ path "transit/keys/sanctum-test/rotate" { capabilities = ["list","read","create","update"] }
42
+ # Permission to modify transit key config
43
+ path "transit/keys/sanctum-test/config" { capabilities = ["list","read","create","update"] }
44
+ # Permission to backup key
45
+ #path "transit/backup/sanctum-test" { capabilities = ["list","read"] }
46
+ # Permission to restore key
47
+ #path "transit/restore/sanctum-test" { capabilities = ["list","read","create","update"] }
48
+ # Transit encryption endpoint
49
+ path "transit/encrypt/sanctum-test" { capabilities = ["list","read","create","update"] }
50
+ # Transit decrypt endpoint
51
+ path "transit/decrypt/sanctum-test" { capabilities = ["list","read","create","update"] }
52
+ # Transit rewrap permissions
53
+ path "transit/rewrap/sanctum-test" { capabilities = ["list","read","create","update"] }
54
+ ##################################################################################################
@@ -0,0 +1,14 @@
1
+ # sanctum.yml
2
+ sanctum:
3
+ force: false
4
+ color: true
5
+
6
+ vault:
7
+ url: http://localhost:8200
8
+ token: my_cool_token
9
+ transit_key: transit/keys/sanctum-test
10
+
11
+ sync:
12
+ - name: sanctum-test
13
+ prefix: sanctum-test #Refers to vault
14
+ path: vault/sanctum-test #Refers to local path relative to sanctum.yaml
@@ -28,21 +28,15 @@ module Sanctum
28
28
 
29
29
  private
30
30
  # TODO: Fix! This is a bit hacky, will update once vault-ruby gets updated with better support for v2 api
31
-
32
-
33
31
  # Internal: gets information about mounts that the user has permissions on
34
32
  # Returns: hash
35
33
  def mounts_info
36
34
  @mounts_info ||= vault_client.request(:get, "/v1/sys/internal/ui/mounts")
37
- rescue Vault::HTTPClientError
38
- warn red(
39
- "Unable to gather info about mounts this maybe due to vault connectivity or permissions"\
40
- "\nTo list info about mounts you have permissions to have following permissions added"\
41
- "\npath \"sys/internal/ui/mounts\" { capabilities = [\"read\"] }"\
42
- )
35
+ rescue Vault::VaultError
36
+ unable_to_determine_version
37
+ raise
43
38
  end
44
39
 
45
-
46
40
  # Internal: automatically detect the api version of the secrets mount
47
41
  # and adds :secrets_version to hash if it doesn't exist
48
42
  #
@@ -55,18 +49,13 @@ module Sanctum
55
49
  next if h.key?(:secrets_version)
56
50
 
57
51
  # If mount options is nil default to api version 1 otherwise use version value
52
+ # generic mounts will not have a version specified
58
53
  if mounts_hash.dig(:data, :secret, "#{h[:prefix]}/".to_sym, :options).nil?
59
54
  h[:secrets_version] = "1"
60
55
  else
61
56
  h[:secrets_version] = mounts_hash.dig(:data, :secret, "#{h[:prefix]}/".to_sym, :options, :version)
62
57
  end
63
58
  end
64
- rescue Vault::VaultError
65
- warn red(
66
- "Unable to automatically determine secrets_version. This maybe due to vault connectivity or permissions"\
67
- "\nTry again, or you could explicitly add `secrets_version:` to your sanctum.yaml to bypass auto detect"
68
- )
69
- raise
70
59
  end
71
60
 
72
61
  # Internal, add /data to prefix or path if secrets_version == "2"
@@ -80,6 +69,15 @@ module Sanctum
80
69
  h[:path] = h[:path].include?("/data") ? h[:path] : "#{h[:path]}/data"
81
70
  end
82
71
  end
72
+
73
+ def unable_to_determine_version
74
+ warn red(
75
+ "Unable to automatically gather info about mounts. This maybe due to vault connectivity or permissions"\
76
+ "\nTo list info about mounts you may need to have following permissions added"\
77
+ "\npath \"sys/internal/ui/mounts\" { capabilities = [\"read\"] }"\
78
+ "\nAlternitivley add `secrets_version: <version>` for each target specified in sanctum.yaml to bypass autodetect"
79
+ )
80
+ end
83
81
  end
84
82
  end
85
83
  end
@@ -51,9 +51,21 @@ module Sanctum
51
51
  end
52
52
  end
53
53
 
54
+ # Check if the path you are creating matches a target path
55
+ # if secrets_version == 2 /data will be added to the path
56
+ # See command/base.rb
57
+ def path_matches_a_target?(path)
58
+ targets.each do |h|
59
+ path.to_s.include?(h[:path]) ? (return true) : (return false)
60
+ end
61
+ end
62
+
54
63
  def validate_path(path)
55
64
  path = Pathname.new(path)
65
+ keys_to_print = targets.map { |h| h.slice(:name, :path) }
56
66
  raise yellow("File exists, use edit command") if path.exist?
67
+ raise yellow("No targets contain a :path key that matches the path you specified\n#{keys_to_print}") unless path_matches_a_target?(path)
68
+
57
69
  path.dirname.mkpath unless path.dirname.exist?
58
70
  end
59
71
 
@@ -4,17 +4,17 @@ module Sanctum
4
4
  module Command
5
5
  class Update < Base
6
6
  def run
7
- targets.each do |target|
8
- # Use command line if force: true
9
- if options[:cli][:force]
10
- force = options[:cli][:force]
11
- else
12
- force = target.fetch(:force) {options[:sanctum][:force]}
13
- end
14
-
15
- update_mount(target, force)
7
+ raise red("Please only specify one target") if targets.count > 1
8
+ target = targets.first
16
9
 
10
+ # Use command line if force: true
11
+ if options[:cli][:force]
12
+ force = options[:cli][:force]
13
+ else
14
+ force = target.fetch(:force) {options[:sanctum][:force]}
17
15
  end
16
+
17
+ update_mount(target, force)
18
18
  end
19
19
 
20
20
  private
@@ -24,30 +24,34 @@ module Sanctum
24
24
  pre_upgrade_warning
25
25
 
26
26
  if force
27
- warn yellow("\nUpgrading #{target[:prefix]}")
28
- upgrade_response = vault_client.request(:post, "/v1/sys/mounts/#{target[:prefix]}/tune", data)
29
- upgrade_response.nil? ? nothing_happened_warning : (warn yellow("#{upgrade_response}"))
27
+ # When force option is used we will try to run the upgrade command mount, even if it's already been upgraded
28
+ # Request will be a no-op and return null. So we need to remove `data` from the prefix if it's been added.
29
+ force_prefix = target[:prefix].include?("/data") ? target[:prefix].sub(/\/data/, "") : target[:prefix]
30
+ warn yellow("\nUpgrading #{force_prefix}")
31
+ upgrade_response = vault_client.request(:post, "/v1/sys/mounts/#{force_prefix}/tune", data)
30
32
  else
31
33
  already_upgraded_warning if target[:secrets_version] == "2"
32
- warn yellow("#{vault_client.request(:post, "/v1/sys/mounts/#{target[:prefix]}/tune", data)}") if confirm_upgrade?(target)
34
+ upgrade_response = confirm_upgrade?(target) ? vault_client.request(:post, "/v1/sys/mounts/#{target[:prefix]}/tune", data) : nil
33
35
  end
34
- post_upgrade_warning(target)
36
+ upgrade_response.nil? ? nothing_happened_warning : (warn yellow("#{upgrade_response}\n#{post_upgrade_warning}"))
37
+
38
+ post_upgrade_tasks(target)
35
39
  end
36
40
 
37
41
  def pre_upgrade_warning
38
42
  warn yellow(
39
43
  "\nPlease read 'Upgrading from Version 1' documentation BEFORE you upgrade"\
40
- "\nThe addition of `/data`, and `/metadata` endpoints will break applications that are depending on v1 endpoints"\
44
+ "\nThe addition of `/data`, and `/metadata` endpoints will break applications that are dependant on v1 endpoints"\
41
45
  "\nYou will want to update permissions policies, and applications BEFORE you upgrade"\
42
46
  "\nhttps://www.vaultproject.io/docs/secrets/kv/kv-v2.html#upgrading-from-version-1"\
43
47
  )
44
48
  additional_acl_warning
45
49
  end
46
50
 
47
- def post_upgrade_warning(target)
51
+ def post_upgrade_warning
48
52
  warn yellow(
49
- "\nOnce the upgrade has been completed, make sure you update your sanctum.yaml."\
50
- "\nPlease add the `secrets_version: 2` key to the #{target[:prefix]} config."
53
+ "\nOnce the upgrade has been completed update sanctum.yaml."\
54
+ "\nPlease add or update `secrets_version:` key to each configured target."\
51
55
  )
52
56
  end
53
57
 
@@ -55,12 +59,7 @@ module Sanctum
55
59
  warn yellow(
56
60
  "\nIf you use policies to limit secrets access you may need to have your permissions updated"\
57
61
  "\nSee https://www.vaultproject.io/docs/secrets/kv/kv-v2.html#acl-rules for more info"\
58
- "\nSpecifically you may need add something similar to the following:"\
59
- "\npath \"<secrets_mount>/data/*\" { capabilities = [\"list\",\"read\",\"create\",\"update\",\"delete\"] }"\
60
- "\npath \"<secrets_mount>/metadata/*\" { capabilities = [\"list\",\"read\",\"create\",\"update\",\"delete\"] }"\
61
- "\npath \"<secrets_mount>/destroy/*\" { capabilities = [\"update\"] }"\
62
- "\npath \"<secrets_mount>/delete/*\" { capabilities = [\"update\"] }"\
63
- "\npath \"<secrets_mount>/undelete/*\" { capabilities = [\"update\"] }"
62
+ "\nSee examples/single_target for updated policy example."\
64
63
  )
65
64
  end
66
65
 
@@ -74,12 +73,13 @@ module Sanctum
74
73
 
75
74
  def nothing_happened_warning
76
75
  warn yellow(
77
- "Request was successfull but returned a nil response, this generally means the mount has is already upgraded!"
76
+ "Request returned a nil response, which could mean mount is already upgraded"
78
77
  )
79
78
  end
80
79
 
81
80
  def confirm_upgrade?(target)
82
81
  warn yellow("\nUpgrading will make the mount temporarily unavailable")
82
+ warn red("\nPlease ensure you are fully synced(all secrets have been pushed/pulled)")
83
83
  warn yellow("Would you like to continue?: ")
84
84
  question = STDIN.gets.chomp.upcase
85
85
 
@@ -87,10 +87,34 @@ module Sanctum
87
87
  warn yellow("\nUpgrading #{target[:prefix]}")
88
88
  true
89
89
  else
90
- warn yellow("\nSkipping....\n")
90
+ raise yellow("\nSkipping....\n")
91
91
  false
92
92
  end
93
93
  end
94
+
95
+ # Post upgrade tasks if mount is being upgraded from generic mount or v1 mount to v2 mount
96
+ # Ensure local files mimic vault v2 by add `/data` to local path
97
+ def post_upgrade_tasks(target)
98
+ config_path = Pathname.new(config_file).dirname.to_s
99
+ full_target_path = "#{config_path}/#{target[:path]}"
100
+
101
+ old_path = full_target_path.include?("/data") ? full_target_path.sub(/\/data/, "") : full_target_path
102
+ new_path = full_target_path.include?("/data") ? full_target_path : "#{full_target_path}/data"
103
+
104
+ # If old path does not exist, chances are sanctum upgrade is being run before sanctum pull/push.
105
+ return unless File.directory?(old_path)
106
+
107
+ files_to_move = Dir.chdir(old_path) { Dir.glob('*') }.delete_if {|i| i == "data"}
108
+ unless files_to_move.empty?
109
+ FileUtils.mkdir_p(new_path) unless File.directory?(new_path)
110
+ files_to_move.each do |f|
111
+ FileUtils.mv("#{old_path}/#{f}", new_path, secure: true)
112
+ end
113
+ end
114
+ rescue
115
+ warn red("Post upgrade tasks failed")
116
+ raise
117
+ end
94
118
  end
95
119
  end
96
120
  end
@@ -12,7 +12,10 @@ module Sanctum
12
12
  # API version 2 uses /metadata path to list, but /data to read.
13
13
  #TODO Fix, change list_prefix back to prefix at some point. Use new kv from vault-ruby once it's updated
14
14
  def get_all
15
- raise yellow("Warning: Vault prefix: '#{prefix}' does not exist.. ") if invalid_prefix?
15
+ raise yellow(
16
+ "Vault prefix: '#{prefix}' does not exist, or doesn't contain any secrets to pull/check"\
17
+ "\nEnsure mount is enabled and use `sanctum create`, and `sanctum push` to add secrets"
18
+ ) if invalid_prefix?
16
19
 
17
20
  secrets_from_vault = Hash.new
18
21
  secrets_from_vault[prefix] = JSON(list_recursive(list_prefix).to_json)
@@ -1,3 +1,3 @@
1
1
  module Sanctum
2
- VERSION = "0.8.5.rc1"
2
+ VERSION = "0.8.5.rc2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sanctum
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.5.rc1
4
+ version: 0.8.5.rc2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Corban Raun
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-02-14 00:00:00.000000000 Z
11
+ date: 2019-02-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: vault
@@ -160,6 +160,8 @@ files:
160
160
  - docker-compose.override.yml_sample
161
161
  - docker-compose.test.yml
162
162
  - docker-compose.yml
163
+ - examples/single_target/example_policy.hcl
164
+ - examples/single_target/sanctum.yaml
163
165
  - lib/sanctum.rb
164
166
  - lib/sanctum/cli.rb
165
167
  - lib/sanctum/colorize_string.rb