diff --git a/.gitattributes b/.gitattributes index e69de29bb..7ccd2fc2c 100644 --- a/.gitattributes +++ b/.gitattributes @@ -0,0 +1 @@ +/pkg/generated/protobuf/** linguist-generated diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index bb8f029ed..99807fd38 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -35,6 +35,8 @@ jobs: - uses: actions/setup-go@f6164bd8c8acb4a71fb2791a8b6c4024ff038dab # v3.0.0 with: go-version: ${{ env.GOVERSION }} + - name: Install protobuf + run: sudo apt update -y && sudo apt install -y -q protobuf-compiler - name: Build run: make -C $GITHUB_WORKSPACE all @@ -43,4 +45,4 @@ jobs: - name: Upload Coverage Report uses: codecov/codecov-action@e3c560433a6cc60aec8812599b7844a7b4fa0d71 # v3.0.0 - name: Ensure no files were modified as a result of the build - run: git update-index --refresh && git diff-index --quiet HEAD -- || git diff --exit-code + 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 diff --git a/.golangci.yml b/.golangci.yml index ea880ceb5..5a6d9b1bf 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -31,6 +31,11 @@ issues: linters: - errcheck - gosec + # the following section is due to the legacy API being deprecated + - path: pkg/api/legacy_server.go + linters: + - staticcheck + text: SA1019 max-issues-per-linter: 0 max-same-issues: 0 run: diff --git a/Makefile b/Makefile index 47f2c029e..3e06a646c 100644 --- a/Makefile +++ b/Makefile @@ -19,9 +19,16 @@ all: fulcio # Ensure Make is run with bash shell as some syntax below is bash-specific SHELL:=/usr/bin/env bash -SRCS = $(shell find cmd -iname "*.go") $(shell find pkg -iname "*.go") +SRCS = $(shell find cmd -iname "*.go") $(shell find pkg -iname "*.go"|grep -v pkg/generated) $(GENSRC) +TOOLS_DIR := hack/tools +TOOLS_BIN_DIR := $(abspath $(TOOLS_DIR)/bin) BIN_DIR := $(abspath $(ROOT_DIR)/bin) +GO_MODULE=$(shell head -1 go.mod | cut -f2 -d ' ') + +GENSRC = pkg/generated/protobuf/%.go +PROTOBUF_DEPS = $(shell find . -iname "*.proto" | grep -v "third_party") + # Set version variables for LDFLAGS GIT_VERSION ?= $(shell git describe --tags --always --dirty) GIT_HASH ?= $(shell git rev-parse HEAD) @@ -39,7 +46,7 @@ ifeq ($(DIFF), 1) GIT_TREESTATE = "dirty" endif -FULCIO_PKG=github.com/sigstore/fulcio/cmd/app +FULCIO_PKG=github.com/sigstore/fulcio/pkg/api LDFLAGS=-X $(FULCIO_PKG).gitVersion=$(GIT_VERSION) -X $(FULCIO_PKG).gitCommit=$(GIT_HASH) -X $(FULCIO_PKG).gitTreeState=$(GIT_TREESTATE) -X $(FULCIO_PKG).buildDate=$(BUILD_DATE) KO_PREFIX ?= gcr.io/projectsigstore @@ -49,12 +56,31 @@ GHCR_PREFIX ?= ghcr.io/sigstore FULCIO_YAML ?= fulcio-$(GIT_TAG).yaml +# Binaries +PROTOC-GEN-GO := $(TOOLS_BIN_DIR)/protoc-gen-go +PROTOC-GEN-GO-GRPC := $(TOOLS_BIN_DIR)/protoc-gen-go-grpc +PROTOC-GEN-GRPC-GATEWAY := $(TOOLS_BIN_DIR)/protoc-gen-grpc-gateway +PROTOC-API-LINTER := $(TOOLS_BIN_DIR)/api-linter + +$(GENSRC): $(PROTOC-GEN-GO) $(PROTOC-GEN-GO-GRPC) $(PROTOC-GEN-GRPC-GATEWAY) $(PROTOC-API-LINTER) $(PROTOBUF_DEPS) + mkdir -p pkg/generated/protobuf + $(PROTOC-API-LINTER) -I third_party/googleapis/ -I . $(PROTOBUF_DEPS) #--set-exit-status # TODO: add strict checking + protoc --plugin=protoc-gen-go=$(TOOLS_BIN_DIR)/protoc-gen-go \ + --go_opt=module=$(GO_MODULE) --go_out=. \ + --plugin=protoc-gen-go-grpc=$(TOOLS_BIN_DIR)/protoc-gen-go-grpc \ + --go-grpc_opt=module=$(GO_MODULE) --go-grpc_out=. \ + --plugin=protoc-gen-grpc-gateway=$(TOOLS_BIN_DIR)/protoc-gen-grpc-gateway \ + --grpc-gateway_opt=module=$(GO_MODULE) --grpc-gateway_opt=logtostderr=true --grpc-gateway_out=. \ + -I third_party/googleapis/ -I . $(PROTOBUF_DEPS) + lint: ## Runs golangci-lint $(GOBIN)/golangci-lint run -v ./... gosec: ## Runs gosec $(GOBIN)/gosec ./... +gen: $(GENSRC) + fulcio: $(SRCS) ## Build Fulcio for local tests go build -trimpath -ldflags "$(LDFLAGS)" @@ -65,6 +91,9 @@ clean: ## Clean the workspace rm -rf dist rm -rf fulcio +clean-gen: clean + rm -rf $(shell find pkg/generated -iname "*.go") + up: ## Start docker compose docker-compose -f docker-compose.yml build docker-compose -f docker-compose.yml up @@ -73,6 +102,22 @@ debug: ## Start docker compose in debug mode docker-compose -f docker-compose.yml -f docker-compose.debug.yml build fulcio-server-debug docker-compose -f docker-compose.yml -f docker-compose.debug.yml up fulcio-server-debug +## -------------------------------------- +## Tooling Binaries +## -------------------------------------- + +$(PROTOC-GEN-GO): $(TOOLS_DIR)/go.mod + cd $(TOOLS_DIR); go build -trimpath -tags=tools -o $(TOOLS_BIN_DIR)/protoc-gen-go google.golang.org/protobuf/cmd/protoc-gen-go + +$(PROTOC-GEN-GO-GRPC): $(TOOLS_DIR)/go.mod + cd $(TOOLS_DIR); go build -trimpath -tags=tools -o $(TOOLS_BIN_DIR)/protoc-gen-go-grpc google.golang.org/grpc/cmd/protoc-gen-go-grpc + +$(PROTOC-GEN-GRPC-GATEWAY): $(TOOLS_DIR)/go.mod + cd $(TOOLS_DIR); go build -trimpath -tags=tools -o $(TOOLS_BIN_DIR)/protoc-gen-grpc-gateway github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway + +$(PROTOC-API-LINTER): $(TOOLS_DIR)/go.mod + cd $(TOOLS_DIR); go build -trimpath -tags=tools -o $(TOOLS_BIN_DIR)/api-linter github.com/googleapis/api-linter/cmd/api-linter + ## -------------------------------------- ## Images with ko ## -------------------------------------- diff --git a/cmd/app/grpc.go b/cmd/app/grpc.go new file mode 100644 index 000000000..a258c7c05 --- /dev/null +++ b/cmd/app/grpc.go @@ -0,0 +1,151 @@ +// Copyright 2022 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 app + +import ( + "context" + "fmt" + "net" + + "github.com/goadesign/goa/grpc/middleware" + ctclient "github.com/google/certificate-transparency-go/client" + grpcmw "github.com/grpc-ecosystem/go-grpc-middleware" + grpc_zap "github.com/grpc-ecosystem/go-grpc-middleware/logging/zap" + grpc_recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery" + grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus" + "github.com/prometheus/client_golang/prometheus" + "github.com/sigstore/fulcio/pkg/api" + "github.com/sigstore/fulcio/pkg/ca" + "github.com/sigstore/fulcio/pkg/config" + gw "github.com/sigstore/fulcio/pkg/generated/protobuf" + gw_legacy "github.com/sigstore/fulcio/pkg/generated/protobuf/legacy" + "github.com/sigstore/fulcio/pkg/log" + "github.com/spf13/viper" + "google.golang.org/grpc" +) + +const ( + LegacyUnixDomainSocket = "@fulcio-legacy-grpc-socket" +) + +type grpcServer struct { + *grpc.Server + grpcServerEndpoint string + caService gw.CAServer +} + +func passFulcioConfigThruContext(cfg *config.FulcioConfig) grpc.UnaryServerInterceptor { + return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + // For each request, infuse context with our snapshot of the FulcioConfig. + // TODO(mattmoor): Consider periodically (every minute?) refreshing the ConfigMap + // from disk, so that we don't need to cycle pods to pick up config updates. + // Alternately we could take advantage of Knative's configmap watcher. + ctx = config.With(ctx, cfg) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + // Calls the inner handler + return handler(ctx, req) + } +} + +func createGRPCServer(cfg *config.FulcioConfig, ctClient *ctclient.LogClient, baseca ca.CertificateAuthority) (*grpcServer, error) { + logger, opts := log.SetupGRPCLogging() + + myServer := grpc.NewServer(grpc.UnaryInterceptor( + grpcmw.ChainUnaryServer( + grpc_recovery.UnaryServerInterceptor(grpc_recovery.WithRecoveryHandlerContext(panicRecoveryHandler)), // recovers from per-transaction panics elegantly, so put it first + middleware.UnaryRequestID(middleware.UseXRequestIDMetadataOption(true), middleware.XRequestMetadataLimitOption(128)), + grpc_zap.UnaryServerInterceptor(logger, opts...), + passFulcioConfigThruContext(cfg), + grpc_prometheus.UnaryServerInterceptor, + )), + grpc.MaxRecvMsgSize(int(maxMsgSize))) + + grpcCAServer := api.NewGRPCCAServer(ctClient, baseca) + // Register your gRPC service implementations. + gw.RegisterCAServer(myServer, grpcCAServer) + + grpcServerEndpoint := fmt.Sprintf("%s:%s", viper.GetString("grpc-host"), viper.GetString("grpc-port")) + return &grpcServer{myServer, grpcServerEndpoint, grpcCAServer}, nil +} + +func (g *grpcServer) setupPrometheus(reg *prometheus.Registry) { + grpcMetrics := grpc_prometheus.DefaultServerMetrics + grpcMetrics.EnableHandlingTimeHistogram() + reg.MustRegister(grpcMetrics, api.MetricLatency, api.RequestsCount) + grpc_prometheus.Register(g.Server) +} + +func (g *grpcServer) startTCPListener() { + go func() { + lis, err := net.Listen("tcp", g.grpcServerEndpoint) + if err != nil { + log.Logger.Fatal(err) + } + defer lis.Close() + + tcpAddr := lis.Addr().(*net.TCPAddr) + g.grpcServerEndpoint = fmt.Sprintf("%v:%d", tcpAddr.IP, tcpAddr.Port) + log.Logger.Infof("listening on grpc at %s", g.grpcServerEndpoint) + + log.Logger.Fatal(g.Server.Serve(lis)) + }() +} + +func (g *grpcServer) startUnixListener() { + go func() { + unixAddr, err := net.ResolveUnixAddr("unix", LegacyUnixDomainSocket) + if err != nil { + log.Logger.Fatal(err) + } + lis, err := net.ListenUnix("unix", unixAddr) + if err != nil { + log.Logger.Fatal(err) + } + defer lis.Close() + + log.Logger.Infof("listening on grpc at %s", unixAddr.String()) + + log.Logger.Fatal(g.Server.Serve(lis)) + }() +} + +func createLegacyGRPCServer(cfg *config.FulcioConfig, v2Server gw.CAServer) (*grpcServer, error) { + logger, opts := log.SetupGRPCLogging() + + myServer := grpc.NewServer(grpc.UnaryInterceptor( + grpcmw.ChainUnaryServer( + grpc_recovery.UnaryServerInterceptor(grpc_recovery.WithRecoveryHandlerContext(panicRecoveryHandler)), // recovers from per-transaction panics elegantly, so put it first + middleware.UnaryRequestID(middleware.UseXRequestIDMetadataOption(true), middleware.XRequestMetadataLimitOption(128)), + grpc_zap.UnaryServerInterceptor(logger, opts...), + passFulcioConfigThruContext(cfg), + grpc_prometheus.UnaryServerInterceptor, + )), + grpc.MaxRecvMsgSize(int(maxMsgSize))) + + legacyGRPCCAServer := api.NewLegacyGRPCCAServer(v2Server) + + // Register your gRPC service implementations. + gw_legacy.RegisterCAServer(myServer, legacyGRPCCAServer) + + return &grpcServer{myServer, LegacyUnixDomainSocket, v2Server}, nil +} + +func panicRecoveryHandler(ctx context.Context, p interface{}) error { + log.ContextLogger(ctx).Error(p) + return fmt.Errorf("panic: %v", p) +} diff --git a/cmd/app/http.go b/cmd/app/http.go new file mode 100644 index 000000000..ff4209e54 --- /dev/null +++ b/cmd/app/http.go @@ -0,0 +1,118 @@ +// Copyright 2022 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 app + +import ( + "context" + "fmt" + "net/http" + "strconv" + "strings" + "time" + + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "github.com/pkg/errors" + "github.com/prometheus/client_golang/prometheus/promhttp" + "github.com/sigstore/fulcio/pkg/api" + gw "github.com/sigstore/fulcio/pkg/generated/protobuf" + legacy_gw "github.com/sigstore/fulcio/pkg/generated/protobuf/legacy" + "github.com/sigstore/fulcio/pkg/log" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + "google.golang.org/grpc/metadata" + "google.golang.org/protobuf/proto" +) + +type httpServer struct { + *http.Server + httpServerEndpoint string +} + +func extractOIDCTokenFromAuthHeader(ctx context.Context, req *http.Request) metadata.MD { + token := strings.Replace(req.Header.Get("Authorization"), "Bearer ", "", 1) + return metadata.Pairs(api.MetadataOIDCTokenKey, token) +} + +func createHTTPServer(ctx context.Context, serverEndpoint string, grpcServer, legacyGRPCServer *grpcServer) httpServer { + mux := runtime.NewServeMux(runtime.WithMetadata(extractOIDCTokenFromAuthHeader), + runtime.WithForwardResponseOption(setResponseCodeModifier)) + + opts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())} + if err := gw.RegisterCAHandlerFromEndpoint(ctx, mux, grpcServer.grpcServerEndpoint, opts); err != nil { + log.Logger.Fatal(err) + } + + if legacyGRPCServer != nil { + endpoint := fmt.Sprintf("unix:%v", legacyGRPCServer.grpcServerEndpoint) + if err := legacy_gw.RegisterCAHandlerFromEndpoint(ctx, mux, endpoint, opts); err != nil { + log.Logger.Fatal(err) + } + } + + // Limit request size + handler := api.WithMaxBytes(mux, maxMsgSize) + handler = promhttp.InstrumentHandlerDuration(api.MetricLatency, handler) + handler = promhttp.InstrumentHandlerCounter(api.RequestsCount, handler) + + api := http.Server{ + Addr: serverEndpoint, + Handler: handler, + + // Timeouts + ReadTimeout: 60 * time.Second, + ReadHeaderTimeout: 60 * time.Second, + WriteTimeout: 60 * time.Second, + IdleTimeout: 60 * time.Second, + } + return httpServer{&api, serverEndpoint} +} + +func (h httpServer) startListener() { + log.Logger.Infof("listening on http at %s", h.httpServerEndpoint) + go func() { + if err := h.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { + log.Logger.Fatal(err) + } + }() +} + +func setResponseCodeModifier(ctx context.Context, w http.ResponseWriter, _ proto.Message) error { + md, ok := runtime.ServerMetadataFromContext(ctx) + if !ok { + return nil + } + + // set SCT if present ahead of modifying response code + if vals := md.HeaderMD.Get(api.SCTMetadataKey); len(vals) > 0 { + delete(md.HeaderMD, api.SCTMetadataKey) + delete(w.Header(), "Grpc-Metadata-sct") + w.Header().Set("SCT", vals[0]) + } + + // set http status code + if vals := md.HeaderMD.Get(api.HTTPResponseCodeMetadataKey); len(vals) > 0 { + code, err := strconv.Atoi(vals[0]) + if err != nil { + return err + } + // delete the headers to not expose any grpc-metadata in http response + delete(md.HeaderMD, api.HTTPResponseCodeMetadataKey) + delete(w.Header(), "Grpc-Metadata-X-Http-Code") + w.WriteHeader(code) + } + + return nil +} diff --git a/cmd/app/serve.go b/cmd/app/serve.go index 098b24754..b2f444bdd 100644 --- a/cmd/app/serve.go +++ b/cmd/app/serve.go @@ -16,6 +16,7 @@ package app import ( + "context" "flag" "fmt" "net/http" @@ -27,8 +28,8 @@ import ( ctclient "github.com/google/certificate-transparency-go/client" "github.com/google/certificate-transparency-go/jsonclient" "github.com/pkg/errors" + "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" - "github.com/sigstore/fulcio/pkg/api" certauth "github.com/sigstore/fulcio/pkg/ca" "github.com/sigstore/fulcio/pkg/ca/ephemeralca" "github.com/sigstore/fulcio/pkg/ca/fileca" @@ -38,6 +39,7 @@ import ( "github.com/sigstore/fulcio/pkg/config" "github.com/sigstore/fulcio/pkg/log" "github.com/spf13/cobra" + "github.com/spf13/pflag" "github.com/spf13/viper" "go.uber.org/zap" ) @@ -69,12 +71,31 @@ func newServeCmd() *cobra.Command { cmd.Flags().Bool("fileca-watch", true, "Watch filesystem for updates") cmd.Flags().String("kms-resource", "", "KMS key resource path. Must be prefixed with awskms://, azurekms://, gcpkms://, or hashivault://") cmd.Flags().String("kms-cert-chain-path", "", "Path to PEM-encoded CA certificate chain for KMS-backed CA") - cmd.Flags().String("host", "0.0.0.0", "The host on which to serve requests") - cmd.Flags().String("port", "8080", "The port on which to serve requests") + cmd.Flags().String("host", "0.0.0.0", "The host on which to serve requests for HTTP; --http-host is alias") + cmd.Flags().String("port", "8080", "The port on which to serve requests for HTTP; --http-port is alias") + cmd.Flags().String("grpc-host", "0.0.0.0", "The host on which to serve requests for GRPC") + cmd.Flags().String("grpc-port", "8081", "The port on which to serve requests for GRPC") + + // convert "http-host" flag to "host" and "http-port" flag to be "port" + cmd.Flags().SetNormalizeFunc(func(f *pflag.FlagSet, name string) pflag.NormalizedName { + switch name { + case "http-port": + name = "port" + case "http-host": + name = "host" + } + return pflag.NormalizedName(name) + }) + viper.RegisterAlias("http-host", "host") + viper.RegisterAlias("http-port", "port") return cmd } +const ( + maxMsgSize int64 = 1 << 22 // 4MiB +) + // Adaptor for logging with the CT log type logAdaptor struct { logger *zap.SugaredLogger @@ -181,17 +202,6 @@ func runServeCmd(cmd *cobra.Command, args []string) { log.Logger.Fatal(err) } - prom := http.Server{ - Addr: ":2112", - Handler: promhttp.Handler(), - } - go func() { - _ = prom.ListenAndServe() - }() - - host, port := viper.GetString("host"), viper.GetString("port") - log.Logger.Infof("%s:%s", host, port) - var ctClient *ctclient.LogClient if logURL := viper.GetString("ct-log-url"); logURL != "" { ctClient, err = ctclient.New(logURL, @@ -205,47 +215,32 @@ func runServeCmd(cmd *cobra.Command, args []string) { } } - var handler http.Handler - { - handler = api.New(ctClient, baseca) + httpServerEndpoint := fmt.Sprintf("%v:%v", viper.GetString("http-host"), viper.GetString("http-port")) - // Inject dependencies - withDependencies := func(inner http.Handler) http.Handler { - return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { - ctx := r.Context() + reg := prometheus.NewRegistry() - // For each request, infuse context with our snapshot of the FulcioConfig. - // TODO(mattmoor): Consider periodically (every minute?) refreshing the ConfigMap - // from disk, so that we don't need to cycle pods to pick up config updates. - // Alternately we could take advantage of Knative's configmap watcher. - ctx = config.With(ctx, cfg) - - inner.ServeHTTP(rw, r.WithContext(ctx)) - }) - } - handler = withDependencies(handler) + grpcServer, err := createGRPCServer(cfg, ctClient, baseca) + if err != nil { + log.Logger.Fatal(err) + } + grpcServer.setupPrometheus(reg) + grpcServer.startTCPListener() - // Instrument Prometheus metrics - handler = promhttp.InstrumentHandlerDuration(api.MetricLatency, handler) - handler = promhttp.InstrumentHandlerCounter(api.RequestsCount, handler) - // Limit request size - handler = api.WithMaxBytes(handler, 1<<22) // 4MiB + legacyGRPCServer, err := createLegacyGRPCServer(cfg, grpcServer.caService) + if err != nil { + log.Logger.Fatal(err) } + legacyGRPCServer.startUnixListener() - api := http.Server{ - Addr: host + ":" + port, - Handler: handler, + httpServer := createHTTPServer(context.Background(), httpServerEndpoint, grpcServer, legacyGRPCServer) + httpServer.startListener() - // Timeouts - ReadTimeout: 60 * time.Second, - ReadHeaderTimeout: 60 * time.Second, - WriteTimeout: 60 * time.Second, - IdleTimeout: 60 * time.Second, + prom := http.Server{ + Addr: ":2112", + Handler: promhttp.Handler(), } + log.Logger.Error(prom.ListenAndServe()) - if err := api.ListenAndServe(); err != nil && err != http.ErrServerClosed { - log.Logger.Fatal(err) - } } func checkServeCmdConfigFile() error { diff --git a/cmd/app/version.go b/cmd/app/version.go index 44ed4a402..d4fb7d37f 100644 --- a/cmd/app/version.go +++ b/cmd/app/version.go @@ -16,32 +16,13 @@ package app import ( - "encoding/json" "fmt" - "runtime" - "strings" - "text/tabwriter" "github.com/pkg/errors" + "github.com/sigstore/fulcio/pkg/api" "github.com/spf13/cobra" ) -// Base version information. -// -// This is the fallback data used when version information from git is not -// provided via go ldflags (e.g. via Makefile). -var ( - // Output of "git describe". The prerequisite is that the branch should be - // tagged using the correct versioning strategy. - gitVersion = "unknown" - // SHA1 from git, output of $(git rev-parse HEAD) - gitCommit = "unknown" - // State of git tree, either "clean" or "dirty" - gitTreeState = "unknown" - // Build date in ISO8601 format, output of $(date -u +'%Y-%m-%dT%H:%M:%SZ') - buildDate = "unknown" -) - type versionOptions struct { json bool } @@ -63,7 +44,7 @@ func newVersionCmd() *cobra.Command { } func runVersion(opts *versionOptions) error { - v := VersionInfo() + v := api.VersionInfo() res := v.String() if opts.json { @@ -77,54 +58,3 @@ func runVersion(opts *versionOptions) error { fmt.Println(res) return nil } - -type Info struct { - GitVersion string - GitCommit string - GitTreeState string - BuildDate string - GoVersion string - Compiler string - Platform string -} - -func VersionInfo() Info { - // These variables typically come from -ldflags settings and in - // their absence fallback to the global defaults set above. - return Info{ - GitVersion: gitVersion, - GitCommit: gitCommit, - GitTreeState: gitTreeState, - BuildDate: buildDate, - GoVersion: runtime.Version(), - Compiler: runtime.Compiler, - Platform: fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH), - } -} - -// String returns the string representation of the version info -func (i *Info) String() string { - b := strings.Builder{} - w := tabwriter.NewWriter(&b, 0, 0, 2, ' ', 0) - - fmt.Fprintf(w, "GitVersion:\t%s\n", i.GitVersion) - fmt.Fprintf(w, "GitCommit:\t%s\n", i.GitCommit) - fmt.Fprintf(w, "GitTreeState:\t%s\n", i.GitTreeState) - fmt.Fprintf(w, "BuildDate:\t%s\n", i.BuildDate) - fmt.Fprintf(w, "GoVersion:\t%s\n", i.GoVersion) - fmt.Fprintf(w, "Compiler:\t%s\n", i.Compiler) - fmt.Fprintf(w, "Platform:\t%s\n", i.Platform) - - w.Flush() // #nosec - return b.String() -} - -// JSONString returns the JSON representation of the version info -func (i *Info) JSONString() (string, error) { - b, err := json.MarshalIndent(i, "", " ") - if err != nil { - return "", err - } - - return string(b), nil -} diff --git a/config/ctfe/ct_server.cfg b/config/ctfe/ct_server.cfg index 7ef4ebae0..cc3501e7c 100644 --- a/config/ctfe/ct_server.cfg +++ b/config/ctfe/ct_server.cfg @@ -8,4 +8,5 @@ config { password: "foobar" } } + ext_key_usages: [ "CodeSigning" ] } diff --git a/config/ctfe/root.pem b/config/ctfe/root.pem deleted file mode 100644 index f658126af..000000000 --- a/config/ctfe/root.pem +++ /dev/null @@ -1,13 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIB+DCCAX6gAwIBAgITNVkDZoCiofPDsy7dfm6geLbuhzAKBggqhkjOPQQDAzAq -MRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxETAPBgNVBAMTCHNpZ3N0b3JlMB4XDTIx -MDMwNzAzMjAyOVoXDTMxMDIyMzAzMjAyOVowKjEVMBMGA1UEChMMc2lnc3RvcmUu -ZGV2MREwDwYDVQQDEwhzaWdzdG9yZTB2MBAGByqGSM49AgEGBSuBBAAiA2IABLSy -A7Ii5k+pNO8ZEWY0ylemWDowOkNa3kL+GZE5Z5GWehL9/A9bRNA3RbrsZ5i0Jcas -taRL7Sp5fp/jD5dxqc/UdTVnlvS16an+2Yfswe/QuLolRUCrcOE2+2iA5+tzd6Nm -MGQwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYE -FMjFHQBBmiQpMlEk6w2uSu1KBtPsMB8GA1UdIwQYMBaAFMjFHQBBmiQpMlEk6w2u -Su1KBtPsMAoGCCqGSM49BAMDA2gAMGUCMH8liWJfMui6vXXBhjDgY4MwslmN/TJx -Ve/83WrFomwmNf056y1X48F9c4m3a3ozXAIxAKjRay5/aj/jsKKGIkmQatjI8uup -Hr/+CxFvaJWmpYqNkLDGRU+9orzh5hI2RrcuaQ== ------END CERTIFICATE----- diff --git a/config/deployment.yaml b/config/deployment.yaml index 36f3beff8..4aba59d47 100644 --- a/config/deployment.yaml +++ b/config/deployment.yaml @@ -46,6 +46,7 @@ spec: image: ko://github.com/sigstore/fulcio ports: - containerPort: 5555 + - containerPort: 5554 - containerPort: 2112 # metrics args: [ "serve", "-c", "/etc/fulcio-config/server.yaml", @@ -107,3 +108,7 @@ spec: protocol: TCP port: 80 targetPort: 5555 + - name: grpc + protocol: TCP + port: 5554 + targetPort: 5554 diff --git a/config/fulcio-config.yaml b/config/fulcio-config.yaml index 5f8ee28c4..d6e9fe56a 100644 --- a/config/fulcio-config.yaml +++ b/config/fulcio-config.yaml @@ -62,6 +62,7 @@ data: server.yaml: |- host: 0.0.0.0 port: 5555 + grpc-port: 5554 ca: googleca ct-log-url: http://ct-log/test log_type: prod diff --git a/config/logid.sh b/config/logid.sh index ca1a5392f..685e9fc22 100644 --- a/config/logid.sh +++ b/config/logid.sh @@ -48,5 +48,10 @@ if ! [[ -s /etc/config/ct_server.cfg ]]; then else echo " found." configid=`cat /etc/config/ct_server.cfg|grep log_id|awk ' { print $2 } '` - echo "Existing configuration uses log ID $configid, exiting" + echo "Existing configuration uses log ID $configid" fi +curl -s --retry-connrefused --retry 10 http://fulcio-server:5555/api/v1/rootCert -o tmpchain.pem +csplit -s -f tmpcert- tmpchain.pem '/-----BEGIN CERTIFICATE-----/' '{*}' +mv $(ls tmpcert-* | tail -1) /etc/config/root.pem +rm tmpcert-* tmpchain.pem +echo "Fetched valid root certificate from Fulcio to limit entries in CTFE instance" \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 20da7a324..0bede199f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -24,8 +24,8 @@ services: "serve", "--host=0.0.0.0", "--port=5555", - "--ca=googleca", - "--gcp_private_ca_parent=projects/project-rekor/locations/us-central1/certificateAuthorities/sigstore", + "--grpc-port=5554", + "--ca=ephemeralca", "--ct-log-url=http://ct_server:6962/test", # Uncomment this for production logging # "--log_type=prod", @@ -33,8 +33,9 @@ services: restart: always # keep the server running ports: - "5555:5555" + - "5554:5554" + - "2112:2112" volumes: - - ~/.config/gcloud:/root/.config/gcloud/:z - ./config/config.jsn:/etc/fulcio-config/config.json:z healthcheck: test: ["CMD", "curl", "-f", "http://localhost:5555/ping"] @@ -45,6 +46,7 @@ services: depends_on: - dex-idp - ct_server + read_only: true dex-idp: image: dexidp/dex:v2.30.0 user: root diff --git a/docs/ctlog.md b/docs/ctlog.md index 988c6e12e..1e4f960bc 100644 --- a/docs/ctlog.md +++ b/docs/ctlog.md @@ -4,7 +4,7 @@ Fulcio maintains a certificate transparency (CT) log, writing all issued certificates to the log. Users of Sigstore can verify via cryptographic proof that certificates are included in the log -along with monitoring the log for inconsistencies. +along with monitoring the log for inconsistencies. The CT log is backed by [Trillian](https://github.com/google/trillian), a highly scalable and verifiable data store. The `certificate-transparency-go` @@ -20,7 +20,7 @@ included in Sigstore's TUF metadata. SCTs can either be embedded in a certificate or detached from the certificate. If an SCT is detached, this means that Fulcio returns the SCT alongside the certificate, and it's up to the caller to store -the SCT. For example, with Cosign, the SCT is not stored, so it is only verified during artifact +the SCT. For example, with Cosign, the SCT is not stored, so it is only verified during artifact signing. All callers should be storing certificates, so SCTs embedded in the certificate can be verified both during artifact signing and verification. @@ -100,4 +100,4 @@ frozen, accepting no more entries. We will create new log shards each year. The log's name will be the year. Currently, the log is accessible at `https://ctfe.sigstore.dev/test`. After sharding the log, the log will be accessible at `https://ctfe.sigstore.dev/2022`. We can use the same signing key for each year's shard, so that we don't -need to distribute a new key each year in the TUF metadata. \ No newline at end of file +need to distribute a new key each year in the TUF metadata. diff --git a/examples/request-certificate/main.go b/examples/request-certificate/main.go index 8de4d43c1..51df28d9a 100644 --- a/examples/request-certificate/main.go +++ b/examples/request-certificate/main.go @@ -17,17 +17,23 @@ package main import ( "bytes" + "context" "crypto" + "crypto/tls" "crypto/x509" "encoding/pem" "fmt" "log" "net/url" - "github.com/sigstore/fulcio/pkg/api" + fulciopb "github.com/sigstore/fulcio/pkg/generated/protobuf" + "github.com/sigstore/sigstore/pkg/cryptoutils" "github.com/sigstore/sigstore/pkg/oauthflow" "github.com/sigstore/sigstore/pkg/signature" "github.com/sigstore/sigstore/pkg/signature/options" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/credentials/insecure" ) var ( @@ -37,7 +43,7 @@ var ( ) // Some of this is just ripped from cosign -func GetCert(signer *signature.RSAPKCS1v15SignerVerifier, fc api.Client, oidcIssuer string, oidcClientID string) (*api.CertificateResponse, error) { +func GetCert(signer *signature.RSAPKCS1v15SignerVerifier, fc fulciopb.CAClient, oidcIssuer string, oidcClientID string) (*fulciopb.SigningCertificate, error) { tok, err := oauthflow.OIDConnect(oidcIssuer, oidcClientID, "", "", oauthflow.DefaultIDTokenGetter) if err != nil { @@ -51,27 +57,38 @@ func GetCert(signer *signature.RSAPKCS1v15SignerVerifier, fc api.Client, oidcIss log.Fatal(err) } - pubBytes, err := x509.MarshalPKIXPublicKey(signer.Public()) + pubBytesPEM, err := cryptoutils.MarshalPublicKeyToPEM(signer.Public()) if err != nil { return nil, err } - cr := api.CertificateRequest{ - PublicKey: api.Key{ - Algorithm: "rsa4096", - Content: pubBytes, + cscr := &fulciopb.CreateSigningCertificateRequest{ + Credentials: &fulciopb.Credentials{ + Credentials: &fulciopb.Credentials_OidcIdentityToken{ + OidcIdentityToken: tok.RawString, + }, }, - SignedEmailAddress: proof, + PublicKey: &fulciopb.PublicKey{ + Content: string(pubBytesPEM), + }, + ProofOfPossession: proof, } - return fc.SigningCert(cr, tok.RawString) + return fc.CreateSigningCertificate(context.Background(), cscr) } -func NewClient(fulcioURL string) (api.Client, error) { +func NewClient(fulcioURL string) (fulciopb.CAClient, error) { fulcioServer, err := url.Parse(fulcioURL) if err != nil { return nil, err } - fClient := api.NewClient(fulcioServer, api.WithUserAgent("Fulcio Example Code")) - return fClient, nil + dialOpt := grpc.WithTransportCredentials(insecure.NewCredentials()) + if fulcioServer.Scheme == "https" { + dialOpt = grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{})) + } + conn, err := grpc.Dial(fulcioServer.Host, dialOpt) + if err != nil { + return nil, err + } + return fulciopb.NewCAClient(conn), nil } func main() { @@ -90,7 +107,14 @@ func main() { log.Fatal(err) } - clientPEM, _ := pem.Decode([]byte(certResp.CertPEM)) + var chain *fulciopb.CertificateChain + switch cert := certResp.Certificate.(type) { + case *fulciopb.SigningCertificate_SignedCertificateDetachedSct: + chain = cert.SignedCertificateDetachedSct.GetChain() + case *fulciopb.SigningCertificate_SignedCertificateEmbeddedSct: + chain = cert.SignedCertificateEmbeddedSct.GetChain() + } + clientPEM, _ := pem.Decode([]byte(chain.Certificates[0])) cert, err := x509.ParseCertificate(clientPEM.Bytes) if err != nil { log.Fatal(err) diff --git a/examples/request-certificate/request-certificate b/examples/request-certificate/request-certificate new file mode 100755 index 000000000..877377397 Binary files /dev/null and b/examples/request-certificate/request-certificate differ diff --git a/fulcio.proto b/fulcio.proto new file mode 100644 index 000000000..d331c9c27 --- /dev/null +++ b/fulcio.proto @@ -0,0 +1,143 @@ +// +// Copyright 2022 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. + +syntax = "proto3"; +package dev.sigstore.fulcio.v2; + +import "google/api/annotations.proto"; +import "google/api/field_behavior.proto"; + +option go_package = "github.com/sigstore/fulcio/pkg/generated/protobuf"; +option java_package = "dev.sigstore.fulcio.v2"; +option java_multiple_files = true; +option java_outer_classname = "FulcioProto"; + +service CA { + /** + * Returns an X.509 certificate created by the Fulcio certificate authority for the given request parameters + */ + rpc CreateSigningCertificate (CreateSigningCertificateRequest) returns (SigningCertificate){ + option (google.api.http) = { + post: "/api/v2/signingCert" + body: "*" + }; + } + /** + * Returns the bundle of certificates that can be used to validate code signing certificates issued by this Fulcio instance + */ + rpc GetTrustBundle (GetTrustBundleRequest) returns (TrustBundle){ + option (google.api.http) = { + get: "/api/v2/trustBundle" + }; + } +} + +message CreateSigningCertificateRequest { + /* + * Identity information about who possesses the private / public key pair presented + */ + Credentials credentials = 1 [(google.api.field_behavior) = REQUIRED]; + /* + * The public key to be stored in the requested certificate + */ + PublicKey public_key = 2 [(google.api.field_behavior) = REQUIRED]; + /* + * Proof that the client possesses the private key; must be verifiable by provided public key + * + * This is a currently a signature over the `sub` claim from the OIDC identity token + */ + bytes proof_of_possession = 3 [(google.api.field_behavior) = REQUIRED]; +} + +message Credentials { + oneof credentials { + /* + * The OIDC token that identifies the caller + */ + string oidc_identity_token = 1; + } +} + +message PublicKey { + /* + * The cryptographic algorithm to use with the key material + */ + PublicKeyAlgorithm algorithm = 1; + /* + * PEM encoded public key + */ + string content = 2 [(google.api.field_behavior) = REQUIRED]; +} + +message SigningCertificate { + oneof certificate { + SigningCertificateDetachedSCT signed_certificate_detached_sct = 1; + SigningCertificateEmbeddedSCT signed_certificate_embedded_sct = 2; + } +} + +// (-- api-linter: core::0142::time-field-type=disabled +// aip.dev/not-precedent: SCT is defined in RFC6962 and we keep the name consistent for easier understanding. --) +message SigningCertificateDetachedSCT { + /* + * The certificate chain serialized with the leaf certificate first, followed + * by all intermediate certificates (if present), finishing with the root certificate. + * + * All values are PEM-encoded certificates. + */ + CertificateChain chain = 1; + /* + * The signed certificate timestamp is a promise for including the certificate in + * a certificate transparency log. It can be "stapled" to verify the inclusion of + * a certificate in the log in an offline fashion. + */ + bytes signed_certificate_timestamp = 2; +} + +message SigningCertificateEmbeddedSCT { + /* + * The certificate chain serialized with the leaf certificate first, followed + * by all intermediate certificates (if present), finishing with the root certificate. + * + * All values are PEM-encoded certificates. + */ + CertificateChain chain = 1; +} + +// This is created for forward compatibility in case we want to add fields to the TrustBundle service in the future +message GetTrustBundleRequest { +} + +message TrustBundle { + /* + * The set of PEM-encoded certificate chains for this Fulcio instance; each chain will start with any + * intermediate certificates (if present), finishing with the root certificate. + */ + repeated CertificateChain chains = 1; +} + +message CertificateChain { + /* + * The PEM-encoded certificate chain, ordered from leaf to intermediate to root as applicable. + */ + repeated string certificates = 1; +} + +enum PublicKeyAlgorithm { + PUBLIC_KEY_ALGORITHM_UNSPECIFIED = 0; + RSA_PSS = 1; + ECDSA = 2; + ED25519 = 3; +} diff --git a/fulcio_legacy.proto b/fulcio_legacy.proto new file mode 100644 index 000000000..36887688e --- /dev/null +++ b/fulcio_legacy.proto @@ -0,0 +1,74 @@ +// +// Copyright 2022 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. + +syntax = "proto3"; +package dev.sigstore.fulcio.v1beta; + +import "google/api/annotations.proto"; +import "google/api/httpbody.proto"; +import "google/protobuf/empty.proto"; + +option go_package = "github.com/sigstore/fulcio/pkg/generated/protobuf/legacy"; +option java_package = "dev.sigstore.fulcio.v1beta"; +option java_multiple_files = true; +option java_outer_classname = "FulcioProto"; + +/* + * This implements the pre-GA HTTP-based Fulcio API. + * This interface is deprecated - clients should prefer the GA GRPC interface! + */ +service CA { + /* + * Returns an X509 certificate created by the Fulcio certificate authority for the given request parameters + */ + rpc CreateSigningCertificate(CreateSigningCertificateRequest) returns (google.api.HttpBody){ + option deprecated = true; + option (google.api.http) = { + post: "/api/v1/signingCert" + body: "*" + }; + } + /* + * Returns the public key that can be used to validate the signed tree head + */ + rpc GetRootCertificate(google.protobuf.Empty) returns (google.api.HttpBody){ + option deprecated = true; + option (google.api.http) = { + get: "/api/v1/rootCert" + }; + } +} + +message CreateSigningCertificateRequest { + /* + * The public key to be stored in the requested certificate + */ + PublicKey publicKey = 1 [ deprecated=true ]; + /* + * Proof that the client possesses the private key + */ + bytes signedEmailAddress = 2 [ deprecated=true ]; +} + +message PublicKey { + /* + * The cryptographic algorithm to use with the key material + */ + string algorithm = 1 [ deprecated=true ]; + /* + * DER or PEM encoded public key + */ + bytes content = 2 [ deprecated=true ]; +} diff --git a/go.mod b/go.mod index 04500a0bd..f61ac8ad5 100644 --- a/go.mod +++ b/go.mod @@ -8,9 +8,13 @@ require ( github.com/ThalesIgnite/crypto11 v1.2.5 github.com/coreos/go-oidc/v3 v3.1.0 github.com/fsnotify/fsnotify v1.5.1 - github.com/go-chi/chi v4.1.2+incompatible + github.com/goadesign/goa v2.2.5+incompatible + github.com/golang/protobuf v1.5.2 github.com/google/certificate-transparency-go v1.1.2 github.com/google/go-cmp v0.5.7 + github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 + github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.8.0 github.com/hashicorp/golang-lru v0.5.4 github.com/magiconair/properties v1.8.6 github.com/pkg/errors v0.9.1 @@ -19,12 +23,15 @@ require ( github.com/prometheus/common v0.33.0 github.com/sigstore/sigstore v1.2.1-0.20220401110139-0e610e39782f github.com/spf13/cobra v1.4.0 + github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.11.0 go.step.sm/crypto v0.16.1 go.uber.org/multierr v1.7.0 // indirect go.uber.org/zap v1.21.0 + goa.design/goa v2.2.5+incompatible // indirect google.golang.org/api v0.74.0 google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac + google.golang.org/grpc v1.45.0 google.golang.org/protobuf v1.28.0 gopkg.in/square/go-jose.v2 v2.6.0 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b diff --git a/go.sum b/go.sum index d5fed0b3b..82461325e 100644 --- a/go.sum +++ b/go.sum @@ -538,8 +538,6 @@ github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmC github.com/gin-gonic/gin v1.7.1/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= -github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec= -github.com/go-chi/chi v4.1.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -584,6 +582,8 @@ github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg78 github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= +github.com/goadesign/goa v2.2.5+incompatible h1:SLgzk0V+QfFs7MVz9sbDHelbTDI9B/d4W7Hl5udTynY= +github.com/goadesign/goa v2.2.5+incompatible/go.mod h1:d/9lpuZBK7HFi/7O0oXfwvdoIl+nx2bwKqctZe/lQao= github.com/gobuffalo/attrs v0.1.0/go.mod h1:fmNpaWyHM0tRm8gCZWKx8yY9fvaNLo2PyzBNSrBZ5Hw= github.com/gobuffalo/envy v1.8.1/go.mod h1:FurDp9+EDPE4aIUS3ZLyD+7/9fpx7YRt/ukY6jIHf0w= github.com/gobuffalo/envy v1.9.0/go.mod h1:FurDp9+EDPE4aIUS3ZLyD+7/9fpx7YRt/ukY6jIHf0w= @@ -626,8 +626,9 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69 github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU= github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= +github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -776,6 +777,8 @@ github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t github.com/grpc-ecosystem/grpc-gateway v1.14.6/go.mod h1:zdiPV4Yse/1gnckTHtghG4GkDEdKCRJduHpTxT3/jcw= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.8.0 h1:/57CcG6YAO31FWwTVUnNl+2RcDUAaT55HtI71KQAXVw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.8.0/go.mod h1:/fckq3NE+vGiJsd4fDt4ge1XrK8cN+e5G5QWIzdg7Q8= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= @@ -1606,6 +1609,8 @@ go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= +goa.design/goa v2.2.5+incompatible h1:mjAtiy7ZdZIkj974hpFxCR6bL69qprfV00Veu3Vybts= +goa.design/goa v2.2.5+incompatible/go.mod h1:NnzBwdNktihbNek+pPiFMQP9PPFsUt8MMPPyo9opDSo= gocloud.dev v0.19.0/go.mod h1:SmKwiR8YwIMMJvQBKLsC3fHNyMwXLw3PMDO+VVteJMI= goji.io/v3 v3.0.0/go.mod h1:c02FFnNiVNCDo+DpR2IhBQpM9r5G1BG/MkHNTPUJ13U= golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -2188,6 +2193,7 @@ google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ6 google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220302033224-9aa15565e42a/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= @@ -2349,6 +2355,7 @@ sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyz sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= +sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/hack/tools/go.mod b/hack/tools/go.mod new file mode 100644 index 000000000..b006f1030 --- /dev/null +++ b/hack/tools/go.mod @@ -0,0 +1,10 @@ +module github.com/sigstore/fulcio/hack/tools + +go 1.16 + +require ( + github.com/googleapis/api-linter v1.30.1 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.8.0 + google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 + google.golang.org/protobuf v1.27.1 +) diff --git a/hack/tools/go.sum b/hack/tools/go.sum new file mode 100644 index 000000000..361f77429 --- /dev/null +++ b/hack/tools/go.sum @@ -0,0 +1,461 @@ +bitbucket.org/creachadair/stringset v0.0.10 h1:DZjkR57sJGMycZNVVbl+26bK7vW1kwLQE6qWICWLteI= +bitbucket.org/creachadair/stringset v0.0.10/go.mod h1:6G0fsnHFxynEdWpihfZf44lnBPpTW6nkrcxITVTBHus= +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/bmatcuk/doublestar/v2 v2.0.4 h1:6I6oUiT/sU27eE2OFcWqBhL1SwjyvQuOssxT4a1yidI= +github.com/bmatcuk/doublestar/v2 v2.0.4/go.mod h1:QMmcs3H2AUQICWhfzLXz+IYln8lRQmTZRptLie8RgRw= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/gertd/go-pluralize v0.1.7 h1:RgvJTJ5W7olOoAks97BOwOlekBFsLEyh00W48Z6ZEZY= +github.com/gertd/go-pluralize v0.1.7/go.mod h1:O4eNeeIf91MHh1GJ2I47DNtaesm66NYvjYgAahcqSDQ= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= +github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/api-linter v1.30.1 h1:QvjGw8cqbycfb+p08wzO/QtFiUOC2pIiU2ErA5aMh3k= +github.com/googleapis/api-linter v1.30.1/go.mod h1:KQGHvRoWHxFAhqLUTaJtW8s0SBmmkrxkWrfxYHZlotk= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.8.0 h1:/57CcG6YAO31FWwTVUnNl+2RcDUAaT55HtI71KQAXVw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.8.0/go.mod h1:/fckq3NE+vGiJsd4fDt4ge1XrK8cN+e5G5QWIzdg7Q8= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/jhump/protoreflect v1.10.1 h1:iH+UZfsbRE6vpyZH7asAjTPWJf7RJbpZ9j/N3lDlKs0= +github.com/jhump/protoreflect v1.10.1/go.mod h1:7GcYQDdMU/O/BBrl/cX6PNHpXh6cenjd8pneu5yW7Tg= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/lithammer/dedent v1.1.0 h1:VNzHMVCBNG1j0fh3OrsFRkVUwStdDArbgBWoPAffktY= +github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/nishanths/predeclared v0.0.0-20200524104333-86fad755b4d3/go.mod h1:nt3d53pc1VYcphSCIaYAJtnPYnr3Zyn8fMq2wvPGPso= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU= +github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200522201501-cb1345f3a375/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200717024301-6ddee64345a6/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20211223182754-3ac035c7e7cb/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220302033224-9aa15565e42a h1:uqouglH745GoGeZ1YFZbPBiu961tgi/9Qm5jaorajjQ= +google.golang.org/genproto v0.0.0-20220302033224-9aa15565e42a/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.44.0 h1:weqSxi/TMs1SqFRMHCtBgXRs8k3X39QIDEZ0pRcttUg= +google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 h1:M1YKkFIboKNieVO5DLUEVzQfGwJD30Nv2jfUgzb5UcE= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.25.1-0.20200805231151-a709e31e5d12/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/pkg/api/ca_test.go b/hack/tools/tools.go similarity index 50% rename from pkg/api/ca_test.go rename to hack/tools/tools.go index 01f5abd83..d66d27798 100644 --- a/pkg/api/ca_test.go +++ b/hack/tools/tools.go @@ -1,3 +1,6 @@ +//go:build tools +// +build tools + // Copyright 2022 The Sigstore Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -13,30 +16,13 @@ // limitations under the License. // -package api - -import "testing" - -func TestVerifyContentType(t *testing.T) { - testCases := []struct { - contentType string - shouldPass bool - }{ - {"application/json", true}, - {"application/json; charset=UTF-8", true}, - {"application/unsupported", false}, - {"some nonsense", false}, - } +// This package imports things required by build scripts, to force `go mod` to see them as dependencies +package tools - for _, tc := range testCases { - t.Run(tc.contentType, func(t *testing.T) { - err := verifyContentType(tc.contentType) - if err != nil && tc.shouldPass { - t.Fatalf("Expected no error but got %q", err) - } - if err == nil && !tc.shouldPass { - t.Fatalf("Expected error but got none") - } - }) - } -} +import ( + _ "github.com/googleapis/api-linter/cmd/api-linter" + _ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway" + _ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2" + _ "google.golang.org/grpc/cmd/protoc-gen-go-grpc" + _ "google.golang.org/protobuf/cmd/protoc-gen-go" +) diff --git a/pkg/api/ca.go b/pkg/api/ca.go deleted file mode 100644 index f49a38483..000000000 --- a/pkg/api/ca.go +++ /dev/null @@ -1,315 +0,0 @@ -// 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 api - -import ( - "bytes" - "context" - "crypto" - "crypto/x509" - "encoding/base64" - "encoding/json" - "fmt" - "mime" - "net/http" - "strings" - - "github.com/coreos/go-oidc/v3/oidc" - ctclient "github.com/google/certificate-transparency-go/client" - certauth "github.com/sigstore/fulcio/pkg/ca" - "github.com/sigstore/fulcio/pkg/challenges" - "github.com/sigstore/fulcio/pkg/config" - "github.com/sigstore/fulcio/pkg/ctl" - "github.com/sigstore/fulcio/pkg/log" - "github.com/sigstore/sigstore/pkg/cryptoutils" -) - -type Key struct { - // +required - Content []byte `json:"content"` - Algorithm string `json:"algorithm,omitempty"` -} - -type CertificateRequest struct { - // +required - PublicKey Key `json:"publicKey"` - - // +required - SignedEmailAddress []byte `json:"signedEmailAddress"` -} - -const ( - signingCertPath = "/api/v1/signingCert" - rootCertPath = "/api/v1/rootCert" -) - -type api struct { - ct *ctclient.LogClient - ca certauth.CertificateAuthority - - *http.ServeMux -} - -// New creates a new http.Handler for serving the Fulcio API. -func New(ct *ctclient.LogClient, ca certauth.CertificateAuthority) http.Handler { - var a api - a.ServeMux = http.NewServeMux() - a.HandleFunc(signingCertPath, a.signingCert) - a.HandleFunc(rootCertPath, a.rootCert) - a.ct = ct - a.ca = ca - return &a -} - -func extractIssuer(token string) (string, error) { - parts := strings.Split(token, ".") - if len(parts) < 2 { - return "", fmt.Errorf("oidc: malformed jwt, expected 3 parts got %d", len(parts)) - } - raw, err := base64.RawURLEncoding.DecodeString(parts[1]) - if err != nil { - return "", fmt.Errorf("oidc: malformed jwt payload: %w", err) - } - var payload struct { - Issuer string `json:"iss"` - } - - if err := json.Unmarshal(raw, &payload); err != nil { - return "", fmt.Errorf("oidc: failed to unmarshal claims: %w", err) - } - return payload.Issuer, nil -} - -// We do this to bypass needing actual OIDC tokens for unit testing. -var authorize = actualAuthorize - -func actualAuthorize(req *http.Request) (*oidc.IDToken, error) { - // Strip off the "Bearer" prefix. - token := strings.Replace(req.Header.Get("Authorization"), "Bearer ", "", 1) - - issuer, err := extractIssuer(token) - if err != nil { - return nil, err - } - - verifier, ok := config.FromContext(req.Context()).GetVerifier(issuer) - if !ok { - return nil, fmt.Errorf("unsupported issuer: %s", issuer) - } - return verifier.Verify(req.Context(), token) -} - -func verifyContentType(contentType string) error { - gotContentType, _, perr := mime.ParseMediaType(contentType) - if perr != nil { - return fmt.Errorf("could not parse Content-Type %q", contentType) - } - wantContentType := "application/json" - if gotContentType != wantContentType { - return fmt.Errorf("signing cert handler must receive %q, got %q", wantContentType, gotContentType) - } - return nil -} - -func (a *api) signingCert(w http.ResponseWriter, req *http.Request) { - if req.Method != http.MethodPost { - err := fmt.Errorf("signing cert handler must receive POSTs, got %s", req.Method) - handleFulcioAPIError(w, req, http.StatusMethodNotAllowed, err, err.Error()) - return - } - - if err := verifyContentType(req.Header.Get("Content-Type")); err != nil { - handleFulcioAPIError(w, req, http.StatusUnsupportedMediaType, err, err.Error()) - return - } - - ctx := req.Context() - logger := log.ContextLogger(ctx) - - principal, err := authorize(req) - if err != nil { - handleFulcioAPIError(w, req, http.StatusUnauthorized, err, invalidCredentials) - return - } - - // Parse the request body. - cr := CertificateRequest{} - if err := json.NewDecoder(req.Body).Decode(&cr); err != nil { - handleFulcioAPIError(w, req, http.StatusBadRequest, err, invalidCertificateRequest) - return - } - - publicKeyBytes := cr.PublicKey.Content - // try to unmarshal as DER - publicKey, err := x509.ParsePKIXPublicKey(publicKeyBytes) - if err != nil { - // try to unmarshal as PEM - logger.Debugf("error parsing public key as DER, trying pem: %v", err.Error()) - publicKey, err = cryptoutils.UnmarshalPEMToPublicKey(publicKeyBytes) - if err != nil { - handleFulcioAPIError(w, req, http.StatusBadRequest, err, invalidPublicKey) - return - } - } - // Validate public key, checking for weak key parameters. - if err := cryptoutils.ValidatePubKey(publicKey); err != nil { - handleFulcioAPIError(w, req, http.StatusBadRequest, err, insecurePublicKey) - return - } - - subject, err := ExtractSubject(ctx, principal, publicKey, cr.SignedEmailAddress) - if err != nil { - handleFulcioAPIError(w, req, http.StatusBadRequest, err, invalidSignature) - return - } - - var csc *certauth.CodeSigningCertificate - var sctBytes []byte - // For CAs that do not support embedded SCTs or if the CT log is not configured - if sctCa, ok := a.ca.(certauth.EmbeddedSCTCA); !ok || a.ct == nil { - // currently configured CA doesn't support pre-certificate flow required to embed SCT in final certificate - csc, err = a.ca.CreateCertificate(ctx, subject) - if err != nil { - // if the error was due to invalid input in the request, return HTTP 400 - if _, ok := err.(certauth.ValidationError); ok { - handleFulcioAPIError(w, req, http.StatusBadRequest, err, err.Error()) - return - } - // otherwise return a 500 error to reflect that it is a transient server issue that the client can't resolve - handleFulcioAPIError(w, req, http.StatusInternalServerError, err, genericCAError) - return - } - - // submit to CTL - if a.ct != nil { - sct, err := a.ct.AddChain(ctx, ctl.BuildCTChain(csc.FinalCertificate, csc.FinalChain)) - if err != nil { - handleFulcioAPIError(w, req, http.StatusInternalServerError, err, failedToEnterCertInCTL) - return - } - // convert to AddChainResponse because Cosign expects this struct. - addChainResp, err := ctl.ToAddChainResponse(sct) - if err != nil { - handleFulcioAPIError(w, req, http.StatusInternalServerError, err, failedToMarshalSCT) - return - } - sctBytes, err = json.Marshal(addChainResp) - if err != nil { - handleFulcioAPIError(w, req, http.StatusInternalServerError, err, failedToMarshalSCT) - return - } - } else { - logger.Info("Skipping CT log upload.") - } - } else { - precert, err := sctCa.CreatePrecertificate(ctx, subject) - if err != nil { - // if the error was due to invalid input in the request, return HTTP 400 - if _, ok := err.(certauth.ValidationError); ok { - handleFulcioAPIError(w, req, http.StatusBadRequest, err, err.Error()) - return - } - // otherwise return a 500 error to reflect that it is a transient server issue that the client can't resolve - handleFulcioAPIError(w, req, http.StatusInternalServerError, err, genericCAError) - } - // submit precertificate and chain to CT log - sct, err := a.ct.AddPreChain(ctx, ctl.BuildCTChain(precert.PreCert, precert.CertChain)) - if err != nil { - handleFulcioAPIError(w, req, http.StatusInternalServerError, err, failedToEnterCertInCTL) - return - } - csc, err = sctCa.IssueFinalCertificate(ctx, precert, sct) - if err != nil { - handleFulcioAPIError(w, req, http.StatusInternalServerError, err, genericCAError) - return - } - } - - metricNewEntries.Inc() - - var ret strings.Builder - finalPEM, err := csc.CertPEM() - if err != nil { - handleFulcioAPIError(w, req, http.StatusInternalServerError, err, failedToMarshalCert) - return - } - fmt.Fprintf(&ret, "%s", finalPEM) - if !bytes.HasSuffix(finalPEM, []byte("\n")) { - fmt.Fprintf(&ret, "\n") - } - - finalChainPEM, err := csc.ChainPEM() - if err != nil { - handleFulcioAPIError(w, req, http.StatusInternalServerError, err, failedToMarshalCert) - return - } - if len(finalChainPEM) > 0 { - fmt.Fprintf(&ret, "%s", finalChainPEM) - if !bytes.HasSuffix(finalChainPEM, []byte("\n")) { - fmt.Fprintf(&ret, "\n") - } - } - - // Set the SCT and Content-Type headers, and then respond with a 201 Created. - if len(sctBytes) != 0 { - w.Header().Add("SCT", base64.StdEncoding.EncodeToString(sctBytes)) - } - w.Header().Add("Content-Type", "application/pem-certificate-chain") - w.WriteHeader(http.StatusCreated) - // Write the PEM encoded certificate chain to the response body. - if _, err := w.Write([]byte(strings.TrimSpace(ret.String()))); err != nil { - logger.Error("Error writing response: ", err) - } -} - -func (a *api) rootCert(w http.ResponseWriter, req *http.Request) { - ctx := req.Context() - logger := log.ContextLogger(ctx) - - root, err := a.ca.Root(ctx) - if err != nil { - logger.Error("Error retrieving root cert: ", err) - handleFulcioAPIError(w, req, http.StatusInternalServerError, err, genericCAError) - return - } - w.Header().Add("Content-Type", "application/pem-certificate-chain") - if _, err := w.Write(root); err != nil { - logger.Error("Error writing response: ", err) - } -} - -func ExtractSubject(ctx context.Context, tok *oidc.IDToken, publicKey crypto.PublicKey, challenge []byte) (*challenges.ChallengeResult, 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) - } - switch iss.Type { - case config.IssuerTypeEmail: - return challenges.Email(ctx, tok, publicKey, challenge) - case config.IssuerTypeSpiffe: - return challenges.Spiffe(ctx, tok, publicKey, challenge) - case config.IssuerTypeGithubWorkflow: - return challenges.GithubWorkflow(ctx, tok, publicKey, challenge) - case config.IssuerTypeKubernetes: - return challenges.Kubernetes(ctx, tok, publicKey, challenge) - case config.IssuerTypeURI: - return challenges.URI(ctx, tok, publicKey, challenge) - case config.IssuerTypeUsername: - return challenges.Username(ctx, tok, publicKey, challenge) - default: - return nil, fmt.Errorf("unsupported issuer: %s", iss.Type) - } -} diff --git a/pkg/api/client.go b/pkg/api/client.go index 7ab8e3305..c2a1179b4 100644 --- a/pkg/api/client.go +++ b/pkg/api/client.go @@ -39,11 +39,30 @@ type RootResponse struct { ChainPEM []byte } +type Key struct { + // +required + Content []byte `json:"content"` + Algorithm string `json:"algorithm,omitempty"` +} + +type CertificateRequest struct { + // +required + PublicKey Key `json:"publicKey"` + + // +required + SignedEmailAddress []byte `json:"signedEmailAddress"` +} + +const ( + signingCertPath = "/api/v1/signingCert" + rootCertPath = "/api/v1/rootCert" +) + // SigstorePublicServerURL is the URL of Sigstore's public Fulcio service. const SigstorePublicServerURL = "https://fulcio.sigstore.dev" -// Client is the interface for accessing the Fulcio API. -type Client interface { +// LegacyClient is the interface for accessing the Fulcio API. +type LegacyClient interface { // SigningCert sends the provided CertificateRequest to the /api/v1/signingCert // endpoint of a Fulcio API, authenticated with the provided bearer token. SigningCert(cr CertificateRequest, token string) (*CertificateResponse, error) @@ -55,7 +74,7 @@ type Client interface { type ClientOption func(*clientOptions) // NewClient creates a new Fulcio API client talking to the provided URL. -func NewClient(url *url.URL, opts ...ClientOption) Client { +func NewClient(url *url.URL, opts ...ClientOption) LegacyClient { o := makeOptions(opts...) return &client{ @@ -72,7 +91,7 @@ type client struct { client *http.Client } -var _ Client = (*client)(nil) +var _ LegacyClient = (*client)(nil) // SigningCert implements Client func (c *client) SigningCert(cr CertificateRequest, token string) (*CertificateResponse, error) { diff --git a/pkg/api/error.go b/pkg/api/error.go index 51a67f0b7..f6ef06927 100644 --- a/pkg/api/error.go +++ b/pkg/api/error.go @@ -16,30 +16,26 @@ package api import ( - "fmt" - "net/http" + "context" "github.com/sigstore/fulcio/pkg/log" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) const ( - invalidSignature = "The signature supplied in the request could not be verified" - invalidCertificateRequest = "The CertificateRequest was invalid" - invalidPublicKey = "The public key supplied in the request could not be parsed" - failedToEnterCertInCTL = "Error entering certificate in CTL" - failedToMarshalSCT = "Error marshaling signed certificate timestamp" - failedToMarshalCert = "Error marshaling code signing certificate" - insecurePublicKey = "The public key supplied in the request is insecure" + invalidSignature = "The signature supplied in the request could not be verified" + invalidPublicKey = "The public key supplied in the request could not be parsed" + failedToEnterCertInCTL = "Error entering certificate in CTL" + failedToMarshalSCT = "Error marshaling signed certificate timestamp" + failedToMarshalCert = "Error marshaling code signing certificate" + insecurePublicKey = "The public key supplied in the request is insecure" //nolint invalidCredentials = "There was an error processing the credentials for this request" genericCAError = "error communicating with CA backend" ) -func handleFulcioAPIError(w http.ResponseWriter, req *http.Request, code int, err error, message string, fields ...interface{}) { - if message == "" { - message = http.StatusText(code) - } - - log.RequestIDLogger(req).Errorw("exiting with error", append([]interface{}{"handler", req.URL.Path, "statusCode", code, "clientMessage", message, "error", err}, fields...)...) - http.Error(w, fmt.Sprintf(`{"code":%d,"message":%q}`, code, message), code) +func handleFulcioGRPCError(ctx context.Context, code codes.Code, err error, message string, fields ...interface{}) error { + log.ContextLogger(ctx).Errorw("returning with error", append([]interface{}{"code", code, "clientMessage", message, "error", err}, fields...)...) + return status.Error(code, message) } diff --git a/pkg/api/grpc_server.go b/pkg/api/grpc_server.go new file mode 100644 index 000000000..0c04c2d4f --- /dev/null +++ b/pkg/api/grpc_server.go @@ -0,0 +1,248 @@ +// Copyright 2022 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 api + +import ( + "context" + "crypto/x509" + "encoding/base64" + "encoding/json" + "fmt" + "strings" + + "github.com/coreos/go-oidc/v3/oidc" + ctclient "github.com/google/certificate-transparency-go/client" + certauth "github.com/sigstore/fulcio/pkg/ca" + "github.com/sigstore/fulcio/pkg/challenges" + "github.com/sigstore/fulcio/pkg/config" + "github.com/sigstore/fulcio/pkg/ctl" + fulciogrpc "github.com/sigstore/fulcio/pkg/generated/protobuf" + "github.com/sigstore/fulcio/pkg/log" + "github.com/sigstore/sigstore/pkg/cryptoutils" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/metadata" +) + +type grpcCAServer struct { + fulciogrpc.UnimplementedCAServer + ct *ctclient.LogClient + ca certauth.CertificateAuthority +} + +func NewGRPCCAServer(ct *ctclient.LogClient, ca certauth.CertificateAuthority) fulciogrpc.CAServer { + return &grpcCAServer{ + ct: ct, + ca: ca, + } +} + +const ( + MetadataOIDCTokenKey = "oidcidentitytoken" +) + +func (g *grpcCAServer) CreateSigningCertificate(ctx context.Context, request *fulciogrpc.CreateSigningCertificateRequest) (*fulciogrpc.SigningCertificate, error) { + logger := log.ContextLogger(ctx) + + // OIDC token either is passed in gRPC field or was extracted from HTTP headers + token := "" + if request.Credentials != nil { + token = request.Credentials.GetOidcIdentityToken() + } + if token == "" { + if md, ok := metadata.FromIncomingContext(ctx); ok { + vals := md.Get(MetadataOIDCTokenKey) + if len(vals) == 1 { + token = vals[0] + } + } + } + + principal, err := authorize(ctx, token) + if err != nil { + return nil, handleFulcioGRPCError(ctx, codes.Unauthenticated, err, invalidCredentials) + } + + publicKeyBytes := request.PublicKey.Content + // try to unmarshal as PEM + publicKey, err := cryptoutils.UnmarshalPEMToPublicKey([]byte(publicKeyBytes)) + if err != nil { + // try to unmarshal as DER + logger.Debugf("error parsing public key as PEM, trying DER: %v", err.Error()) + publicKey, err = x509.ParsePKIXPublicKey([]byte(publicKeyBytes)) + if err != nil { + return nil, handleFulcioGRPCError(ctx, codes.InvalidArgument, err, invalidPublicKey) + } + } + + // Validate public key, checking for weak key parameters. + if err := cryptoutils.ValidatePubKey(publicKey); err != nil { + return nil, handleFulcioGRPCError(ctx, codes.InvalidArgument, err, insecurePublicKey) + } + + subject, err := challenges.ExtractSubject(ctx, principal, publicKey, request.ProofOfPossession) + if err != nil { + return nil, handleFulcioGRPCError(ctx, codes.InvalidArgument, err, invalidSignature) + } + + var csc *certauth.CodeSigningCertificate + var sctBytes []byte + result := &fulciogrpc.SigningCertificate{} + // 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) + if err != nil { + // if the error was due to invalid input in the request, return HTTP 400 + if _, ok := err.(certauth.ValidationError); ok { + return nil, handleFulcioGRPCError(ctx, codes.InvalidArgument, err, err.Error()) + } + // otherwise return a 500 error to reflect that it is a transient server issue that the client can't resolve + return nil, handleFulcioGRPCError(ctx, codes.Internal, err, genericCAError) + } + + // Submit to CTL + if g.ct != nil { + sct, err := g.ct.AddChain(ctx, ctl.BuildCTChain(csc.FinalCertificate, csc.FinalChain)) + if err != nil { + return nil, handleFulcioGRPCError(ctx, codes.Internal, err, failedToEnterCertInCTL) + } + // convert to AddChainResponse because Cosign expects this struct. + addChainResp, err := ctl.ToAddChainResponse(sct) + if err != nil { + return nil, handleFulcioGRPCError(ctx, codes.Internal, err, failedToMarshalSCT) + } + sctBytes, err = json.Marshal(addChainResp) + if err != nil { + return nil, handleFulcioGRPCError(ctx, codes.Internal, err, failedToMarshalSCT) + } + } else { + logger.Info("Skipping CT log upload.") + } + + finalPEM, err := csc.CertPEM() + if err != nil { + return nil, handleFulcioGRPCError(ctx, codes.Internal, err, failedToMarshalCert) + } + + finalChainPEM, err := csc.ChainPEM() + if err != nil { + return nil, handleFulcioGRPCError(ctx, codes.Internal, err, failedToMarshalCert) + } + + result.Certificate = &fulciogrpc.SigningCertificate_SignedCertificateDetachedSct{ + SignedCertificateDetachedSct: &fulciogrpc.SigningCertificateDetachedSCT{ + Chain: &fulciogrpc.CertificateChain{ + Certificates: append([]string{finalPEM}, finalChainPEM...), + }, + }, + } + if len(sctBytes) > 0 { + result.GetSignedCertificateDetachedSct().SignedCertificateTimestamp = sctBytes + } + } else { + precert, err := sctCa.CreatePrecertificate(ctx, subject) + if err != nil { + // if the error was due to invalid input in the request, return HTTP 400 + if _, ok := err.(certauth.ValidationError); ok { + return nil, handleFulcioGRPCError(ctx, codes.InvalidArgument, err, err.Error()) + } + // otherwise return a 500 error to reflect that it is a transient server issue that the client can't resolve + return nil, handleFulcioGRPCError(ctx, codes.Internal, err, genericCAError) + } + // submit precertificate and chain to CT log + sct, err := g.ct.AddPreChain(ctx, ctl.BuildCTChain(precert.PreCert, precert.CertChain)) + if err != nil { + return nil, handleFulcioGRPCError(ctx, codes.Internal, err, failedToEnterCertInCTL) + } + csc, err = sctCa.IssueFinalCertificate(ctx, precert, sct) + if err != nil { + return nil, handleFulcioGRPCError(ctx, codes.Internal, err, genericCAError) + } + + finalPEM, err := csc.CertPEM() + if err != nil { + return nil, handleFulcioGRPCError(ctx, codes.Internal, err, failedToMarshalCert) + } + + finalChainPEM, err := csc.ChainPEM() + if err != nil { + return nil, handleFulcioGRPCError(ctx, codes.Internal, err, failedToMarshalCert) + } + + result.Certificate = &fulciogrpc.SigningCertificate_SignedCertificateEmbeddedSct{ + SignedCertificateEmbeddedSct: &fulciogrpc.SigningCertificateEmbeddedSCT{ + Chain: &fulciogrpc.CertificateChain{ + Certificates: append([]string{finalPEM}, finalChainPEM...), + }, + }, + } + } + + metricNewEntries.Inc() + + return result, nil +} + +func (g *grpcCAServer) GetTrustBundle(ctx context.Context, _ *fulciogrpc.GetTrustBundleRequest) (*fulciogrpc.TrustBundle, error) { + logger := log.ContextLogger(ctx) + + root, err := g.ca.Root(ctx) + if err != nil { + logger.Error("Error retrieving root cert: ", err) + return nil, handleFulcioGRPCError(ctx, codes.Internal, err, genericCAError) + } + + return &fulciogrpc.TrustBundle{ + Chains: []*fulciogrpc.CertificateChain{{ + Certificates: []string{string(root)}, + }}, + }, nil +} + +func extractIssuer(token string) (string, error) { + parts := strings.Split(token, ".") + if len(parts) != 3 { + return "", fmt.Errorf("oidc: malformed jwt, expected 3 parts got %d", len(parts)) + } + raw, err := base64.RawURLEncoding.DecodeString(parts[1]) + if err != nil { + return "", fmt.Errorf("oidc: malformed jwt payload: %w", err) + } + var payload struct { + Issuer string `json:"iss"` + } + + if err := json.Unmarshal(raw, &payload); err != nil { + return "", fmt.Errorf("oidc: failed to unmarshal claims: %w", err) + } + return payload.Issuer, nil +} + +// We do this to bypass needing actual OIDC tokens for unit testing. +var authorize = actualAuthorize + +func actualAuthorize(ctx context.Context, token string) (*oidc.IDToken, error) { + issuer, err := extractIssuer(token) + if err != nil { + return nil, err + } + + verifier, ok := config.FromContext(ctx).GetVerifier(issuer) + if !ok { + return nil, fmt.Errorf("unsupported issuer: %s", issuer) + } + return verifier.Verify(ctx, token) +} diff --git a/pkg/api/api_test.go b/pkg/api/grpc_server_test.go similarity index 75% rename from pkg/api/api_test.go rename to pkg/api/grpc_server_test.go index 355974a05..9399e1b4f 100644 --- a/pkg/api/api_test.go +++ b/pkg/api/grpc_server_test.go @@ -29,6 +29,7 @@ import ( "encoding/pem" "errors" "fmt" + "net" "net/http" "net/http/httptest" "net/url" @@ -43,54 +44,107 @@ import ( "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/sigstore/pkg/cryptoutils" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + "google.golang.org/grpc/test/bufconn" "gopkg.in/square/go-jose.v2" "gopkg.in/square/go-jose.v2/jwt" ) const ( - expectedNoRootMessage = "{\"code\":500,\"message\":\"error communicating with CA backend\"}\n" + expectedNoRootMessage = "rpc error: code = Internal desc = error communicating with CA backend" + bufSize = 1024 * 1024 ) -func TestMissingRootFails(t *testing.T) { - h := New(nil, &FailingCertificateAuthority{}) - server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { - h.ServeHTTP(rw, r) - })) - t.Cleanup(server.Close) +var lis *bufconn.Listener + +func passFulcioConfigThruContext(cfg *config.FulcioConfig) grpc.UnaryServerInterceptor { + return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + // For each request, infuse context with our snapshot of the FulcioConfig. + // TODO(mattmoor): Consider periodically (every minute?) refreshing the ConfigMap + // from disk, so that we don't need to cycle pods to pick up config updates. + // Alternately we could take advantage of Knative's configmap watcher. + ctx = config.With(ctx, cfg) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + // Calls the inner handler + return handler(ctx, req) + } +} - // Create an API client that speaks to the API endpoint we created above. - u, err := url.Parse(server.URL) +func setupGRPCForTest(ctx context.Context, t *testing.T, cfg *config.FulcioConfig, ctl *ctclient.LogClient, ca ca.CertificateAuthority) (*grpc.Server, *grpc.ClientConn) { + t.Helper() + lis = bufconn.Listen(bufSize) + s := grpc.NewServer(grpc.UnaryInterceptor(passFulcioConfigThruContext(cfg))) + protobuf.RegisterCAServer(s, NewGRPCCAServer(ctl, ca)) + go func() { + if err := s.Serve(lis); err != nil && !errors.Is(err, grpc.ErrServerStopped) { + t.Errorf("Server exited with error: %v", err) + } + }() + + conn, err := grpc.DialContext(ctx, "bufnet", + grpc.WithContextDialer(bufDialer), grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { - t.Fatalf("url.Parse() = %v", err) + t.Fatal("could not create grpc connection", err) } + + return s, conn +} + +func bufDialer(ctx context.Context, _ string) (net.Conn, error) { + return lis.DialContext(ctx) +} + +func TestMissingGetTrustBundleFails(t *testing.T) { + ctx := context.Background() + server, conn := setupGRPCForTest(ctx, t, nil, nil, &FailingCertificateAuthority{}) + defer func() { + server.Stop() + conn.Close() + }() + + client := protobuf.NewCAClient(conn) + // Check that we get the CA root back as well. - _, err = NewClient(u).RootCert() + _, err := client.GetTrustBundle(ctx, &protobuf.GetTrustBundleRequest{}) if err == nil { - t.Fatal("RootCert did not fail", err) + t.Fatal("GetTrustBundle did not fail", err) } if err.Error() != expectedNoRootMessage { t.Errorf("got an unexpected error: %q wanted: %q", err, expectedNoRootMessage) } } -func TestRootCertSuccess(t *testing.T) { - eca, serverURL := createCA(&config.FulcioConfig{}, t) +func TestGetTrustBundleSuccess(t *testing.T) { + cfg := &config.FulcioConfig{} + ctClient, eca := createCA(cfg, t) + ctx := context.Background() + server, conn := setupGRPCForTest(ctx, t, cfg, ctClient, eca) + defer func() { + server.Stop() + conn.Close() + }() - // Create an API client that speaks to the API endpoint we created above. - u, err := url.Parse(serverURL) - if err != nil { - t.Fatalf("url.Parse() = %v", err) - } - client := NewClient(u) + client := protobuf.NewCAClient(conn) - root, err := client.RootCert() + root, err := client.GetTrustBundle(ctx, &protobuf.GetTrustBundleRequest{}) if err != nil { - t.Fatal("RootCert did not fail", err) + t.Fatal("GetTrustBundle failed", err) } - if len(root.ChainPEM) == 0 { + if len(root.Chains) == 0 { t.Fatal("got back empty chain") } - block, rest := pem.Decode(root.ChainPEM) + if len(root.Chains) != 1 { + t.Fatal("got back more than one chain") + } + if len(root.Chains[0].Certificates) != 1 { + t.Fatalf("expected 1 cert, found %d", len(root.Chains[0].Certificates)) + } + block, rest := pem.Decode([]byte(root.Chains[0].Certificates[0])) if block == nil { t.Fatal("did not find PEM data") } @@ -178,24 +232,30 @@ func TestAPIWithEmail(t *testing.T) { t.Fatalf("CompactSerialize() = %v", err) } - eca, serverURL := createCA(cfg, t) + ctClient, eca := createCA(cfg, t) + ctx := context.Background() + server, conn := setupGRPCForTest(ctx, t, cfg, ctClient, eca) + defer func() { + server.Stop() + conn.Close() + }() - // Create an API client that speaks to the API endpoint we created above. - u, err := url.Parse(serverURL) - if err != nil { - t.Fatalf("url.Parse() = %v", err) - } - client := NewClient(u) + client := protobuf.NewCAClient(conn) pubBytes, proof := generateKeyAndProof(c.Subject, t) // Hit the API to have it sign our certificate. - resp, err := client.SigningCert(CertificateRequest{ - PublicKey: Key{ + resp, err := client.CreateSigningCertificate(ctx, &protobuf.CreateSigningCertificateRequest{ + Credentials: &protobuf.Credentials{ + Credentials: &protobuf.Credentials_OidcIdentityToken{ + OidcIdentityToken: tok, + }, + }, + PublicKey: &protobuf.PublicKey{ Content: pubBytes, }, - SignedEmailAddress: proof, - }, tok) + ProofOfPossession: proof, + }) if err != nil { t.Fatalf("SigningCert() = %v", err) } @@ -261,24 +321,30 @@ func TestAPIWithUriSubject(t *testing.T) { t.Fatalf("CompactSerialize() = %v", err) } - eca, serverURL := createCA(cfg, t) + ctClient, eca := createCA(cfg, t) + ctx := context.Background() + server, conn := setupGRPCForTest(ctx, t, cfg, ctClient, eca) + defer func() { + server.Stop() + conn.Close() + }() - // Create an API client that speaks to the API endpoint we created above. - u, err := url.Parse(serverURL) - if err != nil { - t.Fatalf("url.Parse() = %v", err) - } - client := NewClient(u) + client := protobuf.NewCAClient(conn) pubBytes, proof := generateKeyAndProof(c.Subject, t) // Hit the API to have it sign our certificate. - resp, err := client.SigningCert(CertificateRequest{ - PublicKey: Key{ + resp, err := client.CreateSigningCertificate(ctx, &protobuf.CreateSigningCertificateRequest{ + Credentials: &protobuf.Credentials{ + Credentials: &protobuf.Credentials_OidcIdentityToken{ + OidcIdentityToken: tok, + }, + }, + PublicKey: &protobuf.PublicKey{ Content: pubBytes, }, - SignedEmailAddress: proof, - }, tok) + ProofOfPossession: proof, + }) if err != nil { t.Fatalf("SigningCert() = %v", err) } @@ -345,24 +411,30 @@ func TestAPIWithKubernetes(t *testing.T) { t.Fatalf("CompactSerialize() = %v", err) } - eca, serverURL := createCA(cfg, t) + ctClient, eca := createCA(cfg, t) + ctx := context.Background() + server, conn := setupGRPCForTest(ctx, t, cfg, ctClient, eca) + defer func() { + server.Stop() + conn.Close() + }() - // Create an API client that speaks to the API endpoint we created above. - u, err := url.Parse(serverURL) - if err != nil { - t.Fatalf("url.Parse() = %v", err) - } - client := NewClient(u) + client := protobuf.NewCAClient(conn) pubBytes, proof := generateKeyAndProof(k8sSubject, t) // Hit the API to have it sign our certificate. - resp, err := client.SigningCert(CertificateRequest{ - PublicKey: Key{ + resp, err := client.CreateSigningCertificate(ctx, &protobuf.CreateSigningCertificateRequest{ + Credentials: &protobuf.Credentials{ + Credentials: &protobuf.Credentials_OidcIdentityToken{ + OidcIdentityToken: tok, + }, + }, + PublicKey: &protobuf.PublicKey{ Content: pubBytes, }, - SignedEmailAddress: proof, - }, tok) + ProofOfPossession: proof, + }) if err != nil { t.Fatalf("SigningCert() = %v", err) } @@ -432,24 +504,30 @@ func TestAPIWithGitHub(t *testing.T) { t.Fatalf("CompactSerialize() = %v", err) } - eca, serverURL := createCA(cfg, t) + ctClient, eca := createCA(cfg, t) + ctx := context.Background() + server, conn := setupGRPCForTest(ctx, t, cfg, ctClient, eca) + defer func() { + server.Stop() + conn.Close() + }() - // Create an API client that speaks to the API endpoint we created above. - u, err := url.Parse(serverURL) - if err != nil { - t.Fatalf("url.Parse() = %v", err) - } - client := NewClient(u) + client := protobuf.NewCAClient(conn) pubBytes, proof := generateKeyAndProof(gitSubject, t) // Hit the API to have it sign our certificate. - resp, err := client.SigningCert(CertificateRequest{ - PublicKey: Key{ + resp, err := client.CreateSigningCertificate(ctx, &protobuf.CreateSigningCertificateRequest{ + Credentials: &protobuf.Credentials{ + Credentials: &protobuf.Credentials_OidcIdentityToken{ + OidcIdentityToken: tok, + }, + }, + PublicKey: &protobuf.PublicKey{ Content: pubBytes, }, - SignedEmailAddress: proof, - }, tok) + ProofOfPossession: proof, + }) if err != nil { t.Fatalf("SigningCert() = %v", err) } @@ -537,14 +615,15 @@ func TestAPIWithInsecurePublicKey(t *testing.T) { t.Fatalf("CompactSerialize() = %v", err) } - _, serverURL := createCA(cfg, t) + ctClient, eca := createCA(cfg, t) + ctx := context.Background() + server, conn := setupGRPCForTest(ctx, t, cfg, ctClient, eca) + defer func() { + server.Stop() + conn.Close() + }() - // Create an API client that speaks to the API endpoint we created above. - u, err := url.Parse(serverURL) - if err != nil { - t.Fatalf("url.Parse() = %v", err) - } - client := NewClient(u) + client := protobuf.NewCAClient(conn) priv, err := rsa.GenerateKey(rand.Reader, 1024) if err != nil { @@ -555,12 +634,18 @@ func TestAPIWithInsecurePublicKey(t *testing.T) { t.Fatalf("x509.MarshalPKIXPublicKey() = %v", err) } - _, err = client.SigningCert(CertificateRequest{ - PublicKey: Key{ - Content: pubBytes, + // Hit the API to have it sign our certificate. + _, err = client.CreateSigningCertificate(ctx, &protobuf.CreateSigningCertificateRequest{ + Credentials: &protobuf.Credentials{ + Credentials: &protobuf.Credentials_OidcIdentityToken{ + OidcIdentityToken: tok, + }, }, - SignedEmailAddress: []byte{}, - }, tok) + PublicKey: &protobuf.PublicKey{ + Content: string(cryptoutils.PEMEncode(cryptoutils.CertificatePEMType, pubBytes)), + }, + ProofOfPossession: []byte{}, + }) if err == nil || !strings.Contains(err.Error(), "The public key supplied in the request is insecure") { t.Fatalf("expected insecure public key error, got %v", err) } @@ -638,7 +723,7 @@ func fakeCTLogServer(t *testing.T) *httptest.Server { } // createCA initializes an ephemeral CA server and CT log server -func createCA(cfg *config.FulcioConfig, t *testing.T) (*ephemeralca.EphemeralCA, string) { +func createCA(cfg *config.FulcioConfig, t *testing.T) (*ctclient.LogClient, *ephemeralca.EphemeralCA) { // Stand up an ephemeral CA we can use for signing certificate requests. eca, err := ephemeralca.NewEphemeralCA() if err != nil { @@ -657,23 +742,12 @@ func createCA(cfg *config.FulcioConfig, t *testing.T) (*ephemeralca.EphemeralCA, if err != nil { t.Fatalf("error creating CT client: %v", err) } - h := New(ctClient, eca) - server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { - ctx := r.Context() - // For each request, infuse context with our snapshot of the FulcioConfig. - ctx = config.With(ctx, cfg) - - h.ServeHTTP(rw, r.WithContext(ctx)) - })) - t.Cleanup(server.Close) - t.Cleanup(ctlogServer.Close) - - return eca, server.URL + return ctClient, eca } // generateKeyAndProof creates a public key to be certified and creates a // signature for the OIDC token subject -func generateKeyAndProof(subject string, t *testing.T) ([]byte, []byte) { +func generateKeyAndProof(subject string, t *testing.T) (string, []byte) { priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { t.Fatalf("GenerateKey() = %v", err) @@ -687,7 +761,7 @@ func generateKeyAndProof(subject string, t *testing.T) ([]byte, []byte) { if err != nil { t.Fatalf("SignASN1() = %v", err) } - return pubBytes, proof + return string(cryptoutils.PEMEncode(cryptoutils.CertificatePEMType, pubBytes)), proof } // findCustomExtension searches a certificate's non-critical extensions by OID @@ -701,19 +775,26 @@ func findCustomExtension(cert *x509.Certificate, oid asn1.ObjectIdentifier) (pki } // verifyResponse validates common response expectations for each response field -func verifyResponse(resp *CertificateResponse, eca *ephemeralca.EphemeralCA, issuer string, t *testing.T) *x509.Certificate { +func verifyResponse(resp *protobuf.SigningCertificate, eca *ephemeralca.EphemeralCA, issuer string, t *testing.T) *x509.Certificate { // Expect SCT - if string(resp.SCT) == "" { + if resp.GetSignedCertificateDetachedSct() != nil && string(resp.GetSignedCertificateDetachedSct().SignedCertificateTimestamp) == "" { t.Fatal("unexpected empty SCT in response") } + var chain *protobuf.CertificateChain + if resp.GetSignedCertificateDetachedSct() != nil { + chain = resp.GetSignedCertificateDetachedSct().Chain + } else { + chain = resp.GetSignedCertificateEmbeddedSct().Chain + } + // Expect root certficate in resp.ChainPEM - if len(resp.ChainPEM) == 0 { + if len(chain.Certificates) == 0 { t.Fatal("unexpected empty chain in response") } // Expect root cert matches the server's configured root - block, rest := pem.Decode(resp.ChainPEM) + block, rest := pem.Decode([]byte(chain.Certificates[1])) if block == nil { t.Fatal("missing PEM data") } @@ -733,7 +814,8 @@ func verifyResponse(resp *CertificateResponse, eca *ephemeralca.EphemeralCA, iss } // Expect leaf certificate values - block, rest = pem.Decode(resp.CertPEM) + //TODO: if there are intermediates added, this logic needs to change + block, rest = pem.Decode([]byte(chain.Certificates[0])) if len(rest) != 0 { t.Fatal("expected only one leaf certificate in PEM block") } diff --git a/pkg/api/legacy_server.go b/pkg/api/legacy_server.go new file mode 100644 index 000000000..5a27b1ca7 --- /dev/null +++ b/pkg/api/legacy_server.go @@ -0,0 +1,137 @@ +// Copyright 2022 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 api + +import ( + "context" + "encoding/base64" + "strings" + + empty "github.com/golang/protobuf/ptypes/empty" + "github.com/pkg/errors" + fulciogrpc "github.com/sigstore/fulcio/pkg/generated/protobuf" + "github.com/sigstore/fulcio/pkg/generated/protobuf/legacy" + "google.golang.org/genproto/googleapis/api/httpbody" + "google.golang.org/grpc" + "google.golang.org/grpc/metadata" +) + +const ( + PEMCertificateChain = "application/pem-certificate-chain" + SCTMetadataKey = "x-sct" + HTTPResponseCodeMetadataKey = "x-http-code" +) + +type legacyGRPCCAServer struct { + legacy.UnimplementedCAServer + v2Server fulciogrpc.CAServer +} + +func NewLegacyGRPCCAServer(v2Server fulciogrpc.CAServer) legacy.CAServer { + return &legacyGRPCCAServer{ + v2Server: v2Server, + } +} + +func (l *legacyGRPCCAServer) CreateSigningCertificate(ctx context.Context, request *legacy.CreateSigningCertificateRequest) (*httpbody.HttpBody, error) { + // OIDC token either is passed in gRPC field or was extracted from HTTP headers + token := "" + if md, ok := metadata.FromIncomingContext(ctx); ok { + vals := md.Get(MetadataOIDCTokenKey) + if len(vals) == 1 { + token = vals[0] + } + } + + creds := fulciogrpc.Credentials{ + Credentials: &fulciogrpc.Credentials_OidcIdentityToken{ + OidcIdentityToken: token, + }, + } + + // create new CA request mapping fields from legacy to actual + algorithmEnum, ok := fulciogrpc.PublicKeyAlgorithm_value[strings.ToUpper(request.PublicKey.Algorithm)] //lint:ignore SA1019 this is valid because we're converting from v1beta to v1 API + if !ok { + algorithmEnum = int32(fulciogrpc.PublicKeyAlgorithm_PUBLIC_KEY_ALGORITHM_UNSPECIFIED) + } + + v2Request := fulciogrpc.CreateSigningCertificateRequest{ + Credentials: &creds, + PublicKey: &fulciogrpc.PublicKey{ + Algorithm: fulciogrpc.PublicKeyAlgorithm(algorithmEnum), + Content: string(request.PublicKey.Content), //lint:ignore SA1019 this is valid because we're converting from v1beta to v1 API + }, + ProofOfPossession: request.SignedEmailAddress, //lint:ignore SA1019 this is valid because we're converting from v1beta to v1 API + } + + v2Response, err := l.v2Server.CreateSigningCertificate(ctx, &v2Request) + if err != nil { + return nil, errors.Wrap(err, "legacy handler") + } + + // we need to return a HTTP 201 Created response code to be backward compliant + if err = grpc.SetHeader(ctx, metadata.Pairs(HTTPResponseCodeMetadataKey, "201")); err != nil { + return nil, errors.Wrap(err, "legacy handler") + } + + detachedResponse := v2Response.GetSignedCertificateDetachedSct() + if detachedResponse != nil && len(detachedResponse.SignedCertificateTimestamp) > 0 { + // the SCT for the certificate needs to be returned in a HTTP response header + sctString := base64.StdEncoding.EncodeToString(detachedResponse.SignedCertificateTimestamp) + if sctString != "" { + if err := grpc.SetHeader(ctx, metadata.Pairs(SCTMetadataKey, sctString)); err != nil { + return nil, errors.Wrap(err, "legacy handler") + } + } + } + var chain *fulciogrpc.CertificateChain + if detachedResponse != nil { + chain = detachedResponse.Chain + } else { + chain = v2Response.GetSignedCertificateEmbeddedSct().Chain + } + + var concatCerts strings.Builder + for _, cert := range chain.Certificates { + concatCerts.WriteString(cert) + concatCerts.WriteRune('\n') + } + + return &httpbody.HttpBody{ + ContentType: PEMCertificateChain, + Data: []byte(string(strings.TrimSpace(concatCerts.String()))), + }, nil +} + +func (l *legacyGRPCCAServer) GetRootCertificate(ctx context.Context, _ *empty.Empty) (*httpbody.HttpBody, error) { + v2Response, err := l.v2Server.GetTrustBundle(ctx, &fulciogrpc.GetTrustBundleRequest{}) + if err != nil { + return nil, errors.Wrap(err, "legacy handler") + } + + var concatCerts strings.Builder + for _, chain := range v2Response.Chains { + for _, cert := range chain.Certificates { + concatCerts.WriteString(cert) + concatCerts.WriteRune('\n') + } + } + + return &httpbody.HttpBody{ + ContentType: PEMCertificateChain, + Data: []byte(strings.TrimSpace(concatCerts.String())), + }, nil +} diff --git a/pkg/api/options_test.go b/pkg/api/options_test.go deleted file mode 100644 index a186665f8..000000000 --- a/pkg/api/options_test.go +++ /dev/null @@ -1,122 +0,0 @@ -// 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 api - -import ( - "net/http" - "net/url" - "testing" - "time" - - "github.com/google/go-cmp/cmp" -) - -func TestMakeOptions(t *testing.T) { - tests := []struct { - desc string - - opts []ClientOption - want *clientOptions - }{{ - desc: "no opts", - want: &clientOptions{}, - }, { - desc: "WithUserAgent", - opts: []ClientOption{WithUserAgent("test user agent")}, - want: &clientOptions{UserAgent: "test user agent"}, - }, { - desc: "WithTimeout", - opts: []ClientOption{WithTimeout(7 * time.Second)}, - want: &clientOptions{Timeout: 7 * time.Second}, - }} - for _, tc := range tests { - t.Run(tc.desc, func(t *testing.T) { - got := makeOptions(tc.opts...) - if d := cmp.Diff(tc.want, got); d != "" { - t.Errorf("makeOptions() returned unexpected result (-want +got): %s", d) - } - }) - } -} - -type mockRoundTripper struct { - gotReqs []*http.Request - - resp *http.Response - err error -} - -// RoundTrip implements `http.RoundTripper` -func (m *mockRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { - m.gotReqs = append(m.gotReqs, req) - return m.resp, m.err -} - -func TestCreateRoundTripper(t *testing.T) { - t.Run("always returns non-nil", func(t *testing.T) { - got := createRoundTripper(nil, &clientOptions{}) - if got == nil { - t.Errorf("createRoundTripper() should never return a nil `http.RoundTripper`") - } - }) - - testReq, err := http.NewRequest(http.MethodGet, "http://www.example.com/test", nil) - if err != nil { - t.Fatalf("http.NewRequest() failed: %v", err) - } - - testResp := &http.Response{ - Status: "OK", - StatusCode: http.StatusOK, - Request: testReq, - } - - expectedUserAgent := "test UserAgent" - - m := &mockRoundTripper{} - rt := createRoundTripper(m, &clientOptions{ - UserAgent: expectedUserAgent, - }) - m.resp = testResp - - gotResp, err := rt.RoundTrip(testReq) - if err != nil { - t.Errorf("RoundTrip() returned error: %v", err) - } - if len(m.gotReqs) < 1 { - t.Fatalf("inner RoundTripper.RoundTrip() was not called") - } - gotReq := m.gotReqs[0] - gotReqUserAgent := gotReq.UserAgent() - if gotReqUserAgent != expectedUserAgent { - t.Errorf("rt.RoundTrip() did not set the User-Agent properly. Wanted: %q, got: %q", expectedUserAgent, gotReqUserAgent) - } - - if testResp != gotResp { - t.Errorf("roundTripper.RoundTrip() should have returned exactly the response of the inner RoundTripper. Wanted %v, got %v", testResp, gotResp) - } -} - -func TestSanity(t *testing.T) { - testURL, err := url.Parse(SigstorePublicServerURL) - if err != nil { - t.Fatalf("url.Parse(SigstorePublicServerURL) returned error: %v", err) - } - - got := NewClient(testURL, WithUserAgent("sanity test"), WithTimeout(11*time.Second)) - if got == nil { - t.Fatalf(`New(testURL, WithUserAgent("sanity test")) returned nil`) - } -} diff --git a/pkg/api/version.go b/pkg/api/version.go new file mode 100644 index 000000000..fff0e9849 --- /dev/null +++ b/pkg/api/version.go @@ -0,0 +1,91 @@ +// Copyright 2022 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 api + +import ( + "encoding/json" + "fmt" + "runtime" + "strings" + "text/tabwriter" +) + +// Base version information. +// +// This is the fallback data used when version information from git is not +// provided via go ldflags (e.g. via Makefile). +var ( + // Output of "git describe". The prerequisite is that the branch should be + // tagged using the correct versioning strategy. + gitVersion = "unknown" + // SHA1 from git, output of $(git rev-parse HEAD) + gitCommit = "unknown" + // State of git tree, either "clean" or "dirty" + gitTreeState = "unknown" + // Build date in ISO8601 format, output of $(date -u +'%Y-%m-%dT%H:%M:%SZ') + buildDate = "unknown" +) + +type Info struct { + GitVersion string + GitCommit string + GitTreeState string + BuildDate string + GoVersion string + Compiler string + Platform string +} + +func VersionInfo() Info { + // These variables typically come from -ldflags settings and in + // their absence fallback to the global defaults set above. + return Info{ + GitVersion: gitVersion, + GitCommit: gitCommit, + GitTreeState: gitTreeState, + BuildDate: buildDate, + GoVersion: runtime.Version(), + Compiler: runtime.Compiler, + Platform: fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH), + } +} + +// String returns the string representation of the version info +func (i *Info) String() string { + b := strings.Builder{} + w := tabwriter.NewWriter(&b, 0, 0, 2, ' ', 0) + + fmt.Fprintf(w, "GitVersion:\t%s\n", i.GitVersion) + fmt.Fprintf(w, "GitCommit:\t%s\n", i.GitCommit) + fmt.Fprintf(w, "GitTreeState:\t%s\n", i.GitTreeState) + fmt.Fprintf(w, "BuildDate:\t%s\n", i.BuildDate) + fmt.Fprintf(w, "GoVersion:\t%s\n", i.GoVersion) + fmt.Fprintf(w, "Compiler:\t%s\n", i.Compiler) + fmt.Fprintf(w, "Platform:\t%s\n", i.Platform) + + w.Flush() // #nosec + return b.String() +} + +// JSONString returns the JSON representation of the version info +func (i *Info) JSONString() (string, error) { + b, err := json.MarshalIndent(i, "", " ") + if err != nil { + return "", err + } + + return string(b), nil +} diff --git a/pkg/ca/interface.go b/pkg/ca/interface.go index 8d46bb460..f1fa13532 100644 --- a/pkg/ca/interface.go +++ b/pkg/ca/interface.go @@ -16,7 +16,6 @@ package ca import ( - "bytes" "context" "crypto" "crypto/x509" @@ -31,8 +30,8 @@ type CodeSigningCertificate struct { Subject *challenges.ChallengeResult FinalCertificate *x509.Certificate FinalChain []*x509.Certificate - finalPEM []byte - finalChainPEM []byte + finalPEM string + finalChainPEM []string } // CodeSigningPreCertificate holds a precertificate and chain. @@ -58,7 +57,7 @@ func CreateCSCFromPEM(subject *challenges.ChallengeResult, cert string, chain [] if err != nil { return nil, err } - c.finalPEM = []byte(cert) + c.finalPEM = strings.TrimSpace(cert) c.FinalCertificate = finalCert[0] // convert to X509 and store both formats @@ -68,7 +67,9 @@ func CreateCSCFromPEM(subject *challenges.ChallengeResult, cert string, chain [] if err != nil { return nil, err } - c.finalChainPEM = chainBytes + for _, cert := range chain { + c.finalChainPEM = append(c.finalChainPEM, strings.TrimSpace(cert)) + } } return c, nil } @@ -79,7 +80,7 @@ func CreateCSCFromDER(subject *challenges.ChallengeResult, cert []byte, chain [] } // convert to X509 and store both formats - c.finalPEM = cryptoutils.PEMEncode(cryptoutils.CertificatePEMType, cert) + c.finalPEM = strings.TrimSpace(string(cryptoutils.PEMEncode(cryptoutils.CertificatePEMType, cert))) c.FinalCertificate, err = x509.ParseCertificate(cert) if err != nil { return nil, err @@ -90,28 +91,30 @@ func CreateCSCFromDER(subject *challenges.ChallengeResult, cert []byte, chain [] if err != nil { return nil, err } - buf := bytes.Buffer{} for _, chainCert := range c.FinalChain { - buf.Write(cryptoutils.PEMEncode(cryptoutils.CertificatePEMType, chainCert.Raw)) + c.finalChainPEM = append(c.finalChainPEM, strings.TrimSpace(string(cryptoutils.PEMEncode(cryptoutils.CertificatePEMType, chainCert.Raw)))) } - c.finalChainPEM = buf.Bytes() return c, nil } -func (c *CodeSigningCertificate) CertPEM() ([]byte, error) { +func (c *CodeSigningCertificate) CertPEM() (string, error) { var err error - if c.finalPEM == nil { - c.finalPEM, err = cryptoutils.MarshalCertificateToPEM(c.FinalCertificate) + if c.finalPEM == "" { + finalPemBytes, err := cryptoutils.MarshalCertificateToPEM(c.FinalCertificate) + if err == nil { + c.finalPEM = strings.TrimSpace(string(finalPemBytes)) + } } return c.finalPEM, err } -func (c *CodeSigningCertificate) ChainPEM() ([]byte, error) { - var err error +func (c *CodeSigningCertificate) ChainPEM() ([]string, error) { if c.finalChainPEM == nil && len(c.FinalChain) > 0 { - c.finalChainPEM, err = cryptoutils.MarshalCertificatesToPEM(c.FinalChain) + for _, chainCert := range c.FinalChain { + c.finalChainPEM = append(c.finalChainPEM, strings.TrimSpace(string(cryptoutils.PEMEncode(cryptoutils.CertificatePEMType, chainCert.Raw)))) + } } - return c.finalChainPEM, err + return c.finalChainPEM, nil } // CertificateAuthority implements certificate creation with a detached SCT and fetching the CA trust bundle. diff --git a/pkg/challenges/challenges.go b/pkg/challenges/challenges.go index 5ea52b2db..ae530773c 100644 --- a/pkg/challenges/challenges.go +++ b/pkg/challenges/challenges.go @@ -442,3 +442,26 @@ 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, challenge []byte) (*ChallengeResult, 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) + } + switch iss.Type { + case config.IssuerTypeEmail: + return Email(ctx, tok, publicKey, challenge) + case config.IssuerTypeSpiffe: + return Spiffe(ctx, tok, publicKey, challenge) + case config.IssuerTypeGithubWorkflow: + return GithubWorkflow(ctx, tok, publicKey, challenge) + case config.IssuerTypeKubernetes: + return Kubernetes(ctx, tok, publicKey, challenge) + case config.IssuerTypeURI: + return URI(ctx, tok, publicKey, challenge) + case config.IssuerTypeUsername: + return Username(ctx, tok, publicKey, challenge) + default: + return nil, fmt.Errorf("unsupported issuer: %s", iss.Type) + } +} diff --git a/pkg/generated/protobuf/fulcio.pb.go b/pkg/generated/protobuf/fulcio.pb.go new file mode 100644 index 000000000..36a43936d --- /dev/null +++ b/pkg/generated/protobuf/fulcio.pb.go @@ -0,0 +1,927 @@ +// +// Copyright 2022 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. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.27.1 +// protoc v3.12.4 +// source: fulcio.proto + +package protobuf + +import ( + _ "google.golang.org/genproto/googleapis/api/annotations" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type PublicKeyAlgorithm int32 + +const ( + PublicKeyAlgorithm_PUBLIC_KEY_ALGORITHM_UNSPECIFIED PublicKeyAlgorithm = 0 + PublicKeyAlgorithm_RSA_PSS PublicKeyAlgorithm = 1 + PublicKeyAlgorithm_ECDSA PublicKeyAlgorithm = 2 + PublicKeyAlgorithm_ED25519 PublicKeyAlgorithm = 3 +) + +// Enum value maps for PublicKeyAlgorithm. +var ( + PublicKeyAlgorithm_name = map[int32]string{ + 0: "PUBLIC_KEY_ALGORITHM_UNSPECIFIED", + 1: "RSA_PSS", + 2: "ECDSA", + 3: "ED25519", + } + PublicKeyAlgorithm_value = map[string]int32{ + "PUBLIC_KEY_ALGORITHM_UNSPECIFIED": 0, + "RSA_PSS": 1, + "ECDSA": 2, + "ED25519": 3, + } +) + +func (x PublicKeyAlgorithm) Enum() *PublicKeyAlgorithm { + p := new(PublicKeyAlgorithm) + *p = x + return p +} + +func (x PublicKeyAlgorithm) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (PublicKeyAlgorithm) Descriptor() protoreflect.EnumDescriptor { + return file_fulcio_proto_enumTypes[0].Descriptor() +} + +func (PublicKeyAlgorithm) Type() protoreflect.EnumType { + return &file_fulcio_proto_enumTypes[0] +} + +func (x PublicKeyAlgorithm) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use PublicKeyAlgorithm.Descriptor instead. +func (PublicKeyAlgorithm) EnumDescriptor() ([]byte, []int) { + return file_fulcio_proto_rawDescGZIP(), []int{0} +} + +type CreateSigningCertificateRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // + // Identity information about who possesses the private / public key pair presented + Credentials *Credentials `protobuf:"bytes,1,opt,name=credentials,proto3" json:"credentials,omitempty"` + // + // The public key to be stored in the requested certificate + PublicKey *PublicKey `protobuf:"bytes,2,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` + // + // Proof that the client possesses the private key; must be verifiable by provided public key + // + // This is a currently a signature over the `sub` claim from the OIDC identity token + ProofOfPossession []byte `protobuf:"bytes,3,opt,name=proof_of_possession,json=proofOfPossession,proto3" json:"proof_of_possession,omitempty"` +} + +func (x *CreateSigningCertificateRequest) Reset() { + *x = CreateSigningCertificateRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_fulcio_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CreateSigningCertificateRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateSigningCertificateRequest) ProtoMessage() {} + +func (x *CreateSigningCertificateRequest) ProtoReflect() protoreflect.Message { + mi := &file_fulcio_proto_msgTypes[0] + 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 CreateSigningCertificateRequest.ProtoReflect.Descriptor instead. +func (*CreateSigningCertificateRequest) Descriptor() ([]byte, []int) { + return file_fulcio_proto_rawDescGZIP(), []int{0} +} + +func (x *CreateSigningCertificateRequest) GetCredentials() *Credentials { + if x != nil { + return x.Credentials + } + return nil +} + +func (x *CreateSigningCertificateRequest) GetPublicKey() *PublicKey { + if x != nil { + return x.PublicKey + } + return nil +} + +func (x *CreateSigningCertificateRequest) GetProofOfPossession() []byte { + if x != nil { + return x.ProofOfPossession + } + return nil +} + +type Credentials struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Credentials: + // *Credentials_OidcIdentityToken + Credentials isCredentials_Credentials `protobuf_oneof:"credentials"` +} + +func (x *Credentials) Reset() { + *x = Credentials{} + if protoimpl.UnsafeEnabled { + mi := &file_fulcio_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Credentials) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Credentials) ProtoMessage() {} + +func (x *Credentials) ProtoReflect() protoreflect.Message { + mi := &file_fulcio_proto_msgTypes[1] + 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 Credentials.ProtoReflect.Descriptor instead. +func (*Credentials) Descriptor() ([]byte, []int) { + return file_fulcio_proto_rawDescGZIP(), []int{1} +} + +func (m *Credentials) GetCredentials() isCredentials_Credentials { + if m != nil { + return m.Credentials + } + return nil +} + +func (x *Credentials) GetOidcIdentityToken() string { + if x, ok := x.GetCredentials().(*Credentials_OidcIdentityToken); ok { + return x.OidcIdentityToken + } + return "" +} + +type isCredentials_Credentials interface { + isCredentials_Credentials() +} + +type Credentials_OidcIdentityToken struct { + // + // The OIDC token that identifies the caller + OidcIdentityToken string `protobuf:"bytes,1,opt,name=oidc_identity_token,json=oidcIdentityToken,proto3,oneof"` +} + +func (*Credentials_OidcIdentityToken) isCredentials_Credentials() {} + +type PublicKey struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // + // The cryptographic algorithm to use with the key material + Algorithm PublicKeyAlgorithm `protobuf:"varint,1,opt,name=algorithm,proto3,enum=dev.sigstore.fulcio.v2.PublicKeyAlgorithm" json:"algorithm,omitempty"` + // + // PEM encoded public key + Content string `protobuf:"bytes,2,opt,name=content,proto3" json:"content,omitempty"` +} + +func (x *PublicKey) Reset() { + *x = PublicKey{} + if protoimpl.UnsafeEnabled { + mi := &file_fulcio_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PublicKey) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PublicKey) ProtoMessage() {} + +func (x *PublicKey) ProtoReflect() protoreflect.Message { + mi := &file_fulcio_proto_msgTypes[2] + 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 PublicKey.ProtoReflect.Descriptor instead. +func (*PublicKey) Descriptor() ([]byte, []int) { + return file_fulcio_proto_rawDescGZIP(), []int{2} +} + +func (x *PublicKey) GetAlgorithm() PublicKeyAlgorithm { + if x != nil { + return x.Algorithm + } + return PublicKeyAlgorithm_PUBLIC_KEY_ALGORITHM_UNSPECIFIED +} + +func (x *PublicKey) GetContent() string { + if x != nil { + return x.Content + } + return "" +} + +type SigningCertificate struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Certificate: + // *SigningCertificate_SignedCertificateDetachedSct + // *SigningCertificate_SignedCertificateEmbeddedSct + Certificate isSigningCertificate_Certificate `protobuf_oneof:"certificate"` +} + +func (x *SigningCertificate) Reset() { + *x = SigningCertificate{} + if protoimpl.UnsafeEnabled { + mi := &file_fulcio_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SigningCertificate) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SigningCertificate) ProtoMessage() {} + +func (x *SigningCertificate) ProtoReflect() protoreflect.Message { + mi := &file_fulcio_proto_msgTypes[3] + 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 SigningCertificate.ProtoReflect.Descriptor instead. +func (*SigningCertificate) Descriptor() ([]byte, []int) { + return file_fulcio_proto_rawDescGZIP(), []int{3} +} + +func (m *SigningCertificate) GetCertificate() isSigningCertificate_Certificate { + if m != nil { + return m.Certificate + } + return nil +} + +func (x *SigningCertificate) GetSignedCertificateDetachedSct() *SigningCertificateDetachedSCT { + if x, ok := x.GetCertificate().(*SigningCertificate_SignedCertificateDetachedSct); ok { + return x.SignedCertificateDetachedSct + } + return nil +} + +func (x *SigningCertificate) GetSignedCertificateEmbeddedSct() *SigningCertificateEmbeddedSCT { + if x, ok := x.GetCertificate().(*SigningCertificate_SignedCertificateEmbeddedSct); ok { + return x.SignedCertificateEmbeddedSct + } + return nil +} + +type isSigningCertificate_Certificate interface { + isSigningCertificate_Certificate() +} + +type SigningCertificate_SignedCertificateDetachedSct struct { + SignedCertificateDetachedSct *SigningCertificateDetachedSCT `protobuf:"bytes,1,opt,name=signed_certificate_detached_sct,json=signedCertificateDetachedSct,proto3,oneof"` +} + +type SigningCertificate_SignedCertificateEmbeddedSct struct { + SignedCertificateEmbeddedSct *SigningCertificateEmbeddedSCT `protobuf:"bytes,2,opt,name=signed_certificate_embedded_sct,json=signedCertificateEmbeddedSct,proto3,oneof"` +} + +func (*SigningCertificate_SignedCertificateDetachedSct) isSigningCertificate_Certificate() {} + +func (*SigningCertificate_SignedCertificateEmbeddedSct) isSigningCertificate_Certificate() {} + +// (-- api-linter: core::0142::time-field-type=disabled +// aip.dev/not-precedent: SCT is defined in RFC6962 and we keep the name consistent for easier understanding. --) +type SigningCertificateDetachedSCT struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // + // The certificate chain serialized with the leaf certificate first, followed + // by all intermediate certificates (if present), finishing with the root certificate. + // + // All values are PEM-encoded certificates. + Chain *CertificateChain `protobuf:"bytes,1,opt,name=chain,proto3" json:"chain,omitempty"` + // + // The signed certificate timestamp is a promise for including the certificate in + // a certificate transparency log. It can be "stapled" to verify the inclusion of + // a certificate in the log in an offline fashion. + SignedCertificateTimestamp []byte `protobuf:"bytes,2,opt,name=signed_certificate_timestamp,json=signedCertificateTimestamp,proto3" json:"signed_certificate_timestamp,omitempty"` +} + +func (x *SigningCertificateDetachedSCT) Reset() { + *x = SigningCertificateDetachedSCT{} + if protoimpl.UnsafeEnabled { + mi := &file_fulcio_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SigningCertificateDetachedSCT) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SigningCertificateDetachedSCT) ProtoMessage() {} + +func (x *SigningCertificateDetachedSCT) ProtoReflect() protoreflect.Message { + mi := &file_fulcio_proto_msgTypes[4] + 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 SigningCertificateDetachedSCT.ProtoReflect.Descriptor instead. +func (*SigningCertificateDetachedSCT) Descriptor() ([]byte, []int) { + return file_fulcio_proto_rawDescGZIP(), []int{4} +} + +func (x *SigningCertificateDetachedSCT) GetChain() *CertificateChain { + if x != nil { + return x.Chain + } + return nil +} + +func (x *SigningCertificateDetachedSCT) GetSignedCertificateTimestamp() []byte { + if x != nil { + return x.SignedCertificateTimestamp + } + return nil +} + +type SigningCertificateEmbeddedSCT struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // + // The certificate chain serialized with the leaf certificate first, followed + // by all intermediate certificates (if present), finishing with the root certificate. + // + // All values are PEM-encoded certificates. + Chain *CertificateChain `protobuf:"bytes,1,opt,name=chain,proto3" json:"chain,omitempty"` +} + +func (x *SigningCertificateEmbeddedSCT) Reset() { + *x = SigningCertificateEmbeddedSCT{} + if protoimpl.UnsafeEnabled { + mi := &file_fulcio_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SigningCertificateEmbeddedSCT) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SigningCertificateEmbeddedSCT) ProtoMessage() {} + +func (x *SigningCertificateEmbeddedSCT) ProtoReflect() protoreflect.Message { + mi := &file_fulcio_proto_msgTypes[5] + 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 SigningCertificateEmbeddedSCT.ProtoReflect.Descriptor instead. +func (*SigningCertificateEmbeddedSCT) Descriptor() ([]byte, []int) { + return file_fulcio_proto_rawDescGZIP(), []int{5} +} + +func (x *SigningCertificateEmbeddedSCT) GetChain() *CertificateChain { + if x != nil { + return x.Chain + } + return nil +} + +// This is created for forward compatibility in case we want to add fields to the TrustBundle service in the future +type GetTrustBundleRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetTrustBundleRequest) Reset() { + *x = GetTrustBundleRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_fulcio_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetTrustBundleRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTrustBundleRequest) ProtoMessage() {} + +func (x *GetTrustBundleRequest) ProtoReflect() protoreflect.Message { + mi := &file_fulcio_proto_msgTypes[6] + 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 GetTrustBundleRequest.ProtoReflect.Descriptor instead. +func (*GetTrustBundleRequest) Descriptor() ([]byte, []int) { + return file_fulcio_proto_rawDescGZIP(), []int{6} +} + +type TrustBundle struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // + // The set of PEM-encoded certificate chains for this Fulcio instance; each chain will start with any + // intermediate certificates (if present), finishing with the root certificate. + Chains []*CertificateChain `protobuf:"bytes,1,rep,name=chains,proto3" json:"chains,omitempty"` +} + +func (x *TrustBundle) Reset() { + *x = TrustBundle{} + if protoimpl.UnsafeEnabled { + mi := &file_fulcio_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TrustBundle) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TrustBundle) ProtoMessage() {} + +func (x *TrustBundle) ProtoReflect() protoreflect.Message { + mi := &file_fulcio_proto_msgTypes[7] + 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 TrustBundle.ProtoReflect.Descriptor instead. +func (*TrustBundle) Descriptor() ([]byte, []int) { + return file_fulcio_proto_rawDescGZIP(), []int{7} +} + +func (x *TrustBundle) GetChains() []*CertificateChain { + if x != nil { + return x.Chains + } + return nil +} + +type CertificateChain struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // + // The PEM-encoded certificate chain, ordered from leaf to intermediate to root as applicable. + Certificates []string `protobuf:"bytes,1,rep,name=certificates,proto3" json:"certificates,omitempty"` +} + +func (x *CertificateChain) Reset() { + *x = CertificateChain{} + if protoimpl.UnsafeEnabled { + mi := &file_fulcio_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CertificateChain) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CertificateChain) ProtoMessage() {} + +func (x *CertificateChain) ProtoReflect() protoreflect.Message { + mi := &file_fulcio_proto_msgTypes[8] + 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 CertificateChain.ProtoReflect.Descriptor instead. +func (*CertificateChain) Descriptor() ([]byte, []int) { + return file_fulcio_proto_rawDescGZIP(), []int{8} +} + +func (x *CertificateChain) GetCertificates() []string { + if x != nil { + return x.Certificates + } + return nil +} + +var File_fulcio_proto protoreflect.FileDescriptor + +var file_fulcio_proto_rawDesc = []byte{ + 0x0a, 0x0c, 0x66, 0x75, 0x6c, 0x63, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x16, + 0x64, 0x65, 0x76, 0x2e, 0x73, 0x69, 0x67, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x66, 0x75, 0x6c, + 0x63, 0x69, 0x6f, 0x2e, 0x76, 0x32, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, + 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, + 0x2f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xe9, 0x01, 0x0a, 0x1f, 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, 0x12, 0x4a, 0x0a, 0x0b, 0x63, 0x72, 0x65, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 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, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x61, 0x6c, 0x73, 0x42, 0x03, 0xe0, 0x41, 0x02, 0x52, 0x0b, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, + 0x74, 0x69, 0x61, 0x6c, 0x73, 0x12, 0x45, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, + 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x64, 0x65, 0x76, 0x2e, + 0x73, 0x69, 0x67, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x66, 0x75, 0x6c, 0x63, 0x69, 0x6f, 0x2e, + 0x76, 0x32, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x42, 0x03, 0xe0, 0x41, + 0x02, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x33, 0x0a, 0x13, + 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x6f, 0x66, 0x5f, 0x70, 0x6f, 0x73, 0x73, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x03, 0xe0, 0x41, 0x02, 0x52, 0x11, + 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x4f, 0x66, 0x50, 0x6f, 0x73, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x22, 0x4e, 0x0a, 0x0b, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, + 0x12, 0x30, 0x0a, 0x13, 0x6f, 0x69, 0x64, 0x63, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, + 0x79, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, + 0x11, 0x6f, 0x69, 0x64, 0x63, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x54, 0x6f, 0x6b, + 0x65, 0x6e, 0x42, 0x0d, 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, + 0x73, 0x22, 0x74, 0x0a, 0x09, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x48, + 0x0a, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0e, 0x32, 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, 0x50, 0x75, 0x62, 0x6c, 0x69, + 0x63, 0x4b, 0x65, 0x79, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x52, 0x09, 0x61, + 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x1d, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x03, 0xe0, 0x41, 0x02, 0x52, 0x07, + 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0xa3, 0x02, 0x0a, 0x12, 0x53, 0x69, 0x67, 0x6e, + 0x69, 0x6e, 0x67, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x7e, + 0x0a, 0x1f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x73, 0x63, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 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, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x53, 0x43, 0x54, 0x48, 0x00, + 0x52, 0x1c, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x65, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x53, 0x63, 0x74, 0x12, 0x7e, + 0x0a, 0x1f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x73, 0x63, + 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 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, 0x45, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x53, 0x43, 0x54, 0x48, 0x00, + 0x52, 0x1c, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x65, 0x45, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x53, 0x63, 0x74, 0x42, 0x0d, + 0x0a, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x22, 0xa1, 0x01, + 0x0a, 0x1d, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x53, 0x43, 0x54, 0x12, + 0x3e, 0x0a, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, + 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, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x52, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x12, + 0x40, 0x0a, 0x1c, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x1a, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, + 0x70, 0x22, 0x5f, 0x0a, 0x1d, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x45, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x53, + 0x43, 0x54, 0x12, 0x3e, 0x0a, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x28, 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, 0x65, 0x72, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x52, 0x05, 0x63, 0x68, 0x61, + 0x69, 0x6e, 0x22, 0x17, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, + 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x4f, 0x0a, 0x0b, 0x54, + 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x40, 0x0a, 0x06, 0x63, 0x68, + 0x61, 0x69, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 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, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x43, + 0x68, 0x61, 0x69, 0x6e, 0x52, 0x06, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x22, 0x36, 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, +} + +var ( + file_fulcio_proto_rawDescOnce sync.Once + file_fulcio_proto_rawDescData = file_fulcio_proto_rawDesc +) + +func file_fulcio_proto_rawDescGZIP() []byte { + file_fulcio_proto_rawDescOnce.Do(func() { + file_fulcio_proto_rawDescData = protoimpl.X.CompressGZIP(file_fulcio_proto_rawDescData) + }) + return file_fulcio_proto_rawDescData +} + +var file_fulcio_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_fulcio_proto_msgTypes = make([]protoimpl.MessageInfo, 9) +var file_fulcio_proto_goTypes = []interface{}{ + (PublicKeyAlgorithm)(0), // 0: dev.sigstore.fulcio.v2.PublicKeyAlgorithm + (*CreateSigningCertificateRequest)(nil), // 1: dev.sigstore.fulcio.v2.CreateSigningCertificateRequest + (*Credentials)(nil), // 2: dev.sigstore.fulcio.v2.Credentials + (*PublicKey)(nil), // 3: dev.sigstore.fulcio.v2.PublicKey + (*SigningCertificate)(nil), // 4: dev.sigstore.fulcio.v2.SigningCertificate + (*SigningCertificateDetachedSCT)(nil), // 5: dev.sigstore.fulcio.v2.SigningCertificateDetachedSCT + (*SigningCertificateEmbeddedSCT)(nil), // 6: dev.sigstore.fulcio.v2.SigningCertificateEmbeddedSCT + (*GetTrustBundleRequest)(nil), // 7: dev.sigstore.fulcio.v2.GetTrustBundleRequest + (*TrustBundle)(nil), // 8: dev.sigstore.fulcio.v2.TrustBundle + (*CertificateChain)(nil), // 9: dev.sigstore.fulcio.v2.CertificateChain +} +var file_fulcio_proto_depIdxs = []int32{ + 2, // 0: dev.sigstore.fulcio.v2.CreateSigningCertificateRequest.credentials:type_name -> dev.sigstore.fulcio.v2.Credentials + 3, // 1: dev.sigstore.fulcio.v2.CreateSigningCertificateRequest.public_key:type_name -> dev.sigstore.fulcio.v2.PublicKey + 0, // 2: dev.sigstore.fulcio.v2.PublicKey.algorithm:type_name -> dev.sigstore.fulcio.v2.PublicKeyAlgorithm + 5, // 3: dev.sigstore.fulcio.v2.SigningCertificate.signed_certificate_detached_sct:type_name -> dev.sigstore.fulcio.v2.SigningCertificateDetachedSCT + 6, // 4: dev.sigstore.fulcio.v2.SigningCertificate.signed_certificate_embedded_sct:type_name -> dev.sigstore.fulcio.v2.SigningCertificateEmbeddedSCT + 9, // 5: dev.sigstore.fulcio.v2.SigningCertificateDetachedSCT.chain:type_name -> dev.sigstore.fulcio.v2.CertificateChain + 9, // 6: dev.sigstore.fulcio.v2.SigningCertificateEmbeddedSCT.chain:type_name -> dev.sigstore.fulcio.v2.CertificateChain + 9, // 7: dev.sigstore.fulcio.v2.TrustBundle.chains:type_name -> dev.sigstore.fulcio.v2.CertificateChain + 1, // 8: dev.sigstore.fulcio.v2.CA.CreateSigningCertificate:input_type -> dev.sigstore.fulcio.v2.CreateSigningCertificateRequest + 7, // 9: dev.sigstore.fulcio.v2.CA.GetTrustBundle:input_type -> dev.sigstore.fulcio.v2.GetTrustBundleRequest + 4, // 10: dev.sigstore.fulcio.v2.CA.CreateSigningCertificate:output_type -> dev.sigstore.fulcio.v2.SigningCertificate + 8, // 11: dev.sigstore.fulcio.v2.CA.GetTrustBundle:output_type -> dev.sigstore.fulcio.v2.TrustBundle + 10, // [10:12] is the sub-list for method output_type + 8, // [8:10] is the sub-list for method input_type + 8, // [8:8] is the sub-list for extension type_name + 8, // [8:8] is the sub-list for extension extendee + 0, // [0:8] is the sub-list for field type_name +} + +func init() { file_fulcio_proto_init() } +func file_fulcio_proto_init() { + if File_fulcio_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_fulcio_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CreateSigningCertificateRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_fulcio_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Credentials); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_fulcio_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PublicKey); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_fulcio_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SigningCertificate); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_fulcio_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SigningCertificateDetachedSCT); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_fulcio_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SigningCertificateEmbeddedSCT); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_fulcio_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetTrustBundleRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_fulcio_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TrustBundle); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_fulcio_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CertificateChain); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_fulcio_proto_msgTypes[1].OneofWrappers = []interface{}{ + (*Credentials_OidcIdentityToken)(nil), + } + file_fulcio_proto_msgTypes[3].OneofWrappers = []interface{}{ + (*SigningCertificate_SignedCertificateDetachedSct)(nil), + (*SigningCertificate_SignedCertificateEmbeddedSct)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_fulcio_proto_rawDesc, + NumEnums: 1, + NumMessages: 9, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_fulcio_proto_goTypes, + DependencyIndexes: file_fulcio_proto_depIdxs, + EnumInfos: file_fulcio_proto_enumTypes, + MessageInfos: file_fulcio_proto_msgTypes, + }.Build() + File_fulcio_proto = out.File + file_fulcio_proto_rawDesc = nil + file_fulcio_proto_goTypes = nil + file_fulcio_proto_depIdxs = nil +} diff --git a/pkg/generated/protobuf/fulcio.pb.gw.go b/pkg/generated/protobuf/fulcio.pb.gw.go new file mode 100644 index 000000000..c36ab85c4 --- /dev/null +++ b/pkg/generated/protobuf/fulcio.pb.gw.go @@ -0,0 +1,232 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: fulcio.proto + +/* +Package protobuf is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package protobuf + +import ( + "context" + "io" + "net/http" + + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "github.com/grpc-ecosystem/grpc-gateway/v2/utilities" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" +) + +// Suppress "imported and not used" errors +var _ codes.Code +var _ io.Reader +var _ status.Status +var _ = runtime.String +var _ = utilities.NewDoubleArray +var _ = metadata.Join + +func request_CA_CreateSigningCertificate_0(ctx context.Context, marshaler runtime.Marshaler, client CAClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq CreateSigningCertificateRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.CreateSigningCertificate(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_CA_CreateSigningCertificate_0(ctx context.Context, marshaler runtime.Marshaler, server CAServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq CreateSigningCertificateRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.CreateSigningCertificate(ctx, &protoReq) + return msg, metadata, err + +} + +func request_CA_GetTrustBundle_0(ctx context.Context, marshaler runtime.Marshaler, client CAClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetTrustBundleRequest + var metadata runtime.ServerMetadata + + msg, err := client.GetTrustBundle(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_CA_GetTrustBundle_0(ctx context.Context, marshaler runtime.Marshaler, server CAServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetTrustBundleRequest + var metadata runtime.ServerMetadata + + msg, err := server.GetTrustBundle(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. +// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterCAHandlerFromEndpoint instead. +func RegisterCAHandlerServer(ctx context.Context, mux *runtime.ServeMux, server CAServer) error { + + mux.Handle("POST", pattern_CA_CreateSigningCertificate_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) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/dev.sigstore.fulcio.v2.CA/CreateSigningCertificate", runtime.WithHTTPPathPattern("/api/v2/signingCert")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_CA_CreateSigningCertificate_0(rctx, 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_CreateSigningCertificate_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_CA_GetTrustBundle_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) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/dev.sigstore.fulcio.v2.CA/GetTrustBundle", runtime.WithHTTPPathPattern("/api/v2/trustBundle")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_CA_GetTrustBundle_0(rctx, 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_GetTrustBundle_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +// RegisterCAHandlerFromEndpoint is same as RegisterCAHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterCAHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.Dial(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + + return RegisterCAHandler(ctx, mux, conn) +} + +// RegisterCAHandler registers the http handlers for service CA to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterCAHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + return RegisterCAHandlerClient(ctx, mux, NewCAClient(conn)) +} + +// RegisterCAHandlerClient registers the http handlers for service CA +// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "CAClient". +// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "CAClient" +// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in +// "CAClient" to call the correct interceptors. +func RegisterCAHandlerClient(ctx context.Context, mux *runtime.ServeMux, client CAClient) error { + + mux.Handle("POST", pattern_CA_CreateSigningCertificate_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) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/dev.sigstore.fulcio.v2.CA/CreateSigningCertificate", runtime.WithHTTPPathPattern("/api/v2/signingCert")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_CA_CreateSigningCertificate_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_CA_CreateSigningCertificate_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_CA_GetTrustBundle_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) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/dev.sigstore.fulcio.v2.CA/GetTrustBundle", runtime.WithHTTPPathPattern("/api/v2/trustBundle")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_CA_GetTrustBundle_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_CA_GetTrustBundle_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +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"}, "")) +) + +var ( + forward_CA_CreateSigningCertificate_0 = runtime.ForwardResponseMessage + + forward_CA_GetTrustBundle_0 = runtime.ForwardResponseMessage +) diff --git a/pkg/generated/protobuf/fulcio_grpc.pb.go b/pkg/generated/protobuf/fulcio_grpc.pb.go new file mode 100644 index 000000000..8cdeaeca7 --- /dev/null +++ b/pkg/generated/protobuf/fulcio_grpc.pb.go @@ -0,0 +1,145 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. + +package protobuf + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +// CAClient is the client API for CA service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type CAClient interface { + //* + // Returns an X.509 certificate created by the Fulcio certificate authority for the given request parameters + CreateSigningCertificate(ctx context.Context, in *CreateSigningCertificateRequest, opts ...grpc.CallOption) (*SigningCertificate, error) + //* + // 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) +} + +type cAClient struct { + cc grpc.ClientConnInterface +} + +func NewCAClient(cc grpc.ClientConnInterface) CAClient { + return &cAClient{cc} +} + +func (c *cAClient) CreateSigningCertificate(ctx context.Context, in *CreateSigningCertificateRequest, opts ...grpc.CallOption) (*SigningCertificate, error) { + out := new(SigningCertificate) + err := c.cc.Invoke(ctx, "/dev.sigstore.fulcio.v2.CA/CreateSigningCertificate", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *cAClient) GetTrustBundle(ctx context.Context, in *GetTrustBundleRequest, opts ...grpc.CallOption) (*TrustBundle, error) { + out := new(TrustBundle) + err := c.cc.Invoke(ctx, "/dev.sigstore.fulcio.v2.CA/GetTrustBundle", 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 +type CAServer interface { + //* + // Returns an X.509 certificate created by the Fulcio certificate authority for the given request parameters + CreateSigningCertificate(context.Context, *CreateSigningCertificateRequest) (*SigningCertificate, error) + //* + // 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) + mustEmbedUnimplementedCAServer() +} + +// UnimplementedCAServer must be embedded to have forward compatible implementations. +type UnimplementedCAServer struct { +} + +func (UnimplementedCAServer) CreateSigningCertificate(context.Context, *CreateSigningCertificateRequest) (*SigningCertificate, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreateSigningCertificate not implemented") +} +func (UnimplementedCAServer) GetTrustBundle(context.Context, *GetTrustBundleRequest) (*TrustBundle, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetTrustBundle not implemented") +} +func (UnimplementedCAServer) mustEmbedUnimplementedCAServer() {} + +// UnsafeCAServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to CAServer will +// result in compilation errors. +type UnsafeCAServer interface { + mustEmbedUnimplementedCAServer() +} + +func RegisterCAServer(s grpc.ServiceRegistrar, srv CAServer) { + s.RegisterService(&CA_ServiceDesc, srv) +} + +func _CA_CreateSigningCertificate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateSigningCertificateRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CAServer).CreateSigningCertificate(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/dev.sigstore.fulcio.v2.CA/CreateSigningCertificate", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CAServer).CreateSigningCertificate(ctx, req.(*CreateSigningCertificateRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _CA_GetTrustBundle_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetTrustBundleRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CAServer).GetTrustBundle(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/dev.sigstore.fulcio.v2.CA/GetTrustBundle", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CAServer).GetTrustBundle(ctx, req.(*GetTrustBundleRequest)) + } + 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) +var CA_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "dev.sigstore.fulcio.v2.CA", + HandlerType: (*CAServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "CreateSigningCertificate", + Handler: _CA_CreateSigningCertificate_Handler, + }, + { + MethodName: "GetTrustBundle", + Handler: _CA_GetTrustBundle_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 new file mode 100644 index 000000000..20ac646e2 --- /dev/null +++ b/pkg/generated/protobuf/legacy/fulcio_legacy.pb.go @@ -0,0 +1,303 @@ +// +// Copyright 2022 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. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.27.1 +// protoc v3.12.4 +// source: fulcio_legacy.proto + +package legacy + +import ( + empty "github.com/golang/protobuf/ptypes/empty" + _ "google.golang.org/genproto/googleapis/api/annotations" + httpbody "google.golang.org/genproto/googleapis/api/httpbody" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type CreateSigningCertificateRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // + // The public key to be stored in the requested certificate + // + // Deprecated: Do not use. + PublicKey *PublicKey `protobuf:"bytes,1,opt,name=publicKey,proto3" json:"publicKey,omitempty"` + // + // Proof that the client possesses the private key + // + // Deprecated: Do not use. + SignedEmailAddress []byte `protobuf:"bytes,2,opt,name=signedEmailAddress,proto3" json:"signedEmailAddress,omitempty"` +} + +func (x *CreateSigningCertificateRequest) Reset() { + *x = CreateSigningCertificateRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_fulcio_legacy_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CreateSigningCertificateRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateSigningCertificateRequest) ProtoMessage() {} + +func (x *CreateSigningCertificateRequest) ProtoReflect() protoreflect.Message { + mi := &file_fulcio_legacy_proto_msgTypes[0] + 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 CreateSigningCertificateRequest.ProtoReflect.Descriptor instead. +func (*CreateSigningCertificateRequest) Descriptor() ([]byte, []int) { + return file_fulcio_legacy_proto_rawDescGZIP(), []int{0} +} + +// Deprecated: Do not use. +func (x *CreateSigningCertificateRequest) GetPublicKey() *PublicKey { + if x != nil { + return x.PublicKey + } + return nil +} + +// Deprecated: Do not use. +func (x *CreateSigningCertificateRequest) GetSignedEmailAddress() []byte { + if x != nil { + return x.SignedEmailAddress + } + return nil +} + +type PublicKey struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // + // The cryptographic algorithm to use with the key material + // + // Deprecated: Do not use. + Algorithm string `protobuf:"bytes,1,opt,name=algorithm,proto3" json:"algorithm,omitempty"` + // + // DER or PEM encoded public key + // + // Deprecated: Do not use. + Content []byte `protobuf:"bytes,2,opt,name=content,proto3" json:"content,omitempty"` +} + +func (x *PublicKey) Reset() { + *x = PublicKey{} + if protoimpl.UnsafeEnabled { + mi := &file_fulcio_legacy_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PublicKey) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PublicKey) ProtoMessage() {} + +func (x *PublicKey) ProtoReflect() protoreflect.Message { + mi := &file_fulcio_legacy_proto_msgTypes[1] + 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 PublicKey.ProtoReflect.Descriptor instead. +func (*PublicKey) Descriptor() ([]byte, []int) { + return file_fulcio_legacy_proto_rawDescGZIP(), []int{1} +} + +// Deprecated: Do not use. +func (x *PublicKey) GetAlgorithm() string { + if x != nil { + return x.Algorithm + } + return "" +} + +// Deprecated: Do not use. +func (x *PublicKey) GetContent() []byte { + if x != nil { + return x.Content + } + return nil +} + +var File_fulcio_legacy_proto protoreflect.FileDescriptor + +var file_fulcio_legacy_proto_rawDesc = []byte{ + 0x0a, 0x13, 0x66, 0x75, 0x6c, 0x63, 0x69, 0x6f, 0x5f, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1a, 0x64, 0x65, 0x76, 0x2e, 0x73, 0x69, 0x67, 0x73, 0x74, + 0x6f, 0x72, 0x65, 0x2e, 0x66, 0x75, 0x6c, 0x63, 0x69, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, + 0x61, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, + 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, + 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x68, 0x74, 0x74, 0x70, + 0x62, 0x6f, 0x64, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, + 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x9e, 0x01, 0x0a, 0x1f, 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, 0x12, 0x47, 0x0a, 0x09, 0x70, + 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, + 0x2e, 0x64, 0x65, 0x76, 0x2e, 0x73, 0x69, 0x67, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x66, 0x75, + 0x6c, 0x63, 0x69, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x2e, 0x50, 0x75, 0x62, 0x6c, + 0x69, 0x63, 0x4b, 0x65, 0x79, 0x42, 0x02, 0x18, 0x01, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, + 0x63, 0x4b, 0x65, 0x79, 0x12, 0x32, 0x0a, 0x12, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x45, 0x6d, + 0x61, 0x69, 0x6c, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, + 0x42, 0x02, 0x18, 0x01, 0x52, 0x12, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x45, 0x6d, 0x61, 0x69, + 0x6c, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x4b, 0x0a, 0x09, 0x50, 0x75, 0x62, 0x6c, + 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x20, 0x0a, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, + 0x68, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x09, 0x61, 0x6c, + 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x1c, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x02, 0x18, 0x01, 0x52, 0x07, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x32, 0xf8, 0x01, 0x0a, 0x02, 0x43, 0x41, 0x12, 0x90, 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, 0x3b, 0x2e, 0x64, 0x65, 0x76, 0x2e, + 0x73, 0x69, 0x67, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x66, 0x75, 0x6c, 0x63, 0x69, 0x6f, 0x2e, + 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 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, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x48, 0x74, 0x74, 0x70, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x21, 0x88, 0x02, + 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x22, 0x13, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, + 0x2f, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x65, 0x72, 0x74, 0x3a, 0x01, 0x2a, 0x12, + 0x5f, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x14, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x48, 0x74, 0x74, 0x70, 0x42, + 0x6f, 0x64, 0x79, 0x22, 0x1b, 0x88, 0x02, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, + 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x6f, 0x74, 0x43, 0x65, 0x72, 0x74, + 0x42, 0x65, 0x0a, 0x1a, 0x64, 0x65, 0x76, 0x2e, 0x73, 0x69, 0x67, 0x73, 0x74, 0x6f, 0x72, 0x65, + 0x2e, 0x66, 0x75, 0x6c, 0x63, 0x69, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x42, 0x0b, + 0x46, 0x75, 0x6c, 0x63, 0x69, 0x6f, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x38, 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, + 0x2f, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_fulcio_legacy_proto_rawDescOnce sync.Once + file_fulcio_legacy_proto_rawDescData = file_fulcio_legacy_proto_rawDesc +) + +func file_fulcio_legacy_proto_rawDescGZIP() []byte { + file_fulcio_legacy_proto_rawDescOnce.Do(func() { + file_fulcio_legacy_proto_rawDescData = protoimpl.X.CompressGZIP(file_fulcio_legacy_proto_rawDescData) + }) + return file_fulcio_legacy_proto_rawDescData +} + +var file_fulcio_legacy_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_fulcio_legacy_proto_goTypes = []interface{}{ + (*CreateSigningCertificateRequest)(nil), // 0: dev.sigstore.fulcio.v1beta.CreateSigningCertificateRequest + (*PublicKey)(nil), // 1: dev.sigstore.fulcio.v1beta.PublicKey + (*empty.Empty)(nil), // 2: google.protobuf.Empty + (*httpbody.HttpBody)(nil), // 3: google.api.HttpBody +} +var file_fulcio_legacy_proto_depIdxs = []int32{ + 1, // 0: dev.sigstore.fulcio.v1beta.CreateSigningCertificateRequest.publicKey:type_name -> dev.sigstore.fulcio.v1beta.PublicKey + 0, // 1: dev.sigstore.fulcio.v1beta.CA.CreateSigningCertificate:input_type -> dev.sigstore.fulcio.v1beta.CreateSigningCertificateRequest + 2, // 2: dev.sigstore.fulcio.v1beta.CA.GetRootCertificate:input_type -> google.protobuf.Empty + 3, // 3: dev.sigstore.fulcio.v1beta.CA.CreateSigningCertificate:output_type -> google.api.HttpBody + 3, // 4: dev.sigstore.fulcio.v1beta.CA.GetRootCertificate:output_type -> google.api.HttpBody + 3, // [3:5] is the sub-list for method output_type + 1, // [1:3] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_fulcio_legacy_proto_init() } +func file_fulcio_legacy_proto_init() { + if File_fulcio_legacy_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_fulcio_legacy_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CreateSigningCertificateRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_fulcio_legacy_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PublicKey); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_fulcio_legacy_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_fulcio_legacy_proto_goTypes, + DependencyIndexes: file_fulcio_legacy_proto_depIdxs, + MessageInfos: file_fulcio_legacy_proto_msgTypes, + }.Build() + File_fulcio_legacy_proto = out.File + file_fulcio_legacy_proto_rawDesc = nil + file_fulcio_legacy_proto_goTypes = nil + file_fulcio_legacy_proto_depIdxs = nil +} diff --git a/pkg/generated/protobuf/legacy/fulcio_legacy.pb.gw.go b/pkg/generated/protobuf/legacy/fulcio_legacy.pb.gw.go new file mode 100644 index 000000000..a88e24480 --- /dev/null +++ b/pkg/generated/protobuf/legacy/fulcio_legacy.pb.gw.go @@ -0,0 +1,233 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: fulcio_legacy.proto + +/* +Package legacy is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package legacy + +import ( + "context" + "io" + "net/http" + + "github.com/golang/protobuf/ptypes/empty" + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "github.com/grpc-ecosystem/grpc-gateway/v2/utilities" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" +) + +// Suppress "imported and not used" errors +var _ codes.Code +var _ io.Reader +var _ status.Status +var _ = runtime.String +var _ = utilities.NewDoubleArray +var _ = metadata.Join + +func request_CA_CreateSigningCertificate_0(ctx context.Context, marshaler runtime.Marshaler, client CAClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq CreateSigningCertificateRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.CreateSigningCertificate(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_CA_CreateSigningCertificate_0(ctx context.Context, marshaler runtime.Marshaler, server CAServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq CreateSigningCertificateRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.CreateSigningCertificate(ctx, &protoReq) + return msg, metadata, err + +} + +func request_CA_GetRootCertificate_0(ctx context.Context, marshaler runtime.Marshaler, client CAClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq empty.Empty + var metadata runtime.ServerMetadata + + msg, err := client.GetRootCertificate(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_CA_GetRootCertificate_0(ctx context.Context, marshaler runtime.Marshaler, server CAServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq empty.Empty + var metadata runtime.ServerMetadata + + msg, err := server.GetRootCertificate(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. +// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterCAHandlerFromEndpoint instead. +func RegisterCAHandlerServer(ctx context.Context, mux *runtime.ServeMux, server CAServer) error { + + mux.Handle("POST", pattern_CA_CreateSigningCertificate_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) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/dev.sigstore.fulcio.v1beta.CA/CreateSigningCertificate", runtime.WithHTTPPathPattern("/api/v1/signingCert")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_CA_CreateSigningCertificate_0(rctx, 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_CreateSigningCertificate_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_CA_GetRootCertificate_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) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/dev.sigstore.fulcio.v1beta.CA/GetRootCertificate", runtime.WithHTTPPathPattern("/api/v1/rootCert")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_CA_GetRootCertificate_0(rctx, 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_GetRootCertificate_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +// RegisterCAHandlerFromEndpoint is same as RegisterCAHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterCAHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.Dial(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + + return RegisterCAHandler(ctx, mux, conn) +} + +// RegisterCAHandler registers the http handlers for service CA to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterCAHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + return RegisterCAHandlerClient(ctx, mux, NewCAClient(conn)) +} + +// RegisterCAHandlerClient registers the http handlers for service CA +// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "CAClient". +// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "CAClient" +// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in +// "CAClient" to call the correct interceptors. +func RegisterCAHandlerClient(ctx context.Context, mux *runtime.ServeMux, client CAClient) error { + + mux.Handle("POST", pattern_CA_CreateSigningCertificate_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) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/dev.sigstore.fulcio.v1beta.CA/CreateSigningCertificate", runtime.WithHTTPPathPattern("/api/v1/signingCert")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_CA_CreateSigningCertificate_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_CA_CreateSigningCertificate_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_CA_GetRootCertificate_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) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/dev.sigstore.fulcio.v1beta.CA/GetRootCertificate", runtime.WithHTTPPathPattern("/api/v1/rootCert")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_CA_GetRootCertificate_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_CA_GetRootCertificate_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +var ( + pattern_CA_CreateSigningCertificate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "signingCert"}, "")) + + pattern_CA_GetRootCertificate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "rootCert"}, "")) +) + +var ( + forward_CA_CreateSigningCertificate_0 = runtime.ForwardResponseMessage + + forward_CA_GetRootCertificate_0 = runtime.ForwardResponseMessage +) diff --git a/pkg/generated/protobuf/legacy/fulcio_legacy_grpc.pb.go b/pkg/generated/protobuf/legacy/fulcio_legacy_grpc.pb.go new file mode 100644 index 000000000..be6ec6368 --- /dev/null +++ b/pkg/generated/protobuf/legacy/fulcio_legacy_grpc.pb.go @@ -0,0 +1,153 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. + +package legacy + +import ( + context "context" + empty "github.com/golang/protobuf/ptypes/empty" + httpbody "google.golang.org/genproto/googleapis/api/httpbody" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +// CAClient is the client API for CA service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type CAClient interface { + // Deprecated: Do not use. + // + // Returns an X509 certificate created by the Fulcio certificate authority for the given request parameters + CreateSigningCertificate(ctx context.Context, in *CreateSigningCertificateRequest, opts ...grpc.CallOption) (*httpbody.HttpBody, error) + // Deprecated: Do not use. + // + // Returns the public key that can be used to validate the signed tree head + GetRootCertificate(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*httpbody.HttpBody, error) +} + +type cAClient struct { + cc grpc.ClientConnInterface +} + +func NewCAClient(cc grpc.ClientConnInterface) CAClient { + return &cAClient{cc} +} + +// Deprecated: Do not use. +func (c *cAClient) CreateSigningCertificate(ctx context.Context, in *CreateSigningCertificateRequest, opts ...grpc.CallOption) (*httpbody.HttpBody, error) { + out := new(httpbody.HttpBody) + err := c.cc.Invoke(ctx, "/dev.sigstore.fulcio.v1beta.CA/CreateSigningCertificate", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Deprecated: Do not use. +func (c *cAClient) GetRootCertificate(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*httpbody.HttpBody, error) { + out := new(httpbody.HttpBody) + err := c.cc.Invoke(ctx, "/dev.sigstore.fulcio.v1beta.CA/GetRootCertificate", 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 +type CAServer interface { + // Deprecated: Do not use. + // + // Returns an X509 certificate created by the Fulcio certificate authority for the given request parameters + CreateSigningCertificate(context.Context, *CreateSigningCertificateRequest) (*httpbody.HttpBody, error) + // Deprecated: Do not use. + // + // Returns the public key that can be used to validate the signed tree head + GetRootCertificate(context.Context, *empty.Empty) (*httpbody.HttpBody, error) + mustEmbedUnimplementedCAServer() +} + +// UnimplementedCAServer must be embedded to have forward compatible implementations. +type UnimplementedCAServer struct { +} + +func (UnimplementedCAServer) CreateSigningCertificate(context.Context, *CreateSigningCertificateRequest) (*httpbody.HttpBody, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreateSigningCertificate not implemented") +} +func (UnimplementedCAServer) GetRootCertificate(context.Context, *empty.Empty) (*httpbody.HttpBody, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetRootCertificate not implemented") +} +func (UnimplementedCAServer) mustEmbedUnimplementedCAServer() {} + +// UnsafeCAServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to CAServer will +// result in compilation errors. +type UnsafeCAServer interface { + mustEmbedUnimplementedCAServer() +} + +func RegisterCAServer(s grpc.ServiceRegistrar, srv CAServer) { + s.RegisterService(&CA_ServiceDesc, srv) +} + +func _CA_CreateSigningCertificate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateSigningCertificateRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CAServer).CreateSigningCertificate(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/dev.sigstore.fulcio.v1beta.CA/CreateSigningCertificate", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CAServer).CreateSigningCertificate(ctx, req.(*CreateSigningCertificateRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _CA_GetRootCertificate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(empty.Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CAServer).GetRootCertificate(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/dev.sigstore.fulcio.v1beta.CA/GetRootCertificate", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CAServer).GetRootCertificate(ctx, req.(*empty.Empty)) + } + 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) +var CA_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "dev.sigstore.fulcio.v1beta.CA", + HandlerType: (*CAServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "CreateSigningCertificate", + Handler: _CA_CreateSigningCertificate_Handler, + }, + { + MethodName: "GetRootCertificate", + Handler: _CA_GetRootCertificate_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "fulcio_legacy.proto", +} diff --git a/pkg/log/log.go b/pkg/log/log.go index befdfa9de..64740dcf3 100644 --- a/pkg/log/log.go +++ b/pkg/log/log.go @@ -18,11 +18,14 @@ package log import ( "context" "log" - "net/http" - "github.com/go-chi/chi/middleware" + "github.com/goadesign/goa/grpc/middleware" + grpc_zap "github.com/grpc-ecosystem/go-grpc-middleware/logging/zap" + "github.com/grpc-ecosystem/go-grpc-middleware/logging/zap/ctxzap" "go.uber.org/zap" "go.uber.org/zap/zapcore" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/metadata" ) // Logger set the default logger to development mode @@ -64,21 +67,47 @@ func createCliLogger() *zap.SugaredLogger { return logger.Sugar() } -func WithRequestID(ctx context.Context, id string) context.Context { - return context.WithValue(ctx, middleware.RequestIDKey, id) -} +type requestIDMetadataKeyType string -func RequestIDLogger(r *http.Request) *zap.SugaredLogger { - return ContextLogger(r.Context()) -} +const ( + requestIDMetadataKey requestIDMetadataKeyType = middleware.RequestIDMetadataKey +) func ContextLogger(ctx context.Context) *zap.SugaredLogger { proposedLogger := Logger if ctx != nil { - if ctxRequestID, ok := ctx.Value(middleware.RequestIDKey).(string); ok { - proposedLogger = proposedLogger.With(zap.String("requestID", ctxRequestID)) + if md, ok := metadata.FromIncomingContext(ctx); ok { + val := md.Get(string(requestIDMetadataKey)) + if len(val) == 1 { + proposedLogger = proposedLogger.With(zap.String("requestID", val[0])) + } } } return proposedLogger } + +func SetupGRPCLogging() (*zap.Logger, []grpc_zap.Option) { + var options []grpc_zap.Option + options = append(options, grpc_zap.WithDecider(func(methodName string, err error) bool { + // TODO: implement filters to eliminate health check log statements + return true + })) + options = append(options, grpc_zap.WithMessageProducer( + func(ctx context.Context, msg string, level zapcore.Level, code codes.Code, err error, duration zapcore.Field) { + var requestID zap.Field + if md, ok := metadata.FromIncomingContext(ctx); ok { + val := md.Get(string(requestIDMetadataKey)) + if len(val) == 1 { + requestID = zap.String("requestID", val[0]) + } + } + ctxzap.Extract(ctx).Check(level, msg).Write( + zap.Error(err), + zap.String("grpc.code", code.String()), + requestID, + duration, + ) + })) + return Logger.Desugar(), options +} diff --git a/third_party/googleapis/google/api/annotations.proto b/third_party/googleapis/google/api/annotations.proto new file mode 100644 index 000000000..efdab3db6 --- /dev/null +++ b/third_party/googleapis/google/api/annotations.proto @@ -0,0 +1,31 @@ +// Copyright 2015 Google LLC +// +// 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. + +syntax = "proto3"; + +package google.api; + +import "google/api/http.proto"; +import "google/protobuf/descriptor.proto"; + +option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; +option java_multiple_files = true; +option java_outer_classname = "AnnotationsProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +extend google.protobuf.MethodOptions { + // See `HttpRule`. + HttpRule http = 72295728; +} diff --git a/third_party/googleapis/google/api/field_behavior.proto b/third_party/googleapis/google/api/field_behavior.proto new file mode 100644 index 000000000..c4abe3b67 --- /dev/null +++ b/third_party/googleapis/google/api/field_behavior.proto @@ -0,0 +1,90 @@ +// Copyright 2018 Google LLC +// +// 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. + +syntax = "proto3"; + +package google.api; + +import "google/protobuf/descriptor.proto"; + +option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; +option java_multiple_files = true; +option java_outer_classname = "FieldBehaviorProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +extend google.protobuf.FieldOptions { + // A designation of a specific field behavior (required, output only, etc.) + // in protobuf messages. + // + // Examples: + // + // string name = 1 [(google.api.field_behavior) = REQUIRED]; + // State state = 1 [(google.api.field_behavior) = OUTPUT_ONLY]; + // google.protobuf.Duration ttl = 1 + // [(google.api.field_behavior) = INPUT_ONLY]; + // google.protobuf.Timestamp expire_time = 1 + // [(google.api.field_behavior) = OUTPUT_ONLY, + // (google.api.field_behavior) = IMMUTABLE]; + repeated google.api.FieldBehavior field_behavior = 1052; +} + +// An indicator of the behavior of a given field (for example, that a field +// is required in requests, or given as output but ignored as input). +// This **does not** change the behavior in protocol buffers itself; it only +// denotes the behavior and may affect how API tooling handles the field. +// +// Note: This enum **may** receive new values in the future. +enum FieldBehavior { + // Conventional default for enums. Do not use this. + FIELD_BEHAVIOR_UNSPECIFIED = 0; + + // Specifically denotes a field as optional. + // While all fields in protocol buffers are optional, this may be specified + // for emphasis if appropriate. + OPTIONAL = 1; + + // Denotes a field as required. + // This indicates that the field **must** be provided as part of the request, + // and failure to do so will cause an error (usually `INVALID_ARGUMENT`). + REQUIRED = 2; + + // Denotes a field as output only. + // This indicates that the field is provided in responses, but including the + // field in a request does nothing (the server *must* ignore it and + // *must not* throw an error as a result of the field's presence). + OUTPUT_ONLY = 3; + + // Denotes a field as input only. + // This indicates that the field is provided in requests, and the + // corresponding field is not included in output. + INPUT_ONLY = 4; + + // Denotes a field as immutable. + // This indicates that the field may be set once in a request to create a + // resource, but may not be changed thereafter. + IMMUTABLE = 5; + + // Denotes that a (repeated) field is an unordered list. + // This indicates that the service may provide the elements of the list + // in any arbitrary order, rather than the order the user originally + // provided. Additionally, the list's order may or may not be stable. + UNORDERED_LIST = 6; + + // Denotes that this field returns a non-empty default value if not set. + // This indicates that if the user provides the empty value in a request, + // a non-empty value will be returned. The user will not be aware of what + // non-empty value to expect. + NON_EMPTY_DEFAULT = 7; +} diff --git a/third_party/googleapis/google/api/http.proto b/third_party/googleapis/google/api/http.proto new file mode 100644 index 000000000..113fa936a --- /dev/null +++ b/third_party/googleapis/google/api/http.proto @@ -0,0 +1,375 @@ +// Copyright 2015 Google LLC +// +// 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. + +syntax = "proto3"; + +package google.api; + +option cc_enable_arenas = true; +option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; +option java_multiple_files = true; +option java_outer_classname = "HttpProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// Defines the HTTP configuration for an API service. It contains a list of +// [HttpRule][google.api.HttpRule], each specifying the mapping of an RPC method +// to one or more HTTP REST API methods. +message Http { + // A list of HTTP configuration rules that apply to individual API methods. + // + // **NOTE:** All service configuration rules follow "last one wins" order. + repeated HttpRule rules = 1; + + // When set to true, URL path parameters will be fully URI-decoded except in + // cases of single segment matches in reserved expansion, where "%2F" will be + // left encoded. + // + // The default behavior is to not decode RFC 6570 reserved characters in multi + // segment matches. + bool fully_decode_reserved_expansion = 2; +} + +// # gRPC Transcoding +// +// gRPC Transcoding is a feature for mapping between a gRPC method and one or +// more HTTP REST endpoints. It allows developers to build a single API service +// that supports both gRPC APIs and REST APIs. Many systems, including [Google +// APIs](https://github.com/googleapis/googleapis), +// [Cloud Endpoints](https://cloud.google.com/endpoints), [gRPC +// Gateway](https://github.com/grpc-ecosystem/grpc-gateway), +// and [Envoy](https://github.com/envoyproxy/envoy) proxy support this feature +// and use it for large scale production services. +// +// `HttpRule` defines the schema of the gRPC/REST mapping. The mapping specifies +// how different portions of the gRPC request message are mapped to the URL +// path, URL query parameters, and HTTP request body. It also controls how the +// gRPC response message is mapped to the HTTP response body. `HttpRule` is +// typically specified as an `google.api.http` annotation on the gRPC method. +// +// Each mapping specifies a URL path template and an HTTP method. The path +// template may refer to one or more fields in the gRPC request message, as long +// as each field is a non-repeated field with a primitive (non-message) type. +// The path template controls how fields of the request message are mapped to +// the URL path. +// +// Example: +// +// service Messaging { +// rpc GetMessage(GetMessageRequest) returns (Message) { +// option (google.api.http) = { +// get: "/v1/{name=messages/*}" +// }; +// } +// } +// message GetMessageRequest { +// string name = 1; // Mapped to URL path. +// } +// message Message { +// string text = 1; // The resource content. +// } +// +// This enables an HTTP REST to gRPC mapping as below: +// +// HTTP | gRPC +// -----|----- +// `GET /v1/messages/123456` | `GetMessage(name: "messages/123456")` +// +// Any fields in the request message which are not bound by the path template +// automatically become HTTP query parameters if there is no HTTP request body. +// For example: +// +// service Messaging { +// rpc GetMessage(GetMessageRequest) returns (Message) { +// option (google.api.http) = { +// get:"/v1/messages/{message_id}" +// }; +// } +// } +// message GetMessageRequest { +// message SubMessage { +// string subfield = 1; +// } +// string message_id = 1; // Mapped to URL path. +// int64 revision = 2; // Mapped to URL query parameter `revision`. +// SubMessage sub = 3; // Mapped to URL query parameter `sub.subfield`. +// } +// +// This enables a HTTP JSON to RPC mapping as below: +// +// HTTP | gRPC +// -----|----- +// `GET /v1/messages/123456?revision=2&sub.subfield=foo` | +// `GetMessage(message_id: "123456" revision: 2 sub: SubMessage(subfield: +// "foo"))` +// +// Note that fields which are mapped to URL query parameters must have a +// primitive type or a repeated primitive type or a non-repeated message type. +// In the case of a repeated type, the parameter can be repeated in the URL +// as `...?param=A¶m=B`. In the case of a message type, each field of the +// message is mapped to a separate parameter, such as +// `...?foo.a=A&foo.b=B&foo.c=C`. +// +// For HTTP methods that allow a request body, the `body` field +// specifies the mapping. Consider a REST update method on the +// message resource collection: +// +// service Messaging { +// rpc UpdateMessage(UpdateMessageRequest) returns (Message) { +// option (google.api.http) = { +// patch: "/v1/messages/{message_id}" +// body: "message" +// }; +// } +// } +// message UpdateMessageRequest { +// string message_id = 1; // mapped to the URL +// Message message = 2; // mapped to the body +// } +// +// The following HTTP JSON to RPC mapping is enabled, where the +// representation of the JSON in the request body is determined by +// protos JSON encoding: +// +// HTTP | gRPC +// -----|----- +// `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: +// "123456" message { text: "Hi!" })` +// +// The special name `*` can be used in the body mapping to define that +// every field not bound by the path template should be mapped to the +// request body. This enables the following alternative definition of +// the update method: +// +// service Messaging { +// rpc UpdateMessage(Message) returns (Message) { +// option (google.api.http) = { +// patch: "/v1/messages/{message_id}" +// body: "*" +// }; +// } +// } +// message Message { +// string message_id = 1; +// string text = 2; +// } +// +// +// The following HTTP JSON to RPC mapping is enabled: +// +// HTTP | gRPC +// -----|----- +// `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: +// "123456" text: "Hi!")` +// +// Note that when using `*` in the body mapping, it is not possible to +// have HTTP parameters, as all fields not bound by the path end in +// the body. This makes this option more rarely used in practice when +// defining REST APIs. The common usage of `*` is in custom methods +// which don't use the URL at all for transferring data. +// +// It is possible to define multiple HTTP methods for one RPC by using +// the `additional_bindings` option. Example: +// +// service Messaging { +// rpc GetMessage(GetMessageRequest) returns (Message) { +// option (google.api.http) = { +// get: "/v1/messages/{message_id}" +// additional_bindings { +// get: "/v1/users/{user_id}/messages/{message_id}" +// } +// }; +// } +// } +// message GetMessageRequest { +// string message_id = 1; +// string user_id = 2; +// } +// +// This enables the following two alternative HTTP JSON to RPC mappings: +// +// HTTP | gRPC +// -----|----- +// `GET /v1/messages/123456` | `GetMessage(message_id: "123456")` +// `GET /v1/users/me/messages/123456` | `GetMessage(user_id: "me" message_id: +// "123456")` +// +// ## Rules for HTTP mapping +// +// 1. Leaf request fields (recursive expansion nested messages in the request +// message) are classified into three categories: +// - Fields referred by the path template. They are passed via the URL path. +// - Fields referred by the [HttpRule.body][google.api.HttpRule.body]. They are passed via the HTTP +// request body. +// - All other fields are passed via the URL query parameters, and the +// parameter name is the field path in the request message. A repeated +// field can be represented as multiple query parameters under the same +// name. +// 2. If [HttpRule.body][google.api.HttpRule.body] is "*", there is no URL query parameter, all fields +// are passed via URL path and HTTP request body. +// 3. If [HttpRule.body][google.api.HttpRule.body] is omitted, there is no HTTP request body, all +// fields are passed via URL path and URL query parameters. +// +// ### Path template syntax +// +// Template = "/" Segments [ Verb ] ; +// Segments = Segment { "/" Segment } ; +// Segment = "*" | "**" | LITERAL | Variable ; +// Variable = "{" FieldPath [ "=" Segments ] "}" ; +// FieldPath = IDENT { "." IDENT } ; +// Verb = ":" LITERAL ; +// +// The syntax `*` matches a single URL path segment. The syntax `**` matches +// zero or more URL path segments, which must be the last part of the URL path +// except the `Verb`. +// +// The syntax `Variable` matches part of the URL path as specified by its +// template. A variable template must not contain other variables. If a variable +// matches a single path segment, its template may be omitted, e.g. `{var}` +// is equivalent to `{var=*}`. +// +// The syntax `LITERAL` matches literal text in the URL path. If the `LITERAL` +// contains any reserved character, such characters should be percent-encoded +// before the matching. +// +// If a variable contains exactly one path segment, such as `"{var}"` or +// `"{var=*}"`, when such a variable is expanded into a URL path on the client +// side, all characters except `[-_.~0-9a-zA-Z]` are percent-encoded. The +// server side does the reverse decoding. Such variables show up in the +// [Discovery +// Document](https://developers.google.com/discovery/v1/reference/apis) as +// `{var}`. +// +// If a variable contains multiple path segments, such as `"{var=foo/*}"` +// or `"{var=**}"`, when such a variable is expanded into a URL path on the +// client side, all characters except `[-_.~/0-9a-zA-Z]` are percent-encoded. +// The server side does the reverse decoding, except "%2F" and "%2f" are left +// unchanged. Such variables show up in the +// [Discovery +// Document](https://developers.google.com/discovery/v1/reference/apis) as +// `{+var}`. +// +// ## Using gRPC API Service Configuration +// +// gRPC API Service Configuration (service config) is a configuration language +// for configuring a gRPC service to become a user-facing product. The +// service config is simply the YAML representation of the `google.api.Service` +// proto message. +// +// As an alternative to annotating your proto file, you can configure gRPC +// transcoding in your service config YAML files. You do this by specifying a +// `HttpRule` that maps the gRPC method to a REST endpoint, achieving the same +// effect as the proto annotation. This can be particularly useful if you +// have a proto that is reused in multiple services. Note that any transcoding +// specified in the service config will override any matching transcoding +// configuration in the proto. +// +// Example: +// +// http: +// rules: +// # Selects a gRPC method and applies HttpRule to it. +// - selector: example.v1.Messaging.GetMessage +// get: /v1/messages/{message_id}/{sub.subfield} +// +// ## Special notes +// +// When gRPC Transcoding is used to map a gRPC to JSON REST endpoints, the +// proto to JSON conversion must follow the [proto3 +// specification](https://developers.google.com/protocol-buffers/docs/proto3#json). +// +// While the single segment variable follows the semantics of +// [RFC 6570](https://tools.ietf.org/html/rfc6570) Section 3.2.2 Simple String +// Expansion, the multi segment variable **does not** follow RFC 6570 Section +// 3.2.3 Reserved Expansion. The reason is that the Reserved Expansion +// does not expand special characters like `?` and `#`, which would lead +// to invalid URLs. As the result, gRPC Transcoding uses a custom encoding +// for multi segment variables. +// +// The path variables **must not** refer to any repeated or mapped field, +// because client libraries are not capable of handling such variable expansion. +// +// The path variables **must not** capture the leading "/" character. The reason +// is that the most common use case "{var}" does not capture the leading "/" +// character. For consistency, all path variables must share the same behavior. +// +// Repeated message fields must not be mapped to URL query parameters, because +// no client library can support such complicated mapping. +// +// If an API needs to use a JSON array for request or response body, it can map +// the request or response body to a repeated field. However, some gRPC +// Transcoding implementations may not support this feature. +message HttpRule { + // Selects a method to which this rule applies. + // + // Refer to [selector][google.api.DocumentationRule.selector] for syntax details. + string selector = 1; + + // Determines the URL pattern is matched by this rules. This pattern can be + // used with any of the {get|put|post|delete|patch} methods. A custom method + // can be defined using the 'custom' field. + oneof pattern { + // Maps to HTTP GET. Used for listing and getting information about + // resources. + string get = 2; + + // Maps to HTTP PUT. Used for replacing a resource. + string put = 3; + + // Maps to HTTP POST. Used for creating a resource or performing an action. + string post = 4; + + // Maps to HTTP DELETE. Used for deleting a resource. + string delete = 5; + + // Maps to HTTP PATCH. Used for updating a resource. + string patch = 6; + + // The custom pattern is used for specifying an HTTP method that is not + // included in the `pattern` field, such as HEAD, or "*" to leave the + // HTTP method unspecified for this rule. The wild-card rule is useful + // for services that provide content to Web (HTML) clients. + CustomHttpPattern custom = 8; + } + + // The name of the request field whose value is mapped to the HTTP request + // body, or `*` for mapping all request fields not captured by the path + // pattern to the HTTP body, or omitted for not having any HTTP request body. + // + // NOTE: the referred field must be present at the top-level of the request + // message type. + string body = 7; + + // Optional. The name of the response field whose value is mapped to the HTTP + // response body. When omitted, the entire response message will be used + // as the HTTP response body. + // + // NOTE: The referred field must be present at the top-level of the response + // message type. + string response_body = 12; + + // Additional HTTP bindings for the selector. Nested bindings must + // not contain an `additional_bindings` field themselves (that is, + // the nesting may only be one level deep). + repeated HttpRule additional_bindings = 11; +} + +// A custom pattern is used for defining custom HTTP verb. +message CustomHttpPattern { + // The name of this custom HTTP verb. + string kind = 1; + + // The path matched by this custom verb. + string path = 2; +} diff --git a/third_party/googleapis/google/api/httpbody.proto b/third_party/googleapis/google/api/httpbody.proto new file mode 100644 index 000000000..00c80aba9 --- /dev/null +++ b/third_party/googleapis/google/api/httpbody.proto @@ -0,0 +1,81 @@ +// Copyright 2015 Google LLC +// +// 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. + +syntax = "proto3"; + +package google.api; + +import "google/protobuf/any.proto"; + +option cc_enable_arenas = true; +option go_package = "google.golang.org/genproto/googleapis/api/httpbody;httpbody"; +option java_multiple_files = true; +option java_outer_classname = "HttpBodyProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// Message that represents an arbitrary HTTP body. It should only be used for +// payload formats that can't be represented as JSON, such as raw binary or +// an HTML page. +// +// +// This message can be used both in streaming and non-streaming API methods in +// the request as well as the response. +// +// It can be used as a top-level request field, which is convenient if one +// wants to extract parameters from either the URL or HTTP template into the +// request fields and also want access to the raw HTTP body. +// +// Example: +// +// message GetResourceRequest { +// // A unique request id. +// string request_id = 1; +// +// // The raw HTTP body is bound to this field. +// google.api.HttpBody http_body = 2; +// +// } +// +// service ResourceService { +// rpc GetResource(GetResourceRequest) +// returns (google.api.HttpBody); +// rpc UpdateResource(google.api.HttpBody) +// returns (google.protobuf.Empty); +// +// } +// +// Example with streaming methods: +// +// service CaldavService { +// rpc GetCalendar(stream google.api.HttpBody) +// returns (stream google.api.HttpBody); +// rpc UpdateCalendar(stream google.api.HttpBody) +// returns (stream google.api.HttpBody); +// +// } +// +// Use of this type only changes how the request and response bodies are +// handled, all other features will continue to work unchanged. +message HttpBody { + // The HTTP Content-Type header value specifying the content type of the body. + string content_type = 1; + + // The HTTP request/response body as raw binary. + bytes data = 2; + + // Application specific response metadata. Must be set in the first response + // for streaming APIs. + repeated google.protobuf.Any extensions = 3; +}