controllers: factor out GitRepository verification

This commit is contained in:
Hidde Beydals 2020-05-02 21:44:27 +02:00
parent 4f1829914d
commit 48fcc52a3d
1 changed files with 35 additions and 32 deletions

View File

@ -25,6 +25,7 @@ import (
"github.com/blang/semver" "github.com/blang/semver"
"github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/go-git/go-git/v5/plumbing/transport" "github.com/go-git/go-git/v5/plumbing/transport"
"github.com/go-logr/logr" "github.com/go-logr/logr"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
@ -129,6 +130,7 @@ func (r *GitRepositoryReconciler) sync(ctx context.Context, repository sourcev1.
// determine ref // determine ref
refName := plumbing.NewBranchReferenceName(branch) refName := plumbing.NewBranchReferenceName(branch)
if repository.Spec.Reference != nil { if repository.Spec.Reference != nil {
if repository.Spec.Reference.Branch != "" { if repository.Spec.Reference.Branch != "" {
branch = repository.Spec.Reference.Branch branch = repository.Spec.Reference.Branch
@ -280,41 +282,19 @@ func (r *GitRepositoryReconciler) sync(ctx context.Context, repository sourcev1.
return sourcev1.GitRepositoryNotReady(repository, sourcev1.GitOperationFailedReason, err.Error()), err return sourcev1.GitRepositoryNotReady(repository, sourcev1.GitOperationFailedReason, err.Error()), err
} }
commit, err := repo.CommitObject(ref.Hash())
if err != nil {
err = fmt.Errorf("git resolve HEAD error: %w", err)
return sourcev1.GitRepositoryNotReady(repository, sourcev1.GitOperationFailedReason, err.Error()), err
}
// verify PGP signature // verify PGP signature
if repository.Spec.Verification != nil { if repository.Spec.Verification != nil {
commit, err := repo.CommitObject(ref.Hash()) err := r.verify(ctx, types.NamespacedName{
Namespace: repository.Namespace,
Name: repository.Spec.Verification.SecretRef.Name,
}, commit)
if err != nil { if err != nil {
err = fmt.Errorf("git resolve HEAD error: %w", err)
return sourcev1.GitRepositoryNotReady(repository, sourcev1.GitOperationFailedReason, err.Error()), err
}
if commit.PGPSignature == "" {
err = fmt.Errorf("PGP signature not found for commit '%s'", ref.Hash())
return sourcev1.GitRepositoryNotReady(repository, sourcev1.VerificationFailedReason, err.Error()), err
}
name := types.NamespacedName{
Namespace: repository.GetNamespace(),
Name: repository.Spec.Verification.SecretRef.Name,
}
var secret corev1.Secret
err = r.Client.Get(ctx, name, &secret)
if err != nil {
err = fmt.Errorf("PGP public keys secret error: %w", err)
return sourcev1.GitRepositoryNotReady(repository, sourcev1.VerificationFailedReason, err.Error()), err
}
var verified bool
for _, bytes := range secret.Data {
if _, err := commit.Verify(string(bytes)); err == nil {
verified = true
break
}
}
if !verified {
err = fmt.Errorf("PGP signature of '%s' can't be verified", commit.Author)
return sourcev1.GitRepositoryNotReady(repository, sourcev1.VerificationFailedReason, err.Error()), err return sourcev1.GitRepositoryNotReady(repository, sourcev1.VerificationFailedReason, err.Error()), err
} }
} }
@ -388,6 +368,29 @@ func (r *GitRepositoryReconciler) shouldResetStatus(repository sourcev1.GitRepos
} }
} }
func (r *GitRepositoryReconciler) verify(ctx context.Context, publicKeySecret types.NamespacedName, commit *object.Commit) error {
if commit.PGPSignature == "" {
return fmt.Errorf("no PGP signature found for commit: %s", commit.Hash)
}
var secret corev1.Secret
if err := r.Client.Get(ctx, publicKeySecret, &secret); err != nil {
return fmt.Errorf("PGP public keys secret error: %w", err)
}
var verified bool
for _, bytes := range secret.Data {
if _, err := commit.Verify(string(bytes)); err == nil {
verified = true
break
}
}
if !verified {
return fmt.Errorf("PGP signature '%s' of '%s' can't be verified", commit.PGPSignature, commit.Author)
}
return nil
}
// gc performs a garbage collection on all but current artifacts of // gc performs a garbage collection on all but current artifacts of
// the given repository. // the given repository.
func (r *GitRepositoryReconciler) gc(repository sourcev1.GitRepository) error { func (r *GitRepositoryReconciler) gc(repository sourcev1.GitRepository) error {