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

Add TrustedRootJSON to TrustRootSpec #1705

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions cmd/tester/trustroot.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/sigstore/policy-controller/pkg/apis/policy/v1alpha1"
"github.com/sigstore/policy-controller/pkg/reconciler/trustroot"
"github.com/sigstore/policy-controller/pkg/tuf"
"github.com/sigstore/sigstore-go/pkg/root"
)

func GetKeysFromTrustRoot(ctx context.Context, tr *v1alpha1.TrustRoot) (*config.SigstoreKeys, error) {
Expand All @@ -43,6 +44,9 @@ func GetKeysFromTrustRoot(ctx context.Context, tr *v1alpha1.TrustRoot) (*config.
return trustroot.GetSigstoreKeysFromTuf(ctx, client, "")
case tr.Spec.SigstoreKeys != nil:
return config.ConvertSigstoreKeys(context.Background(), tr.Spec.SigstoreKeys)

case len(tr.Spec.TrustedRootJSON) > 0:
return root.NewTrustedRootProtobuf([]byte(tr.Spec.TrustedRootJSON))
}
return nil, fmt.Errorf("provided trust root configuration is not supported")
}
3 changes: 3 additions & 0 deletions config/300-trustroot.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ spec:
uri:
description: The URI at which the CA can be accessed.
type: string
trustedRootJSON:
description: TrustedRootJSON contains the serialized trusted_root.json.
type: string
status:
description: Status represents the current state of the TrustRoot. This data may be out of date.
type: object
Expand Down
1 change: 1 addition & 0 deletions docs/api-types/index-v1alpha1.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ TrustRootSpec defines a trusted Root. This is typically either a TUF Root or a b
| remote | Remote specifies initial root of trust & remote mirror. | [Remote](#remote) | false |
| repository | Repository contains the serialized TUF remote repository. | [Repository](#repository) | false |
| sigstoreKeys | SigstoreKeys contains the serialized keys. | [SigstoreKeys](#sigstorekeys) | false |
| trustedRootJSON | TrustedRootJSON contains the serialized trusted_root.json. | string | false |

[Back to TOC](#table-of-contents)

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ require (
github.com/go-jose/go-jose/v4 v4.0.4
github.com/sigstore/protobuf-specs v0.3.2
github.com/sigstore/scaffolding v0.7.11
github.com/sigstore/sigstore-go v0.6.2
github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.10
github.com/sigstore/sigstore/pkg/signature/kms/azure v1.8.10
github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.8.10
Expand Down Expand Up @@ -231,7 +232,6 @@ require (
github.com/sassoftware/relic v7.2.1+incompatible // indirect
github.com/secure-systems-lab/go-securesystemslib v0.8.0 // indirect
github.com/shibumi/go-pathspec v1.3.0 // indirect
github.com/sigstore/sigstore-go v0.6.2 // indirect
github.com/sigstore/timestamp-authority v1.2.2 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
Expand Down
4 changes: 4 additions & 0 deletions pkg/apis/policy/v1alpha1/trustroot_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ type TrustRootSpec struct {
// SigstoreKeys contains the serialized keys.
// +optional
SigstoreKeys *SigstoreKeys `json:"sigstoreKeys,omitempty"`

// TrustedRootJSON contains the serialized trusted_root.json.
// +optional
TrustedRootJSON string `json:"trustedRootJSON,omitempty"`
}

// Remote specifies the TUF with trusted initial root and remote mirror where
Expand Down
19 changes: 12 additions & 7 deletions pkg/apis/policy/v1alpha1/trustroot_validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,27 +41,32 @@ func (tr *TrustRoot) Validate(ctx context.Context) *apis.FieldError {
}

func (spec *TrustRootSpec) Validate(ctx context.Context) (errors *apis.FieldError) {
if spec.Repository == nil && spec.Remote == nil && spec.SigstoreKeys == nil {
return apis.ErrMissingOneOf("repository", "remote", "sigstoreKeys")
if spec.Repository == nil && spec.Remote == nil && spec.SigstoreKeys == nil && len(spec.TrustedRootJSON) == 0 {
return apis.ErrMissingOneOf("repository", "remote", "sigstoreKeys", "trustedRootJSON")
}
if spec.Repository != nil {
if spec.Remote != nil || spec.SigstoreKeys != nil {
return apis.ErrMultipleOneOf("repository", "remote", "sigstoreKeys")
if spec.Remote != nil || spec.SigstoreKeys != nil || len(spec.TrustedRootJSON) > 0 {
return apis.ErrMultipleOneOf("repository", "remote", "sigstoreKeys", "trustedRootJSON")
}
return spec.Repository.Validate(ctx).ViaField("repository")
}
if spec.Remote != nil {
if spec.Repository != nil || spec.SigstoreKeys != nil {
return apis.ErrMultipleOneOf("repository", "remote", "sigstoreKeys")
if spec.Repository != nil || spec.SigstoreKeys != nil || len(spec.TrustedRootJSON) > 0 {
return apis.ErrMultipleOneOf("repository", "remote", "sigstoreKeys", "trustedRootJSON")
}
return spec.Remote.Validate(ctx).ViaField("remote")
}
if spec.SigstoreKeys != nil {
if spec.Remote != nil || spec.Repository != nil {
return apis.ErrMultipleOneOf("repository", "remote", "sigstoreKeys")
return apis.ErrMultipleOneOf("repository", "remote", "sigstoreKeys", "trustedRootJSON")
}
return spec.SigstoreKeys.Validate(ctx).ViaField("sigstoreKeys")
}
if len(spec.TrustedRootJSON) > 0 {
if spec.Remote != nil || spec.Repository != nil || spec.SigstoreKeys != nil {
return apis.ErrMultipleOneOf("repository", "remote", "sigstoreKeys", "trustedRootJSON")
}
}
return
}

Expand Down
8 changes: 8 additions & 0 deletions pkg/reconciler/testing/v1alpha1/trustroot.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,14 @@ func WithRepository(targets string, root, repository []byte, trustedRootTarget s
}
}

// WithTrustedRootJSON constructs a TrustRootOption which sets the
// TrustedRootJSON to the provided value.
func WithTrustedRootJSON(tr string) TrustRootOption {
return func(trustRoot *v1alpha1.TrustRoot) {
trustRoot.Spec.TrustedRootJSON = tr
}
}

func WithInitConditionsTrustRoot(tr *v1alpha1.TrustRoot) {
tr.Status.InitializeConditions()
}
Expand Down
9 changes: 8 additions & 1 deletion pkg/reconciler/trustroot/trustroot.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/sigstore/policy-controller/pkg/reconciler/trustroot/resources"
"github.com/sigstore/policy-controller/pkg/tuf"
pbcommon "github.com/sigstore/protobuf-specs/gen/pb-go/common/v1"
"github.com/sigstore/sigstore-go/pkg/root"
"github.com/sigstore/sigstore/pkg/cryptoutils"
sigstoretuf "github.com/sigstore/sigstore/pkg/tuf"
"github.com/theupdateframework/go-tuf/client"
Expand Down Expand Up @@ -69,9 +70,15 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, trustroot *v1alpha1.Trus
sigstoreKeys, err = r.getSigstoreKeysFromRemote(ctx, trustroot.Spec.Remote)
case trustroot.Spec.SigstoreKeys != nil:
sigstoreKeys, err = config.ConvertSigstoreKeys(ctx, trustroot.Spec.SigstoreKeys)
case len(trustroot.Spec.TrustedRootJSON) > 0:
sigstoreKeys, err = root.NewTrustedRootProtobuf([]byte(trustroot.Spec.TrustedRootJSON))
if err != nil {
err = fmt.Errorf("failed to unmarshal trusted root JSON")
}

default:
// This should not happen since the CRD has been validated.
err = fmt.Errorf("invalid TrustRoot entry: %s missing repository,remote, and sigstoreKeys", trustroot.Name)
err = fmt.Errorf("invalid TrustRoot entry: %s missing repository, remote, sigstoreKeys, and trustedRootJSON", trustroot.Name)
logging.FromContext(ctx).Errorf("Invalid trustroot entry: %s missing repository,remote, and sigstoreKeys", trustroot.Name)
}

Expand Down
51 changes: 51 additions & 0 deletions pkg/reconciler/trustroot/trustroot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,57 @@ func TestReconcile(t *testing.T) {
WithTrustRootFinalizer,
MarkReadyTrustRoot,
)}},
}, {
Name: "With TrustedRootJSON",
Key: testKey,

SkipNamespaceValidation: true, // Cluster scoped
Objects: []runtime.Object{
NewTrustRoot(trName,
WithTrustRootUID(uid),
WithTrustRootResourceVersion(resourceVersion),
WithTrustedRootJSON(marshalledEntry),
WithTrustRootFinalizer,
),
},
WantCreates: []runtime.Object{
makeConfigMapWithMirrorFS(marshalledEntry),
},
WantStatusUpdates: []clientgotesting.UpdateActionImpl{{
Object: NewTrustRoot(trName,
WithTrustRootUID(uid),
WithTrustRootResourceVersion(resourceVersion),
WithTrustedRootJSON(marshalledEntry),
WithTrustRootFinalizer,
MarkReadyTrustRoot,
)}},
}, {
Name: "With invalid TrustedRootJSON",
Key: testKey,

SkipNamespaceValidation: true, // Cluster scoped
Objects: []runtime.Object{
NewTrustRoot(trName,
WithTrustRootUID(uid),
WithTrustRootResourceVersion(resourceVersion),
WithTrustedRootJSON("invalid"),
WithTrustRootFinalizer,
),
},
WantErr: true,
WantEvents: []string{
Eventf(corev1.EventTypeWarning, "InternalError", "failed to unmarshal trusted root JSON"),
},
WantStatusUpdates: []clientgotesting.UpdateActionImpl{{
Object: NewTrustRoot(trName,
WithTrustRootUID(uid),
WithTrustRootResourceVersion(resourceVersion),
WithTrustedRootJSON("invalid"),
WithTrustRootFinalizer,
WithInitConditionsTrustRoot,
WithObservedGenerationTrustRoot(1),
WithMarkInlineKeysFailedTrustRoot("failed to unmarshal trusted root JSON"),
)}},
}}

logger := logtesting.TestLogger(t)
Expand Down
Loading
Loading