@@ -26,7 +26,7 @@ as fetchers and checks are loaded automatically by ``unittest``.
26
26
Evidence
27
27
~~~~~~~~
28
28
29
- Fetchers and checks manage evidence. We have defined three types of
29
+ Fetchers and checks manage evidence. We have defined five types of
30
30
evidence (see :py:mod: `compliance.evidence `):
31
31
32
32
* :py:class: `~compliance.evidence.RawEvidence `: Gathered by
@@ -37,6 +37,18 @@ evidence (see :py:mod:`compliance.evidence`):
37
37
as binary by setting the ``binary_content=True `` keyword argument key/value
38
38
pair when constructing a ``RawEvidence `` object.
39
39
40
+ * :py:class: `~compliance.evidence.DerivedEvidence `: Gathered/Generated by
41
+ fetchers and used by checks as *input *. Derived evidence is useful for
42
+ those cases when a fetcher needs other evidence to perform computations
43
+ over data collected in order to generate a new evidence. This new
44
+ evidence is considered `derived ` in the sense that its data is not the
45
+ same as the source.
46
+
47
+ * :py:class: `~compliance.evidence.TmpEvidence `: Gathered by
48
+ fetchers and used by checks as *input *. This type of evidence is similar to
49
+ RawEvidence but it is never get pushed to the remote git repository. This is
50
+ useful for evidence that contains passwords or credentials.
51
+
40
52
* :py:class: `~compliance.evidence.ExternalEvidence `: Planted in the locker
41
53
with `plant <https://github.com/ComplianceAsCode/auditree-plant >`_
42
54
and used by checks as *input *. For example, a list of users in GitHub.
@@ -212,7 +224,8 @@ A few examples of what it is allowed:
212
224
213
225
In any case, any modification of a new raw evidence **must ** be
214
226
approved and agreed by the reviewers. By default, do **not ** modify
215
- the raw data.
227
+ the raw data. If you need to, then you should consider using derived
228
+ evidence.
216
229
217
230
This is a list of modifications that are completely forbidden:
218
231
@@ -230,11 +243,12 @@ we've provided some helpful decorators and context managers that validate
230
243
``ttl `` for you and if necessary write the evidence to the evidence locker for
231
244
you after it has been fetched.
232
245
233
- * ``store_raw_evidence `` decorator: Use this decorator on your fetcher method
234
- when you know the full path and name of your raw evidence. The decorator
235
- takes as an argument, the path to your raw evidence as a string.
246
+ * ``store_raw_evidence `` and ``store_tmp_evidence `` decorators: Use one of
247
+ these decorators on your fetcher method when you know the path and name of
248
+ your raw or tmp evidence. The decorator takes as an argument, the path to
249
+ your raw or tmp evidence as a string.
236
250
237
- `` @store_raw_evidence `` usage example::
251
+ Usage example::
238
252
239
253
...
240
254
from compliance.evidence import store_raw_evidence
@@ -248,15 +262,16 @@ you after it has been fetched.
248
262
# The decorator will write it to the evidence locker
249
263
return json.dumps(foo_bar_data)
250
264
251
- * ``raw_evidence `` context manager: Use this context manager within your
252
- fetcher method when your fetcher retrieves multiple, similar raw evidence
253
- based on a dynamic set of configurable values. In other words the full name
254
- and content of evidence is based on a configuration and not known prior
255
- to execution of the fetcher logic. The context manager takes as arguments, a
256
- locker object and the path to your raw evidence as a string. The context
257
- manager yields the corresponding raw evidence object.
265
+ * ``raw_evidence `` and ``tmp_evidence `` context managers: Use one of these
266
+ context managers within your fetcher method when your fetcher retrieves
267
+ multiple, similar raw or tmp evidence based on a dynamic set of configurable
268
+ values. In other words the full name and content of evidence is based on a
269
+ configuration and not known prior to execution of the fetcher logic. The
270
+ context manager takes as arguments, a locker object and the path to your raw
271
+ or tmp evidence as a string. The context manager yields the corresponding
272
+ raw or tmp evidence object.
258
273
259
- `` with raw_evidence `` usage example::
274
+ Usage example::
260
275
261
276
...
262
277
from compliance.evidence import raw_evidence
@@ -273,6 +288,109 @@ you after it has been fetched.
273
288
# Upon exit it is written to the evidence locker
274
289
evidence.set_content(json.dumps(foo_bar_data))
275
290
291
+ * ``store_derived_evidence `` decorator: Use this decorator on your fetcher
292
+ method when you know the paths and names of your source evidences and
293
+ the path and name of your target derived evidence. The decorator takes
294
+ as arguments, a list of source evidence paths as strings and a target derived
295
+ evidence path as a string. It also passes the source evidences to the
296
+ decorated method in the form of method arguments.
297
+
298
+ Usage example::
299
+
300
+ ...
301
+ from compliance.evidence import store_derived_evidence
302
+ ...
303
+ @store_derived_evidence(
304
+ ['raw/foo/evidence_bar.json', 'raw/foo/evidence_baz.json'],
305
+ 'foo/derived_bar_baz.json'
306
+ )
307
+ fetch_foo_bar_baz_derived_evidence(self, bar_evidence, baz_evidence):
308
+ # Fetcher code only executes if evidence is stale
309
+ # Construct your derived evidence
310
+ derived_data = self._do_whatever(bar_evidence, baz_evidence)
311
+ # Return the content as a string
312
+ # The decorator will write it to the evidence locker
313
+ return json.dumps(derived_data)
314
+
315
+ * ``derived_evidence `` context manager: Use this context manager within your
316
+ fetcher method when your fetcher generates multiple, similar derived
317
+ evidences based on a dynamic set of configurable values. In other words the
318
+ name and content of the evidences are based on a configuration and not
319
+ known prior to execution of the fetcher logic. The context manager takes as
320
+ arguments, a locker object, source evidence paths and a target derived
321
+ evidence path as a string. The source evidence paths can be in the form of a
322
+ list of paths as strings, a dictionary of key/values pairs as strings where
323
+ the key is an evidence short name and the value is the evidence path, or
324
+ simply a single evidence path as a string. The context manager yields a
325
+ dictionary containing the source and target evidences as the dictionary
326
+ values. The source evidence key is its evidence path if a list of source
327
+ paths were provided or its evidence short name if a dictionary of paths were
328
+ provided or "source" if a single evidence path in the form of a string was
329
+ provided. The target derived evidence key is always "derived".
330
+
331
+ Usage example (source list provided)::
332
+
333
+ ...
334
+ from compliance.evidence import derived_evidence
335
+ ...
336
+ fetch_foo_bar_baz_derived_evidence(self):
337
+ for system in systems:
338
+ sources = ['raw/foo/evidence_bar.json', 'raw/foo/evidence_baz.json']
339
+ target = 'foo/derived_bar_baz_{}.json'.format(system)
340
+ with derived_evidence(self.locker, sources, target) as evidences:
341
+ # None is returned if target evidence is not stale
342
+ if evidences:
343
+ # Construct your derived evidence
344
+ derived_data = self._do_whatever(
345
+ evidences['raw/foo/evidence_bar.json'],
346
+ evidences['raw/foo/evidence_baz.json']
347
+ )
348
+ # Set the content as a string
349
+ # Upon exit it is written to the evidence locker
350
+ evidences['derived'].set_content(json.dumps(derived_data))
351
+
352
+ Usage example (source dictionary provided)::
353
+
354
+ ...
355
+ from compliance.evidence import derived_evidence
356
+ ...
357
+ fetch_foo_bar_baz_derived_evidence(self):
358
+ for system in systems:
359
+ sources = {
360
+ 'bar': 'raw/foo/evidence_bar.json',
361
+ 'baz': 'raw/foo/evidence_baz.json'
362
+ }
363
+ target = 'foo/derived_bar_baz_{}.json'.format(system)
364
+ with derived_evidence(self.locker, sources, target) as evidences:
365
+ # None is returned if target evidence is not stale
366
+ if evidences:
367
+ # Construct your derived evidence
368
+ derived_data = self._do_whatever(
369
+ evidences['bar'],
370
+ evidences['baz']
371
+ )
372
+ # Set the content as a string
373
+ # Upon exit it is written to the evidence locker
374
+ evidences['derived'].set_content(json.dumps(derived_data))
375
+
376
+ Usage example (source string provided)::
377
+
378
+ ...
379
+ from compliance.evidence import derived_evidence
380
+ ...
381
+ fetch_foo_bar_derived_evidence(self):
382
+ for system in systems:
383
+ source = 'raw/foo/evidence_bar.json'
384
+ target = 'foo/derived_bar_{}.json'.format(system)
385
+ with derived_evidence(self.locker, source, target) as evidences:
386
+ # None is returned if target evidence is not stale
387
+ if evidences:
388
+ # Construct your derived evidence
389
+ derived_data = self._do_whatever(evidences['source'])
390
+ # Set the content as a string
391
+ # Upon exit it is written to the evidence locker
392
+ evidences['derived'].set_content(json.dumps(derived_data))
393
+
276
394
Evidence Dependency Chaining
277
395
============================
278
396
@@ -355,22 +473,22 @@ we've provided some helpful decorators and context managers that validate
355
473
``ttl `` for you and will ``ERROR `` the check if evidence ``ttl `` has expired
356
474
prior to executing the check's logic.
357
475
358
- * ``with_raw_evidences ``, ``with_external_evidences `` decorators: Use these
359
- decorators on your check method when you know the full path and name of
360
- your raw or external evidence. Each decorator takes as arguments, the
361
- paths to your raw or external evidence as strings or as evidence
362
- ``LazyLoader `` named tuples. Evidence `` LazyLoader `` has ``path `` and
363
- `` ev_class `` (evidence class) as attributes. If the requested evidence pass
364
- TTL validation the evidence is then passed along to the decorated method in
365
- the form of method arguments. Use an evidence ``LazyLoader `` when dealing
366
- with sub-classed `` RawEvidence `` or ``ExternalEvidence ``, and you want the
367
- evidence provided to the decorated method to be cast as that sub-classed
476
+ * ``with_raw_evidences ``, ``with_derived_evidences ``, `` with_tmp_evidences ``,
477
+ and `` with_external_evidences `` decorators: Use these decorators on your
478
+ check method when you know the path and name of your raw, derived, tmp or
479
+ external evidence. Each decorator takes as arguments, the paths to your evidence as strings or as evidence `` LazyLoader `` named tuples. Evidence
480
+ ``LazyLoader `` has `` path `` and ``ev_class `` (evidence class) as attributes.
481
+ If the requested evidence pass TTL validation the evidence is then passed
482
+ along to the decorated method in the form of method arguments. Use an
483
+ evidence ``LazyLoader `` when dealing with sub-classed `` RawEvidence ``,
484
+ `` DerivedEvidence ``, `` TmpEvidence ``, or ``ExternalEvidence ``, and you want
485
+ the evidence provided to the decorated method to be cast as that sub-classed
368
486
evidence otherwise use a string path and the evidence will be provided as
369
- either `` RawEvidence `` or `` ExternalEvidence `` . A ``LazyLoader `` named tuple
370
- can be constructed by executing the ``lazy_load `` class method of any evidence
487
+ the appropriate base evidence . A ``LazyLoader `` named tuple can be
488
+ constructed by executing the ``lazy_load `` class method of any evidence
371
489
class such as ``BarEvidence.lazy_load('foo/evidence_bar.json') ``.
372
490
373
- `` @with_*_evidences `` usage example::
491
+ Usage example::
374
492
375
493
...
376
494
from compliance.evidence import with_raw_evidences
@@ -413,7 +531,7 @@ prior to executing the check's logic.
413
531
the ``lazy_load `` class method of any evidence class such as
414
532
``BarEvidence.lazy_load('foo/evidence_bar.json') ``.
415
533
416
- `` with evidences `` (list provided) usage example ::
534
+ Usage example (list provided)::
417
535
418
536
...
419
537
from compliance.evidence import evidences
@@ -436,7 +554,7 @@ prior to executing the check's logic.
436
554
self.add_warnings('bar vs. baz', warnings)
437
555
self.add_successes('bar vs. baz', successes)
438
556
439
- `` with evidences `` (dictionary provided) usage example ::
557
+ Usage example (dictionary provided)::
440
558
441
559
...
442
560
from compliance.evidence import evidences
@@ -459,7 +577,7 @@ prior to executing the check's logic.
459
577
self.add_warnings('bar vs. baz', warnings)
460
578
self.add_successes('bar vs. baz', successes)
461
579
462
- `` with evidences `` (string path provided) usage example ::
580
+ Usage example (string path provided)::
463
581
464
582
...
465
583
from compliance.evidence import evidences
@@ -475,7 +593,7 @@ prior to executing the check's logic.
475
593
self.add_warnings('bar stuff', warnings)
476
594
self.add_successes('bar stuff', successes)
477
595
478
- `` with evidences `` (``LazyLoader `` provided) usage example ::
596
+ Usage example (``LazyLoader `` provided)::
479
597
480
598
...
481
599
from compliance.evidence import evidences
0 commit comments