diff --git a/pkg/api/grpc_server.go b/pkg/api/grpc_server.go index 9a91d82f2..d6e1cd0d1 100644 --- a/pkg/api/grpc_server.go +++ b/pkg/api/grpc_server.go @@ -70,7 +70,15 @@ func (g *grpcCAServer) CreateSigningCertificate(ctx context.Context, request *fu } } - principal, err := authorize(ctx, token) + // Authenticate OIDC ID token by checking signature + idtoken, err := authorize(ctx, token) + if err != nil { + return nil, handleFulcioGRPCError(ctx, codes.Unauthenticated, err, invalidCredentials) + } + // Parse authenticated ID token into principal + // TODO:(nsmith5) replace this and authorize call above with + // just identity.IssuerPool.Authenticate() + principal, err := challenges.PrincipalFromIDToken(ctx, idtoken) if err != nil { return nil, handleFulcioGRPCError(ctx, codes.Unauthenticated, err, invalidCredentials) } @@ -103,10 +111,16 @@ func (g *grpcCAServer) CreateSigningCertificate(ctx context.Context, request *fu return nil, handleFulcioGRPCError(ctx, codes.InvalidArgument, err, insecurePublicKey) } - // verify challenge - subject, err := challenges.ExtractSubject(ctx, principal, publicKey, csr, proofOfPossession) - if err != nil { - return nil, handleFulcioGRPCError(ctx, codes.InvalidArgument, err, invalidSignature) + // verify the challenge + if csr != nil { + err = csr.CheckSignature() + if err != nil { + return nil, handleFulcioGRPCError(ctx, codes.InvalidArgument, err, invalidSignature) + } + } else { + if err := challenges.CheckSignature(publicKey, proofOfPossession, principal.Name(ctx)); err != nil { + return nil, handleFulcioGRPCError(ctx, codes.InvalidArgument, err, invalidSignature) + } } var csc *certauth.CodeSigningCertificate @@ -115,7 +129,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, publicKey) + csc, err = g.ca.CreateCertificate(ctx, principal, publicKey) if err != nil { // if the error was due to invalid input in the request, return HTTP 400 if _, ok := err.(certauth.ValidationError); ok { @@ -165,7 +179,7 @@ func (g *grpcCAServer) CreateSigningCertificate(ctx context.Context, request *fu result.GetSignedCertificateDetachedSct().SignedCertificateTimestamp = sctBytes } } else { - precert, err := sctCa.CreatePrecertificate(ctx, subject, publicKey) + precert, err := sctCa.CreatePrecertificate(ctx, principal, publicKey) if err != nil { // if the error was due to invalid input in the request, return HTTP 400 if _, ok := err.(certauth.ValidationError); ok { diff --git a/pkg/challenges/challenges.go b/pkg/challenges/challenges.go index 03ed7db0e..b81a56fd5 100644 --- a/pkg/challenges/challenges.go +++ b/pkg/challenges/challenges.go @@ -493,7 +493,7 @@ func validateAllowedDomain(subjectHostname, issuerHostname string) error { return fmt.Errorf("hostname top-level and second-level domains do not match: %s, %s", subjectHostname, issuerHostname) } -func ExtractSubject(ctx context.Context, tok *oidc.IDToken, publicKey crypto.PublicKey, csr *x509.CertificateRequest, challenge []byte) (identity.Principal, error) { +func PrincipalFromIDToken(ctx context.Context, tok *oidc.IDToken) (identity.Principal, error) { iss, ok := config.FromContext(ctx).GetIssuer(tok.Issuer) if !ok { return nil, fmt.Errorf("configuration can not be loaded for issuer %v", tok.Issuer) @@ -520,18 +520,6 @@ func ExtractSubject(ctx context.Context, tok *oidc.IDToken, publicKey crypto.Pub return nil, err } - // verify the proof of possession of the private key - if csr != nil { - err = csr.CheckSignature() - if err != nil { - return nil, err - } - } else { - if err := CheckSignature(publicKey, challenge, principal.Name(ctx)); err != nil { - return nil, err - } - } - return principal, nil }