Skip to content
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
14 changes: 12 additions & 2 deletions hack/gentestdata/gentestdata.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ import (
"crypto/rand"
"crypto/x509"
"crypto/x509/pkix"
"encoding/hex"
"encoding/pem"
"flag"
"fmt"
"log"
"math/big"
"os"
Expand Down Expand Up @@ -215,14 +217,22 @@ func populateLogIDs(sigstoreKeys *config.SigstoreKeys) error {
if err != nil {
return err
}
sigstoreKeys.Tlogs[i].LogId = &config.LogID{KeyId: []byte(logID)}
logIDBytes, err := hex.DecodeString(logID)
if err != nil {
return fmt.Errorf("failed to decode tlog LogID: %w", err)
}
sigstoreKeys.Tlogs[i].LogId = &config.LogID{KeyId: logIDBytes}
}
for i := range sigstoreKeys.Ctlogs {
logID, err := genLogID(sigstoreKeys.Ctlogs[i].PublicKey.RawBytes)
if err != nil {
return err
}
sigstoreKeys.Ctlogs[i].LogId = &config.LogID{KeyId: []byte(logID)}
logIDBytes, err := hex.DecodeString(logID)
if err != nil {
return fmt.Errorf("failed to decode ctlog LogID: %w", err)
}
sigstoreKeys.Ctlogs[i].LogId = &config.LogID{KeyId: logIDBytes}
}
return nil
}
Expand Down
7 changes: 6 additions & 1 deletion pkg/apis/config/sigstore_keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rsa"
"encoding/hex"
"encoding/pem"
"fmt"

Expand Down Expand Up @@ -166,13 +167,17 @@ func ConvertTransparencyLogInstance(source v1alpha1.TransparencyLogInstance) (*p
if err != nil {
return nil, err
}
logIDBytes, err := hex.DecodeString(logID)
if err != nil {
return nil, fmt.Errorf("failed to decode LogID: %w", err)
}

return &pbtrustroot.TransparencyLogInstance{
BaseUrl: source.BaseURL.String(),
HashAlgorithm: HashStringToHashAlgorithm(source.HashAlgorithm),
PublicKey: pbpk,
LogId: &pbcommon.LogId{
KeyId: []byte(logID),
KeyId: logIDBytes,
},
}, nil
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/reconciler/trustroot/testdata/marshalledEntry.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
}
},
"logId": {
"keyId": "M2E3ZWZjYTk3MGUzMGY2N2U2MTI0MzQ3MzZlMzVkNTRjMDYxZDM4OThlZmY1YjA2Mjc5ZmQ3MjIwNDM4OTY4NQ=="
"keyId": "On78qXDjD2fmEkNHNuNdVMBh04mO/1sGJ5/XIgQ4loU="
}
}
],
Expand Down Expand Up @@ -50,7 +50,7 @@
}
},
"logId": {
"keyId": "ZDc0MGI4ZGQ2NGM5NjE4NTVlODk1M2Y0Mjc2MzY5ZjE4NGQ4MzM3MTZhNmE5OTA4NDRjOTIzYTkwODNkOTI5Ng=="
"keyId": "10C43WTJYYVeiVP0J2Np8YTYM3FqapkIRMkjqQg9kpY="
}
}
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
}
},
"logId": {
"keyId": "M2E3ZWZjYTk3MGUzMGY2N2U2MTI0MzQ3MzZlMzVkNTRjMDYxZDM4OThlZmY1YjA2Mjc5ZmQ3MjIwNDM4OTY4NQ=="
"keyId": "On78qXDjD2fmEkNHNuNdVMBh04mO/1sGJ5/XIgQ4loU="
}
}
],
Expand Down Expand Up @@ -42,7 +42,7 @@
}
},
"logId": {
"keyId": "ZDc0MGI4ZGQ2NGM5NjE4NTVlODk1M2Y0Mjc2MzY5ZjE4NGQ4MzM3MTZhNmE5OTA4NDRjOTIzYTkwODNkOTI5Ng=="
"keyId": "10C43WTJYYVeiVP0J2Np8YTYM3FqapkIRMkjqQg9kpY="
}
}
]
Expand Down
19 changes: 16 additions & 3 deletions pkg/reconciler/trustroot/trustroot.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"context"
"crypto"
"crypto/ecdsa"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
Expand Down Expand Up @@ -95,14 +96,22 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, trustroot *v1alpha1.Trus
if !ok {
return fmt.Errorf("public key %d is not ecdsa.PublicKey", i)
}
sigstoreKeys.Tlogs[i].LogId = &config.LogID{KeyId: []byte(logID)}
logIDBytes, err := hex.DecodeString(logID)
if err != nil {
return fmt.Errorf("invalid rekor log ID encoding %d: %w", i, err)
}
sigstoreKeys.Tlogs[i].LogId = &config.LogID{KeyId: logIDBytes}
}
for i, ctlog := range sigstoreKeys.Ctlogs {
_, logID, err := pemToKeyAndID(config.SerializePublicKey(ctlog.PublicKey))
if err != nil {
return fmt.Errorf("invalid ctlog public key %d: %w", i, err)
}
sigstoreKeys.Ctlogs[i].LogId = &config.LogID{KeyId: []byte(logID)}
logIDBytes, err := hex.DecodeString(logID)
if err != nil {
return fmt.Errorf("invalid ctlog log ID encoding %d: %w", i, err)
}
sigstoreKeys.Ctlogs[i].LogId = &config.LogID{KeyId: logIDBytes}
}

// See if the CM holding configs exists
Expand Down Expand Up @@ -328,10 +337,14 @@ func genTransparencyLogInstance(baseURL string, pkBytes []byte) (*config.Transpa
if err != nil {
return nil, fmt.Errorf("failed to construct LogID: %w", err)
}
logIDBytes, err := hex.DecodeString(logID)
if err != nil {
return nil, fmt.Errorf("failed to decode LogID: %w", err)
}
return &config.TransparencyLogInstance{
BaseUrl: baseURL,
HashAlgorithm: pbcommon.HashAlgorithm_SHA2_256,
PublicKey: pbpk,
LogId: &pbcommon.LogId{KeyId: []byte(logID)},
LogId: &pbcommon.LogId{KeyId: logIDBytes},
}, nil
}
13 changes: 11 additions & 2 deletions pkg/reconciler/trustroot/trustroot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"crypto/x509"
"crypto/x509/pkix"
_ "embed"
"encoding/hex"
"encoding/pem"
"fmt"
"math/big"
Expand Down Expand Up @@ -447,11 +448,19 @@ func makeConfigMapWithSigstoreKeys() *corev1.ConfigMap {
if err != nil {
panic("failed to convert test SigstoreKeys")
}
rekorLogIDBytes, err := hex.DecodeString(rekorLogID)
if err != nil {
panic("failed to decode rekor log ID")
}
for i := range c.Tlogs {
c.Tlogs[i].LogId = &config.LogID{KeyId: []byte(rekorLogID)}
c.Tlogs[i].LogId = &config.LogID{KeyId: rekorLogIDBytes}
}
ctfeLogIDBytes, err := hex.DecodeString(ctfeLogID)
if err != nil {
panic("failed to decode ctfe log ID")
}
for i := range c.Ctlogs {
c.Ctlogs[i].LogId = &config.LogID{KeyId: []byte(ctfeLogID)}
c.Ctlogs[i].LogId = &config.LogID{KeyId: ctfeLogIDBytes}
}
marshalled, err := resources.Marshal(c)
if err != nil {
Expand Down
6 changes: 6 additions & 0 deletions pkg/webhook/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@ func validSignatures(ctx context.Context, ref name.Reference, checkOpts *cosign.
return sigs, err
}

func validBundleSignatures(ctx context.Context, ref name.Reference, checkOpts *cosign.CheckOpts) ([]oci.Signature, error) {
checkOpts.ClaimVerifier = cosign.IntotoSubjectClaimVerifier
sigs, _, err := cosignVerifyAttestations(ctx, ref, checkOpts)
return sigs, err
}

func validAttestations(ctx context.Context, ref name.Reference, checkOpts *cosign.CheckOpts) ([]oci.Signature, error) {
cfg := policycontrollerconfig.FromContextOrDefaults(ctx)
if cfg.EnableOCI11 {
Expand Down
20 changes: 16 additions & 4 deletions pkg/webhook/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -803,7 +803,13 @@ func ValidatePolicySignaturesForAuthority(ctx context.Context, ref name.Referenc

case authority.Keyless != nil:
if authority.Keyless.URL != nil {
sps, err := validSignatures(ctx, ref, checkOpts)
var sps []oci.Signature
var err error
if checkOpts.NewBundleFormat {
sps, err = validBundleSignatures(ctx, ref, checkOpts)
} else {
sps, err = validSignatures(ctx, ref, checkOpts)
}
if err != nil {
logging.FromContext(ctx).Errorf("failed validSignatures for authority %s with fulcio for %s: %v", name, ref.Name(), err)
return nil, fmt.Errorf("signature keyless validation failed for authority %s for %s: %w", name, ref.Name(), err)
Expand All @@ -813,7 +819,13 @@ func ValidatePolicySignaturesForAuthority(ctx context.Context, ref name.Referenc
}
return nil, fmt.Errorf("no Keyless URL specified")
case authority.RFC3161Timestamp != nil:
sps, err := validSignatures(ctx, ref, checkOpts)
var sps []oci.Signature
var err error
if checkOpts.NewBundleFormat {
sps, err = validBundleSignatures(ctx, ref, checkOpts)
} else {
sps, err = validSignatures(ctx, ref, checkOpts)
}
if err != nil {
logging.FromContext(ctx).Errorf("failed validSignatures for authority %s with fulcio for %s: %v", name, ref.Name(), err)
return nil, fmt.Errorf("signature TSA validation failed for authority %s for %s: %w", name, ref.Name(), err)
Expand Down Expand Up @@ -1567,7 +1579,7 @@ func fulcioCertsFromAuthority(ctx context.Context, keylessRef *webhookcip.Keyles
if err != nil {
return nil, nil, nil, fmt.Errorf("unmarshaling public key %d failed: %w", i, err)
}
ctlogKeys.Keys[string(ctlog.LogId.KeyId)] = cosign.TransparencyLogPubKey{
ctlogKeys.Keys[hex.EncodeToString(ctlog.LogId.KeyId)] = cosign.TransparencyLogPubKey{
PubKey: pk,
Status: tuf.Active,
}
Expand Down Expand Up @@ -1659,7 +1671,7 @@ func rekorKeysFromTrustRef(ctx context.Context, trustRootRef string) (*cosign.Tr
if !ok {
return nil, "", fmt.Errorf("public key %d is not ecdsa.PublicKey", i)
}
retKeys.Keys[string(tlog.LogId.KeyId)] = cosign.TransparencyLogPubKey{
retKeys.Keys[hex.EncodeToString(tlog.LogId.KeyId)] = cosign.TransparencyLogPubKey{
PubKey: pkecdsa,
Status: tuf.Active,
}
Expand Down
25 changes: 17 additions & 8 deletions pkg/webhook/validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"crypto/ecdsa"
"crypto/x509"
"encoding/base64"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
Expand Down Expand Up @@ -134,6 +135,14 @@ aEcvjlCkgBCKXbrkumZV0m0dSlK1V1gxEiyQ8y6hk1MxJNe2AZrZUt7a4w==
ctfeLogID = "39d1c085f7d5f3fe7a0de9e52a3ead14186891e52a9269d90de7990a30b55083"
)

func mustHexDecode(s string) []byte {
b, err := hex.DecodeString(s)
if err != nil {
panic(err)
}
return b
}

func TestValidatePodSpec(t *testing.T) {
tag := name.MustParseReference("gcr.io/distroless/static:nonroot")
// Resolved via crane digest on 2021/09/25
Expand Down Expand Up @@ -2998,7 +3007,7 @@ func TestFulcioCertsFromAuthority(t *testing.T) {
CertChain: certChain,
}},
Ctlogs: []*config.TransparencyLogInstance{{
LogId: &config.LogID{KeyId: []byte(ctfeLogID)},
LogId: &config.LogID{KeyId: mustHexDecode(ctfeLogID)},
PublicKey: pbpk,
}},
}
Expand Down Expand Up @@ -3106,7 +3115,7 @@ func TestRekorClientAndKeysFromAuthority(t *testing.T) {
sk := config.SigstoreKeys{
Tlogs: []*config.TransparencyLogInstance{{
PublicKey: pbpk,
LogId: &config.LogID{KeyId: []byte(rekorLogID)},
LogId: &config.LogID{KeyId: mustHexDecode(rekorLogID)},
BaseUrl: "rekor.example.com",
}},
}
Expand Down Expand Up @@ -3249,7 +3258,7 @@ func TestCheckOptsFromAuthority(t *testing.T) {
skRekor := config.SigstoreKeys{
Tlogs: []*config.TransparencyLogInstance{{
PublicKey: pbpkRekor,
LogId: &config.LogID{KeyId: []byte("rekor-logid")},
LogId: &config.LogID{KeyId: mustHexDecode(rekorLogID)},
BaseUrl: "rekor.example.com",
}},
}
Expand All @@ -3266,15 +3275,15 @@ func TestCheckOptsFromAuthority(t *testing.T) {
CertChain: certChainPB,
}},
Ctlogs: []*config.TransparencyLogInstance{{
LogId: &config.LogID{KeyId: []byte(ctfeLogID)},
LogId: &config.LogID{KeyId: mustHexDecode(ctfeLogID)},
PublicKey: pbpkCTFE,
}},
}
skCombined := config.SigstoreKeys{
MediaType: "application/vnd.dev.sigstore.trustedroot+json;version=0.1",
Tlogs: []*config.TransparencyLogInstance{{
PublicKey: pbpkRekor,
LogId: &config.LogID{KeyId: []byte("rekor-logid")},
LogId: &config.LogID{KeyId: mustHexDecode(rekorLogID)},
BaseUrl: "rekor.example.com",
HashAlgorithm: pbcommon.HashAlgorithm_SHA2_256,
}},
Expand All @@ -3286,7 +3295,7 @@ func TestCheckOptsFromAuthority(t *testing.T) {
CertChain: certChainPB,
}},
Ctlogs: []*config.TransparencyLogInstance{{
LogId: &config.LogID{KeyId: []byte(ctfeLogID)},
LogId: &config.LogID{KeyId: mustHexDecode(ctfeLogID)},
PublicKey: pbpkCTFE,
HashAlgorithm: pbcommon.HashAlgorithm_SHA2_256,
}},
Expand Down Expand Up @@ -3349,7 +3358,7 @@ func TestCheckOptsFromAuthority(t *testing.T) {
ctx: testCtx,
wantClient: true,
wantCheckOpts: &cosign.CheckOpts{
RekorPubKeys: &cosign.TrustedTransparencyLogPubKeys{Keys: map[string]cosign.TransparencyLogPubKey{"rekor-logid": {PubKey: ecpk, Status: tuf.Active}}},
RekorPubKeys: &cosign.TrustedTransparencyLogPubKeys{Keys: map[string]cosign.TransparencyLogPubKey{rekorLogID: {PubKey: ecpk, Status: tuf.Active}}},
},
}, {
name: "trustroot found, Fulcio",
Expand Down Expand Up @@ -3382,7 +3391,7 @@ func TestCheckOptsFromAuthority(t *testing.T) {
wantCheckOpts: &cosign.CheckOpts{
RootCerts: roots,
IntermediateCerts: intermediates,
RekorPubKeys: &cosign.TrustedTransparencyLogPubKeys{Keys: map[string]cosign.TransparencyLogPubKey{"rekor-logid": {PubKey: ecpk, Status: tuf.Active}}},
RekorPubKeys: &cosign.TrustedTransparencyLogPubKeys{Keys: map[string]cosign.TransparencyLogPubKey{rekorLogID: {PubKey: ecpk, Status: tuf.Active}}},
Identities: []cosign.Identity{{
Issuer: "issuer",
Subject: "subject",
Expand Down