From 88db463a371070a61462105141c96025ebd45fd5 Mon Sep 17 00:00:00 2001 From: Matt Moore Date: Wed, 8 Sep 2021 11:32:58 -0700 Subject: [PATCH] Break off a `fulcioroot` package. The `cosigned` webhook pulls in the Fulcio roots, and runs as a K8s controller, which consumes `klog`. However, some of the certificate transparency stuff the Fulcio package pulls in consumes `glog`. These both define conflicting `-log_dir` flags, which cause `cosigned` to crash on startup. With this change, `cosigned` can use `fulcioroots.Get` to load the roots without pulling in `glog`. In a subsequent change, I have tests that should catch this before a breaking change merges. Signed-off-by: Matt Moore --- cmd/cosign/cli/fulcio/fulcio.go | 55 +----------- .../cli/fulcio/{ => fulcioroots}/fulcio.pem | 0 .../cli/fulcio/fulcioroots/fulcioroots.go | 86 +++++++++++++++++++ pkg/cosign/kubernetes/webhook/validation.go | 4 +- 4 files changed, 90 insertions(+), 55 deletions(-) rename cmd/cosign/cli/fulcio/{ => fulcioroots}/fulcio.pem (100%) create mode 100644 cmd/cosign/cli/fulcio/fulcioroots/fulcioroots.go diff --git a/cmd/cosign/cli/fulcio/fulcio.go b/cmd/cosign/cli/fulcio/fulcio.go index 978c44ec417..ebff806c01d 100644 --- a/cmd/cosign/cli/fulcio/fulcio.go +++ b/cmd/cosign/cli/fulcio/fulcio.go @@ -16,7 +16,6 @@ package fulcio import ( - "bytes" "context" "crypto" "crypto/ecdsa" @@ -28,10 +27,7 @@ import ( "encoding/json" "encoding/pem" "fmt" - "io/ioutil" "os" - "strings" - "sync" "github.com/go-openapi/runtime" httptransport "github.com/go-openapi/runtime/client" @@ -43,8 +39,8 @@ import ( "github.com/pkg/errors" "golang.org/x/term" + "github.com/sigstore/cosign/cmd/cosign/cli/fulcio/fulcioroots" "github.com/sigstore/cosign/pkg/cosign" - "github.com/sigstore/cosign/pkg/cosign/tuf" fulcioClient "github.com/sigstore/fulcio/pkg/generated/client" "github.com/sigstore/fulcio/pkg/generated/client/operations" "github.com/sigstore/fulcio/pkg/generated/models" @@ -56,7 +52,6 @@ const ( FlowNormal = "normal" FlowDevice = "device" FlowToken = "token" - altRoot = "SIGSTORE_ROOT_FILE" ) type Resp struct { @@ -65,14 +60,9 @@ type Resp struct { SCT []byte } -// This is the root in the fulcio project. -//go:embed fulcio.pem -var rootPem string - // This is the CT log public key //go:embed ctfe.pub var ctPublicKey string -var fulcioTargetStr = `fulcio.crt.pem` var ( // For testing @@ -242,47 +232,6 @@ func (f *Signer) PublicKey(opts ...signature.PublicKeyOption) (crypto.PublicKey, var _ signature.Signer = &Signer{} -var ( - rootsOnce sync.Once - roots *x509.CertPool -) - func GetRoots() *x509.CertPool { - rootsOnce.Do(func() { - roots = initRoots() - }) - return roots -} - -func initRoots() *x509.CertPool { - cp := x509.NewCertPool() - rootEnv := os.Getenv(altRoot) - if rootEnv != "" { - raw, err := ioutil.ReadFile(rootEnv) - if err != nil { - panic(fmt.Sprintf("error reading root PEM file: %s", err)) - } - if !cp.AppendCertsFromPEM(raw) { - panic("error creating root cert pool") - } - } else { - // First try retrieving from TUF root. Otherwise use rootPem. - ctx := context.Background() // TODO: pass in context? - buf := tuf.ByteDestination{Buffer: &bytes.Buffer{}} - err := tuf.GetTarget(ctx, fulcioTargetStr, &buf) - if err != nil { - // The user may not have initialized the local root metadata. Log the error and use the embedded root. - fmt.Fprintln(os.Stderr, "No TUF root installed, using embedded CA certificate.") - if !cp.AppendCertsFromPEM([]byte(rootPem)) { - panic("error creating root cert pool") - } - } else { - // TODO: Remove the string replace when SigStore root is updated. - replaced := strings.ReplaceAll(buf.String(), "\n ", "\n") - if !cp.AppendCertsFromPEM([]byte(replaced)) { - panic("error creating root cert pool") - } - } - } - return cp + return fulcioroots.Get() } diff --git a/cmd/cosign/cli/fulcio/fulcio.pem b/cmd/cosign/cli/fulcio/fulcioroots/fulcio.pem similarity index 100% rename from cmd/cosign/cli/fulcio/fulcio.pem rename to cmd/cosign/cli/fulcio/fulcioroots/fulcio.pem diff --git a/cmd/cosign/cli/fulcio/fulcioroots/fulcioroots.go b/cmd/cosign/cli/fulcio/fulcioroots/fulcioroots.go new file mode 100644 index 00000000000..f3b1ae2e31a --- /dev/null +++ b/cmd/cosign/cli/fulcio/fulcioroots/fulcioroots.go @@ -0,0 +1,86 @@ +// +// Copyright 2021 The Sigstore Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package fulcioroots + +import ( + "bytes" + "context" + "crypto/x509" + "fmt" + "io/ioutil" + "os" + "strings" + "sync" + + _ "embed" // To enable the `go:embed` directive. + + "github.com/sigstore/cosign/pkg/cosign/tuf" +) + +var ( + rootsOnce sync.Once + roots *x509.CertPool +) + +// This is the root in the fulcio project. +//go:embed fulcio.pem +var rootPem string + +var fulcioTargetStr = `fulcio.crt.pem` + +const ( + altRoot = "SIGSTORE_ROOT_FILE" +) + +func Get() *x509.CertPool { + rootsOnce.Do(func() { + roots = initRoots() + }) + return roots +} + +func initRoots() *x509.CertPool { + cp := x509.NewCertPool() + rootEnv := os.Getenv(altRoot) + if rootEnv != "" { + raw, err := ioutil.ReadFile(rootEnv) + if err != nil { + panic(fmt.Sprintf("error reading root PEM file: %s", err)) + } + if !cp.AppendCertsFromPEM(raw) { + panic("error creating root cert pool") + } + } else { + // First try retrieving from TUF root. Otherwise use rootPem. + ctx := context.Background() // TODO: pass in context? + buf := tuf.ByteDestination{Buffer: &bytes.Buffer{}} + err := tuf.GetTarget(ctx, fulcioTargetStr, &buf) + if err != nil { + // The user may not have initialized the local root metadata. Log the error and use the embedded root. + fmt.Fprintln(os.Stderr, "No TUF root installed, using embedded CA certificate.") + if !cp.AppendCertsFromPEM([]byte(rootPem)) { + panic("error creating root cert pool") + } + } else { + // TODO: Remove the string replace when SigStore root is updated. + replaced := strings.ReplaceAll(buf.String(), "\n ", "\n") + if !cp.AppendCertsFromPEM([]byte(replaced)) { + panic("error creating root cert pool") + } + } + } + return cp +} diff --git a/pkg/cosign/kubernetes/webhook/validation.go b/pkg/cosign/kubernetes/webhook/validation.go index d493f0b3c5b..c185dad874e 100644 --- a/pkg/cosign/kubernetes/webhook/validation.go +++ b/pkg/cosign/kubernetes/webhook/validation.go @@ -24,7 +24,7 @@ import ( "fmt" "github.com/google/go-containerregistry/pkg/name" - "github.com/sigstore/cosign/cmd/cosign/cli/fulcio" + "github.com/sigstore/cosign/cmd/cosign/cli/fulcio/fulcioroots" "github.com/sigstore/cosign/pkg/cosign" "github.com/sigstore/sigstore/pkg/signature" appsv1 "k8s.io/api/apps/v1" @@ -129,7 +129,7 @@ func validSignatures(ctx context.Context, img string, key *ecdsa.PublicKey) ([]c } return cosign.Verify(ctx, ref, &cosign.CheckOpts{ - RootCerts: fulcio.GetRoots(), + RootCerts: fulcioroots.Get(), SigVerifier: ecdsaVerifier, ClaimVerifier: cosign.SimpleClaimVerifier, })