diff --git a/cmd/app/serve.go b/cmd/app/serve.go index e5b6ef3b3..b107a778f 100644 --- a/cmd/app/serve.go +++ b/cmd/app/serve.go @@ -31,6 +31,7 @@ import ( "github.com/sigstore/fulcio/pkg/ca/ephemeralca" "github.com/sigstore/fulcio/pkg/ca/fileca" googlecav1 "github.com/sigstore/fulcio/pkg/ca/googleca/v1" + "github.com/sigstore/fulcio/pkg/ca/kmsca" "github.com/sigstore/fulcio/pkg/ca/x509ca" "github.com/sigstore/fulcio/pkg/config" "github.com/sigstore/fulcio/pkg/ctl" @@ -53,7 +54,7 @@ func newServeCmd() *cobra.Command { cmd.Flags().StringVarP(&serveCmdConfigFilePath, "config", "c", "", "config file containing all settings") cmd.Flags().String("log_type", "dev", "logger type to use (dev/prod)") - cmd.Flags().String("ca", "", "googleca | pkcs11ca | fileca | ephemeralca (for testing)") + cmd.Flags().String("ca", "", "googleca | pkcs11ca | fileca | kmsca | ephemeralca (for testing)") cmd.Flags().String("aws-hsm-root-ca-path", "", "Path to root CA on disk (only used with AWS HSM)") cmd.Flags().String("gcp_private_ca_parent", "", "private ca parent: /projects//locations// (only used with --ca googleca)") cmd.Flags().String("hsm-caroot-id", "", "HSM ID for Root CA (only used with --ca pkcs11ca)") @@ -64,6 +65,8 @@ func newServeCmd() *cobra.Command { cmd.Flags().String("fileca-key", "", "Path to CA encrypted private key") cmd.Flags().String("fileca-key-passwd", "", "Password to decrypt CA private key") cmd.Flags().Bool("fileca-watch", true, "Watch filesystem for updates") + cmd.Flags().String("kms-key", "", "KMS key resource path") + cmd.Flags().String("cert-chain-path", "", "Path to PEM-encoded CA certificate chain") 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") @@ -101,7 +104,6 @@ func runServeCmd(cmd *cobra.Command, args []string) { // There's a MarkDeprecated function in cobra/pflags, but it doesn't use log.Logger log.Logger.Warn("gcp_private_ca_version is deprecated and will soon be removed; please remove it") } - case "fileca": if !viper.IsSet("fileca-cert") { log.Logger.Fatal("fileca-cert must be set to certificate path when using fileca") @@ -112,7 +114,13 @@ func runServeCmd(cmd *cobra.Command, args []string) { if !viper.IsSet("fileca-key-passwd") { log.Logger.Fatal("fileca-key-passwd must be set to encryption password for private key file when using fileca") } - + case "kmsca": + if !viper.IsSet("kms-key") { + log.Logger.Fatal("kms-key must be set when using kmsca") + } + if !viper.IsSet("cert-chain-path") { + log.Logger.Fatal("cert-chain-path must be set when using kmsca") + } case "ephemeralca": // this is a no-op since this is a self-signed in-memory CA for testing default: @@ -153,6 +161,8 @@ func runServeCmd(cmd *cobra.Command, args []string) { baseca, err = fileca.NewFileCA(certFile, keyFile, keyPass, watch) case "ephemeralca": baseca, err = ephemeralca.NewEphemeralCA() + case "kmsca": + baseca, err = kmsca.NewKmsCA(cmd.Context(), viper.GetString("kms-key"), viper.GetString("cert-chain-path")) default: err = fmt.Errorf("invalid value for configured CA: %v", baseca) } diff --git a/go.mod b/go.mod index 17f3b98cc..9398a4d9c 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/prometheus/client_golang v1.12.1 github.com/prometheus/client_model v0.2.0 github.com/prometheus/common v0.33.0 - github.com/sigstore/sigstore v1.2.1-0.20220328200116-ef48ee800626 + github.com/sigstore/sigstore v1.2.1-0.20220330193110-d7475aecf1db github.com/spf13/cobra v1.4.0 github.com/spf13/viper v1.10.1 github.com/stretchr/testify v1.7.1 @@ -31,3 +31,5 @@ require ( gopkg.in/square/go-jose.v2 v2.6.0 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b ) + +replace github.com/sigstore/sigstore v1.2.1-0.20220330193110-d7475aecf1db => github.com/haydentherapper/sigstore v1.1.1-0.20220331234123-c28e9d036bd4 diff --git a/go.sum b/go.sum index a8c3ee0a8..623197d0f 100644 --- a/go.sum +++ b/go.sum @@ -45,7 +45,9 @@ cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7 cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY= cloud.google.com/go/iam v0.1.0/go.mod h1:vcUNEa0pEm0qRVpmWepWaFMIAI8/hjB9mO8rNCJtF6c= +cloud.google.com/go/iam v0.1.1 h1:4CapQyNFjiksks1/x7jsvsygFPhihslYk5GptIrlX68= cloud.google.com/go/iam v0.1.1/go.mod h1:CKqrcnI/suGpybEHxZ7BMehL0oA4LpdyJdUlTl9jVMw= +cloud.google.com/go/kms v1.4.0 h1:iElbfoE61VeLhnZcGOltqL8HIly8Nhbe5t6JlH9GXjo= cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA= 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= @@ -62,24 +64,36 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7 filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU= filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go v62.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v63.0.0+incompatible h1:whPsa+jCHQSo5wGMPNLw4bz8q9Co2+vnXHzXGctoTaQ= +github.com/Azure/azure-sdk-for-go v63.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= +github.com/Azure/go-autorest/autorest v0.11.24 h1:1fIGgHKqVm54KIPT+q8Zmd1QlVsmHqeUGso5qm2BqqE= github.com/Azure/go-autorest/autorest v0.11.24/go.mod h1:G6kyRlFnTuSbEYkQGawPfsCswgme4iYf6rfSKUDzbCc= github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= +github.com/Azure/go-autorest/autorest/adal v0.9.18 h1:kLnPsRjzZZUF3K5REu/Kc+qMQrvuza2bwSnNdhmzLfQ= github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= +github.com/Azure/go-autorest/autorest/azure/auth v0.5.11 h1:P6bYXFoao05z5uhOQzbC3Qd8JqF3jUoocoTeIxkp2cA= github.com/Azure/go-autorest/autorest/azure/auth v0.5.11/go.mod h1:84w/uV8E37feW2NCJ08uT9VBfjfUHpgLVnG2InYD6cg= +github.com/Azure/go-autorest/autorest/azure/cli v0.4.5 h1:0W/yGmFdTIT77fvdlGZ0LMISoLHFJ7Tx4U0yeB+uFs4= github.com/Azure/go-autorest/autorest/azure/cli v0.4.5/go.mod h1:ADQAXrkgm7acgWVUNamOgh8YNrv4p27l3Wc55oVfpzg= +github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk= github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE= +github.com/Azure/go-autorest/autorest/validation v0.3.1 h1:AgyqjAd94fwNAoTjl/WQXg4VvFeRFpO+UhNyRXqF1ac= github.com/Azure/go-autorest/autorest/validation v0.3.1/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E= github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= @@ -118,6 +132,7 @@ github.com/PaesslerAG/jsonpath v0.1.1 h1:c1/AToHQMVsduPAa4Vh6xp2U0evy4t8SWp8imEs github.com/PaesslerAG/jsonpath v0.1.1/go.mod h1:lVboNxFGal/VwW6d9JzIy56bUsYAP6tH/x80vjnCseY= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/ReneKroon/ttlcache/v2 v2.11.0 h1:OvlcYFYi941SBN3v9dsDcC2N8vRxyHcCmJb3Vl4QMoM= github.com/ReneKroon/ttlcache/v2 v2.11.0/go.mod h1:mBxvsNY+BT8qLLd6CuAJubbKo6r0jh3nb5et22bbfGY= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= github.com/ThalesIgnite/crypto11 v1.2.5 h1:1IiIIEqYmBvUYFeMnHqRft4bwf/O36jryEUpY+9ef8E= @@ -133,12 +148,15 @@ github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hC github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= +github.com/armon/go-metrics v0.3.10 h1:FR+drcQStOe+32sYyJYyZ7FIdgoGGBnwLl+flodp8Uo= github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= -github.com/aws/aws-sdk-go v1.43.27/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= +github.com/aws/aws-sdk-go v1.43.28 h1:HrBUf2pYEMRB3GDkSa/bZ2lkZIe8gSUOz/IEupG1Te0= +github.com/aws/aws-sdk-go v1.43.28/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= github.com/beeker1121/goque v1.0.3-0.20191103205551-d618510128af/go.mod h1:84CWnaDz4g1tEVnFLnuBigmGK15oPohy0RfvSN8d4eg= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -159,6 +177,7 @@ github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8n github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= +github.com/cenkalti/backoff/v3 v3.2.2 h1:cfUAAO3yvKMYKPrvhDuHSwQnhZNk/RMHKdZqKTxfm6M= github.com/cenkalti/backoff/v3 v3.2.2/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -317,6 +336,7 @@ github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11 github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/docker/cli v20.10.12+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= @@ -364,13 +384,16 @@ github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqL github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/flynn/go-docopt v0.0.0-20140912013429-f6dd2ebbb31e/go.mod h1:HyVoz1Mz5Co8TFO8EupIdlcpwShBmY98dkT2xeHkvEI= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/frankban/quicktest v1.10.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= +github.com/frankban/quicktest v1.13.0 h1:yNZif1OkDfNoDfb9zZa9aXIpejNR4F23Wely0c+Qdqk= github.com/frankban/quicktest v1.13.0/go.mod h1:qLE0fzW0VuyUAJgPU19zByoIr0HtCHN/r/VLSOOIySU= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= @@ -413,7 +436,7 @@ github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTM github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= github.com/go-redis/redis/v8 v8.11.4/go.mod h1:2Z2wHZXdQpCDXEGzqMockDpNyYvi2l4Pxt6RJr792+w= -github.com/go-rod/rod v0.104.2/go.mod h1:SVRIBdiq0sXXDdQxISmWuY8g1kLIUT+Pgk4VZSbOM1s= +github.com/go-rod/rod v0.104.4/go.mod h1:trmrxxg+qUodIIQiYeyJbW5ZMo0FSajmdEGw2tHzlM4= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= @@ -460,6 +483,7 @@ github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= 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/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -498,6 +522,7 @@ 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/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 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= @@ -570,45 +595,59 @@ github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUo github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v1.0.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v1.1.0 h1:QsGcniKx5/LuX2eYoeL+Np3UKYPNaN7YKpTh29h8rbw= github.com/hashicorp/go-hclog v1.1.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-kms-wrapping/entropy v0.1.0/go.mod h1:d1g9WGtAunDNpek8jUIEJnBlbgKS1N2Q61QkHiZyR1g= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-plugin v1.4.3 h1:DXmvivbWD5qdiBts9TpBC7BYL1Aia5sxbRgQB+v6UZM= github.com/hashicorp/go-plugin v1.4.3/go.mod h1:5fGEH17QVwTTcR0zV7yhDPLLmFX9YSZ38b18Udy6vYQ= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= +github.com/hashicorp/go-retryablehttp v0.7.0 h1:eu1EI/mbirUgP5C8hVsTNaGZreBDlYiwC1FZWkvQPQ4= github.com/hashicorp/go-retryablehttp v0.7.0/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= +github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-secure-stdlib/base62 v0.1.1/go.mod h1:EdWO6czbmthiwZ3/PUsDV+UD1D5IRU4ActiaWGwt0Yw= github.com/hashicorp/go-secure-stdlib/mlock v0.1.1/go.mod h1:zq93CJChV6L9QTfGKtfBxKqD7BqqXx5O04A/ns2p5+I= +github.com/hashicorp/go-secure-stdlib/mlock v0.1.2 h1:p4AKXPPS24tO8Wc8i1gLvSKdmkiSY5xuju57czJ/IJQ= github.com/hashicorp/go-secure-stdlib/mlock v0.1.2/go.mod h1:zq93CJChV6L9QTfGKtfBxKqD7BqqXx5O04A/ns2p5+I= github.com/hashicorp/go-secure-stdlib/parseutil v0.1.1/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8= +github.com/hashicorp/go-secure-stdlib/parseutil v0.1.2 h1:Tz6v3Jb2DRnDCfifRSjYKG0m8dLdNq6bcDkB41en7nw= github.com/hashicorp/go-secure-stdlib/parseutil v0.1.2/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8= github.com/hashicorp/go-secure-stdlib/password v0.1.1/go.mod h1:9hH302QllNwu1o2TGYtSk8I8kTAN0ca1EHpwhm5Mmzo= github.com/hashicorp/go-secure-stdlib/strutil v0.1.1/go.mod h1:gKOamz3EwoIoJq7mlMIRBpVTAUn8qPCrEclOKKWhD3U= +github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9CdjCtrXrXGuOpxEA7Ts= github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4= github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.1/go.mod h1:l8slYwnJA26yBz+ErHpp2IRCLr0vuOMGBORIz4rRiAs= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc= github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE= github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.4.0 h1:aAQzgqIrRKRa7w75CKpbBxYsmUoPjzVm1W59ca1L0J4= github.com/hashicorp/go-version v1.4.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= 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= @@ -623,10 +662,15 @@ github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOn github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= +github.com/hashicorp/vault/api v1.5.0 h1:Bp6yc2bn7CWkOrVIzFT/Qurzx528bdavF3nz590eu28= github.com/hashicorp/vault/api v1.5.0/go.mod h1:LkMdrZnWNrFaQyYYazWVn7KshilfDidgVBq6YiTq/bM= +github.com/hashicorp/vault/sdk v0.4.1 h1:3SaHOJY687jY1fnB61PtL0cOkKItphrbLmux7T92HBo= github.com/hashicorp/vault/sdk v0.4.1/go.mod h1:aZ3fNuL5VNydQk8GcLJ2TV8YCRVvyaakYkhZRoVuhj0= github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= +github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 h1:xixZ2bWeofWV68J+x6AzmKuVM/JWCQwkWm6GW/MUR6I= github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= +github.com/haydentherapper/sigstore v1.1.1-0.20220331234123-c28e9d036bd4 h1:B26iYm6TTPB6a0uTSINIF6N8i1+kTrgUzvZsBtxr/rs= +github.com/haydentherapper/sigstore v1.1.1-0.20220331234123-c28e9d036bd4/go.mod h1:dzF7JvyOyg6kcwz7UxS05jGdqXxVg17JUQaQ36nvwZg= github.com/honeycombio/beeline-go v1.1.1 h1:sU8r4ae34uEL3/CguSl8Mr+Asz9DL1nfH9Wwk85Pc7U= github.com/honeycombio/beeline-go v1.1.1/go.mod h1:kN0cfUGBMfA87DyCYbiiLoSzWsnw3bluZvNEWtatHxk= github.com/honeycombio/libhoney-go v1.15.2 h1:5NGcjOxZZma13dmzNcl3OtGbF1hECA0XHJNHEb2t2ck= @@ -677,10 +721,13 @@ github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0f github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE= github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jmhodges/clock v0.0.0-20160418191101-880ee4c33548 h1:dYTbLf4m0a5u0KLmPfB6mgxbcV7588bOCx79hxa5Sr4= github.com/jmhodges/clock v0.0.0-20160418191101-880ee4c33548/go.mod h1:hGT6jSUVzF6no3QaDSMLGLEHtHSBSefs+MgcDWnmhmo= @@ -758,6 +805,7 @@ github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVc github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= @@ -768,6 +816,7 @@ github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2y github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= @@ -793,10 +842,13 @@ github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= @@ -807,6 +859,7 @@ github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGg github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= @@ -832,6 +885,7 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLA github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= @@ -878,6 +932,7 @@ github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqi github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= @@ -885,6 +940,7 @@ github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhEC github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/pierrec/lz4 v2.5.2+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM= github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -952,6 +1008,7 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig= @@ -967,8 +1024,6 @@ github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNX github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sigstore/sigstore v1.2.1-0.20220328200116-ef48ee800626 h1:ocuw0kEgUifM2NLm63T4vILh0YatZ8bD5LPxaqaTx9c= -github.com/sigstore/sigstore v1.2.1-0.20220328200116-ef48ee800626/go.mod h1:iujhJMoAxFbvcOKdVp5+HoPei9pg+2e1udEs8QSzuXE= github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= @@ -1020,6 +1075,7 @@ github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -1078,9 +1134,9 @@ github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/ysmood/goob v0.3.1/go.mod h1:S3lq113Y91y1UBf1wj1pFOxeahvfKkCk6mTWTWbDdWs= -github.com/ysmood/got v0.16.2/go.mod h1:pE1l4LOwOBhQg6A/8IAatkGp7uZjnalzrZolnlhhMgY= -github.com/ysmood/gotrace v0.2.2/go.mod h1:TzhIG7nHDry5//eYZDYcTzuJLYQIkykJzCRIo4/dzQM= -github.com/ysmood/gson v0.6.4/go.mod h1:3Kzs5zDl21g5F/BlLTNcuAGAYLKt2lV5G8D1zF3RNmg= +github.com/ysmood/got v0.19.1/go.mod h1:pE1l4LOwOBhQg6A/8IAatkGp7uZjnalzrZolnlhhMgY= +github.com/ysmood/gotrace v0.4.0/go.mod h1:TzhIG7nHDry5//eYZDYcTzuJLYQIkykJzCRIo4/dzQM= +github.com/ysmood/gson v0.7.0/go.mod h1:3Kzs5zDl21g5F/BlLTNcuAGAYLKt2lV5G8D1zF3RNmg= github.com/ysmood/leakless v0.7.0/go.mod h1:R8iAXPRaG97QJwqxs74RdwzcRHT1SWCGTNqY8q0JvMQ= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -1302,6 +1358,7 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1440,6 +1497,7 @@ golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 h1:GZokNIeuVkl3aZHJchRrr13WCsols02MLUcz1U9is6M= golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/pkg/ca/fileca/fileca.go b/pkg/ca/fileca/fileca.go index 57621c2f2..7f65e243c 100644 --- a/pkg/ca/fileca/fileca.go +++ b/pkg/ca/fileca/fileca.go @@ -16,24 +16,16 @@ package fileca import ( - "context" "crypto" - "crypto/rand" "crypto/x509" - "sync" "github.com/fsnotify/fsnotify" "github.com/sigstore/fulcio/pkg/ca" - "github.com/sigstore/fulcio/pkg/ca/x509ca" - "github.com/sigstore/fulcio/pkg/challenges" - "github.com/sigstore/sigstore/pkg/cryptoutils" + "github.com/sigstore/fulcio/pkg/ca/intermediateca" ) type fileCA struct { - sync.RWMutex - - certs []*x509.Certificate - key crypto.Signer + intermediateca.IntermediateCA } // NewFileCA returns a file backed certificate authority. Expects paths to a @@ -43,7 +35,7 @@ func NewFileCA(certPath, keyPath, keyPass string, watch bool) (ca.CertificateAut var fca fileCA var err error - fca.certs, fca.key, err = loadKeyPair(certPath, keyPath, keyPass) + fca.Certs, fca.Signer, err = loadKeyPair(certPath, keyPath, keyPass) if err != nil { return nil, err } @@ -68,43 +60,13 @@ func NewFileCA(certPath, keyPath, keyPass string, watch bool) (ca.CertificateAut return &fca, err } -func (fca *fileCA) updateX509KeyPair(certs []*x509.Certificate, key crypto.Signer) { +func (fca *fileCA) updateX509KeyPair(certs []*x509.Certificate, signer crypto.Signer) { fca.Lock() defer fca.Unlock() // NB: We use the RWLock to unsure a reading thread can't get a mismatching // cert / key pair by reading the attributes halfway through the update // below. - fca.certs = certs - fca.key = key -} - -func (fca *fileCA) getX509KeyPair() ([]*x509.Certificate, crypto.Signer) { - fca.RLock() - defer fca.RUnlock() - return fca.certs, fca.key -} - -// CreateCertificate issues code signing certificates -func (fca *fileCA) CreateCertificate(_ context.Context, subject *challenges.ChallengeResult) (*ca.CodeSigningCertificate, error) { - cert, err := x509ca.MakeX509(subject) - if err != nil { - return nil, err - } - - certChain, privateKey := fca.getX509KeyPair() - - finalCertBytes, err := x509.CreateCertificate(rand.Reader, cert, certChain[0], subject.PublicKey, privateKey) - if err != nil { - return nil, err - } - - return ca.CreateCSCFromDER(subject, finalCertBytes, certChain) -} - -func (fca *fileCA) Root(ctx context.Context) ([]byte, error) { - fca.RLock() - defer fca.RUnlock() - - return cryptoutils.MarshalCertificatesToPEM(fca.certs) + fca.Certs = certs + fca.Signer = signer } diff --git a/pkg/ca/fileca/fileca_test.go b/pkg/ca/fileca/fileca_test.go index d8dd267eb..49f29b5ba 100644 --- a/pkg/ca/fileca/fileca_test.go +++ b/pkg/ca/fileca/fileca_test.go @@ -57,7 +57,7 @@ func TestCertUpdate(t *testing.T) { t.Fatal(`Bad CA type`) } - _, key := fca.getX509KeyPair() + key := fca.Signer if _, ok = key.(ed25519.PrivateKey); !ok { t.Error(`first key should have been an ed25519 key`) } @@ -68,7 +68,7 @@ func TestCertUpdate(t *testing.T) { } fca.updateX509KeyPair(cert, key) - _, key = fca.getX509KeyPair() + key = fca.Signer if _, ok = key.(*ecdsa.PrivateKey); !ok { t.Fatal(`file CA should have been updated with ecdsa key`) diff --git a/pkg/ca/fileca/load.go b/pkg/ca/fileca/load.go index a2bd961b4..ed8cbf638 100644 --- a/pkg/ca/fileca/load.go +++ b/pkg/ca/fileca/load.go @@ -18,71 +18,30 @@ package fileca import ( "bytes" "crypto" - "crypto/ecdsa" - "crypto/ed25519" - "crypto/rsa" "crypto/x509" "errors" + "os" + "path/filepath" + "github.com/sigstore/fulcio/pkg/ca/intermediateca" + "github.com/sigstore/sigstore/pkg/cryptoutils" "go.step.sm/crypto/pemutil" ) func loadKeyPair(certPath, keyPath, keyPass string) ([]*x509.Certificate, crypto.Signer, error) { - var ( certs []*x509.Certificate err error key crypto.Signer ) - // NB: certs are ordered from leaf at certs[0] to root at - // certs[len(certs)-1] - certs, err = pemutil.ReadCertificateBundle(certPath) + data, err := os.ReadFile(filepath.Clean(certPath)) if err != nil { return nil, nil, err } - - // Verify certificate chain - { - roots := x509.NewCertPool() - roots.AddCert(certs[len(certs)-1]) - - intermediates := x509.NewCertPool() - if len(certs) > 2 { - for _, intermediate := range certs[1 : len(certs)-1] { - intermediates.AddCert(intermediate) - } - } - - opts := x509.VerifyOptions{ - Roots: roots, - Intermediates: intermediates, - KeyUsages: []x509.ExtKeyUsage{ - x509.ExtKeyUsageCodeSigning, - }, - } - if _, err := certs[0].Verify(opts); err != nil { - return nil, nil, err - } - - if !certs[0].IsCA { - return nil, nil, errors.New(`fileca: certificate is not a CA`) - } - - // If using an intermediate, verify that code signing extended key - // usage is set to satify extended key usage chainging - if len(certs) > 1 { - var hasExtKeyUsageCodeSigning bool - for _, extKeyUsage := range certs[0].ExtKeyUsage { - if extKeyUsage == x509.ExtKeyUsageCodeSigning { - hasExtKeyUsageCodeSigning = true - break - } - } - if !hasExtKeyUsageCodeSigning { - return nil, nil, errors.New(`fileca: certificate must have extended key usage code signing set to sign code signing certificates`) - } - } + certs, err = cryptoutils.LoadCertificatesFromPEM(bytes.NewReader(data)) + if err != nil { + return nil, nil, err } { @@ -98,46 +57,9 @@ func loadKeyPair(certPath, keyPath, keyPass string) ([]*x509.Certificate, crypto } } - if !valid(certs[0], key) { - return nil, nil, errors.New(`fileca: certificate public key and private key don't match`) + if err := intermediateca.VerifyCertChain(certs, key); err != nil { + return nil, nil, err } return certs, key, nil } - -func valid(cert *x509.Certificate, key crypto.Signer) bool { - if cert == nil || key == nil { - return false - } - - switch pub := cert.PublicKey.(type) { - case *rsa.PublicKey: - priv, ok := key.(*rsa.PrivateKey) - if !ok { - return false - } - if pub.N.Cmp(priv.N) != 0 { - return false - } - case *ecdsa.PublicKey: - priv, ok := key.(*ecdsa.PrivateKey) - if !ok { - return false - } - if pub.X.Cmp(priv.X) != 0 || pub.Y.Cmp(priv.Y) != 0 { - return false - } - case ed25519.PublicKey: - priv, ok := key.(ed25519.PrivateKey) - if !ok { - return false - } - if !bytes.Equal(priv.Public().(ed25519.PublicKey), pub) { - return false - } - default: - return false - } - - return true -} diff --git a/pkg/ca/fileca/watch_test.go b/pkg/ca/fileca/watch_test.go index 6ebd65927..ea75893b7 100644 --- a/pkg/ca/fileca/watch_test.go +++ b/pkg/ca/fileca/watch_test.go @@ -36,17 +36,13 @@ func cp(src, dst string) error { } func TestIOWatch(t *testing.T) { - dir, err := os.MkdirTemp("", "fileca") - if err != nil { - t.Fatal(`Failed to create temp dir`) - } - // defer os.RemoveAll(dir) + dir := t.TempDir() keyPath := filepath.Join(dir, "key.pem") certPath := filepath.Join(dir, "cert.pem") // Copy initial certs into place - err = cp("testdata/ed25519-key.pem", keyPath) + err := cp("testdata/ed25519-key.pem", keyPath) if err != nil { t.Fatal(`Couldn't copy test data to temp file`) } diff --git a/pkg/ca/intermediateca/fetch_ca_cert/fetch_ca_cert.go b/pkg/ca/intermediateca/fetch_ca_cert/fetch_ca_cert.go new file mode 100644 index 000000000..a2e307635 --- /dev/null +++ b/pkg/ca/intermediateca/fetch_ca_cert/fetch_ca_cert.go @@ -0,0 +1,169 @@ +// 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 main + +import ( + "context" + "crypto" + "crypto/x509" + "errors" + "flag" + "log" + "os" + "time" + + privateca "cloud.google.com/go/security/privateca/apiv1" + "github.com/sigstore/sigstore/pkg/cryptoutils" + privatecapb "google.golang.org/genproto/googleapis/cloud/security/privateca/v1" + "google.golang.org/protobuf/types/known/durationpb" + + // Register the provider-specific plugins + "github.com/sigstore/sigstore/pkg/signature/kms" + _ "github.com/sigstore/sigstore/pkg/signature/kms/aws" + _ "github.com/sigstore/sigstore/pkg/signature/kms/azure" + _ "github.com/sigstore/sigstore/pkg/signature/kms/gcp" + _ "github.com/sigstore/sigstore/pkg/signature/kms/hashivault" +) + +/* +To run: +go run pkg/ca/intermediateca/update/fetch_ca_cert.go \ + --kms-key="gcpkms://projects//locations//keyRings//cryptoKeys//versions/1" \ + --gcp-ca-parent="projects//locations//caPools/" \ + --output="chain.crt.pem" + +You must have the permissions to read the KMS key, and create a certificate in the CA pool. +*/ + +var ( + gcpCaParent = flag.String("gcp-ca-parent", "", "Resource path to GCP CA Service CA") + kmsKey = flag.String("kms-key", "", "Resource path to KMS key, starting with gcpkms://, awskms://, azurekms:// or hashivault://") + outputPath = flag.String("output", "", "Path to the output file") +) + +func fetchCACertificate(ctx context.Context, parent, kmsKey string, client *privateca.CertificateAuthorityClient) ([]*x509.Certificate, error) { + kmsSigner, err := kms.Get(ctx, kmsKey, crypto.SHA256) + if err != nil { + return nil, err + } + signer, _, err := kmsSigner.CryptoSigner(ctx, func(err error) {}) + if err != nil { + return nil, err + } + + pemPubKey, err := cryptoutils.MarshalPublicKeyToPEM(signer.Public()) + if err != nil { + return nil, err + } + + isCa := true + // default value of 0 for int32 + var maxIssuerPathLength int32 + + csr := &privatecapb.CreateCertificateRequest{ + Parent: parent, + Certificate: &privatecapb.Certificate{ + // Default to a very large lifetime - CA Service will truncate the + // lifetime to be no longer than the root's lifetime. + // 20 years (24 hours * 365 days * 20) + Lifetime: durationpb.New(time.Hour * 24 * 365 * 20), + CertificateConfig: &privatecapb.Certificate_Config{ + Config: &privatecapb.CertificateConfig{ + PublicKey: &privatecapb.PublicKey{ + Format: privatecapb.PublicKey_PEM, + Key: pemPubKey, + }, + X509Config: &privatecapb.X509Parameters{ + KeyUsage: &privatecapb.KeyUsage{ + BaseKeyUsage: &privatecapb.KeyUsage_KeyUsageOptions{ + CertSign: true, + CrlSign: true, + }, + ExtendedKeyUsage: &privatecapb.KeyUsage_ExtendedKeyUsageOptions{ + CodeSigning: true, + }, + }, + CaOptions: &privatecapb.X509Parameters_CaOptions{ + IsCa: &isCa, + MaxIssuerPathLength: &maxIssuerPathLength, + }, + }, + SubjectConfig: &privatecapb.CertificateConfig_SubjectConfig{ + Subject: &privatecapb.Subject{ + CommonName: "sigstore-intermediate", + Organization: "sigstore.dev", + }, + }, + }, + }, + }, + } + + resp, err := client.CreateCertificate(ctx, csr) + if err != nil { + return nil, err + } + + var pemCerts []string + pemCerts = append(pemCerts, resp.PemCertificate) + pemCerts = append(pemCerts, resp.PemCertificateChain...) + + var parsedCerts []*x509.Certificate + for _, c := range pemCerts { + certs, err := cryptoutils.UnmarshalCertificatesFromPEM([]byte(c)) + if err != nil { + return nil, err + } + if len(certs) != 1 { + return nil, errors.New("unexpected number of certificates returned") + } + parsedCerts = append(parsedCerts, certs[0]) + } + + return parsedCerts, nil +} + +func main() { + flag.Parse() + + if *gcpCaParent == "" { + log.Fatal("gcp-ca-parent must be set") + } + if *kmsKey == "" { + log.Fatal("kms-key must be set") + } + if *outputPath == "" { + log.Fatal("output must be set") + } + + client, err := privateca.NewCertificateAuthorityClient(context.Background()) + if err != nil { + log.Fatal(err) + } + parsedCerts, err := fetchCACertificate(context.Background(), *gcpCaParent, *kmsKey, client) + if err != nil { + log.Fatal(err) + } + pemCerts, err := cryptoutils.MarshalCertificatesToPEM(parsedCerts) + if err != nil { + log.Fatal(err) + } + + err = os.WriteFile(*outputPath, pemCerts, 0600) + if err != nil { + log.Fatal(err) + } +} diff --git a/pkg/ca/intermediateca/intermediateca.go b/pkg/ca/intermediateca/intermediateca.go new file mode 100644 index 000000000..894c4616c --- /dev/null +++ b/pkg/ca/intermediateca/intermediateca.go @@ -0,0 +1,124 @@ +// 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 intermediateca + +import ( + "context" + "crypto" + "crypto/rand" + "crypto/x509" + "errors" + "sync" + + "github.com/sigstore/fulcio/pkg/ca" + "github.com/sigstore/fulcio/pkg/ca/x509ca" + "github.com/sigstore/fulcio/pkg/challenges" + "github.com/sigstore/sigstore/pkg/cryptoutils" +) + +type IntermediateCA struct { + sync.RWMutex + + // certs is a chain of certificates from intermediate to root + Certs []*x509.Certificate + Signer crypto.Signer +} + +func (ica *IntermediateCA) CreateCertificate(ctx context.Context, challenge *challenges.ChallengeResult) (*ca.CodeSigningCertificate, error) { + cert, err := x509ca.MakeX509(challenge) + if err != nil { + return nil, err + } + + certChain, privateKey := ica.getX509KeyPair() + + finalCertBytes, err := x509.CreateCertificate(rand.Reader, cert, certChain[0], challenge.PublicKey, privateKey) + if err != nil { + return nil, err + } + + return ca.CreateCSCFromDER(challenge, finalCertBytes, certChain) +} + +func (ica *IntermediateCA) Root(ctx context.Context) ([]byte, error) { + ica.RLock() + defer ica.RUnlock() + + return cryptoutils.MarshalCertificatesToPEM(ica.Certs) +} + +func (ica *IntermediateCA) getX509KeyPair() ([]*x509.Certificate, crypto.Signer) { + ica.RLock() + defer ica.RUnlock() + + return ica.Certs, ica.Signer +} + +func VerifyCertChain(certs []*x509.Certificate, signer crypto.Signer) error { + if len(certs) == 0 { + return errors.New("certificate chain must contain at least one certificate") + } + + roots := x509.NewCertPool() + roots.AddCert(certs[len(certs)-1]) + + intermediates := x509.NewCertPool() + if len(certs) > 1 { + for _, intermediate := range certs[1 : len(certs)-1] { + intermediates.AddCert(intermediate) + } + } + + opts := x509.VerifyOptions{ + Roots: roots, + Intermediates: intermediates, + KeyUsages: []x509.ExtKeyUsage{ + x509.ExtKeyUsageCodeSigning, + }, + } + if _, err := certs[0].Verify(opts); err != nil { + return err + } + + if !certs[0].IsCA { + return errors.New("certificate is not a CA") + } + + // If using an intermediate, verify that code signing extended key + // usage is set to satify extended key usage chainging + if len(certs) > 1 { + var hasExtKeyUsageCodeSigning bool + for _, extKeyUsage := range certs[0].ExtKeyUsage { + if extKeyUsage == x509.ExtKeyUsageCodeSigning { + hasExtKeyUsageCodeSigning = true + break + } + } + if !hasExtKeyUsageCodeSigning { + return errors.New(`certificate must have extended key usage code signing set to sign code signing certificates`) + } + } + + if err := cryptoutils.EqualKeys(certs[0].PublicKey, signer.Public()); err != nil { + return err + } + + if err := cryptoutils.ValidatePubKey(signer.Public()); err != nil { + return err + } + + return nil +} diff --git a/pkg/ca/intermediateca/intermediateca_test.go b/pkg/ca/intermediateca/intermediateca_test.go new file mode 100644 index 000000000..da9226f86 --- /dev/null +++ b/pkg/ca/intermediateca/intermediateca_test.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 intermediateca + +import ( + "context" + "crypto/x509" + "reflect" + "strings" + "testing" + + "github.com/sigstore/fulcio/pkg/test" + "github.com/sigstore/sigstore/pkg/cryptoutils" + "github.com/sigstore/sigstore/pkg/signature" +) + +func TestIntermediateCARoot(t *testing.T) { + signer, _, err := signature.NewDefaultECDSASignerVerifier() + if err != nil { + t.Fatalf("unexpected error generating signer: %v", err) + } + + rootCert, rootKey, _ := test.GenerateRootCa() + subCert, _, _ := test.GenerateSubordinateCa(rootCert, rootKey) + certChain := []*x509.Certificate{subCert, rootCert} + pemChain, err := cryptoutils.MarshalCertificatesToPEM(certChain) + if err != nil { + t.Fatalf("unexpected error marshalling cert chain: %v", err) + } + + ica := IntermediateCA{ + Certs: certChain, + Signer: signer, + } + + rootBytes, err := ica.Root(context.TODO()) + if err != nil { + t.Fatalf("unexpected error reading root: %v", err) + } + + if !reflect.DeepEqual(pemChain, rootBytes) { + t.Fatal("expected cert chains to be equivalent") + } +} + +func TestIntermediateCAGetX509KeyPair(t *testing.T) { + signer, _, err := signature.NewDefaultECDSASignerVerifier() + if err != nil { + t.Fatalf("unexpected error generating signer: %v", err) + } + + rootCert, rootKey, _ := test.GenerateRootCa() + subCert, _, _ := test.GenerateSubordinateCa(rootCert, rootKey) + certChain := []*x509.Certificate{subCert, rootCert} + + ica := IntermediateCA{ + Certs: certChain, + Signer: signer, + } + + foundCertChain, foundSigner := ica.getX509KeyPair() + + if !reflect.DeepEqual(certChain, foundCertChain) { + t.Fatal("expected cert chains to be equivalent") + } + + if err := cryptoutils.EqualKeys(signer.Public(), foundSigner.Public()); err != nil { + t.Fatalf("expected keys to be equivalent, expected %v, got %v, error %v", signer.Public(), foundSigner.Public(), err) + } +} + +func TestIntermediateCAVerifyCertChain(t *testing.T) { + rootCert, rootKey, _ := test.GenerateRootCa() + subCert, subKey, _ := test.GenerateSubordinateCa(rootCert, rootKey) + leafCert, _, _ := test.GenerateLeafCert("subject", "oidc-issuer", subCert, subKey) + + err := VerifyCertChain([]*x509.Certificate{subCert, rootCert}, subKey) + if err != nil { + t.Fatalf("unexpected error verifying cert chain: %v", err) + } + + // Handles single certifiacte in chain + err = VerifyCertChain([]*x509.Certificate{rootCert}, rootKey) + if err != nil { + t.Fatalf("unexpected error verifying single cert chain: %v", err) + } + + // Handles multiple intermediates + subCert2, subKey2, _ := test.GenerateSubordinateCa(subCert, subKey) + err = VerifyCertChain([]*x509.Certificate{subCert2, subCert, rootCert}, subKey2) + if err != nil { + t.Fatalf("unexpected error verifying cert chain: %v", err) + } + + // Failure: Certificate is not a CA certificate + err = VerifyCertChain([]*x509.Certificate{leafCert}, nil) + if err == nil || !strings.Contains(err.Error(), "certificate is not a CA") { + t.Fatalf("expected error with non-CA cert: %v", err) + } + + // Failure: Certificate missing EKU + // Note that the wrong EKU will be caught by x509.Verify + invalidSubCert, invalidSubKey, _ := test.GenerateSubordinateCaWithoutEKU(rootCert, rootKey) + err = VerifyCertChain([]*x509.Certificate{invalidSubCert, rootCert}, invalidSubKey) + if err == nil || !strings.Contains(err.Error(), "certificate must have extended key usage code signing") { + t.Fatalf("expected error verifying cert chain without EKU: %v", err) + } + + // Failure: Invalid chain + rootCert2, _, _ := test.GenerateRootCa() + err = VerifyCertChain([]*x509.Certificate{subCert, rootCert2}, subKey) + if err == nil || !strings.Contains(err.Error(), "certificate signed by unknown authority") { + t.Fatalf("expected error verifying cert chain: %v", err) + } + + // Failure: Different signer with different key + signer, _, err := signature.NewDefaultECDSASignerVerifier() + if err != nil { + t.Fatalf("expected error generating signer: %v", err) + } + err = VerifyCertChain([]*x509.Certificate{subCert, rootCert}, signer) + if err == nil || !strings.Contains(err.Error(), "public keys are not equal") { + t.Fatalf("expected error verifying cert with mismatched public keys: %v", err) + } + + // Failure: Weak key + weakSubCert, weakSubKey, _ := test.GenerateWeakSubordinateCa(rootCert, rootKey) + err = VerifyCertChain([]*x509.Certificate{weakSubCert, rootCert}, weakSubKey) + if err == nil || !strings.Contains(err.Error(), "unsupported ec curve") { + t.Fatalf("expected error verifying weak cert chain: %v", err) + } + + // Failure: Empty chain + err = VerifyCertChain([]*x509.Certificate{}, weakSubKey) + if err == nil || !strings.Contains(err.Error(), "certificate chain must contain at least one certificate") { + t.Fatalf("expected error verifying with empty chain: %v", err) + } +} diff --git a/pkg/ca/kmsca/kmsca.go b/pkg/ca/kmsca/kmsca.go new file mode 100644 index 000000000..9caf17385 --- /dev/null +++ b/pkg/ca/kmsca/kmsca.go @@ -0,0 +1,67 @@ +// 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 kmsca + +import ( + "bytes" + "context" + "crypto" + "os" + "path/filepath" + + "github.com/sigstore/fulcio/pkg/ca" + "github.com/sigstore/fulcio/pkg/ca/intermediateca" + "github.com/sigstore/sigstore/pkg/cryptoutils" + "github.com/sigstore/sigstore/pkg/signature/kms" + + // Register the provider-specific plugins + _ "github.com/sigstore/sigstore/pkg/signature/kms/aws" + _ "github.com/sigstore/sigstore/pkg/signature/kms/azure" + _ "github.com/sigstore/sigstore/pkg/signature/kms/gcp" + _ "github.com/sigstore/sigstore/pkg/signature/kms/hashivault" +) + +type kmsCA struct { + intermediateca.IntermediateCA +} + +func NewKmsCA(ctx context.Context, kmsKey, certPath string) (ca.CertificateAuthority, error) { + var ica kmsCA + + kmsSigner, err := kms.Get(ctx, kmsKey, crypto.SHA256) + if err != nil { + return nil, err + } + signer, _, err := kmsSigner.CryptoSigner(ctx, func(err error) {}) + if err != nil { + return nil, err + } + ica.Signer = signer + + data, err := os.ReadFile(filepath.Clean(certPath)) + if err != nil { + return nil, err + } + ica.Certs, err = cryptoutils.LoadCertificatesFromPEM(bytes.NewReader(data)) + if err != nil { + return nil, err + } + if err := intermediateca.VerifyCertChain(ica.Certs, ica.Signer); err != nil { + return nil, err + } + + return &ica, nil +} diff --git a/pkg/ca/kmsca/kmsca_test.go b/pkg/ca/kmsca/kmsca_test.go new file mode 100644 index 000000000..4966abd77 --- /dev/null +++ b/pkg/ca/kmsca/kmsca_test.go @@ -0,0 +1,102 @@ +// 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 kmsca + +import ( + "context" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/x509" + "os" + "path/filepath" + "reflect" + "strings" + "testing" + + "github.com/sigstore/fulcio/pkg/test" + "github.com/sigstore/sigstore/pkg/cryptoutils" + "github.com/sigstore/sigstore/pkg/signature/kms/fake" + _ "github.com/sigstore/sigstore/pkg/signature/kms/fake" +) + +func TestNewKmsCA(t *testing.T) { + dir := t.TempDir() + certPath := filepath.Join(dir, "cert.pem") + + rootCert, rootKey, _ := test.GenerateRootCa() + + priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + t.Fatalf("error generating ecdsa private key: %v", err) + } + + subCert, _ := test.GenerateSubordinateCaWithPublicKey(priv.Public(), rootCert, rootKey) + + pemChain, err := cryptoutils.MarshalCertificatesToPEM([]*x509.Certificate{subCert, rootCert}) + if err != nil { + t.Fatalf("error marshalling cert chain: %v", err) + } + err = os.WriteFile(certPath, pemChain, 0600) + if err != nil { + t.Fatalf("error writing pem chain: %v", err) + } + + ca, err := NewKmsCA(context.WithValue(context.TODO(), fake.KmsCtxKey{}, priv), "fakekms://key", certPath) + if err != nil { + t.Fatalf("unexpected error creating KMS CA: %v", err) + } + + // Expect certificate chain from Root matches provided certificate chain + rootBytes, err := ca.Root(context.TODO()) + if err != nil { + t.Fatalf("error fetching root: %v", err) + } + if !reflect.DeepEqual(rootBytes, pemChain) { + t.Fatal("cert chains do not match") + } + + // Expect signer and certificate's public keys match + ica := ca.(*kmsCA) + if err := cryptoutils.EqualKeys(ica.Signer.Public(), priv.Public()); err != nil { + t.Fatalf("keys between CA and signer do not match: %v", err) + } + if !reflect.DeepEqual(ica.Certs, []*x509.Certificate{subCert, rootCert}) { + t.Fatalf("expected certificate chains to match: %v", err) + } + + // Failure: Mismatch between signer and certificate key + otherPriv, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + ca, err = NewKmsCA(context.WithValue(context.TODO(), fake.KmsCtxKey{}, otherPriv), "fakekms://key", certPath) + if err == nil || !strings.Contains(err.Error(), "ecdsa public keys are not equal") { + t.Fatalf("expected error with mismatched public keys, got %v", err) + } + + // Failure: Invalid certificate chain + otherRootCert, _, _ := test.GenerateRootCa() + pemChain, err = cryptoutils.MarshalCertificatesToPEM([]*x509.Certificate{subCert, otherRootCert}) + if err != nil { + t.Fatalf("error marshalling cert chain: %v", err) + } + err = os.WriteFile(certPath, pemChain, 0600) + if err != nil { + t.Fatalf("error writing pem chain: %v", err) + } + ca, err = NewKmsCA(context.WithValue(context.TODO(), fake.KmsCtxKey{}, priv), "fakekms://key", certPath) + if err == nil || !strings.Contains(err.Error(), "certificate signed by unknown authority") { + t.Fatalf("expected error with invalid certificate chain, got %v", err) + } +} diff --git a/pkg/test/cert_utils.go b/pkg/test/cert_utils.go new file mode 100644 index 000000000..db5116065 --- /dev/null +++ b/pkg/test/cert_utils.go @@ -0,0 +1,225 @@ +// 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 test + +import ( + "crypto" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/x509" + "crypto/x509/pkix" + "encoding/asn1" + "math/big" + "time" +) + +/* +To use: + +rootCert, rootKey, _ := GenerateRootCa() +subCert, subKey, _ := GenerateSubordinateCa(rootCert, rootKey) +leafCert, _, _ := GenerateLeafCert("subject", "oidc-issuer", subCert, subKey) + +roots := x509.NewCertPool() +subs := x509.NewCertPool() +roots.AddCert(rootCert) +subs.AddCert(subCert) +opts := x509.VerifyOptions{ + Roots: roots, + Intermediates: subs, + KeyUsages: []x509.ExtKeyUsage{ + x509.ExtKeyUsageCodeSigning, + }, +} +_, err := leafCert.Verify(opts) +*/ + +func createCertificate(template *x509.Certificate, parent *x509.Certificate, pub interface{}, priv crypto.Signer) (*x509.Certificate, error) { + certBytes, err := x509.CreateCertificate(rand.Reader, template, parent, pub, priv) + if err != nil { + return nil, err + } + + cert, err := x509.ParseCertificate(certBytes) + if err != nil { + return nil, err + } + return cert, nil +} + +func GenerateRootCa() (*x509.Certificate, *ecdsa.PrivateKey, error) { + rootTemplate := &x509.Certificate{ + SerialNumber: big.NewInt(1), + Subject: pkix.Name{ + CommonName: "sigstore", + Organization: []string{"sigstore.dev"}, + }, + NotBefore: time.Now().Add(-5 * time.Minute), + NotAfter: time.Now().Add(5 * time.Hour), + KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign, + BasicConstraintsValid: true, + IsCA: true, + } + + priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + return nil, nil, err + } + + cert, err := createCertificate(rootTemplate, rootTemplate, &priv.PublicKey, priv) + if err != nil { + return nil, nil, err + } + + return cert, priv, nil +} + +func GenerateSubordinateCa(rootTemplate *x509.Certificate, rootPriv crypto.Signer) (*x509.Certificate, *ecdsa.PrivateKey, error) { + subTemplate := &x509.Certificate{ + SerialNumber: big.NewInt(1), + Subject: pkix.Name{ + CommonName: "sigstore-sub", + Organization: []string{"sigstore.dev"}, + }, + NotBefore: time.Now().Add(-2 * time.Minute), + NotAfter: time.Now().Add(2 * time.Hour), + KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageCodeSigning}, + BasicConstraintsValid: true, + IsCA: true, + } + + priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + return nil, nil, err + } + + cert, err := createCertificate(subTemplate, rootTemplate, &priv.PublicKey, rootPriv) + if err != nil { + return nil, nil, err + } + + return cert, priv, nil +} + +// GenerateSubordinateCaWithPublicKey takes a public key to sign instead of generating a keypair. +func GenerateSubordinateCaWithPublicKey(pub crypto.PublicKey, rootTemplate *x509.Certificate, rootPriv crypto.Signer) (*x509.Certificate, error) { + subTemplate := &x509.Certificate{ + SerialNumber: big.NewInt(1), + Subject: pkix.Name{ + CommonName: "sigstore-sub", + Organization: []string{"sigstore.dev"}, + }, + NotBefore: time.Now().Add(-2 * time.Minute), + NotAfter: time.Now().Add(2 * time.Hour), + KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageCodeSigning}, + BasicConstraintsValid: true, + IsCA: true, + } + + cert, err := createCertificate(subTemplate, rootTemplate, pub, rootPriv) + if err != nil { + return nil, err + } + + return cert, nil +} + +func GenerateWeakSubordinateCa(rootTemplate *x509.Certificate, rootPriv crypto.Signer) (*x509.Certificate, *ecdsa.PrivateKey, error) { + subTemplate := &x509.Certificate{ + SerialNumber: big.NewInt(1), + Subject: pkix.Name{ + CommonName: "sigstore-sub", + Organization: []string{"sigstore.dev"}, + }, + NotBefore: time.Now().Add(-2 * time.Minute), + NotAfter: time.Now().Add(2 * time.Hour), + KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageCodeSigning}, + BasicConstraintsValid: true, + IsCA: true, + } + + priv, err := ecdsa.GenerateKey(elliptic.P224(), rand.Reader) + if err != nil { + return nil, nil, err + } + + cert, err := createCertificate(subTemplate, rootTemplate, &priv.PublicKey, rootPriv) + if err != nil { + return nil, nil, err + } + + return cert, priv, nil +} + +func GenerateSubordinateCaWithoutEKU(rootTemplate *x509.Certificate, rootPriv crypto.Signer) (*x509.Certificate, *ecdsa.PrivateKey, error) { + subTemplate := &x509.Certificate{ + SerialNumber: big.NewInt(1), + Subject: pkix.Name{ + CommonName: "sigstore-sub", + Organization: []string{"sigstore.dev"}, + }, + NotBefore: time.Now().Add(-2 * time.Minute), + NotAfter: time.Now().Add(2 * time.Hour), + KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign, + BasicConstraintsValid: true, + IsCA: true, + } + + priv, err := ecdsa.GenerateKey(elliptic.P224(), rand.Reader) + if err != nil { + return nil, nil, err + } + + cert, err := createCertificate(subTemplate, rootTemplate, &priv.PublicKey, rootPriv) + if err != nil { + return nil, nil, err + } + + return cert, priv, nil +} + +func GenerateLeafCert(subject string, oidcIssuer string, parentTemplate *x509.Certificate, parentPriv crypto.Signer) (*x509.Certificate, *ecdsa.PrivateKey, error) { + certTemplate := &x509.Certificate{ + SerialNumber: big.NewInt(1), + EmailAddresses: []string{subject}, + NotBefore: time.Now().Add(-1 * time.Minute), + NotAfter: time.Now().Add(time.Hour), + KeyUsage: x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageCodeSigning}, + IsCA: false, + ExtraExtensions: []pkix.Extension{{ + // OID for OIDC Issuer extension + Id: asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 1}, + Critical: false, + Value: []byte(oidcIssuer), + }}, + } + + priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + return nil, nil, err + } + + cert, err := createCertificate(certTemplate, parentTemplate, &priv.PublicKey, parentPriv) + if err != nil { + return nil, nil, err + } + + return cert, priv, nil +}