Skip to content
This repository has been archived by the owner on Nov 1, 2022. It is now read-only.

Verify git commit signatures #1791

Merged
merged 5 commits into from
May 9, 2019
Merged

Verify git commit signatures #1791

merged 5 commits into from
May 9, 2019

Conversation

hiddeco
Copy link
Member

@hiddeco hiddeco commented Mar 4, 2019

Fixes #1683

This feature adds the --git-verify-signatures flag to the daemon.
When this flag is set the daemon will verify the signatures of the tag
and all commits it is working with, ensuring no unauthorized
modifications are synchronized.

To ensure the daemon always synchronizes a verified state a ratchet
mechanism was introduced to the loop. This mechanism moves the sync
HEAD to the latest valid revision after repository refreshes. During
sync runs this revision gets checked out and is applied on to the
cluster.

During modification actions, either automated or instructed by fluxctl
commands, the HEAD of the working clone is compared to the latest valid
revision. If these mismatch the commit is blocked and an error is
returned as the daemon can not be sure it is committing on top of a
verified state.

daemon/loop.go Outdated Show resolved Hide resolved
@hiddeco hiddeco force-pushed the git-verify branch 9 times, most recently from 2a0fee2 to 320e112 Compare March 7, 2019 13:55
daemon/sync.go Outdated Show resolved Hide resolved
daemon/sync.go Outdated Show resolved Hide resolved
daemon/sync.go Outdated Show resolved Hide resolved
Copy link
Member

@squaremo squaremo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is shaping up well! I am not convinced by the imagePollLock -- see what you think of my reasoning in the comments ...

daemon/sync.go Outdated Show resolved Hide resolved
daemon/sync.go Outdated Show resolved Hide resolved
daemon/loop.go Outdated Show resolved Hide resolved
@jimmyjones2
Copy link

Hey @hiddeco, thanks for your work on this. I presume the admin would configure the operator with their trusted GPG keys?

How do you plan on handling the case when trust is revoked, eg. when someone leaves or their key is compromised? However you'd still want to trust their commits up to a certain point. In normal operation I guess this wouldn't be an issue, as flux would have checked for valid signatures at the time and moved passed that commit and wouldn't ever check again retrospectively. However if you wanted to redeloy from scratch, it would try and verify all commits from the first and fail. Could there be an option to only verify commits from a certain point to handle this and the scenario where someone want to migrate to enforcing signatures without rewriting their history to be all signed?

@hiddeco
Copy link
Member Author

hiddeco commented Mar 18, 2019

I presume the admin would configure the operator with their trusted GPG keys?

Correct, any key imported to Flux (or configured by setting the GNUPGHOME environment variable) is seen as trusted.

How do you plan on handling the case when trust is revoked, eg. when someone leaves or their key is compromised?

This is a good question, and I see two possible solutions

  1. Is letting a human apply the insecure state and create a signed git tag, the daemon will then start synchronization from this point and all is well.

    I like this approach because it is secure and leaves no space for attack vectors. I dislike this approach because it requires manual interaction (although this process could be automated).

  2. Is adding a flag like you suggested, to instruct the daemon to start verifying commits after a certain revision. This is super friendly to our users but also way easier to abuse.

If you put those two on a scale I am not sure what outweighs as the best option. Although the purist in me is telling me to go for option 1.

@2opremio
Copy link
Contributor

refactor the gigantic doSync() method in to smaller elements

❤️

@jimmyjones2
Copy link

  1. Is letting a human apply the insecure state and create a signed git tag, the daemon will then start synchronization from this point and all is well.

I like this approach because it is secure and leaves no space for attack vectors. I dislike this approach because it requires manual interaction (although this process could be automated).

I like this too. Considering people will already in the business of signing commits, doesn't seem that much more to ask to tag where to start from, especially as it'll be rare thing to need to do.

@hiddeco
Copy link
Member Author

hiddeco commented Mar 20, 2019

Gave my head some rest from this after having seen 3 revisions of the solution and I think we are almost there.

The ratchet mechanism introduced detaches the sync itself from the verification part and gives us one point of truth for validated state we are working with, which is really nice (thanks @squaremo for your input on this).

Besides a rebase, there are two things I would like to tackle before this feature is complete:

  • Some listing commands need to work with the verified HEAD instead of the HEAD from the repository.
  • Documentation, and especially documentation about disaster recovery and working with revoked and/or compromised keys. The outline for this is point 1 in my comment above.

@hiddeco hiddeco force-pushed the git-verify branch 3 times, most recently from ec322d4 to ff603fe Compare March 21, 2019 17:19
@hiddeco hiddeco mentioned this pull request Mar 25, 2019
@hiddeco hiddeco force-pushed the git-verify branch 2 times, most recently from c823567 to e6cd756 Compare March 25, 2019 18:43
@hiddeco hiddeco marked this pull request as ready for review March 26, 2019 08:44
Copy link
Member

@squaremo squaremo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments, having followed the instructions:

The instructions are thorough and high quality. There's a couple of bits where it's not clear which key ID is supposed to be used (my understanding is that it's any of them -- but this isn't pointed out, only implied).

When I got to the end and wanted to kick start syncing with verified signatures. I signed the sync tag and pushed that, but the sync process still seems stuck at the first ever commit. I'm not clear on whether I did something wrong, or have the wrong expectation.

cmd/fluxctl/sync_cmd.go Outdated Show resolved Hide resolved
site/git-gpg.md Outdated Show resolved Hide resolved
site/git-gpg.md Outdated Show resolved Hide resolved
site/git-gpg.md Outdated Show resolved Hide resolved
site/git-gpg.md Outdated Show resolved Hide resolved
site/git-gpg.md Show resolved Hide resolved
site/git-gpg.md Show resolved Hide resolved
@hiddeco
Copy link
Member Author

hiddeco commented Mar 29, 2019

Tests are failing due to the Git version in the circleci/golang:1.10 image being too old (--format was introduced in Git 2.12) 😞

@hiddeco hiddeco force-pushed the git-verify branch 2 times, most recently from a1a79c8 to 5053c06 Compare April 10, 2019 16:07
@squaremo
Copy link
Member

For the record: I've happy with how this works and is explained in the docs, but haven't been through the implementation with a fine-toothed comb yet

@squaremo squaremo requested a review from 2opremio April 11, 2019 15:53
@hiddeco hiddeco added this to the v1.13.0 milestone Apr 24, 2019
Copy link
Member

@squaremo squaremo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this is in good shape, and thorough. I think type Sync struct may be more trouble than it's worth -- see if you agree with my comment on that.

I need to check on the possible issue with empty commit notifications that you mentioned IRL; other than that, I think only tidies (or counter arguments) are required here.

daemon/loop.go Outdated Show resolved Hide resolved
cmd/fluxd/main.go Outdated Show resolved Hide resolved
daemon/daemon.go Show resolved Hide resolved
git/working.go Outdated Show resolved Hide resolved
cmd/fluxd/main.go Show resolved Hide resolved
git/working.go Outdated Show resolved Hide resolved
daemon/sync.go Show resolved Hide resolved
daemon/daemon.go Outdated Show resolved Hide resolved
daemon/sync.go Outdated Show resolved Hide resolved
daemon/sync.go Outdated Show resolved Hide resolved
@hiddeco hiddeco force-pushed the git-verify branch 5 times, most recently from f91bd2c to c8885a3 Compare May 7, 2019 09:35
@hiddeco
Copy link
Member Author

hiddeco commented May 7, 2019

@squaremo addressed all your comments and verified (and fixed) my own theory in 4941138.

Copy link
Member

@squaremo squaremo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Getting into nitty-gritty now -- Ii think the code is almost correct as it stands (there's one error check missing). I'm going to build it and run it, again

daemon/errors.go Show resolved Hide resolved
daemon/sync.go Outdated Show resolved Hide resolved
daemon/sync.go Outdated Show resolved Hide resolved
daemon/sync.go Outdated Show resolved Hide resolved
@hiddeco hiddeco force-pushed the git-verify branch 2 times, most recently from 1403dcd to 3aeae2b Compare May 7, 2019 17:26
Copy link
Member

@squaremo squaremo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am happy this is explained well, works as explained, and the code is sound ⛰️. I would suggest git rebase -i to straighten out some of the twists and turns (and to bring it up to date with respect to master).

@hiddeco hiddeco force-pushed the git-verify branch 3 times, most recently from 3aeae2b to a041e90 Compare May 9, 2019 12:15
hiddeco added 5 commits May 9, 2019 15:23
This feature adds the `--git-verify-signatures` flag to the daemon.
When this flag is set the daemon will verify the signatures of the tag
and all commits it is working with, ensuring no unauthorized
modifications are synchronized.

To ensure the daemon always synchronizes a verified state a ratchet
mechanism was introduced to the loop. This mechanism moves the sync
HEAD to the latest valid revision after repository refreshes. During
sync runs this revision gets checked out and is applied on to the
cluster.

During modification actions, either automated or instructed by fluxctl
commands, the HEAD of the working clone is compared to the latest valid
revision. If these mismatch the commit is blocked and an error is
returned as the daemon can not be sure it is committing on top of a
verified state.
This is required when signature verification is enabled as git will
otherwise give an 'U' status back for the signature (good signature
with unknown validity) instead of the 'G' we are aiming for (good
(valid) signature).

We apply this blindly on all keys known to gpg as all keys are added
by the user and thus already trusted.
This makes it possible to, for example, seperate the GPG private key
Flux signs commits with from the public keys Flux verifies commits
with.
@hiddeco hiddeco merged commit bbc0865 into master May 9, 2019
@hiddeco hiddeco deleted the git-verify branch May 9, 2019 13:39
@hiddeco hiddeco mentioned this pull request May 22, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

git signature verification
4 participants