doorstop-dev / doorstop

Requirements management using version control.
https://doorstop.readthedocs.io
Other
476 stars 129 forks source link

Add support for digital signatures of items #375

Open sebhub opened 5 years ago

sebhub commented 5 years ago

Suppose that your requirements must go though a change control board (CCB). Members of the CCB will review and approve your requirements. They can do the approval with a digital signature of the item values contributing to the fingerprint (message). Add a doorstop sign UID command to add a digital signature to the item using GNU Privacy Guard. The digital signatures are stored in a signatures attribute of the item which contains a list of signatures. Add a doorstop verify UID command which verifies the signatures of the item using the current values. This protects also against changes in the fingerprint settings.

jacebrowning commented 5 years ago

In my opinion, this sounds out-of-scope for this tool. Integrity and authentication should be enforced by whatever version control system a project is using.

For Git, this is GPG-signed commits: https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work

sebhub commented 5 years ago

As far as I know in Git, a committer can sign individual commits and tags can be signed. What you cannot do is signing a commit multiple times. You cannot sign individual commits afterwards. Also you have to sign a complete commit. For what I have in mind this is not practical.

The entities approving the requirement may not trust or have to be independent of the repository owner or committer. The entities may also not trust each over or even be visible to the project. For example the software product along with the requirements may undergo an internal approval process. The approval may take place long after the requirements are committed. The approval may be limited to the content that contributes to the fingerprint. So, I think it should be a Doorstop feature.

The Python code to do the signature handling is not huge:

import gnupg
import tempfile
gpg = gnupg.GPG()
sig = gpg.sign(b'x', detach=True)
with tempfile.NamedTemporaryFile() as tmp:
    tmp.write(bytes(str(sig), 'utf-8'))
    tmp.flush()
    ver = gpg.verify_data(tmp.name, b'x')

The verification part can move to the doorstop validation command enabled by a --gpg option. The import of gnupg can be done upon use, so that not every Doorstop user needs it installed:

try:
   import gnupg
except ImportError:
   some message and exit

The validation can be done with an item_hook similar to CycleTracker. We just have to allow a list of item_hooks.

The doorstop sign can also do the import on demand. It just needs a bit of refactoring of the item review functions and a new optional standard attribute signatures.

jacebrowning commented 5 years ago

What you cannot do is signing a commit multiple times.

To clarify, this is how I've always envisioned this working:

  1. Alice adds three new requires which are, by default, unreviewed
  2. She commits them (signed) to the repository and asks Bob and Carl to review
  3. Bob reviews the first two requirements and marks them as reviewed
  4. He commits the new review fingerprints (signed) to the repository
  5. Carl does the same thing for the last requirement
  6. All requirements are now marked as reviewed

If a project does not need this level of independence or traceability a team might opt to track the review in their code review tool instead.

The entities approving the requirement may not trust or have to be independent of the repository owner or committer. The entities may also not trust each over or even be visible to the project.

Can you clarify how other coding workflows are accomplished on such a project? I don't think a project is likely to need to control the authorship and review of requirements to a higher degree than the code itself.

sebhub commented 5 years ago

What you cannot do is signing a commit multiple times.

To clarify, this is how I've always envisioned this working:

1. Alice adds three new requires which are, by default, unreviewed

2. She commits them (signed) to the repository and asks Bob and Carl to review

3. Bob reviews the first two requirements and marks them as reviewed

4. He commits the new review fingerprints (signed) to the repository

5. Carl does the same thing for the last requirement

6. All requirements are now marked as reviewed

For a project internal process this is fine.

If a project does not need this level of independence or traceability a team might opt to track the review in their code review tool instead.

Yes, this is also fine.

The entities approving the requirement may not trust or have to be independent of the repository owner or committer. The entities may also not trust each over or even be visible to the project.

Can you clarify how other coding workflows are accomplished on such a project? I don't think a project is likely to need to control the authorship and review of requirements to a higher degree than the code itself.

I have a particular project in mind, the open source real-time operating system RTEMS. RTEMS supports several architectures (e.g. ARM, SPARC, RISC-V, PowerPC) and various platforms (e.g. Xilinx Zynq, GR740). The development of RTEMS is evolutionary and done through a patch review process on a mailing list. Now the trouble starts. Some RTEMS users what to use it for systems those development must adhere to certain standards (e.g. ECSS, DO-178C, ISO 26262, IEC 61508, ISO 13849). For other RTEMS users this is just overkill. We have to decouple the workflow of the normal RTEMS development from some workflows necessary for standard compliance. There are different people involved and different time scales. Since standard compliance can be quite expensive, you normally restrict the scope to what is absolutely necessary for you, e.g. one user is only interested in platform A with a feature set X, another is only interested in platform B with a feature set Y. The users may use different standards and are from different industries. I would like to enable these independent users to approve a subset of requirements that fits their need at the time they define. I think for this a digital signature of the reviewed requirement content is a good solution.

You find a prototype implementation here:

https://github.com/sebhub/doorstop/commits/gpg

Missing are command line options, tests and documentation.

jacebrowning commented 5 years ago

My hesitation is in adding code (and dependencies), which increase the maintenance cost, for a feature that might only be used by a small percentage of users.

I recommend implementing this as a "plugin" to Doorstop using the hook callbacks: https://github.com/jacebrowning/doorstop/blob/9b02bc564f7bdb516e6170cc59c5fd5ef382fc43/doorstop/core/document.py#L665

Currently, hooks require you to create your own entry point script for Doorstop, but I could see the system expanded such that Doorstop automatically picks up plugin scripts (e.g. doorstop_validate_signatures.py is called automatically if found on the PATH).

https://doorstop.readthedocs.io/en/latest/api/scripting/ also needs some attention. 😄

sebhub commented 5 years ago

A plugin interface to register custom commands would be great. You probably have something in mind how this should work. Would you mind adding an issue for it? I can them make comments and do the implementation if this is all right for you.

sevendays commented 5 years ago

I don't know if signing doorstop reviews is enough: for high integrity, you usually need a review report.

We usually commit (and sign) the report (referring to the current version of the requirement set) instead of editing the requirement set.

sebhub commented 5 years ago

The approach with a report and "the current version of the requirement set" brings us back to the fingerprint, see #358. With a cryptographically secure fingerprint you could dump the fingerprints of the requirement set into your report. Later you can verify which requirement changed some time after your report.