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

fulcio-server -> fulcio-url, pkg/fulcio refactoring #471

Merged
merged 1 commit into from
Jul 22, 2021
Merged
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
22 changes: 12 additions & 10 deletions cmd/cosign/cli/sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ func Sign() *ffcli.Command {
payloadPath = flagset.String("payload", "", "path to a payload file to use rather than generating one.")
force = flagset.Bool("f", false, "skip warnings and confirmations")
recursive = flagset.Bool("r", false, "if a multi-arch image is specified, additionally sign each discrete image")
fulcioURL = flagset.String("fulcio-server", "https://fulcio.sigstore.dev", "[EXPERIMENTAL] address of sigstore PKI server")
fulcioURL = flagset.String("fulcio-url", "https://fulcio.sigstore.dev", "[EXPERIMENTAL] address of sigstore PKI server")
rekorURL = flagset.String("rekor-url", "https://rekor.sigstore.dev", "[EXPERIMENTAL] address of rekor STL server")
idToken = flagset.String("identity-token", "", "[EXPERIMENTAL] identity token to use for certificate from fulcio")
oidcIssuer = flagset.String("oidc-issuer", "https://oauth2.sigstore.dev/auth", "[EXPERIMENTAL] OIDC provider to be used to issue ID token")
Expand Down Expand Up @@ -258,9 +258,8 @@ func SignCmd(ctx context.Context, ko KeyOpts, annotations map[string]interface{}
var rekorBytes []byte
if uploadTLog {
// Upload the cert or the public key, depending on what we have
if sv.Cert != "" {
rekorBytes = []byte(sv.Cert)
} else {
rekorBytes = sv.Cert
if rekorBytes == nil {
pemBytes, err := cosign.PublicKeyPem(sv, options.WithContext(ctx))
if err != nil {
return err
Expand Down Expand Up @@ -398,9 +397,8 @@ func signerFromKeyOpts(ctx context.Context, certPath string, ko KeyOpts) (*certS
if err != nil {
return nil, err
}
cert := string(pemBytes)
return &certSignVerifier{
Cert: cert,
Cert: pemBytes,
SignerVerifier: sv,
}, nil

Expand Down Expand Up @@ -454,12 +452,16 @@ func signerFromKeyOpts(ctx context.Context, certPath string, ko KeyOpts) (*certS
if err != nil {
return nil, errors.Wrap(err, "marshaling certificate to PEM")
}
certSigner.Cert = string(pemBytes)
certSigner.Cert = pemBytes
return certSigner, nil
}
// Default Keyless!
fmt.Fprintln(os.Stderr, "Generating ephemeral keys...")
k, err := fulcio.NewSigner(ctx, ko.IDToken, ko.OIDCIssuer, ko.OIDCClientID, ko.FulcioURL)
fClient, err := fulcio.NewClient(ko.FulcioURL)
if err != nil {
return nil, errors.Wrap(err, "creating Fulcio client")
}
k, err := fulcio.NewSigner(ctx, ko.IDToken, ko.OIDCIssuer, ko.OIDCClientID, fClient)
if err != nil {
return nil, errors.Wrap(err, "getting key from Fulcio")
}
Expand All @@ -471,7 +473,7 @@ func signerFromKeyOpts(ctx context.Context, certPath string, ko KeyOpts) (*certS
}

type certSignVerifier struct {
Cert string
Chain string
Cert []byte
Chain []byte
signature.SignerVerifier
}
8 changes: 3 additions & 5 deletions cmd/cosign/cli/sign_blob.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func SignBlob() *ffcli.Command {
b64 = flagset.Bool("b64", true, "whether to base64 encode the output")
sk = flagset.Bool("sk", false, "whether to use a hardware security key")
slot = flagset.String("slot", "", "security key slot to use for generated key (default: signature) (authentication|signature|card-authentication|key-management)")
fulcioURL = flagset.String("fulcio-server", "https://fulcio.sigstore.dev", "[EXPERIMENTAL] address of sigstore PKI server")
fulcioURL = flagset.String("fulcio-url", "https://fulcio.sigstore.dev", "[EXPERIMENTAL] address of sigstore PKI server")
rekorURL = flagset.String("rekor-url", "https://rekor.sigstore.dev", "[EXPERIMENTAL] address of rekor STL server")
idToken = flagset.String("identity-token", "", "[EXPERIMENTAL] identity token to use for certificate from fulcio")
oidcIssuer = flagset.String("oidc-issuer", "https://oauth2.sigstore.dev/auth", "[EXPERIMENTAL] OIDC provider to be used to issue ID token")
Expand Down Expand Up @@ -146,10 +146,8 @@ func SignBlobCmd(ctx context.Context, ko KeyOpts, payloadPath string, b64 bool,

if EnableExperimental() {
// TODO: Refactor with sign.go
var rekorBytes []byte
if sv.Cert != "" {
rekorBytes = []byte(sv.Cert)
} else {
rekorBytes := sv.Cert
if rekorBytes == nil {
pemBytes, err := cosign.PublicKeyPem(sv, options.WithContext(ctx))
if err != nil {
return nil, err
Expand Down
35 changes: 15 additions & 20 deletions pkg/cosign/fulcio/fulcio.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,22 +68,22 @@ type signingCertProvider interface {
SigningCert(params *operations.SigningCertParams, authInfo runtime.ClientAuthInfoWriter, opts ...operations.ClientOption) (*operations.SigningCertCreated, error)
}

func getCertForOauthID(priv *ecdsa.PrivateKey, scp signingCertProvider, connector oidcConnector, oidcIssuer string, oidcClientID string) (string, string, error) {
func getCertForOauthID(priv *ecdsa.PrivateKey, scp signingCertProvider, connector oidcConnector, oidcIssuer string, oidcClientID string) (certPem, chainPem []byte, err error) {
pubBytes, err := x509.MarshalPKIXPublicKey(&priv.PublicKey)
if err != nil {
return "", "", err
return nil, nil, err
}

tok, err := connector.OIDConnect(oidcIssuer, oidcClientID, "")
if err != nil {
return "", "", err
return nil, nil, err
}

// Sign the email address as part of the request
h := sha256.Sum256([]byte(tok.Subject))
proof, err := ecdsa.SignASN1(rand.Reader, priv, h[:])
if err != nil {
return "", "", err
return nil, nil, err
}

bearerAuth := httptransport.BearerToken(tok.RawString)
Expand All @@ -103,16 +103,16 @@ func getCertForOauthID(priv *ecdsa.PrivateKey, scp signingCertProvider, connecto

resp, err := scp.SigningCert(params, bearerAuth)
if err != nil {
return "", "", err
return nil, nil, err
}

// split the cert and the chain
certBlock, chainPem := pem.Decode([]byte(resp.Payload))
certPem := pem.EncodeToMemory(certBlock)
return string(certPem), string(chainPem), nil
certPem = pem.EncodeToMemory(certBlock)
return certPem, chainPem, nil
}

func getFulcioClient(addr string) (*fulcioClient.Fulcio, error) {
func NewClient(addr string) (*fulcioClient.Fulcio, error) {
url, err := url.Parse(addr)
if err != nil {
return nil, err
Expand All @@ -124,12 +124,7 @@ func getFulcioClient(addr string) (*fulcioClient.Fulcio, error) {
}

// GetCert returns the PEM-encoded signature of the OIDC identity returned as part of an interactive oauth2 flow plus the PEM-encoded cert chain.
func GetCert(ctx context.Context, priv *ecdsa.PrivateKey, idToken, flow string, oidcIssuer string, oidcClientID string, fulcioClient string) (string, string, error) {
fcli, err := getFulcioClient(fulcioClient)
if err != nil {
return "", "", err
}

func GetCert(ctx context.Context, priv *ecdsa.PrivateKey, idToken, flow, oidcIssuer, oidcClientID string, fClient *fulcioClient.Fulcio) (certPemBytes, chainPemBytes []byte, err error) {
c := &realConnector{}
switch flow {
case FlowDevice:
Expand All @@ -140,20 +135,20 @@ func GetCert(ctx context.Context, priv *ecdsa.PrivateKey, idToken, flow string,
case FlowToken:
c.flow = &oauthflow.StaticTokenGetter{RawToken: idToken}
default:
return "", "", fmt.Errorf("unsupported oauth flow: %s", flow)
return nil, nil, fmt.Errorf("unsupported oauth flow: %s", flow)
}

return getCertForOauthID(priv, fcli.Operations, c, oidcIssuer, oidcClientID)
return getCertForOauthID(priv, fClient.Operations, c, oidcIssuer, oidcClientID)
}

type Signer struct {
Cert string
Chain string
Cert []byte
Chain []byte
pub *ecdsa.PublicKey
*signature.ECDSASignerVerifier
}

func NewSigner(ctx context.Context, idToken, oidcIssuer, oidcClientID, fulcioClient string) (*Signer, error) {
func NewSigner(ctx context.Context, idToken, oidcIssuer, oidcClientID string, fClient *fulcioClient.Fulcio) (*Signer, error) {
priv, err := cosign.GeneratePrivateKey()
if err != nil {
return nil, errors.Wrap(err, "generating cert")
Expand All @@ -174,7 +169,7 @@ func NewSigner(ctx context.Context, idToken, oidcIssuer, oidcClientID, fulcioCli
default:
flow = FlowNormal
}
cert, chain, err := GetCert(ctx, priv, idToken, flow, oidcIssuer, oidcClientID, fulcioClient) // TODO, use the chain.
cert, chain, err := GetCert(ctx, priv, idToken, flow, oidcIssuer, oidcClientID, fClient) // TODO, use the chain.
if err != nil {
return nil, errors.Wrap(err, "retrieving cert")
}
Expand Down
10 changes: 6 additions & 4 deletions pkg/cosign/fulcio/fulcio_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,12 +126,14 @@ func TestGetCertForOauthID(t *testing.T) {
}

expectedCert := string(expectedCertBytes)
if cert != expectedCert {
t.Errorf("getCertForOauthID returned cert %q, wanted %q", cert, expectedCert)
actualCert := string(cert)
if actualCert != expectedCert {
t.Errorf("getCertForOauthID returned cert %q, wanted %q", actualCert, expectedCert)
}
expectedChain := string(expectedExtraBytes)
if chain != expectedChain {
t.Errorf("getCertForOauthID returned chain %q, wanted %q", chain, expectedChain)
actualChain := string(chain)
if actualChain != expectedChain {
t.Errorf("getCertForOauthID returned chain %q, wanted %q", actualChain, expectedChain)
}
})
}
Expand Down
10 changes: 5 additions & 5 deletions pkg/cosign/remote/remote.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,8 @@ type Bundle struct {
}

type UploadOpts struct {
Cert string
Chain string
Cert []byte
Chain []byte
DupeDetector signature.Verifier
Bundle *Bundle
AdditionalAnnotations map[string]string
Expand All @@ -169,9 +169,9 @@ func UploadSignature(signature, payload []byte, dst name.Reference, opts UploadO
annotations := map[string]string{
sigkey: base64.StdEncoding.EncodeToString(signature),
}
if opts.Cert != "" {
annotations[certkey] = opts.Cert
annotations[chainkey] = opts.Chain
if opts.Cert != nil {
annotations[certkey] = string(opts.Cert)
annotations[chainkey] = string(opts.Chain)
}
if opts.Bundle != nil {
b, err := swag.WriteJSON(opts.Bundle)
Expand Down