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

feat(queue)!: add priv/pub key signing #843

Merged
merged 29 commits into from
Aug 25, 2023
Merged

feat(queue)!: add priv/pub key signing #843

merged 29 commits into from
Aug 25, 2023

Conversation

plyr4
Copy link
Contributor

@plyr4 plyr4 commented May 11, 2023

closes go-vela/community#807

this adds environment variables (VELA_QUEUE_SIGNING_PRIVATE_KEY and VELA_QUEUE_SIGNING_PUBLIC_KEY) that represent a private/public key pair used for signing/opening items that land on the redis queue.

  • VELA_QUEUE_SIGNING_PRIVATE_KEY would be required in the server.
  • VELA_QUEUE_SIGNING_PUBLIC_KEY would be required in the worker.
  • modifies queue.Push to "sign" items pre-flight.
  • modifies queue.Pop to "open" items post-retrieval.

its a sorta-hack to implement read-only access to the queue that is agnostic of redis installation.

it would require that admins generate and provide a keypair on startup that is encoded in base64.

merging this requires the followup PR for the worker: go-vela/worker#498

it also still needs admin documentation

@plyr4
Copy link
Contributor Author

plyr4 commented May 11, 2023

should i make this optional?
is there a reason someone might want their installation running without queue signing?

@cognifloyd
Copy link
Member

Could the worker retrieve the public key as part of the registration flow?

@plyr4
Copy link
Contributor Author

plyr4 commented May 12, 2023

Could the worker retrieve the public key as part of the registration flow?

absolutely, and it makes me think there would be value in also allowing stored keys to be updated on the fly for a currently-running worker, so we dont depend on a service reboot/restart if, say, the server keys require rotation.

@plyr4
Copy link
Contributor Author

plyr4 commented Aug 8, 2023

opening this for review for v0.21.
the two enhancements described in the comments will be addressed separately.

@plyr4
Copy link
Contributor Author

plyr4 commented Aug 9, 2023

one question for the reviewers, should we accept empty signing keys and skip signing? or just embed a default private/public key so that if you dont provide one, it uses the insecure default?

@plyr4 plyr4 marked this pull request as ready for review August 9, 2023 14:15
@plyr4 plyr4 requested a review from a team as a code owner August 9, 2023 14:15
@codecov
Copy link

codecov bot commented Aug 9, 2023

Codecov Report

Merging #843 (f24894c) into main (5f6be5c) will decrease coverage by 0.05%.
The diff coverage is 65.59%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #843      +/-   ##
==========================================
- Coverage   70.89%   70.84%   -0.05%     
==========================================
  Files         310      311       +1     
  Lines       12743    12833      +90     
==========================================
+ Hits         9034     9092      +58     
- Misses       3255     3278      +23     
- Partials      454      463       +9     
Files Changed Coverage Δ
router/middleware/signing.go 0.00% <0.00%> (ø)
queue/redis/opts.go 80.00% <64.00%> (-20.00%) ⬇️
queue/redis/pop.go 76.92% <64.70%> (-11.54%) ⬇️
queue/redis/push.go 84.21% <81.25%> (-0.79%) ⬇️
queue/redis/redis.go 86.23% <100.00%> (+0.25%) ⬆️
queue/setup.go 100.00% <100.00%> (ø)

@wass3rw3rk
Copy link
Member

wass3rw3rk commented Aug 9, 2023

one question for the reviewers, should we accept empty signing keys and skip signing? or just embed a default private/public key so that if you dont provide one, it uses the insecure default?

i think i lean towards requiring signing as long as we keep it easy for local dev and either supply keys or create on the fly. that wouldn't be much different than slapping secret in docker-compose as we do.

@plyr4 plyr4 changed the title feat: add queue signing feat!(queue): add priv/pub key signing Aug 16, 2023
queue/redis/opts.go Outdated Show resolved Hide resolved
queue/redis/opts.go Outdated Show resolved Hide resolved
queue/redis/pop.go Outdated Show resolved Hide resolved
queue/redis/pop.go Show resolved Hide resolved
queue/redis/push.go Show resolved Hide resolved
@plyr4 plyr4 marked this pull request as draft August 17, 2023 15:29
@plyr4 plyr4 marked this pull request as ready for review August 17, 2023 16:43
@plyr4 plyr4 changed the title feat!(queue): add priv/pub key signing feat(queue)!: add priv/pub key signing Aug 23, 2023
timhuynh94
timhuynh94 previously approved these changes Aug 23, 2023
KellyMerrick
KellyMerrick previously approved these changes Aug 23, 2023
Copy link
Contributor

@KellyMerrick KellyMerrick left a comment

Choose a reason for hiding this comment

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

lgtm

Copy link
Contributor

@ecrupper ecrupper left a comment

Choose a reason for hiding this comment

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

LGTM. Had a couple comments and questions

Cluster: c.Bool("queue.cluster"),
Routes: c.StringSlice("queue.routes"),
Timeout: c.Duration("queue.pop.timeout"),
EncodedSigningPrivateKey: c.String("queue.signing.private-key"),
Copy link
Contributor

Choose a reason for hiding this comment

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

Matter of preference, but I'd prefer brevity with this struct field name

Copy link
Contributor Author

Choose a reason for hiding this comment

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

agreed, im bad at naming, any suggestions on replacement? maybe since we're already in the queue package...

Suggested change
EncodedSigningPrivateKey: c.String("queue.signing.private-key"),
PrivateKey: c.String("queue.private-key"),

Copy link
Contributor

Choose a reason for hiding this comment

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

I like it

return nil
}

privateKeyDecoded, err := base64.StdEncoding.DecodeString(privateKeyEncoded)
Copy link
Contributor

Choose a reason for hiding this comment

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

We don't expect base64 encoding in any of our other private keys (token manager, DB encryption). Is there a reason why we're going with this pattern here? Should this be standardized across all private keys?

Copy link
Contributor Author

@plyr4 plyr4 Aug 23, 2023

Choose a reason for hiding this comment

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

good question, i used base64 here because the private/public keys i generated arent in unicode.
(using this process to make it easier: https://go.dev/play/p/-go_7SnJbnP)
base64 encoding them made it easy to copy+paste, store elsewhere, put into transit, easier handling.

for the other values in the server? id argue we should base64 anything that isnt in a format that is easy to handle.
though i think the other keys are fine because we recommend generating them using -hex from a unicode-safe characterset.

openssl rand -hex 16

from docs
https://go-vela.github.io/docs/installation/server/docker/#step-4-create-the-private-key

so... honestly yeah we should base64 more, but for queue signing since hex isnt a valid way to generate the keypair it becomes more important to encode the pair.

Copy link
Contributor

Choose a reason for hiding this comment

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

Cool, thanks for the explanation

queue/redis/pop.go Outdated Show resolved Hide resolved
Comment on lines 37 to 40
// sign the item using the private key generated using sign
//
// https://pkg.go.dev/golang.org/x/[email protected]/nacl/sign
signed = sign.Sign(out, item, c.config.SigningPrivateKey)
Copy link
Contributor

Choose a reason for hiding this comment

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

Interesting that the library here calls out

Sign uses Ed25519 to sign messages. The length of messages is not hidden. Messages should be small because: 1. The whole message needs to be held in memory to be processed. 2. Using large messages pressures implementations on small machines to process plaintext without verifying the signature.

Prior to #927, I would have been concerned about how long pipeline.Build can be. Something to keep in mind in case we wanted to add anything else to the queue... I think build, repo, and user are small enough to not cause issues. Tried digging in to how long a message can be before considered to be "too long", but didn't find much. I imagine it's a pretty big number.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

good call out, i'll try out some massive payloads and see what happens.
im not sure if the library maybe duplicates the in-memory object while processing it, but, we already store a couple pipelines in memory so im imaging it will be fine. ill test

@plyr4 plyr4 dismissed stale reviews from KellyMerrick and timhuynh94 via 37926a5 August 23, 2023 16:27
ecrupper
ecrupper previously approved these changes Aug 23, 2023
Copy link
Contributor

@KellyMerrick KellyMerrick left a comment

Choose a reason for hiding this comment

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

lgtm

@plyr4 plyr4 merged commit 172a998 into main Aug 25, 2023
11 of 12 checks passed
@plyr4 plyr4 deleted the feat/queue-signing branch August 25, 2023 16:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

enhance: add key signing to queue items
6 participants