File: README.md

package info (click to toggle)
rust-sequoia-git 0.4.0-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,580 kB
  • sloc: sh: 367; makefile: 32
file content (301 lines) | stat: -rw-r--r-- 12,155 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
# Sequoia `git`

`sequoia-git` is tool that can be used to improve a project's supply
chain security.

Documentation is available from Sequoia git's
[homepage](https://sequoia-pgp.gitlab.io/sequoia-git/).

## Introduction

A version control system like git doesn't just track changes, it also
provides a record of who made those changes.  This information can be
used to check that commits are authorized, which can improve software
supply chain security.  In particular, checking a change's provenance
can be used to remove intermediaries like forges, and package
registries from a user's trusted computing base. But, authorship
information can easily be forged.

An obvious solution to prevent forgeries would be to require that
commits are digitally signed.  But by itself a valid digital signature
doesn't prevent forgeries.  The certificate that was used to make the
signature could claim to be one of the project's maintainers.  What is
needed is not only a list of entities who are allowed to modify the
repository, but also the keys they use to sign the commits.  In other
words, to authenticate a commit we need a signing policy, which says
what keys are authorized to make changes.

Creating a policy isn't complicated.  A project's maintainers could
curate a list of entities who are allowed to add commits, and
enumerate the certificates they use to sign them.  The tricky part is
applying the policy.  There are a number of edge cases that need to be
handled like how merge changes from external contributions, who is
allowed to change the policy, and how to deal with compromised keys.

Sequoia git is a project that specifies a set of semantics, defines a
policy language, and provides a set of tools to manage a policy file,
and authenticate commits.

Using Sequoia git is relatively straightforward.  You start by adding
a policy file, `openpgp-policy.toml`, to your project's repository.
The policy is maintained in band to allow it to evolve, just like the
rest of the project. The `openpgp-policy.toml` file is basically a
list of OpenPGP certificates and the type of changes they are
authorized to make.  `sq-git` can help you create it.

Then, before you merge a pull request, you check that commits are
authorized by the policy.  Locally, this is done by running `sq-git
log` on the range of commits that you want to push.  A commit is
considered authorized if the commit has a valid signature, and at
least one immediate parent's policy allows the signer to make that
type of change. Projects hosted on GitHub can use this action to
automatically check that a pull request is authorized when it is
opened, or updated.

Downstream users can use Sequoia git to check that there is a chain of
trust from an older, known-good version of the software to a new
version. This helps prevent the use of versions that include
modifications that weren't authorized by the project's maintainers.

See [the specification] for an in-depth discussion of semantics and
implementation.

  [the specification]: https://sequoia-pgp.gitlab.io/sequoia-git/specification/

## Deploying `sq-git`

To start using Sequoia git in a git repository, you first add one or
more certificates to the project's policy, and grant them some rights.

The policy is called `openpgp-policy.toml`, and is stored in the root
of the repository.  It is a [toml file](https://toml.io), which means
it can be edited by hand, but `sq-git` provides tools that make it
easier to examine and modify it.

There are six different rights: `add-user`, `retire-user`, `audit`,
`sign-tag`, `sign-archive`, and `sign-commit`.  Only users who have
the `add-user` right can add new users to the policy.  Similarly, the
`retire-user` right is needed to remove users from the policy.  The
`audit` right is needed to good list (using `sq-git policy goodlist`)
a commit that was signed by a certificate that was subsequently hard
revoked.  The `sign-tag`, `sign-archive`, and `sign-commit` rights are
needed to sign tags, archives, and commits, respectively.

You can use `sq-git policy authorize` to grant a specific right to a
user.  For instance, you could run:

```
$ sq-git policy authorize --sign-commit 'Neal H. Walfield <neal@pep.foundation>' F7173B3C7C685CD9ECC4191B74E445BA0E15C957
```

This says that the specified certificate can be used to sign commits.
The name is purely decorative.

To make assigning rights easier, `sq-git policy authorize` knows about
three roles: the project maintainer (who gets all rights), the release
manager (who can sign tags, archives, and commits), and the committer
(who can only sign commits).  These can be passed to `sq-git policy
authorized`.  For instance:

```
$ sq-git policy authorize --project-maintainer 'Neal H. Walfield <neal@pep.foundation>' F7173B3C7C685CD9ECC4191B74E445BA0E15C957
```

`sq-git policy authorize` immediately expands the roles to the
corresponding rights; the roles do not appear in the policy file.

You can use the `sq-git init` subcommand to get a quick overview of
who has contributed to the project, and what certificates they used to
sign their commits, if any.  `sq-git init` looks at commits from the
last half year, or the last 10 commits, whichever is more.  As such it
focuses on contributors who have been active recently; it doesn't make
sense to authorize someone has left the project.

Although `sq-git init` usually provides a good starting point, you
should not trust it.  It is essential to verify a contributor's
certificate by, e.g., reaching out to them, and asking what their
certificate's fingerprint is.  As you can always modify the policy
later, it is better to only add the certificates that you are certain
about, from contributors who are active.

Here's how you might initialize a policy file:

```shell
../sequoia-git$ sq-git init
# Examined the 136 commits in the last 183 days.
# Stopped at commit 83ce12f617c9e1dd90f812825707337f8787f69e.

# Encountered 0 unsigned commits

# Neal H. Walfield <neal@walfield.org> added 66 commits (48%).
#
# After checking that they really control the following OpenPGP keys:
#
#   6863C9AD5B4D22D3 (66 commits)
#
# You can make them a project maintainer (someone who can add and
# remove committers) by running:
sq-git policy authorize  --project-maintainer "Neal H. Walfield <neal@walfield.org>" 6863C9AD5B4D22D3

# Justus Winter <justus@sequoia-pgp.org> added 44 commits (32%).
#
# After checking that they really control the following OpenPGP keys:
#
#   686F55B4AB2B3386 (44 commits)
#
# You can make them a committer by running:
sq-git policy authorize --committer "Justus Winter <justus@sequoia-pgp.org>" 686F55B4AB2B3386
...
../sequoia-git$ sq-git policy authorize --project-maintainer "Neal H. Walfield <neal@walfield.org>" 6863C9AD5B4D22D3
  - User "Neal H. Walfield <neal@walfield.org>" was added.
  - User "Neal H. Walfield <neal@walfield.org>" was granted the right sign-commit.
  - User "Neal H. Walfield <neal@walfield.org>" was granted the right sign-tag.
  - User "Neal H. Walfield <neal@walfield.org>" was granted the right sign-archive.
  - User "Neal H. Walfield <neal@walfield.org>" was granted the right add-user.
  - User "Neal H. Walfield <neal@walfield.org>" was granted the right retire-user.
  - User "Neal H. Walfield <neal@walfield.org>" was granted the right audit.
../sequoia-git$ sq-git policy authorize --committer "Justus Winter <justus@sequoia-pgp.org>" 686F55B4AB2B3386
  - User "Justus Winter <justus@sequoia-pgp.org>" was added.
  - User "Justus Winter <justus@sequoia-pgp.org>" was granted the right sign-commit.
```

`sq-git` reads the certificates from the user's certificate store.
Use `sq import < FILE` to import certificates in a file, `sq keyserver
get FINGERPRINT` to fetch certificates from a key server, etc.
Alternatively, you can provide the certificate to `sq-git policy
authorize` using the `--cert-file` argument.

The policy file can be viewed as follows:

```shell
$ sq-git policy describe
# OpenPGP policy file for git, version 0

## Commit Goodlist


## Authorizations

0. Justus Winter <justus@sequoia-pgp.org>
   - may sign commits
   - has OpenPGP cert: D2F2C5D45BE9FDE6A4EE0AAF31855247603831FD
1. Neal H. Walfield <neal@walfield.org>
   - may sign commits
   - may sign tags
   - may sign archives
   - may add users
   - may retire users
   - may goodlist commits
   - has OpenPGP cert: F7173B3C7C685CD9ECC4191B74E445BA0E15C957
```

If you are happy, you can add it to your `git` repository in the usual
manner.

Don't forget to tell `git` to sign commits by adding something like
the following to your repository's `.git/config` file:

```text
[user]
        signingkey = F7173B3C7C685CD9ECC4191B74E445BA0E15C957
        email = 'neal@pep.foundation'
        name = 'Neal H. Walfield'
[commit]
        gpgsign = true
```

Then run:

```shell
../sequoia-git$ git add openpgp-policy.toml
../sequoia-git$ git commit -m 'Add a commit policy.'
[main 911c4eb] Add a commit policy.
 1 file changed, 119 insertions(+), 1831 deletions(-)
 rewrite openpgp-policy.toml (94%)
```

Create a new commit, and verify the new version:

```shell
../sequoia-git$ echo 'hello world' > greeting
../sequoia-git$ git add greeting
../sequoia-git$ git commit -m 'Say hello.'
[main 698876a] Say hello.
 1 file changed, 1 insertion(+)
 create mode 100644 greeting
../sequoia-git$ sq-git log --trust-root 911c4eb1e9832d6df8e733bf103ca4c9f4637eb9
911c4eb1e9832d6df8e733bf103ca4c9f4637eb9..698876a7ff11fff2f8cd0df55bbe8fc5c5d224d9: Neal H. Walfield <neal@walfield.org> [74E445BA0E15C957]
```

Instead of entering the trust root manually, which is error prone, you
can set the trust root in the repository's git config file:

```shell
../sequoia-git$ git config sequoia.trustRoot 911c4eb1e9832d6df8e733bf103ca4c9f4637eb9
../sequoia-git$ sq-git log
911c4eb1e9832d6df8e733bf103ca4c9f4637eb9..698876a7ff11fff2f8cd0df55bbe8fc5c5d224d9: Cached positive verification
```

You can also use tags or branches, however, you must be careful as
these may be updated when you fetch from a remote repository using,
e.g., `git fetch`.

## Rejecting Unauthorized Commits

Insert the following line into `hooks/update` on a shared `git` server
to make it enforce the policy embedded in the repository starting at
the given trust root (`<COMMIT>`), which is specified as a hash:

```text
sq-git update-hook --trust-root=<COMMIT> "$@"
```

## Using `sq-git` in CI

`sequoia-git` is available in an OCI image for ease of use inside of
CI pipelines.

### Gitlab

To authenticate commits from a Gitlab CI pipeline, there is a script
included at `scripts/gitlab.sh` which may be run as a job inside a
project's `.gitlab-ci.yml` manifest:

```
authenticate-commits:
  stage: test
  image: registry.gitlab.com/sequoia-pgp/sequoia-git:latest
  before_script: []
  script:
    - sq-git policy describe
    - /usr/sbin/gitlab.sh # Script baked-in to image
  after_script: []
  rules:
    # TODO: We currently only authenticate the changes on non-merged
    # branches where we use the default branch as the trust root.  For
    # the default branch, the project needs to set an explicit trust
    # root.
    - if: '$CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH'
```

### GitHub

To use `sq-git` to authenticate a pull request in GitHub, you can use
the [`sequoia-pgp/authenticate-commits`
Action](https://github.com/sequoia-pgp/authenticate-commits).  This
action checks that the commits are authorized by the last commit of
the merge base.  [This
video](https://www.youtube.com/watch?v=KdDbU9u5X-Q) shows a
demonstration of the action.

Note: GitHub's interface for merging pull requests offers three merge
strategies, but unfortunately none of them are appropriate for use
with Sequoia git, because they all modify the commits.  With Sequoia
git, it is necessary to either rebase and fast forward the change, or
to add a signed merge commit.  It is possible to use the
[`sequoia-pgp/fast-forward`
action](https://github.com/sequoia-pgp/fast-forward) to fast forward
pull requests.  When enabled for a repository, an authorized user can
add a comment containing `/fast-forward` to the pull request, and the
action will fast forward the merge base.