From 509c7892587969471e04959b8bc9246f7389b88d Mon Sep 17 00:00:00 2001 From: Hayden B Date: Wed, 1 Jun 2022 09:09:18 -0700 Subject: [PATCH] Add API for fetching Fulcio configuration (#608) This API provides the following: * All OIDC issuers, including the meta/wildcard issuers * The expected audience of the token * The claim that must be signed for a proof of possession * The SPIFFE trust domain, when the issuer is of type SPIFFE Also fix the workflow's regex. Signed-off-by: Hayden Blauzvern --- .github/workflows/main.yml | 2 +- fulcio.proto | 36 ++ pkg/config/config.go | 55 +++ pkg/config/config_network_test.go | 5 +- pkg/config/config_test.go | 90 ++++- pkg/generated/protobuf/fulcio.pb.go | 362 +++++++++++++++--- pkg/generated/protobuf/fulcio.pb.gw.go | 67 ++++ pkg/generated/protobuf/fulcio_grpc.pb.go | 42 +- .../protobuf/legacy/fulcio_legacy.pb.go | 2 +- .../protobuf/legacy/fulcio_legacy_grpc.pb.go | 2 +- pkg/server/grpc_server.go | 16 + pkg/server/grpc_server_test.go | 127 ++++++ 12 files changed, 755 insertions(+), 51 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e821520c2..c21e5e528 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -45,4 +45,4 @@ jobs: - name: Upload Coverage Report uses: codecov/codecov-action@81cd2dc8148241f03f5839d295e000b8f761e378 # v3.0.0 - name: Ensure no files were modified as a result of the build - run: git update-index --refresh && git diff-index --quiet -I"^\/\/\s+protoc(-gen-go)?\s+v[0-9]+\.[0-9]+\.[0-9]+$" HEAD -- || git diff -I"^\/\/\s+protoc(-gen-go)?\s+v[0-9]+\.[0-9]+\.[0-9]+$" --exit-code + run: git update-index --refresh && git diff-index --quiet -I"^\/\/\s+(-\s+)?protoc(-gen-go)?\s+v[0-9]+\.[0-9]+\.[0-9]+$" HEAD -- || git diff -I"^\/\/\s+(-\s+)?protoc(-gen-go)?\s+v[0-9]+\.[0-9]+\.[0-9]+$" --exit-code diff --git a/fulcio.proto b/fulcio.proto index aea41df4c..b318d9ba4 100644 --- a/fulcio.proto +++ b/fulcio.proto @@ -48,6 +48,15 @@ service CA { get: "/api/v2/trustBundle" }; } + + /** + * Returns the configuration of supported OIDC issuers, including the required challenge for each issuer. + */ + rpc GetConfiguration (GetConfigurationRequest) returns (Configuration) { + option (google.api.http) = { + get: "/api/v2/configuration" + }; + } } message CreateSigningCertificateRequest { @@ -166,3 +175,30 @@ enum PublicKeyAlgorithm { ECDSA = 2; ED25519 = 3; } + +// This is created for forward compatibility in case we want to add fields in the future. +message GetConfigurationRequest { +} + +// The configuration for the Fulcio instance. +message Configuration { + // The OIDC issuers supported by this Fulcio instance. + repeated OIDCIssuer issuers = 1; +} + +// Metadata about an OIDC issuer. +message OIDCIssuer { + oneof issuer { + // The URL of the OIDC issuer. + string issuer_url = 1; + // The URL of wildcard OIDC issuer, e.g. "https://oidc.eks.*.amazonaws.com/id/*". + // When comparing the issuer, the wildcards will be replaced by "[-_a-zA-Z0-9]+". + string wildcard_issuer_url = 2; + } + // The expected audience of the OIDC token for the issuer. + string audience = 3; + // The OIDC claim that must be signed for a proof of possession challenge. + string challenge_claim = 4; + // The expected SPIFFE trust domain. Only present when the OIDC issuer issues tokens for SPIFFE identities. + string spiffe_trust_domain = 5; +} \ No newline at end of file diff --git a/pkg/config/config.go b/pkg/config/config.go index 46655d047..67f2c0416 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -31,6 +31,7 @@ import ( "github.com/coreos/go-oidc/v3/oidc" lru "github.com/hashicorp/golang-lru" + fulciogrpc "github.com/sigstore/fulcio/pkg/generated/protobuf" "github.com/sigstore/fulcio/pkg/log" "github.com/spiffe/go-spiffe/v2/spiffeid" ) @@ -158,6 +159,33 @@ func (fc *FulcioConfig) GetVerifier(issuerURL string) (*oidc.IDTokenVerifier, bo return verifier, true } +// ToIssuers returns a proto representation of the OIDC issuer configuration. +func (fc *FulcioConfig) ToIssuers() []*fulciogrpc.OIDCIssuer { + var issuers []*fulciogrpc.OIDCIssuer + + for _, cfgIss := range fc.OIDCIssuers { + issuer := &fulciogrpc.OIDCIssuer{ + Issuer: &fulciogrpc.OIDCIssuer_IssuerUrl{IssuerUrl: cfgIss.IssuerURL}, + Audience: cfgIss.ClientID, + SpiffeTrustDomain: cfgIss.SPIFFETrustDomain, + ChallengeClaim: issuerToChallengeClaim(cfgIss.Type), + } + issuers = append(issuers, issuer) + } + + for metaIss, cfgIss := range fc.MetaIssuers { + issuer := &fulciogrpc.OIDCIssuer{ + Issuer: &fulciogrpc.OIDCIssuer_WildcardIssuerUrl{WildcardIssuerUrl: metaIss}, + Audience: cfgIss.ClientID, + SpiffeTrustDomain: cfgIss.SPIFFETrustDomain, + ChallengeClaim: issuerToChallengeClaim(cfgIss.Type), + } + issuers = append(issuers, issuer) + } + + return issuers +} + func (fc *FulcioConfig) prepare() error { fc.verifiers = make(map[string]*oidc.IDTokenVerifier, len(fc.OIDCIssuers)) for _, iss := range fc.OIDCIssuers { @@ -274,6 +302,10 @@ func validateConfig(conf *FulcioConfig) error { return err } } + + if issuerToChallengeClaim(issuer.Type) == "" { + return errors.New("issuer missing challenge claim") + } } for _, metaIssuer := range conf.MetaIssuers { @@ -282,6 +314,10 @@ func validateConfig(conf *FulcioConfig) error { // to trust domains so we fail early and reject this configuration. return errors.New("SPIFFE meta issuers not supported") } + + if issuerToChallengeClaim(metaIssuer.Type) == "" { + return errors.New("issuer missing challenge claim") + } } return nil @@ -421,3 +457,22 @@ func validateAllowedDomain(subjectHostname, issuerHostname string) error { } return fmt.Errorf("hostname top-level and second-level domains do not match: %s, %s", subjectHostname, issuerHostname) } + +func issuerToChallengeClaim(issType IssuerType) string { + switch issType { + case IssuerTypeEmail: + return "email" + case IssuerTypeGithubWorkflow: + return "sub" + case IssuerTypeKubernetes: + return "sub" + case IssuerTypeSpiffe: + return "sub" + case IssuerTypeURI: + return "sub" + case IssuerTypeUsername: + return "sub" + default: + return "" + } +} diff --git a/pkg/config/config_network_test.go b/pkg/config/config_network_test.go index 6ab68d30a..002030d72 100644 --- a/pkg/config/config_network_test.go +++ b/pkg/config/config_network_test.go @@ -34,7 +34,10 @@ func TestLoad(t *testing.T) { t.Fatal(err) } - cfg, _ := Load(cfgPath) + cfg, err := Load(cfgPath) + if err != nil { + t.Fatal(err) + } got, ok := cfg.GetIssuer("https://accounts.google.com") if !ok { t.Error("expected true, got false") diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index 4399ce91f..8e7ce8af2 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -18,7 +18,10 @@ package config import ( "fmt" "net/url" + "reflect" "testing" + + "github.com/sigstore/fulcio/pkg/generated/protobuf" ) var validCfg = ` @@ -26,12 +29,14 @@ var validCfg = ` "OIDCIssuers": { "https://accounts.google.com": { "IssuerURL": "https://accounts.google.com", - "ClientID": "foo" + "ClientID": "foo", + "Type": "email" } }, "MetaIssuers": { "https://oidc.eks.*.amazonaws.com/id/*": { - "ClientID": "bar" + "ClientID": "bar", + "Type": "kubernetes" } } } @@ -299,6 +304,18 @@ func TestValidateConfig(t *testing.T) { }, WantError: true, }, + "type without challenge claim is invalid": { + Config: &FulcioConfig{ + OIDCIssuers: map[string]OIDCIssuer{ + "https://issuer.example.com": { + IssuerURL: "htts://issuer.example.com", + ClientID: "sigstore", + Type: "invalid", + }, + }, + }, + WantError: true, + }, "nil config isn't valid": { Config: nil, WantError: true, @@ -451,3 +468,72 @@ func Test_validateAllowedDomain(t *testing.T) { }) } } + +func Test_issuerToChallengeClaim(t *testing.T) { + if claim := issuerToChallengeClaim(IssuerTypeEmail); claim != "email" { + t.Fatalf("expected email subject claim for email issuer, got %s", claim) + } + if claim := issuerToChallengeClaim(IssuerTypeSpiffe); claim != "sub" { + t.Fatalf("expected sub subject claim for SPIFFE issuer, got %s", claim) + } + if claim := issuerToChallengeClaim(IssuerTypeUsername); claim != "sub" { + t.Fatalf("expected sub subject claim for username issuer, got %s", claim) + } + if claim := issuerToChallengeClaim(IssuerTypeURI); claim != "sub" { + t.Fatalf("expected sub subject claim for URI issuer, got %s", claim) + } + if claim := issuerToChallengeClaim(IssuerTypeGithubWorkflow); claim != "sub" { + t.Fatalf("expected sub subject claim for GitHub issuer, got %s", claim) + } + if claim := issuerToChallengeClaim(IssuerTypeKubernetes); claim != "sub" { + t.Fatalf("expected sub subject claim for K8S issuer, got %s", claim) + } + // unexpected issuer has empty claim + if claim := issuerToChallengeClaim("invalid"); claim != "" { + t.Fatalf("expected no claim for invalid issuer, got %s", claim) + } +} + +func TestToIssuers(t *testing.T) { + config := &FulcioConfig{ + OIDCIssuers: map[string]OIDCIssuer{ + "example.com": { + IssuerURL: "example.com", + ClientID: "sigstore", + Type: IssuerTypeEmail, + }, + }, + MetaIssuers: map[string]OIDCIssuer{ + "wildcard.*.example.com": { + ClientID: "sigstore", + Type: IssuerTypeKubernetes, + }, + }, + } + + issuers := config.ToIssuers() + if len(issuers) != 2 { + t.Fatalf("unexpected number of issues, expected 2, got %v", len(issuers)) + } + + iss := &protobuf.OIDCIssuer{ + Audience: "sigstore", + ChallengeClaim: "email", + Issuer: &protobuf.OIDCIssuer_IssuerUrl{ + IssuerUrl: "example.com", + }, + } + if !reflect.DeepEqual(issuers[0], iss) { + t.Fatalf("expected issuer %v, got %v", iss, issuers[0]) + } + iss = &protobuf.OIDCIssuer{ + Audience: "sigstore", + ChallengeClaim: "sub", + Issuer: &protobuf.OIDCIssuer_WildcardIssuerUrl{ + WildcardIssuerUrl: "wildcard.*.example.com", + }, + } + if !reflect.DeepEqual(issuers[1], iss) { + t.Fatalf("expected issuer %v, got %v", iss, issuers[1]) + } +} diff --git a/pkg/generated/protobuf/fulcio.pb.go b/pkg/generated/protobuf/fulcio.pb.go index dd243c34e..8ec10065a 100644 --- a/pkg/generated/protobuf/fulcio.pb.go +++ b/pkg/generated/protobuf/fulcio.pb.go @@ -16,7 +16,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.0 -// protoc v3.6.1 +// protoc v3.12.4 // source: fulcio.proto package protobuf @@ -713,6 +713,205 @@ func (x *CertificateChain) GetCertificates() []string { return nil } +// This is created for forward compatibility in case we want to add fields in the future. +type GetConfigurationRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetConfigurationRequest) Reset() { + *x = GetConfigurationRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_fulcio_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetConfigurationRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetConfigurationRequest) ProtoMessage() {} + +func (x *GetConfigurationRequest) ProtoReflect() protoreflect.Message { + mi := &file_fulcio_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetConfigurationRequest.ProtoReflect.Descriptor instead. +func (*GetConfigurationRequest) Descriptor() ([]byte, []int) { + return file_fulcio_proto_rawDescGZIP(), []int{10} +} + +// The configuration for the Fulcio instance. +type Configuration struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The OIDC issuers supported by this Fulcio instance. + Issuers []*OIDCIssuer `protobuf:"bytes,1,rep,name=issuers,proto3" json:"issuers,omitempty"` +} + +func (x *Configuration) Reset() { + *x = Configuration{} + if protoimpl.UnsafeEnabled { + mi := &file_fulcio_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Configuration) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Configuration) ProtoMessage() {} + +func (x *Configuration) ProtoReflect() protoreflect.Message { + mi := &file_fulcio_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Configuration.ProtoReflect.Descriptor instead. +func (*Configuration) Descriptor() ([]byte, []int) { + return file_fulcio_proto_rawDescGZIP(), []int{11} +} + +func (x *Configuration) GetIssuers() []*OIDCIssuer { + if x != nil { + return x.Issuers + } + return nil +} + +// Metadata about an OIDC issuer. +type OIDCIssuer struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Issuer: + // *OIDCIssuer_IssuerUrl + // *OIDCIssuer_WildcardIssuerUrl + Issuer isOIDCIssuer_Issuer `protobuf_oneof:"issuer"` + // The expected audience of the OIDC token for the issuer. + Audience string `protobuf:"bytes,3,opt,name=audience,proto3" json:"audience,omitempty"` + // The OIDC claim that must be signed for a proof of possession challenge. + ChallengeClaim string `protobuf:"bytes,4,opt,name=challenge_claim,json=challengeClaim,proto3" json:"challenge_claim,omitempty"` + // The expected SPIFFE trust domain. Only present when the OIDC issuer issues tokens for SPIFFE identities. + SpiffeTrustDomain string `protobuf:"bytes,5,opt,name=spiffe_trust_domain,json=spiffeTrustDomain,proto3" json:"spiffe_trust_domain,omitempty"` +} + +func (x *OIDCIssuer) Reset() { + *x = OIDCIssuer{} + if protoimpl.UnsafeEnabled { + mi := &file_fulcio_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *OIDCIssuer) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*OIDCIssuer) ProtoMessage() {} + +func (x *OIDCIssuer) ProtoReflect() protoreflect.Message { + mi := &file_fulcio_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use OIDCIssuer.ProtoReflect.Descriptor instead. +func (*OIDCIssuer) Descriptor() ([]byte, []int) { + return file_fulcio_proto_rawDescGZIP(), []int{12} +} + +func (m *OIDCIssuer) GetIssuer() isOIDCIssuer_Issuer { + if m != nil { + return m.Issuer + } + return nil +} + +func (x *OIDCIssuer) GetIssuerUrl() string { + if x, ok := x.GetIssuer().(*OIDCIssuer_IssuerUrl); ok { + return x.IssuerUrl + } + return "" +} + +func (x *OIDCIssuer) GetWildcardIssuerUrl() string { + if x, ok := x.GetIssuer().(*OIDCIssuer_WildcardIssuerUrl); ok { + return x.WildcardIssuerUrl + } + return "" +} + +func (x *OIDCIssuer) GetAudience() string { + if x != nil { + return x.Audience + } + return "" +} + +func (x *OIDCIssuer) GetChallengeClaim() string { + if x != nil { + return x.ChallengeClaim + } + return "" +} + +func (x *OIDCIssuer) GetSpiffeTrustDomain() string { + if x != nil { + return x.SpiffeTrustDomain + } + return "" +} + +type isOIDCIssuer_Issuer interface { + isOIDCIssuer_Issuer() +} + +type OIDCIssuer_IssuerUrl struct { + // The URL of the OIDC issuer. + IssuerUrl string `protobuf:"bytes,1,opt,name=issuer_url,json=issuerUrl,proto3,oneof"` +} + +type OIDCIssuer_WildcardIssuerUrl struct { + // The URL of wildcard OIDC issuer, e.g. "https://oidc.eks.*.amazonaws.com/id/*". + // When comparing the issuer, the wildcards will be replaced by "[-_a-zA-Z0-9]+". + WildcardIssuerUrl string `protobuf:"bytes,2,opt,name=wildcard_issuer_url,json=wildcardIssuerUrl,proto3,oneof"` +} + +func (*OIDCIssuer_IssuerUrl) isOIDCIssuer_Issuer() {} + +func (*OIDCIssuer_WildcardIssuerUrl) isOIDCIssuer_Issuer() {} + var File_fulcio_proto protoreflect.FileDescriptor var file_fulcio_proto_rawDesc = []byte{ @@ -806,38 +1005,67 @@ var file_fulcio_proto_rawDesc = []byte{ 0x0a, 0x10, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, - 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x2a, 0x5f, 0x0a, 0x12, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, - 0x4b, 0x65, 0x79, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x24, 0x0a, 0x20, - 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x41, 0x4c, 0x47, 0x4f, 0x52, - 0x49, 0x54, 0x48, 0x4d, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, - 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x53, 0x41, 0x5f, 0x50, 0x53, 0x53, 0x10, 0x01, 0x12, - 0x09, 0x0a, 0x05, 0x45, 0x43, 0x44, 0x53, 0x41, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x45, 0x44, - 0x32, 0x35, 0x35, 0x31, 0x39, 0x10, 0x03, 0x32, 0xaa, 0x02, 0x0a, 0x02, 0x43, 0x41, 0x12, 0x9f, - 0x01, 0x0a, 0x18, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, - 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x37, 0x2e, 0x64, 0x65, - 0x76, 0x2e, 0x73, 0x69, 0x67, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x66, 0x75, 0x6c, 0x63, 0x69, - 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x69, - 0x6e, 0x67, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x64, 0x65, 0x76, 0x2e, 0x73, 0x69, 0x67, 0x73, 0x74, - 0x6f, 0x72, 0x65, 0x2e, 0x66, 0x75, 0x6c, 0x63, 0x69, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x69, - 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, - 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x22, 0x13, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, - 0x32, 0x2f, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x65, 0x72, 0x74, 0x3a, 0x01, 0x2a, - 0x12, 0x81, 0x01, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, - 0x64, 0x6c, 0x65, 0x12, 0x2d, 0x2e, 0x64, 0x65, 0x76, 0x2e, 0x73, 0x69, 0x67, 0x73, 0x74, 0x6f, - 0x72, 0x65, 0x2e, 0x66, 0x75, 0x6c, 0x63, 0x69, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, - 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x64, 0x65, 0x76, 0x2e, 0x73, 0x69, 0x67, 0x73, 0x74, 0x6f, 0x72, - 0x65, 0x2e, 0x66, 0x75, 0x6c, 0x63, 0x69, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x54, 0x72, 0x75, 0x73, - 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, - 0x13, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, - 0x6e, 0x64, 0x6c, 0x65, 0x42, 0x5a, 0x0a, 0x16, 0x64, 0x65, 0x76, 0x2e, 0x73, 0x69, 0x67, 0x73, - 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x66, 0x75, 0x6c, 0x63, 0x69, 0x6f, 0x2e, 0x76, 0x32, 0x42, 0x0b, - 0x46, 0x75, 0x6c, 0x63, 0x69, 0x6f, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x31, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x69, 0x67, 0x73, 0x74, 0x6f, - 0x72, 0x65, 0x2f, 0x66, 0x75, 0x6c, 0x63, 0x69, 0x6f, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x65, - 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x22, 0x19, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x22, 0x4d, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x3c, 0x0a, 0x07, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x64, 0x65, 0x76, 0x2e, 0x73, 0x69, 0x67, 0x73, 0x74, 0x6f, + 0x72, 0x65, 0x2e, 0x66, 0x75, 0x6c, 0x63, 0x69, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x4f, 0x49, 0x44, + 0x43, 0x49, 0x73, 0x73, 0x75, 0x65, 0x72, 0x52, 0x07, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x73, + 0x22, 0xde, 0x01, 0x0a, 0x0a, 0x4f, 0x49, 0x44, 0x43, 0x49, 0x73, 0x73, 0x75, 0x65, 0x72, 0x12, + 0x1f, 0x0a, 0x0a, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x55, 0x72, 0x6c, + 0x12, 0x30, 0x0a, 0x13, 0x77, 0x69, 0x6c, 0x64, 0x63, 0x61, 0x72, 0x64, 0x5f, 0x69, 0x73, 0x73, + 0x75, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, + 0x11, 0x77, 0x69, 0x6c, 0x64, 0x63, 0x61, 0x72, 0x64, 0x49, 0x73, 0x73, 0x75, 0x65, 0x72, 0x55, + 0x72, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x75, 0x64, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x75, 0x64, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x27, + 0x0a, 0x0f, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x5f, 0x63, 0x6c, 0x61, 0x69, + 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, + 0x67, 0x65, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x12, 0x2e, 0x0a, 0x13, 0x73, 0x70, 0x69, 0x66, 0x66, + 0x65, 0x5f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x73, 0x70, 0x69, 0x66, 0x66, 0x65, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x42, 0x08, 0x0a, 0x06, 0x69, 0x73, 0x73, 0x75, 0x65, + 0x72, 0x2a, 0x5f, 0x0a, 0x12, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x41, 0x6c, + 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x24, 0x0a, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, + 0x43, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x41, 0x4c, 0x47, 0x4f, 0x52, 0x49, 0x54, 0x48, 0x4d, 0x5f, + 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, + 0x07, 0x52, 0x53, 0x41, 0x5f, 0x50, 0x53, 0x53, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x43, + 0x44, 0x53, 0x41, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x45, 0x44, 0x32, 0x35, 0x35, 0x31, 0x39, + 0x10, 0x03, 0x32, 0xb6, 0x03, 0x0a, 0x02, 0x43, 0x41, 0x12, 0x9f, 0x01, 0x0a, 0x18, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x65, 0x72, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x37, 0x2e, 0x64, 0x65, 0x76, 0x2e, 0x73, 0x69, 0x67, + 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x66, 0x75, 0x6c, 0x63, 0x69, 0x6f, 0x2e, 0x76, 0x32, 0x2e, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x2a, 0x2e, 0x64, 0x65, 0x76, 0x2e, 0x73, 0x69, 0x67, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x66, + 0x75, 0x6c, 0x63, 0x69, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x18, 0x22, 0x13, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x73, 0x69, 0x67, + 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x65, 0x72, 0x74, 0x3a, 0x01, 0x2a, 0x12, 0x81, 0x01, 0x0a, 0x0e, + 0x47, 0x65, 0x74, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x2d, + 0x2e, 0x64, 0x65, 0x76, 0x2e, 0x73, 0x69, 0x67, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x66, 0x75, + 0x6c, 0x63, 0x69, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x75, 0x73, 0x74, + 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, + 0x64, 0x65, 0x76, 0x2e, 0x73, 0x69, 0x67, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x66, 0x75, 0x6c, + 0x63, 0x69, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, + 0x6c, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x61, 0x70, 0x69, + 0x2f, 0x76, 0x32, 0x2f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, + 0x89, 0x01, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2f, 0x2e, 0x64, 0x65, 0x76, 0x2e, 0x73, 0x69, 0x67, 0x73, 0x74, + 0x6f, 0x72, 0x65, 0x2e, 0x66, 0x75, 0x6c, 0x63, 0x69, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, + 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x64, 0x65, 0x76, 0x2e, 0x73, 0x69, 0x67, 0x73, + 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x66, 0x75, 0x6c, 0x63, 0x69, 0x6f, 0x2e, 0x76, 0x32, 0x2e, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x1d, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x17, 0x12, 0x15, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x5a, 0x0a, 0x16, 0x64, + 0x65, 0x76, 0x2e, 0x73, 0x69, 0x67, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x66, 0x75, 0x6c, 0x63, + 0x69, 0x6f, 0x2e, 0x76, 0x32, 0x42, 0x0b, 0x46, 0x75, 0x6c, 0x63, 0x69, 0x6f, 0x50, 0x72, 0x6f, + 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x73, 0x69, 0x67, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2f, 0x66, 0x75, 0x6c, 0x63, 0x69, 0x6f, + 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -853,7 +1081,7 @@ func file_fulcio_proto_rawDescGZIP() []byte { } var file_fulcio_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_fulcio_proto_msgTypes = make([]protoimpl.MessageInfo, 10) +var file_fulcio_proto_msgTypes = make([]protoimpl.MessageInfo, 13) var file_fulcio_proto_goTypes = []interface{}{ (PublicKeyAlgorithm)(0), // 0: dev.sigstore.fulcio.v2.PublicKeyAlgorithm (*CreateSigningCertificateRequest)(nil), // 1: dev.sigstore.fulcio.v2.CreateSigningCertificateRequest @@ -866,6 +1094,9 @@ var file_fulcio_proto_goTypes = []interface{}{ (*GetTrustBundleRequest)(nil), // 8: dev.sigstore.fulcio.v2.GetTrustBundleRequest (*TrustBundle)(nil), // 9: dev.sigstore.fulcio.v2.TrustBundle (*CertificateChain)(nil), // 10: dev.sigstore.fulcio.v2.CertificateChain + (*GetConfigurationRequest)(nil), // 11: dev.sigstore.fulcio.v2.GetConfigurationRequest + (*Configuration)(nil), // 12: dev.sigstore.fulcio.v2.Configuration + (*OIDCIssuer)(nil), // 13: dev.sigstore.fulcio.v2.OIDCIssuer } var file_fulcio_proto_depIdxs = []int32{ 2, // 0: dev.sigstore.fulcio.v2.CreateSigningCertificateRequest.credentials:type_name -> dev.sigstore.fulcio.v2.Credentials @@ -877,15 +1108,18 @@ var file_fulcio_proto_depIdxs = []int32{ 10, // 6: dev.sigstore.fulcio.v2.SigningCertificateDetachedSCT.chain:type_name -> dev.sigstore.fulcio.v2.CertificateChain 10, // 7: dev.sigstore.fulcio.v2.SigningCertificateEmbeddedSCT.chain:type_name -> dev.sigstore.fulcio.v2.CertificateChain 10, // 8: dev.sigstore.fulcio.v2.TrustBundle.chains:type_name -> dev.sigstore.fulcio.v2.CertificateChain - 1, // 9: dev.sigstore.fulcio.v2.CA.CreateSigningCertificate:input_type -> dev.sigstore.fulcio.v2.CreateSigningCertificateRequest - 8, // 10: dev.sigstore.fulcio.v2.CA.GetTrustBundle:input_type -> dev.sigstore.fulcio.v2.GetTrustBundleRequest - 5, // 11: dev.sigstore.fulcio.v2.CA.CreateSigningCertificate:output_type -> dev.sigstore.fulcio.v2.SigningCertificate - 9, // 12: dev.sigstore.fulcio.v2.CA.GetTrustBundle:output_type -> dev.sigstore.fulcio.v2.TrustBundle - 11, // [11:13] is the sub-list for method output_type - 9, // [9:11] is the sub-list for method input_type - 9, // [9:9] is the sub-list for extension type_name - 9, // [9:9] is the sub-list for extension extendee - 0, // [0:9] is the sub-list for field type_name + 13, // 9: dev.sigstore.fulcio.v2.Configuration.issuers:type_name -> dev.sigstore.fulcio.v2.OIDCIssuer + 1, // 10: dev.sigstore.fulcio.v2.CA.CreateSigningCertificate:input_type -> dev.sigstore.fulcio.v2.CreateSigningCertificateRequest + 8, // 11: dev.sigstore.fulcio.v2.CA.GetTrustBundle:input_type -> dev.sigstore.fulcio.v2.GetTrustBundleRequest + 11, // 12: dev.sigstore.fulcio.v2.CA.GetConfiguration:input_type -> dev.sigstore.fulcio.v2.GetConfigurationRequest + 5, // 13: dev.sigstore.fulcio.v2.CA.CreateSigningCertificate:output_type -> dev.sigstore.fulcio.v2.SigningCertificate + 9, // 14: dev.sigstore.fulcio.v2.CA.GetTrustBundle:output_type -> dev.sigstore.fulcio.v2.TrustBundle + 12, // 15: dev.sigstore.fulcio.v2.CA.GetConfiguration:output_type -> dev.sigstore.fulcio.v2.Configuration + 13, // [13:16] is the sub-list for method output_type + 10, // [10:13] is the sub-list for method input_type + 10, // [10:10] is the sub-list for extension type_name + 10, // [10:10] is the sub-list for extension extendee + 0, // [0:10] is the sub-list for field type_name } func init() { file_fulcio_proto_init() } @@ -1014,6 +1248,42 @@ func file_fulcio_proto_init() { return nil } } + file_fulcio_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetConfigurationRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_fulcio_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Configuration); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_fulcio_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*OIDCIssuer); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } file_fulcio_proto_msgTypes[0].OneofWrappers = []interface{}{ (*CreateSigningCertificateRequest_PublicKeyRequest)(nil), @@ -1026,13 +1296,17 @@ func file_fulcio_proto_init() { (*SigningCertificate_SignedCertificateDetachedSct)(nil), (*SigningCertificate_SignedCertificateEmbeddedSct)(nil), } + file_fulcio_proto_msgTypes[12].OneofWrappers = []interface{}{ + (*OIDCIssuer_IssuerUrl)(nil), + (*OIDCIssuer_WildcardIssuerUrl)(nil), + } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_fulcio_proto_rawDesc, NumEnums: 1, - NumMessages: 10, + NumMessages: 13, NumExtensions: 0, NumServices: 1, }, diff --git a/pkg/generated/protobuf/fulcio.pb.gw.go b/pkg/generated/protobuf/fulcio.pb.gw.go index cd91e2a4a..50737d890 100644 --- a/pkg/generated/protobuf/fulcio.pb.gw.go +++ b/pkg/generated/protobuf/fulcio.pb.gw.go @@ -83,6 +83,24 @@ func local_request_CA_GetTrustBundle_0(ctx context.Context, marshaler runtime.Ma } +func request_CA_GetConfiguration_0(ctx context.Context, marshaler runtime.Marshaler, client CAClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetConfigurationRequest + var metadata runtime.ServerMetadata + + msg, err := client.GetConfiguration(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_CA_GetConfiguration_0(ctx context.Context, marshaler runtime.Marshaler, server CAServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetConfigurationRequest + var metadata runtime.ServerMetadata + + msg, err := server.GetConfiguration(ctx, &protoReq) + return msg, metadata, err + +} + // RegisterCAHandlerServer registers the http handlers for service CA to "mux". // UnaryRPC :call CAServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. @@ -137,6 +155,30 @@ func RegisterCAHandlerServer(ctx context.Context, mux *runtime.ServeMux, server }) + mux.Handle("GET", pattern_CA_GetConfiguration_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + ctx, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/dev.sigstore.fulcio.v2.CA/GetConfiguration", runtime.WithHTTPPathPattern("/api/v2/configuration")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_CA_GetConfiguration_0(ctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_CA_GetConfiguration_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -220,6 +262,27 @@ func RegisterCAHandlerClient(ctx context.Context, mux *runtime.ServeMux, client }) + mux.Handle("GET", pattern_CA_GetConfiguration_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + ctx, err = runtime.AnnotateContext(ctx, mux, req, "/dev.sigstore.fulcio.v2.CA/GetConfiguration", runtime.WithHTTPPathPattern("/api/v2/configuration")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_CA_GetConfiguration_0(ctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_CA_GetConfiguration_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -227,10 +290,14 @@ var ( pattern_CA_CreateSigningCertificate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v2", "signingCert"}, "")) pattern_CA_GetTrustBundle_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v2", "trustBundle"}, "")) + + pattern_CA_GetConfiguration_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v2", "configuration"}, "")) ) var ( forward_CA_CreateSigningCertificate_0 = runtime.ForwardResponseMessage forward_CA_GetTrustBundle_0 = runtime.ForwardResponseMessage + + forward_CA_GetConfiguration_0 = runtime.ForwardResponseMessage ) diff --git a/pkg/generated/protobuf/fulcio_grpc.pb.go b/pkg/generated/protobuf/fulcio_grpc.pb.go index 412920a28..09d3ce0e3 100644 --- a/pkg/generated/protobuf/fulcio_grpc.pb.go +++ b/pkg/generated/protobuf/fulcio_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.2.0 -// - protoc v3.6.1 +// - protoc v3.12.4 // source: fulcio.proto package protobuf @@ -28,6 +28,9 @@ type CAClient interface { //* // Returns the bundle of certificates that can be used to validate code signing certificates issued by this Fulcio instance GetTrustBundle(ctx context.Context, in *GetTrustBundleRequest, opts ...grpc.CallOption) (*TrustBundle, error) + //* + // Returns the configuration of supported OIDC issuers, including the required challenge for each issuer. + GetConfiguration(ctx context.Context, in *GetConfigurationRequest, opts ...grpc.CallOption) (*Configuration, error) } type cAClient struct { @@ -56,6 +59,15 @@ func (c *cAClient) GetTrustBundle(ctx context.Context, in *GetTrustBundleRequest return out, nil } +func (c *cAClient) GetConfiguration(ctx context.Context, in *GetConfigurationRequest, opts ...grpc.CallOption) (*Configuration, error) { + out := new(Configuration) + err := c.cc.Invoke(ctx, "/dev.sigstore.fulcio.v2.CA/GetConfiguration", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // CAServer is the server API for CA service. // All implementations must embed UnimplementedCAServer // for forward compatibility @@ -66,6 +78,9 @@ type CAServer interface { //* // Returns the bundle of certificates that can be used to validate code signing certificates issued by this Fulcio instance GetTrustBundle(context.Context, *GetTrustBundleRequest) (*TrustBundle, error) + //* + // Returns the configuration of supported OIDC issuers, including the required challenge for each issuer. + GetConfiguration(context.Context, *GetConfigurationRequest) (*Configuration, error) mustEmbedUnimplementedCAServer() } @@ -79,6 +94,9 @@ func (UnimplementedCAServer) CreateSigningCertificate(context.Context, *CreateSi func (UnimplementedCAServer) GetTrustBundle(context.Context, *GetTrustBundleRequest) (*TrustBundle, error) { return nil, status.Errorf(codes.Unimplemented, "method GetTrustBundle not implemented") } +func (UnimplementedCAServer) GetConfiguration(context.Context, *GetConfigurationRequest) (*Configuration, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetConfiguration not implemented") +} func (UnimplementedCAServer) mustEmbedUnimplementedCAServer() {} // UnsafeCAServer may be embedded to opt out of forward compatibility for this service. @@ -128,6 +146,24 @@ func _CA_GetTrustBundle_Handler(srv interface{}, ctx context.Context, dec func(i return interceptor(ctx, in, info, handler) } +func _CA_GetConfiguration_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetConfigurationRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CAServer).GetConfiguration(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/dev.sigstore.fulcio.v2.CA/GetConfiguration", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CAServer).GetConfiguration(ctx, req.(*GetConfigurationRequest)) + } + return interceptor(ctx, in, info, handler) +} + // CA_ServiceDesc is the grpc.ServiceDesc for CA service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -143,6 +179,10 @@ var CA_ServiceDesc = grpc.ServiceDesc{ MethodName: "GetTrustBundle", Handler: _CA_GetTrustBundle_Handler, }, + { + MethodName: "GetConfiguration", + Handler: _CA_GetConfiguration_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "fulcio.proto", diff --git a/pkg/generated/protobuf/legacy/fulcio_legacy.pb.go b/pkg/generated/protobuf/legacy/fulcio_legacy.pb.go index 552ad3d6f..75161372e 100644 --- a/pkg/generated/protobuf/legacy/fulcio_legacy.pb.go +++ b/pkg/generated/protobuf/legacy/fulcio_legacy.pb.go @@ -16,7 +16,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.0 -// protoc v3.6.1 +// protoc v3.12.4 // source: fulcio_legacy.proto package legacy diff --git a/pkg/generated/protobuf/legacy/fulcio_legacy_grpc.pb.go b/pkg/generated/protobuf/legacy/fulcio_legacy_grpc.pb.go index bfda465ce..34b53a6f8 100644 --- a/pkg/generated/protobuf/legacy/fulcio_legacy_grpc.pb.go +++ b/pkg/generated/protobuf/legacy/fulcio_legacy_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.2.0 -// - protoc v3.6.1 +// - protoc v3.12.4 // source: fulcio_legacy.proto package legacy diff --git a/pkg/server/grpc_server.go b/pkg/server/grpc_server.go index 71a24e5d4..20b1977cf 100644 --- a/pkg/server/grpc_server.go +++ b/pkg/server/grpc_server.go @@ -20,6 +20,7 @@ import ( "crypto" "encoding/base64" "encoding/json" + "errors" "fmt" "strings" @@ -246,6 +247,21 @@ func (g *grpcCAServer) GetTrustBundle(ctx context.Context, _ *fulciogrpc.GetTrus }, nil } +func (g *grpcCAServer) GetConfiguration(ctx context.Context, _ *fulciogrpc.GetConfigurationRequest) (*fulciogrpc.Configuration, error) { + logger := log.ContextLogger(ctx) + + cfg := config.FromContext(ctx) + if cfg == nil { + err := errors.New("configuration not loaded") + logger.Error(err) + return nil, handleFulcioGRPCError(ctx, codes.Internal, err, genericCAError) + } + + return &fulciogrpc.Configuration{ + Issuers: cfg.ToIssuers(), + }, nil +} + func extractIssuer(token string) (string, error) { parts := strings.Split(token, ".") if len(parts) != 3 { diff --git a/pkg/server/grpc_server_test.go b/pkg/server/grpc_server_test.go index 701c76b7e..65ca3d7ee 100644 --- a/pkg/server/grpc_server_test.go +++ b/pkg/server/grpc_server_test.go @@ -169,6 +169,133 @@ func TestGetTrustBundleSuccess(t *testing.T) { } } +// Tests GetConfiguration API +func TestGetConfiguration(t *testing.T) { + _, emailIssuer := newOIDCIssuer(t) + _, spiffeIssuer := newOIDCIssuer(t) + _, uriIssuer := newOIDCIssuer(t) + _, usernameIssuer := newOIDCIssuer(t) + _, k8sIssuer := newOIDCIssuer(t) + _, gitHubIssuer := newOIDCIssuer(t) + + issuerDomain, err := url.Parse(usernameIssuer) + if err != nil { + t.Fatal("issuer URL could not be parsed", err) + } + + cfg, err := config.Read([]byte(fmt.Sprintf(`{ + "OIDCIssuers": { + %q: { + "IssuerURL": %q, + "ClientID": "sigstore", + "Type": "spiffe", + "SPIFFETrustDomain": "example.com" + }, + %q: { + "IssuerURL": %q, + "ClientID": "sigstore", + "SubjectDomain": %q, + "Type": "uri" + }, + %q: { + "IssuerURL": %q, + "ClientID": "sigstore", + "Type": "email" + }, + %q: { + "IssuerURL": %q, + "ClientID": "sigstore", + "SubjectDomain": %q, + "Type": "username" + }, + %q: { + "IssuerURL": %q, + "ClientID": "sigstore", + "Type": "github-workflow" + } + }, + "MetaIssuers": { + %q: { + "ClientID": "sigstore", + "Type": "kubernetes" + } + } + }`, spiffeIssuer, spiffeIssuer, + uriIssuer, uriIssuer, uriIssuer, + emailIssuer, emailIssuer, + usernameIssuer, usernameIssuer, issuerDomain.Hostname(), + gitHubIssuer, gitHubIssuer, + k8sIssuer))) + if err != nil { + t.Fatalf("config.Read() = %v", err) + } + + ctClient, eca := createCA(cfg, t) + ctx := context.Background() + server, conn := setupGRPCForTest(ctx, t, cfg, ctClient, eca) + defer func() { + server.Stop() + conn.Close() + }() + + client := protobuf.NewCAClient(conn) + + config, err := client.GetConfiguration(ctx, &protobuf.GetConfigurationRequest{}) + if err != nil { + t.Fatal("GetConfiguration failed", err) + } + + if len(config.Issuers) != 6 { + t.Fatalf("expected 6 issuers, got %v", len(config.Issuers)) + } + + expectedIssuers := map[string]bool{ + emailIssuer: true, spiffeIssuer: true, uriIssuer: true, + usernameIssuer: true, k8sIssuer: true, gitHubIssuer: true, + } + for _, iss := range config.Issuers { + var issURL string + switch { + case expectedIssuers[iss.GetIssuerUrl()]: + delete(expectedIssuers, iss.GetIssuerUrl()) + issURL = iss.GetIssuerUrl() + case expectedIssuers[iss.GetWildcardIssuerUrl()]: + delete(expectedIssuers, iss.GetWildcardIssuerUrl()) + issURL = iss.GetWildcardIssuerUrl() + default: + t.Fatal("issuer missing from expected issuers") + } + + if iss.Audience != "sigstore" { + t.Fatalf("expected audience to be sigstore, got %v", iss.Audience) + } + + if issURL == emailIssuer { + if iss.ChallengeClaim != "email" { + t.Fatalf("expected email claim for email PoP challenge, got %v", iss.ChallengeClaim) + } + } else { + if iss.ChallengeClaim != "sub" { + t.Fatalf("expected sub claim for non-email PoP challenge, got %v", iss.ChallengeClaim) + } + } + + if issURL == spiffeIssuer { + if iss.SpiffeTrustDomain != "example.com" { + t.Fatalf("expected SPIFFE trust domain example.com, got %v", iss.SpiffeTrustDomain) + } + } else { + if iss.SpiffeTrustDomain != "" { + t.Fatalf("expected no SPIFFE trust domain, got %v", iss.SpiffeTrustDomain) + } + } + } + + if len(expectedIssuers) != 0 { + t.Fatal("not all issuers were found in configuration") + } +} + // oidcTestContainer holds values needed for each API test invocation type oidcTestContainer struct { Signer jose.Signer