Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Secure cabal-install installation method #7639

Closed
AlistairB opened this issue Sep 12, 2021 · 39 comments
Closed

Secure cabal-install installation method #7639

AlistairB opened this issue Sep 12, 2021 · 39 comments

Comments

@AlistairB
Copy link

AlistairB commented Sep 12, 2021

👋 Haskell docker is exploring some alternative installation methods as https://downloads.haskell.org/debian/ is increasingly slow to be updated. This includes cabal-install which is currently installed via the debian package.

The direction we are thinking of going is directly installing ghc / cabal based on the releases on haskell.org. For example, we can download and GPG verify ghc releases.

Cabal on the other hand do not include GPG sig files that we can use for verification - https://downloads.haskell.org/~cabal/cabal-install-3.6.0.0/

May relate to #6616

Options

1. Cabal to provide GPG signature files

This would be ideal and is the simplest for us and the most secure. GHC has some doco about how this is done - https://gitlab.haskell.org/ghc/ghc/-/wikis/making-releases#sign-and-hash-the-release-artifacts . Perhaps Cabal releases can include a step like this?

2. Verify SHA256SUMS.sig

Cabal does include SHA256SUMS.sig + SHA256SUMS. The process would be something like:

  1. GPG verify SHA256SUMS.sig
  2. Fetch SHA from SHA256SUMS.
  3. Verify SHA256 of the release tar.

The current issue with this is I don't know what GPG key I need to verify SHA256SUMS.sig - https://downloads.haskell.org/~cabal/cabal-install-3.6.0.0/SHA256SUMS.sig.

$ gpg -vv SHA256SUMS.sig
gpg: WARNING: no command supplied.  Trying to guess what you mean ...
# off=0 ctb=89 tag=2 hlen=3 plen=435
:signature packet: algo 1, keyid B3D9F94B8DCAE210
	version 4, created 1631239102, md5len 0, sigclass 0x00
	digest algo 10, begin of digest 39 ed
	hashed subpkt 33 len 21 (issuer fpr v4 A970DF3AC3B9709706D74544B3D9F94B8DCAE210)
	hashed subpkt 2 len 4 (sig created 2021-09-10)
	subpkt 16 len 8 (issuer key ID B3D9F94B8DCAE210)
	data: [3071 bits]
gpg: assuming signed data in 'SHA256SUMS'
gpg: Signature made Fri 10 Sep 2021 11:58:22 AEST
gpg:                using RSA key A970DF3AC3B9709706D74544B3D9F94B8DCAE210
gpg: Can't check signature: No public key

I cannot find key B3D9F94B8DCAE210 anywhere. If this is the preferred option, can details of the key be given and can it be uploaded to some keysevers?

@AlistairB AlistairB changed the title Secure cabal installation method Secure cabal-install installation method Sep 12, 2021
@Mikolaj
Copy link
Member

Mikolaj commented Sep 13, 2021

@hasufell: doesn't ghcup provide that by chance?

@hasufell
Copy link
Member

hasufell commented Sep 13, 2021

I think the docker images maintainer has no interest in using ghcup.

GPG signing in ghcup has been discussed years ago, but no one really came up with a good proposal on how to integrate it:

  1. GPG verification is useless if you haven't verified the key
  2. Not all tarballs provide valid signatures
  3. Many outstanding questions wrt usability: do we invoke gpg via cli? What if it doesn't exist? What do we do on windows? How do we educate the user about it? Etc etc

And lastly: you can already verify ghcup metadata (which contains the hashes of all tarballs) through hoops:

  1. All commits in the ghcup repository are gpg signed
  2. So if you verify the latest commits gpg sig, you also verified https://gitlab.haskell.org/haskell/ghcup-hs/-/blob/master/data/metadata/ghcup-0.0.6.yaml
  3. Now you can check that your local yaml matches that remote files hash or you simply instruct ghcup to use an already verified metadata yaml via ghcup -s <file/http>://<uri> list

It's basically all there if you know what you're doing.

@Mikolaj
Copy link
Member

Mikolaj commented Sep 13, 2021

Oh, that's interesting. Let's brainstorm.

@AlistairB
Copy link
Author

AlistairB commented Sep 13, 2021

As @hasufell notes ghcup does not do GPG verification. As noted Not all tarballs provide valid signatures, cabal does not provide signatures for the release tars, which if resolved would allow for option 1 I have listed. My understanding of ghcup is that it checks the sha256 hash of the releases.

Ideally we want to do the GPG (PGP) verification as official docker images are recommended to do PGP based verification. My understand is that this is stronger as it ties the verification to the user that publishes the artefacts and signature files. You can then choose to trust that user's key. (I've just learnt about all of this recently.. so don't have a deep understanding 😅)

Stack does provide GPG signature files and the current ghc / cabal debian packages also provides this. Which is why we don't want lose it if possible with a new installation approach.

I think the docker images maintainer has no interest in using ghcup.

Can we please assume that everyone is just aiming for the best technical solution? I was directly pushing for a ghcup based solution until @psftw highlighted the shortcomings around the GPG verification. I have no bias other than the best result for the official haskell docker users.

If you really want ghcup to be used in the images I would suggest looking into lack of GPG verification support. (FWIW I think ghcup is AWESOME and I use it :) )

@Mikolaj
Copy link
Member

Mikolaj commented Sep 13, 2021

Uhoh, I apparently made a faux pas. Apologies.

I, too, think that ghcup (and docker-haskell) is AWESOME. :)

@hasufell
Copy link
Member

hasufell commented Sep 13, 2021

If you really want ghcup to be used in the images I would suggest looking into lack of GPG verification support.

Well, GPG is widely misunderstood and I think this misunderstanding is present here as well.

Again: GPG is useless if you don't verify the key. In the sense that it has similar guarantees as SSL, which you're already using successfully. It makes only sense if you trust the person and can manually verify that the key belongs to that person. For all other intents and purposes, GPG is in fact useless. Verifying that a key belongs to a person requires effort (e.g. calling them, sharing secrets, meeting in person, also see https://en.wikipedia.org/wiki/Key_signing_party).

Also, I've already described how you can use gpg today:

  1. have a conversation with me and figure out if you trust me
  2. meet me in person and get my gpg key
  3. clone the ghcup repository and verify the latest commit signature via git log --show-signature
  4. copy data/metadata/ghcup-0.0.6.yaml to your Dockerfile repo and then have the Dockerfil copy it into the docker image
  5. optionally sign it with your own gpg key and do whatever verification you intend
  6. use ghcup -s file:///path/to/ghcup-0.0.6.yaml install ghc ... to only use the previously verified metadata file
  7. Since the metadata file contains sha256 hashes, which are collision resistant, there's no reason to also gpg-verify the tarballs. The chain of trust is met.

But... I mean... what's the point? How does the user know the image they download correspond to the Dockerfile that does the gpg verification? How does the user even know the gpg signature in the Dockerfile is correct/good? You have to sign the Dockerfile as well (or every git commit in your repo). And... does the user even trust you? How are they gonna establish trust with you and verify your key?

So you see... automatic verification isn't really possible.

@emilypi
Copy link
Member

emilypi commented Sep 13, 2021

@AlistairB just to update, I uploaded my key to OpenPGP (https://keys.openpgp.org/vks/v1/by-fingerprint/A970DF3AC3B9709706D74544B3D9F94B8DCAE210) and ubuntu's keyservers. I hope that helps

@AlistairB
Copy link
Author

AlistairB commented Sep 14, 2021

Thanks @emilypi !

I can confirm this is working and I can do:

$ gpg --batch --keyserver keyserver.ubuntu.com --recv-keys b3d9f94b8dcae210
$ curl -O https://downloads.haskell.org/~cabal/cabal-install-3.6.0.0/SHA256SUMS.sig
$ curl -O https://downloads.haskell.org/~cabal/cabal-install-3.6.0.0/SHA256SUMS
$ gpg --verify SHA256SUMS.sig

And it will successfully verify. Which means we can do option 2.

Although, options 1 is ideal as it is simpler (ahem for haskell docker, or others who care) and I think more secure as the final cabal-install binary is being gpg verified, not something in a chain.

Is it possible for you to execute these steps which is what ghc releases are doing?

I would be happy to help in any way that I can ie. add this info to the release checklist or making a release?


@hasufell you may be right, but the point is somewhat moot as the official docker images are recommended to gpg verify any downloaded artefacts as part of the docker build process. There is a review process when updating official images where they will call out stuff like this. Ideally we want to follow their best practice standards unless we have a good reason.

@hasufell
Copy link
Member

you may be right, but the point is somewhat moot as the official docker images are recommended to gpg verify any downloaded artefacts as part of the docker build process.

Yeah, I read it and it clearly states that sha256 sums are valid as well.

@AlistairB
Copy link
Author

Yeah, I read it and it clearly states that sha256 sums are valid as well.

True, they are considered acceptable but as a "Less Secure Alternate" option. I don't want to downgrade the security from the "Preferred" option if possible. The more secure, the more considered best practice by the official images the better I think.

@hasufell
Copy link
Member

So from ghcup perspective I think there's nothing to do. The releases are gpg signed, the metadata can be gpg verified too.

@hasufell
Copy link
Member

hasufell commented Sep 14, 2021

At any rate: I also signed the metadata explicitly, so they're at https://www.haskell.org/ghcup/data/ghcup-<yamlver>.yaml.sig

That way you don't have to go through the git repo. A user can use this information to conform with the docker library standard if they deem that necessary.

@hasufell
Copy link
Member

https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/178
https://gitlab.haskell.org/haskell/ghcup-hs/-/tree/gpg#gpg-verification

Might be of interest. So something like ghcup --gpg=strict install cabal will do it. Given that you've verified the key properly (which most people won't do).

@jneira
Copy link
Member

jneira commented Sep 18, 2021

i think gpg is an excuse to encourage face to face relations 😄

@hasufell
Copy link
Member

i think gpg is an excuse to encourage face to face relations 😄

Yeah, haven't had visitors in a while, so I'm rather thrilled about this feature!

5ngnyj.jpg

@AlistairB
Copy link
Author

AlistairB commented Sep 19, 2021

That way you don't have to go through the git repo. A user can use this information to conform with the docker library standard if they deem that necessary.

@hasufell to clarify the goal of this particular issue is to have cabal, like ghc and stack, provide gpg signature files for the cabal release tar (in the ideal case of option 1).

As mentioned, the motivation in my case is so that the cabal release can be gpg verified as part of the docker haskell build. This is because we want all downloaded artefacts to be gpg verified as per the official guidelines (and as per the current images).

This verification could be done directly via gpg, or it could be done by docker invoking ghcup which then does it. So cabal releases must be updated to include the signature files to fully conform with the official docker guidelines, regardless of the installation method.

i think gpg is an excuse to encourage face to face relations 😄

Hehe, whilst amusing gpg as I understand it is not about trusting the person who does the releases. It is about making it more difficult for someone else nefarious to replicate a release that is not detected. For example someone might hack in and write a SHA256SUMS and cabal-install-3.6.0.0.tar.gz to https://downloads.haskell.org/~cabal/cabal-install-3.6.0.0/ . However, when using gpg they would also need to get a hold of the GPG private key of Emily to create a cabal-install-3.6.0.0.tar.gz.sig file (which probably lives on her machine and may have a passphrase). So it adds another layer of security.

@hasufell
Copy link
Member

hasufell commented Sep 19, 2021

However, when using gpg they would also need to get a hold of the GPG private key of Emily to create a cabal-install-3.6.0.0.tar.gz.sig file

Wrong.

Emily isn't the only person who made releases in the past and won't be the only making them in the future.

There are multiple keys you have to trust today to verify all releases.

So all an attacker needs is access to the downloads file server and the place where we publish the keys (eg homepage). Then they upload perfectly signed releases and add their gpg key to the list, instructing users to blindly trust them (like you do in your Dockerfiles).

That isn't hard and adds no significant layer of security. This is possible with MITM today.

@AlistairB
Copy link
Author

Sorry @hasufell but I'm going to opt out of the merits of gpg discussion. Arguing about the pros and cons of gpg is as mentioned a moot point.

The docker official images state that gpg verifying downloaded artefacts is "Preferred" and checking sha256 is "Less Secure". Whilst that is the recommendation and particularly while the current images achieve this we should endeavour to maintain it.

Even if gpg 'adds no significant layer of security', it is still gives more options for cabal users to pick their preferred verification method. My hope is that adding the signature files is not much work.

@hasufell
Copy link
Member

Sorry @hasufell but I'm going to opt out of the merits of gpg discussion. Arguing about the pros and cons of gpg is as mentioned a moot point.

Sure, but my point is that you seem to not understand attack vectors and threat scenarios very well and your use of GPG is compromised.

That's why I suggest to either refrain from using it or start doing research on how to use it.

Spreading misinformation about security topics is dangerous and we have an obligation to educate users about it.

@AlistairB
Copy link
Author

Sure, but my point is that you seem to not understand attack vectors and threat scenarios very well and your use of GPG is compromised.

That's why I suggest to either refrain from using it or start doing research on how to use it.

Spreading misinformation about security topics is dangerous and we have an obligation to educate users about it.

LOL

@hasufell
Copy link
Member

hasufell commented Sep 19, 2021

LOL

Here are some links from security researchers that you might consider: https://www.schneier.com/blog/archives/2016/12/giving_up_on_pg.html

And the linked essay: http://arstechnica.com/security/2016/12/op-ed-im-giving-up-on-pgp/

@AlistairB
Copy link
Author

AlistairB commented Sep 19, 2021

Honestly @hasufell my link to you would be this and I'm sure I can do better here as well! Sorry! ❤️

@haskell haskell locked as too heated and limited conversation to collaborators Sep 20, 2021
@emilypi
Copy link
Member

emilypi commented Sep 20, 2021

I think with that, we can stop the back and forth. Apologies @AlistairB and @hasufell, but let's cool off and come back another time when the thread of mutual respect returns to the conversation

@ulysses4ever
Copy link
Collaborator

@Mikolaj do you think GPG signatures could be included in (future) cabal releases? I was reading on this thread and it leaves a really sorry impression. My understanding:

  • the fine people doing Haskell Docker images need GPG as per general Docker guidelines,
  • GHC already does GPG,
  • Cabal (cabal-install) comes second only to GHC in being an integral part to Haskell development, so unlocking the Docker folks and following GHC example seems natural.

I don’t know how much effort this requires but at least it should be more or less one time cost: once set up, the signatures will be done and by the CI?

@Mikolaj
Copy link
Member

Mikolaj commented Aug 9, 2022

I have the advantage of being a simple-minded person that doesn't understand the GPG pragmatics, so I'm absolutely fine accepting any not too burdensome rituals that others think would help them in this respect. Especially if we just follow GHC practice straightforwardly. PRs welcome.

@fgaz
Copy link
Member

fgaz commented Aug 9, 2022

I wonder if a much simpler SSH signature would be acceptable

the signatures will be done and by the CI?

does ghc do that? is it a good idea to upload a private key to CI?

@ulysses4ever
Copy link
Collaborator

This issue is still locked. Should we pick a venue where Docker people will be able to engage (e.g. unlock the issue, open a new one, etc.)?

@fgaz is there a reason to believe managing SSH keys will be any easier than GPG ones? If not, perhaps, it's better to follow what Docker people already support and/or what GHC does? @bgamari do you have an advice on what cabal should do w.r.t. signing its binaries?

@fgaz
Copy link
Member

fgaz commented Aug 9, 2022

@fgaz is there a reason to believe managing SSH keys will be any easier than GPG ones?

Yes: most developers already have an SSH key (and cabal contributors must have one - by virtue of the project being hosted on github), while not many have a GPG key. Other advantages are mentioned in the article I linked.

@hasufell
Copy link
Member

hasufell commented Aug 9, 2022

do you think GPG signatures could be included in (future) cabal releases

They are already signed: https://downloads.haskell.org/~cabal/cabal-install-3.8.1.0/SHA256SUMS.sig

I'm not sure who is the signer though.

Signing binaries is not required. Signing the hashes is enough.

@haskell haskell unlocked this conversation Aug 9, 2022
@ulysses4ever
Copy link
Collaborator

They are already signed: https://downloads.haskell.org/~cabal/cabal-install-3.8.1.0/SHA256SUMS.sig

This has been discussed: the Docker people ask to do what GHC does, i.e. not (only) signing the hashes, but also the binaries.

@Mikolaj
Copy link
Member

Mikolaj commented Aug 9, 2022

I'm not sure who is the signer though.

I'm the signer and I've uploaded my key to keys.openpgp.org.

@AlistairB
Copy link
Author

Firstly, apologies for my part in the heated discussion 🙇

I wish to avoid rehashing the same arguments but I'll briefly state my current thoughts.

Providing more mechanisms to verify the cabal-install releases, such as signing the all the files in the release is just a good thing IMO. People can select which verification method they prefer and can continue to use SHA256SUMS.sig if that is what they like.

In the case of the haskell docker images, the docker official images people recommend a specific verification strategy which requires signing the release tars/artefacts themselves. This is what stack and GHC provide and we conform to this pattern.

Lacking this for cabal-install with some help from the official images people we have used an alternate method utilizing SHA256SUMS.sig which is a bit more cumbersome. I will decline to discuss the merits of these 2 methods. I simply wish to follow their recommended practices. However, I think it is fair to say the current method we use is still pretty good, so if the decision is to keep doing things as is that is OK. Feel free to close the issue if so.

If you want to provide these additional signature files, I believe the making a release wiki instructions need to be updated with something like the GHC release signing instructions. eg. gpg --detach-sign SHA256SUMS -> gpg --detach-sign *.tar.xz SHA256SUMS . I think a cabal maintainer will need to make those changes.

I'm the signer and I've uploaded my key to keys.openpgp.org.

@Mikolaj would you mind uploading your key to keyserver.ubuntu.com. That is what we use in the haskell docker images. If I recall we had issues using keys.openpgp.org in the past.

@ffaf1
Copy link
Collaborator

ffaf1 commented Aug 10, 2022 via email

@hasufell
Copy link
Member

They are already signed: https://downloads.haskell.org/~cabal/cabal-install-3.8.1.0/SHA256SUMS.sig

This has been discussed: the Docker people ask to do what GHC does, i.e. not (only) signing the hashes, but also the binaries.

Again: it does not make any sense cryptographically and there is nothing in the docker documentation suggesting this is necessary. Otherwise using package managers inside docker would violate their policy too.

@AlistairB
Copy link
Author

Keyservers are federated and, bar bugs or policy, share keysets periodically. @Mikolaj’s keys is already at Ubuntu’s keyserver

Ah awesome, thanks for the info. Indeed this is now available and working.

@Mikolaj
Copy link
Member

Mikolaj commented Aug 10, 2022

eg. gpg --detach-sign SHA256SUMS -> gpg --detach-sign *.tar.xz SHA256SUMS

Is that really it? That's no burden at all. I have these files in a directory anyway, whenever I release. I've made the change to the wiki, please kindly verify.

@AlistairB
Copy link
Author

AlistairB commented Aug 10, 2022

Is that really it? That's no burden at all. I have these files in a directory anyway, whenever I release. I've made the change to the wiki, please kindly verify.

Looks good! You may as well include .zip ie. gpg --detach-sign *.tar.xz *.tar.gz *.zip SHA256SUMS for good measure as stack and GHC sign these as well, although the haskell official images don't need the zip signed (none of the official images do the gpg verify step on windows. I'm guessing the gpg windows cli support is not great). Either way looks great thanks!

@Mikolaj
Copy link
Member

Mikolaj commented Aug 10, 2022

You may as well include .zip

Done. I guess we are going to use this for the next release. Anything else needed to complete the ticket?

@AlistairB
Copy link
Author

AlistairB commented Aug 10, 2022

Nope that is it. Thank you! ❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants