Add support for verifying helm charts using provenance file#605
Add support for verifying helm charts using provenance file#605aryan9600 wants to merge 10 commits intofluxcd:mainfrom
Conversation
internal/helm/chart/builder_local.go
Outdated
| } | ||
| } | ||
| return nil | ||
| } |
There was a problem hiding this comment.
Maybe it'd be better to move this as an independent function. The only thing it's using from the surrounding is the keyring, which can just be passed as another function argument.
f3b4a81 to
903d29b
Compare
controllers/helmchart_controller.go
Outdated
| }, | ||
| } | ||
|
|
||
| const KeyringFileName = "pubring.gpg" |
There was a problem hiding this comment.
This does not appear to be actively used (and can be omitted in any case due to the API setting a default).
| // Deal with the underlying byte slice to avoid having to read the buffer multiple times. | ||
| chartBuf := res.Bytes() |
There was a problem hiding this comment.
Better to deal with err first and only then load the bytes.
| properties: | ||
| key: | ||
| default: pubring.gpg | ||
| description: The key that corresponds to the keyring value. |
There was a problem hiding this comment.
Looks like old definition.
Running make generate, make manifests and make api-docs seems to result in updates to these and a few other files.
|
|
||
| type VerificationKeyring struct { | ||
| // +required | ||
| SecretRef meta.LocalObjectReference `json:"secretRef,omitempty"` |
There was a problem hiding this comment.
SecretRef and VerificationKeyring can have some description for documentation purposes.
controllers/helmchart_controller.go
Outdated
| Err: fmt.Errorf("failed to get public key for chart signature verification: %w", err), | ||
| Reason: sourcev1.AuthenticationFailedReason, | ||
| } | ||
| conditions.MarkFalse(obj, sourcev1.SourceVerifiedCondition, e.Reason, e.Error()) |
There was a problem hiding this comment.
| conditions.MarkFalse(obj, sourcev1.SourceVerifiedCondition, e.Reason, e.Error()) | |
| conditions.MarkFalse(obj, sourcev1.SourceVerifiedCondition, e.Reason, e.Err.Error()) |
We've been doing it this way in other places with an undocumented agreement that e is an error Event, which just internally calls e.Err.Error() for now, but if the event error string changes in the future, it'd affect the condition message value too.
Event error may not be equal to just the underlying error in the future.
controllers/helmchart_controller.go
Outdated
| if err != nil { | ||
| e := &serror.Event{ | ||
| Err: fmt.Errorf("failed to get public key for chart signature verification: %w", err), | ||
| Reason: sourcev1.AuthenticationFailedReason, |
There was a problem hiding this comment.
This reason doesn't quite fit here. It's not an authentication failure, but we couldn't verify because we couldn't get the material needed to perform the verification.
GitRepository reconciler uses VerificationError as the reason, which sounds more accurate. Let's create a new reason constant for it and use the same.
There was a problem hiding this comment.
The doc of AuthentiactionFailedReason, states that :
AuthenticationFailedReason signals that a Secret does not have the required fields, or the provided credentials do not match.
This seems like the appropriate reason to have here, because getProvenanceKeyring returns an error only when it can't find a secret or the secret doesn't have the required key.
There was a problem hiding this comment.
Yes, but only if the Secret is related to authentication, which provenance isn't.
controllers/helmchart_controller.go
Outdated
| // Build the chart | ||
| ref := chart.RemoteReference{Name: obj.Spec.Chart, Version: obj.Spec.Version} | ||
| build, err := cb.Build(ctx, ref, util.TempPathForObj("", ".tgz", obj), opts) | ||
|
|
There was a problem hiding this comment.
don't think this line break is intentional?
internal/helm/chart/builder.go
Outdated
| // because the list of ValuesFiles has changed. | ||
| Force bool | ||
|
|
||
| // Keyring can be configured with the bytes of a public kering in legacy |
There was a problem hiding this comment.
| // Keyring can be configured with the bytes of a public kering in legacy | |
| // Keyring can be set to the bytes of a public keyring in legacy |
Maybe more consistent with the other descriptions above it?
internal/helm/chart/builder.go
Outdated
| // Can be empty, in which case a failure should be assumed. | ||
| Path string | ||
| // ProvFilePath is the absolute path to a provenance file. | ||
| // Can be empty, in which case it should be assumed that the packaged |
There was a problem hiding this comment.
| // Can be empty, in which case it should be assumed that the packaged | |
| // It can be empty, in which case it should be assumed that the packaged |
internal/helm/chart/builder.go
Outdated
| // chart is not verified. | ||
| ProvFilePath string | ||
| // VerificationSignature is populated when a chart's signature | ||
| // is successfully verified using it's provenance file. |
There was a problem hiding this comment.
| // is successfully verified using it's provenance file. | |
| // is successfully verified using its provenance file. |
internal/helm/chart/builder_local.go
Outdated
| } | ||
| } | ||
| return nil | ||
| } |
| @@ -0,0 +1,91 @@ | |||
| /* | |||
| Copyright 2021 The Flux authors | |||
There was a problem hiding this comment.
| Copyright 2021 The Flux authors | |
| Copyright 2022 The Flux authors |
internal/util/file.go
Outdated
| "path/filepath" | ||
| ) | ||
|
|
||
| func writeBytesToFile(bytes []byte, out string, temp bool) (*os.File, error) { |
There was a problem hiding this comment.
Now that you've two wrapper functions below, how about creating the file in the wrapper functions and don't need to pass a temp variable to this function, pass it os.File that you can just write directly to. Since the wrapper function created the file, it already has the os.File, this function can just return an error.
17d6668 to
c3e0c81
Compare
controllers/helmchart_controller.go
Outdated
| var sigVerMsg strings.Builder | ||
| sigVerMsg.WriteString(fmt.Sprintf("chart signed by: '%v'", strings.Join(build.VerificationSignature.Identities[:], ","))) | ||
| sigVerMsg.WriteString(fmt.Sprintf(" using key with fingeprint: '%X'", build.VerificationSignature.KeyFingerprint)) | ||
| sigVerMsg.WriteString(fmt.Sprintf(" and hash verified: '%s'", build.VerificationSignature.FileHash)) |
There was a problem hiding this comment.
| sigVerMsg.WriteString(fmt.Sprintf(" and hash verified: '%s'", build.VerificationSignature.FileHash)) | |
| sigVerMsg.WriteString(fmt.Sprintf(" and hash verified: %q", build.VerificationSignature.FileHash)) |
There was a problem hiding this comment.
I think it makes more sense to be consistent, since we are using %s instead of %q in a lot of other places.
There was a problem hiding this comment.
We don't use %q because it borks the json we used for logging.
| if err := testStorage.AtomicWriteFile(obj.Status.Artifact, strings.NewReader(v), 0644); err != nil { | ||
| return err | ||
| } | ||
| if err := testStorage.AtomicWriteFile(provArtifact, strings.NewReader(v), 0644); err != nil { |
There was a problem hiding this comment.
Let's use octal format for representing os-level octal values:
| if err := testStorage.AtomicWriteFile(provArtifact, strings.NewReader(v), 0644); err != nil { | |
| if err := testStorage.AtomicWriteFile(provArtifact, strings.NewReader(v), 0o644); err != nil { |
There was a problem hiding this comment.
Rather than making a couple of changes in this PR, I think this change should be addressed overall in the PR regarding #603
There was a problem hiding this comment.
I do agree on this for existing code, but this line specifically is a new introduction.
c252e68 to
94abac5
Compare
Signed-off-by: Sanskar Jaiswal <[email protected]>
Signed-off-by: Sanskar Jaiswal <[email protected]>
Signed-off-by: Sanskar Jaiswal <[email protected]>
Signed-off-by: Sanskar Jaiswal <[email protected]>
Signed-off-by: Sanskar Jaiswal <[email protected]>
Signed-off-by: Sanskar Jaiswal <[email protected]>
Signed-off-by: Sanskar Jaiswal <[email protected]>
Signed-off-by: Sanskar Jaiswal <[email protected]>
Signed-off-by: Sanskar Jaiswal <[email protected]>
Signed-off-by: Sanskar Jaiswal <[email protected]>
94abac5 to
fcd34a8
Compare
|
Converting PR to draft, as this is being put on hold until we reach GA (ref: fluxcd/flux2#2592) |
Ref: #541