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

Consume identity.Principal in CA abstraction #570

Merged
merged 1 commit into from
May 12, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions pkg/api/grpc_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ func (g *grpcCAServer) CreateSigningCertificate(ctx context.Context, request *fu
// For CAs that do not support embedded SCTs or if the CT log is not configured
if sctCa, ok := g.ca.(certauth.EmbeddedSCTCA); !ok || g.ct == nil {
// currently configured CA doesn't support pre-certificate flow required to embed SCT in final certificate
csc, err = g.ca.CreateCertificate(ctx, subject)
csc, err = g.ca.CreateCertificate(ctx, subject, publicKey)
nsmith5 marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
// if the error was due to invalid input in the request, return HTTP 400
if _, ok := err.(certauth.ValidationError); ok {
Expand Down Expand Up @@ -165,7 +165,7 @@ func (g *grpcCAServer) CreateSigningCertificate(ctx context.Context, request *fu
result.GetSignedCertificateDetachedSct().SignedCertificateTimestamp = sctBytes
}
} else {
precert, err := sctCa.CreatePrecertificate(ctx, subject)
precert, err := sctCa.CreatePrecertificate(ctx, subject, publicKey)
if err != nil {
// if the error was due to invalid input in the request, return HTTP 400
if _, ok := err.(certauth.ValidationError); ok {
Expand Down
5 changes: 3 additions & 2 deletions pkg/api/grpc_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package api

import (
"context"
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
Expand All @@ -42,9 +43,9 @@ import (
"github.com/google/certificate-transparency-go/jsonclient"
"github.com/sigstore/fulcio/pkg/ca"
"github.com/sigstore/fulcio/pkg/ca/ephemeralca"
"github.com/sigstore/fulcio/pkg/challenges"
"github.com/sigstore/fulcio/pkg/config"
"github.com/sigstore/fulcio/pkg/generated/protobuf"
"github.com/sigstore/fulcio/pkg/identity"
"github.com/sigstore/sigstore/pkg/cryptoutils"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
Expand Down Expand Up @@ -1250,7 +1251,7 @@ func verifyResponse(resp *protobuf.SigningCertificate, eca *ephemeralca.Ephemera
type FailingCertificateAuthority struct {
}

func (fca *FailingCertificateAuthority) CreateCertificate(ctx context.Context, challenge *challenges.ChallengeResult) (*ca.CodeSigningCertificate, error) {
func (fca *FailingCertificateAuthority) CreateCertificate(context.Context, identity.Principal, crypto.PublicKey) (*ca.CodeSigningCertificate, error) {
return nil, errors.New("CreateCertificate always fails for testing")
}
func (fca *FailingCertificateAuthority) Root(ctx context.Context) ([]byte, error) {
Expand Down
5 changes: 3 additions & 2 deletions pkg/ca/ca.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@ package ca

import (
"context"
"crypto"

"github.com/sigstore/fulcio/pkg/challenges"
"github.com/sigstore/fulcio/pkg/identity"
)

// CertificateAuthority implements certificate creation with a detached SCT and
// fetching the CA trust bundle.
type CertificateAuthority interface {
CreateCertificate(ctx context.Context, challenge *challenges.ChallengeResult) (*CodeSigningCertificate, error)
CreateCertificate(context.Context, identity.Principal, crypto.PublicKey) (*CodeSigningCertificate, error)
Root(ctx context.Context) ([]byte, error)
}
5 changes: 3 additions & 2 deletions pkg/ca/embeddedca.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@ package ca

import (
"context"
"crypto"

ct "github.com/google/certificate-transparency-go"
"github.com/sigstore/fulcio/pkg/challenges"
"github.com/sigstore/fulcio/pkg/identity"
)

// EmbeddedSCTCA implements precertificate and certificate issuance. Certificates will contain an embedded SCT.
type EmbeddedSCTCA interface {
CreatePrecertificate(ctx context.Context, challenge *challenges.ChallengeResult) (*CodeSigningPreCertificate, error)
CreatePrecertificate(context.Context, identity.Principal, crypto.PublicKey) (*CodeSigningPreCertificate, error)
IssueFinalCertificate(ctx context.Context, precert *CodeSigningPreCertificate, sct *ct.SignedCertificateTimestamp) (*CodeSigningCertificate, error)
}
9 changes: 5 additions & 4 deletions pkg/ca/googleca/v1/googleca.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package v1

import (
"context"
"crypto"
"crypto/ecdsa"
"crypto/rsa"
"crypto/x509"
Expand All @@ -30,7 +31,7 @@ import (
privateca "cloud.google.com/go/security/privateca/apiv1"
"github.com/sigstore/fulcio/pkg/ca"
"github.com/sigstore/fulcio/pkg/ca/x509ca"
"github.com/sigstore/fulcio/pkg/challenges"
"github.com/sigstore/fulcio/pkg/identity"
"github.com/sigstore/sigstore/pkg/cryptoutils"
"google.golang.org/api/iterator"
privatecapb "google.golang.org/genproto/googleapis/cloud/security/privateca/v1"
Expand Down Expand Up @@ -160,13 +161,13 @@ func (c *CertAuthorityService) Root(ctx context.Context) ([]byte, error) {
return c.cachedRoots, nil
}

func (c *CertAuthorityService) CreateCertificate(ctx context.Context, subj *challenges.ChallengeResult) (*ca.CodeSigningCertificate, error) {
cert, err := x509ca.MakeX509(subj)
func (c *CertAuthorityService) CreateCertificate(ctx context.Context, principal identity.Principal, publicKey crypto.PublicKey) (*ca.CodeSigningCertificate, error) {
cert, err := x509ca.MakeX509(ctx, principal, publicKey)
if err != nil {
return nil, ca.ValidationError(err)
}

pubKeyBytes, err := cryptoutils.MarshalPublicKeyToPEM(subj.PublicKey)
pubKeyBytes, err := cryptoutils.MarshalPublicKeyToPEM(publicKey)
if err != nil {
return nil, ca.ValidationError(err)
}
Expand Down
14 changes: 7 additions & 7 deletions pkg/ca/intermediateca/intermediateca.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import (
ctx509 "github.com/google/certificate-transparency-go/x509"
"github.com/sigstore/fulcio/pkg/ca"
"github.com/sigstore/fulcio/pkg/ca/x509ca"
"github.com/sigstore/fulcio/pkg/challenges"
"github.com/sigstore/fulcio/pkg/identity"
"github.com/sigstore/sigstore/pkg/cryptoutils"
)

Expand All @@ -49,8 +49,8 @@ type IntermediateCA struct {
Signer crypto.Signer
}

func (ica *IntermediateCA) CreatePrecertificate(ctx context.Context, challenge *challenges.ChallengeResult) (*ca.CodeSigningPreCertificate, error) {
cert, err := x509ca.MakeX509(challenge)
func (ica *IntermediateCA) CreatePrecertificate(ctx context.Context, principal identity.Principal, publicKey crypto.PublicKey) (*ca.CodeSigningPreCertificate, error) {
cert, err := x509ca.MakeX509(ctx, principal, publicKey)
if err != nil {
return nil, err
}
Expand All @@ -64,7 +64,7 @@ func (ica *IntermediateCA) CreatePrecertificate(ctx context.Context, challenge *
Value: asn1.NullBytes,
})

finalCertBytes, err := x509.CreateCertificate(rand.Reader, cert, certChain[0], challenge.PublicKey, privateKey)
finalCertBytes, err := x509.CreateCertificate(rand.Reader, cert, certChain[0], publicKey, privateKey)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -130,15 +130,15 @@ func (ica *IntermediateCA) IssueFinalCertificate(ctx context.Context, precert *c
return ca.CreateCSCFromDER(finalCertBytes, precert.CertChain)
}

func (ica *IntermediateCA) CreateCertificate(ctx context.Context, challenge *challenges.ChallengeResult) (*ca.CodeSigningCertificate, error) {
cert, err := x509ca.MakeX509(challenge)
func (ica *IntermediateCA) CreateCertificate(ctx context.Context, principal identity.Principal, publicKey crypto.PublicKey) (*ca.CodeSigningCertificate, error) {
cert, err := x509ca.MakeX509(ctx, principal, publicKey)
if err != nil {
return nil, err
}

certChain, privateKey := ica.getX509KeyPair()

finalCertBytes, err := x509.CreateCertificate(rand.Reader, cert, certChain[0], challenge.PublicKey, privateKey)
finalCertBytes, err := x509.CreateCertificate(rand.Reader, cert, certChain[0], publicKey, privateKey)
if err != nil {
return nil, err
}
Expand Down
9 changes: 4 additions & 5 deletions pkg/ca/intermediateca/intermediateca_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,11 +165,10 @@ func TestCreatePrecertificateAndIssueFinalCertificate(t *testing.T) {

ica := IntermediateCA{Certs: certChain, Signer: subKey}
precsc, err := ica.CreatePrecertificate(context.TODO(), &challenges.ChallengeResult{
Issuer: "iss",
TypeVal: challenges.EmailValue,
Value: "foo@example.com",
PublicKey: priv.Public(),
})
Issuer: "iss",
TypeVal: challenges.EmailValue,
Value: "foo@example.com",
}, priv.Public())

if err != nil {
t.Fatalf("error generating precertificate: %v", err)
Expand Down
76 changes: 8 additions & 68 deletions pkg/ca/x509ca/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,10 @@ import (
"crypto/rand"
"crypto/x509"
"encoding/pem"
"net/url"
"time"

"github.com/pkg/errors"
"github.com/sigstore/fulcio/pkg/ca"
"github.com/sigstore/fulcio/pkg/challenges"
"github.com/sigstore/fulcio/pkg/identity"
"github.com/sigstore/sigstore/pkg/cryptoutils"
)

Expand All @@ -35,13 +33,13 @@ type X509CA struct {
PrivKey crypto.Signer
}

func MakeX509(subject *challenges.ChallengeResult) (*x509.Certificate, error) {
func MakeX509(ctx context.Context, principal identity.Principal, publicKey crypto.PublicKey) (*x509.Certificate, error) {
serialNumber, err := cryptoutils.GenerateSerialNumber()
if err != nil {
return nil, err
}

skid, err := cryptoutils.SKID(subject.PublicKey)
skid, err := cryptoutils.SKID(publicKey)
if err != nil {
return nil, err
}
Expand All @@ -55,67 +53,9 @@ func MakeX509(subject *challenges.ChallengeResult) (*x509.Certificate, error) {
KeyUsage: x509.KeyUsageDigitalSignature,
}

switch subject.TypeVal {
case challenges.EmailValue:
cert.EmailAddresses = []string{subject.Value}
case challenges.SpiffeValue:
challengeURL, err := url.Parse(subject.Value)
if err != nil {
return nil, ca.ValidationError(err)
}
cert.URIs = []*url.URL{challengeURL}
case challenges.GithubWorkflowValue:
jobWorkflowURI, err := url.Parse(subject.Value)
if err != nil {
return nil, ca.ValidationError(err)
}
cert.URIs = []*url.URL{jobWorkflowURI}
case challenges.KubernetesValue:
k8sURI, err := url.Parse(subject.Value)
if err != nil {
return nil, ca.ValidationError(err)
}
cert.URIs = []*url.URL{k8sURI}
case challenges.URIValue:
subjectURI, err := url.Parse(subject.Value)
if err != nil {
return nil, ca.ValidationError(err)
}
cert.URIs = []*url.URL{subjectURI}
case challenges.UsernameValue:
cert.EmailAddresses = []string{subject.Value}
}

exts := Extensions{
Issuer: subject.Issuer,
}
if subject.TypeVal == challenges.GithubWorkflowValue {
var ok bool
exts.GithubWorkflowTrigger, ok = subject.AdditionalInfo[challenges.GithubWorkflowTrigger]
if !ok {
return nil, errors.New("x509ca: github workflow missing trigger claim")
}
exts.GithubWorkflowSHA, ok = subject.AdditionalInfo[challenges.GithubWorkflowSha]
if !ok {
return nil, errors.New("x509ca: github workflow missing SHA claim")
}
exts.GithubWorkflowName, ok = subject.AdditionalInfo[challenges.GithubWorkflowName]
if !ok {
return nil, errors.New("x509ca: github workflow missing workflow name claim")
}
exts.GithubWorkflowRepository, ok = subject.AdditionalInfo[challenges.GithubWorkflowRepository]
if !ok {
return nil, errors.New("x509ca: github workflow missing repository claim")
}
exts.GithubWorkflowRef, ok = subject.AdditionalInfo[challenges.GithubWorkflowRef]
if !ok {
return nil, errors.New("x509ca: github workflow missing ref claim")
}
}

cert.ExtraExtensions, err = exts.Render()
err = principal.Embed(ctx, cert)
if err != nil {
return nil, err
return nil, ca.ValidationError(err)
}

return cert, nil
Expand All @@ -128,13 +68,13 @@ func (x *X509CA) Root(ctx context.Context) ([]byte, error) {
}), nil
}

func (x *X509CA) CreateCertificate(_ context.Context, subject *challenges.ChallengeResult) (*ca.CodeSigningCertificate, error) {
cert, err := MakeX509(subject)
func (x *X509CA) CreateCertificate(ctx context.Context, principal identity.Principal, publicKey crypto.PublicKey) (*ca.CodeSigningCertificate, error) {
cert, err := MakeX509(ctx, principal, publicKey)
if err != nil {
return nil, err
}

finalCertBytes, err := x509.CreateCertificate(rand.Reader, cert, x.RootCA, subject.PublicKey, x.PrivKey)
finalCertBytes, err := x509.CreateCertificate(rand.Reader, cert, x.RootCA, publicKey, x.PrivKey)
if err != nil {
return nil, err
}
Expand Down