feat(auth): add native rfc9421 HTTP Message Signatures filter (#3952) - #4209
feat(auth): add native rfc9421 HTTP Message Signatures filter (#3952)#4209shardool-patil wants to merge 1 commit into
Conversation
|
@shardool-patil can you add the egress filter also to docs/reference/egress.md ? |
|
|
||
| Signs outgoing HTTP requests according to [RFC 9421 (HTTP Message Signatures)](https://www.rfc-editor.org/rfc/rfc9421). It computes the signature across specified HTTP fields and attaches the `Signature-Input` and `Signature` headers. | ||
|
|
||
| The private key must be supplied via the temporary `x-rfc9421-private-key` request header. The filter reads the key into memory and deletes the header before forwarding the request upstream. |
There was a problem hiding this comment.
Not a bad idea but I would like to have this integrated via ./secrets module, instead.
The people who create the filter are likely not the ones that run skipper, so they have no idea where to read the key from and should not have access to the key. They could easily get the key:
setRequestHeaderFromSecret("x-rfc9421-private-key", "/tmp/secrets/api-secret")
-> logHeader("request")
If the operator is serious about this kind of problem then they can disable the filter setRequestHeaderFromSecret to ensure that people that can create a route and be able to read logs are not able to read the secret key.
|
|
||
| // NewRFC9421 creates a new filter specification for RFC 9421 HTTP Message Signatures. | ||
| func NewRFC9421() filters.Spec { | ||
| return &rfc9421Spec{} |
There was a problem hiding this comment.
spec should get the reference to the secret key and you will need to add a config flag in config/config.go and pass it to skipper.Options and initiate NewRFC9421(secretPath) in ./skipper.go , there are a bunch of similar cases that are done like this.
| return | ||
| } | ||
|
|
||
| signer, err := rfc9421.NewSigner(rfc9421.SignerConfig{ |
There was a problem hiding this comment.
If we have the secret reference this can be created once in NewRFC9421() and passed to the filter instance in CreateFilter() without arguments read from the user.
It will be much more fast and less CPU consumption if we do it like this.
| accesslog.NewEnableAccessLog(), | ||
| auth.NewForwardToken(), | ||
| auth.NewForwardTokenField(), | ||
| auth.NewRFC9421(), |
There was a problem hiding this comment.
this has to be moved to skipper.go
|
|
||
| // signData computes the cryptographic signature over the provided data | ||
| // using the algorithm and private key configured on the Signer. | ||
| func (s *Signer) signData(data []byte) (string, error) { |
There was a problem hiding this comment.
all functions are on "*Signer" so I would say we should move this to to signer.go instead of having a separate file
| } | ||
| } | ||
|
|
||
| params := fmt.Sprintf("(%s);created=%d", strings.Join(compStrings, " "), created.Unix()) |
There was a problem hiding this comment.
params is likely better to be a StringBuilder
|
|
||
| // Signer orchestrates HTTP message signing according to RFC 9421. | ||
| type Signer struct { | ||
| config SignerConfig |
There was a problem hiding this comment.
looks weird to me that we have a SignerConfig. Just move everything to Signer instead.
6e26247 to
5adad57
Compare
|
I've updated the PR to address the feedback:
|
| - Circuit breaker filters | ||
| - [consecutiveBreaker](filters.md#consecutivebreaker) | ||
| - [rateBreaker](filters.md#ratebreaker) | ||
| - [disableBreaker](filters.md#disablebreaker) |
There was a problem hiding this comment.
I think there is a whitespace missing, there is a need for 3x " " in order to make markdown lists a sub-list
| - [bearerinjector](filters.md#bearerinjector) filter, that injects tokens for an app | ||
| - [rfc9421](filters.md#rfc9421) filter, that signs outgoing HTTP requests according to RFC 9421 HTTP Message Signatures using secrets managed by the secrets module | ||
| - The secrets module that does: | ||
| - automated secrets rotation read from files used by the `bearerinjector` filter and `rfc9421` filter |
There was a problem hiding this comment.
here is also the 3rd whitespace missing
|
@shardool-patil thanks for the changes! Can you please revert the egress.md changes that are not your additions? Some of these are breaking markdown and I don't want to see changes that are not part of the feature in this PR. Rest of the changes lgtm. Thanks! |
5adad57 to
57bcf0a
Compare
|
@szuecs i have updated the requested changes so you can take a look. |
|
Do we need to pass the keyfile in the filter? |
|
There is also a linter error detected: Can you add a "doc.go" that has a godoc style documentation for the package? |
The initial design took the
However, I agree that abstracting the file system path away from route authors provides a cleaner interface and aligns better with operator/developer separation. We have two ways:
@szuecs take a look at this, i have fixed the linter failing ci tests and the codeql one is not from the code that i have worked on. |
From what I see from bearerinjector and also oidc filter vs oauthGrant it's not worth the complexity to have the user reference something that they do not know. Therefore I think the best would be to have the file only in the flags and not in the filter. So also drop keyid from the filter input.
staticcheck says you need a godoc for the package: To fix it create rfc/rfc9421/doc.go with content: // Package rfc9421 implements [RFC9421](link to rfc)
package rfc9421 |
57bcf0a to
2ec46b6
Compare
|
I was away for a while, now i have updated the code just take a look @szuecs
|
2ec46b6 to
ad20358
Compare
|
As i was making doc.go a newline was not added which was the cause for the failing ci tests, now that has been fixed, so take a look at this @szuecs |
| } | ||
|
|
||
| if s.keyFile == "" || s.keyID == "" { | ||
| return nil, errors.New("rfc9421: key file and key ID must be configured via flags") |
There was a problem hiding this comment.
fmt.Errorf("your-msg: %w", filters.ErrInvalidFilterParameters)
| } | ||
|
|
||
| var components []string | ||
| for _, part := range strings.Split(componentsStr, ",") { |
There was a problem hiding this comment.
@szuecs both requested changes have been addressed
…o#3952) Signed-off-by: Shardool Patil <shardoolpatil999@gmail.com>
ad20358 to
3726bc1
Compare
|
👍 |
|
@szuecs it looks like |
no worries I take care, retry helps and the problem is known caused by throttled CI env |
|
@szuecs danke schon |
Description
Implements native support for RFC 9421 (HTTP Message Signatures) and adds the
rfc9421egress signing filter.Changes
rfc/rfc9421/):@method,@path,@query,@authority,@scheme, etc.) and HTTP headers.Signature-InputandSignatureheaders.hmac-sha256,ed25519,rsa-pss-sha512,rsa-v1_5-sha256, andecdsa-p256-sha256.filters/auth/rfc9421.go):x-rfc9421-private-keyheader and strips the header before forwarding upstream.filters/builtin/builtin.goand added filter reference documentation todocs/reference/filters.md.Verification
go testpasses acrossrfc/rfc9421,filters/auth, andfilters/builtin.Related Issues
@szuecs I have implemented the code as explained just take a look at it when you get time.