--- type: change description: Re-organize and flesh-out documentation, including writing the tutorials fingerprint: AP5oeODaJO4eq84LRE3rlFgEVGyPa3OywpyftSgsrx13 credentials: - type: pgp_signature pub_key_id: 95C46FA6A41148AC body: iQIzBAABAgAdFiEEJ6tQKp6olvZKJ0lwlcRvpqQRSKwFAl7VRQ8ACgkQlcRvpqQRSKwgPg//R95XdGAKyC5Db0n94rHGW9LY9bcnmIe3WEQlQu2UFLJWzwGk0xJNPHugBz7tKqzEMQ+dQJ6Dl1/UjoCzMfr70Bwv26hAJa+CYLwq0qOoAqmCNZkxBREvlQfGV6E82P3iXZVOsFyNyUUTJEsM9ZdOUQB7+wnBHqw67gsTqOkS/6xXr5EPvUZeyASdG2epgHIh+DciDo6O9h6rBjMtyTgOFkCOCHKsZN8a5elAl+LaRaNWh05DJSh3y0VwPlEqfuR+zph8r5Q64aIJEY2ZA8a91T2SJQhBnUVjZ6H9nEqdhuq3bVbxgGdcZoX07pJIFIaqwIICkzEuxGtuRT0PZUC4yz2fjoiI7ykVTEN5urVOXL+vfZbgbklyST+BAUg5Qlac7fD9CP7nlGQ+alcXwL2cHBkXfRZedzw+MCyn/Qph0cNPE10uzwgR3pSWx2Sr6FOaBW/CXSH9y9rhcSF38jgXA6XirSOy3GpqfwHQaC9ol5Vm2R948XS2u0qJV3RZlcuylE62ST4K8pOiHn97HrGZnfG7TyyiYNvWjAq9avYwNhd3klWpgLs+OrgFN+f08xQxqnVbVEpwKLCwXmhRMyW7UVDRgoGTcfB7MVvWVxqbE3/f9VawF/baX4q324f+cMVkchyk0UeGnV30pJrWoDSw3UN3FAQoS/PYWNW3dZgp5F0= account: mediocregophermain
parent
a1579dcc96
commit
a709a43696
@ -0,0 +1,128 @@ |
|||||||
|
# Tutorial 0: Say Hello! |
||||||
|
|
||||||
|
This tutorial will guide you through cloning a dehub project locally, creating a |
||||||
|
comment, and pushing that comment back up to the remote. The project in |
||||||
|
question: dehub itself! |
||||||
|
|
||||||
|
This tutorial assumes you have [dehub installed](/index.html#getting-started), |
||||||
|
you have git and gpg installed, and you have a gpg key already created. |
||||||
|
|
||||||
|
## Step 0: Clone the Project |
||||||
|
|
||||||
|
Cloning the dehub project is as simple as cloning its git repo: |
||||||
|
|
||||||
|
``` |
||||||
|
git clone https://dehub.dev/src/dehub.git |
||||||
|
cd dehub |
||||||
|
``` |
||||||
|
|
||||||
|
Once cloned, feel free to look around the project. You should initially find |
||||||
|
yourself on the `main` branch, the primary branch of most dehub projects |
||||||
|
(analogous to the `master` branch of most git repos). |
||||||
|
|
||||||
|
Calling `git log` will show the commits messages for all commits in the branch. |
||||||
|
You will notice the commit messages aren't formatted in the familiar way, for |
||||||
|
example: |
||||||
|
|
||||||
|
``` |
||||||
|
commit 351048e9aabef7dc0f99b00f02547e409859a33f |
||||||
|
Author: mediocregopher <> |
||||||
|
Date: Sat Apr 25 15:17:21 2020 -0600 |
||||||
|
|
||||||
|
Completely rewrite SPEC |
||||||
|
|
||||||
|
--- |
||||||
|
type: change |
||||||
|
description: |- |
||||||
|
Completely rewrite SPEC |
||||||
|
|
||||||
|
It's good this time, and complete. After this rewrite it will be necessary to |
||||||
|
update a lot of the code, since quite a few things got renamed. |
||||||
|
fingerprint: AG0s3yILU+0uIZltVY7A9/cgxr/pXk2MzGwExsY/hbIc |
||||||
|
credentials: |
||||||
|
- type: pgp_signature |
||||||
|
pub_key_id: 95C46FA6A41148AC |
||||||
|
body: BIG LONG STRING |
||||||
|
account: mediocregopher |
||||||
|
``` |
||||||
|
|
||||||
|
Instead of just being a human-readable description they are YAML encoded payload |
||||||
|
objects. We will dive into these payload objects more throughout this tutorial |
||||||
|
series. |
||||||
|
|
||||||
|
## Step 1: Checkout the Welcome Branch |
||||||
|
|
||||||
|
Next you're going to checkout the public welcome branch. This is done through a |
||||||
|
normal git checkout command: |
||||||
|
|
||||||
|
``` |
||||||
|
git checkout public/welcome |
||||||
|
``` |
||||||
|
|
||||||
|
You can do `git log` to see all the comments people have been leaving in this |
||||||
|
branch. The `public/welcome` branch is differentiated from the `main` branch in |
||||||
|
two ways: |
||||||
|
|
||||||
|
* It has been configured to allow comment commits from anonymous users to be |
||||||
|
pushed to it. Project configuration is covered in a future tutorial. |
||||||
|
|
||||||
|
* It has no code files tracked, its only purpose is for comments. |
||||||
|
|
||||||
|
## Step 2: Create Your Comment |
||||||
|
|
||||||
|
Now that you've poked around the welcome branch a bit, it's time to leave a |
||||||
|
comment of your own! This is as easy as doing: |
||||||
|
|
||||||
|
``` |
||||||
|
dehub commit --anon-pgp-key=KEY_NAME comment |
||||||
|
``` |
||||||
|
|
||||||
|
(`KEY_NAME` should be replaced with any selector which will match your pgp key, |
||||||
|
such as the key ID, the name on the key, or the email.) |
||||||
|
|
||||||
|
Your default text editor (defined by the EDITOR environment variable) will pop |
||||||
|
up and you can then write down your comment. When you save and close your editor |
||||||
|
dehub will sign the comment with your pgp key and create a commit with it. |
||||||
|
|
||||||
|
If you're having trouble thinking of something to say, here's some prompts to |
||||||
|
get you going: |
||||||
|
|
||||||
|
* Introduce yourself; say where you're from and what your interests are. |
||||||
|
|
||||||
|
* How did you find dehub? Why is it interesting to you? |
||||||
|
|
||||||
|
* If you're using dehub for a project, shill your project! |
||||||
|
|
||||||
|
* If you'd like to get involved in dehub's development, let us know what your |
||||||
|
skills are and how you can help. Remember, it takes more than expert |
||||||
|
programmers to make a project successful. |
||||||
|
|
||||||
|
Once you've created your commit you can call `git log` to verify that it's been |
||||||
|
created to your liking. If there's anything about the comment you'd like to |
||||||
|
change you can amend the commit like so: |
||||||
|
|
||||||
|
``` |
||||||
|
dehub commit --anon-pgp-key=KEY_NAME comment --amend |
||||||
|
``` |
||||||
|
|
||||||
|
## Step 3: Push Your Commit |
||||||
|
|
||||||
|
As of now your comment commit only exists on your local machine. For everyone |
||||||
|
else to see it you'll need to push it to the dehub server, exactly like with a |
||||||
|
normal git commit. Pushing is done in the same way as a normal git commit as |
||||||
|
well: `git push`. |
||||||
|
|
||||||
|
If you receive an error that's like `Updates were rejected because the tip of |
||||||
|
your current branch is behind` then someone else has pushed to the branch in |
||||||
|
between the last time you pulled and now. Do a `git pull --rebase` to pull in |
||||||
|
those new changes, and try pushing again. |
||||||
|
|
||||||
|
## Step 4: Follow the Conversation |
||||||
|
|
||||||
|
In order to see other people's responses to your comment, and all other parts of |
||||||
|
the conversation, all you need to do is call `git pull` with the |
||||||
|
`public/welcome` branch checked out. |
||||||
|
|
||||||
|
You now have all the tools needed to participate in a dehub discussion thread! |
||||||
|
Continue on to [Tutorial 1](tut1.html) to set up your own dehub project and |
||||||
|
learn about credentials and their verification. |
@ -0,0 +1,178 @@ |
|||||||
|
# Tutorial 1: Create Your Own Project |
||||||
|
|
||||||
|
This tutorial will guide you through starting a dehub project of your own, as |
||||||
|
well as introducing some basic concepts regarding how commit payloads work. You |
||||||
|
will use an example hello world project to do this. |
||||||
|
|
||||||
|
This tutorial assumes you have already completed [Tutorial 0](tut0.html). |
||||||
|
|
||||||
|
## Step 0: Init the Project |
||||||
|
|
||||||
|
A dehub project is initialized in the same way as a git project. An empty |
||||||
|
directory is created, and `dehub init` is run within that directory. |
||||||
|
|
||||||
|
``` |
||||||
|
mkdir hello-world |
||||||
|
cd hello-world |
||||||
|
dehub init |
||||||
|
``` |
||||||
|
|
||||||
|
`dehub init` does nearly exactly the same thing as `git init`, with the primary |
||||||
|
difference being that it sets the initial branch to be `main` instead of |
||||||
|
`master`. dehub makes a distinction between `main` and `master` in order to help |
||||||
|
prevent confusion between dehub and vanilla git projects, as well as to avoid |
||||||
|
conflicts when migrating vanilla git projects to dehub. |
||||||
|
|
||||||
|
## Step 1: Add the First Account |
||||||
|
|
||||||
|
A dehub project is not fully initialized until it has an account defined for it. |
||||||
|
dehub accounts refer to a specific user who has some kind of access to the |
||||||
|
project. Each account can have specific permissions for it, as well as multiple |
||||||
|
ways of signifying itself. |
||||||
|
|
||||||
|
For now, you'll add a basic account `tut` with a pgp key signifier. First, |
||||||
|
create the `.dehub` directory, which is where all dehub project configuration |
||||||
|
goes, and put your pgp key there: |
||||||
|
|
||||||
|
``` |
||||||
|
mkdir .dehub |
||||||
|
gpg -a --export KEY_ID > .dehub/tut.asc |
||||||
|
``` |
||||||
|
|
||||||
|
Next you'll create the `.dehub/config.yml` file, which is where accounts are |
||||||
|
actually defined (amongst many other things). The file should have the following |
||||||
|
contents: |
||||||
|
|
||||||
|
```yaml |
||||||
|
# contents of .dehub/config.yml |
||||||
|
--- |
||||||
|
accounts: |
||||||
|
- id: tut |
||||||
|
signifiers: |
||||||
|
- type: pgp_public_key_file |
||||||
|
path: ".dehub/tut.asc" |
||||||
|
``` |
||||||
|
|
||||||
|
Finally, you'll commit these changes and the project will have its first commit! |
||||||
|
Committing changes works very similarly to committing comments (as you did in |
||||||
|
[Tutorial 0](tut0.html)). Where a comment commit merely carries a user's |
||||||
|
comment, a change commit describes a set of changes to the tracked files in the |
||||||
|
git repo. |
||||||
|
|
||||||
|
``` |
||||||
|
git add --all |
||||||
|
dehub commit --as tut change |
||||||
|
``` |
||||||
|
|
||||||
|
Like when you made a comment commit this will pop up with your editor asking for |
||||||
|
a description of the changes. Fill it in with something like `Initialize the |
||||||
|
project` and save/close the editor. Depending on your pgp key settings you'll |
||||||
|
likely be prompted for your pgp key password at this point. After that the |
||||||
|
commit has been created! |
||||||
|
|
||||||
|
## Step 2: Inspect the Payload |
||||||
|
|
||||||
|
In this step you're going to look at the commit you just created and learn about |
||||||
|
the contents of the payload. To view the commit do `git show`. Something similar |
||||||
|
to the following should be output as the commit message: |
||||||
|
|
||||||
|
``` |
||||||
|
commit 3cdcbc19546d4e6d817ebfba3e18afbc23283ec0 |
||||||
|
Author: username <> |
||||||
|
Date: Sat Apr 25 15:17:21 2020 -0600 |
||||||
|
|
||||||
|
Initialize the project |
||||||
|
|
||||||
|
--- |
||||||
|
type: change |
||||||
|
description: Initialize the project |
||||||
|
fingerprint: AG0s3yILU+0uIZltVY7A9/cgxr/pXk2MzGwExsY/hbIc |
||||||
|
credentials: |
||||||
|
- type: pgp_signature |
||||||
|
pub_key_id: 95C46FA6A41148AC |
||||||
|
body: BIG LONG STRING |
||||||
|
account: tut |
||||||
|
``` |
||||||
|
|
||||||
|
All commits in a dehub project will contain a similar looking message. The first |
||||||
|
line (the head) is always a human readable description of the commit. In this |
||||||
|
case our commit description itself, `Initialize the project`, was used. |
||||||
|
|
||||||
|
After the head comes the payload, which is always a YAML encoded object. All |
||||||
|
payloads have a `type` field indicating what type of payload they are. That type |
||||||
|
will determine what other fields the payload is expected to have. The other |
||||||
|
fields in this payload object are: |
||||||
|
|
||||||
|
* `description`: This is the description which was input into the editor when |
||||||
|
creating the change commit. |
||||||
|
|
||||||
|
* `fingerprint`: A unique descriptor for this set of changes. It is computed |
||||||
|
using both `description` and the files changed. |
||||||
|
|
||||||
|
* `credentials`: A set of credentials for this commit, each one declaring |
||||||
|
that this commit has been given approval by a user. This commit has one |
||||||
|
`pgp_signature` credential, created by the `tut` account. The `body` is a |
||||||
|
signature of the `fingerprint` created by the `tut`'s pgp key. |
||||||
|
|
||||||
|
## Step 3: Create Another Commit |
||||||
|
|
||||||
|
Now that the initial commit is created, and configuration has been added to the |
||||||
|
dehub project, you can continue on to use the project for what it was intended |
||||||
|
for: greeting the world! |
||||||
|
|
||||||
|
Add a simple "hello world" script to the project by doing: |
||||||
|
|
||||||
|
``` |
||||||
|
echo 'echo "hello world"' > hello.sh |
||||||
|
git add hello.sh |
||||||
|
dehub commit --as tut change --descr 'add hello.sh' |
||||||
|
``` |
||||||
|
|
||||||
|
You'll notice that this time around you used the `--descr` flag to declare the |
||||||
|
change's description, rather than opening up the editor |
||||||
|
|
||||||
|
Once again you can inspect the payload you just created using `git show`, if |
||||||
|
you'd like, or continue on to the next step to learn about commit verification. |
||||||
|
|
||||||
|
## Step 4: Verify Your Commits |
||||||
|
|
||||||
|
All this work to create YAML encoded payloads has been done for one primary |
||||||
|
purpose: to make commits verifiable. A verifiable commit is one which follows |
||||||
|
the access controls defined by its parent. |
||||||
|
|
||||||
|
Your dehub project doesn't have any explicitly defined access controls (that |
||||||
|
will be covered in a future tutorial), and so the defaults are used. By default, |
||||||
|
dehub requires that all commits in `main` are change commits which have been |
||||||
|
signed by at least one account. |
||||||
|
|
||||||
|
In order to verify the HEAD commit you can do: |
||||||
|
|
||||||
|
``` |
||||||
|
dehub verify |
||||||
|
``` |
||||||
|
|
||||||
|
This command looks at the project configuration defined in the parent of HEAD |
||||||
|
and verifies that HEAD conforms to it. The HEAD of your project is a change |
||||||
|
commit signed by the account `tut`, and so should be verifiable. |
||||||
|
|
||||||
|
Arbitrary commits can be verified using the `--rev` flag. This command will |
||||||
|
verify the parent of HEAD, i.e. the initial commit: |
||||||
|
|
||||||
|
``` |
||||||
|
dehub verify --rev HEAD^ |
||||||
|
``` |
||||||
|
|
||||||
|
The initial commit doesn't have a parent, and so is a special case for |
||||||
|
verification. The initial commit uses the configuration defined within itself in |
||||||
|
order to verify itself. This creates an exploit opportunity: if you clone a |
||||||
|
remote dehub project and an attacker intercepts that request they will be able |
||||||
|
to send you back a project with a different initial commit than what you |
||||||
|
expected. The whole project will still be verifiable, even though it's been |
||||||
|
compromised. For this reason it's important to manually verify that the initial |
||||||
|
commit of projects you clone are configured correctly, using the expected |
||||||
|
signifiers for the expected accounts. |
||||||
|
|
||||||
|
You are now able to initialize a project, configure accounts within it, commit |
||||||
|
changes to its files, and verify those commits. Well done! Continue on to |
||||||
|
[Tutorial 2](tut2.html), where you will learn how to configure dehub's access |
||||||
|
controls. |
@ -0,0 +1,259 @@ |
|||||||
|
# Tutorial 2: Access Controls |
||||||
|
|
||||||
|
Access controls, in the context of a dehub project, refer to configuration |
||||||
|
defining who is allowed to do what. These controls are defined within the dehub |
||||||
|
project itself, within the `.dehub/config.yml` file. This tutorial will guide |
||||||
|
you through the basics of how access controls work, how to define them, and some |
||||||
|
examples of what can be done with them. |
||||||
|
|
||||||
|
This tutorial assumes you have already completed [Tutorial 1](tut1.html), and |
||||||
|
builds on top of the project which was started there. |
||||||
|
|
||||||
|
## Step 0: Create a Restricted Account |
||||||
|
|
||||||
|
Inside the project you started in [Tutorial 1](tut1.html) you're going to add |
||||||
|
another account to the project, called `tot`. Initially, `tot` will have all the |
||||||
|
same permissions as `tut`, except being allowed to modify the project |
||||||
|
configuration. |
||||||
|
|
||||||
|
First, export your gpg key into the project for `tot` to use, the same key used |
||||||
|
for `tut`: |
||||||
|
|
||||||
|
``` |
||||||
|
gpg -a --export KEY_ID > .dehub/tot.asc |
||||||
|
``` |
||||||
|
|
||||||
|
(For the purposes of a tutorial it's fine for two accounts to share a |
||||||
|
key, but it's not something which generally makes sense to do.) |
||||||
|
|
||||||
|
Now, modify the `.dehub/config.yml` to have the following contents: |
||||||
|
|
||||||
|
```yaml |
||||||
|
# contents of .dehub/config.yml |
||||||
|
--- |
||||||
|
accounts: |
||||||
|
- id: tut |
||||||
|
signifiers: |
||||||
|
- type: pgp_public_key_file |
||||||
|
path: ".dehub/tut.asc" |
||||||
|
- id: tot |
||||||
|
signifiers: |
||||||
|
- type: pgp_public_key_file |
||||||
|
path: ".dehub/tot.asc" |
||||||
|
|
||||||
|
access_controls: |
||||||
|
- action: allow |
||||||
|
filters: |
||||||
|
- type: signature |
||||||
|
account_ids: |
||||||
|
- tut |
||||||
|
- type: files_changed |
||||||
|
pattern: .dehub/* |
||||||
|
|
||||||
|
- action: deny |
||||||
|
filters: |
||||||
|
- type: files_changed |
||||||
|
pattern: .dehub/* |
||||||
|
``` |
||||||
|
|
||||||
|
The `accounts` section has been modified to add the `tot` account, but the |
||||||
|
primary change here has been to add the `access_controls` section. The next |
||||||
|
sub-sections will explain what exactly is being done here, but for now go ahead |
||||||
|
and commit these changes: |
||||||
|
|
||||||
|
``` |
||||||
|
git add --all |
||||||
|
dehub commit --as tut change --descr 'add new restricted tot account' |
||||||
|
``` |
||||||
|
|
||||||
|
### Access Controls |
||||||
|
|
||||||
|
Each access control is an action/filters pair. For any commit being verified, |
||||||
|
the access controls defined in its parent commit are iterated through, in order, |
||||||
|
until one is found whose filters all match the commit being verified. The action |
||||||
|
for that access control, either `allow` or `deny`, is then taken. |
||||||
|
|
||||||
|
If no access controls are defined, or none match, then the default access |
||||||
|
controls are used. These are explicitly defined in the [SPEC](SPEC.html), but |
||||||
|
the general effect of them is to require that all commits have one signature |
||||||
|
from any of the project's accounts. |
||||||
|
|
||||||
|
### Access Control Filters |
||||||
|
|
||||||
|
There are many different filter types, so only the ones used in the tutorial |
||||||
|
will be explained. An exhaustive listing can be found in the [SPEC](SPEC.html). |
||||||
|
|
||||||
|
The `signature` filter matches commits which have a signature credential created |
||||||
|
by any one of the specified accounts. The `files_changed` filter matches commits |
||||||
|
which have changed files whose paths match the specified patterns (relative to |
||||||
|
the project's root). |
||||||
|
|
||||||
|
### Putting it Together |
||||||
|
|
||||||
|
The first of the new actions controls you've defined is: |
||||||
|
|
||||||
|
``` |
||||||
|
- action: allow |
||||||
|
filters: |
||||||
|
- type: signature |
||||||
|
account_ids: |
||||||
|
- tut |
||||||
|
- type: files_changed |
||||||
|
pattern: .dehub/* |
||||||
|
``` |
||||||
|
|
||||||
|
This allows any commits which have been signed by `tut` and which modify any of |
||||||
|
the files in `.dehub/*`. The second access control is: |
||||||
|
|
||||||
|
``` |
||||||
|
- action: deny |
||||||
|
filters: |
||||||
|
- type: files_changed |
||||||
|
pattern: .dehub/* |
||||||
|
``` |
||||||
|
|
||||||
|
This denies any commits which modify any of the files in `.dehub/*`. If a commit |
||||||
|
does not match the first access control, but does match this second access |
||||||
|
control, it can be assumed that the commit does _not_ have a signature from |
||||||
|
`tut` (because that's the only difference between them). Therefore, the effect |
||||||
|
of these two controls put together is to only allow `tut` to make changes to the |
||||||
|
`.dehub` directory's files. |
||||||
|
|
||||||
|
## Step 1: Test the Restrictions |
||||||
|
|
||||||
|
Let's say that your new user `tot` is having a bit of rebellious phase, and |
||||||
|
wants to kick `tut` out of the project. Change `.dehub/config.yml` to have the |
||||||
|
following contents (note that `accounts` has been left the same and so is mostly |
||||||
|
elided): |
||||||
|
|
||||||
|
``` |
||||||
|
# abbreviated contents of .dehub/config.yml |
||||||
|
--- |
||||||
|
accounts: |
||||||
|
... |
||||||
|
|
||||||
|
access_controls: |
||||||
|
- action: deny |
||||||
|
filters: |
||||||
|
- type: signature |
||||||
|
account_ids: |
||||||
|
- tut |
||||||
|
``` |
||||||
|
|
||||||
|
So edgy. Make the commit for `tot`, being sure that the value for the `--as` |
||||||
|
flag indicates you're committing _as_ `tot`: |
||||||
|
|
||||||
|
``` |
||||||
|
git add --all |
||||||
|
dehub commit --as tot change --descr 'tut is a butt' |
||||||
|
``` |
||||||
|
|
||||||
|
Somewhat unexpectedly, the commit has been created! You can see it by doing `git |
||||||
|
show`. Is dehub broken? |
||||||
|
|
||||||
|
The fact is that, regardless of whether or not the `dehub` tool allows one to |
||||||
|
create this commit, `tut` can create this commit. The important thing is that |
||||||
|
`tot` is able to notice that it's been created and do something about it. In a |
||||||
|
real-world situation, both `tot` and `tut` would be using different computers, |
||||||
|
and when `tot` (or anyone else) receives the commit from `tut` they will try to |
||||||
|
verify it, fail to do so, and ignore it. |
||||||
|
|
||||||
|
If you perform `dehub verify` you will be greeted with the following error: |
||||||
|
|
||||||
|
``` |
||||||
|
exiting: blah blah blah: commit matched and denied by this access control: |
||||||
|
action: deny |
||||||
|
filters: |
||||||
|
- type: files_changed |
||||||
|
pattern: .dehub/* |
||||||
|
``` |
||||||
|
|
||||||
|
Because the parent of this commit's config disallows this commit (via the given |
||||||
|
access control) it is not verifiable. Go ahead and delete the commit by doing: |
||||||
|
|
||||||
|
``` |
||||||
|
git reset --hard "$(git rev-list HEAD | tail -3 | head -n1)" |
||||||
|
``` |
||||||
|
|
||||||
|
## Step 2: Different Restrictions |
||||||
|
|
||||||
|
In light of `tot`'s recent actions it might be prudent to pull back their |
||||||
|
permissions a bit. Go ahead and change the `.dehub/config.yml` to: |
||||||
|
|
||||||
|
|
||||||
|
``` |
||||||
|
# abbreviated contents of .dehub/config.yml |
||||||
|
--- |
||||||
|
accounts: |
||||||
|
... |
||||||
|
|
||||||
|
access_controls: |
||||||
|
- action: allow |
||||||
|
filters: |
||||||
|
- type: signature |
||||||
|
account_ids: |
||||||
|
- tot |
||||||
|
- type: branch |
||||||
|
pattern: tot/* |
||||||
|
|
||||||
|
- action: deny |
||||||
|
filters: |
||||||
|
- type: signature |
||||||
|
account_ids: |
||||||
|
- tot |
||||||
|
``` |
||||||
|
|
||||||
|
and commit the change: |
||||||
|
|
||||||
|
``` |
||||||
|
git add --all |
||||||
|
dehub commit --as tut change --descr 'restrict tot to non-main branches' |
||||||
|
``` |
||||||
|
|
||||||
|
After this, `tot` will still be able to interact with the project, but only |
||||||
|
within branches whose names have the prefix `tot/`; the `main` branch remains |
||||||
|
open to other accounts, such as `tut`, due to the default access controls. |
||||||
|
|
||||||
|
### Check the New Restrictions |
||||||
|
|
||||||
|
`tot` has decided to do something constructive and wants to make a shell script |
||||||
|
which wraps the `echo` command. So helpful. Make a new branch for `tot` to use, |
||||||
|
and create a commit on it: |
||||||
|
|
||||||
|
``` |
||||||
|
git checkout -b tot/echo-script |
||||||
|
echo 'echo "$@"' > echo.sh |
||||||
|
git add echo.sh |
||||||
|
dehub commit --as tot change --descr "added echo.sh script" |
||||||
|
``` |
||||||
|
|
||||||
|
Check that the commit verifies (it should, since it's on a branch with the |
||||||
|
prefix `tot/`): |
||||||
|
|
||||||
|
``` |
||||||
|
dehub verify |
||||||
|
``` |
||||||
|
|
||||||
|
Now, as a final sanity check, you'll cherry-pick the commit onto `main` and |
||||||
|
ensure that it does _not_ verify there. |
||||||
|
|
||||||
|
``` |
||||||
|
git checkout main |
||||||
|
git cherry-pick tot/echo-script |
||||||
|
``` |
||||||
|
|
||||||
|
Running `dehub verify` now should fail, even though the commit remains the same. |
||||||
|
The only difference is the branch name; the commit is allowed in branches with |
||||||
|
the prefix `tot/`, and disallowed otherwise. |
||||||
|
|
||||||
|
Finally, reverse that cherry-pick to make main verifiable again: |
||||||
|
|
||||||
|
``` |
||||||
|
git reset --hard "$(git rev-list HEAD | tail -4 | head -n1)" |
||||||
|
``` |
||||||
|
|
||||||
|
You now have an understanding of how dehub's access controls work. Access |
||||||
|
controls are extremely flexible and can be formulated to fit a wide-variety of |
||||||
|
use-cases. In [Tutorial 3](tut3.html) we'll see how access controls can be |
||||||
|
formulated to allow for commit sign-offs, where multiple accounts must accredit |
||||||
|
a commit before it can be verified, and how such a commit can be created. |
@ -0,0 +1,247 @@ |
|||||||
|
# Tutorial 3: Commit Sign-Off |
||||||
|
|
||||||
|
Commit sign-off is a common pattern in vanilla git projects, where a commit must |
||||||
|
be approved by one or more people (besides the commit author themselves) in |
||||||
|
order to be allowed into the primary branch. |
||||||
|
|
||||||
|
dehub is able to accomplish this same pattern using only the access controls |
||||||
|
which have already been covered in this tutorial series and a command which has |
||||||
|
not: `dehub combine`. This tutorial will guide you through using `dehub combine` |
||||||
|
to facilitate commit sign-off. |
||||||
|
|
||||||
|
This tutorial assumes you have already completed [Tutorial 2](tut2.html), and |
||||||
|
builds on top of the project which was started there. |
||||||
|
|
||||||
|
## Step 0: Loosen the Previous Restrictions |
||||||
|
|
||||||
|
In the [previous tutorial](tut2.html) you took an existing project, added a new |
||||||
|
user `tot` to it, and then restricted `tot` to only be allowed to make commits |
||||||
|
in a certain subset of branches which excluded the `main` branch. |
||||||
|
|
||||||
|
As seen in that tutorial, `tot` is not able to create commits for the `main` |
||||||
|
branch _at all_. In this tutorial we're going to open `main` back up to `tot`, |
||||||
|
but only with a very important caveat: `tot`'s commits must be approved by |
||||||
|
someone else. |
||||||
|
|
||||||
|
In the `hello-world` project which was used for previous tutorials, with the |
||||||
|
`main` branch checked out, go ahead and modify `.dehub/config.yml` to have the |
||||||
|
following contents: |
||||||
|
|
||||||
|
``` |
||||||
|
# contents of .dehub/config.yml |
||||||
|
--- |
||||||
|
accounts: |
||||||
|
- id: tut |
||||||
|
signifiers: |
||||||
|
- type: pgp_public_key_file |
||||||
|
path: ".dehub/tut.asc" |
||||||
|
- id: tot |
||||||
|
signifiers: |
||||||
|
- type: pgp_public_key_file |
||||||
|
path: ".dehub/tot.asc" |
||||||
|
|
||||||
|
access_controls: |
||||||
|
- action: allow |
||||||
|
filters: |
||||||
|
- type: signature |
||||||
|
account_ids: |
||||||
|
- tot |
||||||
|
- type: branch |
||||||
|
pattern: tot/* |
||||||
|
|
||||||
|
- action: deny |
||||||
|
filters: |
||||||
|
- type: branch |
||||||
|
pattern: main |
||||||
|
- type: not |
||||||
|
filter: |
||||||
|
type: signature |
||||||
|
any_account: true |
||||||
|
count: 2 |
||||||
|
``` |
||||||
|
|
||||||
|
and commit the changes: |
||||||
|
|
||||||
|
``` |
||||||
|
git add .dehub/config.yml |
||||||
|
dehub commit --as tut change --descr 'require commit sign-offs in main' |
||||||
|
``` |
||||||
|
|
||||||
|
The primary change was to replace the old access control denying `tot` the |
||||||
|
ability to commit to anything (outside of `tot/*` branches) with this one: |
||||||
|
|
||||||
|
``` |
||||||
|
- action: deny |
||||||
|
filters: |
||||||
|
- type: branch |
||||||
|
pattern: main |
||||||
|
- type: not |
||||||
|
filter: |
||||||
|
type: signature |
||||||
|
any_account: true |
||||||
|
count: 2 |
||||||
|
``` |
||||||
|
|
||||||
|
There are two new things here. The first is the new fields on the `signature` |
||||||
|
filter: `any_account` replaces the `account_ids` field, and refers to any |
||||||
|
account which is defined in the `accounts` section; `count` declares how many |
||||||
|
accounts must have a signature on the commit for the filter to match (if not |
||||||
|
specified it defaults to 1). |
||||||
|
|
||||||
|
The second new thing is the `not` filter: `not` wraps any other filter, and |
||||||
|
reverses whether or not it matches. In this case, it's wrapping our `signature` |
||||||
|
filter, such that this access control will match only if the commit _does not_ |
||||||
|
have signature credentials from 2 different accounts. |
||||||
|
|
||||||
|
The total effect of this access control is to deny any commits to `main` which |
||||||
|
do not have signature credentials from 2 different accounts. In effect, commit |
||||||
|
sign-off. |
||||||
|
|
||||||
|
## Step 1: Some Changes to Merge |
||||||
|
|
||||||
|
In the previous tutorial `tot` created a new script, `echo.sh`, in a new branch |
||||||
|
called `tot/echo-script`. Check that branch out, rebase it on `main` (this will |
||||||
|
help in later steps), and add another script to it: |
||||||
|
|
||||||
|
``` |
||||||
|
git checkout tot/echo-script |
||||||
|
git rebase main |
||||||
|
echo 'echo "$@" | awk "{ print toupper(\$0) }"' > echo-upper.sh |
||||||
|
git add echo-upper.sh |
||||||
|
dehub commit --as tot change --descr 'echo-upper.sh' |
||||||
|
``` |
||||||
|
|
||||||
|
Now the `tot/echo-script` branch contains two commits which aren't on `main`, |
||||||
|
both of them signed by `tot`. What will happen next is that the branch's commits |
||||||
|
will be combined into a single commit, be given accreditation by both `tut` and |
||||||
|
`tot`, and added to the `main` branch. |
||||||
|
|
||||||
|
## Step 2: Accreditation |
||||||
|
|
||||||
|
First, `tot` will accredit both commits, and unify the two descriptions in the |
||||||
|
process. To do this, you will create your first `credential` commit: |
||||||
|
|
||||||
|
``` |
||||||
|
dehub commit --as tot credential --start HEAD^^ --descr 'add echo.sh and echo-upper.sh' |
||||||
|
``` |
||||||
|
|
||||||
|
A `credential` commit, at its core, contains nothing except credentials for any |
||||||
|
arbitrary fingerprint. To view the credential commit you just made |
||||||
|
do: `git show`. You should see a commit message like: |
||||||
|
|
||||||
|
``` |
||||||
|
Credential of AO3dn4Se61hq6OWy4Lm6m3MxdT2ru6TrIobuHaWJJidt |
||||||
|
|
||||||
|
--- |
||||||
|
type: credential |
||||||
|
commits: |
||||||
|
- f085f13fa839ece122476601d970460ac249dc69 # these will be different |
||||||
|
- 40a81ffb4f52dc4149570672f7f7fc053f12226a |
||||||
|
change_description: add echo.sh and echo-upper.sh |
||||||
|
fingerprint: AO3dn4Se61hq6OWy4Lm6m3MxdT2ru6TrIobuHaWJJidt |
||||||
|
credentials: |
||||||
|
- type: pgp_signature |
||||||
|
pub_key_id: XXX |
||||||
|
body: BIG LONG STRING |
||||||
|
account: tot |
||||||
|
``` |
||||||
|
|
||||||
|
You'll notice that the credential commit's fingerprint is different than either |
||||||
|
of the two commits it accredits. This is the fingerprint is based on the |
||||||
|
_combination_ of the two commits; it is based on the total of the file changes |
||||||
|
and the description provided by the user. The two commits are enumerated in the |
||||||
|
`commits` field of the payload, and the description provided by the user is |
||||||
|
stored in the `change_description` field. |
||||||
|
|
||||||
|
The combined commits have now been accredited by `tot`, but not `tut`, and so |
||||||
|
they still lack a necessary credential. Have `tut` make a credential now: |
||||||
|
|
||||||
|
``` |
||||||
|
dehub commit --as tut credential --rev HEAD |
||||||
|
``` |
||||||
|
|
||||||
|
This form of the `credential` sub-command only accredits a single commit. When a |
||||||
|
single commit is accredited and it itself is a credential commit then the new |
||||||
|
commit which is created is merely a copy of the specified credential commit with |
||||||
|
the caller's own credential appended to the `credentials` list. You can see this |
||||||
|
with `git show`, which should look like: |
||||||
|
|
||||||
|
``` |
||||||
|
Credential of AO3dn4Se61hq6OWy4Lm6m3MxdT2ru6TrIobuHaWJJidt |
||||||
|
|
||||||
|
--- |
||||||
|
type: credential |
||||||
|
commits: |
||||||
|
- f085f13fa839ece122476601d970460ac249dc69 # these will be different |
||||||
|
- 40a81ffb4f52dc4149570672f7f7fc053f12226a |
||||||
|
change_description: add echo.sh and echo-upper.sh |
||||||
|
fingerprint: AO3dn4Se61hq6OWy4Lm6m3MxdT2ru6TrIobuHaWJJidt |
||||||
|
credentials: |
||||||
|
- type: pgp_signature |
||||||
|
pub_key_id: XXX |
||||||
|
body: BIG LONG STRING |
||||||
|
account: tot |
||||||
|
- type: pgp_signature |
||||||
|
pub_key_id: XXX |
||||||
|
body: BIG LONG STRING |
||||||
|
account: tut |
||||||
|
``` |
||||||
|
|
||||||
|
There is now enough credentials to combine both commits in the `tot/echo-script` |
||||||
|
branch into a single commit on the `main` branch. |
||||||
|
|
||||||
|
## Step 3: Combination |
||||||
|
|
||||||
|
At this point the `tot/echo-script` branch has the following elements in place: |
||||||
|
|
||||||
|
* Two change commits, which we want to combine and bring over to `main`. |
||||||
|
* A credential commit made by `tot` for the combined changes. |
||||||
|
* A credential commit made by `tut` for the combined changes, which includes |
||||||
|
`tot`'s credentials. |
||||||
|
|
||||||
|
Combining the commits and placing them on `main` is done with a single command: |
||||||
|
|
||||||
|
``` |
||||||
|
dehub combine --start HEAD^^^^ --end HEAD --onto main |
||||||
|
``` |
||||||
|
|
||||||
|
This `combine` command combines all changes made within the given commit range, |
||||||
|
the last change description found in that range (in this case it will be from |
||||||
|
`tut`'s credential commit), and all credentials for that set of changes. The |
||||||
|
command combines them into a single commit which it places on the `main` branch. |
||||||
|
You can see the commit you've just created by doing: |
||||||
|
|
||||||
|
``` |
||||||
|
git checkout main |
||||||
|
git show |
||||||
|
``` |
||||||
|
|
||||||
|
The commit should contain both of the new files, and the message should look |
||||||
|
something like: |
||||||
|
|
||||||
|
``` |
||||||
|
add echo.sh and echo-upper.sh |
||||||
|
|
||||||
|
--- |
||||||
|
type: change |
||||||
|
description: add echo.sh and echo-upper.sh |
||||||
|
fingerprint: ALOcEuKJkgIdz27z0fjF1NEbK6Y9cEh2RH4/sL3uf3oa |
||||||
|
credentials: |
||||||
|
- type: pgp_signature |
||||||
|
pub_key_id: XXX |
||||||
|
body: BIG LONG BODY |
||||||
|
account: tot |
||||||
|
- type: pgp_signature |
||||||
|
pub_key_id: XXX |
||||||
|
body: BIG LONG BODY |
||||||
|
account: tut |
||||||
|
``` |
||||||
|
|
||||||
|
The commit is accredited by two different accounts, and so is allowed to be on |
||||||
|
the `main` branch. This can be verified by doing `dehub verify`. |
||||||
|
|
||||||
|
You now are able to require commit sign-off and create signed-off commits! The |
||||||
|
access control settings surrounding commit sign-offs are entirely up to you and |
||||||
|
your project's needs. You can require sign-off from specific accounts, any |
||||||
|
accounts, only on specific files, only in certain branches, etc... all using the |
||||||
|
same basic access control building blocks. |
Loading…
Reference in new issue