chef-vault 3.3.0 → 4.1.11
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 +5 -5
- data/Gemfile +32 -6
- data/bin/chef-vault +5 -5
- data/chef-vault.gemspec +7 -26
- data/lib/chef/knife/mixin/helper.rb +29 -1
- data/lib/chef/knife/vault_admins.rb +5 -1
- data/lib/chef/knife/vault_base.rb +23 -13
- data/lib/chef/knife/vault_create.rb +26 -23
- data/lib/chef/knife/vault_delete.rb +4 -2
- data/lib/chef/knife/vault_download.rb +2 -2
- data/lib/chef/knife/vault_edit.rb +4 -4
- data/lib/chef/knife/vault_isvault.rb +4 -4
- data/lib/chef/knife/vault_itemtype.rb +4 -4
- data/lib/chef/knife/vault_list.rb +5 -5
- data/lib/chef/knife/vault_refresh.rb +7 -7
- data/lib/chef/knife/vault_remove.rb +19 -16
- data/lib/chef/knife/vault_rotate_all_keys.rb +5 -4
- data/lib/chef/knife/vault_rotate_keys.rb +3 -3
- data/lib/chef/knife/vault_show.rb +8 -10
- data/lib/chef/knife/vault_update.rb +38 -24
- data/lib/chef-vault/actor.rb +9 -7
- data/lib/chef-vault/chef_api.rb +4 -4
- data/lib/chef-vault/exceptions.rb +3 -0
- data/lib/chef-vault/item.rb +57 -21
- data/lib/chef-vault/item_keys.rb +35 -9
- data/lib/chef-vault/mixins.rb +2 -2
- data/lib/chef-vault/version.rb +1 -1
- data/lib/chef-vault.rb +8 -8
- metadata +8 -135
- data/.github/CODEOWNERS +0 -2
- data/.gitignore +0 -33
- data/.rspec +0 -2
- data/.rubocop.yml +0 -6
- data/.simplecov +0 -6
- data/.travis.yml +0 -19
- data/Changelog.md +0 -134
- data/DEMO.md +0 -60
- data/KNIFE_EXAMPLES.md +0 -256
- data/README.md +0 -333
- data/Rakefile +0 -50
- data/THEORY.md +0 -363
- data/UPGRADE.md +0 -55
- data/appveyor.yml +0 -32
- data/features/clean.feature +0 -23
- data/features/clean_on_refresh.feature +0 -27
- data/features/clean_unknown_clients.feature +0 -45
- data/features/detect_and_warn_v1_vault.feature +0 -14
- data/features/isvault.feature +0 -29
- data/features/itemtype.feature +0 -24
- data/features/step_definitions/chef-databag.rb +0 -9
- data/features/step_definitions/chef-repo.rb +0 -72
- data/features/step_definitions/chef-vault.rb +0 -151
- data/features/step_definitions/chef_databagitem.rb +0 -9
- data/features/support/env.rb +0 -14
- data/features/vault_create.feature +0 -63
- data/features/vault_list.feature +0 -31
- data/features/vault_show.feature +0 -45
- data/features/vault_show_vaultname.feature +0 -21
- data/features/vault_update.feature +0 -18
- data/features/verify_id_matches.feature +0 -10
- data/features/wrong_private_key.feature +0 -13
- data/hooks/pre-commit +0 -43
- data/spec/chef-vault/actor_spec.rb +0 -247
- data/spec/chef-vault/certificate_spec.rb +0 -37
- data/spec/chef-vault/chef_api_spec.rb +0 -39
- data/spec/chef-vault/item_keys_spec.rb +0 -263
- data/spec/chef-vault/item_spec.rb +0 -360
- data/spec/chef-vault/user_spec.rb +0 -36
- data/spec/chef-vault_spec.rb +0 -65
- data/spec/spec_helper.rb +0 -91
- data/tasks/github_changelog_generator.rb +0 -30
data/THEORY.md
DELETED
@@ -1,363 +0,0 @@
|
|
1
|
-
# How chef-vault works
|
2
|
-
|
3
|
-
## The Problem
|
4
|
-
|
5
|
-
Chef provides [encrypted data bags](https://docs.chef.io/chef/essentials_data_bags.html)
|
6
|
-
as part of the core software, but leaves the problem of key
|
7
|
-
distribution up to end users. Encrypted data bags are
|
8
|
-
symmetrically encrypted, and so you have to distribute the
|
9
|
-
decryption key out-of-band to your nodes (e.g. baking it into
|
10
|
-
your image or pushing it to the system before running
|
11
|
-
chef-client).
|
12
|
-
|
13
|
-
## The Solution
|
14
|
-
|
15
|
-
Every node managed by chef has an associated client object
|
16
|
-
on the Chef Server. The client object has the public half of
|
17
|
-
an RSA keypair. The private half only lives on the node,
|
18
|
-
typically in `/etc/chef/client.pem`.
|
19
|
-
|
20
|
-
Every API user on the chef server also has an RSA keypair.
|
21
|
-
This is typically kept in your `~/.chef` directory in PEM
|
22
|
-
format. Like nodes, the public half is stored on the Chef
|
23
|
-
server.
|
24
|
-
|
25
|
-
chef-vault creates an encrypted data bag which is symmetrically
|
26
|
-
encrypted using a random secret (a 32-byte string generated
|
27
|
-
using [SecureRandom.random_bytes](http://ruby-doc.org/stdlib-2.1.2/libdoc/securerandom/rdoc/SecureRandom.html#method-c-random_bytes)). We'll refer to this secret as the 'shared secret' through
|
28
|
-
the rest of this document.
|
29
|
-
|
30
|
-
A vault has a list of administrative users and a list of
|
31
|
-
clients. The shared secret is asymmetrically encrypted
|
32
|
-
for each of the administrators and clients using their public
|
33
|
-
key (a separate copy for each).
|
34
|
-
|
35
|
-
The administrators of a vault are API users named explicitly
|
36
|
-
when the vault is created. The clients can be provided
|
37
|
-
explicitly, but are more often determined by running a SOLR
|
38
|
-
query against the Chef server. The query is stored as part
|
39
|
-
of the \_keys data bag so that the clients can be updated by
|
40
|
-
re-executing the search.
|
41
|
-
|
42
|
-
The asymmmetrically encrypted keys are stored in a second
|
43
|
-
data bag item whose name is appended with \_keys
|
44
|
-
|
45
|
-
## Data Bag Structure
|
46
|
-
|
47
|
-
These examples assume that I have two nodes in my Chef
|
48
|
-
server/organization, named 'one' and 'two'. I also have
|
49
|
-
two administrators named 'alice' and 'bob'.
|
50
|
-
|
51
|
-
Given a file named `item.json` containing the following:
|
52
|
-
|
53
|
-
```json
|
54
|
-
{ "foo": "bar" }
|
55
|
-
```
|
56
|
-
|
57
|
-
Running
|
58
|
-
|
59
|
-
> knife vault create foo bar -A alice,bob -S '*:*' -J item.json
|
60
|
-
|
61
|
-
will create a data bag named 'foo' and two data bag items
|
62
|
-
within named 'bar' and 'bar_keys':
|
63
|
-
|
64
|
-
> knife data bag show foo
|
65
|
-
bar
|
66
|
-
bar_keys
|
67
|
-
|
68
|
-
The 'bar' item contains the symmetrically encrypted version
|
69
|
-
of the JSON data:
|
70
|
-
|
71
|
-
> knife data bag show -F json foo bar
|
72
|
-
{
|
73
|
-
"id": "bar",
|
74
|
-
"foo": {
|
75
|
-
"encrypted_data": "k9On2aJxnLDRwOeCr60l0C41XjIJ2+5Xu0AYFbmSvFw=\n",
|
76
|
-
"iv": "oKeiEkIlaspvhKghee30GA==\n",
|
77
|
-
"version": 1,
|
78
|
-
"cipher": "aes-256-cbc"
|
79
|
-
}
|
80
|
-
}
|
81
|
-
|
82
|
-
(this is a standard Chef encrypted data bag)
|
83
|
-
|
84
|
-
The 'bar_keys' item contains four copies of the asymetrically
|
85
|
-
encrypted shared secret:
|
86
|
-
|
87
|
-
> knife data bag show -F json foo bar_keys
|
88
|
-
{
|
89
|
-
"id": "bar_keys",
|
90
|
-
"admins": [
|
91
|
-
"alice",
|
92
|
-
"bob"
|
93
|
-
],
|
94
|
-
"clients": [
|
95
|
-
"one",
|
96
|
-
"two"
|
97
|
-
],
|
98
|
-
"search_query": "*:*",
|
99
|
-
"alice": "MW7hOvoc7XvYHJbbm0gWAaLNbVcHnxv5YDMnYsjiK/F1qxnFrY4X8pTwzgUI\nRsZuREpEpCSWY9C23ESolTHnBtgEHkR6Xe74NFUr9OURiAGljZL9zEzVUFJu\npds8pWjgGnqpwULxiPZT96xKEw+BnMy0ipYChdF2iaJtQzVAlIzXZoPaOXeH\nJPd1dwmD/G0X2nK0+cNEnJGUP6gideMun3S+dTN9rpP0/7bInjNRPAAXV5yY\nKNRBFgtFyG828B9uXXJ8wXaYYOzp7VLK4ehJw25g5VNkMttqNQVWyIbxGirf\nuvys/PTlCXzLkJ3+e0X5q4ZSotQ+1zJ5UVs16VOChQ==\n",
|
100
|
-
"bob": "h9qvmFyR3ygYUQgoW42ABIeCov16cSyYFlj9wKrscLFDzhs0jRrFRdvpcBBl\nqU3Glk79Y898L3C4+/EYomi2I7/EuxZozP+wgeTJDIcXQdeZwEWxGzY1JZq2\nxZYezdoWKATysAtPJEtNIPRzOGiloq+QanHDrxq3JVvZrJ/L5fE0eyV0Nh3T\nbX4X0KzZ4LzeGeUCXXOVa9C2rEHpf61PsMF79iAnULDpD++YdxDGHv6KgHJS\nVENHvyIWi4erRGrcwZRq709iB1BRm/14Zb9ZzZT/HcHIw5P47Ht0wgZ8x71V\nbhAjK410AWG9QtefDf6ybD/ERkKgVjeqcZ57TysdvQ==\n",
|
101
|
-
"one": "Ugwpeq2du2RqEzAcn1GA+Uj+dW9fHq7+coCT4LWD2CLo9og9Qu7MSkwuZXaj\nZngl31skSCyvE15ZVhhXilkwmJmrOoEU0B5FlbZTzjHxlq/ga2MhemXmASAH\nyu39if2fb++sE/g5RLy1A9EQs7oeVY53BLZCtENA5XHGjMA1WoBi1PfQTpUs\nZZKW604vs4i/zw88j1Np5o7xb77Wt7zZQsRS+uLxp7qWOTPaT85usChk5ygS\nFrPNZF/F95ODe74o6qwxAtQhKroEeUV6GSWCB2M9FTIoGH+Fhj7oDSiLT1AA\n4VqF4mCMuVMeAM2GTx5IvdIYja2GV7DbomTBNYsGiA==\n",
|
102
|
-
"two": "yO6eaCnDmNnQP5d1h1LxZyQdHhYh0BvhBhauVBv8RXWuyuY/8qC7iREPlN52\nRFCr38BStHO9/D4m+uv6SnJhKREe99eOtpddSXD92K/I4bMSCszC+/TmaZWj\nNibZonivam1SuutMbh6WPlHT6/yjIXb1w0cXxple5R+WmPttuMj13V0at0wY\nWMg4JC5/PpYoX8qfmUKvcrVxqFdbQ0YlgAzzdJwzWJOpN+ZEfiFSJopREt6L\n2wSkWezHylGmIWuGLmANSCdluk0oaEVyA1Panf8HL87tWlEc+BajY53JZxY1\n3YIZNWpelU6W/Nl8zu8R206ksKNNMk0yuhd++7F+yw==\n"
|
103
|
-
}
|
104
|
-
|
105
|
-
It also contains the list of administrators and clients for
|
106
|
-
which the key is encrypted and the query used to choose which
|
107
|
-
clients can decrypt the vault.
|
108
|
-
|
109
|
-
In practice, the search query would not be `*:*`. More common
|
110
|
-
practice is to select which nodes can decrypt the vault based
|
111
|
-
on characteristics like:
|
112
|
-
|
113
|
-
* which recipes are in the node's runlist
|
114
|
-
* which chef environment the node belongs to
|
115
|
-
* what OS or platform the node runs
|
116
|
-
* attributes collected by Ohai Plugins (such as AWS tags).
|
117
|
-
|
118
|
-
While there are four copies of the shared secret, any single
|
119
|
-
user or node will only be able to decrypt one of the copies,
|
120
|
-
because no user or node (should) have more than one private key.
|
121
|
-
|
122
|
-
Likewise, a node or user for whom the vault was not encrypted
|
123
|
-
is able to see the contents of the 'bar_keys' data bag,
|
124
|
-
but since they lack a private key that can decrypt any of the
|
125
|
-
copies of the shared secret, they cannot access the 'bar' encrypted
|
126
|
-
data bag item.
|
127
|
-
|
128
|
-
As alice or bob, I can show the contents of the vault:
|
129
|
-
|
130
|
-
> knife vault show -F json foo bar
|
131
|
-
{
|
132
|
-
"id": "bar",
|
133
|
-
"foo": "bar"
|
134
|
-
}
|
135
|
-
|
136
|
-
Or in a recipe that runs on node one or two:
|
137
|
-
|
138
|
-
vaultitem = ChefVault::Item.load('foo', 'bar')
|
139
|
-
Chef::Log.debug "the vault value foo is #{vaultitem['foo']}"
|
140
|
-
|
141
|
-
## Use Cases
|
142
|
-
|
143
|
-
In these use cases, assume there are three API clients:
|
144
|
-
|
145
|
-
* alice (Administrator)
|
146
|
-
* bob (Administrator)
|
147
|
-
* charlie (Normal User)
|
148
|
-
|
149
|
-
And three nodes, of the given platform:
|
150
|
-
|
151
|
-
* one (Linux, Ubuntu)
|
152
|
-
* two (Linux, CentOS)
|
153
|
-
* three (Windows)
|
154
|
-
|
155
|
-
The use cases are written from the perspective of 'client'
|
156
|
-
mode using a Chef server, but work similarly in 'solo' mode
|
157
|
-
assuming that the commands are run from the directory containing
|
158
|
-
the Chef repository.
|
159
|
-
|
160
|
-
We also assume that the commands are being run from a Linux
|
161
|
-
terminal session (paths to key files are slightly different
|
162
|
-
on Windows)
|
163
|
-
|
164
|
-
### Creating a Vault
|
165
|
-
|
166
|
-
The actor in this case is alice. When she runs
|
167
|
-
|
168
|
-
knife vault create foo bar -S os:linux -A alice,bob
|
169
|
-
|
170
|
-
After editing the empty JSON document and saving it, chef-vault
|
171
|
-
generates a random 32 byte string for the shared secret.
|
172
|
-
|
173
|
-
A new data bag named 'foo/bar_keys' is created. chef-vault then
|
174
|
-
executes the search 'os:linux' against the node index.
|
175
|
-
|
176
|
-
For each of the nodes returned from the search (one and two), the
|
177
|
-
public keys are fetched for the like-named client and the shared
|
178
|
-
secret is encrypted using it. The client name is added to the
|
179
|
-
'clients' array in the bar_keys data bag item. The node-specific
|
180
|
-
encrypted copy of the shared secret is stored in the bar_keys
|
181
|
-
data bag item, keyed by node name.
|
182
|
-
|
183
|
-
The search query is also stored in the keys data bag, for use
|
184
|
-
during future update or refresh operations.
|
185
|
-
|
186
|
-
In a similar fashion, the public keys for alice and bob are
|
187
|
-
retrieved from the Chef server and the shared secret is
|
188
|
-
asymmetrically encrypted for each. The names of the admins are
|
189
|
-
stored in the 'admins' array in the bar_keys data bag item.
|
190
|
-
|
191
|
-
At this point, the bar_keys data bag item is only present in
|
192
|
-
memory. It is saved to the server, and if that operation fails
|
193
|
-
the vault create throws an error.
|
194
|
-
|
195
|
-
The data bag 'foo' is then fetched (or created if it does
|
196
|
-
not already exist). An encrypted data bag item named 'bar'
|
197
|
-
is created, encrypted with the shared secret. The data bag
|
198
|
-
item is saved to the Chef server.
|
199
|
-
|
200
|
-
### Decrypting a Vault using knife
|
201
|
-
|
202
|
-
The actor in this case is alice. When she runs
|
203
|
-
|
204
|
-
knife vault show foo bar
|
205
|
-
|
206
|
-
chef-vault fetches the data bag item foo/bar_keys. It
|
207
|
-
then looks for a key in the data bag named 'alice'. The value
|
208
|
-
of this key is the asymmetrically encrypted copy of the shared
|
209
|
-
secret specific to alice.
|
210
|
-
|
211
|
-
chef-vault then uses alice's private key (typically `~/.chef/alice.pem`) to decrypt the shared secret.
|
212
|
-
|
213
|
-
If the \_keys data bag did not have a key 'alice', chef-vault
|
214
|
-
would have emitted an error to the effect that the vault was not
|
215
|
-
encrypted for her and that someone else who does have access to
|
216
|
-
the bag needs to add her as an administrator before she can view
|
217
|
-
it.
|
218
|
-
|
219
|
-
Using the decrypted shared secret, chef-vault loads the Chef
|
220
|
-
encrypted data bag foo/bar. The plaintext contents of this bag
|
221
|
-
are then displayed to alice. If the appropriate options are
|
222
|
-
provided on the command line, additional information such as
|
223
|
-
the list of administrators, the list of clients and the search
|
224
|
-
query (all of which are stored in the bar_keys data bag item)
|
225
|
-
are also displayed.
|
226
|
-
|
227
|
-
### Decrypting a Vault in a Chef Recipe
|
228
|
-
|
229
|
-
The actor in this case is chef-client (running as root) on
|
230
|
-
the server 'one'.
|
231
|
-
|
232
|
-
Assuming that the recipe contains code such as this:
|
233
|
-
|
234
|
-
chef_gem 'chef-vault' do
|
235
|
-
compile_time true if respond_to?(:compile_time)
|
236
|
-
end
|
237
|
-
require 'chef-vault'
|
238
|
-
vaultitem = ChefVault::Item.load('foo', 'bar')
|
239
|
-
|
240
|
-
chef-vault fetches the data bag item foo/bar_keys. It
|
241
|
-
then looks for a key in the data bag named 'one'. The value
|
242
|
-
of this key is the asymetrically encrypted copy of the shared
|
243
|
-
secret specific to the node 'one'.
|
244
|
-
|
245
|
-
chef-vault then uses the private key of node one (typically
|
246
|
-
`/etc/chef/client.pem`) to decrypt the shared secret.
|
247
|
-
|
248
|
-
If the \_keys data bag did not have a key 'one', chef-vault
|
249
|
-
would have thrown an exception indicating that the vault was
|
250
|
-
not encrypted for the node and that an administrator needs to
|
251
|
-
refresh the vault (possibly after updating the search query)
|
252
|
-
before the recipe can use the vault.
|
253
|
-
|
254
|
-
Uncaught, this would cause chef-client to abort in the compile
|
255
|
-
phase. Robust recipes can be written that catch the exception
|
256
|
-
and do other things, such as only converging resources that do
|
257
|
-
not need the secrets, or sending an alert so that a human can
|
258
|
-
update the vault, or even sending a request to a work queue
|
259
|
-
to automatically update the vault.
|
260
|
-
|
261
|
-
Using the decrypted shared secret, chef-vault loads the Chef
|
262
|
-
encrypted data bag foo/bar. The plaintext contents of this bag
|
263
|
-
are now available to the recipe in the local variable named
|
264
|
-
'vaultitem'. At this point the data looks and feels like a
|
265
|
-
normal data bag (i.e. it behaves in a hash-like way)
|
266
|
-
|
267
|
-
### Adding a new Administrator
|
268
|
-
|
269
|
-
The actor in this case is Alice, who wants to make charlie
|
270
|
-
an administrator of the vault. We assume she is working with
|
271
|
-
the vault created in the section 'Creating a Vault'. When she
|
272
|
-
runs
|
273
|
-
|
274
|
-
knife vault update -A charlie foo bar
|
275
|
-
|
276
|
-
This vault is decrypted in the same fashion as described
|
277
|
-
in 'Decrypting a Vault using knife'. This results in the
|
278
|
-
plain text of the shared secret being available in memory.
|
279
|
-
|
280
|
-
The search query is run again, returning the same two nodes.
|
281
|
-
The shared secret is then asymmetrically encrypted for each
|
282
|
-
as described in 'Creating a Vault'.
|
283
|
-
|
284
|
-
The shared secret is then asymmetrically encrypted for all
|
285
|
-
of the admins (alice, bob and the newly-added charlie) as
|
286
|
-
described in 'Creating a Vault'.
|
287
|
-
|
288
|
-
The data bag item 'foo/bar_keys' is then saved, followed by the
|
289
|
-
data bag item 'foo/bar'.
|
290
|
-
|
291
|
-
charlie can now view the contents of the vault using `knife
|
292
|
-
vault show` because there is a now a copy of the shared
|
293
|
-
secret that he can access.
|
294
|
-
|
295
|
-
### Adding a new Node
|
296
|
-
|
297
|
-
The actor in this case is Alice, who wants to encrypt the
|
298
|
-
value for all nodes instead of just those running linux.
|
299
|
-
When she runs
|
300
|
-
|
301
|
-
knife vault update -S '*:*' foo bar
|
302
|
-
|
303
|
-
This vault is decrypted in the same fashion as described
|
304
|
-
in 'Decrypting a Vault using knife'. This results in the
|
305
|
-
plain text of the shared secret being available in memory.
|
306
|
-
|
307
|
-
The search query is run again, returning three nodes this
|
308
|
-
time: one, two and three. The shared secret is then
|
309
|
-
asymmetrically encrypted for each as described in 'Creating
|
310
|
-
a Vault'.
|
311
|
-
|
312
|
-
The data bag item 'foo/bar_keys' is then saved, followed by the
|
313
|
-
data bag item 'foo/bar'.
|
314
|
-
|
315
|
-
Node three can now use the vault in a recipe because
|
316
|
-
there is a now a copy of the shared secret that he it access.
|
317
|
-
|
318
|
-
### Rotating Keys
|
319
|
-
|
320
|
-
Rotating keys chooses a new shared secret for the bag and
|
321
|
-
encrypts it for all of the administrators and clients
|
322
|
-
who currently have access. Unlike the `knife vault update`
|
323
|
-
command, the search query is not re-run to pick up new clients.
|
324
|
-
|
325
|
-
The actor in this case is Alice, who wants to rotate the keys
|
326
|
-
(perhaps to conform to an internal security policy). When
|
327
|
-
she runs
|
328
|
-
|
329
|
-
knife vault rotate_keys foo bar
|
330
|
-
|
331
|
-
The vault is decrypted in the same fashion as described
|
332
|
-
in 'Decrypting a Vault using knife'.
|
333
|
-
|
334
|
-
chef-vault generates a new 32-byte random string. It then
|
335
|
-
creates an asymmetrically encrypted version of the new
|
336
|
-
shared secret for each of the clients and administrators
|
337
|
-
listed in the data bag item 'foo/bar_keys'.
|
338
|
-
|
339
|
-
The data bag item 'foo/bar_keys' is then saved, followed by the
|
340
|
-
data bag item 'foo/bar'.
|
341
|
-
|
342
|
-
## Failure Scenarios
|
343
|
-
|
344
|
-
Because the secret data is just a normal Chef encrypted
|
345
|
-
data bag item, the keys are stored separately in a data bag
|
346
|
-
suffixed with \_keys. When the vault is saved, the data bag
|
347
|
-
item containing the keys is saved before the encrypted data
|
348
|
-
bag is.
|
349
|
-
|
350
|
-
If the key data bag item save succeeds, but the vault data bag
|
351
|
-
item fails, the vault will be in an unsable state, because
|
352
|
-
it will be encrypted with the old shared secret, but the keys
|
353
|
-
data bag item contains asymmetrically encrypted copies of the
|
354
|
-
new shared secret.
|
355
|
-
|
356
|
-
This can be mitigated by using solo mode, which writes the
|
357
|
-
encrypted data bags to JSON files on disk rather than making
|
358
|
-
changes using the Chef Server API. Another option is to use
|
359
|
-
`knife download` to temporarily store a on-disk version of the
|
360
|
-
vault data bag item and the keys data bag item before making
|
361
|
-
changes. If any probems are encountered, the old copy of
|
362
|
-
the data bags can be loaded back into the Chef server using
|
363
|
-
`knife data bag from file`.
|
data/UPGRADE.md
DELETED
@@ -1,55 +0,0 @@
|
|
1
|
-
# UPGRADING A v1 VAULT to v2
|
2
|
-
|
3
|
-
chef-vault v2 added metadata to the vault to keep track of
|
4
|
-
which secrets belong to clients and which belong to admins,
|
5
|
-
as well as the search query to use during a `knife vault refresh`
|
6
|
-
operation.
|
7
|
-
|
8
|
-
You can use chef-vault v2 to decrypt v1 vaults, but the management
|
9
|
-
operations are unable to intuit which of the secrets belong to
|
10
|
-
clients and which belong to admins. Fixing this error thus requires
|
11
|
-
some manual intervention.
|
12
|
-
|
13
|
-
If you attempt to use the management operations (refresh, update, etc.)
|
14
|
-
on a v1 vault, you will get this error:
|
15
|
-
|
16
|
-
ChefVault::Exceptions::V1Format: cannot manage a v1 vault. See UPGRADE.md for help
|
17
|
-
|
18
|
-
To fix this, you need to edit the data bag item by hand. Assuming a
|
19
|
-
vault 'foo' with an item 'bar', run:
|
20
|
-
|
21
|
-
knife data bag edit foo bar_keys
|
22
|
-
|
23
|
-
This will present you with a JSON representation of the extra data
|
24
|
-
bag item managed by chef-vault. It will have an id key as well as a key
|
25
|
-
for every user for whom the vault item is encrypted:
|
26
|
-
|
27
|
-
{
|
28
|
-
"id" : "bar_keys",
|
29
|
-
"james" : "iWdGgm...\n",
|
30
|
-
"one" : "RjJ4rlh....\n",
|
31
|
-
"two" : "NHJlqnfd9...\n",
|
32
|
-
"three" : "GjXkrxq...\n"
|
33
|
-
}
|
34
|
-
|
35
|
-
Add keys for 'admins', 'clients' and 'search_query':
|
36
|
-
|
37
|
-
{
|
38
|
-
"id" : "bar_keys",
|
39
|
-
"james" : "iWdGgm...\n",
|
40
|
-
"one" : "RjJ4rlh....\n",
|
41
|
-
"two" : "NHJlqnfd9...\n",
|
42
|
-
"three" : "GjXkrxq...\n",
|
43
|
-
"admins": [],
|
44
|
-
"clients": [],
|
45
|
-
"search_query": ""
|
46
|
-
}
|
47
|
-
|
48
|
-
Save the edited data bag and run knife vault update with the appropriate values to populate those keys:
|
49
|
-
|
50
|
-
knife vault update foo bar -S 'name:*' -A james
|
51
|
-
|
52
|
-
(set your search query to something appropriate for your environment)
|
53
|
-
|
54
|
-
v2.7.0 of chef-vault may add some automation to this step, but for now this
|
55
|
-
provides a way to upgrade without breaking your ability to manage things.
|
data/appveyor.yml
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
version: "master-{build}"
|
2
|
-
|
3
|
-
os: Windows Server 2012 R2
|
4
|
-
platform:
|
5
|
-
- x64
|
6
|
-
|
7
|
-
clone_depth: 1
|
8
|
-
skip_tags: true
|
9
|
-
skip_branch_with_pr: true
|
10
|
-
branches:
|
11
|
-
only:
|
12
|
-
- master
|
13
|
-
|
14
|
-
# caching vendor/bundle appears to break horribly in the face of gems checked out of git
|
15
|
-
# cache:
|
16
|
-
# - vendor/bundle
|
17
|
-
|
18
|
-
install:
|
19
|
-
- ps: iex (irm https://omnitruck.chef.io/install.ps1); Install-Project -Project chefdk -channel stable
|
20
|
-
- bundle config --local path vendor/bundle
|
21
|
-
- SET CI=true
|
22
|
-
- SET BUNDLE_WITHOUT=changelog:style
|
23
|
-
|
24
|
-
build_script:
|
25
|
-
- ps: c:\opscode\chefdk\bin\chef.bat shell-init powershell | iex
|
26
|
-
- bundle install || bundle install || bundle install
|
27
|
-
|
28
|
-
test_script:
|
29
|
-
- SET SPEC_OPTS=--format progress
|
30
|
-
- c:\opscode\chefdk\bin\chef.bat exec bundle exec rake spec
|
31
|
-
# aruba on windows seems pretty terribadly broken: https://github.com/cucumber/aruba/pull/422
|
32
|
-
# - c:\opscode\chefdk\bin\chef.bat exec bundle exec cucumber
|
data/features/clean.feature
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
Feature: clean client keys
|
2
|
-
When updating a vault item, chef-vault normally performs the
|
3
|
-
saved or specified query and encrypts the item for all nodes
|
4
|
-
returned. It does not remove old client keys from the vault
|
5
|
-
item keys data bag, which will grow over time. Using the
|
6
|
-
--clean switch will cause all client keys to be removed from
|
7
|
-
the data bag before encrypting the item for all clients
|
8
|
-
returned by the query
|
9
|
-
|
10
|
-
Scenario: Do not clean client keys on update
|
11
|
-
Given a local mode chef repo with nodes 'one,two,three'
|
12
|
-
And I create a vault item 'test/item' containing the JSON '{"foo": "bar"}' encrypted for 'one,two'
|
13
|
-
Then the vault item 'test/item' should be encrypted for 'one,two'
|
14
|
-
And I update the vault item 'test/item' to be encrypted for 'two,three'
|
15
|
-
Then the vault item 'test/item' should be encrypted for 'one,two,three'
|
16
|
-
|
17
|
-
Scenario: Clean client keys on update
|
18
|
-
Given a local mode chef repo with nodes 'one,two,three'
|
19
|
-
And I create a vault item 'test/item' containing the JSON '{"foo": "bar"}' encrypted for 'one,two'
|
20
|
-
Then the vault item 'test/item' should be encrypted for 'one,two'
|
21
|
-
And I update the vault item 'test/item' to be encrypted for 'two,three' with the clean option
|
22
|
-
Then the vault item 'test/item' should be encrypted for 'two,three'
|
23
|
-
And the vault item 'test/item' should not be encrypted for 'one'
|
@@ -1,27 +0,0 @@
|
|
1
|
-
Feature: clean unknown clients on vault refresh
|
2
|
-
When refreshing a vault, new clients may be added if they match
|
3
|
-
the search query or client list, but old clients that no longer
|
4
|
-
exist will never be removed. The --clean-unknown-clients switch
|
5
|
-
will cause cause any unknown clients to be removed from the vault
|
6
|
-
item's access list as well
|
7
|
-
|
8
|
-
Scenario: Refresh without clean option
|
9
|
-
Given a local mode chef repo with nodes 'one,two,three'
|
10
|
-
And I create a vault item 'test/item' containing the JSON '{"foo": "bar"}' encrypted for 'one,two,three'
|
11
|
-
Then the vault item 'test/item' should be encrypted for 'one,two,three'
|
12
|
-
And I delete node 'one' from the Chef server
|
13
|
-
And I refresh the vault item 'test/item'
|
14
|
-
And the vault item 'test/item' should be encrypted for 'one,two,three'
|
15
|
-
And 'one,two,three' should be a client for the vault item 'test/item'
|
16
|
-
|
17
|
-
Scenario: Refresh with clean option
|
18
|
-
Given a local mode chef repo with nodes 'one,two,three'
|
19
|
-
And I create a vault item 'test/item' containing the JSON '{"foo": "bar"}' encrypted for 'one,two,three'
|
20
|
-
Then the vault item 'test/item' should be encrypted for 'one,two,three'
|
21
|
-
And I delete node 'one' from the Chef server
|
22
|
-
And I refresh the vault item 'test/item' with the 'clean-unknown-clients' option
|
23
|
-
Then the output should contain "Removing unknown client 'one'"
|
24
|
-
And the vault item 'test/item' should be encrypted for 'two,three'
|
25
|
-
And the vault item 'test/item' should not be encrypted for 'one'
|
26
|
-
And 'two,three' should be a client for the vault item 'test/item'
|
27
|
-
And 'one' should not be a client for the vault item 'test/item'
|
@@ -1,45 +0,0 @@
|
|
1
|
-
Feature: clean unknown clients on key rotation
|
2
|
-
When removing a client from a vault item, chef-vault normally
|
3
|
-
removes the key and then rotates the key. If a node has been
|
4
|
-
deleted in the meantime from the Chef server but not the vault,
|
5
|
-
the rotation will fail due to that client's public key missing.
|
6
|
-
Using the --clean-unknown-clients switch will cause any clients
|
7
|
-
that have been removed to be removed from the vault item's
|
8
|
-
access list as well
|
9
|
-
|
10
|
-
Scenario: Prune clients when rotating keys
|
11
|
-
Given a local mode chef repo with nodes 'one,two,three'
|
12
|
-
And I create a vault item 'test/item' containing the JSON '{"foo": "bar"}' encrypted for 'one,two,three'
|
13
|
-
Then the vault item 'test/item' should be encrypted for 'one,two,three'
|
14
|
-
And I delete node 'one' from the Chef server
|
15
|
-
And I rotate the keys for vault item 'test/item' with the 'clean-unknown-clients' option
|
16
|
-
Then the output should contain "Removing unknown client 'one'"
|
17
|
-
And the vault item 'test/item' should be encrypted for 'two,three'
|
18
|
-
And the vault item 'test/item' should not be encrypted for 'one'
|
19
|
-
And 'two,three' should be a client for the vault item 'test/item'
|
20
|
-
And 'one' should not be a client for the vault item 'test/item'
|
21
|
-
|
22
|
-
Scenario: Prune clients when rotating all keys
|
23
|
-
Given a local mode chef repo with nodes 'one,two,three'
|
24
|
-
And I create a vault item 'test/item' containing the JSON '{"foo": "bar"}' encrypted for 'one,two,three'
|
25
|
-
Then the vault item 'test/item' should be encrypted for 'one,two,three'
|
26
|
-
And I delete nodes 'one,two' from the Chef server
|
27
|
-
And I rotate all keys with the 'clean-unknown-clients' option
|
28
|
-
Then the output should contain "Removing unknown client 'one'"
|
29
|
-
And the output should contain "Removing unknown client 'two'"
|
30
|
-
And the vault item 'test/item' should be encrypted for 'three'
|
31
|
-
And the vault item 'test/item' should not be encrypted for 'one,two'
|
32
|
-
And 'three' should be a client for the vault item 'test/item'
|
33
|
-
And 'one,two' should not be a client for the vault item 'test/item'
|
34
|
-
|
35
|
-
Scenario: Prune clients when node gone but client exists
|
36
|
-
Given a local mode chef repo with nodes 'one,two,three'
|
37
|
-
And I create a vault item 'test/item' containing the JSON '{"foo": "bar"}' encrypted for 'one,two,three'
|
38
|
-
Then the vault item 'test/item' should be encrypted for 'one,two,three'
|
39
|
-
And I delete node 'one' from the Chef server
|
40
|
-
And I rotate the keys for vault item 'test/item' with the 'clean-unknown-clients' option
|
41
|
-
Then the output should contain "Removing unknown client 'one'"
|
42
|
-
And the vault item 'test/item' should be encrypted for 'two,three'
|
43
|
-
And the vault item 'test/item' should not be encrypted for 'one'
|
44
|
-
And 'two,three' should be a client for the vault item 'test/item'
|
45
|
-
And 'one' should not be a client for the vault item 'test/item'
|
@@ -1,14 +0,0 @@
|
|
1
|
-
Feature: Detect and Warn for v1 Vaults
|
2
|
-
chef-vault can read a v1 vault, but the management commands
|
3
|
-
tend to break when they try to reference v2 fields like
|
4
|
-
clients and admins. They should detect and warn when trying
|
5
|
-
to access a v1 vault
|
6
|
-
|
7
|
-
Scenario: Add search query to v1 vault
|
8
|
-
Given a local mode chef repo with nodes 'one,two,three' with admins 'bob'
|
9
|
-
And I create a vault item 'test/item' containing the JSON '{"foo": "bar"}' encrypted for 'one,two,three'
|
10
|
-
Then the vault item 'test/item' should be encrypted for 'one,two,three'
|
11
|
-
And 'one,two,three' should be a client for the vault item 'test/item'
|
12
|
-
And I downgrade the vault item 'test/item' to v1 syntax
|
13
|
-
And I try to add 'bob' as an admin for the vault item 'test/item'
|
14
|
-
Then the output should match /cannot manage a v1 vault. See UPGRADE.md for help/
|
data/features/isvault.feature
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
Feature: determine if a data bag item is a vault
|
2
|
-
If a data bag item is a vault, 'knife vault isvault VAULTNAME ITEMNAME'
|
3
|
-
should exit 0. Otherwise it should exit 1.
|
4
|
-
|
5
|
-
Scenario: detect vault item
|
6
|
-
Given a local mode chef repo with nodes 'one,two,three'
|
7
|
-
And I create a vault item 'test/item' containing the JSON '{"foo": "bar"}' encrypted for 'one,two,three'
|
8
|
-
And I check if the data bag item 'test/item' is a vault
|
9
|
-
Then the exit status should be 0
|
10
|
-
|
11
|
-
Scenario: detect vault item with keys in sparse mode
|
12
|
-
Given a local mode chef repo with nodes 'one,two,three'
|
13
|
-
And I create a vault item 'test/item' with keys in sparse mode containing the JSON '{"foo": "bar"}' encrypted for 'one,two,three'
|
14
|
-
And I check if the data bag item 'test/item' is a vault
|
15
|
-
Then the exit status should be 0
|
16
|
-
|
17
|
-
Scenario: detect non-vault item (encrypted data bag)
|
18
|
-
Given a local mode chef repo with nodes 'one,two,three'
|
19
|
-
And I create an empty data bag 'test'
|
20
|
-
And I create an encrypted data bag item 'test/item' containing the JSON '{"id": "item", "foo": "bar"}' with the secret 'sekrit'
|
21
|
-
And I check if the data bag item 'test/item' is a vault
|
22
|
-
Then the exit status should not be 0
|
23
|
-
|
24
|
-
Scenario: detect non-vault item (normal data bag)
|
25
|
-
Given a local mode chef repo with nodes 'one,two,three'
|
26
|
-
And I create an empty data bag 'test'
|
27
|
-
And I create a data bag item 'test/item' containing the JSON '{"id": "item", "foo": "bar"}'
|
28
|
-
And I check if the data bag item 'test/item' is a vault
|
29
|
-
Then the exit status should not be 0
|
data/features/itemtype.feature
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
Feature: determine the type of a data bag item
|
2
|
-
'knife vault itemtype VAULTNAME ITEMNAME' should output one of
|
3
|
-
'normal', 'encrypted', or 'vault' depending on what type of item
|
4
|
-
it detects
|
5
|
-
|
6
|
-
Scenario: detect vault item
|
7
|
-
Given a local mode chef repo with nodes 'one,two,three'
|
8
|
-
And I create a vault item 'test/item' containing the JSON '{"foo": "bar"}' encrypted for 'one,two,three'
|
9
|
-
And I check the type of the data bag item 'test/item'
|
10
|
-
Then the output should match /^vault$/
|
11
|
-
|
12
|
-
Scenario: detect non-vault item (encrypted data bag)
|
13
|
-
Given a local mode chef repo with nodes 'one,two,three'
|
14
|
-
And I create an empty data bag 'test'
|
15
|
-
And I create an encrypted data bag item 'test/item' containing the JSON '{"id": "item", "foo": "bar"}' with the secret 'sekrit'
|
16
|
-
And I check the type of the data bag item 'test/item'
|
17
|
-
Then the output should match /^encrypted$/
|
18
|
-
|
19
|
-
Scenario: detect non-vault item (normal data bag)
|
20
|
-
Given a local mode chef repo with nodes 'one,two,three'
|
21
|
-
And I create an empty data bag 'test'
|
22
|
-
And I create a data bag item 'test/item' containing the JSON '{"id": "item", "foo": "bar"}'
|
23
|
-
And I check the type of the data bag item 'test/item'
|
24
|
-
Then the output should match /^normal$/
|
@@ -1,9 +0,0 @@
|
|
1
|
-
When /^I create a data bag '(.+)' containing the JSON '(.+)'$/ do |bag, json|
|
2
|
-
write_file "item.json", json
|
3
|
-
run_simple "knife data bag create #{bag} -z -c knife.rb -d"
|
4
|
-
run_simple "knife data bag from_file #{bag} -z -c knife.rb item.json"
|
5
|
-
end
|
6
|
-
|
7
|
-
Given(/^I create an empty data bag '(.+)'$/) do |databag|
|
8
|
-
run_simple "knife data bag create #{databag} -z -c knife.rb", false
|
9
|
-
end
|