Browse Source

Spec: Pegleg secret generation and encryption

This patchset adds a spec outlining the work effort and high-level
implementation considerations for adding the ability to generate,
encrypt, and decrypt secrets from Pegleg.

Change-Id: Iacc99008be96a4b0bac145d5fa84143cc64e9b67
Story: 2003708
Task: 26363
Matt McEuen 7 months ago
parent
commit
d1fca12693
2 changed files with 372 additions and 8 deletions
  1. 0
    8
      specs/approved/_placeholder.rst
  2. 372
    0
      specs/approved/pegleg-secrets.rst

+ 0
- 8
specs/approved/_placeholder.rst View File

@@ -1,8 +0,0 @@
1
-.. placeholder:
2
-
3
-===========
4
-Placeholder
5
-===========
6
-
7
-This file is a placeholder and should be deleted when the first spec is moved
8
-to this directory.

+ 372
- 0
specs/approved/pegleg-secrets.rst View File

@@ -0,0 +1,372 @@
1
+..
2
+  This work is licensed under a Creative Commons Attribution 3.0 Unported
3
+  License.
4
+
5
+  http://creativecommons.org/licenses/by/3.0/legalcode
6
+
7
+.. index::
8
+   single: template
9
+   single: creating specs
10
+
11
+=======================================
12
+Pegleg Secret Generation and Encryption
13
+=======================================
14
+
15
+Pegleg is responsible for shepherding deployment manifest documents from their
16
+resting places in Git repositories to a consumable format that is ready
17
+for ingestion into Airship.  This spec expands its responsibility to
18
+account for secure generation and encryption of secrets that are
19
+required within an Airship-based deployment.
20
+
21
+Links
22
+=====
23
+
24
+The work to author and implement this spec will be tracked under this
25
+`Storyboard Story`_.
26
+
27
+Problem description
28
+===================
29
+
30
+Airship supports the ability to identify secret information
31
+required for functioning deployments, such as passwords and keys; to
32
+ingest it into the site in a least-privilege-oriented fashion; and
33
+to encrypt it at rest within Deckhand.  However, lifecycle management of
34
+the secrets outside the site should be made automatable and
35
+repeatable, to facilitate operational needs such as periodic password
36
+rotation, and to ensure that unencrypted secrets are only accessible by
37
+authorized individuals.
38
+
39
+Impacted components
40
+===================
41
+
42
+The following Airship components will be impacted by this solution:
43
+
44
+#. Pegleg: enhanced to generate, rotate, encrypt, and decrypt secrets.
45
+#. Promenade: PKICatalog will move to Pegleg.
46
+#. Treasuremap: site manifests augmented to support the updated Secrets schema.
47
+#. Airship-in-a-Bottle: site manifests augmented to support the updated
48
+   Secrets schema.
49
+
50
+Proposed change
51
+===============
52
+
53
+PeglegManagedDocument
54
+---------------------
55
+
56
+With this spec, the role of Pegleg grows from being a custodian of deployment
57
+manifests to additionally being the author of certain manifests.  A new YAML
58
+schema will be created to describe these documents:
59
+``pegleg/PeglegManagedDocument/v1``.
60
+Documents of this type will have one or both of the following data elements,
61
+although more may be added in the future: ``generated``, ``encrypted``.
62
+PeglegManagedDocuments serve as wrappers around other documents, and the
63
+wrapping serves to capture additional metadata that is necessary, but
64
+separate from the managed document proper.
65
+The managed document data will live in the ``data.managedDocument`` portion
66
+of a PeglegManagedDocument.
67
+
68
+If a PeglegManagedDocument is ``generated``, then its contents have been
69
+created by Pegleg, and it must include provenance information per this
70
+example::
71
+
72
+  schema: pegleg/PeglegManagedDocument/v1
73
+  metadata:
74
+    name: matches-document-name
75
+    schema: deckhand/Document/v1
76
+    labels:
77
+      matching: wrapped-doc
78
+    layeringDefinition:
79
+      abstract: false
80
+      # Pegleg will initially support generation at site level only
81
+      layer: site
82
+    storagePolicy: encrypted
83
+  data:
84
+    generated:
85
+      at: <timestamp>
86
+      by: <author>
87
+      specifiedBy:
88
+        repo: <...>
89
+        reference: <git ref-head or similar>
90
+        path: <PKICatalog/PassphraseCatalog details>
91
+    managedDocument:
92
+      metadata:
93
+        storagePolicy: encrypted
94
+        schema: <as appropriate for wrapped document>
95
+        <metadata from parent PeglegManagedDocument>
96
+        <any other metadata as appropriate>
97
+      data: <generated data>
98
+
99
+If a PeglegManagedDocument is ``encrypted``, then its contents have been
100
+encrypted by Pegleg, and it must include provenance information per this
101
+example::
102
+
103
+  schema: pegleg/PeglegManagedDocument/v1
104
+  metadata:
105
+    name: matches-document-name
106
+    schema: deckhand/Document/v1
107
+    labels:
108
+      matching: wrapped-doc
109
+    layeringDefinition:
110
+      abstract: false
111
+      layer: matching-wrapped-doc
112
+    storagePolicy: encrypted
113
+  data:
114
+    encrypted:
115
+      at: <timestamp>
116
+      by: <author>
117
+    managedDocument:
118
+      metadata:
119
+        storagePolicy: encrypted
120
+        schema: <as appropriate for wrapped document>
121
+        <metadata from parent PeglegManagedDocument>
122
+        <any other metadata as appropriate>
123
+      data: <encrypted string blob>
124
+
125
+A PeglegManagedDocument that is both generated via a Catalog, and encrypted
126
+(as specified by the catalog) will contain both ``generated`` and
127
+``encrypted`` stanzas.
128
+
129
+Note that this ``encrypted`` has a different purpose than the Deckhand
130
+``storagePolicy: encrypted`` metadata, which indicates an *intent* for Deckhand
131
+to store a document encrypted at rest in the cluster.  The two can be used
132
+together to ensure security, however:  if a document is marked as
133
+``storagePolicy: encrypted``, then automation may validate that it is only
134
+persisted (e.g. to a Git repository) if it is in fact encrypted within
135
+a PeglegManagedDocument.
136
+
137
+Document Generation
138
+-------------------
139
+
140
+Document generation will follow the pattern established by Promenade's
141
+PKICatalog pattern.  In fact, PKICatalog management responsibility will move
142
+to Pegleg as part of this effort.  The types of documents that are expected
143
+to be generated are certificates and keys, which are defined via PKICatalog
144
+documents now, and passphrases, which will be defined via a new
145
+``pegleg/PassphraseCatalog/v1`` document.  Longer-term, these specifications
146
+may be combined, or split further (into a CertificateCatalog and
147
+KeypairCatalog), but this is not needed in the initial implementation in
148
+Pegleg.  A collection of manifests
149
+may define more than one of each of these secret catalog documents if desired.
150
+
151
+The documents generated via PKICatalog and PassphraseCatalog will follow the
152
+PeglegManagedDocument schema above; note that this is a change to existing
153
+PKICatalog behavior.  The PKICatalog schema and associated code should be
154
+copied to Pegleg (and renamed to ``pegleg/PKICatalog/v1``), and during a
155
+transition period the old and new PKICatalog implementations will exist
156
+side-by-side with slightly different semantics.  Promenade's PKICatalog can
157
+be removed once all deployment manifests have been updated to use the new one.
158
+
159
+Pegleg will place generated document files in ``<site>/secrets/passphrases/``,
160
+``<site>/secrets/certificates``, or ``<site>/secrets/keypairs`` as appropriate:
161
+
162
+* The generated filenames for passphrases will follow the pattern
163
+  ``<passphrase-doc-name>.yaml``.
164
+* The generated filenames for certificate authorities will follow the pattern
165
+  ``<ca-name>_ca.yaml``.
166
+* The generated filenames for certificates will follow the pattern
167
+  ``<ca-name>_<certificate-doc-name>_certificate.yaml``.
168
+* The generated filenames for certificate keys will follow the pattern
169
+  ``<ca-name>_<certificate-doc-name>_key.yaml``.
170
+* The generated filenames for keypairs will follow the pattern
171
+  ``<keypair-doc-name>.yaml``.
172
+* Dashes in the document names will be converted to underscores for consistency.
173
+
174
+A PassphraseCatalog will capture the following example structure::
175
+
176
+  schema: pegleg/PassphraseCatalog/v1
177
+  metadata:
178
+    schema: metadata/Document/v1
179
+    name: cluster-passphrases
180
+    layeringDefinition:
181
+      abstract: false
182
+      layer: site
183
+    storagePolicy: cleartext
184
+  data:
185
+    passphrases:
186
+      - document_name: osh-nova-password
187
+        description: Service password for Nova
188
+        encrypted: true
189
+      - document_name: osh-nova-oslo-db-password
190
+        description: Database password for Nova
191
+        encrypted: true
192
+        length: 12
193
+
194
+The nonobvious bits of the document described above are:
195
+
196
+* ``encrypted`` is optional, and denotes whether the generated
197
+  PeglegManagedDocument will be ``encrypted``, as well as whether the wrapped
198
+  document will have ``storagePolicy: encrypted`` or
199
+  ``storagePolicy: cleartext`` metadata.
200
+  If absent, ``encrypted`` defaults to ``true``.
201
+* ``document_name`` is required, and is used to create the filename of the
202
+  generated PeglegManagedDocument manifest, and the ``metadata.name`` of
203
+  the wrapped ``deckhand/Passphrase/v1`` document.  In both cases, Pegleg will
204
+  replace dashes in the ``document_name`` with underscores.
205
+* ``length`` is optional, and denotes the length in characters of the
206
+  generated cleartext passphrase data.  If absent, ``length`` defaults
207
+  to ``24``.
208
+* ``description`` is optional.
209
+
210
+The ``encrypted`` key will be added to the PKICatalog schema, and adds the same
211
+semantics to PKICatalog-based generation as are described above for
212
+PassphraseCatalog.
213
+
214
+Pegleg CLI Changes
215
+------------------
216
+
217
+The Pegleg CLI interface will be extended as follows.  These
218
+commands will create PeglegManagedDocument manifests in the local repository.
219
+Committing and pushing the changes will be left to the
220
+operator or to script-based automation.
221
+
222
+For the CLI commands below which encrypt or decrypt secrets, an environment
223
+variable (e.g. ``$PEGLEG_KEY`` will be use to capture the key/passphrase to use.
224
+``pegleg site secrets rotate`` will use a second variable
225
+(e.g. ``$PEGLEG_PREVIOUS_KEY``) to hold the key/passphrase being rotated
226
+out.
227
+
228
+``pegleg site secrets generate passphrases``:  Generate passphrases according to
229
+all PassphraseCatalog documents in the site.
230
+Note that regenerating passphrases can be accomplished
231
+simply by re-running ``pegleg site secrets generate passphrases``.
232
+
233
+``pegleg site secrets generate pki``:  Generate certificates and keys according
234
+to all PKICatalog documents in the site.
235
+Note that regenerating certificates can be accomplished
236
+simply by re-running ``pegleg site secrets generate pki``.
237
+
238
+``pegleg site secrets generate``:  Combines the two commands above.
239
+May be expanded in the future to include other manifest generation activities.
240
+
241
+``pegleg site bootstrap``: For now, a synonym for
242
+``pegleg site secrets generate``,
243
+and may be expanded in the future to include other bootstrapping activities.
244
+
245
+``pegleg site secrets encrypt``:  Encrypt all site documents which have
246
+``metadata.storagePolicy: encrypted``, and which are not already encrypted
247
+within a wrapping PeglegManagedDocument.  Note that the
248
+``pegleg site secrets generate`` commands encrypt generated secrets as
249
+specified, so ``pegleg site secrets encrypt`` is intended mainly for
250
+external-facing secrets which a deployment engineer brings to the site
251
+manifests.
252
+The output PeglegManagedDocument will be written back to the filename that
253
+served as its source.
254
+
255
+``pegleg site secrets decrypt <document YAML file>``: Decrypt a specific
256
+PeglegManagedDocument manifest, unwrapping it and outputting the cleartext
257
+original document YAML to standard output.  This is intended to be used when
258
+an authorized deployment engineer needs to determine a particular cleartext
259
+secret for a specific operational purpose.
260
+
261
+``pegleg site secrets rotate``:  This action re-encrypts encrypted secrets
262
+with a new key/passphrase, and it takes the previously-used key and a new
263
+key as input.  It accomplishes its task via two activities:
264
+
265
+* For encrypted secrets that were imported from outside of Pegleg
266
+  (i.e. PeglegManagedDocuments which lack the ``generated`` stanza),
267
+  decrypt them with the old key (in-memory), re-encrypt them with
268
+  the new key, and output the results.
269
+* Perform a fresh ``pegleg site secrets generate`` process using the new key.
270
+  This will replace all ``generated`` secrets with new secret values
271
+  for added security.  There is an assumption here that the only actors
272
+  that need to know generated secrets are the services within the
273
+  Airship-managed cluster, not external services or deployment engineers,
274
+  except perhaps for point-in-time troubleshooting or operational
275
+  exercises.
276
+
277
+Driving deployment of a site directly via Pegleg is follow-on functionality
278
+which will
279
+collect site documents, use them to create the ``genesis.sh`` script, and then
280
+interact directly with Shipyard to drive deployments.  Its details are beyond
281
+the scope of this spec, but when implemented, it should decrypt documents
282
+wrapped by applicable PeglegManagedDocuments at the lst responsible moment,
283
+and take care not to write, log, or stdout them to disk as cleartext.
284
+
285
+Note that existing ``pegleg collect`` functionality should **not** be changed
286
+to decrypt encrypted secrets; this is because it writes its output to disk.
287
+If ``pegleg collect`` is called, at this point in time, the
288
+PeglegManagedDocuments will be written (encrypted) to disk.
289
+To enable special case full site secret decryption, a ``--force-decrypt`` flag
290
+will be added to ``pegleg collect`` to do this under controlled circumstances,
291
+and to help bridge the gap with existing CICD pipelines until Pegleg-driven
292
+site deployment is in place.  It will leverage the ``$PEGLEG_KEY``
293
+variable described above.
294
+
295
+Secret Generation
296
+-----------------
297
+
298
+The ``rstr`` library should be invoked to generate secrets of the
299
+appropriate length and character set.
300
+This library uses the ``os.urandom()`` function,
301
+which in turn leverages ``/dev/urandom`` on Linux,
302
+and it is suitable for cryptographic purposes.
303
+
304
+Characters in generated secrets will be evenly distributed across lower-
305
+and upper-case letters, digits, and punctuation in
306
+!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~.  Note this is equivalent to the union of
307
+Python string.ascii_letters, string.digits, and string.punctuation.
308
+
309
+Secret Encryption
310
+-----------------
311
+
312
+Details around encryption will be defined in a follow-on patch set to this spec.
313
+
314
+Security impact
315
+===============
316
+
317
+These changes will result in a system that handles site secrets in a highly
318
+secure manner, in the face of multiple roles and day 2 operational needs.
319
+
320
+Performance impact
321
+==================
322
+
323
+Performance impact to existing flows will be minimal.  Pegleg will need to
324
+additionally decrypt secrets as part of site deployment, but this will be
325
+an efficient operation performed once per deployment.
326
+
327
+Alternatives
328
+============
329
+
330
+The Python ``secrets`` library presents a convenient interface for generating
331
+random strings.  However, it was introduced in Python 3.6, and it would be
332
+limiting to introduce this constraint on Airship CICD pipelines.
333
+
334
+The ``strgen`` library presents an even more convenient interface for
335
+generating pseudo-random strings; however, it leverages the Python ``random``
336
+library, which is unsuitably random for cryptographic purposes.
337
+
338
+Deckhand already supports a ``storagePolicy`` element which indicates whether
339
+whether Deckhand will persist document data in an encrypted state, and this
340
+flag could have been re-used by Pegleg to indicate whether a secret is
341
+(or should be) encrypted.  However, "should this data be encrypted" is a
342
+fundamentally different question than "is this data encrypted now", and
343
+additional metadata-esque parameters (``generated``, ``generatedLength``)
344
+were desired as well, so this proposal adds ``data.encrypted`` to indicate
345
+the point-in-time encryption status.  ``storagePolicy`` is still valuable
346
+in this context to make sure everything that *should* be encrypted *is*,
347
+prior to performing actions with it (e.g. Git commits).
348
+
349
+This proposed implementation writes the output of generation/encryption events
350
+back to the same source files from which the original data came.  This is a
351
+destructive operation; however, it wasn't evident that it is problematic in
352
+any anticipated workflow.  In addition, it sidesteps challenges around
353
+naming of generated files, and cleanup of original files.
354
+
355
+Implementation
356
+==============
357
+
358
+Please refer to the `Storyboard Story`_ for implementation planning information.
359
+
360
+Dependencies
361
+============
362
+
363
+This work should be based on the patchset to add `Git branch and revision
364
+support`_ to Pegleg, if it is not merged by the time implementation begins.
365
+This patchset alters the CLI interface and Git repository management code,
366
+and basing on it will avoid future refactoring.
367
+
368
+References
369
+==========
370
+
371
+.. _Storyboard Story: https://storyboard.openstack.org/#!/story/2003708
372
+.. _Git branch and revision support: https://review.openstack.org/#/c/577886/

Loading…
Cancel
Save