From 725788d63e8bc37fdef5f39d9bc1cc12d63ad40f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Jun 2024 09:28:48 -0400 Subject: [PATCH 01/56] Bump the all group across 1 directory with 6 updates (#1699) * Bump the all group across 1 directory with 6 updates Bumps the all group with 3 updates in the / directory: [chainguard.dev/go-grpc-kit](https://github.com/chainguard-dev/go-grpc-kit), [github.com/spf13/cobra](https://github.com/spf13/cobra) and google.golang.org/protobuf. Updates `chainguard.dev/go-grpc-kit` from 0.17.3 to 0.17.5 - [Release notes](https://github.com/chainguard-dev/go-grpc-kit/releases) - [Commits](https://github.com/chainguard-dev/go-grpc-kit/compare/v0.17.3...v0.17.5) Updates `github.com/grpc-ecosystem/grpc-gateway/v2` from 2.19.1 to 2.20.0 - [Release notes](https://github.com/grpc-ecosystem/grpc-gateway/releases) - [Changelog](https://github.com/grpc-ecosystem/grpc-gateway/blob/main/.goreleaser.yml) - [Commits](https://github.com/grpc-ecosystem/grpc-gateway/compare/v2.19.1...v2.20.0) Updates `github.com/spf13/cobra` from 1.8.0 to 1.8.1 - [Release notes](https://github.com/spf13/cobra/releases) - [Commits](https://github.com/spf13/cobra/compare/v1.8.0...v1.8.1) Updates `google.golang.org/genproto/googleapis/api` from 0.0.0-20240513163218-0867130af1f8 to 0.0.0-20240520151616-dc85e6b867a5 - [Commits](https://github.com/googleapis/go-genproto/commits) Updates `google.golang.org/grpc` from 1.63.2 to 1.64.0 - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.63.2...v1.64.0) Updates `google.golang.org/protobuf` from 1.34.1 to 1.34.2 --- updated-dependencies: - dependency-name: chainguard.dev/go-grpc-kit dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all - dependency-name: github.com/grpc-ecosystem/grpc-gateway/v2 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: all - dependency-name: github.com/spf13/cobra dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all - dependency-name: google.golang.org/genproto/googleapis/api dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all - dependency-name: google.golang.org/grpc dependency-type: direct:production update-type: version-update:semver-minor dependency-group: all - dependency-name: google.golang.org/protobuf dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all ... Signed-off-by: dependabot[bot] * fix deprecation Signed-off-by: cpanato * update e2e tests Signed-off-by: cpanato --------- Signed-off-by: dependabot[bot] Signed-off-by: cpanato Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: cpanato --- .github/workflows/verify-k8s.yml | 4 +- cmd/app/http.go | 2 +- cmd/app/http_test.go | 4 +- cmd/app/serve_test.go | 2 +- go.mod | 32 ++++++++-------- go.sum | 66 ++++++++++++++++---------------- pkg/server/grpc_server_test.go | 55 +++++++++++++++----------- 7 files changed, 88 insertions(+), 77 deletions(-) diff --git a/.github/workflows/verify-k8s.yml b/.github/workflows/verify-k8s.yml index 8357b4a9c..5693f3761 100644 --- a/.github/workflows/verify-k8s.yml +++ b/.github/workflows/verify-k8s.yml @@ -83,9 +83,9 @@ jobs: - uses: ko-build/setup-ko@ace48d793556083a76f1e3e6068850c1f4a369aa # v0.6 - name: Setup Cluster - uses: chainguard-dev/actions/setup-kind@f5a6616ce43b6ffabeddb87480a13721fffb3588 # main + uses: chainguard-dev/actions/setup-kind@f94883c3bd16936401291899070258f855b5d849 # main with: - k8s-version: 1.24.x + k8s-version: 1.26.x registry-authority: ${{ env.REGISTRY_NAME }}:${{ env.REGISTRY_PORT }} - name: Generate temporary CA files diff --git a/cmd/app/http.go b/cmd/app/http.go index 1c73d75bb..d85d03d8c 100644 --- a/cmd/app/http.go +++ b/cmd/app/http.go @@ -63,7 +63,7 @@ func createHTTPServer(ctx context.Context, serverEndpoint string, grpcServer, le } else { opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials())) } - cc, err := grpc.Dial(grpcServer.grpcServerEndpoint, opts...) + cc, err := grpc.NewClient(grpcServer.grpcServerEndpoint, opts...) if err != nil { log.Logger.Fatal(err) } diff --git a/cmd/app/http_test.go b/cmd/app/http_test.go index debb70036..b93b71be5 100644 --- a/cmd/app/http_test.go +++ b/cmd/app/http_test.go @@ -53,7 +53,7 @@ func setupHTTPServer(t *testing.T) (httpServer, string) { } var wg sync.WaitGroup grpcServer.startTCPListener(&wg) - conn, err := grpc.Dial(grpcServer.grpcServerEndpoint, grpc.WithTransportCredentials(insecure.NewCredentials())) + conn, err := grpc.NewClient(grpcServer.grpcServerEndpoint, grpc.WithTransportCredentials(insecure.NewCredentials())) defer func() { if conn != nil { _ = conn.Close() @@ -100,7 +100,7 @@ func setupHTTPServerWithGRPCTLS(t *testing.T) (httpServer, string) { var wg sync.WaitGroup grpcServer.startTCPListener(&wg) - conn, err := grpc.Dial(grpcServer.grpcServerEndpoint, grpc.WithTransportCredentials(insecure.NewCredentials())) + conn, err := grpc.NewClient(grpcServer.grpcServerEndpoint, grpc.WithTransportCredentials(insecure.NewCredentials())) defer func() { if conn != nil { _ = conn.Close() diff --git a/cmd/app/serve_test.go b/cmd/app/serve_test.go index b3e82fa43..fe1f6b854 100644 --- a/cmd/app/serve_test.go +++ b/cmd/app/serve_test.go @@ -72,7 +72,7 @@ func TestDuplex(t *testing.T) { var grpcRootCert string t.Run("grpc", func(t *testing.T) { // Grab the rootcert with the v2 endpoint - conn, err := grpc.Dial(fmt.Sprintf("localhost:%d", port), grpc.WithTransportCredentials(insecure.NewCredentials())) + conn, err := grpc.NewClient(fmt.Sprintf("localhost:%d", port), grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { t.Fatal(err) } diff --git a/go.mod b/go.mod index 1c3f1b5f0..8355a6e01 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/sigstore/fulcio go 1.21.9 require ( - chainguard.dev/go-grpc-kit v0.17.3 + chainguard.dev/go-grpc-kit v0.17.5 cloud.google.com/go/security v1.17.0 github.com/PaesslerAG/jsonpath v0.1.1 github.com/ThalesIgnite/crypto11 v1.2.5 @@ -17,7 +17,7 @@ require ( github.com/google/tink/go v1.7.0 github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20210315223345-82c243799c99 - github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 github.com/hashicorp/golang-lru v1.0.2 github.com/magiconair/properties v1.8.7 github.com/prometheus/client_golang v1.19.1 @@ -29,16 +29,16 @@ require ( github.com/sigstore/sigstore/pkg/signature/kms/azure v1.8.4 github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.8.4 github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.8.4 - github.com/spf13/cobra v1.8.0 + github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.19.0 github.com/spiffe/go-spiffe/v2 v2.2.0 go.step.sm/crypto v0.45.0 go.uber.org/zap v1.27.0 google.golang.org/api v0.181.0 - google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8 - google.golang.org/grpc v1.63.2 - google.golang.org/protobuf v1.34.1 + google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5 + google.golang.org/grpc v1.64.0 + google.golang.org/protobuf v1.34.2 gopkg.in/square/go-jose.v2 v2.6.0 gopkg.in/yaml.v3 v3.0.1 sigs.k8s.io/release-utils v0.8.2 @@ -77,7 +77,7 @@ require ( github.com/aws/smithy-go v1.20.2 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v3 v3.2.2 // indirect - github.com/cenkalti/backoff/v4 v4.2.1 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/chainguard-dev/slogctx v1.2.2 // indirect github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be // indirect @@ -129,15 +129,15 @@ require ( github.com/thales-e-security/pool v0.0.2 // indirect github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect - go.opentelemetry.io/otel v1.24.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 // indirect - go.opentelemetry.io/otel/metric v1.24.0 // indirect - go.opentelemetry.io/otel/sdk v1.24.0 // indirect - go.opentelemetry.io/otel/trace v1.24.0 // indirect - go.opentelemetry.io/proto/otlp v1.1.0 // indirect + go.opentelemetry.io/otel v1.27.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 // indirect + go.opentelemetry.io/otel/metric v1.27.0 // indirect + go.opentelemetry.io/otel/sdk v1.27.0 // indirect + go.opentelemetry.io/otel/trace v1.27.0 // indirect + go.opentelemetry.io/proto/otlp v1.2.0 // indirect go.uber.org/multierr v1.11.0 // indirect goa.design/goa v2.2.5+incompatible // indirect golang.org/x/crypto v0.24.0 // indirect @@ -150,7 +150,7 @@ require ( golang.org/x/text v0.16.0 // indirect golang.org/x/time v0.5.0 // indirect google.golang.org/genproto v0.0.0-20240401170217-c3f982113cda // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240520151616-dc85e6b867a5 // indirect gopkg.in/go-jose/go-jose.v2 v2.6.3 // indirect gopkg.in/ini.v1 v1.67.0 // indirect k8s.io/klog/v2 v2.120.1 // indirect diff --git a/go.sum b/go.sum index 6c9f8c5b1..5c182f613 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -chainguard.dev/go-grpc-kit v0.17.3 h1:gmFAibYg6yWEY/Pxj9Ci5tPyPKY9/2DunRCd10yjhrk= -chainguard.dev/go-grpc-kit v0.17.3/go.mod h1:VqcMN1nCR52/kAKNeF0TVl4qZM+ZaRkmyit7TE5LYmM= +chainguard.dev/go-grpc-kit v0.17.5 h1:y0MHgqm3v0LKKQfxPJV57wkXxa8uMSpNTjhtHbNh1DY= +chainguard.dev/go-grpc-kit v0.17.5/go.mod h1:vQGcwZiX6jXwhyLPCZwVMvjITD+XcrSmQzuCTW/XcVc= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.113.0 h1:g3C70mn3lWfckKBiCVsAshabrDg01pQ0pnX1MNtnMkA= cloud.google.com/go v0.113.0/go.mod h1:glEqlogERKYeePz6ZdkcLJ28Q2I6aERgDDErBg9GzO8= @@ -79,8 +79,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= 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.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= -github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -92,7 +92,7 @@ github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be h1:J5BL github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be/go.mod h1:mk5IQ+Y0ZeO87b858TlA645sVcEcbiX6YqP98kt+7+w= github.com/coreos/go-oidc/v3 v3.10.0 h1:tDnXHnLyiTVyT/2zLDGj09pFPkhND8Gl8lnTRhoEaJU= github.com/coreos/go-oidc/v3 v3.10.0/go.mod h1:5j11xcw0D3+SGxn6Z/WFADsgcWVMyNAlSQupk0KK3ac= -github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -177,8 +177,8 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDa github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20210315223345-82c243799c99 h1:JYghRBlGCZyCF2wNUJ8W0cwaQdtpcssJ4CgC406g+WU= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20210315223345-82c243799c99/go.mod h1:3bDW6wMZJB7tiONtC/1Xpicra6Wp5GgbTbQWCbI5fkc= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0QDGLKzqOmktBjT+Is= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= 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= @@ -314,8 +314,8 @@ github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= -github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= -github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= 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/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= @@ -358,24 +358,24 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0 h1:vS1Ao/R55RNV4O7TA2Qopok8yN+X0LIP6RVWLFkprck= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0/go.mod h1:BMsdeOxN04K0L5FNUBfjFdvwWGNe/rkmSwH4Aelu/X0= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= -go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= -go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 h1:t6wl9SPayj+c7lEIFgm4ooDBZVb01IhLB4InpomhRw8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0/go.mod h1:iSDOcsnSA5INXzZtwaBPrKp/lWu/V14Dd+llD0oI2EA= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 h1:Mw5xcxMwlqoJd97vwPxA8isEaIoxsta9/Q51+TTJLGE= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0/go.mod h1:CQNu9bj7o7mC6U7+CA/schKEYakYXWr79ucDHTMGhCM= -go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= -go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= -go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= -go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= -go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= -go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= -go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= -go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= +go.opentelemetry.io/otel v1.27.0 h1:9BZoF3yMK/O1AafMiQTVu0YDj5Ea4hPhxCs7sGva+cg= +go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 h1:R9DE4kQ4k+YtfLI2ULwX82VtNQ2J8yZmA7ZIF/D+7Mc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0/go.mod h1:OQFyQVrDlbe+R7xrEyDr/2Wr67Ol0hRUgsfA+V5A95s= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 h1:qFffATk0X+HD+f1Z8lswGiOQYKHRlzfmdJm0wEaVrFA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0/go.mod h1:MOiCmryaYtc+V0Ei+Tx9o5S1ZjA7kzLucuVuyzBZloQ= +go.opentelemetry.io/otel/metric v1.27.0 h1:hvj3vdEKyeCi4YaYfNjv2NUje8FqKqUY8IlF0FxV/ik= +go.opentelemetry.io/otel/metric v1.27.0/go.mod h1:mVFgmRlhljgBiuk/MP/oKylr4hs85GZAylncepAX/ak= +go.opentelemetry.io/otel/sdk v1.27.0 h1:mlk+/Y1gLPLn84U4tI8d3GNJmGT/eXe3ZuOXN9kTWmI= +go.opentelemetry.io/otel/sdk v1.27.0/go.mod h1:Ha9vbLwJE6W86YstIywK2xFfPjbWlCuwPtMkKdz/Y4A= +go.opentelemetry.io/otel/trace v1.27.0 h1:IqYb813p7cmbHk0a5y6pD5JPakbVfftRXABGt5/Rscw= +go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4= +go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94= +go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= go.step.sm/crypto v0.45.0 h1:Z0WYAaaOYrJmKP9sJkPW+6wy3pgN3Ija8ek/D4serjc= go.step.sm/crypto v0.45.0/go.mod h1:6IYlT0L2jfj81nVyCPpvA5cORy0EVHPhieSgQyuwHIY= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -496,10 +496,10 @@ google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20240401170217-c3f982113cda h1:wu/KJm9KJwpfHWhkkZGohVC6KRrc1oJNr4jwtQMOQXw= google.golang.org/genproto v0.0.0-20240401170217-c3f982113cda/go.mod h1:g2LLCvCeCSir/JJSWosk19BR4NVxGqHUC6rxIRsd7Aw= -google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8 h1:W5Xj/70xIA4x60O/IFyXivR5MGqblAb8R3w26pnD6No= -google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8/go.mod h1:vPrPUTsDCYxXWjP7clS81mZ6/803D8K4iM9Ma27VKas= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8 h1:mxSlqyb8ZAHsYDCfiXN1EDdNTdvjUJSLY+OnAUtYNYA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8/go.mod h1:I7Y+G38R2bu5j1aLzfFmQfTcU/WnFuqDwLZAbvKTKpM= +google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5 h1:P8OJ/WCl/Xo4E4zoe4/bifHpSmmKwARqyqE4nW6J2GQ= +google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5/go.mod h1:RGnPtTG7r4i8sPlNyDeikXF99hMM+hN6QMm4ooG9g2g= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240520151616-dc85e6b867a5 h1:Q2RxlXqh1cgzzUgV261vBO2jI5R/3DD1J2pM0nI4NhU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240520151616-dc85e6b867a5/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= @@ -507,8 +507,8 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= -google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY= +google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= 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= @@ -518,8 +518,8 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 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.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= -google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= diff --git a/pkg/server/grpc_server_test.go b/pkg/server/grpc_server_test.go index cf7991eec..854a70c6f 100644 --- a/pkg/server/grpc_server_test.go +++ b/pkg/server/grpc_server_test.go @@ -50,6 +50,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials/insecure" + "google.golang.org/grpc/resolver" "google.golang.org/grpc/status" "google.golang.org/grpc/test/bufconn" "gopkg.in/square/go-jose.v2" @@ -62,6 +63,10 @@ const ( bufSize = 1024 * 1024 ) +func init() { + resolver.SetDefaultScheme("passthrough") +} + var lis *bufconn.Listener func passFulcioConfigThruContext(cfg *config.FulcioConfig) grpc.UnaryServerInterceptor { @@ -79,7 +84,7 @@ func passFulcioConfigThruContext(cfg *config.FulcioConfig) grpc.UnaryServerInter } } -func setupGRPCForTest(ctx context.Context, t *testing.T, cfg *config.FulcioConfig, ctl *ctclient.LogClient, ca ca.CertificateAuthority) (*grpc.Server, *grpc.ClientConn) { +func setupGRPCForTest(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))) @@ -91,8 +96,14 @@ func setupGRPCForTest(ctx context.Context, t *testing.T, cfg *config.FulcioConfi } }() - conn, err := grpc.DialContext(ctx, "bufnet", - grpc.WithContextDialer(bufDialer), grpc.WithTransportCredentials(insecure.NewCredentials())) + // Create a dial option using a custom dialer + dialOptions := []grpc.DialOption{ + grpc.WithContextDialer(bufDialer), + grpc.WithTransportCredentials(insecure.NewCredentials()), + } + + // Use grpc.NewClient to create the client connection + conn, err := grpc.NewClient("passthrough", dialOptions...) if err != nil { t.Fatal("could not create grpc connection", err) } @@ -107,7 +118,7 @@ func bufDialer(ctx context.Context, _ string) (net.Conn, error) { func TestMissingGetTrustBundleFails(t *testing.T) { ctx := context.Background() cfg := &config.FulcioConfig{} - server, conn := setupGRPCForTest(ctx, t, cfg, nil, &FailingCertificateAuthority{}) + server, conn := setupGRPCForTest(t, cfg, nil, &FailingCertificateAuthority{}) defer func() { server.Stop() conn.Close() @@ -132,7 +143,7 @@ func TestGetTrustBundleSuccess(t *testing.T) { cfg := &config.FulcioConfig{} ctClient, eca := createCA(cfg, t) ctx := context.Background() - server, conn := setupGRPCForTest(ctx, t, cfg, ctClient, eca) + server, conn := setupGRPCForTest(t, cfg, ctClient, eca) defer func() { server.Stop() conn.Close() @@ -257,7 +268,7 @@ func TestGetConfiguration(t *testing.T) { ctClient, eca := createCA(cfg, t) ctx := context.Background() - server, conn := setupGRPCForTest(ctx, t, cfg, ctClient, eca) + server, conn := setupGRPCForTest(t, cfg, ctClient, eca) defer func() { server.Stop() conn.Close() @@ -397,7 +408,7 @@ func TestGetConfigurationFromYaml(t *testing.T) { ctClient, eca := createCA(cfg, t) ctx := context.Background() - server, conn := setupGRPCForTest(ctx, t, cfg, ctClient, eca) + server, conn := setupGRPCForTest(t, cfg, ctClient, eca) defer func() { server.Stop() conn.Close() @@ -517,7 +528,7 @@ func TestAPIWithEmail(t *testing.T) { ctClient, eca := createCA(cfg, t) ctx := context.Background() - server, conn := setupGRPCForTest(ctx, t, cfg, ctClient, eca) + server, conn := setupGRPCForTest(t, cfg, ctClient, eca) defer func() { server.Stop() conn.Close() @@ -606,7 +617,7 @@ func TestAPIWithUsername(t *testing.T) { ctClient, eca := createCA(cfg, t) ctx := context.Background() - server, conn := setupGRPCForTest(ctx, t, cfg, ctClient, eca) + server, conn := setupGRPCForTest(t, cfg, ctClient, eca) defer func() { server.Stop() conn.Close() @@ -704,7 +715,7 @@ func TestAPIWithUriSubject(t *testing.T) { ctClient, eca := createCA(cfg, t) ctx := context.Background() - server, conn := setupGRPCForTest(ctx, t, cfg, ctClient, eca) + server, conn := setupGRPCForTest(t, cfg, ctClient, eca) defer func() { server.Stop() conn.Close() @@ -797,7 +808,7 @@ func TestAPIWithKubernetes(t *testing.T) { ctClient, eca := createCA(cfg, t) ctx := context.Background() - server, conn := setupGRPCForTest(ctx, t, cfg, ctClient, eca) + server, conn := setupGRPCForTest(t, cfg, ctClient, eca) defer func() { server.Stop() conn.Close() @@ -886,7 +897,7 @@ func TestAPIWithBuildkite(t *testing.T) { ctClient, eca := createCA(cfg, t) ctx := context.Background() - server, conn := setupGRPCForTest(ctx, t, cfg, ctClient, eca) + server, conn := setupGRPCForTest(t, cfg, ctClient, eca) defer func() { server.Stop() conn.Close() @@ -1004,7 +1015,7 @@ func TestAPIWithGitHub(t *testing.T) { ctClient, eca := createCA(cfg, t) ctx := context.Background() - server, conn := setupGRPCForTest(ctx, t, cfg, ctClient, eca) + server, conn := setupGRPCForTest(t, cfg, ctClient, eca) defer func() { server.Stop() conn.Close() @@ -1172,7 +1183,7 @@ func TestAPIWithGitLab(t *testing.T) { ctClient, eca := createCA(cfg, t) ctx := context.Background() - server, conn := setupGRPCForTest(ctx, t, cfg, ctClient, eca) + server, conn := setupGRPCForTest(t, cfg, ctClient, eca) defer func() { server.Stop() conn.Close() @@ -1315,7 +1326,7 @@ func TestAPIWithCodefresh(t *testing.T) { ctClient, eca := createCA(cfg, t) ctx := context.Background() - server, conn := setupGRPCForTest(ctx, t, cfg, ctClient, eca) + server, conn := setupGRPCForTest(t, cfg, ctClient, eca) defer func() { server.Stop() conn.Close() @@ -1423,7 +1434,7 @@ func TestAPIWithIssuerClaimConfig(t *testing.T) { ctClient, eca := createCA(cfg, t) ctx := context.Background() - server, conn := setupGRPCForTest(ctx, t, cfg, ctClient, eca) + server, conn := setupGRPCForTest(t, cfg, ctClient, eca) defer func() { server.Stop() conn.Close() @@ -1499,7 +1510,7 @@ func TestAPIWithCSRChallenge(t *testing.T) { ctClient, eca := createCA(cfg, t) ctx := context.Background() - server, conn := setupGRPCForTest(ctx, t, cfg, ctClient, eca) + server, conn := setupGRPCForTest(t, cfg, ctClient, eca) defer func() { server.Stop() conn.Close() @@ -1581,7 +1592,7 @@ func TestAPIWithInsecurePublicKey(t *testing.T) { ctClient, eca := createCA(cfg, t) ctx := context.Background() - server, conn := setupGRPCForTest(ctx, t, cfg, ctClient, eca) + server, conn := setupGRPCForTest(t, cfg, ctClient, eca) defer func() { server.Stop() conn.Close() @@ -1656,7 +1667,7 @@ func TestAPIWithoutPublicKey(t *testing.T) { ctClient, eca := createCA(cfg, t) ctx := context.Background() - server, conn := setupGRPCForTest(ctx, t, cfg, ctClient, eca) + server, conn := setupGRPCForTest(t, cfg, ctClient, eca) defer func() { server.Stop() conn.Close() @@ -1732,7 +1743,7 @@ func TestAPIWithInvalidChallenge(t *testing.T) { ctClient, eca := createCA(cfg, t) ctx := context.Background() - server, conn := setupGRPCForTest(ctx, t, cfg, ctClient, eca) + server, conn := setupGRPCForTest(t, cfg, ctClient, eca) defer func() { server.Stop() conn.Close() @@ -1800,7 +1811,7 @@ func TestAPIWithInvalidCSR(t *testing.T) { ctClient, eca := createCA(cfg, t) ctx := context.Background() - server, conn := setupGRPCForTest(ctx, t, cfg, ctClient, eca) + server, conn := setupGRPCForTest(t, cfg, ctClient, eca) defer func() { server.Stop() conn.Close() @@ -1861,7 +1872,7 @@ func TestAPIWithInvalidCSRSignature(t *testing.T) { ctClient, eca := createCA(cfg, t) ctx := context.Background() - server, conn := setupGRPCForTest(ctx, t, cfg, ctClient, eca) + server, conn := setupGRPCForTest(t, cfg, ctClient, eca) defer func() { server.Stop() conn.Close() From 2a8c3cf21d913fd70dd16bc1348c8d66a57909b0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Jun 2024 13:30:00 +0000 Subject: [PATCH 02/56] Bump go.step.sm/crypto from 0.45.0 to 0.47.1 Bumps [go.step.sm/crypto](https://github.com/smallstep/crypto) from 0.45.0 to 0.47.1. - [Release notes](https://github.com/smallstep/crypto/releases) - [Commits](https://github.com/smallstep/crypto/compare/v0.45.0...v0.47.1) --- updated-dependencies: - dependency-name: go.step.sm/crypto dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 42 ++++++++++++++--------------- go.sum | 84 +++++++++++++++++++++++++++++----------------------------- 2 files changed, 63 insertions(+), 63 deletions(-) diff --git a/go.mod b/go.mod index 8355a6e01..a10c6de35 100644 --- a/go.mod +++ b/go.mod @@ -33,10 +33,10 @@ require ( github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.19.0 github.com/spiffe/go-spiffe/v2 v2.2.0 - go.step.sm/crypto v0.45.0 + go.step.sm/crypto v0.47.1 go.uber.org/zap v1.27.0 - google.golang.org/api v0.181.0 - google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5 + google.golang.org/api v0.183.0 + google.golang.org/genproto/googleapis/api v0.0.0-20240521202816-d264139d666e google.golang.org/grpc v1.64.0 google.golang.org/protobuf v1.34.2 gopkg.in/square/go-jose.v2 v2.6.0 @@ -45,35 +45,35 @@ require ( ) require ( - cloud.google.com/go v0.113.0 // indirect - cloud.google.com/go/auth v0.4.1 // indirect + cloud.google.com/go v0.114.0 // indirect + cloud.google.com/go/auth v0.5.1 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect cloud.google.com/go/compute/metadata v0.3.0 // indirect cloud.google.com/go/iam v1.1.8 // indirect cloud.google.com/go/kms v1.17.1 // indirect cloud.google.com/go/longrunning v0.5.7 // indirect filippo.io/edwards25519 v1.1.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.1.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0 // indirect github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect github.com/PaesslerAG/gval v1.0.0 // indirect github.com/aws/aws-sdk-go v1.53.10 // indirect - github.com/aws/aws-sdk-go-v2 v1.27.0 // indirect - github.com/aws/aws-sdk-go-v2/config v1.27.16 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.17.16 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.3 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.7 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.7 // indirect + github.com/aws/aws-sdk-go-v2 v1.27.1 // indirect + github.com/aws/aws-sdk-go-v2/config v1.27.17 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.17.17 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.4 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.8 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.8 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.9 // indirect - github.com/aws/aws-sdk-go-v2/service/kms v1.32.1 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.20.9 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.3 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.28.10 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.10 // indirect + github.com/aws/aws-sdk-go-v2/service/kms v1.32.2 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.20.10 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.4 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.28.11 // indirect github.com/aws/smithy-go v1.20.2 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v3 v3.2.2 // indirect @@ -143,14 +143,14 @@ require ( golang.org/x/crypto v0.24.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/oauth2 v0.20.0 // indirect + golang.org/x/oauth2 v0.21.0 // indirect golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.21.0 // indirect golang.org/x/term v0.21.0 // indirect golang.org/x/text v0.16.0 // indirect golang.org/x/time v0.5.0 // indirect - google.golang.org/genproto v0.0.0-20240401170217-c3f982113cda // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240520151616-dc85e6b867a5 // indirect + google.golang.org/genproto v0.0.0-20240528184218-531527333157 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect gopkg.in/go-jose/go-jose.v2 v2.6.3 // indirect gopkg.in/ini.v1 v1.67.0 // indirect k8s.io/klog/v2 v2.120.1 // indirect diff --git a/go.sum b/go.sum index 5c182f613..134b19a4a 100644 --- a/go.sum +++ b/go.sum @@ -1,10 +1,10 @@ chainguard.dev/go-grpc-kit v0.17.5 h1:y0MHgqm3v0LKKQfxPJV57wkXxa8uMSpNTjhtHbNh1DY= chainguard.dev/go-grpc-kit v0.17.5/go.mod h1:vQGcwZiX6jXwhyLPCZwVMvjITD+XcrSmQzuCTW/XcVc= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.113.0 h1:g3C70mn3lWfckKBiCVsAshabrDg01pQ0pnX1MNtnMkA= -cloud.google.com/go v0.113.0/go.mod h1:glEqlogERKYeePz6ZdkcLJ28Q2I6aERgDDErBg9GzO8= -cloud.google.com/go/auth v0.4.1 h1:Z7YNIhlWRtrnKlZke7z3GMqzvuYzdc2z98F9D1NV5Hg= -cloud.google.com/go/auth v0.4.1/go.mod h1:QVBuVEKpCn4Zp58hzRGvL0tjRGU0YqdRTdCHM1IHnro= +cloud.google.com/go v0.114.0 h1:OIPFAdfrFDFO2ve2U7r/H5SwSbBzEdrBdE7xkgwc+kY= +cloud.google.com/go v0.114.0/go.mod h1:ZV9La5YYxctro1HTPug5lXH/GefROyW8PPD4T8n9J8E= +cloud.google.com/go/auth v0.5.1 h1:0QNO7VThG54LUzKiQxv8C6x1YX7lUrzlAa1nVLF8CIw= +cloud.google.com/go/auth v0.5.1/go.mod h1:vbZT8GjzDf3AVqCcQmqeeM32U9HBFc32vVVAbwDsa6s= cloud.google.com/go/auth/oauth2adapt v0.2.2 h1:+TTV8aXpjeChS9M+aTtN/TjdQnzJvmzKFt//oWu7HX4= cloud.google.com/go/auth/oauth2adapt v0.2.2/go.mod h1:wcYjgpZI9+Yu7LyYBg4pqSiaRkfEK3GQcpb7C/uyF1Q= cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= @@ -19,12 +19,12 @@ cloud.google.com/go/security v1.17.0 h1:u4RCnEQPvlrrnFRFinU0T3WsjtrsQErkWBfqTM5o cloud.google.com/go/security v1.17.0/go.mod h1:eSuFs0SlBv1gWg7gHIoF0hYOvcSwJCek/GFXtgO6aA0= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 h1:E+OJmp2tPvt1W+amx48v1eqbjDYsgN+RzP4q16yV5eM= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1/go.mod h1:a6xsAQUZg+VsS3TJ05SRp524Hs4pZ/AeFSr5ENf0Yjo= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0 h1:1nGuui+4POelzDwI7RG56yfQJHCnKvwfMoU7VsEp+Zg= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0/go.mod h1:99EvauvlcJ1U06amZiksfYz/3aFGyIhWGHVyiZXtBAI= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0 h1:U2rTu3Ef+7w9FHKIAXM6ZyqF3UOWJZ12zIm8zECAFfg= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 h1:jBQA3cKT4L2rWMpgE7Yt3Hwh2aUj8KXjIGLxjHeYNNo= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0/go.mod h1:4OG6tQ9EOP/MT0NMjDlRzWoVFxfu9rN9B2X+tlSVktg= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.0 h1:H+U3Gk9zY56G3u872L82bk4thcsy2Gghb9ExT4Zvm1o= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.0/go.mod h1:mgrmMSgaLp9hmax62XQTd0N4aAqSE5E0DulSpVYK7vc= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.1.0 h1:DRiANoJTiW6obBQe3SqZizkuV1PEgfiiGivmVocDy64= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.1.0/go.mod h1:qLIye2hwb/ZouqhpSD9Zn3SJipvpEnz1Ywl3VUk9Y0s= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0 h1:D3occbWoio4EBLkbkevetNMAVX197GkzbUMtqjGWn80= @@ -44,32 +44,32 @@ github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-sdk-go v1.53.10 h1:3enP5l5WtezT9Ql+XZqs56JBf5YUd/FEzTCg///OIGY= github.com/aws/aws-sdk-go v1.53.10/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= -github.com/aws/aws-sdk-go-v2 v1.27.0 h1:7bZWKoXhzI+mMR/HjdMx8ZCC5+6fY0lS5tr0bbgiLlo= -github.com/aws/aws-sdk-go-v2 v1.27.0/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM= -github.com/aws/aws-sdk-go-v2/config v1.27.16 h1:knpCuH7laFVGYTNd99Ns5t+8PuRjDn4HnnZK48csipM= -github.com/aws/aws-sdk-go-v2/config v1.27.16/go.mod h1:vutqgRhDUktwSge3hrC3nkuirzkJ4E/mLj5GvI0BQas= -github.com/aws/aws-sdk-go-v2/credentials v1.17.16 h1:7d2QxY83uYl0l58ceyiSpxg9bSbStqBC6BeEeHEchwo= -github.com/aws/aws-sdk-go-v2/credentials v1.17.16/go.mod h1:Ae6li/6Yc6eMzysRL2BXlPYvnrLLBg3D11/AmOjw50k= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.3 h1:dQLK4TjtnlRGb0czOht2CevZ5l6RSyRWAnKeGd7VAFE= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.3/go.mod h1:TL79f2P6+8Q7dTsILpiVST+AL9lkF6PPGI167Ny0Cjw= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.7 h1:lf/8VTF2cM+N4SLzaYJERKEWAXq8MOMpZfU6wEPWsPk= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.7/go.mod h1:4SjkU7QiqK2M9oozyMzfZ/23LmUY+h3oFqhdeP5OMiI= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.7 h1:4OYVp0705xu8yjdyoWix0r9wPIRXnIzzOoUpQVHIJ/g= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.7/go.mod h1:vd7ESTEvI76T2Na050gODNmNU7+OyKrIKroYTu4ABiI= +github.com/aws/aws-sdk-go-v2 v1.27.1 h1:xypCL2owhog46iFxBKKpBcw+bPTX/RJzwNj8uSilENw= +github.com/aws/aws-sdk-go-v2 v1.27.1/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM= +github.com/aws/aws-sdk-go-v2/config v1.27.17 h1:L0JZN7Gh7pT6u5CJReKsLhGKparqNKui+mcpxMXjDZc= +github.com/aws/aws-sdk-go-v2/config v1.27.17/go.mod h1:MzM3balLZeaafYcPz8IihAmam/aCz6niPQI0FdprxW0= +github.com/aws/aws-sdk-go-v2/credentials v1.17.17 h1:b3Dk9uxQByS9sc6r0sc2jmxsJKO75eOcb9nNEiaUBLM= +github.com/aws/aws-sdk-go-v2/credentials v1.17.17/go.mod h1:e4khg9iY08LnFK/HXQDWMf9GDaiMari7jWPnXvKAuBU= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.4 h1:0cSfTYYL9qiRcdi4Dvz+8s3JUgNR2qvbgZkXcwPEEEk= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.4/go.mod h1:Wjn5O9eS7uSi7vlPKt/v0MLTncANn9EMmoDvnzJli6o= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.8 h1:RnLB7p6aaFMRfyQkD6ckxR7myCC9SABIqSz4czYUUbU= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.8/go.mod h1:XH7dQJd+56wEbP1I4e4Duo+QhSMxNArE8VP7NuUOTeM= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.8 h1:jzApk2f58L9yW9q1GEab3BMMFWUkkiZhyrRUtbwUbKU= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.8/go.mod h1:WqO+FftfO3tGePUtQxPXM6iODVfqMwsVMgTbG/ZXIdQ= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 h1:Ji0DY1xUsUr3I8cHps0G+XM3WWU16lP6yG8qu1GAZAs= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2/go.mod h1:5CsjAbs3NlGQyZNFACh+zztPDI7fU6eW9QsxjfnuBKg= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.9 h1:Wx0rlZoEJR7JwlSZcHnEa7CNjrSIyVxMFWGAaXy4fJY= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.9/go.mod h1:aVMHdE0aHO3v+f/iw01fmXV/5DbfQ3Bi9nN7nd9bE9Y= -github.com/aws/aws-sdk-go-v2/service/kms v1.32.1 h1:FARrQLRQXpCFYylIUVF1dRij6YbPCmtwudq9NBk4kFc= -github.com/aws/aws-sdk-go-v2/service/kms v1.32.1/go.mod h1:8lETO9lelSG2B6KMXFh2OwPPqGV6WQM3RqLAEjP1xaU= -github.com/aws/aws-sdk-go-v2/service/sso v1.20.9 h1:aD7AGQhvPuAxlSUfo0CWU7s6FpkbyykMhGYMvlqTjVs= -github.com/aws/aws-sdk-go-v2/service/sso v1.20.9/go.mod h1:c1qtZUWtygI6ZdvKppzCSXsDOq5I4luJPZ0Ud3juFCA= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.3 h1:Pav5q3cA260Zqez42T9UhIlsd9QeypszRPwC9LdSSsQ= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.3/go.mod h1:9lmoVDVLz/yUZwLaQ676TK02fhCu4+PgRSmMaKR1ozk= -github.com/aws/aws-sdk-go-v2/service/sts v1.28.10 h1:69tpbPED7jKPyzMcrwSvhWcJ9bPnZsZs18NT40JwM0g= -github.com/aws/aws-sdk-go-v2/service/sts v1.28.10/go.mod h1:0Aqn1MnEuitqfsCNyKsdKLhDUOr4txD/g19EfiUqgws= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.10 h1:7kZqP7akv0enu6ykJhb9OYlw16oOrSy+Epus8o/VqMY= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.10/go.mod h1:gYVF3nM1ApfTRDj9pvdhootBb8WbiIejuqn4w8ruMes= +github.com/aws/aws-sdk-go-v2/service/kms v1.32.2 h1:WuwRxTSPc+E4dwDRmxh4TILJsnYoqm41KTb11pRkzBA= +github.com/aws/aws-sdk-go-v2/service/kms v1.32.2/go.mod h1:qEy625xFxrw6hA+eOAD030wmLERPa7LNCArh+gAC+8o= +github.com/aws/aws-sdk-go-v2/service/sso v1.20.10 h1:ItKVmFwbyb/ZnCWf+nu3XBVmUirpO9eGEQd7urnBA0s= +github.com/aws/aws-sdk-go-v2/service/sso v1.20.10/go.mod h1:5XKooCTi9VB/xZmJDvh7uZ+v3uQ7QdX6diOyhvPA+/w= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.4 h1:QMSCYDg3Iyls0KZc/dk3JtS2c1lFfqbmYO10qBPPkJk= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.4/go.mod h1:MZ/PVYU/mRbmSF6WK3ybCYHjA2mig8utVokDEVLDgE0= +github.com/aws/aws-sdk-go-v2/service/sts v1.28.11 h1:HYS0csS7UJxdYRoG+bGgUYrSwVnV3/ece/wHm90TApM= +github.com/aws/aws-sdk-go-v2/service/sts v1.28.11/go.mod h1:QXnthRM35zI92048MMwfFChjFmoufTdhtHmouwNfhhU= github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q= github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -376,8 +376,8 @@ go.opentelemetry.io/otel/trace v1.27.0 h1:IqYb813p7cmbHk0a5y6pD5JPakbVfftRXABGt5 go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4= go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94= go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= -go.step.sm/crypto v0.45.0 h1:Z0WYAaaOYrJmKP9sJkPW+6wy3pgN3Ija8ek/D4serjc= -go.step.sm/crypto v0.45.0/go.mod h1:6IYlT0L2jfj81nVyCPpvA5cORy0EVHPhieSgQyuwHIY= +go.step.sm/crypto v0.47.1 h1:XvqgWLA1OTJXkmkmD6QSDZrmGKP4flv3PEoau60htcU= +go.step.sm/crypto v0.47.1/go.mod h1:0fz8+Am8oIwfOJgr9HHf7MwTa7Gffliv35VxDrQqU0Y= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -425,8 +425,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.20.0 h1:4mQdhULixXKP1rwYBW0vAijoXnkTG0BLCDRzfe1idMo= -golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= +golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= 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-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -486,20 +486,20 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T 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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.181.0 h1:rPdjwnWgiPPOJx3IcSAQ2III5aX5tCer6wMpa/xmZi4= -google.golang.org/api v0.181.0/go.mod h1:MnQ+M0CFsfUwA5beZ+g/vCBCPXvtmZwRz2qzZk8ih1k= +google.golang.org/api v0.183.0 h1:PNMeRDwo1pJdgNcFQ9GstuLe/noWKIc89pRWRLMvLwE= +google.golang.org/api v0.183.0/go.mod h1:q43adC5/pHoSZTx5h2mSmdF7NcyfW9JuDyIOJAgS9ZQ= 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/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20240401170217-c3f982113cda h1:wu/KJm9KJwpfHWhkkZGohVC6KRrc1oJNr4jwtQMOQXw= -google.golang.org/genproto v0.0.0-20240401170217-c3f982113cda/go.mod h1:g2LLCvCeCSir/JJSWosk19BR4NVxGqHUC6rxIRsd7Aw= -google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5 h1:P8OJ/WCl/Xo4E4zoe4/bifHpSmmKwARqyqE4nW6J2GQ= -google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5/go.mod h1:RGnPtTG7r4i8sPlNyDeikXF99hMM+hN6QMm4ooG9g2g= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240520151616-dc85e6b867a5 h1:Q2RxlXqh1cgzzUgV261vBO2jI5R/3DD1J2pM0nI4NhU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240520151616-dc85e6b867a5/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/genproto v0.0.0-20240528184218-531527333157 h1:u7WMYrIrVvs0TF5yaKwKNbcJyySYf+HAIFXxWltJOXE= +google.golang.org/genproto v0.0.0-20240528184218-531527333157/go.mod h1:ubQlAQnzejB8uZzszhrTCU2Fyp6Vi7ZE5nn0c3W8+qQ= +google.golang.org/genproto/googleapis/api v0.0.0-20240521202816-d264139d666e h1:SkdGTrROJl2jRGT/Fxv5QUf9jtdKCQh4KQJXbXVLAi0= +google.golang.org/genproto/googleapis/api v0.0.0-20240521202816-d264139d666e/go.mod h1:LweJcLbyVij6rCex8YunD8DYR5VDonap/jYl3ZRxcIU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 h1:Zy9XzmMEflZ/MAaA7vNcoebnRAld7FsPW1EeBB7V0m8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= From 7437ab7c01b703f34ef9411ddfe4b1a7f9c0ebf3 Mon Sep 17 00:00:00 2001 From: Tomas Turek Date: Fri, 21 Jun 2024 12:38:16 +0200 Subject: [PATCH 03/56] Update /healthz probe to use localhost for gRPC readiness checks Signed-off-by: Tomas Turek --- cmd/app/http.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/app/http.go b/cmd/app/http.go index d85d03d8c..648fb68ca 100644 --- a/cmd/app/http.go +++ b/cmd/app/http.go @@ -63,7 +63,8 @@ func createHTTPServer(ctx context.Context, serverEndpoint string, grpcServer, le } else { opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials())) } - cc, err := grpc.NewClient(grpcServer.grpcServerEndpoint, opts...) + grpcHealthEndpoint := fmt.Sprintf("localhost:%s", viper.GetString("grpc-port")) + cc, err := grpc.NewClient(grpcHealthEndpoint, opts...) if err != nil { log.Logger.Fatal(err) } From 76d06f45654f81a5941df9dc086141e28bd0e2d8 Mon Sep 17 00:00:00 2001 From: cpanato Date: Sat, 22 Jun 2024 11:06:27 +0200 Subject: [PATCH 04/56] bump to go1.22.4 and update goreleaser and golangci-lint Signed-off-by: cpanato --- .github/workflows/validate-release.yml | 6 +++--- .github/workflows/verify.yml | 2 +- .goreleaser.yml | 1 + release/cloudbuild.yaml | 8 ++++---- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/.github/workflows/validate-release.yml b/.github/workflows/validate-release.yml index db5dfe4f6..1d81c195e 100644 --- a/.github/workflows/validate-release.yml +++ b/.github/workflows/validate-release.yml @@ -33,9 +33,9 @@ jobs: steps: - name: Check Signature run: | - cosign verify ghcr.io/gythialy/golang-cross:v1.22.3-0@sha256:3217c1e30a7081d73500e620987947d1539cfebc99064ba0f7d5d6eef399475e \ + cosign verify ghcr.io/gythialy/golang-cross:v1.22.4-0@sha256:7769c9e4c92f1b598410566270a0aac39f6d0f68491e5bf0862df4ff0f11f06b \ --certificate-oidc-issuer https://token.actions.githubusercontent.com \ - --certificate-identity "https://github.com/gythialy/golang-cross/.github/workflows/release-golang-cross.yml@refs/tags/v1.22.3-0" + --certificate-identity "https://github.com/gythialy/golang-cross/.github/workflows/release-golang-cross.yml@refs/tags/v1.22.4-0" env: TUF_ROOT: /tmp @@ -44,7 +44,7 @@ jobs: needs: - check-signature container: - image: ghcr.io/gythialy/golang-cross:v1.22.3-0@sha256:3217c1e30a7081d73500e620987947d1539cfebc99064ba0f7d5d6eef399475e + image: ghcr.io/gythialy/golang-cross:v1.22.4-0@sha256:7769c9e4c92f1b598410566270a0aac39f6d0f68491e5bf0862df4ff0f11f06b steps: - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index 0f80673a9..32544d9f1 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -71,7 +71,7 @@ jobs: uses: golangci/golangci-lint-action@a4f60bb28d35aeee14e6880718e0c85ff1882e64 # v6.0.1 timeout-minutes: 10 with: - version: v1.57 + version: v1.59 oidc-config: name: oidc-config diff --git a/.goreleaser.yml b/.goreleaser.yml index 9a55fb619..1e863edcb 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -1,4 +1,5 @@ project_name: fulcio +version: 2 env: - GO111MODULE=on diff --git a/release/cloudbuild.yaml b/release/cloudbuild.yaml index 9893fd65d..472cf894b 100644 --- a/release/cloudbuild.yaml +++ b/release/cloudbuild.yaml @@ -38,13 +38,13 @@ steps: - TUF_ROOT=/tmp args: - 'verify' - - 'ghcr.io/gythialy/golang-cross:v1.22.3-0@sha256:3217c1e30a7081d73500e620987947d1539cfebc99064ba0f7d5d6eef399475e' + - 'ghcr.io/gythialy/golang-cross:v1.22.4-0@sha256:7769c9e4c92f1b598410566270a0aac39f6d0f68491e5bf0862df4ff0f11f06b' - '--certificate-oidc-issuer' - "https://token.actions.githubusercontent.com" - '--certificate-identity' - - "https://github.com/gythialy/golang-cross/.github/workflows/release-golang-cross.yml@refs/tags/v1.22.3-0" + - "https://github.com/gythialy/golang-cross/.github/workflows/release-golang-cross.yml@refs/tags/v1.22.4-0" - - name: ghcr.io/gythialy/golang-cross:v1.22.3-0@sha256:3217c1e30a7081d73500e620987947d1539cfebc99064ba0f7d5d6eef399475e + - name: ghcr.io/gythialy/golang-cross:v1.22.4-0@sha256:7769c9e4c92f1b598410566270a0aac39f6d0f68491e5bf0862df4ff0f11f06b entrypoint: /bin/sh dir: "go/src/sigstore/fulcio" env: @@ -67,7 +67,7 @@ steps: gcloud auth configure-docker \ && make release - - name: ghcr.io/gythialy/golang-cross:v1.22.3-0@sha256:3217c1e30a7081d73500e620987947d1539cfebc99064ba0f7d5d6eef399475e + - name: ghcr.io/gythialy/golang-cross:v1.22.4-0@sha256:7769c9e4c92f1b598410566270a0aac39f6d0f68491e5bf0862df4ff0f11f06b entrypoint: 'bash' dir: "go/src/sigstore/fulcio" env: From e9f17e374ad5c7e584043d1474702aa13f59e5d5 Mon Sep 17 00:00:00 2001 From: Matt Moore Date: Fri, 21 Jun 2024 16:48:40 -0700 Subject: [PATCH 05/56] Bump the version of Go Signed-off-by: Matt Moore --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index a10c6de35..a54b3a25b 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/sigstore/fulcio -go 1.21.9 +go 1.22.2 require ( chainguard.dev/go-grpc-kit v0.17.5 From 3ad7abb92de971b7df055ef84113197d9f3957b5 Mon Sep 17 00:00:00 2001 From: Matt Moore Date: Fri, 21 Jun 2024 16:59:55 -0700 Subject: [PATCH 06/56] Update go.mod Signed-off-by: Matt Moore --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index a54b3a25b..ce3c52a91 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/sigstore/fulcio -go 1.22.2 +go 1.22.4 require ( chainguard.dev/go-grpc-kit v0.17.5 From c0eb75b4c141642cffca00618549e494344c4a7e Mon Sep 17 00:00:00 2001 From: cpanato Date: Sat, 22 Jun 2024 11:12:17 +0200 Subject: [PATCH 07/56] update deprecated flags Signed-off-by: cpanato --- release/release.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release/release.mk b/release/release.mk index 93bd1bf19..4c96953b5 100644 --- a/release/release.mk +++ b/release/release.mk @@ -10,7 +10,7 @@ release: # used when need to validate the goreleaser .PHONY: snapshot snapshot: - LDFLAGS="$(LDFLAGS)" goreleaser release --skip-sign --skip-publish --snapshot --rm-dist + LDFLAGS="$(LDFLAGS)" goreleaser release --skip=sign,publish --snapshot --clean ################## From dd9fcc9e28845c68289ee4963082302c5ac43d4a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Jun 2024 02:04:36 +0000 Subject: [PATCH 08/56] Bump google.golang.org/api from 0.183.0 to 0.185.0 Bumps [google.golang.org/api](https://github.com/googleapis/google-api-go-client) from 0.183.0 to 0.185.0. - [Release notes](https://github.com/googleapis/google-api-go-client/releases) - [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md) - [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.183.0...v0.185.0) --- updated-dependencies: - dependency-name: google.golang.org/api dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index ce3c52a91..ae5ad807e 100644 --- a/go.mod +++ b/go.mod @@ -35,8 +35,8 @@ require ( github.com/spiffe/go-spiffe/v2 v2.2.0 go.step.sm/crypto v0.47.1 go.uber.org/zap v1.27.0 - google.golang.org/api v0.183.0 - google.golang.org/genproto/googleapis/api v0.0.0-20240521202816-d264139d666e + google.golang.org/api v0.185.0 + google.golang.org/genproto/googleapis/api v0.0.0-20240610135401-a8a62080eff3 google.golang.org/grpc v1.64.0 google.golang.org/protobuf v1.34.2 gopkg.in/square/go-jose.v2 v2.6.0 @@ -45,7 +45,7 @@ require ( ) require ( - cloud.google.com/go v0.114.0 // indirect + cloud.google.com/go v0.115.0 // indirect cloud.google.com/go/auth v0.5.1 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect cloud.google.com/go/compute/metadata v0.3.0 // indirect @@ -149,8 +149,8 @@ require ( golang.org/x/term v0.21.0 // indirect golang.org/x/text v0.16.0 // indirect golang.org/x/time v0.5.0 // indirect - google.golang.org/genproto v0.0.0-20240528184218-531527333157 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect + google.golang.org/genproto v0.0.0-20240617180043-68d350f18fd4 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240617180043-68d350f18fd4 // indirect gopkg.in/go-jose/go-jose.v2 v2.6.3 // indirect gopkg.in/ini.v1 v1.67.0 // indirect k8s.io/klog/v2 v2.120.1 // indirect diff --git a/go.sum b/go.sum index 134b19a4a..90934a828 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,8 @@ chainguard.dev/go-grpc-kit v0.17.5 h1:y0MHgqm3v0LKKQfxPJV57wkXxa8uMSpNTjhtHbNh1DY= chainguard.dev/go-grpc-kit v0.17.5/go.mod h1:vQGcwZiX6jXwhyLPCZwVMvjITD+XcrSmQzuCTW/XcVc= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.114.0 h1:OIPFAdfrFDFO2ve2U7r/H5SwSbBzEdrBdE7xkgwc+kY= -cloud.google.com/go v0.114.0/go.mod h1:ZV9La5YYxctro1HTPug5lXH/GefROyW8PPD4T8n9J8E= +cloud.google.com/go v0.115.0 h1:CnFSK6Xo3lDYRoBKEcAtia6VSC837/ZkJuRduSFnr14= +cloud.google.com/go v0.115.0/go.mod h1:8jIM5vVgoAEoiVxQ/O4BFTfHqulPZgs/ufEzMcFMdWU= cloud.google.com/go/auth v0.5.1 h1:0QNO7VThG54LUzKiQxv8C6x1YX7lUrzlAa1nVLF8CIw= cloud.google.com/go/auth v0.5.1/go.mod h1:vbZT8GjzDf3AVqCcQmqeeM32U9HBFc32vVVAbwDsa6s= cloud.google.com/go/auth/oauth2adapt v0.2.2 h1:+TTV8aXpjeChS9M+aTtN/TjdQnzJvmzKFt//oWu7HX4= @@ -486,20 +486,20 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T 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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.183.0 h1:PNMeRDwo1pJdgNcFQ9GstuLe/noWKIc89pRWRLMvLwE= -google.golang.org/api v0.183.0/go.mod h1:q43adC5/pHoSZTx5h2mSmdF7NcyfW9JuDyIOJAgS9ZQ= +google.golang.org/api v0.185.0 h1:ENEKk1k4jW8SmmaT6RE+ZasxmxezCrD5Vw4npvr+pAU= +google.golang.org/api v0.185.0/go.mod h1:HNfvIkJGlgrIlrbYkAm9W9IdkmKZjOTVh33YltygGbg= 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/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20240528184218-531527333157 h1:u7WMYrIrVvs0TF5yaKwKNbcJyySYf+HAIFXxWltJOXE= -google.golang.org/genproto v0.0.0-20240528184218-531527333157/go.mod h1:ubQlAQnzejB8uZzszhrTCU2Fyp6Vi7ZE5nn0c3W8+qQ= -google.golang.org/genproto/googleapis/api v0.0.0-20240521202816-d264139d666e h1:SkdGTrROJl2jRGT/Fxv5QUf9jtdKCQh4KQJXbXVLAi0= -google.golang.org/genproto/googleapis/api v0.0.0-20240521202816-d264139d666e/go.mod h1:LweJcLbyVij6rCex8YunD8DYR5VDonap/jYl3ZRxcIU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 h1:Zy9XzmMEflZ/MAaA7vNcoebnRAld7FsPW1EeBB7V0m8= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/genproto v0.0.0-20240617180043-68d350f18fd4 h1:CUiCqkPw1nNrNQzCCG4WA65m0nAmQiwXHpub3dNyruU= +google.golang.org/genproto v0.0.0-20240617180043-68d350f18fd4/go.mod h1:EvuUDCulqGgV80RvP1BHuom+smhX4qtlhnNatHuroGQ= +google.golang.org/genproto/googleapis/api v0.0.0-20240610135401-a8a62080eff3 h1:QW9+G6Fir4VcRXVH8x3LilNAb6cxBGLa6+GM4hRwexE= +google.golang.org/genproto/googleapis/api v0.0.0-20240610135401-a8a62080eff3/go.mod h1:kdrSS/OiLkPrNUpzD4aHgCq2rVuC/YRxok32HXZ4vRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240617180043-68d350f18fd4 h1:Di6ANFilr+S60a4S61ZM00vLdw0IrQOSMS2/6mrnOU0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240617180043-68d350f18fd4/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= From 61de6a0d186f9bd7a0af39e1f50b39d8a4eeb721 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Jun 2024 02:04:53 +0000 Subject: [PATCH 09/56] Bump github.com/spiffe/go-spiffe/v2 from 2.2.0 to 2.3.0 Bumps [github.com/spiffe/go-spiffe/v2](https://github.com/spiffe/go-spiffe) from 2.2.0 to 2.3.0. - [Release notes](https://github.com/spiffe/go-spiffe/releases) - [Changelog](https://github.com/spiffe/go-spiffe/blob/main/CHANGELOG.md) - [Commits](https://github.com/spiffe/go-spiffe/compare/v2.2.0...v2.3.0) --- updated-dependencies: - dependency-name: github.com/spiffe/go-spiffe/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index ae5ad807e..99ed3fdac 100644 --- a/go.mod +++ b/go.mod @@ -32,7 +32,7 @@ require ( github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.19.0 - github.com/spiffe/go-spiffe/v2 v2.2.0 + github.com/spiffe/go-spiffe/v2 v2.3.0 go.step.sm/crypto v0.47.1 go.uber.org/zap v1.27.0 google.golang.org/api v0.185.0 @@ -83,7 +83,7 @@ require ( github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-jose/go-jose/v3 v3.0.3 // indirect - github.com/go-jose/go-jose/v4 v4.0.1 // indirect + github.com/go-jose/go-jose/v4 v4.0.2 // indirect github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/golang-jwt/jwt/v5 v5.2.1 // indirect diff --git a/go.sum b/go.sum index 90934a828..e70dc2d3b 100644 --- a/go.sum +++ b/go.sum @@ -112,8 +112,8 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k= github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ= -github.com/go-jose/go-jose/v4 v4.0.1 h1:QVEPDE3OluqXBQZDcnNvQrInro2h0e4eqNbnZSWqS6U= -github.com/go-jose/go-jose/v4 v4.0.1/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY= +github.com/go-jose/go-jose/v4 v4.0.2 h1:R3l3kkBds16bO7ZFAEEcofK0MkrAJt3jlJznWZG0nvk= +github.com/go-jose/go-jose/v4 v4.0.2/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -320,8 +320,8 @@ 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/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= -github.com/spiffe/go-spiffe/v2 v2.2.0 h1:9Vf06UsvsDbLYK/zJ4sYsIsHmMFknUD+feA7IYoWMQY= -github.com/spiffe/go-spiffe/v2 v2.2.0/go.mod h1:Urzb779b3+IwDJD2ZbN8fVl3Aa8G4N/PiUe6iXC0XxU= +github.com/spiffe/go-spiffe/v2 v2.3.0 h1:g2jYNb/PDMB8I7mBGL2Zuq/Ur6hUhoroxGQFyD6tTj8= +github.com/spiffe/go-spiffe/v2 v2.3.0/go.mod h1:Oxsaio7DBgSNqhAO9i/9tLClaVlfRok7zvJnTV8ZyIY= 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.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= From caf94db8675f7c3e4ef7820819b2b5943dba47f4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Jun 2024 02:04:46 +0000 Subject: [PATCH 10/56] Bump github.com/google/certificate-transparency-go from 1.1.8 to 1.2.1 Bumps [github.com/google/certificate-transparency-go](https://github.com/google/certificate-transparency-go) from 1.1.8 to 1.2.1. - [Release notes](https://github.com/google/certificate-transparency-go/releases) - [Changelog](https://github.com/google/certificate-transparency-go/blob/master/CHANGELOG.md) - [Commits](https://github.com/google/certificate-transparency-go/compare/v1.1.8...v1.2.1) --- updated-dependencies: - dependency-name: github.com/google/certificate-transparency-go dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 99ed3fdac..e3d3a3034 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/fsnotify/fsnotify v1.7.0 github.com/goadesign/goa v2.2.5+incompatible github.com/golang/protobuf v1.5.4 - github.com/google/certificate-transparency-go v1.1.8 + github.com/google/certificate-transparency-go v1.2.1 github.com/google/go-cmp v0.6.0 github.com/google/tink/go v1.7.0 github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 diff --git a/go.sum b/go.sum index e70dc2d3b..e72e029f8 100644 --- a/go.sum +++ b/go.sum @@ -149,8 +149,8 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/certificate-transparency-go v1.1.8 h1:LGYKkgZF7satzgTak9R4yzfJXEeYVAjV6/EAEJOf1to= -github.com/google/certificate-transparency-go v1.1.8/go.mod h1:bV/o8r0TBKRf1X//iiiSgWrvII4d7/8OiA+3vG26gI8= +github.com/google/certificate-transparency-go v1.2.1 h1:4iW/NwzqOqYEEoCBEFP+jPbBXbLqMpq3CifMyOnDUME= +github.com/google/certificate-transparency-go v1.2.1/go.mod h1:bvn/ytAccv+I6+DGkqpvSsEdiVGramgaSC6RD3tEmeE= 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= From 99481ec2d76e690dffff06a14bda5ce9b812a26b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 23 Jun 2024 10:07:47 +0000 Subject: [PATCH 11/56] Bump the all group across 1 directory with 4 updates Bumps the all group with 4 updates in the / directory: [actions/checkout](https://github.com/actions/checkout), [ko-build/setup-ko](https://github.com/ko-build/setup-ko), [codecov/codecov-action](https://github.com/codecov/codecov-action) and [protocolbuffers/protobuf](https://github.com/protocolbuffers/protobuf). Updates `actions/checkout` from 4.1.6 to 4.1.7 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/a5ac7e51b41094c92402da3b24376905380afc29...692973e3d937129bcbf40652eb9f2f61becf3332) Updates `ko-build/setup-ko` from 0.6 to 0.7 - [Release notes](https://github.com/ko-build/setup-ko/releases) - [Commits](https://github.com/ko-build/setup-ko/compare/ace48d793556083a76f1e3e6068850c1f4a369aa...3aebd0597dc1e9d1a26bcfdb7cbeb19c131d3037) Updates `codecov/codecov-action` from 4.4.1 to 4.5.0 - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/125fc84a9a348dbcf27191600683ec096ec9021c...e28ff129e5465c2c0dcc6f003fc735cb6ae0c673) Updates `protocolbuffers/protobuf` from 27.0 to 27.1 - [Release notes](https://github.com/protocolbuffers/protobuf/releases) - [Changelog](https://github.com/protocolbuffers/protobuf/blob/main/protobuf_release.bzl) - [Commits](https://github.com/protocolbuffers/protobuf/compare/v27.0...v27.1) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all - dependency-name: ko-build/setup-ko dependency-type: direct:production update-type: version-update:semver-minor dependency-group: all - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-minor dependency-group: all - dependency-name: protocolbuffers/protobuf dependency-type: direct:production update-type: version-update:semver-minor dependency-group: all ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/container-build.yml | 4 ++-- .github/workflows/main.yml | 4 ++-- .github/workflows/protoc-dependabot-hack.yml | 2 +- .github/workflows/scorecard_action.yml | 2 +- .github/workflows/validate-release.yml | 2 +- .github/workflows/verify-k8s.yml | 6 +++--- .github/workflows/verify.yml | 6 +++--- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 573a468bc..0b2371772 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -39,7 +39,7 @@ jobs: language: [ 'go' ] steps: - name: Checkout repository - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 # TODO: uncomment when we bump to go1.22 in go.mod # - name: Extract version of Go to use diff --git a/.github/workflows/container-build.yml b/.github/workflows/container-build.yml index 8c5f27b46..4a274b097 100644 --- a/.github/workflows/container-build.yml +++ b/.github/workflows/container-build.yml @@ -33,7 +33,7 @@ jobs: contents: read steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0 # TODO: uncomment when we bump to go1.22 in go.mod @@ -48,7 +48,7 @@ jobs: - name: deps run: sudo apt-get update && sudo apt-get install -yq libpcsclite-dev - - uses: ko-build/setup-ko@ace48d793556083a76f1e3e6068850c1f4a369aa # v0.6 + - uses: ko-build/setup-ko@3aebd0597dc1e9d1a26bcfdb7cbeb19c131d3037 # v0.7 - name: Set up Cloud SDK uses: google-github-actions/auth@71fee32a0bb7e97b4d33d548e7d957010649d8fa # v2.1.3 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 38bf9fac1..924daca66 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -29,7 +29,7 @@ jobs: runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 # TODO: uncomment when we bump to go1.22 in go.mod # - name: Extract version of Go to use @@ -53,7 +53,7 @@ jobs: run: go test -v -coverprofile=coverage.txt -covermode=atomic ./... - name: Upload Coverage Report - uses: codecov/codecov-action@125fc84a9a348dbcf27191600683ec096ec9021c # v4.4.1 + uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0 - name: Ensure no files were modified as a result of the build run: git update-index --refresh && git diff-index --quiet -I"^\/\/\s+(-\s+)?protoc(-gen-go)?\s+v[0-9]+\.[0-9]+\.[0-9]+$" HEAD -- || git diff -I"^\/\/\s+(-\s+)?protoc(-gen-go)?\s+v[0-9]+\.[0-9]+\.[0-9]+$" --exit-code diff --git a/.github/workflows/protoc-dependabot-hack.yml b/.github/workflows/protoc-dependabot-hack.yml index 69695a59d..f31b7459b 100644 --- a/.github/workflows/protoc-dependabot-hack.yml +++ b/.github/workflows/protoc-dependabot-hack.yml @@ -16,4 +16,4 @@ jobs: # update the version in these places manually when Dependabot proposes a change to it here: # 1. the version in main.yml used to install protoc - - uses: protocolbuffers/protobuf@v27.0 + - uses: protocolbuffers/protobuf@v27.1 diff --git a/.github/workflows/scorecard_action.yml b/.github/workflows/scorecard_action.yml index ec8367e56..2a0dc531b 100644 --- a/.github/workflows/scorecard_action.yml +++ b/.github/workflows/scorecard_action.yml @@ -23,7 +23,7 @@ jobs: id-token: write steps: - name: "Checkout code" - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: persist-credentials: false diff --git a/.github/workflows/validate-release.yml b/.github/workflows/validate-release.yml index 1d81c195e..d85ee4773 100644 --- a/.github/workflows/validate-release.yml +++ b/.github/workflows/validate-release.yml @@ -47,7 +47,7 @@ jobs: image: ghcr.io/gythialy/golang-cross:v1.22.4-0@sha256:7769c9e4c92f1b598410566270a0aac39f6d0f68491e5bf0862df4ff0f11f06b steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 # Error: fatal: detected dubious ownership in repository at '/__w/fulcio/fulcio' # To add an exception for this directory, call: diff --git a/.github/workflows/verify-k8s.yml b/.github/workflows/verify-k8s.yml index 5693f3761..0e47b993f 100644 --- a/.github/workflows/verify-k8s.yml +++ b/.github/workflows/verify-k8s.yml @@ -25,7 +25,7 @@ jobs: name: k8s manifest check runs-on: ubuntu-latest steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 # TODO: uncomment when we bump to go1.22 in go.mod # - name: Extract version of Go to use @@ -69,7 +69,7 @@ jobs: GIT_VERSION: test steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 # TODO: uncomment when we bump to go1.22 in go.mod # - name: Extract version of Go to use @@ -80,7 +80,7 @@ jobs: go-version: '1.22' check-latest: true - - uses: ko-build/setup-ko@ace48d793556083a76f1e3e6068850c1f4a369aa # v0.6 + - uses: ko-build/setup-ko@3aebd0597dc1e9d1a26bcfdb7cbeb19c131d3037 # v0.7 - name: Setup Cluster uses: chainguard-dev/actions/setup-kind@f94883c3bd16936401291899070258f855b5d849 # main diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index 32544d9f1..ec2722d9b 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -29,7 +29,7 @@ jobs: name: license boilerplate check runs-on: ubuntu-latest steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 # TODO: uncomment when we bump to go1.22 in go.mod # - name: Extract version of Go to use @@ -53,7 +53,7 @@ jobs: name: golangci-lint runs-on: ubuntu-latest steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: deps run: sudo apt-get update && sudo apt-get install -yq libpcsclite-dev @@ -77,7 +77,7 @@ jobs: name: oidc-config runs-on: ubuntu-latest steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 # TODO: uncomment when we bump to go1.22 in go.mod # - name: Extract version of Go to use From 0367b02a267fd0539fc4de83335121ee44967523 Mon Sep 17 00:00:00 2001 From: Carlos Tadeu Panato Junior Date: Mon, 24 Jun 2024 09:53:02 +0200 Subject: [PATCH 12/56] Update README.md (#1700) Signed-off-by: Carlos Tadeu Panato Junior --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4a1eccf00..f834f5402 100644 --- a/README.md +++ b/README.md @@ -118,7 +118,7 @@ process](https://github.com/sigstore/.github/blob/main/SECURITY.md). Fulcio is developed as part of the [`sigstore`](https://sigstore.dev) project. We also use a [slack channel](https://sigstore.slack.com)! -Click [here](https://links.sigstore.dev/slack-invite) for the invite link. +To check more information about Slack and other communication channels please check the [community repository](https://github.com/sigstore/community?tab=readme-ov-file#slack) ## Additional Documentation From 14ca3dc8905baa9bf09ef5b06c8c5d2a0be895b1 Mon Sep 17 00:00:00 2001 From: Carlos Tadeu Panato Junior Date: Mon, 24 Jun 2024 17:14:36 +0200 Subject: [PATCH 13/56] replace gopkg.in/square/go-jose.v2 to github.com/go-jose/go-jose/v4 (#1686) Signed-off-by: cpanato --- go.mod | 3 +- go.sum | 2 - pkg/server/grpc_server.go | 9 ++-- pkg/server/grpc_server_test.go | 76 +++++++++++++++++----------------- 4 files changed, 45 insertions(+), 45 deletions(-) diff --git a/go.mod b/go.mod index e3d3a3034..05cf24829 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d github.com/coreos/go-oidc/v3 v3.10.0 github.com/fsnotify/fsnotify v1.7.0 + github.com/go-jose/go-jose/v4 v4.0.2 github.com/goadesign/goa v2.2.5+incompatible github.com/golang/protobuf v1.5.4 github.com/google/certificate-transparency-go v1.2.1 @@ -39,7 +40,6 @@ require ( google.golang.org/genproto/googleapis/api v0.0.0-20240610135401-a8a62080eff3 google.golang.org/grpc v1.64.0 google.golang.org/protobuf v1.34.2 - gopkg.in/square/go-jose.v2 v2.6.0 gopkg.in/yaml.v3 v3.0.1 sigs.k8s.io/release-utils v0.8.2 ) @@ -83,7 +83,6 @@ require ( github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-jose/go-jose/v3 v3.0.3 // indirect - github.com/go-jose/go-jose/v4 v4.0.2 // indirect github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/golang-jwt/jwt/v5 v5.2.1 // indirect diff --git a/go.sum b/go.sum index e72e029f8..71dc3ca48 100644 --- a/go.sum +++ b/go.sum @@ -528,8 +528,6 @@ gopkg.in/go-jose/go-jose.v2 v2.6.3 h1:nt80fvSDlhKWQgSWyHyy5CfmlQr+asih51R8PTWNKK gopkg.in/go-jose/go-jose.v2 v2.6.3/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= -gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= diff --git a/pkg/server/grpc_server.go b/pkg/server/grpc_server.go index 73e8b4072..9b0cb5991 100644 --- a/pkg/server/grpc_server.go +++ b/pkg/server/grpc_server.go @@ -22,9 +22,13 @@ import ( "errors" "fmt" + ctclient "github.com/google/certificate-transparency-go/client" health "google.golang.org/grpc/health/grpc_health_v1" - ctclient "github.com/google/certificate-transparency-go/client" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" + certauth "github.com/sigstore/fulcio/pkg/ca" "github.com/sigstore/fulcio/pkg/challenges" "github.com/sigstore/fulcio/pkg/config" @@ -33,9 +37,6 @@ import ( "github.com/sigstore/fulcio/pkg/identity" "github.com/sigstore/fulcio/pkg/log" "github.com/sigstore/sigstore/pkg/cryptoutils" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/metadata" - "google.golang.org/grpc/status" ) type GRPCCAServer interface { diff --git a/pkg/server/grpc_server_test.go b/pkg/server/grpc_server_test.go index 854a70c6f..06d6c9e2e 100644 --- a/pkg/server/grpc_server_test.go +++ b/pkg/server/grpc_server_test.go @@ -39,22 +39,24 @@ import ( "testing" "time" + "github.com/go-jose/go-jose/v4" + "github.com/go-jose/go-jose/v4/jwt" ctclient "github.com/google/certificate-transparency-go/client" "github.com/google/certificate-transparency-go/jsonclient" + + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/credentials/insecure" + "google.golang.org/grpc/status" + "google.golang.org/grpc/test/bufconn" + "github.com/sigstore/fulcio/pkg/ca" "github.com/sigstore/fulcio/pkg/ca/ephemeralca" "github.com/sigstore/fulcio/pkg/config" "github.com/sigstore/fulcio/pkg/generated/protobuf" "github.com/sigstore/fulcio/pkg/identity" "github.com/sigstore/sigstore/pkg/cryptoutils" - "google.golang.org/grpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/resolver" - "google.golang.org/grpc/status" - "google.golang.org/grpc/test/bufconn" - "gopkg.in/square/go-jose.v2" - "gopkg.in/square/go-jose.v2/jwt" ) const ( @@ -521,9 +523,9 @@ func TestAPIWithEmail(t *testing.T) { Expiry: jwt.NewNumericDate(time.Now().Add(30 * time.Minute)), Subject: c.Subject, Audience: jwt.Audience{"sigstore"}, - }).Claims(customClaims{Email: c.Subject, EmailVerified: true}).CompactSerialize() + }).Claims(customClaims{Email: c.Subject, EmailVerified: true}).Serialize() if err != nil { - t.Fatalf("CompactSerialize() = %v", err) + t.Fatalf("Serialize() = %v", err) } ctClient, eca := createCA(cfg, t) @@ -610,9 +612,9 @@ func TestAPIWithUsername(t *testing.T) { Expiry: jwt.NewNumericDate(time.Now().Add(30 * time.Minute)), Subject: c.Subject, Audience: jwt.Audience{"sigstore"}, - }).Claims(customClaims{Email: c.Subject, EmailVerified: true}).CompactSerialize() + }).Claims(customClaims{Email: c.Subject, EmailVerified: true}).Serialize() if err != nil { - t.Fatalf("CompactSerialize() = %v", err) + t.Fatalf("Serialize() = %v", err) } ctClient, eca := createCA(cfg, t) @@ -708,9 +710,9 @@ func TestAPIWithUriSubject(t *testing.T) { Expiry: jwt.NewNumericDate(time.Now().Add(30 * time.Minute)), Subject: c.Subject, Audience: jwt.Audience{"sigstore"}, - }).CompactSerialize() + }).Serialize() if err != nil { - t.Fatalf("CompactSerialize() = %v", err) + t.Fatalf("Serialize() = %v", err) } ctClient, eca := createCA(cfg, t) @@ -801,9 +803,9 @@ func TestAPIWithKubernetes(t *testing.T) { Expiry: jwt.NewNumericDate(time.Now().Add(30 * time.Minute)), Subject: k8sSubject, Audience: jwt.Audience{"sigstore"}, - }).Claims(&claims).CompactSerialize() + }).Claims(&claims).Serialize() if err != nil { - t.Fatalf("CompactSerialize() = %v", err) + t.Fatalf("Serialize() = %v", err) } ctClient, eca := createCA(cfg, t) @@ -890,9 +892,9 @@ func TestAPIWithBuildkite(t *testing.T) { Expiry: jwt.NewNumericDate(time.Now().Add(30 * time.Minute)), Subject: buildkiteSubject, Audience: jwt.Audience{"sigstore"}, - }).Claims(&claims).CompactSerialize() + }).Claims(&claims).Serialize() if err != nil { - t.Fatalf("CompactSerialize() = %v", err) + t.Fatalf("Serialize() = %v", err) } ctClient, eca := createCA(cfg, t) @@ -1008,9 +1010,9 @@ func TestAPIWithGitHub(t *testing.T) { Expiry: jwt.NewNumericDate(time.Now().Add(30 * time.Minute)), Subject: githubSubject, Audience: jwt.Audience{"sigstore"}, - }).Claims(&claims).CompactSerialize() + }).Claims(&claims).Serialize() if err != nil { - t.Fatalf("CompactSerialize() = %v", err) + t.Fatalf("Serialize() = %v", err) } ctClient, eca := createCA(cfg, t) @@ -1176,9 +1178,9 @@ func TestAPIWithGitLab(t *testing.T) { Expiry: jwt.NewNumericDate(time.Now().Add(30 * time.Minute)), Subject: gitLabSubject, Audience: jwt.Audience{"sigstore"}, - }).Claims(&claims).CompactSerialize() + }).Claims(&claims).Serialize() if err != nil { - t.Fatalf("CompactSerialize() = %v", err) + t.Fatalf("Serialize() = %v", err) } ctClient, eca := createCA(cfg, t) @@ -1319,9 +1321,9 @@ func TestAPIWithCodefresh(t *testing.T) { Expiry: jwt.NewNumericDate(time.Now().Add(30 * time.Minute)), Subject: codefreshSubject, Audience: jwt.Audience{"sigstore"}, - }).Claims(&claims).CompactSerialize() + }).Claims(&claims).Serialize() if err != nil { - t.Fatalf("CompactSerialize() = %v", err) + t.Fatalf("Serialize() = %v", err) } ctClient, eca := createCA(cfg, t) @@ -1427,9 +1429,9 @@ func TestAPIWithIssuerClaimConfig(t *testing.T) { Expiry: jwt.NewNumericDate(time.Now().Add(30 * time.Minute)), Subject: emailSubject, Audience: jwt.Audience{"sigstore"}, - }).Claims(customClaims{Email: emailSubject, EmailVerified: true, OtherIssuer: otherIssuerVal}).CompactSerialize() + }).Claims(customClaims{Email: emailSubject, EmailVerified: true, OtherIssuer: otherIssuerVal}).Serialize() if err != nil { - t.Fatalf("CompactSerialize() = %v", err) + t.Fatalf("Serialize() = %v", err) } ctClient, eca := createCA(cfg, t) @@ -1503,9 +1505,9 @@ func TestAPIWithCSRChallenge(t *testing.T) { Expiry: jwt.NewNumericDate(time.Now().Add(30 * time.Minute)), Subject: emailSubject, Audience: jwt.Audience{"sigstore"}, - }).Claims(customClaims{Email: emailSubject, EmailVerified: true}).CompactSerialize() + }).Claims(customClaims{Email: emailSubject, EmailVerified: true}).Serialize() if err != nil { - t.Fatalf("CompactSerialize() = %v", err) + t.Fatalf("Serialize() = %v", err) } ctClient, eca := createCA(cfg, t) @@ -1585,9 +1587,9 @@ func TestAPIWithInsecurePublicKey(t *testing.T) { Expiry: jwt.NewNumericDate(time.Now().Add(30 * time.Minute)), Subject: emailSubject, Audience: jwt.Audience{"sigstore"}, - }).Claims(customClaims{Email: emailSubject, EmailVerified: true}).CompactSerialize() + }).Claims(customClaims{Email: emailSubject, EmailVerified: true}).Serialize() if err != nil { - t.Fatalf("CompactSerialize() = %v", err) + t.Fatalf("Serialize() = %v", err) } ctClient, eca := createCA(cfg, t) @@ -1660,9 +1662,9 @@ func TestAPIWithoutPublicKey(t *testing.T) { Expiry: jwt.NewNumericDate(time.Now().Add(30 * time.Minute)), Subject: emailSubject, Audience: jwt.Audience{"sigstore"}, - }).Claims(customClaims{Email: emailSubject, EmailVerified: true}).CompactSerialize() + }).Claims(customClaims{Email: emailSubject, EmailVerified: true}).Serialize() if err != nil { - t.Fatalf("CompactSerialize() = %v", err) + t.Fatalf("Serialize() = %v", err) } ctClient, eca := createCA(cfg, t) @@ -1736,9 +1738,9 @@ func TestAPIWithInvalidChallenge(t *testing.T) { Expiry: jwt.NewNumericDate(time.Now().Add(30 * time.Minute)), Subject: emailSubject, Audience: jwt.Audience{"sigstore"}, - }).Claims(customClaims{Email: emailSubject, EmailVerified: true}).CompactSerialize() + }).Claims(customClaims{Email: emailSubject, EmailVerified: true}).Serialize() if err != nil { - t.Fatalf("CompactSerialize() = %v", err) + t.Fatalf("Serialize() = %v", err) } ctClient, eca := createCA(cfg, t) @@ -1804,9 +1806,9 @@ func TestAPIWithInvalidCSR(t *testing.T) { Expiry: jwt.NewNumericDate(time.Now().Add(30 * time.Minute)), Subject: emailSubject, Audience: jwt.Audience{"sigstore"}, - }).Claims(customClaims{Email: emailSubject, EmailVerified: true}).CompactSerialize() + }).Claims(customClaims{Email: emailSubject, EmailVerified: true}).Serialize() if err != nil { - t.Fatalf("CompactSerialize() = %v", err) + t.Fatalf("Serialize() = %v", err) } ctClient, eca := createCA(cfg, t) @@ -1865,9 +1867,9 @@ func TestAPIWithInvalidCSRSignature(t *testing.T) { Expiry: jwt.NewNumericDate(time.Now().Add(30 * time.Minute)), Subject: emailSubject, Audience: jwt.Audience{"sigstore"}, - }).Claims(customClaims{Email: emailSubject, EmailVerified: true}).CompactSerialize() + }).Claims(customClaims{Email: emailSubject, EmailVerified: true}).Serialize() if err != nil { - t.Fatalf("CompactSerialize() = %v", err) + t.Fatalf("Serialize() = %v", err) } ctClient, eca := createCA(cfg, t) From 0445bbd2c54b0b325d5e1f0377333605d3e9b108 Mon Sep 17 00:00:00 2001 From: Matt Moore Date: Mon, 24 Jun 2024 22:30:21 -0700 Subject: [PATCH 14/56] Add Chainguard OIDC provider. (#1703) This adds support for Chainguard issued tokens, so that users can sign with their Chainguard-issued identity, and so that we can explore signing our own content with our internal service principal construct (see issue). Related: https://github.com/sigstore/fulcio/issues/1702 Signed-off-by: Matt Moore --- config/config.jsn | 5 + config/fulcio-config.yaml | 5 + federation/issuer.enforce.dev/config.yaml | 19 ++ go.mod | 3 +- go.sum | 6 +- pkg/config/config.go | 3 + pkg/config/config_test.go | 3 + pkg/identity/chainguard/issuer.go | 40 ++++ pkg/identity/chainguard/issuer_test.go | 97 +++++++++ pkg/identity/chainguard/principal.go | 80 ++++++++ pkg/identity/chainguard/principal_test.go | 232 ++++++++++++++++++++++ pkg/server/grpc_server_test.go | 137 ++++++++++++- pkg/server/issuer_pool.go | 3 + 13 files changed, 628 insertions(+), 5 deletions(-) create mode 100644 federation/issuer.enforce.dev/config.yaml create mode 100644 pkg/identity/chainguard/issuer.go create mode 100644 pkg/identity/chainguard/issuer_test.go create mode 100644 pkg/identity/chainguard/principal.go create mode 100644 pkg/identity/chainguard/principal_test.go diff --git a/config/config.jsn b/config/config.jsn index 8e66be79e..27fae5423 100644 --- a/config/config.jsn +++ b/config/config.jsn @@ -25,6 +25,11 @@ "IssuerURL": "https://oidc.codefresh.io", "ClientID": "sigstore", "Type": "codefresh-workflow" + }, + "https://issuer.enforce.dev": { + "IssuerURL": "https://issuer.enforce.dev", + "ClientID": "sigstore", + "Type": "chainguard-identity" } } } diff --git a/config/fulcio-config.yaml b/config/fulcio-config.yaml index 44a7107bb..0f7a0aded 100644 --- a/config/fulcio-config.yaml +++ b/config/fulcio-config.yaml @@ -58,6 +58,11 @@ data: "ClientID": "sigstore", "Type": "gitlab-pipeline" }, + "https://issuer.enforce.dev": { + "IssuerURL": "https://issuer.enforce.dev", + "ClientID": "sigstore", + "Type": "chainguard-identity" + }, "https://oauth2.sigstore.dev/auth": { "IssuerURL": "https://oauth2.sigstore.dev/auth", "ClientID": "sigstore", diff --git a/federation/issuer.enforce.dev/config.yaml b/federation/issuer.enforce.dev/config.yaml new file mode 100644 index 000000000..45e252a88 --- /dev/null +++ b/federation/issuer.enforce.dev/config.yaml @@ -0,0 +1,19 @@ +# Copyright 2024 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. + +url: https://issuer.enforce.dev +# TODO(mattmoor): Change to a group. +contact: mattmoor@chainguard.dev +description: "Chainguard identity tokens" +type: "chainguard-identity" diff --git a/go.mod b/go.mod index 05cf24829..b33009ceb 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.22.4 require ( chainguard.dev/go-grpc-kit v0.17.5 + chainguard.dev/sdk v0.1.20 cloud.google.com/go/security v1.17.0 github.com/PaesslerAG/jsonpath v0.1.1 github.com/ThalesIgnite/crypto11 v1.2.5 @@ -140,7 +141,7 @@ require ( go.uber.org/multierr v1.11.0 // indirect goa.design/goa v2.2.5+incompatible // indirect golang.org/x/crypto v0.24.0 // indirect - golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect + golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb // indirect golang.org/x/net v0.26.0 // indirect golang.org/x/oauth2 v0.21.0 // indirect golang.org/x/sync v0.7.0 // indirect diff --git a/go.sum b/go.sum index 71dc3ca48..16749b98f 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ chainguard.dev/go-grpc-kit v0.17.5 h1:y0MHgqm3v0LKKQfxPJV57wkXxa8uMSpNTjhtHbNh1DY= chainguard.dev/go-grpc-kit v0.17.5/go.mod h1:vQGcwZiX6jXwhyLPCZwVMvjITD+XcrSmQzuCTW/XcVc= +chainguard.dev/sdk v0.1.20 h1:x46/Nd+DbfvaO4F0NEHUYIkGFa/B3wA+0KKByVNd61I= +chainguard.dev/sdk v0.1.20/go.mod h1:UO+3bmvsha1UoXxvgNnMze1kfNLuADe2WWi3AirvvxE= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.115.0 h1:CnFSK6Xo3lDYRoBKEcAtia6VSC837/ZkJuRduSFnr14= cloud.google.com/go v0.115.0/go.mod h1:8jIM5vVgoAEoiVxQ/O4BFTfHqulPZgs/ufEzMcFMdWU= @@ -398,8 +400,8 @@ golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDf golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= -golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb h1:c0vyKkb6yr3KR7jEfJaOSv4lG7xPkbN6r52aJz1d8a8= +golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= 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-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= diff --git a/pkg/config/config.go b/pkg/config/config.go index 900ecef26..6a6aca77e 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -279,6 +279,7 @@ const ( IssuerTypeGithubWorkflow = "github-workflow" IssuerTypeCodefreshWorkflow = "codefresh-workflow" IssuerTypeGitLabPipeline = "gitlab-pipeline" + IssuerTypeChainguard = "chainguard-identity" IssuerTypeKubernetes = "kubernetes" IssuerTypeSpiffe = "spiffe" IssuerTypeURI = "uri" @@ -517,6 +518,8 @@ func issuerToChallengeClaim(issType IssuerType, challengeClaim string) string { return "sub" case IssuerTypeCodefreshWorkflow: return "sub" + case IssuerTypeChainguard: + return "sub" case IssuerTypeKubernetes: return "sub" case IssuerTypeSpiffe: diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index 1c926a044..4c0967660 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -498,6 +498,9 @@ func Test_issuerToChallengeClaim(t *testing.T) { if claim := issuerToChallengeClaim(IssuerTypeCodefreshWorkflow, ""); claim != "sub" { t.Fatalf("expected sub subject claim for Codefresh issuer, got %s", claim) } + if claim := issuerToChallengeClaim(IssuerTypeChainguard, ""); claim != "sub" { + t.Fatalf("expected sub subject claim for Chainguard issuer, got %s", claim) + } if claim := issuerToChallengeClaim(IssuerTypeKubernetes, ""); claim != "sub" { t.Fatalf("expected sub subject claim for K8S issuer, got %s", claim) } diff --git a/pkg/identity/chainguard/issuer.go b/pkg/identity/chainguard/issuer.go new file mode 100644 index 000000000..41df8c4b0 --- /dev/null +++ b/pkg/identity/chainguard/issuer.go @@ -0,0 +1,40 @@ +// Copyright 2024 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 chainguard + +import ( + "context" + "fmt" + + "github.com/sigstore/fulcio/pkg/config" + "github.com/sigstore/fulcio/pkg/identity" + "github.com/sigstore/fulcio/pkg/identity/base" +) + +type issuer struct { + identity.Issuer +} + +func Issuer(issuerURL string) identity.Issuer { + return &issuer{base.Issuer(issuerURL)} +} + +func (e *issuer) Authenticate(ctx context.Context, token string, opts ...config.InsecureOIDCConfigOption) (identity.Principal, error) { + idtoken, err := identity.Authorize(ctx, token, opts...) + if err != nil { + return nil, fmt.Errorf("authorizing chainguard issuer: %w", err) + } + return PrincipalFromIDToken(ctx, idtoken) +} diff --git a/pkg/identity/chainguard/issuer_test.go b/pkg/identity/chainguard/issuer_test.go new file mode 100644 index 000000000..6e3412a26 --- /dev/null +++ b/pkg/identity/chainguard/issuer_test.go @@ -0,0 +1,97 @@ +// Copyright 2024 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 chainguard + +import ( + "context" + "encoding/json" + "fmt" + "reflect" + "testing" + "unsafe" + + "chainguard.dev/sdk/uidp" + "github.com/coreos/go-oidc/v3/oidc" + "github.com/sigstore/fulcio/pkg/config" + "github.com/sigstore/fulcio/pkg/identity" +) + +func TestIssuer(t *testing.T) { + ctx := context.Background() + url := "test-issuer-url" + issuer := Issuer(url) + + // test the Match function + t.Run("match", func(t *testing.T) { + if matches := issuer.Match(ctx, url); !matches { + t.Fatal("expected url to match but it doesn't") + } + if matches := issuer.Match(ctx, "some-other-url"); matches { + t.Fatal("expected match to fail but it didn't") + } + }) + + t.Run("authenticate", func(t *testing.T) { + group := uidp.NewUIDP("") + id := group.NewChild() + + token := &oidc.IDToken{ + Issuer: "https://iss.example.com", + Subject: id.String(), + } + claims, err := json.Marshal(map[string]interface{}{ + "iss": "https://iss.example.com", + "sub": id.String(), + + // Actor claims track the identity that was used to assume the + // Chainguard identity. In this case, it is the Catalog Syncer + // service principal. + "act": map[string]string{ + "iss": "https://iss.example.com/", + "sub": fmt.Sprintf("catalog-syncer:%s", group.String()), + "aud": "chainguard", + }, + "internal": map[string]interface{}{ + "service-principal": "CATALOG_SYNCER", + }, + }) + if err != nil { + t.Fatal(err) + } + withClaims(token, claims) + + identity.Authorize = func(_ context.Context, _ string, _ ...config.InsecureOIDCConfigOption) (*oidc.IDToken, error) { + return token, nil + } + principal, err := issuer.Authenticate(ctx, "token") + if err != nil { + t.Fatal(err) + } + + if principal.Name(ctx) != id.String() { + t.Fatalf("got unexpected name %s", principal.Name(ctx)) + } + }) +} + +// reflect hack because "claims" field is unexported by oidc IDToken +// https://github.com/coreos/go-oidc/pull/329 +func withClaims(token *oidc.IDToken, data []byte) { + val := reflect.Indirect(reflect.ValueOf(token)) + member := val.FieldByName("claims") + pointer := unsafe.Pointer(member.UnsafeAddr()) + realPointer := (*[]byte)(pointer) + *realPointer = data +} diff --git a/pkg/identity/chainguard/principal.go b/pkg/identity/chainguard/principal.go new file mode 100644 index 000000000..d2940c667 --- /dev/null +++ b/pkg/identity/chainguard/principal.go @@ -0,0 +1,80 @@ +// Copyright 2024 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 chainguard + +import ( + "context" + "crypto/x509" + "net/url" + + "github.com/coreos/go-oidc/v3/oidc" + "github.com/sigstore/fulcio/pkg/certificate" + "github.com/sigstore/fulcio/pkg/identity" +) + +type workflowPrincipal struct { + issuer string + subject string + + actor map[string]string + servicePrincipal string +} + +var _ identity.Principal = (*workflowPrincipal)(nil) + +func (w workflowPrincipal) Name(_ context.Context) string { + return w.subject +} + +func PrincipalFromIDToken(_ context.Context, token *oidc.IDToken) (identity.Principal, error) { + var claims struct { + Actor map[string]string `json:"act"` + Internal struct { + ServicePrincipal string `json:"service-principal,omitempty"` + } `json:"internal"` + } + + if err := token.Claims(&claims); err != nil { + return nil, err + } + + return &workflowPrincipal{ + issuer: token.Issuer, + subject: token.Subject, + actor: claims.Actor, + servicePrincipal: claims.Internal.ServicePrincipal, + }, nil +} + +func (w workflowPrincipal) Embed(_ context.Context, cert *x509.Certificate) error { + baseURL, err := url.Parse(w.issuer) + if err != nil { + return err + } + + // Set SAN to the / + cert.URIs = []*url.URL{baseURL.JoinPath(w.subject)} + + cert.ExtraExtensions, err = certificate.Extensions{ + Issuer: w.issuer, + + // TODO(mattmoor): Embed more of the Chainguard token structure via OIDs. + }.Render() + if err != nil { + return err + } + + return nil +} diff --git a/pkg/identity/chainguard/principal_test.go b/pkg/identity/chainguard/principal_test.go new file mode 100644 index 000000000..db995db17 --- /dev/null +++ b/pkg/identity/chainguard/principal_test.go @@ -0,0 +1,232 @@ +// Copyright 2024 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 chainguard + +import ( + "context" + "crypto/x509" + "encoding/asn1" + "encoding/json" + "errors" + "fmt" + "net/url" + "reflect" + "strings" + "testing" + + "chainguard.dev/sdk/uidp" + "github.com/coreos/go-oidc/v3/oidc" + "github.com/sigstore/fulcio/pkg/identity" +) + +func TestJobPrincipalFromIDToken(t *testing.T) { + group := uidp.NewUIDP("") + id := group.NewChild() + + tests := map[string]struct { + Claims map[string]interface{} + ExpectPrincipal workflowPrincipal + WantErr bool + ErrContains string + }{ + `Service principal token`: { + Claims: map[string]interface{}{ + "iss": "https://issuer.enforce.dev", + "sub": id.String(), + // Actor claims track the identity that was used to assume the + // Chainguard identity. In this case, it is the Catalog Syncer + // service principal. + "act": map[string]string{ + "iss": "https://iss.example.com/", + "sub": fmt.Sprintf("catalog-syncer:%s", group.String()), + "aud": "chainguard", + }, + "internal": map[string]interface{}{ + "service-principal": "CATALOG_SYNCER", + }, + }, + ExpectPrincipal: workflowPrincipal{ + issuer: "https://issuer.enforce.dev", + subject: id.String(), + actor: map[string]string{ + "iss": "https://iss.example.com/", + "sub": fmt.Sprintf("catalog-syncer:%s", group.String()), + "aud": "chainguard", + }, + servicePrincipal: "CATALOG_SYNCER", + }, + WantErr: false, + }, + `Human SSO token`: { + Claims: map[string]interface{}{ + "iss": "https://issuer.enforce.dev", + "sub": group.String(), + // Actor claims track the identity that was used to assume the + // Chainguard identity. In this case, it is the Catalog Syncer + // service principal. + "act": map[string]string{ + "iss": "https://auth.chainguard.dev/", + "sub": "google-oauth2|1234567890", + "aud": "fdsaldfkjhasldf", + }, + }, + ExpectPrincipal: workflowPrincipal{ + issuer: "https://issuer.enforce.dev", + subject: group.String(), + actor: map[string]string{ + "iss": "https://auth.chainguard.dev/", + "sub": "google-oauth2|1234567890", + "aud": "fdsaldfkjhasldf", + }, + }, + WantErr: false, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + token := &oidc.IDToken{ + Issuer: test.Claims["iss"].(string), + Subject: test.Claims["sub"].(string), + } + claims, err := json.Marshal(test.Claims) + if err != nil { + t.Fatal(err) + } + withClaims(token, claims) + + untyped, err := PrincipalFromIDToken(context.TODO(), token) + if err != nil { + if !test.WantErr { + t.Fatal("didn't expect error", err) + } + if !strings.Contains(err.Error(), test.ErrContains) { + t.Fatalf("expected error %s to contain %s", err, test.ErrContains) + } + return + } + if err == nil && test.WantErr { + t.Fatal("expected error but got none") + } + + principal, ok := untyped.(*workflowPrincipal) + if !ok { + t.Errorf("Got wrong principal type %v", untyped) + } + if !reflect.DeepEqual(*principal, test.ExpectPrincipal) { + t.Errorf("got %v principal and expected %v", *principal, test.ExpectPrincipal) + } + }) + } +} + +func TestEmbed(t *testing.T) { + group := uidp.NewUIDP("") + id := group.NewChild() + + tests := map[string]struct { + Principal identity.Principal + WantErr bool + WantFacts map[string]func(x509.Certificate) error + }{ + `Chainguard Service Principal`: { + Principal: &workflowPrincipal{ + issuer: "https://issuer.enforce.dev", + subject: id.String(), + actor: map[string]string{ + "iss": "https://iss.example.com/", + "sub": fmt.Sprintf("catalog-syncer:%s", group.String()), + "aud": "chainguard", + }, + servicePrincipal: "CATALOG_SYNCER", + }, + WantErr: false, + WantFacts: map[string]func(x509.Certificate) error{ + `Certificate SAN has correct value`: factSanURIIs(fmt.Sprintf("https://issuer.enforce.dev/%s", id.String())), + `Certificate has correct issuer (v2) extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 8}, "https://issuer.enforce.dev"), + }, + }, + `Chainguard Human SSO`: { + Principal: &workflowPrincipal{ + issuer: "https://issuer.enforce.dev", + subject: group.String(), + actor: map[string]string{ + "iss": "https://auth.chainguard.dev/", + "sub": "google-oauth2|1234567890", + "aud": "fdsaldfkjhasldf", + }, + }, + WantErr: false, + WantFacts: map[string]func(x509.Certificate) error{ + `Certificate SAN has correct value`: factSanURIIs(fmt.Sprintf("https://issuer.enforce.dev/%s", group.String())), + `Certificate has correct issuer (v2) extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 8}, "https://issuer.enforce.dev"), + }, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + var cert x509.Certificate + err := test.Principal.Embed(context.TODO(), &cert) + if err != nil { + if !test.WantErr { + t.Error(err) + } + return + } else if test.WantErr { + t.Error("expected error") + } + for factName, fact := range test.WantFacts { + t.Run(factName, func(t *testing.T) { + if err := fact(cert); err != nil { + t.Error(err) + } + }) + } + }) + } +} + +func factExtensionIs(oid asn1.ObjectIdentifier, value string) func(x509.Certificate) error { + return func(cert x509.Certificate) error { + for _, ext := range cert.ExtraExtensions { + if ext.Id.Equal(oid) { + var strVal string + _, _ = asn1.Unmarshal(ext.Value, &strVal) + if value != strVal { + return fmt.Errorf("expected oid %v to be %s, but got %s", oid, value, strVal) + } + return nil + } + } + return errors.New("extension not set") + } +} + +func factSanURIIs(value string) func(x509.Certificate) error { + return func(cert x509.Certificate) error { + url, err := url.Parse(value) + + if err != nil { + return err + } + + if cert.URIs[0].String() != url.String() { + return fmt.Errorf("expected SAN o be %s, but got %s", value, cert.URIs[0].String()) + } + + return nil + } +} diff --git a/pkg/server/grpc_server_test.go b/pkg/server/grpc_server_test.go index 06d6c9e2e..999083160 100644 --- a/pkg/server/grpc_server_test.go +++ b/pkg/server/grpc_server_test.go @@ -39,6 +39,7 @@ import ( "testing" "time" + "chainguard.dev/sdk/uidp" "github.com/go-jose/go-jose/v4" "github.com/go-jose/go-jose/v4/jwt" ctclient "github.com/google/certificate-transparency-go/client" @@ -197,6 +198,7 @@ func TestGetConfiguration(t *testing.T) { _, gitHubIssuer := newOIDCIssuer(t) _, gitLabIssuer := newOIDCIssuer(t) _, codefreshIssuer := newOIDCIssuer(t) + _, chainguardIssuer := newOIDCIssuer(t) issuerDomain, err := url.Parse(usernameIssuer) if err != nil { @@ -247,6 +249,11 @@ func TestGetConfiguration(t *testing.T) { "IssuerURL": %q, "ClientID": "sigstore", "Type": "codefresh-workflow" + }, + %q: { + "IssuerURL": %q, + "ClientID": "sigstore", + "Type": "chainguard-identity" } }, "MetaIssuers": { @@ -263,6 +270,7 @@ func TestGetConfiguration(t *testing.T) { gitHubIssuer, gitHubIssuer, gitLabIssuer, gitLabIssuer, codefreshIssuer, codefreshIssuer, + chainguardIssuer, chainguardIssuer, k8sIssuer))) if err != nil { t.Fatalf("config.Read() = %v", err) @@ -283,14 +291,15 @@ func TestGetConfiguration(t *testing.T) { t.Fatal("GetConfiguration failed", err) } - if len(config.Issuers) != 9 { - t.Fatalf("expected 9 issuers, got %v", len(config.Issuers)) + if got, want := len(config.Issuers), 10; got != want { + t.Fatalf("expected %d issuers, got %d", want, got) } expectedIssuers := map[string]bool{ emailIssuer: true, spiffeIssuer: true, uriIssuer: true, usernameIssuer: true, k8sIssuer: true, gitHubIssuer: true, buildkiteIssuer: true, gitLabIssuer: true, codefreshIssuer: true, + chainguardIssuer: true, } for _, iss := range config.Issuers { var issURL string @@ -1400,6 +1409,130 @@ func TestAPIWithCodefresh(t *testing.T) { } } +// chainguardClaims holds the additional JWT claims for Chainguard OIDC tokens +type chainguardClaims struct { + Actor map[string]string `json:"act"` + Internal struct { + ServicePrincipal string `json:"service-principal,omitempty"` + } `json:"internal"` +} + +// Tests API for Chainguard subject types +func TestAPIWithChainguard(t *testing.T) { + chainguardSigner, chainguardIssuer := newOIDCIssuer(t) + + // Create a FulcioConfig that supports these issuers. + cfg, err := config.Read([]byte(fmt.Sprintf(`{ + "OIDCIssuers": { + %q: { + "IssuerURL": %q, + "ClientID": "sigstore", + "Type": "chainguard-identity" + } + } + }`, chainguardIssuer, chainguardIssuer))) + if err != nil { + t.Fatalf("config.Read() = %v", err) + } + + group := uidp.NewUIDP("") + chainguardSubject := group.NewChild() + claims := chainguardClaims{ + Actor: map[string]string{ + "iss": chainguardIssuer, + "sub": fmt.Sprintf("catalog-syncer:%s", group.String()), + "aud": "chainguard", + }, + Internal: struct { + ServicePrincipal string `json:"service-principal,omitempty"` + }{ + ServicePrincipal: "CATALOG_SYNCER", + }, + } + + // Create an OIDC token using this issuer's signer. + tok, err := jwt.Signed(chainguardSigner).Claims(jwt.Claims{ + Issuer: chainguardIssuer, + IssuedAt: jwt.NewNumericDate(time.Now()), + Expiry: jwt.NewNumericDate(time.Now().Add(30 * time.Minute)), + Subject: chainguardSubject.String(), + Audience: jwt.Audience{"sigstore"}, + }).Claims(&claims).Serialize() + if err != nil { + t.Fatalf("CompactSerialize() = %v", err) + } + + ctClient, eca := createCA(cfg, t) + ctx := context.Background() + server, conn := setupGRPCForTest(t, cfg, ctClient, eca) + defer func() { + server.Stop() + conn.Close() + }() + + client := protobuf.NewCAClient(conn) + + pubBytes, proof := generateKeyAndProof(chainguardSubject.String(), t) + + // Hit the API to have it sign our certificate. + resp, err := client.CreateSigningCertificate(ctx, &protobuf.CreateSigningCertificateRequest{ + Credentials: &protobuf.Credentials{ + Credentials: &protobuf.Credentials_OidcIdentityToken{ + OidcIdentityToken: tok, + }, + }, + Key: &protobuf.CreateSigningCertificateRequest_PublicKeyRequest{ + PublicKeyRequest: &protobuf.PublicKeyRequest{ + PublicKey: &protobuf.PublicKey{ + Content: pubBytes, + }, + ProofOfPossession: proof, + }, + }, + }) + if err != nil { + t.Fatalf("SigningCert() = %v", err) + } + + leafCert := verifyResponse(resp, eca, chainguardIssuer, t) + + // Expect URI values + if len(leafCert.URIs) != 1 { + t.Fatalf("unexpected length of leaf certificate URIs, expected 1, got %d", len(leafCert.URIs)) + } + chainguardURL := fmt.Sprintf("%s/%s", chainguardIssuer, chainguardSubject) + chainguardURI, err := url.Parse(chainguardURL) + if err != nil { + t.Fatalf("failed to parse expected url") + } + if *leafCert.URIs[0] != *chainguardURI { + t.Fatalf("URIs do not match: Expected %v, got %v", chainguardURI, leafCert.URIs[0]) + } + + expectedExts := map[int]string{ + 8: chainguardIssuer, + + // TODO(mattmoor): Embed more of the Chainguard token structure via OIDs. + } + for o, value := range expectedExts { + ext, found := findCustomExtension(leafCert, asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, o}) + if !found { + t.Fatalf("expected extension in custom OID 1.3.6.1.4.1.57264.1.%d", o) + } + var extValue string + rest, err := asn1.Unmarshal(ext.Value, &extValue) + if err != nil { + t.Fatalf("error unmarshalling extension: :%v", err) + } + if len(rest) != 0 { + t.Fatal("error unmarshalling extension, rest is not 0") + } + if string(extValue) != value { + t.Fatalf("unexpected extension value, expected %s, got %s", value, extValue) + } + } +} + // Tests API with issuer claim in different field in the OIDC token func TestAPIWithIssuerClaimConfig(t *testing.T) { emailSigner, emailIssuer := newOIDCIssuer(t) diff --git a/pkg/server/issuer_pool.go b/pkg/server/issuer_pool.go index 9905df5cb..18349f262 100644 --- a/pkg/server/issuer_pool.go +++ b/pkg/server/issuer_pool.go @@ -18,6 +18,7 @@ import ( "github.com/sigstore/fulcio/pkg/config" "github.com/sigstore/fulcio/pkg/identity" "github.com/sigstore/fulcio/pkg/identity/buildkite" + "github.com/sigstore/fulcio/pkg/identity/chainguard" "github.com/sigstore/fulcio/pkg/identity/codefresh" "github.com/sigstore/fulcio/pkg/identity/email" "github.com/sigstore/fulcio/pkg/identity/github" @@ -62,6 +63,8 @@ func getIssuer(meta string, i config.OIDCIssuer) identity.Issuer { return buildkite.Issuer(issuerURL) case config.IssuerTypeCodefreshWorkflow: return codefresh.Issuer(issuerURL) + case config.IssuerTypeChainguard: + return chainguard.Issuer(issuerURL) case config.IssuerTypeKubernetes: return kubernetes.Issuer(issuerURL) case config.IssuerTypeSpiffe: From 98929593d42be8d32aec6df8b8ebcbdb8c3b424a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Jun 2024 22:13:51 +0000 Subject: [PATCH 15/56] Bump github.com/hashicorp/go-retryablehttp in the go_modules group Bumps the go_modules group with 1 update: [github.com/hashicorp/go-retryablehttp](https://github.com/hashicorp/go-retryablehttp). Updates `github.com/hashicorp/go-retryablehttp` from 0.7.6 to 0.7.7 - [Changelog](https://github.com/hashicorp/go-retryablehttp/blob/main/CHANGELOG.md) - [Commits](https://github.com/hashicorp/go-retryablehttp/compare/v0.7.6...v0.7.7) --- updated-dependencies: - dependency-name: github.com/hashicorp/go-retryablehttp dependency-type: indirect dependency-group: go_modules ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b33009ceb..8caa0c7bf 100644 --- a/go.mod +++ b/go.mod @@ -96,7 +96,7 @@ require ( github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-retryablehttp v0.7.6 // indirect + github.com/hashicorp/go-retryablehttp v0.7.7 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect github.com/hashicorp/go-secure-stdlib/parseutil v0.1.7 // indirect github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect diff --git a/go.sum b/go.sum index 16749b98f..e17dcbadb 100644 --- a/go.sum +++ b/go.sum @@ -191,8 +191,8 @@ github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVH github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= 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-retryablehttp v0.7.6 h1:TwRYfx2z2C4cLbXmT8I5PgP/xmuqASDyiVuGYfs9GZM= -github.com/hashicorp/go-retryablehttp v0.7.6/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= +github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= +github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= 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/parseutil v0.1.7 h1:UpiO20jno/eV1eVZcxqWnUohyKRe1g8FPV/xH1s/2qs= From 486397ec306f25a295b5bfc1bdad2007f3fa4ee1 Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Mon, 27 May 2024 17:54:51 +0000 Subject: [PATCH 16/56] drafting generic issuer implementation Signed-off-by: Javan lacerda --- go.mod | 1 + pkg/config/config.yaml | 36 ++ pkg/config/config_reader.go | 72 +++ pkg/identity/generic/issuer.go | 39 ++ pkg/identity/generic/issuer_test.go | 81 +++ pkg/identity/generic/principal.go | 164 ++++++ pkg/identity/generic/principal_test.go | 662 +++++++++++++++++++++++++ 7 files changed, 1055 insertions(+) create mode 100644 pkg/config/config.yaml create mode 100644 pkg/config/config_reader.go create mode 100644 pkg/identity/generic/issuer.go create mode 100644 pkg/identity/generic/issuer_test.go create mode 100644 pkg/identity/generic/principal.go create mode 100644 pkg/identity/generic/principal_test.go diff --git a/go.mod b/go.mod index 8caa0c7bf..3d7b601d5 100644 --- a/go.mod +++ b/go.mod @@ -41,6 +41,7 @@ require ( google.golang.org/genproto/googleapis/api v0.0.0-20240610135401-a8a62080eff3 google.golang.org/grpc v1.64.0 google.golang.org/protobuf v1.34.2 + gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 sigs.k8s.io/release-utils v0.8.2 ) diff --git a/pkg/config/config.yaml b/pkg/config/config.yaml new file mode 100644 index 000000000..094ff7e1e --- /dev/null +++ b/pkg/config/config.yaml @@ -0,0 +1,36 @@ +# TODO: Fill it properly for the current providers +providers: + github: + extensions: + build-signer-digest: job_workflow_sha + source-repository-digest: sha + source-repository-ref: ref + source-repository-identifier: repository_id + run-invocation-uri: "{{.url}}/{{.repository}}/actions/runs/{{.run_id}}/" + uris: + - "{{.url}}/{{.job_workflow_ref}}" + defaults: + url: https://github.com + gitlab: + extensions: + build-signer-digest: ci_config_sha + source-repository-digest: sha + source-repository-ref: ref + source-repository-identifier: project_id + run-invocation-uri: "{{.url}}/{{.project_path}}/-/jobs/{{.job_id}}" + uris: + - ci_config_ref_uri + defaults: + url: https://gitlab.com + codefresh: + extensions: + build-signer-digest: build/{{.workflow_id}} + runner-environment: runner_environment + source-repository-uri: scm_repo_url + source-repository-ref: scm_ref + build-config-uri: api/pipelines/{{.pipeline_id}} + run-invocation-uri: build/{{.workflow_id}} + uris: + - "{{.platform_url}}/{{.account_name}}/{{.pipeline_name}}:{{.account_id}}/{{.pipeline_id}}" + defaults: + platform_url: https://g.codefresh.io diff --git a/pkg/config/config_reader.go b/pkg/config/config_reader.go new file mode 100644 index 000000000..8dad9615f --- /dev/null +++ b/pkg/config/config_reader.go @@ -0,0 +1,72 @@ +// 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 config + +import ( + "fmt" + "os" + + "gopkg.in/yaml.v3" +) + +type Extensions struct { + Issuer string // OID 1.3.6.1.4.1.57264.1.8 and 1.3.6.1.4.1.57264.1.1 (Deprecated) + Subject string + GithubWorkflowTrigger string `yaml:"github-workflow-trigger"` // OID 1.3.6.1.4.1.57264.1.2 + GithubWorkflowSHA string `yaml:"github-workflow-sha"` // OID 1.3.6.1.4.1.57264.1.3 + GithubWorkflowName string `yaml:"github-workflow-name"` // OID 1.3.6.1.4.1.57264.1.4 + GithubWorkflowRepository string `yaml:"github-workflow-repository"` // OID 1.3.6.1.4.1.57264.1.5 + GithubWorkflowRef string `yaml:"github-workflow-ref"` // 1.3.6.1.4.1.57264.1.6 + BuildSignerURI string `yaml:"build-signer-uri"` // 1.3.6.1.4.1.57264.1.9 + BuildSignerDigest string `yaml:"build-signer-digest"` // 1.3.6.1.4.1.57264.1.10 + RunnerEnvironment string `yaml:"runner-environment"` // 1.3.6.1.4.1.57264.1.11 + SourceRepositoryURI string `yaml:"source-repository-uri"` // 1.3.6.1.4.1.57264.1.12 + SourceRepositoryDigest string `yaml:"source-repository-digest"` // 1.3.6.1.4.1.57264.1.13 + SourceRepositoryRef string `yaml:"source-repository-ref"` // 1.3.6.1.4.1.57264.1.14 + SourceRepositoryIdentifier string `yaml:"source-repository-identifier"` // 1.3.6.1.4.1.57264.1.15 + SourceRepositoryOwnerURI string `yaml:"source-repository-owner-uri"` // 1.3.6.1.4.1.57264.1.16 + SourceRepositoryOwnerIdentifier string `yaml:"source-repository-owner-identifier"` // 1.3.6.1.4.1.57264.1.17 + BuildConfigURI string `yaml:"build-config-uri"` // 1.3.6.1.4.1.57264.1.18 + BuildConfigDigest string `yaml:"build-config-digest"` // 1.3.6.1.4.1.57264.1.19 + BuildTrigger string `yaml:"build-trigger"` // 1.3.6.1.4.1.57264.1.20 + RunInvocationURI string `yaml:"run-invocation-uri"` // 1.3.6.1.4.1.57264.1.21 + SourceRepositoryVisibilityAtSigning string `yaml:"source-repository-visibility-at-signing"` // 1.3.6.1.4.1.57264.1.22 +} + +type RootYaml struct { + Providers map[string]Provider +} + +type Provider struct { + Extensions Extensions + Uris []string + Defaults map[string]string +} + +func readYaml() RootYaml { + var obj RootYaml + + yamlFile, err := os.ReadFile("config.yaml") + if err != nil { + fmt.Printf("yamlFile.Get err #%v ", err) + } + err = yaml.Unmarshal(yamlFile, &obj) + if err != nil { + fmt.Printf("Unmarshal: %v", err) + } + + return obj +} diff --git a/pkg/identity/generic/issuer.go b/pkg/identity/generic/issuer.go new file mode 100644 index 000000000..0b2d1e24e --- /dev/null +++ b/pkg/identity/generic/issuer.go @@ -0,0 +1,39 @@ +// 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 generic + +import ( + "context" + + "github.com/sigstore/fulcio/pkg/config" + "github.com/sigstore/fulcio/pkg/identity" + "github.com/sigstore/fulcio/pkg/identity/base" +) + +type genericIssuer struct { + identity.Issuer +} + +func Issuer(issuerURL string) identity.Issuer { + return &genericIssuer{base.Issuer(issuerURL)} +} + +func (e *genericIssuer) Authenticate(ctx context.Context, token string, opts ...config.InsecureOIDCConfigOption) (identity.Principal, error) { + idtoken, err := identity.Authorize(ctx, token, opts...) + if err != nil { + return nil, err + } + return WorkflowPrincipalFromIDToken(ctx, idtoken) +} diff --git a/pkg/identity/generic/issuer_test.go b/pkg/identity/generic/issuer_test.go new file mode 100644 index 000000000..5b06e743a --- /dev/null +++ b/pkg/identity/generic/issuer_test.go @@ -0,0 +1,81 @@ +// Copyright 2023 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 generic + +import ( + "context" + "encoding/json" + "testing" + + "github.com/coreos/go-oidc/v3/oidc" + "github.com/sigstore/fulcio/pkg/config" + "github.com/sigstore/fulcio/pkg/identity" +) + +func TestIssuer(t *testing.T) { + ctx := context.Background() + url := "test-issuer-url" + issuer := Issuer(url) + + // test the Match function + t.Run("match", func(t *testing.T) { + if matches := issuer.Match(ctx, url); !matches { + t.Fatal("expected url to match but it doesn't") + } + if matches := issuer.Match(ctx, "some-other-url"); matches { + t.Fatal("expected match to fail but it didn't") + } + }) + + t.Run("authenticate", func(t *testing.T) { + token := &oidc.IDToken{ + Issuer: "https://iss.example.com", + Subject: "subject", + } + claims, err := json.Marshal(map[string]interface{}{ + "aud": "sigstore", + "iss": "https://iss.example.com", + "sub": "doesntmatter", + "email": "alice@example.com", + "email_verified": true, + }) + if err != nil { + t.Fatal(err) + } + withClaims(token, claims) + + ctx := config.With(context.Background(), &config.FulcioConfig{ + OIDCIssuers: map[string]config.OIDCIssuer{ + "https://iss.example.com": { + IssuerURL: "https://iss.example.com", + Type: config.IssuerTypeEmail, + ClientID: "sigstore", + }, + }, + }) + + identity.Authorize = func(_ context.Context, _ string, _ ...config.InsecureOIDCConfigOption) (*oidc.IDToken, error) { + return token, nil + } + principal, err := issuer.Authenticate(ctx, "token") + if err != nil { + t.Fatal(err) + } + + if principal.Name(ctx) != "alice@example.com" { + t.Fatalf("got unexpected name %s", principal.Name(ctx)) + } + }) +} diff --git a/pkg/identity/generic/principal.go b/pkg/identity/generic/principal.go new file mode 100644 index 000000000..e492b2fc1 --- /dev/null +++ b/pkg/identity/generic/principal.go @@ -0,0 +1,164 @@ +// 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 generic + +import ( + "bytes" + "context" + "crypto/x509" + "fmt" + "net/url" + "os" + "strings" + "text/template" + + "github.com/coreos/go-oidc/v3/oidc" + "github.com/sigstore/fulcio/pkg/certificate" + "github.com/sigstore/fulcio/pkg/identity" + "gopkg.in/yaml.v2" +) + +// TODO: Delete after merged the config reader and get it directly from the github repo +type RootYaml struct { + Providers map[string]Provider +} + +type Provider struct { + Subject string + Extensions certificate.Extensions + Uris []string + Defaults map[string]string +} + +func readYaml() RootYaml { + var obj RootYaml + + yamlFile, err := os.ReadFile("../../config/config.yaml") + if err != nil { + fmt.Printf("yamlFile.Get err #%v ", err) + } + err = yaml.Unmarshal(yamlFile, &obj) + if err != nil { + fmt.Printf("Unmarshal: %v", err) + } + + return obj +} + +func WorkflowPrincipalFromIDToken(_ context.Context, token *oidc.IDToken) (identity.Principal, error) { + var claims map[string]string + if err := token.Claims(&claims); err != nil { + return nil, err + } + + yaml := readYaml() + + // It probably doesn't work + provider := yaml.Providers[token.Subject] + e := provider.Extensions + defaults := provider.Defaults + finalExtensions := certificate.Extensions{ + Issuer: ApplyTemplate(e.Issuer, claims, defaults), + GithubWorkflowTrigger: ApplyTemplate(e.GithubWorkflowTrigger, claims, defaults), + GithubWorkflowSHA: ApplyTemplate(e.GithubWorkflowSHA, claims, defaults), + GithubWorkflowName: ApplyTemplate(e.GithubWorkflowName, claims, defaults), + GithubWorkflowRepository: ApplyTemplate(e.GithubWorkflowRepository, claims, defaults), + GithubWorkflowRef: ApplyTemplate(e.GithubWorkflowRef, claims, defaults), + BuildSignerURI: ApplyTemplate(e.BuildSignerURI, claims, defaults), + BuildConfigDigest: ApplyTemplate(e.BuildConfigDigest, claims, defaults), + RunnerEnvironment: ApplyTemplate(e.RunnerEnvironment, claims, defaults), + SourceRepositoryURI: ApplyTemplate(e.SourceRepositoryURI, claims, defaults), + SourceRepositoryDigest: ApplyTemplate(e.SourceRepositoryDigest, claims, defaults), + SourceRepositoryRef: ApplyTemplate(e.SourceRepositoryRef, claims, defaults), + SourceRepositoryIdentifier: ApplyTemplate(e.SourceRepositoryIdentifier, claims, defaults), + SourceRepositoryOwnerURI: ApplyTemplate(e.SourceRepositoryOwnerURI, claims, defaults), + SourceRepositoryOwnerIdentifier: ApplyTemplate(e.SourceRepositoryOwnerIdentifier, claims, defaults), + BuildConfigURI: ApplyTemplate(e.BuildConfigURI, claims, defaults), + BuildSignerDigest: ApplyTemplate(e.BuildSignerDigest, claims, defaults), + BuildTrigger: ApplyTemplate(e.BuildTrigger, claims, defaults), + RunInvocationURI: ApplyTemplate(e.RunInvocationURI, claims, defaults), + SourceRepositoryVisibilityAtSigning: ApplyTemplate(e.SourceRepositoryVisibilityAtSigning, claims, defaults), + } + finalUris := make([]string, len(provider.Uris)-1) + for _, val := range provider.Uris { + finalUris = append(finalUris, ApplyTemplate(val, claims, defaults)) + } + + return &Provider{ + Subject: token.Subject, + Extensions: finalExtensions, + Uris: finalUris, + }, nil +} + +func ApplyTemplate(path string, data map[string]string, defaultData map[string]string) string { + + // Here we merge the data from was claimed by the id token with the + // default data provided by the yaml file. + // The order here matter because we want to override the default data + // with the claimed data. + mergedData := make(map[string]string) + for k, v := range defaultData { + mergedData[k] = v + } + for k, v := range data { + mergedData[k] = v + } + + // It checks it is a path or a raw field by + // checking exists template syntax into the string + if strings.Contains(path, "{{.") { + var doc bytes.Buffer + t := template.New("") + p, err := t.Parse(path) + if err != nil { + panic(err) + } + err = p.Execute(&doc, mergedData) + if err != nil { + panic(err) + } + return doc.String() + } else { + return mergedData[path] + } +} + +func (p Provider) Name(_ context.Context) string { + return p.Subject +} + +func (p Provider) Embed(_ context.Context, cert *x509.Certificate) error { + + uris := make([]*url.URL, len(p.Uris)) + for _, value := range p.Uris { + url, err := url.Parse(value) + if err != nil { + panic(err) + } + uris = append(uris, url) + } + // Set workflow ref URL to SubjectAlternativeName on certificate + cert.URIs = uris + + var err error + // Embed additional information into custom extensions + cert.ExtraExtensions, err = p.Extensions.Render() + if err != nil { + return err + } + + return nil +} diff --git a/pkg/identity/generic/principal_test.go b/pkg/identity/generic/principal_test.go new file mode 100644 index 000000000..9ee4fd1f7 --- /dev/null +++ b/pkg/identity/generic/principal_test.go @@ -0,0 +1,662 @@ +// 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 generic + +import ( + "bytes" + "context" + "crypto/x509" + "encoding/asn1" + "encoding/json" + "errors" + "fmt" + "reflect" + "testing" + "unsafe" + + "github.com/coreos/go-oidc/v3/oidc" + "github.com/sigstore/fulcio/pkg/identity" +) + +func TestWorkflowPrincipalFromIDToken(t *testing.T) { + tests := map[string]struct { + Claims map[string]interface{} + ExpectPrincipal Provider + WantErr bool + ErrContains string + }{ + `Valid token authenticates with correct claims`: { + Claims: map[string]interface{}{ + "aud": "sigstore", + "event_name": "push", + "exp": 0, + "iss": "https://token.actions.githubusercontent.com", + "job_workflow_ref": "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main", + "job_workflow_sha": "example-sha", + "ref": "refs/heads/main", + "repository": "sigstore/fulcio", + "repository_id": "12345", + "repository_owner": "username", + "repository_owner_id": "345", + "repository_visibility": "public", + "run_attempt": "1", + "run_id": "42", + "runner_environment": "cloud-hosted", + "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "sub": "repo:sigstore/fulcio:ref:refs/heads/main", + "workflow": "foo", + "workflow_ref": "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", + "workflow_sha": "example-sha-other", + }, + ExpectPrincipal: Provider{}, + WantErr: false, + }, + `Token missing job_workflow_ref claim should be rejected`: { + Claims: map[string]interface{}{ + "aud": "sigstore", + "event_name": "push", + "exp": 0, + "iss": "https://token.actions.githubusercontent.com", + "job_workflow_sha": "example-sha", + "ref": "refs/heads/main", + "repository": "sigstore/fulcio", + "repository_id": "12345", + "repository_owner": "username", + "repository_owner_id": "345", + "repository_visibility": "public", + "run_attempt": "1", + "run_id": "42", + "runner_environment": "cloud-hosted", + "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "sub": "repo:sigstore/fulcio:ref:refs/heads/main", + "workflow": "foo", + "workflow_ref": "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", + "workflow_sha": "example-sha-other", + }, + WantErr: true, + ErrContains: "job_workflow_ref", + }, + `Token missing sha should be rejected`: { + Claims: map[string]interface{}{ + "aud": "sigstore", + "event_name": "push", + "exp": 0, + "iss": "https://token.actions.githubusercontent.com", + "job_workflow_ref": "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main", + "job_workflow_sha": "example-sha", + "ref": "refs/heads/main", + "repository": "sigstore/fulcio", + "repository_id": "12345", + "repository_owner": "username", + "repository_owner_id": "345", + "repository_visibility": "public", + "run_attempt": "1", + "run_id": "42", + "runner_environment": "cloud-hosted", + "sub": "repo:sigstore/fulcio:ref:refs/heads/main", + "workflow": "foo", + "workflow_ref": "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", + "workflow_sha": "example-sha-other", + }, + WantErr: true, + ErrContains: "sha", + }, + `Token missing event_name claim should be rejected`: { + Claims: map[string]interface{}{ + "aud": "sigstore", + "exp": 0, + "iss": "https://token.actions.githubusercontent.com", + "job_workflow_ref": "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main", + "job_workflow_sha": "example-sha", + "ref": "refs/heads/main", + "repository": "sigstore/fulcio", + "repository_id": "12345", + "repository_owner": "username", + "repository_owner_id": "345", + "repository_visibility": "public", + "run_attempt": "1", + "run_id": "42", + "runner_environment": "cloud-hosted", + "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "sub": "repo:sigstore/fulcio:ref:refs/heads/main", + "workflow": "foo", + "workflow_ref": "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", + "workflow_sha": "example-sha-other", + }, + WantErr: true, + ErrContains: "event_name", + }, + `Token missing repository claim should be rejected`: { + Claims: map[string]interface{}{ + "aud": "sigstore", + "event_name": "push", + "exp": 0, + "iss": "https://token.actions.githubusercontent.com", + "job_workflow_ref": "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main", + "job_workflow_sha": "example-sha", + "ref": "refs/heads/main", + "repository_id": "12345", + "repository_owner": "username", + "repository_owner_id": "345", + "repository_visibility": "public", + "run_attempt": "1", + "run_id": "42", + "runner_environment": "cloud-hosted", + "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "sub": "repo:sigstore/fulcio:ref:refs/heads/main", + "workflow": "foo", + "workflow_ref": "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", + "workflow_sha": "example-sha-other", + }, + WantErr: true, + ErrContains: "repository", + }, + `Token missing workflow claim should be rejected`: { + Claims: map[string]interface{}{ + "aud": "sigstore", + "event_name": "push", + "exp": 0, + "iss": "https://token.actions.githubusercontent.com", + "job_workflow_ref": "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main", + "job_workflow_sha": "example-sha", + "ref": "refs/heads/main", + "repository": "sigstore/fulcio", + "repository_id": "12345", + "repository_owner": "username", + "repository_owner_id": "345", + "repository_visibility": "public", + "run_attempt": "1", + "run_id": "42", + "runner_environment": "cloud-hosted", + "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "sub": "repo:sigstore/fulcio:ref:refs/heads/main", + "workflow_ref": "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", + "workflow_sha": "example-sha-other", + }, + WantErr: true, + ErrContains: "workflow", + }, + `Token missing ref claim should be rejected`: { + Claims: map[string]interface{}{ + "aud": "sigstore", + "event_name": "push", + "exp": 0, + "iss": "https://token.actions.githubusercontent.com", + "job_workflow_ref": "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main", + "job_workflow_sha": "example-sha", + "repository": "sigstore/fulcio", + "repository_id": "12345", + "repository_owner": "username", + "repository_owner_id": "345", + "repository_visibility": "public", + "run_attempt": "1", + "run_id": "42", + "runner_environment": "cloud-hosted", + "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "sub": "repo:sigstore/fulcio:ref:refs/heads/main", + "workflow": "foo", + "workflow_ref": "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", + "workflow_sha": "example-sha-other", + }, + WantErr: true, + ErrContains: "ref", + }, + `Token missing job_workflow_sha claim should be rejected`: { + Claims: map[string]interface{}{ + "aud": "sigstore", + "event_name": "push", + "exp": 0, + "iss": "https://token.actions.githubusercontent.com", + "job_workflow_ref": "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main", + "ref": "refs/heads/main", + "repository": "sigstore/fulcio", + "repository_id": "12345", + "repository_owner": "username", + "repository_owner_id": "345", + "repository_visibility": "public", + "run_attempt": "1", + "run_id": "42", + "runner_environment": "cloud-hosted", + "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "sub": "repo:sigstore/fulcio:ref:refs/heads/main", + "workflow": "foo", + "workflow_ref": "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", + "workflow_sha": "example-sha-other", + }, + WantErr: true, + ErrContains: "job_workflow_sha", + }, + `Token missing runner_environment claim should be rejected`: { + Claims: map[string]interface{}{ + "aud": "sigstore", + "event_name": "push", + "exp": 0, + "iss": "https://token.actions.githubusercontent.com", + "job_workflow_ref": "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main", + "job_workflow_sha": "example-sha", + "ref": "refs/heads/main", + "repository": "sigstore/fulcio", + "repository_id": "12345", + "repository_owner": "username", + "repository_owner_id": "345", + "repository_visibility": "public", + "run_attempt": "1", + "run_id": "42", + "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "sub": "repo:sigstore/fulcio:ref:refs/heads/main", + "workflow": "foo", + "workflow_ref": "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", + "workflow_sha": "example-sha-other", + }, + WantErr: true, + ErrContains: "runner_environment", + }, + `Token missing repository_id claim should be rejected`: { + Claims: map[string]interface{}{ + "aud": "sigstore", + "event_name": "push", + "exp": 0, + "iss": "https://token.actions.githubusercontent.com", + "job_workflow_ref": "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main", + "job_workflow_sha": "example-sha", + "ref": "refs/heads/main", + "repository": "sigstore/fulcio", + "repository_owner": "username", + "repository_owner_id": "345", + "repository_visibility": "public", + "run_attempt": "1", + "run_id": "42", + "runner_environment": "cloud-hosted", + "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "sub": "repo:sigstore/fulcio:ref:refs/heads/main", + "workflow": "foo", + "workflow_ref": "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", + "workflow_sha": "example-sha-other", + }, + WantErr: true, + ErrContains: "repository_id", + }, + `Token missing repository_owner claim should be rejected`: { + Claims: map[string]interface{}{ + "aud": "sigstore", + "event_name": "push", + "exp": 0, + "iss": "https://token.actions.githubusercontent.com", + "job_workflow_ref": "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main", + "job_workflow_sha": "example-sha", + "ref": "refs/heads/main", + "repository": "sigstore/fulcio", + "repository_id": "12345", + "repository_owner_id": "345", + "repository_visibility": "public", + "run_attempt": "1", + "run_id": "42", + "runner_environment": "cloud-hosted", + "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "sub": "repo:sigstore/fulcio:ref:refs/heads/main", + "workflow": "foo", + "workflow_ref": "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", + "workflow_sha": "example-sha-other", + }, + WantErr: true, + ErrContains: "repository_owner", + }, + `Token missing repository_owner_id claim should be rejected`: { + Claims: map[string]interface{}{ + "aud": "sigstore", + "event_name": "push", + "exp": 0, + "iss": "https://token.actions.githubusercontent.com", + "job_workflow_ref": "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main", + "job_workflow_sha": "example-sha", + "ref": "refs/heads/main", + "repository": "sigstore/fulcio", + "repository_id": "12345", + "repository_owner": "username", + "repository_visibility": "public", + "run_attempt": "1", + "run_id": "42", + "runner_environment": "cloud-hosted", + "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "sub": "repo:sigstore/fulcio:ref:refs/heads/main", + "workflow": "foo", + "workflow_ref": "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", + "workflow_sha": "example-sha-other", + }, + WantErr: true, + ErrContains: "repository_owner_id", + }, + `Token missing workflow_ref claim should be rejected`: { + Claims: map[string]interface{}{ + "aud": "sigstore", + "event_name": "push", + "exp": 0, + "iss": "https://token.actions.githubusercontent.com", + "job_workflow_ref": "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main", + "job_workflow_sha": "example-sha", + "ref": "refs/heads/main", + "repository": "sigstore/fulcio", + "repository_id": "12345", + "repository_owner": "username", + "repository_owner_id": "345", + "repository_visibility": "public", + "run_attempt": "1", + "run_id": "42", + "runner_environment": "cloud-hosted", + "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "sub": "repo:sigstore/fulcio:ref:refs/heads/main", + "workflow": "foo", + "workflow_sha": "example-sha-other", + }, + WantErr: true, + ErrContains: "workflow_ref", + }, + `Token missing workflow_sha claim should be rejected`: { + Claims: map[string]interface{}{ + "aud": "sigstore", + "event_name": "push", + "exp": 0, + "iss": "https://token.actions.githubusercontent.com", + "job_workflow_ref": "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main", + "job_workflow_sha": "example-sha", + "ref": "refs/heads/main", + "repository": "sigstore/fulcio", + "repository_id": "12345", + "repository_owner": "username", + "repository_owner_id": "345", + "repository_visibility": "public", + "run_attempt": "1", + "run_id": "42", + "runner_environment": "cloud-hosted", + "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "sub": "repo:sigstore/fulcio:ref:refs/heads/main", + "workflow": "foo", + "workflow_ref": "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", + }, + WantErr: true, + ErrContains: "workflow_sha", + }, + `Token missing run_id claim should be rejected`: { + Claims: map[string]interface{}{ + "aud": "sigstore", + "event_name": "push", + "exp": 0, + "iss": "https://token.actions.githubusercontent.com", + "job_workflow_ref": "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main", + "job_workflow_sha": "example-sha", + "ref": "refs/heads/main", + "repository": "sigstore/fulcio", + "repository_id": "12345", + "repository_owner": "username", + "repository_owner_id": "345", + "repository_visibility": "public", + "run_attempt": "1", + "runner_environment": "cloud-hosted", + "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "sub": "repo:sigstore/fulcio:ref:refs/heads/main", + "workflow": "foo", + "workflow_ref": "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", + "workflow_sha": "example-sha-other", + }, + WantErr: true, + ErrContains: "run_id", + }, + `Token missing run_attempt claim should be rejected`: { + Claims: map[string]interface{}{ + "aud": "sigstore", + "event_name": "push", + "exp": 0, + "iss": "https://token.actions.githubusercontent.com", + "job_workflow_ref": "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main", + "job_workflow_sha": "example-sha", + "ref": "refs/heads/main", + "repository": "sigstore/fulcio", + "repository_id": "12345", + "repository_owner": "username", + "repository_owner_id": "345", + "repository_visibility": "public", + "run_id": "42", + "runner_environment": "cloud-hosted", + "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "sub": "repo:sigstore/fulcio:ref:refs/heads/main", + "workflow": "foo", + "workflow_ref": "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", + "workflow_sha": "example-sha-other", + }, + WantErr: true, + ErrContains: "run_attempt", + }, + `Token missing repository_visibility claim should be rejected`: { + Claims: map[string]interface{}{ + "aud": "sigstore", + "event_name": "push", + "exp": 0, + "iss": "https://token.actions.githubusercontent.com", + "job_workflow_ref": "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main", + "job_workflow_sha": "example-sha", + "ref": "refs/heads/main", + "repository": "sigstore/fulcio", + "repository_id": "12345", + "repository_owner": "username", + "repository_owner_id": "345", + "run_id": "42", + "runner_environment": "cloud-hosted", + "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "sub": "repo:sigstore/fulcio:ref:refs/heads/main", + "workflow": "foo", + "workflow_ref": "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", + "workflow_sha": "example-sha-other", + }, + WantErr: true, + ErrContains: "repository_visibility", + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + token := &oidc.IDToken{ + Issuer: test.Claims["iss"].(string), + Subject: test.Claims["sub"].(string), + } + claims, err := json.Marshal(test.Claims) + if err != nil { + t.Fatal(err) + } + withClaims(token, claims) + + // untyped, err := WorkflowPrincipalFromIDToken(context.TODO(), token) + // if err != nil { + // if !test.WantErr { + // t.Fatal("didn't expect error", err) + // } + // if !strings.Contains(err.Error(), test.ErrContains) { + // t.Fatalf("expected error %s to contain %s", err, test.ErrContains) + // } + // return + // } + // if err == nil && test.WantErr { + // t.Fatal("expected error but got none") + // } + + // principal, ok := untyped.(*Provider) + // if !ok { + // t.Errorf("Got wrong principal type %v", untyped) + // } + // if *principal != test.ExpectPrincipal { + // t.Errorf("got %v principal and expected %v", *principal, test.ExpectPrincipal) + // } + }) + } +} + +// reflect hack because "claims" field is unexported by oidc IDToken +// https://github.com/coreos/go-oidc/pull/329 +func withClaims(token *oidc.IDToken, data []byte) { + val := reflect.Indirect(reflect.ValueOf(token)) + member := val.FieldByName("claims") + pointer := unsafe.Pointer(member.UnsafeAddr()) + realPointer := (*[]byte)(pointer) + *realPointer = data +} + +func TestName(t *testing.T) { + tests := map[string]struct { + Claims map[string]interface{} + ExpectName string + }{ + `Valid token authenticates with correct claims`: { + Claims: map[string]interface{}{ + "aud": "sigstore", + "event_name": "push", + "exp": 0, + "iss": "https://token.actions.githubusercontent.com", + "job_workflow_ref": "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main", + "job_workflow_sha": "example-sha", + "ref": "refs/heads/main", + "repository": "sigstore/fulcio", + "repository_id": "12345", + "repository_owner": "username", + "repository_owner_id": "345", + "repository_visibility": "public", + "run_attempt": "1", + "run_id": "42", + "runner_environment": "cloud-hosted", + "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "sub": "repo:sigstore/fulcio:ref:refs/heads/main", + "workflow": "foo", + "workflow_ref": "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", + "workflow_sha": "example-sha-other", + }, + ExpectName: "repo:sigstore/fulcio:ref:refs/heads/main", + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + token := &oidc.IDToken{ + Issuer: test.Claims["iss"].(string), + Subject: test.Claims["sub"].(string), + } + claims, err := json.Marshal(test.Claims) + if err != nil { + t.Fatal(err) + } + withClaims(token, claims) + + principal, err := WorkflowPrincipalFromIDToken(context.TODO(), token) + if err != nil { + t.Fatal(err) + } + + gotName := principal.Name(context.TODO()) + if gotName != test.ExpectName { + t.Error("name should match sub claim") + } + }) + } + +} + +func TestEmbed(t *testing.T) { + tests := map[string]struct { + Principal identity.Principal + WantErr bool + WantFacts map[string]func(x509.Certificate) error + }{ + `Github workflow challenge should have all Github workflow extensions and issuer set`: { + Principal: &Provider{}, + WantErr: false, + WantFacts: map[string]func(x509.Certificate) error{ + `Certifificate should have correct issuer`: factDeprecatedExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 1}, "https://token.actions.githubusercontent.com"), + `Certificate has correct trigger extension`: factDeprecatedExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 2}, "trigger"), + `Certificate has correct SHA extension`: factDeprecatedExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 3}, "sha"), + `Certificate has correct workflow extension`: factDeprecatedExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 4}, "workflowname"), + `Certificate has correct repository extension`: factDeprecatedExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 5}, "repository"), + `Certificate has correct ref extension`: factDeprecatedExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 6}, "ref"), + `Certificate has correct issuer (v2) extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 8}, "https://token.actions.githubusercontent.com"), + `Certificate has correct builder signer URI extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 9}, "https://github.com/jobWorkflowRef"), + `Certificate has correct builder signer digest extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 10}, "jobWorkflowSha"), + `Certificate has correct runner environment extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 11}, "runnerEnv"), + `Certificate has correct source repo URI extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 12}, "https://github.com/repository"), + `Certificate has correct source repo digest extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 13}, "sha"), + `Certificate has correct source repo ref extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 14}, "ref"), + `Certificate has correct source repo ID extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 15}, "repoID"), + `Certificate has correct source repo owner URI extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 16}, "https://github.com/repoOwner"), + `Certificate has correct source repo owner ID extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 17}, "repoOwnerID"), + `Certificate has correct build config URI extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 18}, "https://github.com/workflowRef"), + `Certificate has correct build config digest extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 19}, "workflowSHA"), + `Certificate has correct build trigger extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 20}, "trigger"), + `Certificate has correct run invocation ID extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 21}, "https://github.com/repository/actions/runs/runID/attempts/runAttempt"), + `Certificate has correct source repository visibility extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 22}, "public"), + }, + }, + `Github workflow value with bad URL fails`: { + Principal: &Provider{}, + WantErr: true, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + var cert x509.Certificate + err := test.Principal.Embed(context.TODO(), &cert) + if err != nil { + if !test.WantErr { + t.Error(err) + } + return + } else if test.WantErr { + t.Error("expected error") + } + for factName, fact := range test.WantFacts { + t.Run(factName, func(t *testing.T) { + if err := fact(cert); err != nil { + t.Error(err) + } + }) + } + }) + } +} + +func factExtensionIs(oid asn1.ObjectIdentifier, value string) func(x509.Certificate) error { + return func(cert x509.Certificate) error { + for _, ext := range cert.ExtraExtensions { + if ext.Id.Equal(oid) { + var strVal string + _, _ = asn1.Unmarshal(ext.Value, &strVal) + if value != strVal { + return fmt.Errorf("expected oid %v to be %s, but got %s", oid, value, strVal) + } + return nil + } + } + return errors.New("extension not set") + } +} + +func factDeprecatedExtensionIs(oid asn1.ObjectIdentifier, value string) func(x509.Certificate) error { + return func(cert x509.Certificate) error { + for _, ext := range cert.ExtraExtensions { + if ext.Id.Equal(oid) { + if !bytes.Equal(ext.Value, []byte(value)) { + return fmt.Errorf("expected oid %v to be %s, but got %s", oid, value, ext.Value) + } + return nil + } + } + return errors.New("extension not set") + } +} From f74f6a6a752c793dda4f94cd9c0de35d50c9c46b Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Mon, 27 May 2024 18:11:06 +0000 Subject: [PATCH 17/56] adding license o yaml file Signed-off-by: Javan lacerda --- pkg/config/config.yaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/pkg/config/config.yaml b/pkg/config/config.yaml index 094ff7e1e..35176a1ef 100644 --- a/pkg/config/config.yaml +++ b/pkg/config/config.yaml @@ -1,3 +1,17 @@ +# Copyright 2024 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. + # TODO: Fill it properly for the current providers providers: github: From cc5a602b267324cfe2011967d02c7d07f6868e75 Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Tue, 28 May 2024 15:44:42 +0000 Subject: [PATCH 18/56] remove yaml2.0 Signed-off-by: Javan lacerda --- go.mod | 1 - pkg/identity/generic/principal.go | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 3d7b601d5..8caa0c7bf 100644 --- a/go.mod +++ b/go.mod @@ -41,7 +41,6 @@ require ( google.golang.org/genproto/googleapis/api v0.0.0-20240610135401-a8a62080eff3 google.golang.org/grpc v1.64.0 google.golang.org/protobuf v1.34.2 - gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 sigs.k8s.io/release-utils v0.8.2 ) diff --git a/pkg/identity/generic/principal.go b/pkg/identity/generic/principal.go index e492b2fc1..1823ff437 100644 --- a/pkg/identity/generic/principal.go +++ b/pkg/identity/generic/principal.go @@ -27,7 +27,7 @@ import ( "github.com/coreos/go-oidc/v3/oidc" "github.com/sigstore/fulcio/pkg/certificate" "github.com/sigstore/fulcio/pkg/identity" - "gopkg.in/yaml.v2" + "gopkg.in/yaml.v3" ) // TODO: Delete after merged the config reader and get it directly from the github repo From 9c2c0f84b9c1668d3da7090e756198ee28f6a4b6 Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Tue, 28 May 2024 17:45:34 +0000 Subject: [PATCH 19/56] start removing IssuerType usage Signed-off-by: Javan lacerda --- pkg/challenges/challenges.go | 58 +++++++++++++------------------ pkg/config/config.go | 2 ++ pkg/identity/generic/principal.go | 12 ++++--- 3 files changed, 34 insertions(+), 38 deletions(-) diff --git a/pkg/challenges/challenges.go b/pkg/challenges/challenges.go index dda3298ff..9a724c1f2 100644 --- a/pkg/challenges/challenges.go +++ b/pkg/challenges/challenges.go @@ -21,19 +21,10 @@ import ( "crypto" "crypto/x509" "errors" - "fmt" "strings" - "github.com/sigstore/fulcio/pkg/config" "github.com/sigstore/fulcio/pkg/identity" - "github.com/sigstore/fulcio/pkg/identity/buildkite" - "github.com/sigstore/fulcio/pkg/identity/email" - "github.com/sigstore/fulcio/pkg/identity/github" - "github.com/sigstore/fulcio/pkg/identity/gitlabcom" - "github.com/sigstore/fulcio/pkg/identity/kubernetes" - "github.com/sigstore/fulcio/pkg/identity/spiffe" - "github.com/sigstore/fulcio/pkg/identity/uri" - "github.com/sigstore/fulcio/pkg/identity/username" + "github.com/sigstore/fulcio/pkg/identity/generic" "github.com/coreos/go-oidc/v3/oidc" "github.com/sigstore/sigstore/pkg/cryptoutils" @@ -52,32 +43,31 @@ func CheckSignature(pub crypto.PublicKey, proof []byte, subject string) error { } func PrincipalFromIDToken(ctx context.Context, tok *oidc.IDToken) (identity.Principal, error) { - iss, ok := config.FromContext(ctx).GetIssuer(tok.Issuer) - if !ok { - return nil, fmt.Errorf("configuration can not be loaded for issuer %v", tok.Issuer) - } var principal identity.Principal var err error - switch iss.Type { - case config.IssuerTypeBuildkiteJob: - principal, err = buildkite.JobPrincipalFromIDToken(ctx, tok) - case config.IssuerTypeGitLabPipeline: - principal, err = gitlabcom.JobPrincipalFromIDToken(ctx, tok) - case config.IssuerTypeEmail: - principal, err = email.PrincipalFromIDToken(ctx, tok) - case config.IssuerTypeSpiffe: - principal, err = spiffe.PrincipalFromIDToken(ctx, tok) - case config.IssuerTypeGithubWorkflow: - principal, err = github.WorkflowPrincipalFromIDToken(ctx, tok) - case config.IssuerTypeKubernetes: - principal, err = kubernetes.PrincipalFromIDToken(ctx, tok) - case config.IssuerTypeURI: - principal, err = uri.PrincipalFromIDToken(ctx, tok) - case config.IssuerTypeUsername: - principal, err = username.PrincipalFromIDToken(ctx, tok) - default: - return nil, fmt.Errorf("unsupported issuer: %s", iss.Type) - } + + principal, err = generic.WorkflowPrincipalFromIDToken(ctx, tok) + + // switch iss.Type { + // case config.IssuerTypeBuildkiteJob: + // principal, err = buildkite.JobPrincipalFromIDToken(ctx, tok) + // case config.IssuerTypeGitLabPipeline: + // principal, err = gitlabcom.JobPrincipalFromIDToken(ctx, tok) + // case config.IssuerTypeEmail: + // principal, err = email.PrincipalFromIDToken(ctx, tok) + // case config.IssuerTypeSpiffe: + // principal, err = spiffe.PrincipalFromIDToken(ctx, tok) + // case config.IssuerTypeGithubWorkflow: + // principal, err = github.WorkflowPrincipalFromIDToken(ctx, tok) + // case config.IssuerTypeKubernetes: + // principal, err = kubernetes.PrincipalFromIDToken(ctx, tok) + // case config.IssuerTypeURI: + // principal, err = uri.PrincipalFromIDToken(ctx, tok) + // case config.IssuerTypeUsername: + // principal, err = username.PrincipalFromIDToken(ctx, tok) + // default: + // return nil, fmt.Errorf("unsupported issuer: %s", iss.Type) + // } if err != nil { return nil, err } diff --git a/pkg/config/config.go b/pkg/config/config.go index 6a6aca77e..d50d86673 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -271,6 +271,8 @@ func (fc *FulcioConfig) prepare() error { return nil } +// I would like to remove this completely, to be able to add or remove +// oidc providers only by the config.yaml file. type IssuerType string const ( diff --git a/pkg/identity/generic/principal.go b/pkg/identity/generic/principal.go index 1823ff437..9b77a1046 100644 --- a/pkg/identity/generic/principal.go +++ b/pkg/identity/generic/principal.go @@ -26,6 +26,7 @@ import ( "github.com/coreos/go-oidc/v3/oidc" "github.com/sigstore/fulcio/pkg/certificate" + "github.com/sigstore/fulcio/pkg/config" "github.com/sigstore/fulcio/pkg/identity" "gopkg.in/yaml.v3" ) @@ -57,16 +58,19 @@ func readYaml() RootYaml { return obj } -func WorkflowPrincipalFromIDToken(_ context.Context, token *oidc.IDToken) (identity.Principal, error) { +func WorkflowPrincipalFromIDToken(ctx context.Context, token *oidc.IDToken) (identity.Principal, error) { + iss, ok := config.FromContext(ctx).GetIssuer(token.Issuer) + if !ok { + return nil, fmt.Errorf("configuration can not be loaded for issuer %v", token.Issuer) + } + var claims map[string]string if err := token.Claims(&claims); err != nil { return nil, err } yaml := readYaml() - - // It probably doesn't work - provider := yaml.Providers[token.Subject] + provider := yaml.Providers[string(iss.Type)] e := provider.Extensions defaults := provider.Defaults finalExtensions := certificate.Extensions{ From 1261f88f88b7eec13ec0c3d3d88132d1d2d6ae32 Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Tue, 28 May 2024 17:48:07 +0000 Subject: [PATCH 20/56] update license year Signed-off-by: Javan lacerda --- pkg/config/config.go | 2 +- pkg/config/config_reader.go | 2 +- pkg/identity/generic/issuer.go | 2 +- pkg/identity/generic/issuer_test.go | 2 +- pkg/identity/generic/principal.go | 2 +- pkg/identity/generic/principal_test.go | 3 ++- 6 files changed, 7 insertions(+), 6 deletions(-) diff --git a/pkg/config/config.go b/pkg/config/config.go index d50d86673..0777d925d 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -272,7 +272,7 @@ func (fc *FulcioConfig) prepare() error { } // I would like to remove this completely, to be able to add or remove -// oidc providers only by the config.yaml file. +// oidc providers only by updating the config.yaml file. type IssuerType string const ( diff --git a/pkg/config/config_reader.go b/pkg/config/config_reader.go index 8dad9615f..2a0d55d8c 100644 --- a/pkg/config/config_reader.go +++ b/pkg/config/config_reader.go @@ -1,4 +1,4 @@ -// Copyright 2021 The Sigstore Authors. +// Copyright 2024 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. diff --git a/pkg/identity/generic/issuer.go b/pkg/identity/generic/issuer.go index 0b2d1e24e..5ed6a26e5 100644 --- a/pkg/identity/generic/issuer.go +++ b/pkg/identity/generic/issuer.go @@ -1,4 +1,4 @@ -// Copyright 2022 The Sigstore Authors. +// Copyright 2024 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. diff --git a/pkg/identity/generic/issuer_test.go b/pkg/identity/generic/issuer_test.go index 5b06e743a..dfaaf4268 100644 --- a/pkg/identity/generic/issuer_test.go +++ b/pkg/identity/generic/issuer_test.go @@ -1,4 +1,4 @@ -// Copyright 2023 The Sigstore Authors. +// Copyright 2024 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. diff --git a/pkg/identity/generic/principal.go b/pkg/identity/generic/principal.go index 9b77a1046..c11e57698 100644 --- a/pkg/identity/generic/principal.go +++ b/pkg/identity/generic/principal.go @@ -1,4 +1,4 @@ -// Copyright 2022 The Sigstore Authors. +// Copyright 2024 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. diff --git a/pkg/identity/generic/principal_test.go b/pkg/identity/generic/principal_test.go index 9ee4fd1f7..73ed3dd88 100644 --- a/pkg/identity/generic/principal_test.go +++ b/pkg/identity/generic/principal_test.go @@ -1,4 +1,4 @@ -// Copyright 2022 The Sigstore Authors. +// Copyright 2024 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. @@ -30,6 +30,7 @@ import ( "github.com/sigstore/fulcio/pkg/identity" ) +// TO BE IMPLEMENTED. Just keeped as a guide func TestWorkflowPrincipalFromIDToken(t *testing.T) { tests := map[string]struct { Claims map[string]interface{} From 73c988cd3d76bc5b6934428264d70cb7a0f7daac Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Tue, 4 Jun 2024 16:31:44 +0000 Subject: [PATCH 21/56] log Signed-off-by: Javan lacerda --- federation/main.go | 29 ++++++++++++++++++++++ pkg/identity/generic/principal.go | 41 +++++-------------------------- 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/federation/main.go b/federation/main.go index 7926f772a..e33aeb6a6 100644 --- a/federation/main.go +++ b/federation/main.go @@ -17,9 +17,11 @@ package main import ( "encoding/json" + "fmt" "os" "path/filepath" + "github.com/sigstore/fulcio/pkg/certificate" "github.com/sigstore/fulcio/pkg/config" "gopkg.in/yaml.v3" ) @@ -48,6 +50,33 @@ type federationConfig struct { SpiffeTrustDomain string } +type RootYaml struct { + Providers map[string]Provider +} + +type Provider struct { + Subject string + Extensions certificate.Extensions + Uris []string + Defaults map[string]string + OIDCIssuers []config.OIDCIssuer `yaml:"oidc-issuers,omitempty"` +} + +func readYaml() RootYaml { + var obj RootYaml + + yamlFile, err := os.ReadFile("../../config/config.yaml") + if err != nil { + fmt.Printf("yamlFile.Get err #%v ", err) + } + err = yaml.Unmarshal(yamlFile, &obj) + if err != nil { + fmt.Printf("Unmarshal: %v", err) + } + + return obj +} + func main() { matches := []string{} for _, rp := range rootPaths { diff --git a/pkg/identity/generic/principal.go b/pkg/identity/generic/principal.go index c11e57698..8f0b34632 100644 --- a/pkg/identity/generic/principal.go +++ b/pkg/identity/generic/principal.go @@ -20,7 +20,6 @@ import ( "crypto/x509" "fmt" "net/url" - "os" "strings" "text/template" @@ -28,37 +27,9 @@ import ( "github.com/sigstore/fulcio/pkg/certificate" "github.com/sigstore/fulcio/pkg/config" "github.com/sigstore/fulcio/pkg/identity" - "gopkg.in/yaml.v3" ) -// TODO: Delete after merged the config reader and get it directly from the github repo -type RootYaml struct { - Providers map[string]Provider -} - -type Provider struct { - Subject string - Extensions certificate.Extensions - Uris []string - Defaults map[string]string -} - -func readYaml() RootYaml { - var obj RootYaml - - yamlFile, err := os.ReadFile("../../config/config.yaml") - if err != nil { - fmt.Printf("yamlFile.Get err #%v ", err) - } - err = yaml.Unmarshal(yamlFile, &obj) - if err != nil { - fmt.Printf("Unmarshal: %v", err) - } - - return obj -} - -func WorkflowPrincipalFromIDToken(ctx context.Context, token *oidc.IDToken) (identity.Principal, error) { +func WorkflowPrincipalFromIDToken(ctx context.Context, token *oidc.IDToken, yaml RootYaml) (identity.Principal, error) { iss, ok := config.FromContext(ctx).GetIssuer(token.Issuer) if !ok { return nil, fmt.Errorf("configuration can not be loaded for issuer %v", token.Issuer) @@ -69,7 +40,6 @@ func WorkflowPrincipalFromIDToken(ctx context.Context, token *oidc.IDToken) (ide return nil, err } - yaml := readYaml() provider := yaml.Providers[string(iss.Type)] e := provider.Extensions defaults := provider.Defaults @@ -101,9 +71,10 @@ func WorkflowPrincipalFromIDToken(ctx context.Context, token *oidc.IDToken) (ide } return &Provider{ - Subject: token.Subject, - Extensions: finalExtensions, - Uris: finalUris, + Subject: token.Subject, + Extensions: finalExtensions, + Uris: finalUris, + OIDCIssuers: provider.OIDCIssuers, }, nil } @@ -123,7 +94,7 @@ func ApplyTemplate(path string, data map[string]string, defaultData map[string]s // It checks it is a path or a raw field by // checking exists template syntax into the string - if strings.Contains(path, "{{.") { + if strings.Contains(path, "{{") { var doc bytes.Buffer t := template.New("") p, err := t.Parse(path) From be6acf8dc3deb67017aafe706a29f34f58e4596e Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Thu, 6 Jun 2024 14:07:04 +0000 Subject: [PATCH 22/56] adding ci provider flag Signed-off-by: Javan lacerda --- federation/main.go | 29 -- pkg/challenges/challenges.go | 61 ++- pkg/config/config.go | 9 +- pkg/config/config_test.go | 31 +- pkg/identity/generic/issuer_test.go | 58 --- pkg/identity/generic/principal.go | 35 +- pkg/identity/generic/principal_test.go | 631 ------------------------- pkg/server/grpc_server_test.go | 3 +- 8 files changed, 99 insertions(+), 758 deletions(-) diff --git a/federation/main.go b/federation/main.go index e33aeb6a6..7926f772a 100644 --- a/federation/main.go +++ b/federation/main.go @@ -17,11 +17,9 @@ package main import ( "encoding/json" - "fmt" "os" "path/filepath" - "github.com/sigstore/fulcio/pkg/certificate" "github.com/sigstore/fulcio/pkg/config" "gopkg.in/yaml.v3" ) @@ -50,33 +48,6 @@ type federationConfig struct { SpiffeTrustDomain string } -type RootYaml struct { - Providers map[string]Provider -} - -type Provider struct { - Subject string - Extensions certificate.Extensions - Uris []string - Defaults map[string]string - OIDCIssuers []config.OIDCIssuer `yaml:"oidc-issuers,omitempty"` -} - -func readYaml() RootYaml { - var obj RootYaml - - yamlFile, err := os.ReadFile("../../config/config.yaml") - if err != nil { - fmt.Printf("yamlFile.Get err #%v ", err) - } - err = yaml.Unmarshal(yamlFile, &obj) - if err != nil { - fmt.Printf("Unmarshal: %v", err) - } - - return obj -} - func main() { matches := []string{} for _, rp := range rootPaths { diff --git a/pkg/challenges/challenges.go b/pkg/challenges/challenges.go index 9a724c1f2..e40a31a4a 100644 --- a/pkg/challenges/challenges.go +++ b/pkg/challenges/challenges.go @@ -21,10 +21,20 @@ import ( "crypto" "crypto/x509" "errors" + "fmt" "strings" + "github.com/sigstore/fulcio/pkg/config" "github.com/sigstore/fulcio/pkg/identity" + "github.com/sigstore/fulcio/pkg/identity/buildkite" + "github.com/sigstore/fulcio/pkg/identity/email" "github.com/sigstore/fulcio/pkg/identity/generic" + "github.com/sigstore/fulcio/pkg/identity/github" + "github.com/sigstore/fulcio/pkg/identity/gitlabcom" + "github.com/sigstore/fulcio/pkg/identity/kubernetes" + "github.com/sigstore/fulcio/pkg/identity/spiffe" + "github.com/sigstore/fulcio/pkg/identity/uri" + "github.com/sigstore/fulcio/pkg/identity/username" "github.com/coreos/go-oidc/v3/oidc" "github.com/sigstore/sigstore/pkg/cryptoutils" @@ -43,31 +53,36 @@ func CheckSignature(pub crypto.PublicKey, proof []byte, subject string) error { } func PrincipalFromIDToken(ctx context.Context, tok *oidc.IDToken) (identity.Principal, error) { + iss, ok := config.FromContext(ctx).GetIssuer(tok.Issuer) + if !ok { + return nil, fmt.Errorf("configuration can not be loaded for issuer %v", tok.Issuer) + } var principal identity.Principal var err error - - principal, err = generic.WorkflowPrincipalFromIDToken(ctx, tok) - - // switch iss.Type { - // case config.IssuerTypeBuildkiteJob: - // principal, err = buildkite.JobPrincipalFromIDToken(ctx, tok) - // case config.IssuerTypeGitLabPipeline: - // principal, err = gitlabcom.JobPrincipalFromIDToken(ctx, tok) - // case config.IssuerTypeEmail: - // principal, err = email.PrincipalFromIDToken(ctx, tok) - // case config.IssuerTypeSpiffe: - // principal, err = spiffe.PrincipalFromIDToken(ctx, tok) - // case config.IssuerTypeGithubWorkflow: - // principal, err = github.WorkflowPrincipalFromIDToken(ctx, tok) - // case config.IssuerTypeKubernetes: - // principal, err = kubernetes.PrincipalFromIDToken(ctx, tok) - // case config.IssuerTypeURI: - // principal, err = uri.PrincipalFromIDToken(ctx, tok) - // case config.IssuerTypeUsername: - // principal, err = username.PrincipalFromIDToken(ctx, tok) - // default: - // return nil, fmt.Errorf("unsupported issuer: %s", iss.Type) - // } + if iss.IsCiProvider { + principal, err = generic.WorkflowPrincipalFromIDToken(ctx, tok) + } else { + switch iss.Type { + case config.IssuerTypeBuildkiteJob: + principal, err = buildkite.JobPrincipalFromIDToken(ctx, tok) + case config.IssuerTypeGitLabPipeline: + principal, err = gitlabcom.JobPrincipalFromIDToken(ctx, tok) + case config.IssuerTypeEmail: + principal, err = email.PrincipalFromIDToken(ctx, tok) + case config.IssuerTypeSpiffe: + principal, err = spiffe.PrincipalFromIDToken(ctx, tok) + case config.IssuerTypeGithubWorkflow: + principal, err = github.WorkflowPrincipalFromIDToken(ctx, tok) + case config.IssuerTypeKubernetes: + principal, err = kubernetes.PrincipalFromIDToken(ctx, tok) + case config.IssuerTypeURI: + principal, err = uri.PrincipalFromIDToken(ctx, tok) + case config.IssuerTypeUsername: + principal, err = username.PrincipalFromIDToken(ctx, tok) + default: + return nil, fmt.Errorf("unsupported issuer: %s", iss.Type) + } + } if err != nil { return nil, err } diff --git a/pkg/config/config.go b/pkg/config/config.go index 0777d925d..8c4bdf2f3 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -126,6 +126,7 @@ func (fc *FulcioConfig) GetIssuer(issuerURL string) (OIDCIssuer, bool) { Type: iss.Type, IssuerClaim: iss.IssuerClaim, SubjectDomain: iss.SubjectDomain, + IsCiProvider: iss.IsCiProvider, }, true } } @@ -205,7 +206,7 @@ func (fc *FulcioConfig) ToIssuers() []*fulciogrpc.OIDCIssuer { Issuer: &fulciogrpc.OIDCIssuer_IssuerUrl{IssuerUrl: cfgIss.IssuerURL}, Audience: cfgIss.ClientID, SpiffeTrustDomain: cfgIss.SPIFFETrustDomain, - ChallengeClaim: issuerToChallengeClaim(cfgIss.Type, cfgIss.ChallengeClaim), + ChallengeClaim: issuerToChallengeClaim(cfgIss, cfgIss.ChallengeClaim), } issuers = append(issuers, issuer) } @@ -215,7 +216,7 @@ func (fc *FulcioConfig) ToIssuers() []*fulciogrpc.OIDCIssuer { Issuer: &fulciogrpc.OIDCIssuer_WildcardIssuerUrl{WildcardIssuerUrl: metaIss}, Audience: cfgIss.ClientID, SpiffeTrustDomain: cfgIss.SPIFFETrustDomain, - ChallengeClaim: issuerToChallengeClaim(cfgIss.Type, cfgIss.ChallengeClaim), + ChallengeClaim: issuerToChallengeClaim(cfgIss, cfgIss.ChallengeClaim), } issuers = append(issuers, issuer) } @@ -376,7 +377,7 @@ func validateConfig(conf *FulcioConfig) error { } } - if issuerToChallengeClaim(issuer.Type, issuer.ChallengeClaim) == "" { + if issuerToChallengeClaim(issuer, issuer.ChallengeClaim) == "" { return errors.New("issuer missing challenge claim") } } @@ -388,7 +389,7 @@ func validateConfig(conf *FulcioConfig) error { return errors.New("SPIFFE meta issuers not supported") } - if issuerToChallengeClaim(metaIssuer.Type, metaIssuer.ChallengeClaim) == "" { + if issuerToChallengeClaim(metaIssuer, metaIssuer.ChallengeClaim) == "" { return errors.New("issuer missing challenge claim") } } diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index 4c0967660..11e4defcb 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -474,28 +474,37 @@ func Test_validateAllowedDomain(t *testing.T) { } func Test_issuerToChallengeClaim(t *testing.T) { - if claim := issuerToChallengeClaim(IssuerTypeEmail, ""); claim != "email" { + issuer := OIDCIssuer{} + issuer.Type = IssuerTypeEmail + if claim := issuerToChallengeClaim(issuer, ""); claim != "email" { t.Fatalf("expected email subject claim for email issuer, got %s", claim) } - if claim := issuerToChallengeClaim(IssuerTypeSpiffe, ""); claim != "sub" { + issuer.Type = IssuerTypeSpiffe + if claim := issuerToChallengeClaim(issuer, ""); claim != "sub" { t.Fatalf("expected sub subject claim for SPIFFE issuer, got %s", claim) } - if claim := issuerToChallengeClaim(IssuerTypeUsername, ""); claim != "sub" { + issuer.Type = IssuerTypeUsername + if claim := issuerToChallengeClaim(issuer, ""); claim != "sub" { t.Fatalf("expected sub subject claim for username issuer, got %s", claim) } - if claim := issuerToChallengeClaim(IssuerTypeURI, ""); claim != "sub" { + issuer.Type = IssuerTypeURI + if claim := issuerToChallengeClaim(issuer, ""); claim != "sub" { t.Fatalf("expected sub subject claim for URI issuer, got %s", claim) } - if claim := issuerToChallengeClaim(IssuerTypeBuildkiteJob, ""); claim != "sub" { + issuer.Type = IssuerTypeBuildkiteJob + if claim := issuerToChallengeClaim(issuer, ""); claim != "sub" { t.Fatalf("expected sub subject claim for Buildkite issuer, got %s", claim) } - if claim := issuerToChallengeClaim(IssuerTypeGithubWorkflow, ""); claim != "sub" { + issuer.Type = IssuerTypeGithubWorkflow + if claim := issuerToChallengeClaim(issuer, ""); claim != "sub" { t.Fatalf("expected sub subject claim for GitHub issuer, got %s", claim) } - if claim := issuerToChallengeClaim(IssuerTypeGitLabPipeline, ""); claim != "sub" { + issuer.Type = IssuerTypeGitLabPipeline + if claim := issuerToChallengeClaim(issuer, ""); claim != "sub" { t.Fatalf("expected sub subject claim for GitLab issuer, got %s", claim) } - if claim := issuerToChallengeClaim(IssuerTypeCodefreshWorkflow, ""); claim != "sub" { + issuer.Type = IssuerTypeCodefreshWorkflow + if claim := issuerToChallengeClaim(issuer, ""); claim != "sub" { t.Fatalf("expected sub subject claim for Codefresh issuer, got %s", claim) } if claim := issuerToChallengeClaim(IssuerTypeChainguard, ""); claim != "sub" { @@ -504,12 +513,14 @@ func Test_issuerToChallengeClaim(t *testing.T) { if claim := issuerToChallengeClaim(IssuerTypeKubernetes, ""); claim != "sub" { t.Fatalf("expected sub subject claim for K8S issuer, got %s", claim) } + issuer.Type = "invalid" // unexpected issuer has empty claim and no claim was provided - if claim := issuerToChallengeClaim("invalid", ""); claim != "" { + if claim := issuerToChallengeClaim(issuer, ""); claim != "" { t.Fatalf("expected no claim for invalid issuer, got %s", claim) } // custom issuer provides a claim - if claim := issuerToChallengeClaim("custom", "email"); claim != "email" { + issuer.Type = "custom" + if claim := issuerToChallengeClaim(issuer, "email"); claim != "email" { t.Fatalf("expected email subject claim for custom issuer, got %s", claim) } } diff --git a/pkg/identity/generic/issuer_test.go b/pkg/identity/generic/issuer_test.go index dfaaf4268..2a9e3099d 100644 --- a/pkg/identity/generic/issuer_test.go +++ b/pkg/identity/generic/issuer_test.go @@ -15,67 +15,9 @@ package generic import ( - "context" - "encoding/json" "testing" - - "github.com/coreos/go-oidc/v3/oidc" - "github.com/sigstore/fulcio/pkg/config" - "github.com/sigstore/fulcio/pkg/identity" ) func TestIssuer(t *testing.T) { - ctx := context.Background() - url := "test-issuer-url" - issuer := Issuer(url) - - // test the Match function - t.Run("match", func(t *testing.T) { - if matches := issuer.Match(ctx, url); !matches { - t.Fatal("expected url to match but it doesn't") - } - if matches := issuer.Match(ctx, "some-other-url"); matches { - t.Fatal("expected match to fail but it didn't") - } - }) - - t.Run("authenticate", func(t *testing.T) { - token := &oidc.IDToken{ - Issuer: "https://iss.example.com", - Subject: "subject", - } - claims, err := json.Marshal(map[string]interface{}{ - "aud": "sigstore", - "iss": "https://iss.example.com", - "sub": "doesntmatter", - "email": "alice@example.com", - "email_verified": true, - }) - if err != nil { - t.Fatal(err) - } - withClaims(token, claims) - - ctx := config.With(context.Background(), &config.FulcioConfig{ - OIDCIssuers: map[string]config.OIDCIssuer{ - "https://iss.example.com": { - IssuerURL: "https://iss.example.com", - Type: config.IssuerTypeEmail, - ClientID: "sigstore", - }, - }, - }) - - identity.Authorize = func(_ context.Context, _ string, _ ...config.InsecureOIDCConfigOption) (*oidc.IDToken, error) { - return token, nil - } - principal, err := issuer.Authenticate(ctx, "token") - if err != nil { - t.Fatal(err) - } - if principal.Name(ctx) != "alice@example.com" { - t.Fatalf("got unexpected name %s", principal.Name(ctx)) - } - }) } diff --git a/pkg/identity/generic/principal.go b/pkg/identity/generic/principal.go index 8f0b34632..60182280c 100644 --- a/pkg/identity/generic/principal.go +++ b/pkg/identity/generic/principal.go @@ -20,6 +20,7 @@ import ( "crypto/x509" "fmt" "net/url" + "os" "strings" "text/template" @@ -27,9 +28,37 @@ import ( "github.com/sigstore/fulcio/pkg/certificate" "github.com/sigstore/fulcio/pkg/config" "github.com/sigstore/fulcio/pkg/identity" + "gopkg.in/yaml.v3" ) -func WorkflowPrincipalFromIDToken(ctx context.Context, token *oidc.IDToken, yaml RootYaml) (identity.Principal, error) { +type RootYaml struct { + Providers map[string]Provider +} + +type Provider struct { + Subject string + Extensions certificate.Extensions + Uris []string + Defaults map[string]string + OIDCIssuers []config.OIDCIssuer `yaml:"oidc-issuers,omitempty"` +} + +func readYaml() RootYaml { + var obj RootYaml + + yamlFile, err := os.ReadFile("../../config/config.yaml") + if err != nil { + fmt.Printf("yamlFile.Get err #%v ", err) + } + err = yaml.Unmarshal(yamlFile, &obj) + if err != nil { + fmt.Printf("Unmarshal: %v", err) + } + + return obj +} + +func WorkflowPrincipalFromIDToken(ctx context.Context, token *oidc.IDToken) (identity.Principal, error) { iss, ok := config.FromContext(ctx).GetIssuer(token.Issuer) if !ok { return nil, fmt.Errorf("configuration can not be loaded for issuer %v", token.Issuer) @@ -40,7 +69,9 @@ func WorkflowPrincipalFromIDToken(ctx context.Context, token *oidc.IDToken, yaml return nil, err } - provider := yaml.Providers[string(iss.Type)] + configYaml := readYaml() + + provider := configYaml.Providers[string(iss.Type)] e := provider.Extensions defaults := provider.Defaults finalExtensions := certificate.Extensions{ diff --git a/pkg/identity/generic/principal_test.go b/pkg/identity/generic/principal_test.go index 73ed3dd88..25e33a5b5 100644 --- a/pkg/identity/generic/principal_test.go +++ b/pkg/identity/generic/principal_test.go @@ -15,649 +15,18 @@ package generic import ( - "bytes" - "context" - "crypto/x509" - "encoding/asn1" - "encoding/json" - "errors" - "fmt" - "reflect" "testing" - "unsafe" - - "github.com/coreos/go-oidc/v3/oidc" - "github.com/sigstore/fulcio/pkg/identity" ) // TO BE IMPLEMENTED. Just keeped as a guide func TestWorkflowPrincipalFromIDToken(t *testing.T) { - tests := map[string]struct { - Claims map[string]interface{} - ExpectPrincipal Provider - WantErr bool - ErrContains string - }{ - `Valid token authenticates with correct claims`: { - Claims: map[string]interface{}{ - "aud": "sigstore", - "event_name": "push", - "exp": 0, - "iss": "https://token.actions.githubusercontent.com", - "job_workflow_ref": "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main", - "job_workflow_sha": "example-sha", - "ref": "refs/heads/main", - "repository": "sigstore/fulcio", - "repository_id": "12345", - "repository_owner": "username", - "repository_owner_id": "345", - "repository_visibility": "public", - "run_attempt": "1", - "run_id": "42", - "runner_environment": "cloud-hosted", - "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "sub": "repo:sigstore/fulcio:ref:refs/heads/main", - "workflow": "foo", - "workflow_ref": "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", - "workflow_sha": "example-sha-other", - }, - ExpectPrincipal: Provider{}, - WantErr: false, - }, - `Token missing job_workflow_ref claim should be rejected`: { - Claims: map[string]interface{}{ - "aud": "sigstore", - "event_name": "push", - "exp": 0, - "iss": "https://token.actions.githubusercontent.com", - "job_workflow_sha": "example-sha", - "ref": "refs/heads/main", - "repository": "sigstore/fulcio", - "repository_id": "12345", - "repository_owner": "username", - "repository_owner_id": "345", - "repository_visibility": "public", - "run_attempt": "1", - "run_id": "42", - "runner_environment": "cloud-hosted", - "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "sub": "repo:sigstore/fulcio:ref:refs/heads/main", - "workflow": "foo", - "workflow_ref": "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", - "workflow_sha": "example-sha-other", - }, - WantErr: true, - ErrContains: "job_workflow_ref", - }, - `Token missing sha should be rejected`: { - Claims: map[string]interface{}{ - "aud": "sigstore", - "event_name": "push", - "exp": 0, - "iss": "https://token.actions.githubusercontent.com", - "job_workflow_ref": "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main", - "job_workflow_sha": "example-sha", - "ref": "refs/heads/main", - "repository": "sigstore/fulcio", - "repository_id": "12345", - "repository_owner": "username", - "repository_owner_id": "345", - "repository_visibility": "public", - "run_attempt": "1", - "run_id": "42", - "runner_environment": "cloud-hosted", - "sub": "repo:sigstore/fulcio:ref:refs/heads/main", - "workflow": "foo", - "workflow_ref": "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", - "workflow_sha": "example-sha-other", - }, - WantErr: true, - ErrContains: "sha", - }, - `Token missing event_name claim should be rejected`: { - Claims: map[string]interface{}{ - "aud": "sigstore", - "exp": 0, - "iss": "https://token.actions.githubusercontent.com", - "job_workflow_ref": "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main", - "job_workflow_sha": "example-sha", - "ref": "refs/heads/main", - "repository": "sigstore/fulcio", - "repository_id": "12345", - "repository_owner": "username", - "repository_owner_id": "345", - "repository_visibility": "public", - "run_attempt": "1", - "run_id": "42", - "runner_environment": "cloud-hosted", - "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "sub": "repo:sigstore/fulcio:ref:refs/heads/main", - "workflow": "foo", - "workflow_ref": "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", - "workflow_sha": "example-sha-other", - }, - WantErr: true, - ErrContains: "event_name", - }, - `Token missing repository claim should be rejected`: { - Claims: map[string]interface{}{ - "aud": "sigstore", - "event_name": "push", - "exp": 0, - "iss": "https://token.actions.githubusercontent.com", - "job_workflow_ref": "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main", - "job_workflow_sha": "example-sha", - "ref": "refs/heads/main", - "repository_id": "12345", - "repository_owner": "username", - "repository_owner_id": "345", - "repository_visibility": "public", - "run_attempt": "1", - "run_id": "42", - "runner_environment": "cloud-hosted", - "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "sub": "repo:sigstore/fulcio:ref:refs/heads/main", - "workflow": "foo", - "workflow_ref": "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", - "workflow_sha": "example-sha-other", - }, - WantErr: true, - ErrContains: "repository", - }, - `Token missing workflow claim should be rejected`: { - Claims: map[string]interface{}{ - "aud": "sigstore", - "event_name": "push", - "exp": 0, - "iss": "https://token.actions.githubusercontent.com", - "job_workflow_ref": "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main", - "job_workflow_sha": "example-sha", - "ref": "refs/heads/main", - "repository": "sigstore/fulcio", - "repository_id": "12345", - "repository_owner": "username", - "repository_owner_id": "345", - "repository_visibility": "public", - "run_attempt": "1", - "run_id": "42", - "runner_environment": "cloud-hosted", - "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "sub": "repo:sigstore/fulcio:ref:refs/heads/main", - "workflow_ref": "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", - "workflow_sha": "example-sha-other", - }, - WantErr: true, - ErrContains: "workflow", - }, - `Token missing ref claim should be rejected`: { - Claims: map[string]interface{}{ - "aud": "sigstore", - "event_name": "push", - "exp": 0, - "iss": "https://token.actions.githubusercontent.com", - "job_workflow_ref": "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main", - "job_workflow_sha": "example-sha", - "repository": "sigstore/fulcio", - "repository_id": "12345", - "repository_owner": "username", - "repository_owner_id": "345", - "repository_visibility": "public", - "run_attempt": "1", - "run_id": "42", - "runner_environment": "cloud-hosted", - "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "sub": "repo:sigstore/fulcio:ref:refs/heads/main", - "workflow": "foo", - "workflow_ref": "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", - "workflow_sha": "example-sha-other", - }, - WantErr: true, - ErrContains: "ref", - }, - `Token missing job_workflow_sha claim should be rejected`: { - Claims: map[string]interface{}{ - "aud": "sigstore", - "event_name": "push", - "exp": 0, - "iss": "https://token.actions.githubusercontent.com", - "job_workflow_ref": "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main", - "ref": "refs/heads/main", - "repository": "sigstore/fulcio", - "repository_id": "12345", - "repository_owner": "username", - "repository_owner_id": "345", - "repository_visibility": "public", - "run_attempt": "1", - "run_id": "42", - "runner_environment": "cloud-hosted", - "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "sub": "repo:sigstore/fulcio:ref:refs/heads/main", - "workflow": "foo", - "workflow_ref": "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", - "workflow_sha": "example-sha-other", - }, - WantErr: true, - ErrContains: "job_workflow_sha", - }, - `Token missing runner_environment claim should be rejected`: { - Claims: map[string]interface{}{ - "aud": "sigstore", - "event_name": "push", - "exp": 0, - "iss": "https://token.actions.githubusercontent.com", - "job_workflow_ref": "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main", - "job_workflow_sha": "example-sha", - "ref": "refs/heads/main", - "repository": "sigstore/fulcio", - "repository_id": "12345", - "repository_owner": "username", - "repository_owner_id": "345", - "repository_visibility": "public", - "run_attempt": "1", - "run_id": "42", - "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "sub": "repo:sigstore/fulcio:ref:refs/heads/main", - "workflow": "foo", - "workflow_ref": "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", - "workflow_sha": "example-sha-other", - }, - WantErr: true, - ErrContains: "runner_environment", - }, - `Token missing repository_id claim should be rejected`: { - Claims: map[string]interface{}{ - "aud": "sigstore", - "event_name": "push", - "exp": 0, - "iss": "https://token.actions.githubusercontent.com", - "job_workflow_ref": "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main", - "job_workflow_sha": "example-sha", - "ref": "refs/heads/main", - "repository": "sigstore/fulcio", - "repository_owner": "username", - "repository_owner_id": "345", - "repository_visibility": "public", - "run_attempt": "1", - "run_id": "42", - "runner_environment": "cloud-hosted", - "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "sub": "repo:sigstore/fulcio:ref:refs/heads/main", - "workflow": "foo", - "workflow_ref": "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", - "workflow_sha": "example-sha-other", - }, - WantErr: true, - ErrContains: "repository_id", - }, - `Token missing repository_owner claim should be rejected`: { - Claims: map[string]interface{}{ - "aud": "sigstore", - "event_name": "push", - "exp": 0, - "iss": "https://token.actions.githubusercontent.com", - "job_workflow_ref": "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main", - "job_workflow_sha": "example-sha", - "ref": "refs/heads/main", - "repository": "sigstore/fulcio", - "repository_id": "12345", - "repository_owner_id": "345", - "repository_visibility": "public", - "run_attempt": "1", - "run_id": "42", - "runner_environment": "cloud-hosted", - "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "sub": "repo:sigstore/fulcio:ref:refs/heads/main", - "workflow": "foo", - "workflow_ref": "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", - "workflow_sha": "example-sha-other", - }, - WantErr: true, - ErrContains: "repository_owner", - }, - `Token missing repository_owner_id claim should be rejected`: { - Claims: map[string]interface{}{ - "aud": "sigstore", - "event_name": "push", - "exp": 0, - "iss": "https://token.actions.githubusercontent.com", - "job_workflow_ref": "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main", - "job_workflow_sha": "example-sha", - "ref": "refs/heads/main", - "repository": "sigstore/fulcio", - "repository_id": "12345", - "repository_owner": "username", - "repository_visibility": "public", - "run_attempt": "1", - "run_id": "42", - "runner_environment": "cloud-hosted", - "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "sub": "repo:sigstore/fulcio:ref:refs/heads/main", - "workflow": "foo", - "workflow_ref": "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", - "workflow_sha": "example-sha-other", - }, - WantErr: true, - ErrContains: "repository_owner_id", - }, - `Token missing workflow_ref claim should be rejected`: { - Claims: map[string]interface{}{ - "aud": "sigstore", - "event_name": "push", - "exp": 0, - "iss": "https://token.actions.githubusercontent.com", - "job_workflow_ref": "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main", - "job_workflow_sha": "example-sha", - "ref": "refs/heads/main", - "repository": "sigstore/fulcio", - "repository_id": "12345", - "repository_owner": "username", - "repository_owner_id": "345", - "repository_visibility": "public", - "run_attempt": "1", - "run_id": "42", - "runner_environment": "cloud-hosted", - "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "sub": "repo:sigstore/fulcio:ref:refs/heads/main", - "workflow": "foo", - "workflow_sha": "example-sha-other", - }, - WantErr: true, - ErrContains: "workflow_ref", - }, - `Token missing workflow_sha claim should be rejected`: { - Claims: map[string]interface{}{ - "aud": "sigstore", - "event_name": "push", - "exp": 0, - "iss": "https://token.actions.githubusercontent.com", - "job_workflow_ref": "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main", - "job_workflow_sha": "example-sha", - "ref": "refs/heads/main", - "repository": "sigstore/fulcio", - "repository_id": "12345", - "repository_owner": "username", - "repository_owner_id": "345", - "repository_visibility": "public", - "run_attempt": "1", - "run_id": "42", - "runner_environment": "cloud-hosted", - "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "sub": "repo:sigstore/fulcio:ref:refs/heads/main", - "workflow": "foo", - "workflow_ref": "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", - }, - WantErr: true, - ErrContains: "workflow_sha", - }, - `Token missing run_id claim should be rejected`: { - Claims: map[string]interface{}{ - "aud": "sigstore", - "event_name": "push", - "exp": 0, - "iss": "https://token.actions.githubusercontent.com", - "job_workflow_ref": "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main", - "job_workflow_sha": "example-sha", - "ref": "refs/heads/main", - "repository": "sigstore/fulcio", - "repository_id": "12345", - "repository_owner": "username", - "repository_owner_id": "345", - "repository_visibility": "public", - "run_attempt": "1", - "runner_environment": "cloud-hosted", - "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "sub": "repo:sigstore/fulcio:ref:refs/heads/main", - "workflow": "foo", - "workflow_ref": "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", - "workflow_sha": "example-sha-other", - }, - WantErr: true, - ErrContains: "run_id", - }, - `Token missing run_attempt claim should be rejected`: { - Claims: map[string]interface{}{ - "aud": "sigstore", - "event_name": "push", - "exp": 0, - "iss": "https://token.actions.githubusercontent.com", - "job_workflow_ref": "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main", - "job_workflow_sha": "example-sha", - "ref": "refs/heads/main", - "repository": "sigstore/fulcio", - "repository_id": "12345", - "repository_owner": "username", - "repository_owner_id": "345", - "repository_visibility": "public", - "run_id": "42", - "runner_environment": "cloud-hosted", - "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "sub": "repo:sigstore/fulcio:ref:refs/heads/main", - "workflow": "foo", - "workflow_ref": "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", - "workflow_sha": "example-sha-other", - }, - WantErr: true, - ErrContains: "run_attempt", - }, - `Token missing repository_visibility claim should be rejected`: { - Claims: map[string]interface{}{ - "aud": "sigstore", - "event_name": "push", - "exp": 0, - "iss": "https://token.actions.githubusercontent.com", - "job_workflow_ref": "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main", - "job_workflow_sha": "example-sha", - "ref": "refs/heads/main", - "repository": "sigstore/fulcio", - "repository_id": "12345", - "repository_owner": "username", - "repository_owner_id": "345", - "run_id": "42", - "runner_environment": "cloud-hosted", - "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "sub": "repo:sigstore/fulcio:ref:refs/heads/main", - "workflow": "foo", - "workflow_ref": "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", - "workflow_sha": "example-sha-other", - }, - WantErr: true, - ErrContains: "repository_visibility", - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - token := &oidc.IDToken{ - Issuer: test.Claims["iss"].(string), - Subject: test.Claims["sub"].(string), - } - claims, err := json.Marshal(test.Claims) - if err != nil { - t.Fatal(err) - } - withClaims(token, claims) - - // untyped, err := WorkflowPrincipalFromIDToken(context.TODO(), token) - // if err != nil { - // if !test.WantErr { - // t.Fatal("didn't expect error", err) - // } - // if !strings.Contains(err.Error(), test.ErrContains) { - // t.Fatalf("expected error %s to contain %s", err, test.ErrContains) - // } - // return - // } - // if err == nil && test.WantErr { - // t.Fatal("expected error but got none") - // } - // principal, ok := untyped.(*Provider) - // if !ok { - // t.Errorf("Got wrong principal type %v", untyped) - // } - // if *principal != test.ExpectPrincipal { - // t.Errorf("got %v principal and expected %v", *principal, test.ExpectPrincipal) - // } - }) - } -} - -// reflect hack because "claims" field is unexported by oidc IDToken -// https://github.com/coreos/go-oidc/pull/329 -func withClaims(token *oidc.IDToken, data []byte) { - val := reflect.Indirect(reflect.ValueOf(token)) - member := val.FieldByName("claims") - pointer := unsafe.Pointer(member.UnsafeAddr()) - realPointer := (*[]byte)(pointer) - *realPointer = data } func TestName(t *testing.T) { - tests := map[string]struct { - Claims map[string]interface{} - ExpectName string - }{ - `Valid token authenticates with correct claims`: { - Claims: map[string]interface{}{ - "aud": "sigstore", - "event_name": "push", - "exp": 0, - "iss": "https://token.actions.githubusercontent.com", - "job_workflow_ref": "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main", - "job_workflow_sha": "example-sha", - "ref": "refs/heads/main", - "repository": "sigstore/fulcio", - "repository_id": "12345", - "repository_owner": "username", - "repository_owner_id": "345", - "repository_visibility": "public", - "run_attempt": "1", - "run_id": "42", - "runner_environment": "cloud-hosted", - "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "sub": "repo:sigstore/fulcio:ref:refs/heads/main", - "workflow": "foo", - "workflow_ref": "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", - "workflow_sha": "example-sha-other", - }, - ExpectName: "repo:sigstore/fulcio:ref:refs/heads/main", - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - token := &oidc.IDToken{ - Issuer: test.Claims["iss"].(string), - Subject: test.Claims["sub"].(string), - } - claims, err := json.Marshal(test.Claims) - if err != nil { - t.Fatal(err) - } - withClaims(token, claims) - - principal, err := WorkflowPrincipalFromIDToken(context.TODO(), token) - if err != nil { - t.Fatal(err) - } - - gotName := principal.Name(context.TODO()) - if gotName != test.ExpectName { - t.Error("name should match sub claim") - } - }) - } } func TestEmbed(t *testing.T) { - tests := map[string]struct { - Principal identity.Principal - WantErr bool - WantFacts map[string]func(x509.Certificate) error - }{ - `Github workflow challenge should have all Github workflow extensions and issuer set`: { - Principal: &Provider{}, - WantErr: false, - WantFacts: map[string]func(x509.Certificate) error{ - `Certifificate should have correct issuer`: factDeprecatedExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 1}, "https://token.actions.githubusercontent.com"), - `Certificate has correct trigger extension`: factDeprecatedExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 2}, "trigger"), - `Certificate has correct SHA extension`: factDeprecatedExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 3}, "sha"), - `Certificate has correct workflow extension`: factDeprecatedExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 4}, "workflowname"), - `Certificate has correct repository extension`: factDeprecatedExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 5}, "repository"), - `Certificate has correct ref extension`: factDeprecatedExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 6}, "ref"), - `Certificate has correct issuer (v2) extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 8}, "https://token.actions.githubusercontent.com"), - `Certificate has correct builder signer URI extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 9}, "https://github.com/jobWorkflowRef"), - `Certificate has correct builder signer digest extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 10}, "jobWorkflowSha"), - `Certificate has correct runner environment extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 11}, "runnerEnv"), - `Certificate has correct source repo URI extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 12}, "https://github.com/repository"), - `Certificate has correct source repo digest extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 13}, "sha"), - `Certificate has correct source repo ref extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 14}, "ref"), - `Certificate has correct source repo ID extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 15}, "repoID"), - `Certificate has correct source repo owner URI extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 16}, "https://github.com/repoOwner"), - `Certificate has correct source repo owner ID extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 17}, "repoOwnerID"), - `Certificate has correct build config URI extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 18}, "https://github.com/workflowRef"), - `Certificate has correct build config digest extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 19}, "workflowSHA"), - `Certificate has correct build trigger extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 20}, "trigger"), - `Certificate has correct run invocation ID extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 21}, "https://github.com/repository/actions/runs/runID/attempts/runAttempt"), - `Certificate has correct source repository visibility extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 22}, "public"), - }, - }, - `Github workflow value with bad URL fails`: { - Principal: &Provider{}, - WantErr: true, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - var cert x509.Certificate - err := test.Principal.Embed(context.TODO(), &cert) - if err != nil { - if !test.WantErr { - t.Error(err) - } - return - } else if test.WantErr { - t.Error("expected error") - } - for factName, fact := range test.WantFacts { - t.Run(factName, func(t *testing.T) { - if err := fact(cert); err != nil { - t.Error(err) - } - }) - } - }) - } -} - -func factExtensionIs(oid asn1.ObjectIdentifier, value string) func(x509.Certificate) error { - return func(cert x509.Certificate) error { - for _, ext := range cert.ExtraExtensions { - if ext.Id.Equal(oid) { - var strVal string - _, _ = asn1.Unmarshal(ext.Value, &strVal) - if value != strVal { - return fmt.Errorf("expected oid %v to be %s, but got %s", oid, value, strVal) - } - return nil - } - } - return errors.New("extension not set") - } -} -func factDeprecatedExtensionIs(oid asn1.ObjectIdentifier, value string) func(x509.Certificate) error { - return func(cert x509.Certificate) error { - for _, ext := range cert.ExtraExtensions { - if ext.Id.Equal(oid) { - if !bytes.Equal(ext.Value, []byte(value)) { - return fmt.Errorf("expected oid %v to be %s, but got %s", oid, value, ext.Value) - } - return nil - } - } - return errors.New("extension not set") - } } diff --git a/pkg/server/grpc_server_test.go b/pkg/server/grpc_server_test.go index 999083160..6a008e8d1 100644 --- a/pkg/server/grpc_server_test.go +++ b/pkg/server/grpc_server_test.go @@ -243,7 +243,8 @@ func TestGetConfiguration(t *testing.T) { %q: { "IssuerURL": %q, "ClientID": "sigstore", - "Type": "gitlab-pipeline" + "Type": "gitlab-pipeline", + "IsCiProvider": true }, %q: { "IssuerURL": %q, From ee93df8a45b37ec927127db578c01f748c5c4775 Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Thu, 6 Jun 2024 15:18:08 +0000 Subject: [PATCH 23/56] removing drafting logic for generic principal, to be done in another pr Signed-off-by: Javan lacerda --- pkg/identity/generic/issuer_test.go | 1 + pkg/identity/generic/principal.go | 111 +--------------------------- 2 files changed, 5 insertions(+), 107 deletions(-) diff --git a/pkg/identity/generic/issuer_test.go b/pkg/identity/generic/issuer_test.go index 2a9e3099d..e728b30e4 100644 --- a/pkg/identity/generic/issuer_test.go +++ b/pkg/identity/generic/issuer_test.go @@ -18,6 +18,7 @@ import ( "testing" ) +// TO BE IMPLEMENTED. Just keeped as a guide func TestIssuer(t *testing.T) { } diff --git a/pkg/identity/generic/principal.go b/pkg/identity/generic/principal.go index 60182280c..b12596264 100644 --- a/pkg/identity/generic/principal.go +++ b/pkg/identity/generic/principal.go @@ -15,26 +15,16 @@ package generic import ( - "bytes" "context" "crypto/x509" - "fmt" "net/url" - "os" - "strings" - "text/template" "github.com/coreos/go-oidc/v3/oidc" "github.com/sigstore/fulcio/pkg/certificate" "github.com/sigstore/fulcio/pkg/config" "github.com/sigstore/fulcio/pkg/identity" - "gopkg.in/yaml.v3" ) -type RootYaml struct { - Providers map[string]Provider -} - type Provider struct { Subject string Extensions certificate.Extensions @@ -43,107 +33,14 @@ type Provider struct { OIDCIssuers []config.OIDCIssuer `yaml:"oidc-issuers,omitempty"` } -func readYaml() RootYaml { - var obj RootYaml - - yamlFile, err := os.ReadFile("../../config/config.yaml") - if err != nil { - fmt.Printf("yamlFile.Get err #%v ", err) - } - err = yaml.Unmarshal(yamlFile, &obj) - if err != nil { - fmt.Printf("Unmarshal: %v", err) - } - - return obj -} - +// TO BE IMPLEMENTED. Just keeped as a guide func WorkflowPrincipalFromIDToken(ctx context.Context, token *oidc.IDToken) (identity.Principal, error) { - iss, ok := config.FromContext(ctx).GetIssuer(token.Issuer) - if !ok { - return nil, fmt.Errorf("configuration can not be loaded for issuer %v", token.Issuer) - } - - var claims map[string]string - if err := token.Claims(&claims); err != nil { - return nil, err - } - - configYaml := readYaml() - - provider := configYaml.Providers[string(iss.Type)] - e := provider.Extensions - defaults := provider.Defaults - finalExtensions := certificate.Extensions{ - Issuer: ApplyTemplate(e.Issuer, claims, defaults), - GithubWorkflowTrigger: ApplyTemplate(e.GithubWorkflowTrigger, claims, defaults), - GithubWorkflowSHA: ApplyTemplate(e.GithubWorkflowSHA, claims, defaults), - GithubWorkflowName: ApplyTemplate(e.GithubWorkflowName, claims, defaults), - GithubWorkflowRepository: ApplyTemplate(e.GithubWorkflowRepository, claims, defaults), - GithubWorkflowRef: ApplyTemplate(e.GithubWorkflowRef, claims, defaults), - BuildSignerURI: ApplyTemplate(e.BuildSignerURI, claims, defaults), - BuildConfigDigest: ApplyTemplate(e.BuildConfigDigest, claims, defaults), - RunnerEnvironment: ApplyTemplate(e.RunnerEnvironment, claims, defaults), - SourceRepositoryURI: ApplyTemplate(e.SourceRepositoryURI, claims, defaults), - SourceRepositoryDigest: ApplyTemplate(e.SourceRepositoryDigest, claims, defaults), - SourceRepositoryRef: ApplyTemplate(e.SourceRepositoryRef, claims, defaults), - SourceRepositoryIdentifier: ApplyTemplate(e.SourceRepositoryIdentifier, claims, defaults), - SourceRepositoryOwnerURI: ApplyTemplate(e.SourceRepositoryOwnerURI, claims, defaults), - SourceRepositoryOwnerIdentifier: ApplyTemplate(e.SourceRepositoryOwnerIdentifier, claims, defaults), - BuildConfigURI: ApplyTemplate(e.BuildConfigURI, claims, defaults), - BuildSignerDigest: ApplyTemplate(e.BuildSignerDigest, claims, defaults), - BuildTrigger: ApplyTemplate(e.BuildTrigger, claims, defaults), - RunInvocationURI: ApplyTemplate(e.RunInvocationURI, claims, defaults), - SourceRepositoryVisibilityAtSigning: ApplyTemplate(e.SourceRepositoryVisibilityAtSigning, claims, defaults), - } - finalUris := make([]string, len(provider.Uris)-1) - for _, val := range provider.Uris { - finalUris = append(finalUris, ApplyTemplate(val, claims, defaults)) - } - - return &Provider{ - Subject: token.Subject, - Extensions: finalExtensions, - Uris: finalUris, - OIDCIssuers: provider.OIDCIssuers, - }, nil -} - -func ApplyTemplate(path string, data map[string]string, defaultData map[string]string) string { - - // Here we merge the data from was claimed by the id token with the - // default data provided by the yaml file. - // The order here matter because we want to override the default data - // with the claimed data. - mergedData := make(map[string]string) - for k, v := range defaultData { - mergedData[k] = v - } - for k, v := range data { - mergedData[k] = v - } - - // It checks it is a path or a raw field by - // checking exists template syntax into the string - if strings.Contains(path, "{{") { - var doc bytes.Buffer - t := template.New("") - p, err := t.Parse(path) - if err != nil { - panic(err) - } - err = p.Execute(&doc, mergedData) - if err != nil { - panic(err) - } - return doc.String() - } else { - return mergedData[path] - } + return nil, nil } +// TO BE IMPLEMENTED. Just keeped as a guide func (p Provider) Name(_ context.Context) string { - return p.Subject + return "" } func (p Provider) Embed(_ context.Context, cert *x509.Certificate) error { From f7cd58aabed0423ae440a6f50ce51053739d74e8 Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Thu, 6 Jun 2024 15:25:39 +0000 Subject: [PATCH 24/56] fixes Signed-off-by: Javan lacerda --- pkg/config/config.go | 2 - pkg/config/config.yaml | 50 ------------------ pkg/config/config_reader.go | 72 -------------------------- pkg/identity/generic/issuer_test.go | 2 +- pkg/identity/generic/principal.go | 4 +- pkg/identity/generic/principal_test.go | 6 +-- 6 files changed, 6 insertions(+), 130 deletions(-) delete mode 100644 pkg/config/config.yaml delete mode 100644 pkg/config/config_reader.go diff --git a/pkg/config/config.go b/pkg/config/config.go index 8c4bdf2f3..f349e1369 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -272,8 +272,6 @@ func (fc *FulcioConfig) prepare() error { return nil } -// I would like to remove this completely, to be able to add or remove -// oidc providers only by updating the config.yaml file. type IssuerType string const ( diff --git a/pkg/config/config.yaml b/pkg/config/config.yaml deleted file mode 100644 index 35176a1ef..000000000 --- a/pkg/config/config.yaml +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright 2024 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. - -# TODO: Fill it properly for the current providers -providers: - github: - extensions: - build-signer-digest: job_workflow_sha - source-repository-digest: sha - source-repository-ref: ref - source-repository-identifier: repository_id - run-invocation-uri: "{{.url}}/{{.repository}}/actions/runs/{{.run_id}}/" - uris: - - "{{.url}}/{{.job_workflow_ref}}" - defaults: - url: https://github.com - gitlab: - extensions: - build-signer-digest: ci_config_sha - source-repository-digest: sha - source-repository-ref: ref - source-repository-identifier: project_id - run-invocation-uri: "{{.url}}/{{.project_path}}/-/jobs/{{.job_id}}" - uris: - - ci_config_ref_uri - defaults: - url: https://gitlab.com - codefresh: - extensions: - build-signer-digest: build/{{.workflow_id}} - runner-environment: runner_environment - source-repository-uri: scm_repo_url - source-repository-ref: scm_ref - build-config-uri: api/pipelines/{{.pipeline_id}} - run-invocation-uri: build/{{.workflow_id}} - uris: - - "{{.platform_url}}/{{.account_name}}/{{.pipeline_name}}:{{.account_id}}/{{.pipeline_id}}" - defaults: - platform_url: https://g.codefresh.io diff --git a/pkg/config/config_reader.go b/pkg/config/config_reader.go deleted file mode 100644 index 2a0d55d8c..000000000 --- a/pkg/config/config_reader.go +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2024 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 config - -import ( - "fmt" - "os" - - "gopkg.in/yaml.v3" -) - -type Extensions struct { - Issuer string // OID 1.3.6.1.4.1.57264.1.8 and 1.3.6.1.4.1.57264.1.1 (Deprecated) - Subject string - GithubWorkflowTrigger string `yaml:"github-workflow-trigger"` // OID 1.3.6.1.4.1.57264.1.2 - GithubWorkflowSHA string `yaml:"github-workflow-sha"` // OID 1.3.6.1.4.1.57264.1.3 - GithubWorkflowName string `yaml:"github-workflow-name"` // OID 1.3.6.1.4.1.57264.1.4 - GithubWorkflowRepository string `yaml:"github-workflow-repository"` // OID 1.3.6.1.4.1.57264.1.5 - GithubWorkflowRef string `yaml:"github-workflow-ref"` // 1.3.6.1.4.1.57264.1.6 - BuildSignerURI string `yaml:"build-signer-uri"` // 1.3.6.1.4.1.57264.1.9 - BuildSignerDigest string `yaml:"build-signer-digest"` // 1.3.6.1.4.1.57264.1.10 - RunnerEnvironment string `yaml:"runner-environment"` // 1.3.6.1.4.1.57264.1.11 - SourceRepositoryURI string `yaml:"source-repository-uri"` // 1.3.6.1.4.1.57264.1.12 - SourceRepositoryDigest string `yaml:"source-repository-digest"` // 1.3.6.1.4.1.57264.1.13 - SourceRepositoryRef string `yaml:"source-repository-ref"` // 1.3.6.1.4.1.57264.1.14 - SourceRepositoryIdentifier string `yaml:"source-repository-identifier"` // 1.3.6.1.4.1.57264.1.15 - SourceRepositoryOwnerURI string `yaml:"source-repository-owner-uri"` // 1.3.6.1.4.1.57264.1.16 - SourceRepositoryOwnerIdentifier string `yaml:"source-repository-owner-identifier"` // 1.3.6.1.4.1.57264.1.17 - BuildConfigURI string `yaml:"build-config-uri"` // 1.3.6.1.4.1.57264.1.18 - BuildConfigDigest string `yaml:"build-config-digest"` // 1.3.6.1.4.1.57264.1.19 - BuildTrigger string `yaml:"build-trigger"` // 1.3.6.1.4.1.57264.1.20 - RunInvocationURI string `yaml:"run-invocation-uri"` // 1.3.6.1.4.1.57264.1.21 - SourceRepositoryVisibilityAtSigning string `yaml:"source-repository-visibility-at-signing"` // 1.3.6.1.4.1.57264.1.22 -} - -type RootYaml struct { - Providers map[string]Provider -} - -type Provider struct { - Extensions Extensions - Uris []string - Defaults map[string]string -} - -func readYaml() RootYaml { - var obj RootYaml - - yamlFile, err := os.ReadFile("config.yaml") - if err != nil { - fmt.Printf("yamlFile.Get err #%v ", err) - } - err = yaml.Unmarshal(yamlFile, &obj) - if err != nil { - fmt.Printf("Unmarshal: %v", err) - } - - return obj -} diff --git a/pkg/identity/generic/issuer_test.go b/pkg/identity/generic/issuer_test.go index e728b30e4..77326f965 100644 --- a/pkg/identity/generic/issuer_test.go +++ b/pkg/identity/generic/issuer_test.go @@ -19,6 +19,6 @@ import ( ) // TO BE IMPLEMENTED. Just keeped as a guide -func TestIssuer(t *testing.T) { +func TestIssuer(_ *testing.T) { } diff --git a/pkg/identity/generic/principal.go b/pkg/identity/generic/principal.go index b12596264..f3c9fbeae 100644 --- a/pkg/identity/generic/principal.go +++ b/pkg/identity/generic/principal.go @@ -34,12 +34,12 @@ type Provider struct { } // TO BE IMPLEMENTED. Just keeped as a guide -func WorkflowPrincipalFromIDToken(ctx context.Context, token *oidc.IDToken) (identity.Principal, error) { +func WorkflowPrincipalFromIDToken(_ context.Context, _ *oidc.IDToken) (identity.Principal, error) { return nil, nil } // TO BE IMPLEMENTED. Just keeped as a guide -func (p Provider) Name(_ context.Context) string { +func (Provider) Name(_ context.Context) string { return "" } diff --git a/pkg/identity/generic/principal_test.go b/pkg/identity/generic/principal_test.go index 25e33a5b5..96540fe90 100644 --- a/pkg/identity/generic/principal_test.go +++ b/pkg/identity/generic/principal_test.go @@ -19,14 +19,14 @@ import ( ) // TO BE IMPLEMENTED. Just keeped as a guide -func TestWorkflowPrincipalFromIDToken(t *testing.T) { +func TestWorkflowPrincipalFromIDToken(_ *testing.T) { } -func TestName(t *testing.T) { +func TestName(_ *testing.T) { } -func TestEmbed(t *testing.T) { +func TestEmbed(_ *testing.T) { } From ba9e42eabddabcddd8f9a2dac748cf5e9d39f43c Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Thu, 6 Jun 2024 15:37:16 +0000 Subject: [PATCH 25/56] generate config Signed-off-by: Javan lacerda --- config/fulcio-config.yaml | 51 ++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/config/fulcio-config.yaml b/config/fulcio-config.yaml index 0f7a0aded..876ae2459 100644 --- a/config/fulcio-config.yaml +++ b/config/fulcio-config.yaml @@ -20,43 +20,51 @@ data: "https://accounts.google.com": { "IssuerURL": "https://accounts.google.com", "ClientID": "sigstore", - "Type": "email" + "Type": "email", + "IsCiProvider": false }, "https://agent.buildkite.com": { "IssuerURL": "https://agent.buildkite.com", "ClientID": "sigstore", - "Type": "buildkite-job" + "Type": "buildkite-job", + "IsCiProvider": false }, "https://allow.pub": { "IssuerURL": "https://allow.pub", "ClientID": "sigstore", "Type": "spiffe", - "SPIFFETrustDomain": "allow.pub" + "SPIFFETrustDomain": "allow.pub", + "IsCiProvider": false }, "https://auth-staging.eclipse.org/realms/sigstore": { "IssuerURL": "https://auth-staging.eclipse.org/realms/sigstore", "ClientID": "sigstore", - "Type": "email" + "Type": "email", + "IsCiProvider": false }, "https://auth.eclipse.org/auth/realms/sigstore": { "IssuerURL": "https://auth.eclipse.org/auth/realms/sigstore", "ClientID": "sigstore", - "Type": "email" + "Type": "email", + "IsCiProvider": false }, "https://dev.gitlab.org": { "IssuerURL": "https://dev.gitlab.org", "ClientID": "sigstore", - "Type": "gitlab-pipeline" + "Type": "gitlab-pipeline", + "IsCiProvider": false }, "https://gitlab.archlinux.org": { "IssuerURL": "https://gitlab.archlinux.org", "ClientID": "sigstore", - "Type": "gitlab-pipeline" + "Type": "gitlab-pipeline", + "IsCiProvider": false }, "https://gitlab.com": { "IssuerURL": "https://gitlab.com", "ClientID": "sigstore", - "Type": "gitlab-pipeline" + "Type": "gitlab-pipeline", + "IsCiProvider": false }, "https://issuer.enforce.dev": { "IssuerURL": "https://issuer.enforce.dev", @@ -67,44 +75,53 @@ data: "IssuerURL": "https://oauth2.sigstore.dev/auth", "ClientID": "sigstore", "Type": "email", - "IssuerClaim": "$.federated_claims.connector_id" + "IssuerClaim": "$.federated_claims.connector_id", + "IsCiProvider": false }, "https://oidc.codefresh.io": { "IssuerURL": "https://oidc.codefresh.io", "ClientID": "sigstore", - "Type": "codefresh-workflow" + "Type": "codefresh-workflow", + "IsCiProvider": false }, "https://ops.gitlab.net": { "IssuerURL": "https://ops.gitlab.net", "ClientID": "sigstore", - "Type": "gitlab-pipeline" + "Type": "gitlab-pipeline", + "IsCiProvider": false }, "https://token.actions.githubusercontent.com": { "IssuerURL": "https://token.actions.githubusercontent.com", "ClientID": "sigstore", - "Type": "github-workflow" + "Type": "github-workflow", + "IsCiProvider": false } }, "MetaIssuers": { "https://*.oic.prod-aks.azure.com/*": { "ClientID": "sigstore", - "Type": "kubernetes" + "Type": "kubernetes", + "IsCiProvider": false }, "https://container.googleapis.com/v1/projects/*/locations/*/clusters/*": { "ClientID": "sigstore", - "Type": "kubernetes" + "Type": "kubernetes", + "IsCiProvider": false }, "https://oidc.eks.*.amazonaws.com/id/*": { "ClientID": "sigstore", - "Type": "kubernetes" + "Type": "kubernetes", + "IsCiProvider": false }, "https://oidc.prod-aks.azure.com/*": { "ClientID": "sigstore", - "Type": "kubernetes" + "Type": "kubernetes", + "IsCiProvider": false }, "https://token.actions.githubusercontent.com/*": { "ClientID": "sigstore", - "Type": "github-workflow" + "Type": "github-workflow", + "IsCiProvider": false } } } From e0e6c5390aa50b9134042d5e5b54725ceb5febda Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Tue, 11 Jun 2024 14:34:33 +0000 Subject: [PATCH 26/56] set ci provider as a new type instead of a flag Signed-off-by: Javan lacerda --- config/fulcio-config.yaml | 51 ++++++++++++------------------------ pkg/challenges/challenges.go | 43 +++++++++++++++--------------- pkg/config/config.go | 2 +- pkg/server/issuer_pool.go | 3 +++ 4 files changed, 42 insertions(+), 57 deletions(-) diff --git a/config/fulcio-config.yaml b/config/fulcio-config.yaml index 876ae2459..0f7a0aded 100644 --- a/config/fulcio-config.yaml +++ b/config/fulcio-config.yaml @@ -20,51 +20,43 @@ data: "https://accounts.google.com": { "IssuerURL": "https://accounts.google.com", "ClientID": "sigstore", - "Type": "email", - "IsCiProvider": false + "Type": "email" }, "https://agent.buildkite.com": { "IssuerURL": "https://agent.buildkite.com", "ClientID": "sigstore", - "Type": "buildkite-job", - "IsCiProvider": false + "Type": "buildkite-job" }, "https://allow.pub": { "IssuerURL": "https://allow.pub", "ClientID": "sigstore", "Type": "spiffe", - "SPIFFETrustDomain": "allow.pub", - "IsCiProvider": false + "SPIFFETrustDomain": "allow.pub" }, "https://auth-staging.eclipse.org/realms/sigstore": { "IssuerURL": "https://auth-staging.eclipse.org/realms/sigstore", "ClientID": "sigstore", - "Type": "email", - "IsCiProvider": false + "Type": "email" }, "https://auth.eclipse.org/auth/realms/sigstore": { "IssuerURL": "https://auth.eclipse.org/auth/realms/sigstore", "ClientID": "sigstore", - "Type": "email", - "IsCiProvider": false + "Type": "email" }, "https://dev.gitlab.org": { "IssuerURL": "https://dev.gitlab.org", "ClientID": "sigstore", - "Type": "gitlab-pipeline", - "IsCiProvider": false + "Type": "gitlab-pipeline" }, "https://gitlab.archlinux.org": { "IssuerURL": "https://gitlab.archlinux.org", "ClientID": "sigstore", - "Type": "gitlab-pipeline", - "IsCiProvider": false + "Type": "gitlab-pipeline" }, "https://gitlab.com": { "IssuerURL": "https://gitlab.com", "ClientID": "sigstore", - "Type": "gitlab-pipeline", - "IsCiProvider": false + "Type": "gitlab-pipeline" }, "https://issuer.enforce.dev": { "IssuerURL": "https://issuer.enforce.dev", @@ -75,53 +67,44 @@ data: "IssuerURL": "https://oauth2.sigstore.dev/auth", "ClientID": "sigstore", "Type": "email", - "IssuerClaim": "$.federated_claims.connector_id", - "IsCiProvider": false + "IssuerClaim": "$.federated_claims.connector_id" }, "https://oidc.codefresh.io": { "IssuerURL": "https://oidc.codefresh.io", "ClientID": "sigstore", - "Type": "codefresh-workflow", - "IsCiProvider": false + "Type": "codefresh-workflow" }, "https://ops.gitlab.net": { "IssuerURL": "https://ops.gitlab.net", "ClientID": "sigstore", - "Type": "gitlab-pipeline", - "IsCiProvider": false + "Type": "gitlab-pipeline" }, "https://token.actions.githubusercontent.com": { "IssuerURL": "https://token.actions.githubusercontent.com", "ClientID": "sigstore", - "Type": "github-workflow", - "IsCiProvider": false + "Type": "github-workflow" } }, "MetaIssuers": { "https://*.oic.prod-aks.azure.com/*": { "ClientID": "sigstore", - "Type": "kubernetes", - "IsCiProvider": false + "Type": "kubernetes" }, "https://container.googleapis.com/v1/projects/*/locations/*/clusters/*": { "ClientID": "sigstore", - "Type": "kubernetes", - "IsCiProvider": false + "Type": "kubernetes" }, "https://oidc.eks.*.amazonaws.com/id/*": { "ClientID": "sigstore", - "Type": "kubernetes", - "IsCiProvider": false + "Type": "kubernetes" }, "https://oidc.prod-aks.azure.com/*": { "ClientID": "sigstore", - "Type": "kubernetes", - "IsCiProvider": false + "Type": "kubernetes" }, "https://token.actions.githubusercontent.com/*": { "ClientID": "sigstore", - "Type": "github-workflow", - "IsCiProvider": false + "Type": "github-workflow" } } } diff --git a/pkg/challenges/challenges.go b/pkg/challenges/challenges.go index e40a31a4a..81bc27df4 100644 --- a/pkg/challenges/challenges.go +++ b/pkg/challenges/challenges.go @@ -59,29 +59,28 @@ func PrincipalFromIDToken(ctx context.Context, tok *oidc.IDToken) (identity.Prin } var principal identity.Principal var err error - if iss.IsCiProvider { + switch iss.Type { + case config.IssuerTypeCiProvider: principal, err = generic.WorkflowPrincipalFromIDToken(ctx, tok) - } else { - switch iss.Type { - case config.IssuerTypeBuildkiteJob: - principal, err = buildkite.JobPrincipalFromIDToken(ctx, tok) - case config.IssuerTypeGitLabPipeline: - principal, err = gitlabcom.JobPrincipalFromIDToken(ctx, tok) - case config.IssuerTypeEmail: - principal, err = email.PrincipalFromIDToken(ctx, tok) - case config.IssuerTypeSpiffe: - principal, err = spiffe.PrincipalFromIDToken(ctx, tok) - case config.IssuerTypeGithubWorkflow: - principal, err = github.WorkflowPrincipalFromIDToken(ctx, tok) - case config.IssuerTypeKubernetes: - principal, err = kubernetes.PrincipalFromIDToken(ctx, tok) - case config.IssuerTypeURI: - principal, err = uri.PrincipalFromIDToken(ctx, tok) - case config.IssuerTypeUsername: - principal, err = username.PrincipalFromIDToken(ctx, tok) - default: - return nil, fmt.Errorf("unsupported issuer: %s", iss.Type) - } + case config.IssuerTypeBuildkiteJob: + principal, err = buildkite.JobPrincipalFromIDToken(ctx, tok) + case config.IssuerTypeGitLabPipeline: + principal, err = gitlabcom.JobPrincipalFromIDToken(ctx, tok) + case config.IssuerTypeEmail: + principal, err = email.PrincipalFromIDToken(ctx, tok) + case config.IssuerTypeSpiffe: + principal, err = spiffe.PrincipalFromIDToken(ctx, tok) + case config.IssuerTypeGithubWorkflow: + principal, err = github.WorkflowPrincipalFromIDToken(ctx, tok) + case config.IssuerTypeKubernetes: + principal, err = kubernetes.PrincipalFromIDToken(ctx, tok) + case config.IssuerTypeURI: + principal, err = uri.PrincipalFromIDToken(ctx, tok) + case config.IssuerTypeUsername: + principal, err = username.PrincipalFromIDToken(ctx, tok) + default: + return nil, fmt.Errorf("unsupported issuer: %s", iss.Type) + } if err != nil { return nil, err diff --git a/pkg/config/config.go b/pkg/config/config.go index f349e1369..e9ffa443e 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -126,7 +126,6 @@ func (fc *FulcioConfig) GetIssuer(issuerURL string) (OIDCIssuer, bool) { Type: iss.Type, IssuerClaim: iss.IssuerClaim, SubjectDomain: iss.SubjectDomain, - IsCiProvider: iss.IsCiProvider, }, true } } @@ -285,6 +284,7 @@ const ( IssuerTypeSpiffe = "spiffe" IssuerTypeURI = "uri" IssuerTypeUsername = "username" + IssuerTypeCiProvider = "ci-provider" ) func parseConfig(b []byte) (cfg *FulcioConfig, err error) { diff --git a/pkg/server/issuer_pool.go b/pkg/server/issuer_pool.go index 18349f262..4f5f7303d 100644 --- a/pkg/server/issuer_pool.go +++ b/pkg/server/issuer_pool.go @@ -21,6 +21,7 @@ import ( "github.com/sigstore/fulcio/pkg/identity/chainguard" "github.com/sigstore/fulcio/pkg/identity/codefresh" "github.com/sigstore/fulcio/pkg/identity/email" + "github.com/sigstore/fulcio/pkg/identity/generic" "github.com/sigstore/fulcio/pkg/identity/github" "github.com/sigstore/fulcio/pkg/identity/gitlabcom" "github.com/sigstore/fulcio/pkg/identity/kubernetes" @@ -53,6 +54,8 @@ func getIssuer(meta string, i config.OIDCIssuer) identity.Issuer { issuerURL = meta } switch i.Type { + case config.IssuerTypeCiProvider: + return generic.Issuer(issuerURL) case config.IssuerTypeEmail: return email.Issuer(issuerURL) case config.IssuerTypeGithubWorkflow: From 4930187c55d169a0fa6b303c9175fa66000dd267 Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Tue, 11 Jun 2024 16:27:29 +0000 Subject: [PATCH 27/56] rollback isserToChallengeC Signed-off-by: Javan lacerda --- pkg/challenges/challenges.go | 1 - pkg/config/config.go | 8 +++---- pkg/config/config_test.go | 31 +++++++++----------------- pkg/identity/generic/issuer_test.go | 2 +- pkg/identity/generic/principal.go | 4 ++-- pkg/identity/generic/principal_test.go | 2 +- 6 files changed, 18 insertions(+), 30 deletions(-) diff --git a/pkg/challenges/challenges.go b/pkg/challenges/challenges.go index 81bc27df4..667beaf31 100644 --- a/pkg/challenges/challenges.go +++ b/pkg/challenges/challenges.go @@ -80,7 +80,6 @@ func PrincipalFromIDToken(ctx context.Context, tok *oidc.IDToken) (identity.Prin principal, err = username.PrincipalFromIDToken(ctx, tok) default: return nil, fmt.Errorf("unsupported issuer: %s", iss.Type) - } if err != nil { return nil, err diff --git a/pkg/config/config.go b/pkg/config/config.go index e9ffa443e..2d46e64ed 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -205,7 +205,7 @@ func (fc *FulcioConfig) ToIssuers() []*fulciogrpc.OIDCIssuer { Issuer: &fulciogrpc.OIDCIssuer_IssuerUrl{IssuerUrl: cfgIss.IssuerURL}, Audience: cfgIss.ClientID, SpiffeTrustDomain: cfgIss.SPIFFETrustDomain, - ChallengeClaim: issuerToChallengeClaim(cfgIss, cfgIss.ChallengeClaim), + ChallengeClaim: issuerToChallengeClaim(cfgIss.Type, cfgIss.ChallengeClaim), } issuers = append(issuers, issuer) } @@ -215,7 +215,7 @@ func (fc *FulcioConfig) ToIssuers() []*fulciogrpc.OIDCIssuer { Issuer: &fulciogrpc.OIDCIssuer_WildcardIssuerUrl{WildcardIssuerUrl: metaIss}, Audience: cfgIss.ClientID, SpiffeTrustDomain: cfgIss.SPIFFETrustDomain, - ChallengeClaim: issuerToChallengeClaim(cfgIss, cfgIss.ChallengeClaim), + ChallengeClaim: issuerToChallengeClaim(cfgIss.Type, cfgIss.ChallengeClaim), } issuers = append(issuers, issuer) } @@ -375,7 +375,7 @@ func validateConfig(conf *FulcioConfig) error { } } - if issuerToChallengeClaim(issuer, issuer.ChallengeClaim) == "" { + if issuerToChallengeClaim(issuer.Type, issuer.ChallengeClaim) == "" { return errors.New("issuer missing challenge claim") } } @@ -387,7 +387,7 @@ func validateConfig(conf *FulcioConfig) error { return errors.New("SPIFFE meta issuers not supported") } - if issuerToChallengeClaim(metaIssuer, metaIssuer.ChallengeClaim) == "" { + if issuerToChallengeClaim(metaIssuer.Type, metaIssuer.ChallengeClaim) == "" { return errors.New("issuer missing challenge claim") } } diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index 11e4defcb..4c0967660 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -474,37 +474,28 @@ func Test_validateAllowedDomain(t *testing.T) { } func Test_issuerToChallengeClaim(t *testing.T) { - issuer := OIDCIssuer{} - issuer.Type = IssuerTypeEmail - if claim := issuerToChallengeClaim(issuer, ""); claim != "email" { + if claim := issuerToChallengeClaim(IssuerTypeEmail, ""); claim != "email" { t.Fatalf("expected email subject claim for email issuer, got %s", claim) } - issuer.Type = IssuerTypeSpiffe - if claim := issuerToChallengeClaim(issuer, ""); claim != "sub" { + if claim := issuerToChallengeClaim(IssuerTypeSpiffe, ""); claim != "sub" { t.Fatalf("expected sub subject claim for SPIFFE issuer, got %s", claim) } - issuer.Type = IssuerTypeUsername - if claim := issuerToChallengeClaim(issuer, ""); claim != "sub" { + if claim := issuerToChallengeClaim(IssuerTypeUsername, ""); claim != "sub" { t.Fatalf("expected sub subject claim for username issuer, got %s", claim) } - issuer.Type = IssuerTypeURI - if claim := issuerToChallengeClaim(issuer, ""); claim != "sub" { + if claim := issuerToChallengeClaim(IssuerTypeURI, ""); claim != "sub" { t.Fatalf("expected sub subject claim for URI issuer, got %s", claim) } - issuer.Type = IssuerTypeBuildkiteJob - if claim := issuerToChallengeClaim(issuer, ""); claim != "sub" { + if claim := issuerToChallengeClaim(IssuerTypeBuildkiteJob, ""); claim != "sub" { t.Fatalf("expected sub subject claim for Buildkite issuer, got %s", claim) } - issuer.Type = IssuerTypeGithubWorkflow - if claim := issuerToChallengeClaim(issuer, ""); claim != "sub" { + if claim := issuerToChallengeClaim(IssuerTypeGithubWorkflow, ""); claim != "sub" { t.Fatalf("expected sub subject claim for GitHub issuer, got %s", claim) } - issuer.Type = IssuerTypeGitLabPipeline - if claim := issuerToChallengeClaim(issuer, ""); claim != "sub" { + if claim := issuerToChallengeClaim(IssuerTypeGitLabPipeline, ""); claim != "sub" { t.Fatalf("expected sub subject claim for GitLab issuer, got %s", claim) } - issuer.Type = IssuerTypeCodefreshWorkflow - if claim := issuerToChallengeClaim(issuer, ""); claim != "sub" { + if claim := issuerToChallengeClaim(IssuerTypeCodefreshWorkflow, ""); claim != "sub" { t.Fatalf("expected sub subject claim for Codefresh issuer, got %s", claim) } if claim := issuerToChallengeClaim(IssuerTypeChainguard, ""); claim != "sub" { @@ -513,14 +504,12 @@ func Test_issuerToChallengeClaim(t *testing.T) { if claim := issuerToChallengeClaim(IssuerTypeKubernetes, ""); claim != "sub" { t.Fatalf("expected sub subject claim for K8S issuer, got %s", claim) } - issuer.Type = "invalid" // unexpected issuer has empty claim and no claim was provided - if claim := issuerToChallengeClaim(issuer, ""); claim != "" { + if claim := issuerToChallengeClaim("invalid", ""); claim != "" { t.Fatalf("expected no claim for invalid issuer, got %s", claim) } // custom issuer provides a claim - issuer.Type = "custom" - if claim := issuerToChallengeClaim(issuer, "email"); claim != "email" { + if claim := issuerToChallengeClaim("custom", "email"); claim != "email" { t.Fatalf("expected email subject claim for custom issuer, got %s", claim) } } diff --git a/pkg/identity/generic/issuer_test.go b/pkg/identity/generic/issuer_test.go index 77326f965..060796bb0 100644 --- a/pkg/identity/generic/issuer_test.go +++ b/pkg/identity/generic/issuer_test.go @@ -18,7 +18,7 @@ import ( "testing" ) -// TO BE IMPLEMENTED. Just keeped as a guide +// TO BE IMPLEMENTED. Just kept as a guide func TestIssuer(_ *testing.T) { } diff --git a/pkg/identity/generic/principal.go b/pkg/identity/generic/principal.go index f3c9fbeae..a7eea734a 100644 --- a/pkg/identity/generic/principal.go +++ b/pkg/identity/generic/principal.go @@ -33,12 +33,12 @@ type Provider struct { OIDCIssuers []config.OIDCIssuer `yaml:"oidc-issuers,omitempty"` } -// TO BE IMPLEMENTED. Just keeped as a guide +// TO BE IMPLEMENTED. Just kept as a guide func WorkflowPrincipalFromIDToken(_ context.Context, _ *oidc.IDToken) (identity.Principal, error) { return nil, nil } -// TO BE IMPLEMENTED. Just keeped as a guide +// TO BE IMPLEMENTED. Just kept as a guide func (Provider) Name(_ context.Context) string { return "" } diff --git a/pkg/identity/generic/principal_test.go b/pkg/identity/generic/principal_test.go index 96540fe90..0c9d1adac 100644 --- a/pkg/identity/generic/principal_test.go +++ b/pkg/identity/generic/principal_test.go @@ -18,7 +18,7 @@ import ( "testing" ) -// TO BE IMPLEMENTED. Just keeped as a guide +// TO BE IMPLEMENTED. Just kept as a guide func TestWorkflowPrincipalFromIDToken(_ *testing.T) { } From cafe1db6420e604666d98821c161a276648003d9 Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Tue, 11 Jun 2024 16:39:55 +0000 Subject: [PATCH 28/56] change module name to ci_provider Signed-off-by: Javan lacerda --- pkg/challenges/challenges.go | 2 +- pkg/identity/{generic => ci_provider}/issuer.go | 8 ++++---- pkg/identity/{generic => ci_provider}/issuer_test.go | 2 +- pkg/identity/{generic => ci_provider}/principal.go | 2 +- pkg/identity/{generic => ci_provider}/principal_test.go | 2 +- pkg/server/issuer_pool.go | 4 ++-- 6 files changed, 10 insertions(+), 10 deletions(-) rename pkg/identity/{generic => ci_provider}/issuer.go (79%) rename pkg/identity/{generic => ci_provider}/issuer_test.go (97%) rename pkg/identity/{generic => ci_provider}/principal.go (98%) rename pkg/identity/{generic => ci_provider}/principal_test.go (97%) diff --git a/pkg/challenges/challenges.go b/pkg/challenges/challenges.go index 667beaf31..09817c2b2 100644 --- a/pkg/challenges/challenges.go +++ b/pkg/challenges/challenges.go @@ -27,8 +27,8 @@ import ( "github.com/sigstore/fulcio/pkg/config" "github.com/sigstore/fulcio/pkg/identity" "github.com/sigstore/fulcio/pkg/identity/buildkite" + generic "github.com/sigstore/fulcio/pkg/identity/ci_provider" "github.com/sigstore/fulcio/pkg/identity/email" - "github.com/sigstore/fulcio/pkg/identity/generic" "github.com/sigstore/fulcio/pkg/identity/github" "github.com/sigstore/fulcio/pkg/identity/gitlabcom" "github.com/sigstore/fulcio/pkg/identity/kubernetes" diff --git a/pkg/identity/generic/issuer.go b/pkg/identity/ci_provider/issuer.go similarity index 79% rename from pkg/identity/generic/issuer.go rename to pkg/identity/ci_provider/issuer.go index 5ed6a26e5..23fbdaa65 100644 --- a/pkg/identity/generic/issuer.go +++ b/pkg/identity/ci_provider/issuer.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package generic +package ci_provider import ( "context" @@ -22,15 +22,15 @@ import ( "github.com/sigstore/fulcio/pkg/identity/base" ) -type genericIssuer struct { +type ciProviderIssuer struct { identity.Issuer } func Issuer(issuerURL string) identity.Issuer { - return &genericIssuer{base.Issuer(issuerURL)} + return &ciProviderIssuer{base.Issuer(issuerURL)} } -func (e *genericIssuer) Authenticate(ctx context.Context, token string, opts ...config.InsecureOIDCConfigOption) (identity.Principal, error) { +func (e *ciProviderIssuer) Authenticate(ctx context.Context, token string, opts ...config.InsecureOIDCConfigOption) (identity.Principal, error) { idtoken, err := identity.Authorize(ctx, token, opts...) if err != nil { return nil, err diff --git a/pkg/identity/generic/issuer_test.go b/pkg/identity/ci_provider/issuer_test.go similarity index 97% rename from pkg/identity/generic/issuer_test.go rename to pkg/identity/ci_provider/issuer_test.go index 060796bb0..59773c3f8 100644 --- a/pkg/identity/generic/issuer_test.go +++ b/pkg/identity/ci_provider/issuer_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package generic +package ci_provider import ( "testing" diff --git a/pkg/identity/generic/principal.go b/pkg/identity/ci_provider/principal.go similarity index 98% rename from pkg/identity/generic/principal.go rename to pkg/identity/ci_provider/principal.go index a7eea734a..cdbfd3945 100644 --- a/pkg/identity/generic/principal.go +++ b/pkg/identity/ci_provider/principal.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package generic +package ci_provider import ( "context" diff --git a/pkg/identity/generic/principal_test.go b/pkg/identity/ci_provider/principal_test.go similarity index 97% rename from pkg/identity/generic/principal_test.go rename to pkg/identity/ci_provider/principal_test.go index 0c9d1adac..eda7811ab 100644 --- a/pkg/identity/generic/principal_test.go +++ b/pkg/identity/ci_provider/principal_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package generic +package ci_provider import ( "testing" diff --git a/pkg/server/issuer_pool.go b/pkg/server/issuer_pool.go index 4f5f7303d..c669fa865 100644 --- a/pkg/server/issuer_pool.go +++ b/pkg/server/issuer_pool.go @@ -19,9 +19,9 @@ import ( "github.com/sigstore/fulcio/pkg/identity" "github.com/sigstore/fulcio/pkg/identity/buildkite" "github.com/sigstore/fulcio/pkg/identity/chainguard" + "github.com/sigstore/fulcio/pkg/identity/ci_provider" "github.com/sigstore/fulcio/pkg/identity/codefresh" "github.com/sigstore/fulcio/pkg/identity/email" - "github.com/sigstore/fulcio/pkg/identity/generic" "github.com/sigstore/fulcio/pkg/identity/github" "github.com/sigstore/fulcio/pkg/identity/gitlabcom" "github.com/sigstore/fulcio/pkg/identity/kubernetes" @@ -55,7 +55,7 @@ func getIssuer(meta string, i config.OIDCIssuer) identity.Issuer { } switch i.Type { case config.IssuerTypeCiProvider: - return generic.Issuer(issuerURL) + return ci_provider.Issuer(issuerURL) case config.IssuerTypeEmail: return email.Issuer(issuerURL) case config.IssuerTypeGithubWorkflow: From c3651531609f960a020770389fdb034bae912bdd Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Tue, 11 Jun 2024 16:41:32 +0000 Subject: [PATCH 29/56] remove IsCiProvider from test Signed-off-by: Javan lacerda --- pkg/challenges/challenges.go | 4 ++-- pkg/server/grpc_server_test.go | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/pkg/challenges/challenges.go b/pkg/challenges/challenges.go index 09817c2b2..4c5b31781 100644 --- a/pkg/challenges/challenges.go +++ b/pkg/challenges/challenges.go @@ -27,7 +27,7 @@ import ( "github.com/sigstore/fulcio/pkg/config" "github.com/sigstore/fulcio/pkg/identity" "github.com/sigstore/fulcio/pkg/identity/buildkite" - generic "github.com/sigstore/fulcio/pkg/identity/ci_provider" + "github.com/sigstore/fulcio/pkg/identity/ci_provider" "github.com/sigstore/fulcio/pkg/identity/email" "github.com/sigstore/fulcio/pkg/identity/github" "github.com/sigstore/fulcio/pkg/identity/gitlabcom" @@ -61,7 +61,7 @@ func PrincipalFromIDToken(ctx context.Context, tok *oidc.IDToken) (identity.Prin var err error switch iss.Type { case config.IssuerTypeCiProvider: - principal, err = generic.WorkflowPrincipalFromIDToken(ctx, tok) + principal, err = ci_provider.WorkflowPrincipalFromIDToken(ctx, tok) case config.IssuerTypeBuildkiteJob: principal, err = buildkite.JobPrincipalFromIDToken(ctx, tok) case config.IssuerTypeGitLabPipeline: diff --git a/pkg/server/grpc_server_test.go b/pkg/server/grpc_server_test.go index 6a008e8d1..999083160 100644 --- a/pkg/server/grpc_server_test.go +++ b/pkg/server/grpc_server_test.go @@ -243,8 +243,7 @@ func TestGetConfiguration(t *testing.T) { %q: { "IssuerURL": %q, "ClientID": "sigstore", - "Type": "gitlab-pipeline", - "IsCiProvider": true + "Type": "gitlab-pipeline" }, %q: { "IssuerURL": %q, From 39bdc22ac5b88149f8af67c21baabd529ab0e4b8 Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Tue, 11 Jun 2024 16:56:35 +0000 Subject: [PATCH 30/56] removing underscore Signed-off-by: Javan lacerda --- pkg/challenges/challenges.go | 4 ++-- pkg/identity/{ci_provider => ciprovider}/issuer.go | 2 +- pkg/identity/{ci_provider => ciprovider}/issuer_test.go | 2 +- pkg/identity/{ci_provider => ciprovider}/principal.go | 2 +- pkg/identity/{ci_provider => ciprovider}/principal_test.go | 2 +- pkg/server/issuer_pool.go | 3 +-- 6 files changed, 7 insertions(+), 8 deletions(-) rename pkg/identity/{ci_provider => ciprovider}/issuer.go (98%) rename pkg/identity/{ci_provider => ciprovider}/issuer_test.go (97%) rename pkg/identity/{ci_provider => ciprovider}/principal.go (98%) rename pkg/identity/{ci_provider => ciprovider}/principal_test.go (97%) diff --git a/pkg/challenges/challenges.go b/pkg/challenges/challenges.go index 4c5b31781..14f444e67 100644 --- a/pkg/challenges/challenges.go +++ b/pkg/challenges/challenges.go @@ -27,7 +27,7 @@ import ( "github.com/sigstore/fulcio/pkg/config" "github.com/sigstore/fulcio/pkg/identity" "github.com/sigstore/fulcio/pkg/identity/buildkite" - "github.com/sigstore/fulcio/pkg/identity/ci_provider" + "github.com/sigstore/fulcio/pkg/identity/ciprovider" "github.com/sigstore/fulcio/pkg/identity/email" "github.com/sigstore/fulcio/pkg/identity/github" "github.com/sigstore/fulcio/pkg/identity/gitlabcom" @@ -61,7 +61,7 @@ func PrincipalFromIDToken(ctx context.Context, tok *oidc.IDToken) (identity.Prin var err error switch iss.Type { case config.IssuerTypeCiProvider: - principal, err = ci_provider.WorkflowPrincipalFromIDToken(ctx, tok) + principal, err = ciprovider.WorkflowPrincipalFromIDToken(ctx, tok) case config.IssuerTypeBuildkiteJob: principal, err = buildkite.JobPrincipalFromIDToken(ctx, tok) case config.IssuerTypeGitLabPipeline: diff --git a/pkg/identity/ci_provider/issuer.go b/pkg/identity/ciprovider/issuer.go similarity index 98% rename from pkg/identity/ci_provider/issuer.go rename to pkg/identity/ciprovider/issuer.go index 23fbdaa65..ce82d3558 100644 --- a/pkg/identity/ci_provider/issuer.go +++ b/pkg/identity/ciprovider/issuer.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package ci_provider +package ciprovider import ( "context" diff --git a/pkg/identity/ci_provider/issuer_test.go b/pkg/identity/ciprovider/issuer_test.go similarity index 97% rename from pkg/identity/ci_provider/issuer_test.go rename to pkg/identity/ciprovider/issuer_test.go index 59773c3f8..630d8f16e 100644 --- a/pkg/identity/ci_provider/issuer_test.go +++ b/pkg/identity/ciprovider/issuer_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package ci_provider +package ciprovider import ( "testing" diff --git a/pkg/identity/ci_provider/principal.go b/pkg/identity/ciprovider/principal.go similarity index 98% rename from pkg/identity/ci_provider/principal.go rename to pkg/identity/ciprovider/principal.go index cdbfd3945..a5b7f0ee7 100644 --- a/pkg/identity/ci_provider/principal.go +++ b/pkg/identity/ciprovider/principal.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package ci_provider +package ciprovider import ( "context" diff --git a/pkg/identity/ci_provider/principal_test.go b/pkg/identity/ciprovider/principal_test.go similarity index 97% rename from pkg/identity/ci_provider/principal_test.go rename to pkg/identity/ciprovider/principal_test.go index eda7811ab..0cded51fb 100644 --- a/pkg/identity/ci_provider/principal_test.go +++ b/pkg/identity/ciprovider/principal_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package ci_provider +package ciprovider import ( "testing" diff --git a/pkg/server/issuer_pool.go b/pkg/server/issuer_pool.go index c669fa865..6f284c5d3 100644 --- a/pkg/server/issuer_pool.go +++ b/pkg/server/issuer_pool.go @@ -19,7 +19,6 @@ import ( "github.com/sigstore/fulcio/pkg/identity" "github.com/sigstore/fulcio/pkg/identity/buildkite" "github.com/sigstore/fulcio/pkg/identity/chainguard" - "github.com/sigstore/fulcio/pkg/identity/ci_provider" "github.com/sigstore/fulcio/pkg/identity/codefresh" "github.com/sigstore/fulcio/pkg/identity/email" "github.com/sigstore/fulcio/pkg/identity/github" @@ -55,7 +54,7 @@ func getIssuer(meta string, i config.OIDCIssuer) identity.Issuer { } switch i.Type { case config.IssuerTypeCiProvider: - return ci_provider.Issuer(issuerURL) + return ciprovider.Issuer(issuerURL) case config.IssuerTypeEmail: return email.Issuer(issuerURL) case config.IssuerTypeGithubWorkflow: From af67958090e12ec81a99b8e6b83ed861bc5f64b3 Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Mon, 10 Jun 2024 13:46:44 +0000 Subject: [PATCH 31/56] logging Signed-off-by: Javan lacerda --- pkg/identity/ciprovider/principal.go | 100 +++++++++++++++++++++++---- 1 file changed, 88 insertions(+), 12 deletions(-) diff --git a/pkg/identity/ciprovider/principal.go b/pkg/identity/ciprovider/principal.go index a5b7f0ee7..edbd18a04 100644 --- a/pkg/identity/ciprovider/principal.go +++ b/pkg/identity/ciprovider/principal.go @@ -15,9 +15,13 @@ package ciprovider import ( + "bytes" "context" "crypto/x509" + "fmt" + "html/template" "net/url" + "strings" "github.com/coreos/go-oidc/v3/oidc" "github.com/sigstore/fulcio/pkg/certificate" @@ -25,22 +29,94 @@ import ( "github.com/sigstore/fulcio/pkg/identity" ) -type Provider struct { - Subject string - Extensions certificate.Extensions - Uris []string - Defaults map[string]string - OIDCIssuers []config.OIDCIssuer `yaml:"oidc-issuers,omitempty"` +func ApplyTemplate(path string, data map[string]string, defaultData map[string]string) string { + + // Here we merge the data from was claimed by the id token with the + // default data provided by the yaml file. + // The order here matter because we want to override the default data + // with the claimed data. + mergedData := make(map[string]string) + for k, v := range defaultData { + mergedData[k] = v + } + for k, v := range data { + mergedData[k] = v + } + + // It checks it is a path or a raw field by + // checking exists template syntax into the string + // TODO: Check if it is a best way to check that we should apply the template + if strings.Contains(path, "{{") { + var doc bytes.Buffer + t := template.New("") + p, err := t.Parse(path) + if err != nil { + panic(err) + } + err = p.Execute(&doc, mergedData) + if err != nil { + panic(err) + } + return doc.String() + } else { + return mergedData[path] + } } -// TO BE IMPLEMENTED. Just kept as a guide -func WorkflowPrincipalFromIDToken(_ context.Context, _ *oidc.IDToken) (identity.Principal, error) { - return nil, nil +// TO BE IMPLEMENTED. Just keeped as a guide +func WorkflowPrincipalFromIDToken(ctx context.Context, token *oidc.IDToken) (identity.Principal, error) { + iss, ok := config.FromContext(ctx).GetIssuer(token.Issuer) + if !ok { + return nil, fmt.Errorf("configuration can not be loaded for issuer %v", token.Issuer) + } + var claims map[string]string + if err := token.Claims(&claims); err != nil { + return nil, err + } + + configYaml := readYaml() + provider := configYaml.Providers[iss.Type] + e := provider.Extensions + defaults := provider.Defaults + + finalExtensions := certificate.Extensions{ + Issuer: ApplyTemplate(e.Issuer, claims, defaults), + GithubWorkflowTrigger: ApplyTemplate(e.GithubWorkflowTrigger, claims, defaults), + GithubWorkflowSHA: ApplyTemplate(e.GithubWorkflowSHA, claims, defaults), + GithubWorkflowName: ApplyTemplate(e.GithubWorkflowName, claims, defaults), + GithubWorkflowRepository: ApplyTemplate(e.GithubWorkflowRepository, claims, defaults), + GithubWorkflowRef: ApplyTemplate(e.GithubWorkflowRef, claims, defaults), + BuildSignerURI: ApplyTemplate(e.BuildSignerURI, claims, defaults), + BuildConfigDigest: ApplyTemplate(e.BuildConfigDigest, claims, defaults), + RunnerEnvironment: ApplyTemplate(e.RunnerEnvironment, claims, defaults), + SourceRepositoryURI: ApplyTemplate(e.SourceRepositoryURI, claims, defaults), + SourceRepositoryDigest: ApplyTemplate(e.SourceRepositoryDigest, claims, defaults), + SourceRepositoryRef: ApplyTemplate(e.SourceRepositoryRef, claims, defaults), + SourceRepositoryIdentifier: ApplyTemplate(e.SourceRepositoryIdentifier, claims, defaults), + SourceRepositoryOwnerURI: ApplyTemplate(e.SourceRepositoryOwnerURI, claims, defaults), + SourceRepositoryOwnerIdentifier: ApplyTemplate(e.SourceRepositoryOwnerIdentifier, claims, defaults), + BuildConfigURI: ApplyTemplate(e.BuildConfigURI, claims, defaults), + BuildSignerDigest: ApplyTemplate(e.BuildSignerDigest, claims, defaults), + BuildTrigger: ApplyTemplate(e.BuildTrigger, claims, defaults), + RunInvocationURI: ApplyTemplate(e.RunInvocationURI, claims, defaults), + SourceRepositoryVisibilityAtSigning: ApplyTemplate(e.SourceRepositoryVisibilityAtSigning, claims, defaults), + } + finalUris := make([]string, len(provider.Uris)-1) + for _, val := range provider.Uris { + finalUris = append(finalUris, ApplyTemplate(val, claims, defaults)) + } + + return &Provider{ + Subject: token.Subject, + Extensions: finalExtensions, + Uris: finalUris, + OIDCIssuers: provider.OIDCIssuers, + }, nil + } -// TO BE IMPLEMENTED. Just kept as a guide -func (Provider) Name(_ context.Context) string { - return "" +func (p Provider) Name(_ context.Context) string { + return p.Subject } func (p Provider) Embed(_ context.Context, cert *x509.Certificate) error { From 3c66a3a8cbc56b56c7aac35579864d8a7ac4d1dc Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Wed, 12 Jun 2024 18:00:04 +0000 Subject: [PATCH 32/56] implementing ci provider principal logic and test for Name function Signed-off-by: Javan lacerda --- pkg/identity/ciprovider/config.yaml | 33 +++++++++ pkg/identity/ciprovider/principal.go | 38 ++++++++-- pkg/identity/ciprovider/principal_test.go | 84 ++++++++++++++++++++++- 3 files changed, 147 insertions(+), 8 deletions(-) create mode 100644 pkg/identity/ciprovider/config.yaml diff --git a/pkg/identity/ciprovider/config.yaml b/pkg/identity/ciprovider/config.yaml new file mode 100644 index 000000000..fa0a8b710 --- /dev/null +++ b/pkg/identity/ciprovider/config.yaml @@ -0,0 +1,33 @@ +# Copyright 2024 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. + +providers: + github-workflow: + extensions: + build-signer-digest: job_workflow_sha + source-repository-digest: sha + source-repository-ref: ref + source-repository-identifier: repository_id + run-invocation-uri: "{{.url}}/{{.repository}}/actions/runs/{{.run_id}}/" + uris: + - "{{.url}}/{{.job_workflow_ref}}" + defaults: + url: https://github.com + meta-issuers: + - issuer-url: "https://token.actions.githubusercontent.com/*" + client-id: "sigstore" + oidc-issuers: + - issuer-url: https://token.actions.githubusercontent.com + contact: tac@sigstore.dev + description: "GitHub Actions OIDC auth" \ No newline at end of file diff --git a/pkg/identity/ciprovider/principal.go b/pkg/identity/ciprovider/principal.go index edbd18a04..404e37523 100644 --- a/pkg/identity/ciprovider/principal.go +++ b/pkg/identity/ciprovider/principal.go @@ -21,14 +21,43 @@ import ( "fmt" "html/template" "net/url" + "os" "strings" "github.com/coreos/go-oidc/v3/oidc" "github.com/sigstore/fulcio/pkg/certificate" "github.com/sigstore/fulcio/pkg/config" "github.com/sigstore/fulcio/pkg/identity" + "gopkg.in/yaml.v3" ) +type RootYaml struct { + Providers map[config.IssuerType]Provider +} +type Provider struct { + Subject string + Extensions certificate.Extensions + Uris []string + Defaults map[string]string + OIDCIssuers []config.OIDCIssuer `yaml:"oidc-issuers,omitempty"` + MetaIssuers []config.OIDCIssuer `yaml:"meta-issuers,omitempty"` +} + +func readYaml() RootYaml { + var obj RootYaml + + yamlFile, err := os.ReadFile("config.yaml") + if err != nil { + fmt.Printf("yamlFile.Get err #%v ", err) + } + err = yaml.Unmarshal(yamlFile, &obj) + if err != nil { + fmt.Printf("Unmarshal: %v", err) + } + + return obj +} + func ApplyTemplate(path string, data map[string]string, defaultData map[string]string) string { // Here we merge the data from was claimed by the id token with the @@ -43,9 +72,6 @@ func ApplyTemplate(path string, data map[string]string, defaultData map[string]s mergedData[k] = v } - // It checks it is a path or a raw field by - // checking exists template syntax into the string - // TODO: Check if it is a best way to check that we should apply the template if strings.Contains(path, "{{") { var doc bytes.Buffer t := template.New("") @@ -58,12 +84,10 @@ func ApplyTemplate(path string, data map[string]string, defaultData map[string]s panic(err) } return doc.String() - } else { - return mergedData[path] } + return mergedData[path] } -// TO BE IMPLEMENTED. Just keeped as a guide func WorkflowPrincipalFromIDToken(ctx context.Context, token *oidc.IDToken) (identity.Principal, error) { iss, ok := config.FromContext(ctx).GetIssuer(token.Issuer) if !ok { @@ -73,7 +97,6 @@ func WorkflowPrincipalFromIDToken(ctx context.Context, token *oidc.IDToken) (ide if err := token.Claims(&claims); err != nil { return nil, err } - configYaml := readYaml() provider := configYaml.Providers[iss.Type] e := provider.Extensions @@ -111,6 +134,7 @@ func WorkflowPrincipalFromIDToken(ctx context.Context, token *oidc.IDToken) (ide Extensions: finalExtensions, Uris: finalUris, OIDCIssuers: provider.OIDCIssuers, + MetaIssuers: provider.MetaIssuers, }, nil } diff --git a/pkg/identity/ciprovider/principal_test.go b/pkg/identity/ciprovider/principal_test.go index 0cded51fb..ed5544cda 100644 --- a/pkg/identity/ciprovider/principal_test.go +++ b/pkg/identity/ciprovider/principal_test.go @@ -15,7 +15,14 @@ package ciprovider import ( + "context" + "encoding/json" + "reflect" "testing" + "unsafe" + + "github.com/coreos/go-oidc/v3/oidc" + "github.com/sigstore/fulcio/pkg/config" ) // TO BE IMPLEMENTED. Just kept as a guide @@ -23,8 +30,83 @@ func TestWorkflowPrincipalFromIDToken(_ *testing.T) { } -func TestName(_ *testing.T) { +// reflect hack because "claims" field is unexported by oidc IDToken +// https://github.com/coreos/go-oidc/pull/329 +func withClaims(token *oidc.IDToken, data []byte) { + val := reflect.Indirect(reflect.ValueOf(token)) + member := val.FieldByName("claims") + pointer := unsafe.Pointer(member.UnsafeAddr()) + realPointer := (*[]byte)(pointer) + *realPointer = data +} + +func TestName(t *testing.T) { + tests := map[string]struct { + Claims map[string]interface{} + ExpectName string + }{ + `Valid token authenticates with correct claims`: { + Claims: map[string]interface{}{ + "aud": "sigstore", + "event_name": "push", + "exp": "0", + "iss": "https://token.actions.githubusercontent.com", + "job_workflow_ref": "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main", + "job_workflow_sha": "example-sha", + "ref": "refs/heads/main", + "repository": "sigstore/fulcio", + "repository_id": "12345", + "repository_owner": "username", + "repository_owner_id": "345", + "repository_visibility": "public", + "run_attempt": "1", + "run_id": "42", + "runner_environment": "cloud-hosted", + "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "sub": "repo:sigstore/fulcio:ref:refs/heads/main", + "workflow": "foo", + "workflow_ref": "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", + "workflow_sha": "example-sha-other", + }, + ExpectName: "repo:sigstore/fulcio:ref:refs/heads/main", + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + token := &oidc.IDToken{ + Issuer: test.Claims["iss"].(string), + Subject: test.Claims["sub"].(string), + } + claims, err := json.Marshal(test.Claims) + if err != nil { + t.Fatal(err) + } + withClaims(token, claims) + ctx := context.TODO() + OIDCIssuers := + map[string]config.OIDCIssuer{ + token.Issuer: { + IssuerURL: token.Issuer, + Type: config.IssuerTypeGithubWorkflow, + ClientID: "sigstore", + }, + } + cfg := &config.FulcioConfig{ + OIDCIssuers: OIDCIssuers, + } + ctx = config.With(ctx, cfg) + principal, err := WorkflowPrincipalFromIDToken(ctx, token) + if err != nil { + t.Fatal(err) + } + gotName := principal.Name(context.TODO()) + if gotName != test.ExpectName { + t.Error("name should match sub claim") + } + }) + } } func TestEmbed(_ *testing.T) { From 2cbe6daeae5ae96846ba24524daf53e0d9f8b145 Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Thu, 13 Jun 2024 20:37:31 +0000 Subject: [PATCH 33/56] moving embed logic to embed function and test Signed-off-by: Javan lacerda --- pkg/challenges/challenges.go | 3 - pkg/config/config.go | 1 - pkg/identity/ciprovider/principal.go | 90 +++++++------- pkg/identity/ciprovider/principal_test.go | 142 +++++++++++++++++++++- pkg/server/issuer_pool.go | 2 - 5 files changed, 185 insertions(+), 53 deletions(-) diff --git a/pkg/challenges/challenges.go b/pkg/challenges/challenges.go index 14f444e67..dda3298ff 100644 --- a/pkg/challenges/challenges.go +++ b/pkg/challenges/challenges.go @@ -27,7 +27,6 @@ import ( "github.com/sigstore/fulcio/pkg/config" "github.com/sigstore/fulcio/pkg/identity" "github.com/sigstore/fulcio/pkg/identity/buildkite" - "github.com/sigstore/fulcio/pkg/identity/ciprovider" "github.com/sigstore/fulcio/pkg/identity/email" "github.com/sigstore/fulcio/pkg/identity/github" "github.com/sigstore/fulcio/pkg/identity/gitlabcom" @@ -60,8 +59,6 @@ func PrincipalFromIDToken(ctx context.Context, tok *oidc.IDToken) (identity.Prin var principal identity.Principal var err error switch iss.Type { - case config.IssuerTypeCiProvider: - principal, err = ciprovider.WorkflowPrincipalFromIDToken(ctx, tok) case config.IssuerTypeBuildkiteJob: principal, err = buildkite.JobPrincipalFromIDToken(ctx, tok) case config.IssuerTypeGitLabPipeline: diff --git a/pkg/config/config.go b/pkg/config/config.go index 2d46e64ed..6a6aca77e 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -284,7 +284,6 @@ const ( IssuerTypeSpiffe = "spiffe" IssuerTypeURI = "uri" IssuerTypeUsername = "username" - IssuerTypeCiProvider = "ci-provider" ) func parseConfig(b []byte) (cfg *FulcioConfig, err error) { diff --git a/pkg/identity/ciprovider/principal.go b/pkg/identity/ciprovider/principal.go index 404e37523..96dee02b4 100644 --- a/pkg/identity/ciprovider/principal.go +++ b/pkg/identity/ciprovider/principal.go @@ -31,7 +31,7 @@ import ( "gopkg.in/yaml.v3" ) -type RootYaml struct { +type Config struct { Providers map[config.IssuerType]Provider } type Provider struct { @@ -41,16 +41,17 @@ type Provider struct { Defaults map[string]string OIDCIssuers []config.OIDCIssuer `yaml:"oidc-issuers,omitempty"` MetaIssuers []config.OIDCIssuer `yaml:"meta-issuers,omitempty"` + Claims map[string]interface{} } -func readYaml() RootYaml { - var obj RootYaml +func readConfig() Config { + var obj Config - yamlFile, err := os.ReadFile("config.yaml") + configFile, err := os.ReadFile("config.yaml") if err != nil { fmt.Printf("yamlFile.Get err #%v ", err) } - err = yaml.Unmarshal(yamlFile, &obj) + err = yaml.Unmarshal(configFile, &obj) if err != nil { fmt.Printf("Unmarshal: %v", err) } @@ -58,6 +59,14 @@ func readYaml() RootYaml { return obj } +func claimsToString(claims map[string]interface{}) map[string]string { + stringClaims := make(map[string]string) + for k, v := range claims { + stringClaims[k] = v.(string) + } + return stringClaims +} + func ApplyTemplate(path string, data map[string]string, defaultData map[string]string) string { // Here we merge the data from was claimed by the id token with the @@ -93,16 +102,40 @@ func WorkflowPrincipalFromIDToken(ctx context.Context, token *oidc.IDToken) (ide if !ok { return nil, fmt.Errorf("configuration can not be loaded for issuer %v", token.Issuer) } - var claims map[string]string + var claims map[string]interface{} if err := token.Claims(&claims); err != nil { return nil, err } - configYaml := readYaml() + configYaml := readConfig() provider := configYaml.Providers[iss.Type] - e := provider.Extensions - defaults := provider.Defaults + provider.Claims = claims + provider.Subject = token.Subject + return provider, nil +} + +func (p Provider) Name(_ context.Context) string { + return p.Subject +} + +func (p Provider) Embed(_ context.Context, cert *x509.Certificate) error { - finalExtensions := certificate.Extensions{ + e := p.Extensions + defaults := p.Defaults + claims := claimsToString(p.Claims) + uris := make([]*url.URL, len(p.Uris)) + for _, value := range p.Uris { + url, err := url.Parse(ApplyTemplate(value, claims, defaults)) + if err != nil { + panic(err) + } + uris = append(uris, url) + } + // Set workflow ref URL to SubjectAlternativeName on certificate + cert.URIs = uris + + var err error + // Embed additional information into custom extensions + cert.ExtraExtensions, err = certificate.Extensions{ Issuer: ApplyTemplate(e.Issuer, claims, defaults), GithubWorkflowTrigger: ApplyTemplate(e.GithubWorkflowTrigger, claims, defaults), GithubWorkflowSHA: ApplyTemplate(e.GithubWorkflowSHA, claims, defaults), @@ -123,42 +156,7 @@ func WorkflowPrincipalFromIDToken(ctx context.Context, token *oidc.IDToken) (ide BuildTrigger: ApplyTemplate(e.BuildTrigger, claims, defaults), RunInvocationURI: ApplyTemplate(e.RunInvocationURI, claims, defaults), SourceRepositoryVisibilityAtSigning: ApplyTemplate(e.SourceRepositoryVisibilityAtSigning, claims, defaults), - } - finalUris := make([]string, len(provider.Uris)-1) - for _, val := range provider.Uris { - finalUris = append(finalUris, ApplyTemplate(val, claims, defaults)) - } - - return &Provider{ - Subject: token.Subject, - Extensions: finalExtensions, - Uris: finalUris, - OIDCIssuers: provider.OIDCIssuers, - MetaIssuers: provider.MetaIssuers, - }, nil - -} - -func (p Provider) Name(_ context.Context) string { - return p.Subject -} - -func (p Provider) Embed(_ context.Context, cert *x509.Certificate) error { - - uris := make([]*url.URL, len(p.Uris)) - for _, value := range p.Uris { - url, err := url.Parse(value) - if err != nil { - panic(err) - } - uris = append(uris, url) - } - // Set workflow ref URL to SubjectAlternativeName on certificate - cert.URIs = uris - - var err error - // Embed additional information into custom extensions - cert.ExtraExtensions, err = p.Extensions.Render() + }.Render() if err != nil { return err } diff --git a/pkg/identity/ciprovider/principal_test.go b/pkg/identity/ciprovider/principal_test.go index ed5544cda..16fac3dff 100644 --- a/pkg/identity/ciprovider/principal_test.go +++ b/pkg/identity/ciprovider/principal_test.go @@ -15,14 +15,21 @@ package ciprovider import ( + "bytes" "context" + "crypto/x509" + "encoding/asn1" "encoding/json" + "errors" + "fmt" "reflect" "testing" "unsafe" "github.com/coreos/go-oidc/v3/oidc" + "github.com/sigstore/fulcio/pkg/certificate" "github.com/sigstore/fulcio/pkg/config" + "github.com/sigstore/fulcio/pkg/identity" ) // TO BE IMPLEMENTED. Just kept as a guide @@ -109,6 +116,139 @@ func TestName(t *testing.T) { } } -func TestEmbed(_ *testing.T) { +func TestEmbed(t *testing.T) { + tests := map[string]struct { + Principal identity.Principal + WantErr bool + WantFacts map[string]func(x509.Certificate) error + }{ + `Github workflow challenge should have all Github workflow extensions and issuer set`: { + Principal: &Provider{ + Extensions: certificate.Extensions{ + Issuer: "issuer", + GithubWorkflowTrigger: "event_name", + GithubWorkflowSHA: "sha", + GithubWorkflowName: "workflow", + GithubWorkflowRepository: "repository", + GithubWorkflowRef: "ref", + BuildSignerURI: "{{ .url }}/{{ .job_workflow_ref }}", + BuildSignerDigest: "job_workflow_sha", + RunnerEnvironment: "runner_environment", + SourceRepositoryURI: "{{ .url }}/{{ .repository }}", + SourceRepositoryDigest: "sha", + SourceRepositoryRef: "ref", + SourceRepositoryIdentifier: "repository_id", + SourceRepositoryOwnerURI: "{{ .url }}/{{ .repository_owner }}", + SourceRepositoryOwnerIdentifier: "repository_owner_id", + BuildConfigURI: "{{ .url }}/{{ .workflow_ref }}", + BuildConfigDigest: "workflow_sha", + BuildTrigger: "event_name", + RunInvocationURI: "{{ .url }}/{{ .repository }}/actions/runs/{{ .run_id }}/attempts/{{ .run_attempt }}", + SourceRepositoryVisibilityAtSigning: "repository_visibility", + }, + Claims: map[string]interface{}{ + "issuer": "https://token.actions.githubusercontent.com", + "event_name": "trigger", + "sha": "sha", + "workflow": "workflowname", + "repository": "repository", + "ref": "ref", + "job_workflow_sha": "jobWorkflowSha", + "job_workflow_ref": "jobWorkflowRef", + "runner_environment": "runnerEnv", + "repository_id": "repoID", + "repository_owner": "repoOwner", + "repository_owner_id": "repoOwnerID", + "workflow_ref": "workflowRef", + "workflow_sha": "workflowSHA", + "run_id": "runID", + "run_attempt": "runAttempt", + "repository_visibility": "public", + }, + Defaults: map[string]string{ + "url": "https://github.com", + }, + }, + WantErr: false, + WantFacts: map[string]func(x509.Certificate) error{ + `Certifificate should have correct issuer`: factDeprecatedExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 1}, "https://token.actions.githubusercontent.com"), + `Certificate has correct trigger extension`: factDeprecatedExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 2}, "trigger"), + `Certificate has correct SHA extension`: factDeprecatedExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 3}, "sha"), + `Certificate has correct workflow extension`: factDeprecatedExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 4}, "workflowname"), + `Certificate has correct repository extension`: factDeprecatedExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 5}, "repository"), + `Certificate has correct ref extension`: factDeprecatedExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 6}, "ref"), + `Certificate has correct issuer (v2) extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 8}, "https://token.actions.githubusercontent.com"), + `Certificate has correct builder signer URI extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 9}, "https://github.com/jobWorkflowRef"), + `Certificate has correct builder signer digest extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 10}, "jobWorkflowSha"), + `Certificate has correct runner environment extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 11}, "runnerEnv"), + `Certificate has correct source repo URI extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 12}, "https://github.com/repository"), + `Certificate has correct source repo digest extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 13}, "sha"), + `Certificate has correct source repo ref extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 14}, "ref"), + `Certificate has correct source repo ID extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 15}, "repoID"), + `Certificate has correct source repo owner URI extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 16}, "https://github.com/repoOwner"), + `Certificate has correct source repo owner ID extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 17}, "repoOwnerID"), + `Certificate has correct build config URI extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 18}, "https://github.com/workflowRef"), + `Certificate has correct build config digest extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 19}, "workflowSHA"), + `Certificate has correct build trigger extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 20}, "trigger"), + `Certificate has correct run invocation ID extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 21}, "https://github.com/repository/actions/runs/runID/attempts/runAttempt"), + `Certificate has correct source repository visibility extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 22}, "public"), + }, + }, + `Github workflow value with bad URL fails`: { + Principal: &Provider{}, + WantErr: true, + }, + } + for name, test := range tests { + t.Run(name, func(t *testing.T) { + var cert x509.Certificate + err := test.Principal.Embed(context.TODO(), &cert) + if err != nil { + if !test.WantErr { + t.Error(err) + } + return + } else if test.WantErr { + t.Error("expected error") + } + for factName, fact := range test.WantFacts { + t.Run(factName, func(t *testing.T) { + if err := fact(cert); err != nil { + t.Error(err) + } + }) + } + }) + } +} + +func factExtensionIs(oid asn1.ObjectIdentifier, value string) func(x509.Certificate) error { + return func(cert x509.Certificate) error { + for _, ext := range cert.ExtraExtensions { + if ext.Id.Equal(oid) { + var strVal string + _, _ = asn1.Unmarshal(ext.Value, &strVal) + if value != strVal { + return fmt.Errorf("expected oid %v to be %s, but got %s", oid, value, strVal) + } + return nil + } + } + return errors.New("extension not set") + } +} + +func factDeprecatedExtensionIs(oid asn1.ObjectIdentifier, value string) func(x509.Certificate) error { + return func(cert x509.Certificate) error { + for _, ext := range cert.ExtraExtensions { + if ext.Id.Equal(oid) { + if !bytes.Equal(ext.Value, []byte(value)) { + return fmt.Errorf("expected oid %v to be %s, but got %s", oid, value, ext.Value) + } + return nil + } + } + return errors.New("extension not set") + } } diff --git a/pkg/server/issuer_pool.go b/pkg/server/issuer_pool.go index 6f284c5d3..18349f262 100644 --- a/pkg/server/issuer_pool.go +++ b/pkg/server/issuer_pool.go @@ -53,8 +53,6 @@ func getIssuer(meta string, i config.OIDCIssuer) identity.Issuer { issuerURL = meta } switch i.Type { - case config.IssuerTypeCiProvider: - return ciprovider.Issuer(issuerURL) case config.IssuerTypeEmail: return email.Issuer(issuerURL) case config.IssuerTypeGithubWorkflow: From aa257ed15d5b66743ee9981749a16d5278ecea0a Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Fri, 14 Jun 2024 13:32:57 +0000 Subject: [PATCH 34/56] adding test for ci provider WorkflowPrincipalFromIDToken Signed-off-by: Javan lacerda --- pkg/certificate/extensions.go | 38 ++++---- pkg/identity/ciprovider/principal_test.go | 108 +++++++++++++++++++++- 2 files changed, 125 insertions(+), 21 deletions(-) diff --git a/pkg/certificate/extensions.go b/pkg/certificate/extensions.go index 38f80d5ae..e3e96fe41 100644 --- a/pkg/certificate/extensions.go +++ b/pkg/certificate/extensions.go @@ -69,69 +69,69 @@ type Extensions struct { // Deprecated // Triggering event of the Github Workflow. Matches the `event_name` claim of ID // tokens from Github Actions - GithubWorkflowTrigger string // OID 1.3.6.1.4.1.57264.1.2 + GithubWorkflowTrigger string `yaml:"github-workflow-trigger"` // OID 1.3.6.1.4.1.57264.1.2 // Deprecated // SHA of git commit being built in Github Actions. Matches the `sha` claim of ID // tokens from Github Actions - GithubWorkflowSHA string // OID 1.3.6.1.4.1.57264.1.3 + GithubWorkflowSHA string `yaml:"github-workflow-sha"` // OID 1.3.6.1.4.1.57264.1.3 // Deprecated // Name of Github Actions Workflow. Matches the `workflow` claim of the ID // tokens from Github Actions - GithubWorkflowName string // OID 1.3.6.1.4.1.57264.1.4 + GithubWorkflowName string `yaml:"github-workflow-name"` // OID 1.3.6.1.4.1.57264.1.4 // Deprecated // Repository of the Github Actions Workflow. Matches the `repository` claim of the ID // tokens from Github Actions - GithubWorkflowRepository string // OID 1.3.6.1.4.1.57264.1.5 + GithubWorkflowRepository string `yaml:"github-workflow-repository"` // OID 1.3.6.1.4.1.57264.1.5 // Deprecated // Git Ref of the Github Actions Workflow. Matches the `ref` claim of the ID tokens // from Github Actions - GithubWorkflowRef string // 1.3.6.1.4.1.57264.1.6 + GithubWorkflowRef string `yaml:"github-workflow-ref"` // 1.3.6.1.4.1.57264.1.6 // Reference to specific build instructions that are responsible for signing. - BuildSignerURI string // 1.3.6.1.4.1.57264.1.9 + BuildSignerURI string `yaml:"build-signer-uri"` // 1.3.6.1.4.1.57264.1.9 // Immutable reference to the specific version of the build instructions that is responsible for signing. - BuildSignerDigest string // 1.3.6.1.4.1.57264.1.10 + BuildSignerDigest string `yaml:"build-signer-digest"` // 1.3.6.1.4.1.57264.1.10 // Specifies whether the build took place in platform-hosted cloud infrastructure or customer/self-hosted infrastructure. - RunnerEnvironment string // 1.3.6.1.4.1.57264.1.11 + RunnerEnvironment string `yaml:"runner-environment"` // 1.3.6.1.4.1.57264.1.11 // Source repository URL that the build was based on. - SourceRepositoryURI string // 1.3.6.1.4.1.57264.1.12 + SourceRepositoryURI string `yaml:"source-repository-uri"` // 1.3.6.1.4.1.57264.1.12 // Immutable reference to a specific version of the source code that the build was based upon. - SourceRepositoryDigest string // 1.3.6.1.4.1.57264.1.13 + SourceRepositoryDigest string `yaml:"source-repository-digest"` // 1.3.6.1.4.1.57264.1.13 // Source Repository Ref that the build run was based upon. - SourceRepositoryRef string // 1.3.6.1.4.1.57264.1.14 + SourceRepositoryRef string `yaml:"source-repository-ref"` // 1.3.6.1.4.1.57264.1.14 // Immutable identifier for the source repository the workflow was based upon. - SourceRepositoryIdentifier string // 1.3.6.1.4.1.57264.1.15 + SourceRepositoryIdentifier string `yaml:"source-repository-identifier"` // 1.3.6.1.4.1.57264.1.15 // Source repository owner URL of the owner of the source repository that the build was based on. - SourceRepositoryOwnerURI string // 1.3.6.1.4.1.57264.1.16 + SourceRepositoryOwnerURI string `yaml:"source-repository-owner-uri"` // 1.3.6.1.4.1.57264.1.16 // Immutable identifier for the owner of the source repository that the workflow was based upon. - SourceRepositoryOwnerIdentifier string // 1.3.6.1.4.1.57264.1.17 + SourceRepositoryOwnerIdentifier string `yaml:"source-repository-owner-identifier"` // 1.3.6.1.4.1.57264.1.17 // Build Config URL to the top-level/initiating build instructions. - BuildConfigURI string // 1.3.6.1.4.1.57264.1.18 + BuildConfigURI string `yaml:"build-config-uri"` // 1.3.6.1.4.1.57264.1.18 // Immutable reference to the specific version of the top-level/initiating build instructions. - BuildConfigDigest string // 1.3.6.1.4.1.57264.1.19 + BuildConfigDigest string `yaml:"build-config-digest"` // 1.3.6.1.4.1.57264.1.19 // Event or action that initiated the build. - BuildTrigger string // 1.3.6.1.4.1.57264.1.20 + BuildTrigger string `yaml:"build-trigger"` // 1.3.6.1.4.1.57264.1.20 // Run Invocation URL to uniquely identify the build execution. - RunInvocationURI string // 1.3.6.1.4.1.57264.1.21 + RunInvocationURI string `yaml:"run-invocation-uri"` // 1.3.6.1.4.1.57264.1.21 // Source repository visibility at the time of signing the certificate. - SourceRepositoryVisibilityAtSigning string // 1.3.6.1.4.1.57264.1.22 + SourceRepositoryVisibilityAtSigning string `yaml:"source-repository-visibility-at-signing"` // 1.3.6.1.4.1.57264.1.22 } func (e Extensions) Render() ([]pkix.Extension, error) { diff --git a/pkg/identity/ciprovider/principal_test.go b/pkg/identity/ciprovider/principal_test.go index 16fac3dff..4edea7851 100644 --- a/pkg/identity/ciprovider/principal_test.go +++ b/pkg/identity/ciprovider/principal_test.go @@ -32,9 +32,113 @@ import ( "github.com/sigstore/fulcio/pkg/identity" ) -// TO BE IMPLEMENTED. Just kept as a guide -func TestWorkflowPrincipalFromIDToken(_ *testing.T) { +func TestWorkflowPrincipalFromIDToken(t *testing.T) { + tests := map[string]struct { + Claims map[string]interface{} + ExpectedPrincipal Provider + }{ + `Valid token authenticates with correct claims`: { + Claims: map[string]interface{}{ + "issuer": "https://token.actions.githubusercontent.com", + "event_name": "trigger", + "sha": "sha", + "workflow": "workflowname", + "repository": "repository", + "ref": "ref", + "job_workflow_sha": "jobWorkflowSha", + "job_workflow_ref": "jobWorkflowRef", + "runner_environment": "runnerEnv", + "repository_id": "repoID", + "repository_owner": "repoOwner", + "repository_owner_id": "repoOwnerID", + "workflow_ref": "workflowRef", + "workflow_sha": "workflowSHA", + "run_id": "runID", + "run_attempt": "runAttempt", + "repository_visibility": "public", + }, + ExpectedPrincipal: Provider{ + Subject: "subject-test", + Extensions: certificate.Extensions{ + BuildSignerDigest: "job_workflow_sha", + SourceRepositoryDigest: "sha", + SourceRepositoryRef: "ref", + SourceRepositoryIdentifier: "repository_id", + RunInvocationURI: "{{.url}}/{{.repository}}/actions/runs/{{.run_id}}/", + }, + Uris: []string{ + "{{.url}}/{{.job_workflow_ref}}", + }, + Defaults: map[string]string{ + "url": "https://github.com", + }, + OIDCIssuers: []config.OIDCIssuer{ + { + IssuerURL: "https://token.actions.githubusercontent.com", + }, + }, + MetaIssuers: []config.OIDCIssuer{ + { + IssuerURL: "https://token.actions.githubusercontent.com/*", + ClientID: "sigstore", + }, + }, + Claims: map[string]interface{}{ + "event_name": "trigger", + "issuer": "https://token.actions.githubusercontent.com", + "job_workflow_ref": "jobWorkflowRef", + "job_workflow_sha": "jobWorkflowSha", + "ref": "ref", + "repository": "repository", + "repository_id": "repoID", + "repository_owner": "repoOwner", + "repository_owner_id": "repoOwnerID", + "repository_visibility": "public", + "run_attempt": "runAttempt", + "run_id": "runID", + "runner_environment": "runnerEnv", + "sha": "sha", + "workflow": "workflowname", + "workflow_ref": "workflowRef", + "workflow_sha": "workflowSHA", + }, + }, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + token := &oidc.IDToken{ + Subject: "subject-test", + } + claims, err := json.Marshal(test.Claims) + if err != nil { + t.Fatal(err) + } + withClaims(token, claims) + ctx := context.TODO() + OIDCIssuers := + map[string]config.OIDCIssuer{ + token.Issuer: { + IssuerURL: token.Issuer, + Type: config.IssuerTypeGithubWorkflow, + ClientID: "sigstore", + }, + } + cfg := &config.FulcioConfig{ + OIDCIssuers: OIDCIssuers, + } + ctx = config.With(ctx, cfg) + principal, err := WorkflowPrincipalFromIDToken(ctx, token) + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(principal, test.ExpectedPrincipal) { + t.Error("Principals should be equals") + } + }) + } } // reflect hack because "claims" field is unexported by oidc IDToken From 4a86f57b2e63093b35024402fce551b9ccd025a7 Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Fri, 14 Jun 2024 14:10:03 +0000 Subject: [PATCH 35/56] adding test issuer for ci provider Signed-off-by: Javan lacerda --- pkg/identity/ciprovider/issuer_test.go | 79 +++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 2 deletions(-) diff --git a/pkg/identity/ciprovider/issuer_test.go b/pkg/identity/ciprovider/issuer_test.go index 630d8f16e..dab56caab 100644 --- a/pkg/identity/ciprovider/issuer_test.go +++ b/pkg/identity/ciprovider/issuer_test.go @@ -15,10 +15,85 @@ package ciprovider import ( + "context" + "encoding/json" "testing" + + "github.com/coreos/go-oidc/v3/oidc" + "github.com/sigstore/fulcio/pkg/config" + "github.com/sigstore/fulcio/pkg/identity" ) -// TO BE IMPLEMENTED. Just kept as a guide -func TestIssuer(_ *testing.T) { +func TestIssuer(t *testing.T) { + ctx := context.Background() + url := "test-issuer-url" + issuer := Issuer(url) + + // test the Match function + t.Run("match", func(t *testing.T) { + if matches := issuer.Match(ctx, url); !matches { + t.Fatal("expected url to match but it doesn't") + } + if matches := issuer.Match(ctx, "some-other-url"); matches { + t.Fatal("expected match to fail but it didn't") + } + }) + + t.Run("authenticate", func(t *testing.T) { + token := &oidc.IDToken{ + Issuer: "https://iss.example.com", + Subject: "repo:sigstore/fulcio:ref:refs/heads/main", + } + claims, err := json.Marshal(map[string]interface{}{ + "aud": "sigstore", + "event_name": "push", + "exp": 0, + "iss": "https://token.actions.githubusercontent.com", + "job_workflow_ref": "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main", + "job_workflow_sha": "example-sha", + "ref": "refs/heads/main", + "repository": "sigstore/fulcio", + "repository_id": "12345", + "repository_owner": "username", + "repository_owner_id": "345", + "repository_visibility": "public", + "run_attempt": "1", + "run_id": "42", + "runner_environment": "cloud-hosted", + "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "sub": "repo:sigstore/fulcio:ref:refs/heads/main", + "workflow": "foo", + "workflow_ref": "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", + "workflow_sha": "example-sha-other", + }) + if err != nil { + t.Fatal(err) + } + + withClaims(token, claims) + ctx := context.TODO() + OIDCIssuers := + map[string]config.OIDCIssuer{ + token.Issuer: { + IssuerURL: token.Issuer, + Type: config.IssuerTypeGithubWorkflow, + ClientID: "sigstore", + }, + } + cfg := &config.FulcioConfig{ + OIDCIssuers: OIDCIssuers, + } + ctx = config.With(ctx, cfg) + identity.Authorize = func(_ context.Context, _ string, _ ...config.InsecureOIDCConfigOption) (*oidc.IDToken, error) { + return token, nil + } + principal, err := issuer.Authenticate(ctx, "token") + if err != nil { + t.Fatal(err) + } + if principal.Name(ctx) != "repo:sigstore/fulcio:ref:refs/heads/main" { + t.Fatalf("got unexpected name %s", principal.Name(ctx)) + } + }) } From 342f8ad75499fbcc62a043b9e547c10778e08e26 Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Fri, 14 Jun 2024 14:19:47 +0000 Subject: [PATCH 36/56] change providers config file name Signed-off-by: Javan lacerda --- pkg/identity/ciprovider/principal.go | 2 +- pkg/identity/ciprovider/{config.yaml => providers_config.yaml} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename pkg/identity/ciprovider/{config.yaml => providers_config.yaml} (100%) diff --git a/pkg/identity/ciprovider/principal.go b/pkg/identity/ciprovider/principal.go index 96dee02b4..f9548933c 100644 --- a/pkg/identity/ciprovider/principal.go +++ b/pkg/identity/ciprovider/principal.go @@ -47,7 +47,7 @@ type Provider struct { func readConfig() Config { var obj Config - configFile, err := os.ReadFile("config.yaml") + configFile, err := os.ReadFile("providers_config.yaml") if err != nil { fmt.Printf("yamlFile.Get err #%v ", err) } diff --git a/pkg/identity/ciprovider/config.yaml b/pkg/identity/ciprovider/providers_config.yaml similarity index 100% rename from pkg/identity/ciprovider/config.yaml rename to pkg/identity/ciprovider/providers_config.yaml From 2b1ea3fec52dbde0d42821c0da30c932db2f0fe9 Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Wed, 19 Jun 2024 14:33:00 +0000 Subject: [PATCH 37/56] refactoring Signed-off-by: Javan lacerda --- cmd/app/serve.go | 4 + config/fulcio-config.yaml | 50 ++-- pkg/challenges/challenges.go | 3 + pkg/config/config.go | 70 +++++- pkg/config/config_test.go | 3 + .../providers_config.yaml | 3 +- pkg/identity/ciprovider/issuer_test.go | 3 +- pkg/identity/ciprovider/principal.go | 124 ++++------ pkg/identity/ciprovider/principal_test.go | 227 +++++++++--------- pkg/server/issuer_pool.go | 3 + 10 files changed, 278 insertions(+), 212 deletions(-) rename pkg/{identity/ciprovider => config}/providers_config.yaml (95%) diff --git a/cmd/app/serve.go b/cmd/app/serve.go index de0b28194..a20918efb 100644 --- a/cmd/app/serve.go +++ b/cmd/app/serve.go @@ -214,6 +214,10 @@ func runServeCmd(cmd *cobra.Command, args []string) { //nolint: revive if err != nil { log.Logger.Fatalf("error loading --config-path=%s: %v", cp, err) } + cfg, err = config.LoadCiProvidersConfig(cfg) + if err != nil { + log.Logger.Fatalf("error loading CiProviderConfig: %v", err) + } var baseca certauth.CertificateAuthority switch viper.GetString("ca") { diff --git a/config/fulcio-config.yaml b/config/fulcio-config.yaml index 0f7a0aded..4dd5d23bd 100644 --- a/config/fulcio-config.yaml +++ b/config/fulcio-config.yaml @@ -20,43 +20,51 @@ data: "https://accounts.google.com": { "IssuerURL": "https://accounts.google.com", "ClientID": "sigstore", - "Type": "email" + "Type": "email", + "SubType": "" }, "https://agent.buildkite.com": { "IssuerURL": "https://agent.buildkite.com", "ClientID": "sigstore", - "Type": "buildkite-job" + "Type": "buildkite-job", + "SubType": "" }, "https://allow.pub": { "IssuerURL": "https://allow.pub", "ClientID": "sigstore", "Type": "spiffe", + "SubType": "", "SPIFFETrustDomain": "allow.pub" }, "https://auth-staging.eclipse.org/realms/sigstore": { "IssuerURL": "https://auth-staging.eclipse.org/realms/sigstore", "ClientID": "sigstore", - "Type": "email" + "Type": "email", + "SubType": "" }, "https://auth.eclipse.org/auth/realms/sigstore": { "IssuerURL": "https://auth.eclipse.org/auth/realms/sigstore", "ClientID": "sigstore", - "Type": "email" + "Type": "email", + "SubType": "" }, "https://dev.gitlab.org": { "IssuerURL": "https://dev.gitlab.org", "ClientID": "sigstore", - "Type": "gitlab-pipeline" + "Type": "gitlab-pipeline", + "SubType": "" }, "https://gitlab.archlinux.org": { "IssuerURL": "https://gitlab.archlinux.org", "ClientID": "sigstore", - "Type": "gitlab-pipeline" + "Type": "gitlab-pipeline", + "SubType": "" }, "https://gitlab.com": { "IssuerURL": "https://gitlab.com", "ClientID": "sigstore", - "Type": "gitlab-pipeline" + "Type": "gitlab-pipeline", + "SubType": "" }, "https://issuer.enforce.dev": { "IssuerURL": "https://issuer.enforce.dev", @@ -67,46 +75,56 @@ data: "IssuerURL": "https://oauth2.sigstore.dev/auth", "ClientID": "sigstore", "Type": "email", + "SubType": "", "IssuerClaim": "$.federated_claims.connector_id" }, "https://oidc.codefresh.io": { "IssuerURL": "https://oidc.codefresh.io", "ClientID": "sigstore", - "Type": "codefresh-workflow" + "Type": "codefresh-workflow", + "SubType": "" }, "https://ops.gitlab.net": { "IssuerURL": "https://ops.gitlab.net", "ClientID": "sigstore", - "Type": "gitlab-pipeline" + "Type": "gitlab-pipeline", + "SubType": "" }, "https://token.actions.githubusercontent.com": { "IssuerURL": "https://token.actions.githubusercontent.com", "ClientID": "sigstore", - "Type": "github-workflow" + "Type": "github-workflow", + "SubType": "" } }, "MetaIssuers": { "https://*.oic.prod-aks.azure.com/*": { "ClientID": "sigstore", - "Type": "kubernetes" + "Type": "kubernetes", + "SubType": "" }, "https://container.googleapis.com/v1/projects/*/locations/*/clusters/*": { "ClientID": "sigstore", - "Type": "kubernetes" + "Type": "kubernetes", + "SubType": "" }, "https://oidc.eks.*.amazonaws.com/id/*": { "ClientID": "sigstore", - "Type": "kubernetes" + "Type": "kubernetes", + "SubType": "" }, "https://oidc.prod-aks.azure.com/*": { "ClientID": "sigstore", - "Type": "kubernetes" + "Type": "kubernetes", + "SubType": "" }, "https://token.actions.githubusercontent.com/*": { "ClientID": "sigstore", - "Type": "github-workflow" + "Type": "github-workflow", + "SubType": "" } - } + }, + "IssuersMetadata": null } server.yaml: |- host: 0.0.0.0 diff --git a/pkg/challenges/challenges.go b/pkg/challenges/challenges.go index dda3298ff..b80cdc76b 100644 --- a/pkg/challenges/challenges.go +++ b/pkg/challenges/challenges.go @@ -27,6 +27,7 @@ import ( "github.com/sigstore/fulcio/pkg/config" "github.com/sigstore/fulcio/pkg/identity" "github.com/sigstore/fulcio/pkg/identity/buildkite" + "github.com/sigstore/fulcio/pkg/identity/ciprovider" "github.com/sigstore/fulcio/pkg/identity/email" "github.com/sigstore/fulcio/pkg/identity/github" "github.com/sigstore/fulcio/pkg/identity/gitlabcom" @@ -75,6 +76,8 @@ func PrincipalFromIDToken(ctx context.Context, tok *oidc.IDToken) (identity.Prin principal, err = uri.PrincipalFromIDToken(ctx, tok) case config.IssuerTypeUsername: principal, err = username.PrincipalFromIDToken(ctx, tok) + case config.IssuerTypeCiProvider: + principal, err = ciprovider.WorkflowPrincipalFromIDToken(ctx, tok) default: return nil, fmt.Errorf("unsupported issuer: %s", iss.Type) } diff --git a/pkg/config/config.go b/pkg/config/config.go index 6a6aca77e..41cdc421b 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -24,13 +24,16 @@ import ( "net/http" "net/url" "os" + "path/filepath" "reflect" "regexp" + "runtime" "strings" "time" "github.com/coreos/go-oidc/v3/oidc" lru "github.com/hashicorp/golang-lru" + "github.com/sigstore/fulcio/pkg/certificate" fulciogrpc "github.com/sigstore/fulcio/pkg/generated/protobuf" "github.com/sigstore/fulcio/pkg/log" "github.com/spiffe/go-spiffe/v2/spiffeid" @@ -60,12 +63,21 @@ type FulcioConfig struct { // * https://container.googleapis.com/v1/projects/mattmoor-credit/locations/us-west1-b/clusters/tenant-cluster MetaIssuers map[string]OIDCIssuer `json:"MetaIssuers,omitempty" yaml:"meta-issuers,omitempty"` + // defines the metadata for the issuers + IssuersMetadata map[string]IssuersMetadata + // verifiers is a fixed mapping from our OIDCIssuers to their OIDC verifiers. verifiers map[string][]*verifierWithConfig // lru is an LRU cache of recently used verifiers for our meta issuers. lru *lru.TwoQueueCache } +type IssuersMetadata struct { + Defaults map[string]string + ClaimsMapper certificate.Extensions + SubjectAlternativeName string +} + type OIDCIssuer struct { // The expected issuer of an OIDC token IssuerURL string `json:"IssuerURL,omitempty" yaml:"issuer-url,omitempty"` @@ -74,6 +86,8 @@ type OIDCIssuer struct { // Used to determine the subject of the certificate and if additional // certificate values are needed Type IssuerType `json:"Type" yaml:"type,omitempty"` + // Issuers subtype + SubType string `json:"SubType" yaml:"sub-type,omitempty"` // Optional, if the issuer is in a different claim in the OIDC token IssuerClaim string `json:"IssuerClaim,omitempty" yaml:"issuer-claim,omitempty"` // The domain that must be present in the subject for 'uri' issuer types @@ -284,6 +298,7 @@ const ( IssuerTypeSpiffe = "spiffe" IssuerTypeURI = "uri" IssuerTypeUsername = "username" + IssuerTypeCiProvider = "ci-provider" ) func parseConfig(b []byte) (cfg *FulcioConfig, err error) { @@ -432,6 +447,52 @@ func FromContext(ctx context.Context) *FulcioConfig { return untyped.(*FulcioConfig) } +type CiProvidersConfig struct { + Providers map[string]Provider +} +type Provider struct { + Extensions certificate.Extensions `yaml:"extensions,omitempty"` + SubjectAlternativeName string `yaml:"subject-alternative-name,omitempty"` + Defaults map[string]string `yaml:"defaults,omitempty"` + OIDCIssuers []OIDCIssuer `yaml:"oidc-issuers,omitempty"` + MetaIssuers []OIDCIssuer `yaml:"meta-issuers,omitempty"` +} + +func LoadCiProvidersConfig(cfg *FulcioConfig) (*FulcioConfig, error) { + var ciProvidersConfig CiProvidersConfig + _, path, _, _ := runtime.Caller(0) + basepath := filepath.Dir(path) + providersConfigFile, err := os.ReadFile(basepath + "/providers_config.yaml") + + if err != nil { + fmt.Printf("yamlFile.Get err #%v ", err) + } + err = yaml.Unmarshal(providersConfigFile, &ciProvidersConfig) + if err != nil { + fmt.Printf("Unmarshal: %v", err) + } + + cfg.IssuersMetadata = make(map[string]IssuersMetadata) + for k, v := range ciProvidersConfig.Providers { + cfg.IssuersMetadata[k] = IssuersMetadata{ + v.Defaults, + v.Extensions, + v.SubjectAlternativeName, + } + for _, issuer := range v.OIDCIssuers { + issuer.SubType = k + issuer.Type = IssuerTypeCiProvider + cfg.OIDCIssuers[issuer.IssuerURL] = issuer + } + for _, issuer := range v.MetaIssuers { + issuer.SubType = k + issuer.Type = IssuerTypeCiProvider + cfg.MetaIssuers[issuer.IssuerURL] = issuer + } + } + return cfg, err +} + // Load a config from disk, or use defaults func Load(configPath string) (*FulcioConfig, error) { if _, err := os.Stat(configPath); os.IsNotExist(err) { @@ -446,7 +507,12 @@ func Load(configPath string) (*FulcioConfig, error) { if err != nil { return nil, fmt.Errorf("read file: %w", err) } - return Read(b) + fulcioConfig, err := Read(b) + if err != nil { + return fulcioConfig, err + } + + return fulcioConfig, err } // Read parses the bytes of a config @@ -516,6 +582,8 @@ func issuerToChallengeClaim(issType IssuerType, challengeClaim string) string { return "email" case IssuerTypeGithubWorkflow: return "sub" + case IssuerTypeCiProvider: + return "sub" case IssuerTypeCodefreshWorkflow: return "sub" case IssuerTypeChainguard: diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index 4c0967660..c5473a098 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -492,6 +492,9 @@ func Test_issuerToChallengeClaim(t *testing.T) { if claim := issuerToChallengeClaim(IssuerTypeGithubWorkflow, ""); claim != "sub" { t.Fatalf("expected sub subject claim for GitHub issuer, got %s", claim) } + if claim := issuerToChallengeClaim(IssuerTypeCiProvider, ""); claim != "sub" { + t.Fatalf("expected sub subject claim for GitHub issuer, got %s", claim) + } if claim := issuerToChallengeClaim(IssuerTypeGitLabPipeline, ""); claim != "sub" { t.Fatalf("expected sub subject claim for GitLab issuer, got %s", claim) } diff --git a/pkg/identity/ciprovider/providers_config.yaml b/pkg/config/providers_config.yaml similarity index 95% rename from pkg/identity/ciprovider/providers_config.yaml rename to pkg/config/providers_config.yaml index fa0a8b710..ef3c6e85f 100644 --- a/pkg/identity/ciprovider/providers_config.yaml +++ b/pkg/config/providers_config.yaml @@ -20,8 +20,7 @@ providers: source-repository-ref: ref source-repository-identifier: repository_id run-invocation-uri: "{{.url}}/{{.repository}}/actions/runs/{{.run_id}}/" - uris: - - "{{.url}}/{{.job_workflow_ref}}" + subject-alternative-name: "{{.url}}/{{.job_workflow_ref}}" defaults: url: https://github.com meta-issuers: diff --git a/pkg/identity/ciprovider/issuer_test.go b/pkg/identity/ciprovider/issuer_test.go index dab56caab..31fe91e3a 100644 --- a/pkg/identity/ciprovider/issuer_test.go +++ b/pkg/identity/ciprovider/issuer_test.go @@ -76,7 +76,8 @@ func TestIssuer(t *testing.T) { map[string]config.OIDCIssuer{ token.Issuer: { IssuerURL: token.Issuer, - Type: config.IssuerTypeGithubWorkflow, + Type: config.IssuerTypeCiProvider, + SubType: "github-workflow", ClientID: "sigstore", }, } diff --git a/pkg/identity/ciprovider/principal.go b/pkg/identity/ciprovider/principal.go index f9548933c..1b7ae7561 100644 --- a/pkg/identity/ciprovider/principal.go +++ b/pkg/identity/ciprovider/principal.go @@ -21,44 +21,14 @@ import ( "fmt" "html/template" "net/url" - "os" "strings" "github.com/coreos/go-oidc/v3/oidc" "github.com/sigstore/fulcio/pkg/certificate" "github.com/sigstore/fulcio/pkg/config" "github.com/sigstore/fulcio/pkg/identity" - "gopkg.in/yaml.v3" ) -type Config struct { - Providers map[config.IssuerType]Provider -} -type Provider struct { - Subject string - Extensions certificate.Extensions - Uris []string - Defaults map[string]string - OIDCIssuers []config.OIDCIssuer `yaml:"oidc-issuers,omitempty"` - MetaIssuers []config.OIDCIssuer `yaml:"meta-issuers,omitempty"` - Claims map[string]interface{} -} - -func readConfig() Config { - var obj Config - - configFile, err := os.ReadFile("providers_config.yaml") - if err != nil { - fmt.Printf("yamlFile.Get err #%v ", err) - } - err = yaml.Unmarshal(configFile, &obj) - if err != nil { - fmt.Printf("Unmarshal: %v", err) - } - - return obj -} - func claimsToString(claims map[string]interface{}) map[string]string { stringClaims := make(map[string]string) for k, v := range claims { @@ -67,7 +37,7 @@ func claimsToString(claims map[string]interface{}) map[string]string { return stringClaims } -func ApplyTemplate(path string, data map[string]string, defaultData map[string]string) string { +func applyTemplate(path string, data map[string]string, defaultData map[string]string) string { // Here we merge the data from was claimed by the id token with the // default data provided by the yaml file. @@ -97,65 +67,69 @@ func ApplyTemplate(path string, data map[string]string, defaultData map[string]s return mergedData[path] } +type Config struct { + Token *oidc.IDToken + Metadata config.IssuersMetadata +} + func WorkflowPrincipalFromIDToken(ctx context.Context, token *oidc.IDToken) (identity.Principal, error) { - iss, ok := config.FromContext(ctx).GetIssuer(token.Issuer) + cfg := config.FromContext(ctx) + issuer, ok := cfg.GetIssuer(token.Issuer) if !ok { return nil, fmt.Errorf("configuration can not be loaded for issuer %v", token.Issuer) } - var claims map[string]interface{} - if err := token.Claims(&claims); err != nil { - return nil, err - } - configYaml := readConfig() - provider := configYaml.Providers[iss.Type] - provider.Claims = claims - provider.Subject = token.Subject - return provider, nil + + return Config{ + token, + cfg.IssuersMetadata[issuer.SubType], + }, nil } -func (p Provider) Name(_ context.Context) string { - return p.Subject +func (p Config) Name(_ context.Context) string { + return p.Token.Subject } -func (p Provider) Embed(_ context.Context, cert *x509.Certificate) error { +func (p Config) Embed(_ context.Context, cert *x509.Certificate) error { - e := p.Extensions - defaults := p.Defaults - claims := claimsToString(p.Claims) - uris := make([]*url.URL, len(p.Uris)) - for _, value := range p.Uris { - url, err := url.Parse(ApplyTemplate(value, claims, defaults)) - if err != nil { - panic(err) - } - uris = append(uris, url) + e := p.Metadata.ClaimsMapper + defaults := p.Metadata.Defaults + + var rawClaims map[string]interface{} + if err := p.Token.Claims(&rawClaims); err != nil { + return err + } + claims := claimsToString(rawClaims) + + subjectAlternativeNameURL, err := url.Parse(applyTemplate(p.Metadata.SubjectAlternativeName, claims, defaults)) + if err != nil { + panic(err) } + uris := []*url.URL{subjectAlternativeNameURL} // Set workflow ref URL to SubjectAlternativeName on certificate cert.URIs = uris - var err error // Embed additional information into custom extensions cert.ExtraExtensions, err = certificate.Extensions{ - Issuer: ApplyTemplate(e.Issuer, claims, defaults), - GithubWorkflowTrigger: ApplyTemplate(e.GithubWorkflowTrigger, claims, defaults), - GithubWorkflowSHA: ApplyTemplate(e.GithubWorkflowSHA, claims, defaults), - GithubWorkflowName: ApplyTemplate(e.GithubWorkflowName, claims, defaults), - GithubWorkflowRepository: ApplyTemplate(e.GithubWorkflowRepository, claims, defaults), - GithubWorkflowRef: ApplyTemplate(e.GithubWorkflowRef, claims, defaults), - BuildSignerURI: ApplyTemplate(e.BuildSignerURI, claims, defaults), - BuildConfigDigest: ApplyTemplate(e.BuildConfigDigest, claims, defaults), - RunnerEnvironment: ApplyTemplate(e.RunnerEnvironment, claims, defaults), - SourceRepositoryURI: ApplyTemplate(e.SourceRepositoryURI, claims, defaults), - SourceRepositoryDigest: ApplyTemplate(e.SourceRepositoryDigest, claims, defaults), - SourceRepositoryRef: ApplyTemplate(e.SourceRepositoryRef, claims, defaults), - SourceRepositoryIdentifier: ApplyTemplate(e.SourceRepositoryIdentifier, claims, defaults), - SourceRepositoryOwnerURI: ApplyTemplate(e.SourceRepositoryOwnerURI, claims, defaults), - SourceRepositoryOwnerIdentifier: ApplyTemplate(e.SourceRepositoryOwnerIdentifier, claims, defaults), - BuildConfigURI: ApplyTemplate(e.BuildConfigURI, claims, defaults), - BuildSignerDigest: ApplyTemplate(e.BuildSignerDigest, claims, defaults), - BuildTrigger: ApplyTemplate(e.BuildTrigger, claims, defaults), - RunInvocationURI: ApplyTemplate(e.RunInvocationURI, claims, defaults), - SourceRepositoryVisibilityAtSigning: ApplyTemplate(e.SourceRepositoryVisibilityAtSigning, claims, defaults), + Issuer: applyTemplate(e.Issuer, claims, defaults), + GithubWorkflowTrigger: applyTemplate(e.GithubWorkflowTrigger, claims, defaults), + GithubWorkflowSHA: applyTemplate(e.GithubWorkflowSHA, claims, defaults), + GithubWorkflowName: applyTemplate(e.GithubWorkflowName, claims, defaults), + GithubWorkflowRepository: applyTemplate(e.GithubWorkflowRepository, claims, defaults), + GithubWorkflowRef: applyTemplate(e.GithubWorkflowRef, claims, defaults), + BuildSignerURI: applyTemplate(e.BuildSignerURI, claims, defaults), + BuildConfigDigest: applyTemplate(e.BuildConfigDigest, claims, defaults), + RunnerEnvironment: applyTemplate(e.RunnerEnvironment, claims, defaults), + SourceRepositoryURI: applyTemplate(e.SourceRepositoryURI, claims, defaults), + SourceRepositoryDigest: applyTemplate(e.SourceRepositoryDigest, claims, defaults), + SourceRepositoryRef: applyTemplate(e.SourceRepositoryRef, claims, defaults), + SourceRepositoryIdentifier: applyTemplate(e.SourceRepositoryIdentifier, claims, defaults), + SourceRepositoryOwnerURI: applyTemplate(e.SourceRepositoryOwnerURI, claims, defaults), + SourceRepositoryOwnerIdentifier: applyTemplate(e.SourceRepositoryOwnerIdentifier, claims, defaults), + BuildConfigURI: applyTemplate(e.BuildConfigURI, claims, defaults), + BuildSignerDigest: applyTemplate(e.BuildSignerDigest, claims, defaults), + BuildTrigger: applyTemplate(e.BuildTrigger, claims, defaults), + RunInvocationURI: applyTemplate(e.RunInvocationURI, claims, defaults), + SourceRepositoryVisibilityAtSigning: applyTemplate(e.SourceRepositoryVisibilityAtSigning, claims, defaults), }.Render() if err != nil { return err diff --git a/pkg/identity/ciprovider/principal_test.go b/pkg/identity/ciprovider/principal_test.go index 4edea7851..81d719a63 100644 --- a/pkg/identity/ciprovider/principal_test.go +++ b/pkg/identity/ciprovider/principal_test.go @@ -29,16 +29,49 @@ import ( "github.com/coreos/go-oidc/v3/oidc" "github.com/sigstore/fulcio/pkg/certificate" "github.com/sigstore/fulcio/pkg/config" - "github.com/sigstore/fulcio/pkg/identity" ) func TestWorkflowPrincipalFromIDToken(t *testing.T) { tests := map[string]struct { - Claims map[string]interface{} - ExpectedPrincipal Provider + ExpectedPrincipal Config }{ - `Valid token authenticates with correct claims`: { - Claims: map[string]interface{}{ + `Github workflow challenge should have all Github workflow extensions and issuer set`: { + ExpectedPrincipal: Config{ + Metadata: config.IssuersMetadata{ + ClaimsMapper: certificate.Extensions{ + Issuer: "issuer", + GithubWorkflowTrigger: "event_name", + GithubWorkflowSHA: "sha", + GithubWorkflowName: "workflow", + GithubWorkflowRepository: "repository", + GithubWorkflowRef: "ref", + BuildSignerURI: "{{ .url }}/{{ .job_workflow_ref }}", + BuildSignerDigest: "job_workflow_sha", + RunnerEnvironment: "runner_environment", + SourceRepositoryURI: "{{ .url }}/{{ .repository }}", + SourceRepositoryDigest: "sha", + SourceRepositoryRef: "ref", + SourceRepositoryIdentifier: "repository_id", + SourceRepositoryOwnerURI: "{{ .url }}/{{ .repository_owner }}", + SourceRepositoryOwnerIdentifier: "repository_owner_id", + BuildConfigURI: "{{ .url }}/{{ .workflow_ref }}", + BuildConfigDigest: "workflow_sha", + BuildTrigger: "event_name", + RunInvocationURI: "{{ .url }}/{{ .repository }}/actions/runs/{{ .run_id }}/attempts/{{ .run_attempt }}", + SourceRepositoryVisibilityAtSigning: "repository_visibility", + }, + Defaults: map[string]string{ + "url": "https://github.com", + }, + SubjectAlternativeName: "{{.url}}/{{.job_workflow_ref}}", + }, + }, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + claims, err := json.Marshal(map[string]interface{}{ "issuer": "https://token.actions.githubusercontent.com", "event_name": "trigger", "sha": "sha", @@ -56,89 +89,41 @@ func TestWorkflowPrincipalFromIDToken(t *testing.T) { "run_id": "runID", "run_attempt": "runAttempt", "repository_visibility": "public", - }, - ExpectedPrincipal: Provider{ - Subject: "subject-test", - Extensions: certificate.Extensions{ - BuildSignerDigest: "job_workflow_sha", - SourceRepositoryDigest: "sha", - SourceRepositoryRef: "ref", - SourceRepositoryIdentifier: "repository_id", - RunInvocationURI: "{{.url}}/{{.repository}}/actions/runs/{{.run_id}}/", - }, - Uris: []string{ - "{{.url}}/{{.job_workflow_ref}}", - }, - Defaults: map[string]string{ - "url": "https://github.com", - }, - OIDCIssuers: []config.OIDCIssuer{ - { - IssuerURL: "https://token.actions.githubusercontent.com", - }, - }, - MetaIssuers: []config.OIDCIssuer{ - { - IssuerURL: "https://token.actions.githubusercontent.com/*", - ClientID: "sigstore", - }, - }, - Claims: map[string]interface{}{ - "event_name": "trigger", - "issuer": "https://token.actions.githubusercontent.com", - "job_workflow_ref": "jobWorkflowRef", - "job_workflow_sha": "jobWorkflowSha", - "ref": "ref", - "repository": "repository", - "repository_id": "repoID", - "repository_owner": "repoOwner", - "repository_owner_id": "repoOwnerID", - "repository_visibility": "public", - "run_attempt": "runAttempt", - "run_id": "runID", - "runner_environment": "runnerEnv", - "sha": "sha", - "workflow": "workflowname", - "workflow_ref": "workflowRef", - "workflow_sha": "workflowSHA", - }, - }, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - token := &oidc.IDToken{ - Subject: "subject-test", - } - claims, err := json.Marshal(test.Claims) + }) if err != nil { t.Fatal(err) } + token := &oidc.IDToken{} withClaims(token, claims) + + test.ExpectedPrincipal.Token = token ctx := context.TODO() OIDCIssuers := map[string]config.OIDCIssuer{ token.Issuer: { IssuerURL: token.Issuer, - Type: config.IssuerTypeGithubWorkflow, + Type: config.IssuerTypeCiProvider, + SubType: "github-workflow", ClientID: "sigstore", }, } + meta := make(map[string]config.IssuersMetadata) + meta["github-workflow"] = test.ExpectedPrincipal.Metadata cfg := &config.FulcioConfig{ - OIDCIssuers: OIDCIssuers, + OIDCIssuers: OIDCIssuers, + IssuersMetadata: meta, } ctx = config.With(ctx, cfg) principal, err := WorkflowPrincipalFromIDToken(ctx, token) if err != nil { t.Fatal(err) } - if !reflect.DeepEqual(principal, test.ExpectedPrincipal) { t.Error("Principals should be equals") } }) } + } // reflect hack because "claims" field is unexported by oidc IDToken @@ -199,7 +184,8 @@ func TestName(t *testing.T) { map[string]config.OIDCIssuer{ token.Issuer: { IssuerURL: token.Issuer, - Type: config.IssuerTypeGithubWorkflow, + Type: config.IssuerTypeCiProvider, + SubType: "ci-provider", ClientID: "sigstore", }, } @@ -222,57 +208,10 @@ func TestName(t *testing.T) { func TestEmbed(t *testing.T) { tests := map[string]struct { - Principal identity.Principal WantErr bool WantFacts map[string]func(x509.Certificate) error }{ `Github workflow challenge should have all Github workflow extensions and issuer set`: { - Principal: &Provider{ - Extensions: certificate.Extensions{ - Issuer: "issuer", - GithubWorkflowTrigger: "event_name", - GithubWorkflowSHA: "sha", - GithubWorkflowName: "workflow", - GithubWorkflowRepository: "repository", - GithubWorkflowRef: "ref", - BuildSignerURI: "{{ .url }}/{{ .job_workflow_ref }}", - BuildSignerDigest: "job_workflow_sha", - RunnerEnvironment: "runner_environment", - SourceRepositoryURI: "{{ .url }}/{{ .repository }}", - SourceRepositoryDigest: "sha", - SourceRepositoryRef: "ref", - SourceRepositoryIdentifier: "repository_id", - SourceRepositoryOwnerURI: "{{ .url }}/{{ .repository_owner }}", - SourceRepositoryOwnerIdentifier: "repository_owner_id", - BuildConfigURI: "{{ .url }}/{{ .workflow_ref }}", - BuildConfigDigest: "workflow_sha", - BuildTrigger: "event_name", - RunInvocationURI: "{{ .url }}/{{ .repository }}/actions/runs/{{ .run_id }}/attempts/{{ .run_attempt }}", - SourceRepositoryVisibilityAtSigning: "repository_visibility", - }, - Claims: map[string]interface{}{ - "issuer": "https://token.actions.githubusercontent.com", - "event_name": "trigger", - "sha": "sha", - "workflow": "workflowname", - "repository": "repository", - "ref": "ref", - "job_workflow_sha": "jobWorkflowSha", - "job_workflow_ref": "jobWorkflowRef", - "runner_environment": "runnerEnv", - "repository_id": "repoID", - "repository_owner": "repoOwner", - "repository_owner_id": "repoOwnerID", - "workflow_ref": "workflowRef", - "workflow_sha": "workflowSHA", - "run_id": "runID", - "run_attempt": "runAttempt", - "repository_visibility": "public", - }, - Defaults: map[string]string{ - "url": "https://github.com", - }, - }, WantErr: false, WantFacts: map[string]func(x509.Certificate) error{ `Certifificate should have correct issuer`: factDeprecatedExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 1}, "https://token.actions.githubusercontent.com"), @@ -298,16 +237,70 @@ func TestEmbed(t *testing.T) { `Certificate has correct source repository visibility extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 22}, "public"), }, }, - `Github workflow value with bad URL fails`: { - Principal: &Provider{}, - WantErr: true, - }, } for name, test := range tests { t.Run(name, func(t *testing.T) { var cert x509.Certificate - err := test.Principal.Embed(context.TODO(), &cert) + claims, err := json.Marshal(map[string]interface{}{ + "issuer": "https://token.actions.githubusercontent.com", + "event_name": "trigger", + "sha": "sha", + "workflow": "workflowname", + "repository": "repository", + "ref": "ref", + "job_workflow_sha": "jobWorkflowSha", + "job_workflow_ref": "jobWorkflowRef", + "runner_environment": "runnerEnv", + "repository_id": "repoID", + "repository_owner": "repoOwner", + "repository_owner_id": "repoOwnerID", + "workflow_ref": "workflowRef", + "workflow_sha": "workflowSHA", + "run_id": "runID", + "run_attempt": "runAttempt", + "repository_visibility": "public", + }) + if err != nil { + t.Fatal(err) + } + token := &oidc.IDToken{} + withClaims(token, claims) + + principal := + &Config{ + Metadata: config.IssuersMetadata{ + ClaimsMapper: certificate.Extensions{ + Issuer: "issuer", + GithubWorkflowTrigger: "event_name", + GithubWorkflowSHA: "sha", + GithubWorkflowName: "workflow", + GithubWorkflowRepository: "repository", + GithubWorkflowRef: "ref", + BuildSignerURI: "{{ .url }}/{{ .job_workflow_ref }}", + BuildSignerDigest: "job_workflow_sha", + RunnerEnvironment: "runner_environment", + SourceRepositoryURI: "{{ .url }}/{{ .repository }}", + SourceRepositoryDigest: "sha", + SourceRepositoryRef: "ref", + SourceRepositoryIdentifier: "repository_id", + SourceRepositoryOwnerURI: "{{ .url }}/{{ .repository_owner }}", + SourceRepositoryOwnerIdentifier: "repository_owner_id", + BuildConfigURI: "{{ .url }}/{{ .workflow_ref }}", + BuildConfigDigest: "workflow_sha", + BuildTrigger: "event_name", + RunInvocationURI: "{{ .url }}/{{ .repository }}/actions/runs/{{ .run_id }}/attempts/{{ .run_attempt }}", + SourceRepositoryVisibilityAtSigning: "repository_visibility", + }, + Defaults: map[string]string{ + "url": "https://github.com", + }, + SubjectAlternativeName: "{{.url}}/{{.job_workflow_ref}}", + }, + Token: token, + } + + err = principal.Embed(context.TODO(), &cert) if err != nil { if !test.WantErr { t.Error(err) diff --git a/pkg/server/issuer_pool.go b/pkg/server/issuer_pool.go index 18349f262..25f442cf4 100644 --- a/pkg/server/issuer_pool.go +++ b/pkg/server/issuer_pool.go @@ -19,6 +19,7 @@ import ( "github.com/sigstore/fulcio/pkg/identity" "github.com/sigstore/fulcio/pkg/identity/buildkite" "github.com/sigstore/fulcio/pkg/identity/chainguard" + "github.com/sigstore/fulcio/pkg/identity/ciprovider" "github.com/sigstore/fulcio/pkg/identity/codefresh" "github.com/sigstore/fulcio/pkg/identity/email" "github.com/sigstore/fulcio/pkg/identity/github" @@ -57,6 +58,8 @@ func getIssuer(meta string, i config.OIDCIssuer) identity.Issuer { return email.Issuer(issuerURL) case config.IssuerTypeGithubWorkflow: return github.Issuer(issuerURL) + case config.IssuerTypeCiProvider: + return ciprovider.Issuer(issuerURL) case config.IssuerTypeGitLabPipeline: return gitlabcom.Issuer(issuerURL) case config.IssuerTypeBuildkiteJob: From c50cd30858d684ee2ac103d20b00f20aaedc39e9 Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Wed, 19 Jun 2024 15:53:50 +0000 Subject: [PATCH 38/56] comment applyTemplate Signed-off-by: Javan lacerda --- pkg/identity/ciprovider/principal.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/identity/ciprovider/principal.go b/pkg/identity/ciprovider/principal.go index 1b7ae7561..c2b6b6b6f 100644 --- a/pkg/identity/ciprovider/principal.go +++ b/pkg/identity/ciprovider/principal.go @@ -37,6 +37,8 @@ func claimsToString(claims map[string]interface{}) map[string]string { return stringClaims } +// It makes string interpolation for a given string by using the +// templates syntax https://pkg.go.dev/text/template func applyTemplate(path string, data map[string]string, defaultData map[string]string) string { // Here we merge the data from was claimed by the id token with the @@ -110,7 +112,7 @@ func (p Config) Embed(_ context.Context, cert *x509.Certificate) error { // Embed additional information into custom extensions cert.ExtraExtensions, err = certificate.Extensions{ - Issuer: applyTemplate(e.Issuer, claims, defaults), + Issuer: e.Issuer, GithubWorkflowTrigger: applyTemplate(e.GithubWorkflowTrigger, claims, defaults), GithubWorkflowSHA: applyTemplate(e.GithubWorkflowSHA, claims, defaults), GithubWorkflowName: applyTemplate(e.GithubWorkflowName, claims, defaults), From cedc9cff0581a9d94302b92e47b4f349ae8f0a17 Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Wed, 19 Jun 2024 16:04:06 +0000 Subject: [PATCH 39/56] removing github for now, we should add it futher for rollouting Signed-off-by: Javan lacerda --- pkg/config/providers_config.yaml | 17 ------ pkg/identity/ciprovider/principal.go | 44 +++++++------- pkg/identity/ciprovider/principal_test.go | 74 ++++++++++------------- 3 files changed, 55 insertions(+), 80 deletions(-) diff --git a/pkg/config/providers_config.yaml b/pkg/config/providers_config.yaml index ef3c6e85f..3165b449e 100644 --- a/pkg/config/providers_config.yaml +++ b/pkg/config/providers_config.yaml @@ -13,20 +13,3 @@ # limitations under the License. providers: - github-workflow: - extensions: - build-signer-digest: job_workflow_sha - source-repository-digest: sha - source-repository-ref: ref - source-repository-identifier: repository_id - run-invocation-uri: "{{.url}}/{{.repository}}/actions/runs/{{.run_id}}/" - subject-alternative-name: "{{.url}}/{{.job_workflow_ref}}" - defaults: - url: https://github.com - meta-issuers: - - issuer-url: "https://token.actions.githubusercontent.com/*" - client-id: "sigstore" - oidc-issuers: - - issuer-url: https://token.actions.githubusercontent.com - contact: tac@sigstore.dev - description: "GitHub Actions OIDC auth" \ No newline at end of file diff --git a/pkg/identity/ciprovider/principal.go b/pkg/identity/ciprovider/principal.go index c2b6b6b6f..5ccebc520 100644 --- a/pkg/identity/ciprovider/principal.go +++ b/pkg/identity/ciprovider/principal.go @@ -39,7 +39,7 @@ func claimsToString(claims map[string]interface{}) map[string]string { // It makes string interpolation for a given string by using the // templates syntax https://pkg.go.dev/text/template -func applyTemplate(path string, data map[string]string, defaultData map[string]string) string { +func applyTemplateOrReplace(path string, data map[string]string, defaultData map[string]string) string { // Here we merge the data from was claimed by the id token with the // default data provided by the yaml file. @@ -102,7 +102,7 @@ func (p Config) Embed(_ context.Context, cert *x509.Certificate) error { } claims := claimsToString(rawClaims) - subjectAlternativeNameURL, err := url.Parse(applyTemplate(p.Metadata.SubjectAlternativeName, claims, defaults)) + subjectAlternativeNameURL, err := url.Parse(applyTemplateOrReplace(p.Metadata.SubjectAlternativeName, claims, defaults)) if err != nil { panic(err) } @@ -112,26 +112,26 @@ func (p Config) Embed(_ context.Context, cert *x509.Certificate) error { // Embed additional information into custom extensions cert.ExtraExtensions, err = certificate.Extensions{ - Issuer: e.Issuer, - GithubWorkflowTrigger: applyTemplate(e.GithubWorkflowTrigger, claims, defaults), - GithubWorkflowSHA: applyTemplate(e.GithubWorkflowSHA, claims, defaults), - GithubWorkflowName: applyTemplate(e.GithubWorkflowName, claims, defaults), - GithubWorkflowRepository: applyTemplate(e.GithubWorkflowRepository, claims, defaults), - GithubWorkflowRef: applyTemplate(e.GithubWorkflowRef, claims, defaults), - BuildSignerURI: applyTemplate(e.BuildSignerURI, claims, defaults), - BuildConfigDigest: applyTemplate(e.BuildConfigDigest, claims, defaults), - RunnerEnvironment: applyTemplate(e.RunnerEnvironment, claims, defaults), - SourceRepositoryURI: applyTemplate(e.SourceRepositoryURI, claims, defaults), - SourceRepositoryDigest: applyTemplate(e.SourceRepositoryDigest, claims, defaults), - SourceRepositoryRef: applyTemplate(e.SourceRepositoryRef, claims, defaults), - SourceRepositoryIdentifier: applyTemplate(e.SourceRepositoryIdentifier, claims, defaults), - SourceRepositoryOwnerURI: applyTemplate(e.SourceRepositoryOwnerURI, claims, defaults), - SourceRepositoryOwnerIdentifier: applyTemplate(e.SourceRepositoryOwnerIdentifier, claims, defaults), - BuildConfigURI: applyTemplate(e.BuildConfigURI, claims, defaults), - BuildSignerDigest: applyTemplate(e.BuildSignerDigest, claims, defaults), - BuildTrigger: applyTemplate(e.BuildTrigger, claims, defaults), - RunInvocationURI: applyTemplate(e.RunInvocationURI, claims, defaults), - SourceRepositoryVisibilityAtSigning: applyTemplate(e.SourceRepositoryVisibilityAtSigning, claims, defaults), + Issuer: applyTemplateOrReplace(e.Issuer, claims, defaults), + GithubWorkflowTrigger: applyTemplateOrReplace(e.GithubWorkflowTrigger, claims, defaults), + GithubWorkflowSHA: applyTemplateOrReplace(e.GithubWorkflowSHA, claims, defaults), + GithubWorkflowName: applyTemplateOrReplace(e.GithubWorkflowName, claims, defaults), + GithubWorkflowRepository: applyTemplateOrReplace(e.GithubWorkflowRepository, claims, defaults), + GithubWorkflowRef: applyTemplateOrReplace(e.GithubWorkflowRef, claims, defaults), + BuildSignerURI: applyTemplateOrReplace(e.BuildSignerURI, claims, defaults), + BuildConfigDigest: applyTemplateOrReplace(e.BuildConfigDigest, claims, defaults), + RunnerEnvironment: applyTemplateOrReplace(e.RunnerEnvironment, claims, defaults), + SourceRepositoryURI: applyTemplateOrReplace(e.SourceRepositoryURI, claims, defaults), + SourceRepositoryDigest: applyTemplateOrReplace(e.SourceRepositoryDigest, claims, defaults), + SourceRepositoryRef: applyTemplateOrReplace(e.SourceRepositoryRef, claims, defaults), + SourceRepositoryIdentifier: applyTemplateOrReplace(e.SourceRepositoryIdentifier, claims, defaults), + SourceRepositoryOwnerURI: applyTemplateOrReplace(e.SourceRepositoryOwnerURI, claims, defaults), + SourceRepositoryOwnerIdentifier: applyTemplateOrReplace(e.SourceRepositoryOwnerIdentifier, claims, defaults), + BuildConfigURI: applyTemplateOrReplace(e.BuildConfigURI, claims, defaults), + BuildSignerDigest: applyTemplateOrReplace(e.BuildSignerDigest, claims, defaults), + BuildTrigger: applyTemplateOrReplace(e.BuildTrigger, claims, defaults), + RunInvocationURI: applyTemplateOrReplace(e.RunInvocationURI, claims, defaults), + SourceRepositoryVisibilityAtSigning: applyTemplateOrReplace(e.SourceRepositoryVisibilityAtSigning, claims, defaults), }.Render() if err != nil { return err diff --git a/pkg/identity/ciprovider/principal_test.go b/pkg/identity/ciprovider/principal_test.go index 81d719a63..88c7568f8 100644 --- a/pkg/identity/ciprovider/principal_test.go +++ b/pkg/identity/ciprovider/principal_test.go @@ -208,11 +208,10 @@ func TestName(t *testing.T) { func TestEmbed(t *testing.T) { tests := map[string]struct { - WantErr bool WantFacts map[string]func(x509.Certificate) error + Principal Config }{ `Github workflow challenge should have all Github workflow extensions and issuer set`: { - WantErr: false, WantFacts: map[string]func(x509.Certificate) error{ `Certifificate should have correct issuer`: factDeprecatedExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 1}, "https://token.actions.githubusercontent.com"), `Certificate has correct trigger extension`: factDeprecatedExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 2}, "trigger"), @@ -236,6 +235,36 @@ func TestEmbed(t *testing.T) { `Certificate has correct run invocation ID extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 21}, "https://github.com/repository/actions/runs/runID/attempts/runAttempt"), `Certificate has correct source repository visibility extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 22}, "public"), }, + Principal: Config{ + Metadata: config.IssuersMetadata{ + ClaimsMapper: certificate.Extensions{ + Issuer: "issuer", + GithubWorkflowTrigger: "event_name", + GithubWorkflowSHA: "sha", + GithubWorkflowName: "workflow", + GithubWorkflowRepository: "repository", + GithubWorkflowRef: "ref", + BuildSignerURI: "{{ .url }}/{{ .job_workflow_ref }}", + BuildSignerDigest: "job_workflow_sha", + RunnerEnvironment: "runner_environment", + SourceRepositoryURI: "{{ .url }}/{{ .repository }}", + SourceRepositoryDigest: "sha", + SourceRepositoryRef: "ref", + SourceRepositoryIdentifier: "repository_id", + SourceRepositoryOwnerURI: "{{ .url }}/{{ .repository_owner }}", + SourceRepositoryOwnerIdentifier: "repository_owner_id", + BuildConfigURI: "{{ .url }}/{{ .workflow_ref }}", + BuildConfigDigest: "workflow_sha", + BuildTrigger: "event_name", + RunInvocationURI: "{{ .url }}/{{ .repository }}/actions/runs/{{ .run_id }}/attempts/{{ .run_attempt }}", + SourceRepositoryVisibilityAtSigning: "repository_visibility", + }, + Defaults: map[string]string{ + "url": "https://github.com", + }, + SubjectAlternativeName: "{{.url}}/{{.job_workflow_ref}}", + }, + }, }, } @@ -267,47 +296,10 @@ func TestEmbed(t *testing.T) { token := &oidc.IDToken{} withClaims(token, claims) - principal := - &Config{ - Metadata: config.IssuersMetadata{ - ClaimsMapper: certificate.Extensions{ - Issuer: "issuer", - GithubWorkflowTrigger: "event_name", - GithubWorkflowSHA: "sha", - GithubWorkflowName: "workflow", - GithubWorkflowRepository: "repository", - GithubWorkflowRef: "ref", - BuildSignerURI: "{{ .url }}/{{ .job_workflow_ref }}", - BuildSignerDigest: "job_workflow_sha", - RunnerEnvironment: "runner_environment", - SourceRepositoryURI: "{{ .url }}/{{ .repository }}", - SourceRepositoryDigest: "sha", - SourceRepositoryRef: "ref", - SourceRepositoryIdentifier: "repository_id", - SourceRepositoryOwnerURI: "{{ .url }}/{{ .repository_owner }}", - SourceRepositoryOwnerIdentifier: "repository_owner_id", - BuildConfigURI: "{{ .url }}/{{ .workflow_ref }}", - BuildConfigDigest: "workflow_sha", - BuildTrigger: "event_name", - RunInvocationURI: "{{ .url }}/{{ .repository }}/actions/runs/{{ .run_id }}/attempts/{{ .run_attempt }}", - SourceRepositoryVisibilityAtSigning: "repository_visibility", - }, - Defaults: map[string]string{ - "url": "https://github.com", - }, - SubjectAlternativeName: "{{.url}}/{{.job_workflow_ref}}", - }, - Token: token, - } - - err = principal.Embed(context.TODO(), &cert) + test.Principal.Token = token + err = test.Principal.Embed(context.TODO(), &cert) if err != nil { - if !test.WantErr { - t.Error(err) - } return - } else if test.WantErr { - t.Error("expected error") } for factName, fact := range test.WantFacts { t.Run(factName, func(t *testing.T) { From 31f8e11a9509d2517f2fa6cefb408e0bbcbce277 Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Thu, 20 Jun 2024 16:59:29 +0000 Subject: [PATCH 40/56] Adding option to check the required claim exist Signed-off-by: Javan lacerda --- pkg/identity/ciprovider/principal.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/identity/ciprovider/principal.go b/pkg/identity/ciprovider/principal.go index 5ccebc520..5bf1d5cda 100644 --- a/pkg/identity/ciprovider/principal.go +++ b/pkg/identity/ciprovider/principal.go @@ -55,7 +55,9 @@ func applyTemplateOrReplace(path string, data map[string]string, defaultData map if strings.Contains(path, "{{") { var doc bytes.Buffer - t := template.New("") + // This option forces to having the claim that is required + // for the template + t := template.New("").Option("missingkey=error") p, err := t.Parse(path) if err != nil { panic(err) From 8eff53250949a51af6b1ca5e9ec7de3a5d43e7bd Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Mon, 24 Jun 2024 13:43:39 +0000 Subject: [PATCH 41/56] omit subytype for json Signed-off-by: Javan lacerda --- config/fulcio-config.yaml | 47 +++++++++++++-------------------------- pkg/config/config.go | 2 +- 2 files changed, 16 insertions(+), 33 deletions(-) diff --git a/config/fulcio-config.yaml b/config/fulcio-config.yaml index 4dd5d23bd..c11af31b5 100644 --- a/config/fulcio-config.yaml +++ b/config/fulcio-config.yaml @@ -20,51 +20,43 @@ data: "https://accounts.google.com": { "IssuerURL": "https://accounts.google.com", "ClientID": "sigstore", - "Type": "email", - "SubType": "" + "Type": "email" }, "https://agent.buildkite.com": { "IssuerURL": "https://agent.buildkite.com", "ClientID": "sigstore", - "Type": "buildkite-job", - "SubType": "" + "Type": "buildkite-job" }, "https://allow.pub": { "IssuerURL": "https://allow.pub", "ClientID": "sigstore", "Type": "spiffe", - "SubType": "", "SPIFFETrustDomain": "allow.pub" }, "https://auth-staging.eclipse.org/realms/sigstore": { "IssuerURL": "https://auth-staging.eclipse.org/realms/sigstore", "ClientID": "sigstore", - "Type": "email", - "SubType": "" + "Type": "email" }, "https://auth.eclipse.org/auth/realms/sigstore": { "IssuerURL": "https://auth.eclipse.org/auth/realms/sigstore", "ClientID": "sigstore", - "Type": "email", - "SubType": "" + "Type": "email" }, "https://dev.gitlab.org": { "IssuerURL": "https://dev.gitlab.org", "ClientID": "sigstore", - "Type": "gitlab-pipeline", - "SubType": "" + "Type": "gitlab-pipeline" }, "https://gitlab.archlinux.org": { "IssuerURL": "https://gitlab.archlinux.org", "ClientID": "sigstore", - "Type": "gitlab-pipeline", - "SubType": "" + "Type": "gitlab-pipeline" }, "https://gitlab.com": { "IssuerURL": "https://gitlab.com", "ClientID": "sigstore", - "Type": "gitlab-pipeline", - "SubType": "" + "Type": "gitlab-pipeline" }, "https://issuer.enforce.dev": { "IssuerURL": "https://issuer.enforce.dev", @@ -75,53 +67,44 @@ data: "IssuerURL": "https://oauth2.sigstore.dev/auth", "ClientID": "sigstore", "Type": "email", - "SubType": "", "IssuerClaim": "$.federated_claims.connector_id" }, "https://oidc.codefresh.io": { "IssuerURL": "https://oidc.codefresh.io", "ClientID": "sigstore", - "Type": "codefresh-workflow", - "SubType": "" + "Type": "codefresh-workflow" }, "https://ops.gitlab.net": { "IssuerURL": "https://ops.gitlab.net", "ClientID": "sigstore", - "Type": "gitlab-pipeline", - "SubType": "" + "Type": "gitlab-pipeline" }, "https://token.actions.githubusercontent.com": { "IssuerURL": "https://token.actions.githubusercontent.com", "ClientID": "sigstore", - "Type": "github-workflow", - "SubType": "" + "Type": "github-workflow" } }, "MetaIssuers": { "https://*.oic.prod-aks.azure.com/*": { "ClientID": "sigstore", - "Type": "kubernetes", - "SubType": "" + "Type": "kubernetes" }, "https://container.googleapis.com/v1/projects/*/locations/*/clusters/*": { "ClientID": "sigstore", - "Type": "kubernetes", - "SubType": "" + "Type": "kubernetes" }, "https://oidc.eks.*.amazonaws.com/id/*": { "ClientID": "sigstore", - "Type": "kubernetes", - "SubType": "" + "Type": "kubernetes" }, "https://oidc.prod-aks.azure.com/*": { "ClientID": "sigstore", - "Type": "kubernetes", - "SubType": "" + "Type": "kubernetes" }, "https://token.actions.githubusercontent.com/*": { "ClientID": "sigstore", - "Type": "github-workflow", - "SubType": "" + "Type": "github-workflow" } }, "IssuersMetadata": null diff --git a/pkg/config/config.go b/pkg/config/config.go index 41cdc421b..020558df9 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -87,7 +87,7 @@ type OIDCIssuer struct { // certificate values are needed Type IssuerType `json:"Type" yaml:"type,omitempty"` // Issuers subtype - SubType string `json:"SubType" yaml:"sub-type,omitempty"` + SubType string `json:"SubType,omitempty" yaml:"sub-type,omitempty"` // Optional, if the issuer is in a different claim in the OIDC token IssuerClaim string `json:"IssuerClaim,omitempty" yaml:"issuer-claim,omitempty"` // The domain that must be present in the subject for 'uri' issuer types From b4800325bec8686c8591175e2f39f34c6363a42b Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Mon, 24 Jun 2024 18:28:10 +0000 Subject: [PATCH 42/56] rename issuers metadata Signed-off-by: Javan lacerda --- config/fulcio-config.yaml | 2 +- pkg/config/config.go | 31 +++++++++++++++-------- pkg/identity/ciprovider/issuer_test.go | 8 +++--- pkg/identity/ciprovider/principal.go | 4 +-- pkg/identity/ciprovider/principal_test.go | 26 +++++++++---------- 5 files changed, 40 insertions(+), 31 deletions(-) diff --git a/config/fulcio-config.yaml b/config/fulcio-config.yaml index c11af31b5..6619e9cd9 100644 --- a/config/fulcio-config.yaml +++ b/config/fulcio-config.yaml @@ -107,7 +107,7 @@ data: "Type": "github-workflow" } }, - "IssuersMetadata": null + "DefaultTemplateValues": null } server.yaml: |- host: 0.0.0.0 diff --git a/pkg/config/config.go b/pkg/config/config.go index 020558df9..a4eb9695f 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -63,8 +63,11 @@ type FulcioConfig struct { // * https://container.googleapis.com/v1/projects/mattmoor-credit/locations/us-west1-b/clusters/tenant-cluster MetaIssuers map[string]OIDCIssuer `json:"MetaIssuers,omitempty" yaml:"meta-issuers,omitempty"` - // defines the metadata for the issuers - IssuersMetadata map[string]IssuersMetadata + // It defines metadata to be used for the CIProvider identity provider principal. + // The CI provider has a generic logic for ci providers, this metadata is used + // to define the right behavior for each ci provider that is defined + // on the configuration file + CIIssuerMetadata map[string]DefaultTemplateValues // verifiers is a fixed mapping from our OIDCIssuers to their OIDC verifiers. verifiers map[string][]*verifierWithConfig @@ -72,9 +75,15 @@ type FulcioConfig struct { lru *lru.TwoQueueCache } -type IssuersMetadata struct { - Defaults map[string]string - ClaimsMapper certificate.Extensions +type DefaultTemplateValues struct { + // Default key and values that can be used for filling the templates + // If a key cannot be found on the token claims, the template will use the defaults + Defaults map[string]string + // It is the mapper from the id token claims to the Extensions. + // It expects strings with templates syntax https://pkg.go.dev/text/template + // or raw strings with claims keys to be replaced + ClaimsMapper certificate.Extensions + // A alternative name for the issuer subject SubjectAlternativeName string } @@ -86,8 +95,8 @@ type OIDCIssuer struct { // Used to determine the subject of the certificate and if additional // certificate values are needed Type IssuerType `json:"Type" yaml:"type,omitempty"` - // Issuers subtype - SubType string `json:"SubType,omitempty" yaml:"sub-type,omitempty"` + // Issuers CiProvider type + CIProvider string `json:"CIProvider,omitempty" yaml:"ci-provider,omitempty"` // Optional, if the issuer is in a different claim in the OIDC token IssuerClaim string `json:"IssuerClaim,omitempty" yaml:"issuer-claim,omitempty"` // The domain that must be present in the subject for 'uri' issuer types @@ -472,20 +481,20 @@ func LoadCiProvidersConfig(cfg *FulcioConfig) (*FulcioConfig, error) { fmt.Printf("Unmarshal: %v", err) } - cfg.IssuersMetadata = make(map[string]IssuersMetadata) + cfg.CIIssuerMetadata = make(map[string]DefaultTemplateValues) for k, v := range ciProvidersConfig.Providers { - cfg.IssuersMetadata[k] = IssuersMetadata{ + cfg.CIIssuerMetadata[k] = DefaultTemplateValues{ v.Defaults, v.Extensions, v.SubjectAlternativeName, } for _, issuer := range v.OIDCIssuers { - issuer.SubType = k + issuer.CIProvider = k issuer.Type = IssuerTypeCiProvider cfg.OIDCIssuers[issuer.IssuerURL] = issuer } for _, issuer := range v.MetaIssuers { - issuer.SubType = k + issuer.CIProvider = k issuer.Type = IssuerTypeCiProvider cfg.MetaIssuers[issuer.IssuerURL] = issuer } diff --git a/pkg/identity/ciprovider/issuer_test.go b/pkg/identity/ciprovider/issuer_test.go index 31fe91e3a..52753de94 100644 --- a/pkg/identity/ciprovider/issuer_test.go +++ b/pkg/identity/ciprovider/issuer_test.go @@ -75,10 +75,10 @@ func TestIssuer(t *testing.T) { OIDCIssuers := map[string]config.OIDCIssuer{ token.Issuer: { - IssuerURL: token.Issuer, - Type: config.IssuerTypeCiProvider, - SubType: "github-workflow", - ClientID: "sigstore", + IssuerURL: token.Issuer, + Type: config.IssuerTypeCiProvider, + CIProvider: "github-workflow", + ClientID: "sigstore", }, } cfg := &config.FulcioConfig{ diff --git a/pkg/identity/ciprovider/principal.go b/pkg/identity/ciprovider/principal.go index 5bf1d5cda..681091e17 100644 --- a/pkg/identity/ciprovider/principal.go +++ b/pkg/identity/ciprovider/principal.go @@ -73,7 +73,7 @@ func applyTemplateOrReplace(path string, data map[string]string, defaultData map type Config struct { Token *oidc.IDToken - Metadata config.IssuersMetadata + Metadata config.DefaultTemplateValues } func WorkflowPrincipalFromIDToken(ctx context.Context, token *oidc.IDToken) (identity.Principal, error) { @@ -85,7 +85,7 @@ func WorkflowPrincipalFromIDToken(ctx context.Context, token *oidc.IDToken) (ide return Config{ token, - cfg.IssuersMetadata[issuer.SubType], + cfg.CIIssuerMetadata[issuer.CIProvider], }, nil } diff --git a/pkg/identity/ciprovider/principal_test.go b/pkg/identity/ciprovider/principal_test.go index 88c7568f8..a973c033b 100644 --- a/pkg/identity/ciprovider/principal_test.go +++ b/pkg/identity/ciprovider/principal_test.go @@ -37,7 +37,7 @@ func TestWorkflowPrincipalFromIDToken(t *testing.T) { }{ `Github workflow challenge should have all Github workflow extensions and issuer set`: { ExpectedPrincipal: Config{ - Metadata: config.IssuersMetadata{ + Metadata: config.DefaultTemplateValues{ ClaimsMapper: certificate.Extensions{ Issuer: "issuer", GithubWorkflowTrigger: "event_name", @@ -101,17 +101,17 @@ func TestWorkflowPrincipalFromIDToken(t *testing.T) { OIDCIssuers := map[string]config.OIDCIssuer{ token.Issuer: { - IssuerURL: token.Issuer, - Type: config.IssuerTypeCiProvider, - SubType: "github-workflow", - ClientID: "sigstore", + IssuerURL: token.Issuer, + Type: config.IssuerTypeCiProvider, + CIProvider: "github-workflow", + ClientID: "sigstore", }, } - meta := make(map[string]config.IssuersMetadata) + meta := make(map[string]config.DefaultTemplateValues) meta["github-workflow"] = test.ExpectedPrincipal.Metadata cfg := &config.FulcioConfig{ - OIDCIssuers: OIDCIssuers, - IssuersMetadata: meta, + OIDCIssuers: OIDCIssuers, + CIIssuerMetadata: meta, } ctx = config.With(ctx, cfg) principal, err := WorkflowPrincipalFromIDToken(ctx, token) @@ -183,10 +183,10 @@ func TestName(t *testing.T) { OIDCIssuers := map[string]config.OIDCIssuer{ token.Issuer: { - IssuerURL: token.Issuer, - Type: config.IssuerTypeCiProvider, - SubType: "ci-provider", - ClientID: "sigstore", + IssuerURL: token.Issuer, + Type: config.IssuerTypeCiProvider, + CIProvider: "ci-provider", + ClientID: "sigstore", }, } cfg := &config.FulcioConfig{ @@ -236,7 +236,7 @@ func TestEmbed(t *testing.T) { `Certificate has correct source repository visibility extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 22}, "public"), }, Principal: Config{ - Metadata: config.IssuersMetadata{ + Metadata: config.DefaultTemplateValues{ ClaimsMapper: certificate.Extensions{ Issuer: "issuer", GithubWorkflowTrigger: "event_name", From 6558b317de3fdf0e8aa6de93ee68e30ca2e93875 Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Mon, 24 Jun 2024 18:59:38 +0000 Subject: [PATCH 43/56] update the templates data order to prioritize default data over claimed data Signed-off-by: Javan lacerda --- pkg/identity/ciprovider/principal.go | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/pkg/identity/ciprovider/principal.go b/pkg/identity/ciprovider/principal.go index 681091e17..8767a34e2 100644 --- a/pkg/identity/ciprovider/principal.go +++ b/pkg/identity/ciprovider/principal.go @@ -39,26 +39,27 @@ func claimsToString(claims map[string]interface{}) map[string]string { // It makes string interpolation for a given string by using the // templates syntax https://pkg.go.dev/text/template -func applyTemplateOrReplace(path string, data map[string]string, defaultData map[string]string) string { +func applyTemplateOrReplace(extValueTemplate string, tokenClaims map[string]string, defaultTemplateValues map[string]string) string { // Here we merge the data from was claimed by the id token with the // default data provided by the yaml file. - // The order here matter because we want to override the default data - // with the claimed data. + // The order here matter because we want to override the claimed data + // with the default data. + // The default data will have priority over the claimed data. mergedData := make(map[string]string) - for k, v := range defaultData { + for k, v := range tokenClaims { mergedData[k] = v } - for k, v := range data { + for k, v := range defaultTemplateValues { mergedData[k] = v } - if strings.Contains(path, "{{") { + if strings.Contains(extValueTemplate, "{{") { var doc bytes.Buffer // This option forces to having the claim that is required // for the template t := template.New("").Option("missingkey=error") - p, err := t.Parse(path) + p, err := t.Parse(extValueTemplate) if err != nil { panic(err) } @@ -68,7 +69,7 @@ func applyTemplateOrReplace(path string, data map[string]string, defaultData map } return doc.String() } - return mergedData[path] + return mergedData[extValueTemplate] } type Config struct { From 5c7ee8554b4a8a3a4c8d677811e2b7ed37a849a3 Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Mon, 24 Jun 2024 21:23:42 +0000 Subject: [PATCH 44/56] adding error handling for applyTemplateOrReplace Signed-off-by: Javan lacerda --- go.mod | 1 + go.sum | 2 + pkg/certificate/extensions.go | 38 ++++++------- pkg/config/config.go | 2 +- pkg/identity/ciprovider/principal.go | 66 +++++++++++------------ pkg/identity/ciprovider/principal_test.go | 6 +-- 6 files changed, 59 insertions(+), 56 deletions(-) diff --git a/go.mod b/go.mod index 8caa0c7bf..66c96ee25 100644 --- a/go.mod +++ b/go.mod @@ -82,6 +82,7 @@ require ( github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/chainguard-dev/slogctx v1.2.2 // indirect github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be // indirect + github.com/fatih/structs v1.1.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-jose/go-jose/v3 v3.0.3 // indirect github.com/go-logr/logr v1.4.1 // indirect diff --git a/go.sum b/go.sum index e17dcbadb..d11f6604d 100644 --- a/go.sum +++ b/go.sum @@ -106,6 +106,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +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.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= diff --git a/pkg/certificate/extensions.go b/pkg/certificate/extensions.go index e3e96fe41..c07670336 100644 --- a/pkg/certificate/extensions.go +++ b/pkg/certificate/extensions.go @@ -69,69 +69,69 @@ type Extensions struct { // Deprecated // Triggering event of the Github Workflow. Matches the `event_name` claim of ID // tokens from Github Actions - GithubWorkflowTrigger string `yaml:"github-workflow-trigger"` // OID 1.3.6.1.4.1.57264.1.2 + GithubWorkflowTrigger string `yaml:"github-workflow-trigger,omitempty"` // OID 1.3.6.1.4.1.57264.1.2 // Deprecated // SHA of git commit being built in Github Actions. Matches the `sha` claim of ID // tokens from Github Actions - GithubWorkflowSHA string `yaml:"github-workflow-sha"` // OID 1.3.6.1.4.1.57264.1.3 + GithubWorkflowSHA string `yaml:"github-workflow-sha,omitempty"` // OID 1.3.6.1.4.1.57264.1.3 // Deprecated // Name of Github Actions Workflow. Matches the `workflow` claim of the ID // tokens from Github Actions - GithubWorkflowName string `yaml:"github-workflow-name"` // OID 1.3.6.1.4.1.57264.1.4 + GithubWorkflowName string `yaml:"github-workflow-name,omitempty"` // OID 1.3.6.1.4.1.57264.1.4 // Deprecated // Repository of the Github Actions Workflow. Matches the `repository` claim of the ID // tokens from Github Actions - GithubWorkflowRepository string `yaml:"github-workflow-repository"` // OID 1.3.6.1.4.1.57264.1.5 + GithubWorkflowRepository string `yaml:"github-workflow-repository,omitempty"` // OID 1.3.6.1.4.1.57264.1.5 // Deprecated // Git Ref of the Github Actions Workflow. Matches the `ref` claim of the ID tokens // from Github Actions - GithubWorkflowRef string `yaml:"github-workflow-ref"` // 1.3.6.1.4.1.57264.1.6 + GithubWorkflowRef string `yaml:"github-workflow-ref,omitempty"` // 1.3.6.1.4.1.57264.1.6 // Reference to specific build instructions that are responsible for signing. - BuildSignerURI string `yaml:"build-signer-uri"` // 1.3.6.1.4.1.57264.1.9 + BuildSignerURI string `yaml:"build-signer-uri,omitempty"` // 1.3.6.1.4.1.57264.1.9 // Immutable reference to the specific version of the build instructions that is responsible for signing. - BuildSignerDigest string `yaml:"build-signer-digest"` // 1.3.6.1.4.1.57264.1.10 + BuildSignerDigest string `yaml:"build-signer-digest,omitempty"` // 1.3.6.1.4.1.57264.1.10 // Specifies whether the build took place in platform-hosted cloud infrastructure or customer/self-hosted infrastructure. - RunnerEnvironment string `yaml:"runner-environment"` // 1.3.6.1.4.1.57264.1.11 + RunnerEnvironment string `yaml:"runner-environment,omitempty"` // 1.3.6.1.4.1.57264.1.11 // Source repository URL that the build was based on. - SourceRepositoryURI string `yaml:"source-repository-uri"` // 1.3.6.1.4.1.57264.1.12 + SourceRepositoryURI string `yaml:"source-repository-uri,omitempty"` // 1.3.6.1.4.1.57264.1.12 // Immutable reference to a specific version of the source code that the build was based upon. - SourceRepositoryDigest string `yaml:"source-repository-digest"` // 1.3.6.1.4.1.57264.1.13 + SourceRepositoryDigest string `yaml:"source-repository-digest,omitempty"` // 1.3.6.1.4.1.57264.1.13 // Source Repository Ref that the build run was based upon. - SourceRepositoryRef string `yaml:"source-repository-ref"` // 1.3.6.1.4.1.57264.1.14 + SourceRepositoryRef string `yaml:"source-repository-ref,omitempty"` // 1.3.6.1.4.1.57264.1.14 // Immutable identifier for the source repository the workflow was based upon. - SourceRepositoryIdentifier string `yaml:"source-repository-identifier"` // 1.3.6.1.4.1.57264.1.15 + SourceRepositoryIdentifier string `yaml:"source-repository-identifier,omitempty"` // 1.3.6.1.4.1.57264.1.15 // Source repository owner URL of the owner of the source repository that the build was based on. - SourceRepositoryOwnerURI string `yaml:"source-repository-owner-uri"` // 1.3.6.1.4.1.57264.1.16 + SourceRepositoryOwnerURI string `yaml:"source-repository-owner-uri,omitempty"` // 1.3.6.1.4.1.57264.1.16 // Immutable identifier for the owner of the source repository that the workflow was based upon. - SourceRepositoryOwnerIdentifier string `yaml:"source-repository-owner-identifier"` // 1.3.6.1.4.1.57264.1.17 + SourceRepositoryOwnerIdentifier string `yaml:"source-repository-owner-identifier,omitempty"` // 1.3.6.1.4.1.57264.1.17 // Build Config URL to the top-level/initiating build instructions. - BuildConfigURI string `yaml:"build-config-uri"` // 1.3.6.1.4.1.57264.1.18 + BuildConfigURI string `yaml:"build-config-uri,omitempty"` // 1.3.6.1.4.1.57264.1.18 // Immutable reference to the specific version of the top-level/initiating build instructions. - BuildConfigDigest string `yaml:"build-config-digest"` // 1.3.6.1.4.1.57264.1.19 + BuildConfigDigest string `yaml:"build-config-digest,omitempty"` // 1.3.6.1.4.1.57264.1.19 // Event or action that initiated the build. - BuildTrigger string `yaml:"build-trigger"` // 1.3.6.1.4.1.57264.1.20 + BuildTrigger string `yaml:"build-trigger,omitempty"` // 1.3.6.1.4.1.57264.1.20 // Run Invocation URL to uniquely identify the build execution. - RunInvocationURI string `yaml:"run-invocation-uri"` // 1.3.6.1.4.1.57264.1.21 + RunInvocationURI string `yaml:"run-invocation-uri,omitempty"` // 1.3.6.1.4.1.57264.1.21 // Source repository visibility at the time of signing the certificate. - SourceRepositoryVisibilityAtSigning string `yaml:"source-repository-visibility-at-signing"` // 1.3.6.1.4.1.57264.1.22 + SourceRepositoryVisibilityAtSigning string `yaml:"source-repository-visibility-at-signing,omitempty"` // 1.3.6.1.4.1.57264.1.22 } func (e Extensions) Render() ([]pkix.Extension, error) { diff --git a/pkg/config/config.go b/pkg/config/config.go index a4eb9695f..027476eb5 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -82,7 +82,7 @@ type DefaultTemplateValues struct { // It is the mapper from the id token claims to the Extensions. // It expects strings with templates syntax https://pkg.go.dev/text/template // or raw strings with claims keys to be replaced - ClaimsMapper certificate.Extensions + ClaimsMap certificate.Extensions // A alternative name for the issuer subject SubjectAlternativeName string } diff --git a/pkg/identity/ciprovider/principal.go b/pkg/identity/ciprovider/principal.go index 8767a34e2..7bfaa168d 100644 --- a/pkg/identity/ciprovider/principal.go +++ b/pkg/identity/ciprovider/principal.go @@ -24,12 +24,14 @@ import ( "strings" "github.com/coreos/go-oidc/v3/oidc" + "github.com/fatih/structs" + "github.com/mitchellh/mapstructure" "github.com/sigstore/fulcio/pkg/certificate" "github.com/sigstore/fulcio/pkg/config" "github.com/sigstore/fulcio/pkg/identity" ) -func claimsToString(claims map[string]interface{}) map[string]string { +func mapValuesToString(claims map[string]interface{}) map[string]string { stringClaims := make(map[string]string) for k, v := range claims { stringClaims[k] = v.(string) @@ -39,7 +41,7 @@ func claimsToString(claims map[string]interface{}) map[string]string { // It makes string interpolation for a given string by using the // templates syntax https://pkg.go.dev/text/template -func applyTemplateOrReplace(extValueTemplate string, tokenClaims map[string]string, defaultTemplateValues map[string]string) string { +func applyTemplateOrReplace(extValueTemplate string, tokenClaims map[string]string, defaultTemplateValues map[string]string) (string, error) { // Here we merge the data from was claimed by the id token with the // default data provided by the yaml file. @@ -61,15 +63,19 @@ func applyTemplateOrReplace(extValueTemplate string, tokenClaims map[string]stri t := template.New("").Option("missingkey=error") p, err := t.Parse(extValueTemplate) if err != nil { - panic(err) + return "", err } err = p.Execute(&doc, mergedData) if err != nil { - panic(err) + return "", err } - return doc.String() + return doc.String(), nil } - return mergedData[extValueTemplate] + claimValue, ok := mergedData[extValueTemplate] + if !ok { + return "", fmt.Errorf("value <%s> not present in either claims or defaults", extValueTemplate) + } + return claimValue, nil } type Config struct { @@ -96,46 +102,40 @@ func (p Config) Name(_ context.Context) string { func (p Config) Embed(_ context.Context, cert *x509.Certificate) error { - e := p.Metadata.ClaimsMapper + e := p.Metadata.ClaimsMap defaults := p.Metadata.Defaults var rawClaims map[string]interface{} if err := p.Token.Claims(&rawClaims); err != nil { return err } - claims := claimsToString(rawClaims) + claims := mapValuesToString(rawClaims) - subjectAlternativeNameURL, err := url.Parse(applyTemplateOrReplace(p.Metadata.SubjectAlternativeName, claims, defaults)) + subjectAlternativeName, err := applyTemplateOrReplace(p.Metadata.SubjectAlternativeName, claims, defaults) if err != nil { - panic(err) + return err + } + subjectAlternativeNameURL, err := url.Parse(subjectAlternativeName) + if err != nil { + return err } uris := []*url.URL{subjectAlternativeNameURL} // Set workflow ref URL to SubjectAlternativeName on certificate cert.URIs = uris - + mapExtensionsForTemplate := mapValuesToString(structs.Map(e)) + for k, v := range mapExtensionsForTemplate { + mapExtensionsForTemplate[k], err = applyTemplateOrReplace(v, claims, defaults) + if err != nil { + return err + } + } + ext := &certificate.Extensions{} + err = mapstructure.Decode(mapExtensionsForTemplate, &ext) + if err != nil { + return err + } // Embed additional information into custom extensions - cert.ExtraExtensions, err = certificate.Extensions{ - Issuer: applyTemplateOrReplace(e.Issuer, claims, defaults), - GithubWorkflowTrigger: applyTemplateOrReplace(e.GithubWorkflowTrigger, claims, defaults), - GithubWorkflowSHA: applyTemplateOrReplace(e.GithubWorkflowSHA, claims, defaults), - GithubWorkflowName: applyTemplateOrReplace(e.GithubWorkflowName, claims, defaults), - GithubWorkflowRepository: applyTemplateOrReplace(e.GithubWorkflowRepository, claims, defaults), - GithubWorkflowRef: applyTemplateOrReplace(e.GithubWorkflowRef, claims, defaults), - BuildSignerURI: applyTemplateOrReplace(e.BuildSignerURI, claims, defaults), - BuildConfigDigest: applyTemplateOrReplace(e.BuildConfigDigest, claims, defaults), - RunnerEnvironment: applyTemplateOrReplace(e.RunnerEnvironment, claims, defaults), - SourceRepositoryURI: applyTemplateOrReplace(e.SourceRepositoryURI, claims, defaults), - SourceRepositoryDigest: applyTemplateOrReplace(e.SourceRepositoryDigest, claims, defaults), - SourceRepositoryRef: applyTemplateOrReplace(e.SourceRepositoryRef, claims, defaults), - SourceRepositoryIdentifier: applyTemplateOrReplace(e.SourceRepositoryIdentifier, claims, defaults), - SourceRepositoryOwnerURI: applyTemplateOrReplace(e.SourceRepositoryOwnerURI, claims, defaults), - SourceRepositoryOwnerIdentifier: applyTemplateOrReplace(e.SourceRepositoryOwnerIdentifier, claims, defaults), - BuildConfigURI: applyTemplateOrReplace(e.BuildConfigURI, claims, defaults), - BuildSignerDigest: applyTemplateOrReplace(e.BuildSignerDigest, claims, defaults), - BuildTrigger: applyTemplateOrReplace(e.BuildTrigger, claims, defaults), - RunInvocationURI: applyTemplateOrReplace(e.RunInvocationURI, claims, defaults), - SourceRepositoryVisibilityAtSigning: applyTemplateOrReplace(e.SourceRepositoryVisibilityAtSigning, claims, defaults), - }.Render() + cert.ExtraExtensions, err = ext.Render() if err != nil { return err } diff --git a/pkg/identity/ciprovider/principal_test.go b/pkg/identity/ciprovider/principal_test.go index a973c033b..29e9d1b4a 100644 --- a/pkg/identity/ciprovider/principal_test.go +++ b/pkg/identity/ciprovider/principal_test.go @@ -38,7 +38,7 @@ func TestWorkflowPrincipalFromIDToken(t *testing.T) { `Github workflow challenge should have all Github workflow extensions and issuer set`: { ExpectedPrincipal: Config{ Metadata: config.DefaultTemplateValues{ - ClaimsMapper: certificate.Extensions{ + ClaimsMap: certificate.Extensions{ Issuer: "issuer", GithubWorkflowTrigger: "event_name", GithubWorkflowSHA: "sha", @@ -237,7 +237,7 @@ func TestEmbed(t *testing.T) { }, Principal: Config{ Metadata: config.DefaultTemplateValues{ - ClaimsMapper: certificate.Extensions{ + ClaimsMap: certificate.Extensions{ Issuer: "issuer", GithubWorkflowTrigger: "event_name", GithubWorkflowSHA: "sha", @@ -299,7 +299,7 @@ func TestEmbed(t *testing.T) { test.Principal.Token = token err = test.Principal.Embed(context.TODO(), &cert) if err != nil { - return + t.Error(err) } for factName, fact := range test.WantFacts { t.Run(factName, func(t *testing.T) { From 54c4e6dac820fb2414a40f0ffa95c9bfd8acafcd Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Tue, 25 Jun 2024 14:11:02 +0000 Subject: [PATCH 45/56] fixes and refactoring Signed-off-by: Javan lacerda --- pkg/challenges/challenges.go | 2 +- pkg/config/config.go | 22 +++++------- pkg/config/config_test.go | 4 +-- pkg/identity/ciprovider/issuer_test.go | 2 +- pkg/identity/ciprovider/principal.go | 44 ++++++++++++----------- pkg/identity/ciprovider/principal_test.go | 26 +++++++------- pkg/server/issuer_pool.go | 2 +- 7 files changed, 51 insertions(+), 51 deletions(-) diff --git a/pkg/challenges/challenges.go b/pkg/challenges/challenges.go index b80cdc76b..143fdaab9 100644 --- a/pkg/challenges/challenges.go +++ b/pkg/challenges/challenges.go @@ -76,7 +76,7 @@ func PrincipalFromIDToken(ctx context.Context, tok *oidc.IDToken) (identity.Prin principal, err = uri.PrincipalFromIDToken(ctx, tok) case config.IssuerTypeUsername: principal, err = username.PrincipalFromIDToken(ctx, tok) - case config.IssuerTypeCiProvider: + case config.IssuerTypeCIProvider: principal, err = ciprovider.WorkflowPrincipalFromIDToken(ctx, tok) default: return nil, fmt.Errorf("unsupported issuer: %s", iss.Type) diff --git a/pkg/config/config.go b/pkg/config/config.go index 027476eb5..e2c43c430 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -79,12 +79,13 @@ type DefaultTemplateValues struct { // Default key and values that can be used for filling the templates // If a key cannot be found on the token claims, the template will use the defaults Defaults map[string]string - // It is the mapper from the id token claims to the Extensions. + // It is a Extensions version which the values are template strigs. // It expects strings with templates syntax https://pkg.go.dev/text/template // or raw strings with claims keys to be replaced - ClaimsMap certificate.Extensions + ClaimsTemplates certificate.Extensions // A alternative name for the issuer subject - SubjectAlternativeName string + // It's typically the same value as Build Signer URI + SubjectAlternativeNameTemplate string } type OIDCIssuer struct { @@ -307,7 +308,7 @@ const ( IssuerTypeSpiffe = "spiffe" IssuerTypeURI = "uri" IssuerTypeUsername = "username" - IssuerTypeCiProvider = "ci-provider" + IssuerTypeCIProvider = "ci-provider" ) func parseConfig(b []byte) (cfg *FulcioConfig, err error) { @@ -490,12 +491,12 @@ func LoadCiProvidersConfig(cfg *FulcioConfig) (*FulcioConfig, error) { } for _, issuer := range v.OIDCIssuers { issuer.CIProvider = k - issuer.Type = IssuerTypeCiProvider + issuer.Type = IssuerTypeCIProvider cfg.OIDCIssuers[issuer.IssuerURL] = issuer } for _, issuer := range v.MetaIssuers { issuer.CIProvider = k - issuer.Type = IssuerTypeCiProvider + issuer.Type = IssuerTypeCIProvider cfg.MetaIssuers[issuer.IssuerURL] = issuer } } @@ -516,12 +517,7 @@ func Load(configPath string) (*FulcioConfig, error) { if err != nil { return nil, fmt.Errorf("read file: %w", err) } - fulcioConfig, err := Read(b) - if err != nil { - return fulcioConfig, err - } - - return fulcioConfig, err + return Read(b) } // Read parses the bytes of a config @@ -591,7 +587,7 @@ func issuerToChallengeClaim(issType IssuerType, challengeClaim string) string { return "email" case IssuerTypeGithubWorkflow: return "sub" - case IssuerTypeCiProvider: + case IssuerTypeCIProvider: return "sub" case IssuerTypeCodefreshWorkflow: return "sub" diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index c5473a098..390bd6f6b 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -492,8 +492,8 @@ func Test_issuerToChallengeClaim(t *testing.T) { if claim := issuerToChallengeClaim(IssuerTypeGithubWorkflow, ""); claim != "sub" { t.Fatalf("expected sub subject claim for GitHub issuer, got %s", claim) } - if claim := issuerToChallengeClaim(IssuerTypeCiProvider, ""); claim != "sub" { - t.Fatalf("expected sub subject claim for GitHub issuer, got %s", claim) + if claim := issuerToChallengeClaim(IssuerTypeCIProvider, ""); claim != "sub" { + t.Fatalf("expected sub subject claim for CI issuer, got %s", claim) } if claim := issuerToChallengeClaim(IssuerTypeGitLabPipeline, ""); claim != "sub" { t.Fatalf("expected sub subject claim for GitLab issuer, got %s", claim) diff --git a/pkg/identity/ciprovider/issuer_test.go b/pkg/identity/ciprovider/issuer_test.go index 52753de94..1d8e605e3 100644 --- a/pkg/identity/ciprovider/issuer_test.go +++ b/pkg/identity/ciprovider/issuer_test.go @@ -76,7 +76,7 @@ func TestIssuer(t *testing.T) { map[string]config.OIDCIssuer{ token.Issuer: { IssuerURL: token.Issuer, - Type: config.IssuerTypeCiProvider, + Type: config.IssuerTypeCIProvider, CIProvider: "github-workflow", ClientID: "sigstore", }, diff --git a/pkg/identity/ciprovider/principal.go b/pkg/identity/ciprovider/principal.go index 7bfaa168d..7aa35f91b 100644 --- a/pkg/identity/ciprovider/principal.go +++ b/pkg/identity/ciprovider/principal.go @@ -39,6 +39,14 @@ func mapValuesToString(claims map[string]interface{}) map[string]string { return stringClaims } +func getTokenClaims(token *oidc.IDToken) (map[string]string, error) { + var tokenClaims map[string]interface{} + if err := token.Claims(&tokenClaims); err != nil { + return nil, err + } + return mapValuesToString(tokenClaims), nil +} + // It makes string interpolation for a given string by using the // templates syntax https://pkg.go.dev/text/template func applyTemplateOrReplace(extValueTemplate string, tokenClaims map[string]string, defaultTemplateValues map[string]string) (string, error) { @@ -78,49 +86,45 @@ func applyTemplateOrReplace(extValueTemplate string, tokenClaims map[string]stri return claimValue, nil } -type Config struct { - Token *oidc.IDToken - Metadata config.DefaultTemplateValues +type ciPrincipal struct { + Token *oidc.IDToken + ClaimsMetadata config.DefaultTemplateValues } func WorkflowPrincipalFromIDToken(ctx context.Context, token *oidc.IDToken) (identity.Principal, error) { cfg := config.FromContext(ctx) - issuer, ok := cfg.GetIssuer(token.Issuer) + issuerCfg, ok := cfg.GetIssuer(token.Issuer) if !ok { return nil, fmt.Errorf("configuration can not be loaded for issuer %v", token.Issuer) } - return Config{ + return ciPrincipal{ token, - cfg.CIIssuerMetadata[issuer.CIProvider], + cfg.CIIssuerMetadata[issuerCfg.CIProvider], }, nil } -func (p Config) Name(_ context.Context) string { - return p.Token.Subject +func (principal ciPrincipal) Name(_ context.Context) string { + return principal.Token.Subject } -func (p Config) Embed(_ context.Context, cert *x509.Certificate) error { +func (principal ciPrincipal) Embed(_ context.Context, cert *x509.Certificate) error { - e := p.Metadata.ClaimsMap - defaults := p.Metadata.Defaults - - var rawClaims map[string]interface{} - if err := p.Token.Claims(&rawClaims); err != nil { + e := principal.ClaimsMetadata.ClaimsTemplates + defaults := principal.ClaimsMetadata.Defaults + claims, err := getTokenClaims(principal.Token) + if err != nil { return err } - claims := mapValuesToString(rawClaims) - - subjectAlternativeName, err := applyTemplateOrReplace(p.Metadata.SubjectAlternativeName, claims, defaults) + subjectAlternativeName, err := applyTemplateOrReplace(principal.ClaimsMetadata.SubjectAlternativeNameTemplate, claims, defaults) if err != nil { return err } - subjectAlternativeNameURL, err := url.Parse(subjectAlternativeName) + sanURL, err := url.Parse(subjectAlternativeName) if err != nil { return err } - uris := []*url.URL{subjectAlternativeNameURL} - // Set workflow ref URL to SubjectAlternativeName on certificate + uris := []*url.URL{sanURL} cert.URIs = uris mapExtensionsForTemplate := mapValuesToString(structs.Map(e)) for k, v := range mapExtensionsForTemplate { diff --git a/pkg/identity/ciprovider/principal_test.go b/pkg/identity/ciprovider/principal_test.go index 29e9d1b4a..ea3e3e24e 100644 --- a/pkg/identity/ciprovider/principal_test.go +++ b/pkg/identity/ciprovider/principal_test.go @@ -33,12 +33,12 @@ import ( func TestWorkflowPrincipalFromIDToken(t *testing.T) { tests := map[string]struct { - ExpectedPrincipal Config + ExpectedPrincipal ciPrincipal }{ `Github workflow challenge should have all Github workflow extensions and issuer set`: { - ExpectedPrincipal: Config{ - Metadata: config.DefaultTemplateValues{ - ClaimsMap: certificate.Extensions{ + ExpectedPrincipal: ciPrincipal{ + ClaimsMetadata: config.DefaultTemplateValues{ + ClaimsTemplates: certificate.Extensions{ Issuer: "issuer", GithubWorkflowTrigger: "event_name", GithubWorkflowSHA: "sha", @@ -63,7 +63,7 @@ func TestWorkflowPrincipalFromIDToken(t *testing.T) { Defaults: map[string]string{ "url": "https://github.com", }, - SubjectAlternativeName: "{{.url}}/{{.job_workflow_ref}}", + SubjectAlternativeNameTemplate: "{{.url}}/{{.job_workflow_ref}}", }, }, }, @@ -102,13 +102,13 @@ func TestWorkflowPrincipalFromIDToken(t *testing.T) { map[string]config.OIDCIssuer{ token.Issuer: { IssuerURL: token.Issuer, - Type: config.IssuerTypeCiProvider, + Type: config.IssuerTypeCIProvider, CIProvider: "github-workflow", ClientID: "sigstore", }, } meta := make(map[string]config.DefaultTemplateValues) - meta["github-workflow"] = test.ExpectedPrincipal.Metadata + meta["github-workflow"] = test.ExpectedPrincipal.ClaimsMetadata cfg := &config.FulcioConfig{ OIDCIssuers: OIDCIssuers, CIIssuerMetadata: meta, @@ -184,7 +184,7 @@ func TestName(t *testing.T) { map[string]config.OIDCIssuer{ token.Issuer: { IssuerURL: token.Issuer, - Type: config.IssuerTypeCiProvider, + Type: config.IssuerTypeCIProvider, CIProvider: "ci-provider", ClientID: "sigstore", }, @@ -209,7 +209,7 @@ func TestName(t *testing.T) { func TestEmbed(t *testing.T) { tests := map[string]struct { WantFacts map[string]func(x509.Certificate) error - Principal Config + Principal ciPrincipal }{ `Github workflow challenge should have all Github workflow extensions and issuer set`: { WantFacts: map[string]func(x509.Certificate) error{ @@ -235,9 +235,9 @@ func TestEmbed(t *testing.T) { `Certificate has correct run invocation ID extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 21}, "https://github.com/repository/actions/runs/runID/attempts/runAttempt"), `Certificate has correct source repository visibility extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 22}, "public"), }, - Principal: Config{ - Metadata: config.DefaultTemplateValues{ - ClaimsMap: certificate.Extensions{ + Principal: ciPrincipal{ + ClaimsMetadata: config.DefaultTemplateValues{ + ClaimsTemplates: certificate.Extensions{ Issuer: "issuer", GithubWorkflowTrigger: "event_name", GithubWorkflowSHA: "sha", @@ -262,7 +262,7 @@ func TestEmbed(t *testing.T) { Defaults: map[string]string{ "url": "https://github.com", }, - SubjectAlternativeName: "{{.url}}/{{.job_workflow_ref}}", + SubjectAlternativeNameTemplate: "{{.url}}/{{.job_workflow_ref}}", }, }, }, diff --git a/pkg/server/issuer_pool.go b/pkg/server/issuer_pool.go index 25f442cf4..61e05fa34 100644 --- a/pkg/server/issuer_pool.go +++ b/pkg/server/issuer_pool.go @@ -58,7 +58,7 @@ func getIssuer(meta string, i config.OIDCIssuer) identity.Issuer { return email.Issuer(issuerURL) case config.IssuerTypeGithubWorkflow: return github.Issuer(issuerURL) - case config.IssuerTypeCiProvider: + case config.IssuerTypeCIProvider: return ciprovider.Issuer(issuerURL) case config.IssuerTypeGitLabPipeline: return gitlabcom.Issuer(issuerURL) From 8f54c6a3f60c8fc70e07f84fe349ee16ecaef7f5 Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Tue, 25 Jun 2024 15:18:22 +0000 Subject: [PATCH 46/56] set token.issuer as extension issuer Signed-off-by: Javan lacerda --- pkg/identity/ciprovider/principal.go | 27 ++++++++++++++--------- pkg/identity/ciprovider/principal_test.go | 3 +-- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/pkg/identity/ciprovider/principal.go b/pkg/identity/ciprovider/principal.go index 7aa35f91b..86e8494bd 100644 --- a/pkg/identity/ciprovider/principal.go +++ b/pkg/identity/ciprovider/principal.go @@ -32,11 +32,11 @@ import ( ) func mapValuesToString(claims map[string]interface{}) map[string]string { - stringClaims := make(map[string]string) + newMap := make(map[string]string) for k, v := range claims { - stringClaims[k] = v.(string) + newMap[k] = fmt.Sprintf("%v", v) } - return stringClaims + return newMap } func getTokenClaims(token *oidc.IDToken) (map[string]string, error) { @@ -110,7 +110,7 @@ func (principal ciPrincipal) Name(_ context.Context) string { func (principal ciPrincipal) Embed(_ context.Context, cert *x509.Certificate) error { - e := principal.ClaimsMetadata.ClaimsTemplates + claimsTemplates := principal.ClaimsMetadata.ClaimsTemplates defaults := principal.ClaimsMetadata.Defaults claims, err := getTokenClaims(principal.Token) if err != nil { @@ -126,23 +126,30 @@ func (principal ciPrincipal) Embed(_ context.Context, cert *x509.Certificate) er } uris := []*url.URL{sanURL} cert.URIs = uris - mapExtensionsForTemplate := mapValuesToString(structs.Map(e)) + mapExtensionsForTemplate := mapValuesToString(structs.Map(claimsTemplates)) for k, v := range mapExtensionsForTemplate { - mapExtensionsForTemplate[k], err = applyTemplateOrReplace(v, claims, defaults) - if err != nil { - return err + // It avoids to try applying template or replace for a empty string. + if v != "" { + mapExtensionsForTemplate[k], err = applyTemplateOrReplace(v, claims, defaults) + if err != nil { + return err + } } } - ext := &certificate.Extensions{} + ext := &certificate.Extensions{ + Issuer: principal.Token.Issuer, + } err = mapstructure.Decode(mapExtensionsForTemplate, &ext) if err != nil { return err } + // Guarantees to set the extension issuer as the token issuer + // regardless of whether this field has been set before + ext.Issuer = principal.Token.Issuer // Embed additional information into custom extensions cert.ExtraExtensions, err = ext.Render() if err != nil { return err } - return nil } diff --git a/pkg/identity/ciprovider/principal_test.go b/pkg/identity/ciprovider/principal_test.go index ea3e3e24e..bc5c19778 100644 --- a/pkg/identity/ciprovider/principal_test.go +++ b/pkg/identity/ciprovider/principal_test.go @@ -238,7 +238,6 @@ func TestEmbed(t *testing.T) { Principal: ciPrincipal{ ClaimsMetadata: config.DefaultTemplateValues{ ClaimsTemplates: certificate.Extensions{ - Issuer: "issuer", GithubWorkflowTrigger: "event_name", GithubWorkflowSHA: "sha", GithubWorkflowName: "workflow", @@ -272,7 +271,6 @@ func TestEmbed(t *testing.T) { t.Run(name, func(t *testing.T) { var cert x509.Certificate claims, err := json.Marshal(map[string]interface{}{ - "issuer": "https://token.actions.githubusercontent.com", "event_name": "trigger", "sha": "sha", "workflow": "workflowname", @@ -294,6 +292,7 @@ func TestEmbed(t *testing.T) { t.Fatal(err) } token := &oidc.IDToken{} + token.Issuer = "https://token.actions.githubusercontent.com" withClaims(token, claims) test.Principal.Token = token From a35b6ccdf77c2f3614f253860c0a258a0633f463 Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Tue, 25 Jun 2024 20:47:30 +0000 Subject: [PATCH 47/56] remove load for providers, merge with fulcio config Signed-off-by: Javan lacerda --- cmd/app/serve.go | 4 ---- config/fulcio-config.yaml | 2 +- pkg/config/config.go | 48 --------------------------------------- 3 files changed, 1 insertion(+), 53 deletions(-) diff --git a/cmd/app/serve.go b/cmd/app/serve.go index a20918efb..de0b28194 100644 --- a/cmd/app/serve.go +++ b/cmd/app/serve.go @@ -214,10 +214,6 @@ func runServeCmd(cmd *cobra.Command, args []string) { //nolint: revive if err != nil { log.Logger.Fatalf("error loading --config-path=%s: %v", cp, err) } - cfg, err = config.LoadCiProvidersConfig(cfg) - if err != nil { - log.Logger.Fatalf("error loading CiProviderConfig: %v", err) - } var baseca certauth.CertificateAuthority switch viper.GetString("ca") { diff --git a/config/fulcio-config.yaml b/config/fulcio-config.yaml index 6619e9cd9..9df7c7cbb 100644 --- a/config/fulcio-config.yaml +++ b/config/fulcio-config.yaml @@ -107,7 +107,7 @@ data: "Type": "github-workflow" } }, - "DefaultTemplateValues": null + "CIIssuerMetadata": null } server.yaml: |- host: 0.0.0.0 diff --git a/pkg/config/config.go b/pkg/config/config.go index e2c43c430..de0927946 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -24,10 +24,8 @@ import ( "net/http" "net/url" "os" - "path/filepath" "reflect" "regexp" - "runtime" "strings" "time" @@ -457,52 +455,6 @@ func FromContext(ctx context.Context) *FulcioConfig { return untyped.(*FulcioConfig) } -type CiProvidersConfig struct { - Providers map[string]Provider -} -type Provider struct { - Extensions certificate.Extensions `yaml:"extensions,omitempty"` - SubjectAlternativeName string `yaml:"subject-alternative-name,omitempty"` - Defaults map[string]string `yaml:"defaults,omitempty"` - OIDCIssuers []OIDCIssuer `yaml:"oidc-issuers,omitempty"` - MetaIssuers []OIDCIssuer `yaml:"meta-issuers,omitempty"` -} - -func LoadCiProvidersConfig(cfg *FulcioConfig) (*FulcioConfig, error) { - var ciProvidersConfig CiProvidersConfig - _, path, _, _ := runtime.Caller(0) - basepath := filepath.Dir(path) - providersConfigFile, err := os.ReadFile(basepath + "/providers_config.yaml") - - if err != nil { - fmt.Printf("yamlFile.Get err #%v ", err) - } - err = yaml.Unmarshal(providersConfigFile, &ciProvidersConfig) - if err != nil { - fmt.Printf("Unmarshal: %v", err) - } - - cfg.CIIssuerMetadata = make(map[string]DefaultTemplateValues) - for k, v := range ciProvidersConfig.Providers { - cfg.CIIssuerMetadata[k] = DefaultTemplateValues{ - v.Defaults, - v.Extensions, - v.SubjectAlternativeName, - } - for _, issuer := range v.OIDCIssuers { - issuer.CIProvider = k - issuer.Type = IssuerTypeCIProvider - cfg.OIDCIssuers[issuer.IssuerURL] = issuer - } - for _, issuer := range v.MetaIssuers { - issuer.CIProvider = k - issuer.Type = IssuerTypeCIProvider - cfg.MetaIssuers[issuer.IssuerURL] = issuer - } - } - return cfg, err -} - // Load a config from disk, or use defaults func Load(configPath string) (*FulcioConfig, error) { if _, err := os.Stat(configPath); os.IsNotExist(err) { From 66a07a03b044d6af44aa0f362d2a926e3bce5dbd Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Wed, 26 Jun 2024 12:58:41 +0000 Subject: [PATCH 48/56] remove providers config file Signed-off-by: Javan lacerda --- go.mod | 4 ++-- pkg/config/providers_config.yaml | 15 --------------- 2 files changed, 2 insertions(+), 17 deletions(-) delete mode 100644 pkg/config/providers_config.yaml diff --git a/go.mod b/go.mod index 66c96ee25..b46686650 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/ThalesIgnite/crypto11 v1.2.5 github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d github.com/coreos/go-oidc/v3 v3.10.0 + github.com/fatih/structs v1.1.0 github.com/fsnotify/fsnotify v1.7.0 github.com/go-jose/go-jose/v4 v4.0.2 github.com/goadesign/goa v2.2.5+incompatible @@ -22,6 +23,7 @@ require ( github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 github.com/hashicorp/golang-lru v1.0.2 github.com/magiconair/properties v1.8.7 + github.com/mitchellh/mapstructure v1.5.0 github.com/prometheus/client_golang v1.19.1 github.com/prometheus/client_model v0.6.1 github.com/prometheus/common v0.54.0 @@ -82,7 +84,6 @@ require ( github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/chainguard-dev/slogctx v1.2.2 // indirect github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be // indirect - github.com/fatih/structs v1.1.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-jose/go-jose/v3 v3.0.3 // indirect github.com/go-logr/logr v1.4.1 // indirect @@ -111,7 +112,6 @@ require ( github.com/letsencrypt/boulder v0.0.0-20230907030200-6d76a0f91e1e // indirect github.com/miekg/pkcs11 v1.1.1 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect diff --git a/pkg/config/providers_config.yaml b/pkg/config/providers_config.yaml deleted file mode 100644 index 3165b449e..000000000 --- a/pkg/config/providers_config.yaml +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright 2024 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. - -providers: From e7cd08fb4cc43802f6f98aabf880b84dc9f364f8 Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Wed, 26 Jun 2024 16:46:33 +0000 Subject: [PATCH 49/56] adding check for parsing templates Signed-off-by: Javan lacerda --- pkg/config/config.go | 36 +++++++++++++++++++++++- pkg/config/config_network_test.go | 42 ++++++++++++++++++++++++++++ pkg/identity/ciprovider/principal.go | 2 ++ 3 files changed, 79 insertions(+), 1 deletion(-) diff --git a/pkg/config/config.go b/pkg/config/config.go index de0927946..d80b3fb7f 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -21,6 +21,7 @@ import ( "encoding/json" "errors" "fmt" + "html/template" "net/http" "net/url" "os" @@ -30,6 +31,7 @@ import ( "time" "github.com/coreos/go-oidc/v3/oidc" + "github.com/fatih/structs" lru "github.com/hashicorp/golang-lru" "github.com/sigstore/fulcio/pkg/certificate" fulciogrpc "github.com/sigstore/fulcio/pkg/generated/protobuf" @@ -455,6 +457,32 @@ func FromContext(ctx context.Context) *FulcioConfig { return untyped.(*FulcioConfig) } +// It checks that the templates defined are parseable +// We should check it during the service bootstrap to avoid errors further +func CheckParseTemplates(fulcioConfig *FulcioConfig) error { + + checkParse := func(temp interface{}) error { + t := template.New("").Option("missingkey=error") + _, err := t.Parse(temp.(string)) + return err + } + + for _, ciIssuerMetadata := range fulcioConfig.CIIssuerMetadata { + claimsTemplates := structs.Map(ciIssuerMetadata.ClaimsTemplates) + for _, temp := range claimsTemplates { + err := checkParse(temp) + if err != nil { + return err + } + } + err := checkParse(ciIssuerMetadata.SubjectAlternativeNameTemplate) + if err != nil { + return err + } + } + return nil +} + // Load a config from disk, or use defaults func Load(configPath string) (*FulcioConfig, error) { if _, err := os.Stat(configPath); os.IsNotExist(err) { @@ -469,7 +497,13 @@ func Load(configPath string) (*FulcioConfig, error) { if err != nil { return nil, fmt.Errorf("read file: %w", err) } - return Read(b) + + fulcioConfig, err := Read(b) + if err != nil { + return fulcioConfig, err + } + err = CheckParseTemplates(fulcioConfig) + return fulcioConfig, err } // Read parses the bytes of a config diff --git a/pkg/config/config_network_test.go b/pkg/config/config_network_test.go index 52808181a..99405b594 100644 --- a/pkg/config/config_network_test.go +++ b/pkg/config/config_network_test.go @@ -25,6 +25,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" + "github.com/sigstore/fulcio/pkg/certificate" ) func TestLoad(t *testing.T) { @@ -68,6 +69,47 @@ func TestLoad(t *testing.T) { } } +func TestParseTemplate(t *testing.T) { + + validTemplate := "{{.foobar}}" + invalidTemplate := "{{.foobar}" + ciissuerMetadata := make(map[string]DefaultTemplateValues) + ciissuerMetadata["github"] = DefaultTemplateValues{ + ClaimsTemplates: certificate.Extensions{ + BuildTrigger: invalidTemplate, + }, + } + fulcioConfig := &FulcioConfig{ + CIIssuerMetadata: ciissuerMetadata, + } + err := CheckParseTemplates(fulcioConfig) + if err == nil { + t.Error("It should raise an error") + } + ciissuerMetadata["github"] = DefaultTemplateValues{ + ClaimsTemplates: certificate.Extensions{ + BuildTrigger: validTemplate, + }, + } + fulcioConfig = &FulcioConfig{ + CIIssuerMetadata: ciissuerMetadata, + } + err = CheckParseTemplates(fulcioConfig) + if err != nil { + t.Error("It shouldn't raise an error") + } + ciissuerMetadata["github"] = DefaultTemplateValues{ + SubjectAlternativeNameTemplate: invalidTemplate, + } + fulcioConfig = &FulcioConfig{ + CIIssuerMetadata: ciissuerMetadata, + } + err = CheckParseTemplates(fulcioConfig) + if err == nil { + t.Error("It should raise an error") + } +} + func TestLoadDefaults(t *testing.T) { td := t.TempDir() diff --git a/pkg/identity/ciprovider/principal.go b/pkg/identity/ciprovider/principal.go index 86e8494bd..c54231d3e 100644 --- a/pkg/identity/ciprovider/principal.go +++ b/pkg/identity/ciprovider/principal.go @@ -69,6 +69,8 @@ func applyTemplateOrReplace(extValueTemplate string, tokenClaims map[string]stri // This option forces to having the claim that is required // for the template t := template.New("").Option("missingkey=error") + // It shouldn't raise error since we already checked all + // templates in CheckParseTemplates functions in config.go p, err := t.Parse(extValueTemplate) if err != nil { return "", err From 13e70598bfc73736c8255ff166dc665ac98cb2c5 Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Wed, 26 Jun 2024 17:10:19 +0000 Subject: [PATCH 50/56] remove structs usage, using mapstructure instead Signed-off-by: Javan lacerda --- go.mod | 1 - go.sum | 2 -- pkg/config/config.go | 10 +++++++--- pkg/identity/ciprovider/principal.go | 10 +++++++--- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index b46686650..bf517cd26 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,6 @@ require ( github.com/ThalesIgnite/crypto11 v1.2.5 github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d github.com/coreos/go-oidc/v3 v3.10.0 - github.com/fatih/structs v1.1.0 github.com/fsnotify/fsnotify v1.7.0 github.com/go-jose/go-jose/v4 v4.0.2 github.com/goadesign/goa v2.2.5+incompatible diff --git a/go.sum b/go.sum index d11f6604d..e17dcbadb 100644 --- a/go.sum +++ b/go.sum @@ -106,8 +106,6 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= -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.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= diff --git a/pkg/config/config.go b/pkg/config/config.go index d80b3fb7f..9e309b4ba 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -31,8 +31,8 @@ import ( "time" "github.com/coreos/go-oidc/v3/oidc" - "github.com/fatih/structs" lru "github.com/hashicorp/golang-lru" + "github.com/mitchellh/mapstructure" "github.com/sigstore/fulcio/pkg/certificate" fulciogrpc "github.com/sigstore/fulcio/pkg/generated/protobuf" "github.com/sigstore/fulcio/pkg/log" @@ -468,14 +468,18 @@ func CheckParseTemplates(fulcioConfig *FulcioConfig) error { } for _, ciIssuerMetadata := range fulcioConfig.CIIssuerMetadata { - claimsTemplates := structs.Map(ciIssuerMetadata.ClaimsTemplates) + claimsTemplates := make(map[string]interface{}) + err := mapstructure.Decode(ciIssuerMetadata.ClaimsTemplates, &claimsTemplates) + if err != nil { + return err + } for _, temp := range claimsTemplates { err := checkParse(temp) if err != nil { return err } } - err := checkParse(ciIssuerMetadata.SubjectAlternativeNameTemplate) + err = checkParse(ciIssuerMetadata.SubjectAlternativeNameTemplate) if err != nil { return err } diff --git a/pkg/identity/ciprovider/principal.go b/pkg/identity/ciprovider/principal.go index c54231d3e..e6c3879c6 100644 --- a/pkg/identity/ciprovider/principal.go +++ b/pkg/identity/ciprovider/principal.go @@ -24,7 +24,6 @@ import ( "strings" "github.com/coreos/go-oidc/v3/oidc" - "github.com/fatih/structs" "github.com/mitchellh/mapstructure" "github.com/sigstore/fulcio/pkg/certificate" "github.com/sigstore/fulcio/pkg/config" @@ -128,8 +127,13 @@ func (principal ciPrincipal) Embed(_ context.Context, cert *x509.Certificate) er } uris := []*url.URL{sanURL} cert.URIs = uris - mapExtensionsForTemplate := mapValuesToString(structs.Map(claimsTemplates)) - for k, v := range mapExtensionsForTemplate { + mapExtensionsForTemplate := make(map[string]interface{}) + err = mapstructure.Decode(claimsTemplates, &mapExtensionsForTemplate) + if err != nil { + return err + } + + for k, v := range mapValuesToString(mapExtensionsForTemplate) { // It avoids to try applying template or replace for a empty string. if v != "" { mapExtensionsForTemplate[k], err = applyTemplateOrReplace(v, claims, defaults) From 397eee3970d514e077c203fcf70b8edc13ef6b54 Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Sun, 30 Jun 2024 15:59:09 +0000 Subject: [PATCH 51/56] renamme IssuerMetadata Signed-off-by: Javan lacerda --- pkg/config/config.go | 6 +++--- pkg/config/config_network_test.go | 8 ++++---- pkg/identity/ciprovider/principal.go | 8 ++++---- pkg/identity/ciprovider/principal_test.go | 10 +++++----- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/pkg/config/config.go b/pkg/config/config.go index 9e309b4ba..6b601a28b 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -67,7 +67,7 @@ type FulcioConfig struct { // The CI provider has a generic logic for ci providers, this metadata is used // to define the right behavior for each ci provider that is defined // on the configuration file - CIIssuerMetadata map[string]DefaultTemplateValues + CIIssuerMetadata map[string]IssuerMetadata // verifiers is a fixed mapping from our OIDCIssuers to their OIDC verifiers. verifiers map[string][]*verifierWithConfig @@ -75,10 +75,10 @@ type FulcioConfig struct { lru *lru.TwoQueueCache } -type DefaultTemplateValues struct { +type IssuerMetadata struct { // Default key and values that can be used for filling the templates // If a key cannot be found on the token claims, the template will use the defaults - Defaults map[string]string + DefaultTemplateValues map[string]string // It is a Extensions version which the values are template strigs. // It expects strings with templates syntax https://pkg.go.dev/text/template // or raw strings with claims keys to be replaced diff --git a/pkg/config/config_network_test.go b/pkg/config/config_network_test.go index 99405b594..54a67dc63 100644 --- a/pkg/config/config_network_test.go +++ b/pkg/config/config_network_test.go @@ -73,8 +73,8 @@ func TestParseTemplate(t *testing.T) { validTemplate := "{{.foobar}}" invalidTemplate := "{{.foobar}" - ciissuerMetadata := make(map[string]DefaultTemplateValues) - ciissuerMetadata["github"] = DefaultTemplateValues{ + ciissuerMetadata := make(map[string]IssuerMetadata) + ciissuerMetadata["github"] = IssuerMetadata{ ClaimsTemplates: certificate.Extensions{ BuildTrigger: invalidTemplate, }, @@ -86,7 +86,7 @@ func TestParseTemplate(t *testing.T) { if err == nil { t.Error("It should raise an error") } - ciissuerMetadata["github"] = DefaultTemplateValues{ + ciissuerMetadata["github"] = IssuerMetadata{ ClaimsTemplates: certificate.Extensions{ BuildTrigger: validTemplate, }, @@ -98,7 +98,7 @@ func TestParseTemplate(t *testing.T) { if err != nil { t.Error("It shouldn't raise an error") } - ciissuerMetadata["github"] = DefaultTemplateValues{ + ciissuerMetadata["github"] = IssuerMetadata{ SubjectAlternativeNameTemplate: invalidTemplate, } fulcioConfig = &FulcioConfig{ diff --git a/pkg/identity/ciprovider/principal.go b/pkg/identity/ciprovider/principal.go index e6c3879c6..ac50c6514 100644 --- a/pkg/identity/ciprovider/principal.go +++ b/pkg/identity/ciprovider/principal.go @@ -48,7 +48,7 @@ func getTokenClaims(token *oidc.IDToken) (map[string]string, error) { // It makes string interpolation for a given string by using the // templates syntax https://pkg.go.dev/text/template -func applyTemplateOrReplace(extValueTemplate string, tokenClaims map[string]string, defaultTemplateValues map[string]string) (string, error) { +func applyTemplateOrReplace(extValueTemplate string, tokenClaims map[string]string, issuerMetadata map[string]string) (string, error) { // Here we merge the data from was claimed by the id token with the // default data provided by the yaml file. @@ -59,7 +59,7 @@ func applyTemplateOrReplace(extValueTemplate string, tokenClaims map[string]stri for k, v := range tokenClaims { mergedData[k] = v } - for k, v := range defaultTemplateValues { + for k, v := range issuerMetadata { mergedData[k] = v } @@ -89,7 +89,7 @@ func applyTemplateOrReplace(extValueTemplate string, tokenClaims map[string]stri type ciPrincipal struct { Token *oidc.IDToken - ClaimsMetadata config.DefaultTemplateValues + ClaimsMetadata config.IssuerMetadata } func WorkflowPrincipalFromIDToken(ctx context.Context, token *oidc.IDToken) (identity.Principal, error) { @@ -112,7 +112,7 @@ func (principal ciPrincipal) Name(_ context.Context) string { func (principal ciPrincipal) Embed(_ context.Context, cert *x509.Certificate) error { claimsTemplates := principal.ClaimsMetadata.ClaimsTemplates - defaults := principal.ClaimsMetadata.Defaults + defaults := principal.ClaimsMetadata.DefaultTemplateValues claims, err := getTokenClaims(principal.Token) if err != nil { return err diff --git a/pkg/identity/ciprovider/principal_test.go b/pkg/identity/ciprovider/principal_test.go index bc5c19778..2d70e5959 100644 --- a/pkg/identity/ciprovider/principal_test.go +++ b/pkg/identity/ciprovider/principal_test.go @@ -37,7 +37,7 @@ func TestWorkflowPrincipalFromIDToken(t *testing.T) { }{ `Github workflow challenge should have all Github workflow extensions and issuer set`: { ExpectedPrincipal: ciPrincipal{ - ClaimsMetadata: config.DefaultTemplateValues{ + ClaimsMetadata: config.IssuerMetadata{ ClaimsTemplates: certificate.Extensions{ Issuer: "issuer", GithubWorkflowTrigger: "event_name", @@ -60,7 +60,7 @@ func TestWorkflowPrincipalFromIDToken(t *testing.T) { RunInvocationURI: "{{ .url }}/{{ .repository }}/actions/runs/{{ .run_id }}/attempts/{{ .run_attempt }}", SourceRepositoryVisibilityAtSigning: "repository_visibility", }, - Defaults: map[string]string{ + DefaultTemplateValues: map[string]string{ "url": "https://github.com", }, SubjectAlternativeNameTemplate: "{{.url}}/{{.job_workflow_ref}}", @@ -107,7 +107,7 @@ func TestWorkflowPrincipalFromIDToken(t *testing.T) { ClientID: "sigstore", }, } - meta := make(map[string]config.DefaultTemplateValues) + meta := make(map[string]config.IssuerMetadata) meta["github-workflow"] = test.ExpectedPrincipal.ClaimsMetadata cfg := &config.FulcioConfig{ OIDCIssuers: OIDCIssuers, @@ -236,7 +236,7 @@ func TestEmbed(t *testing.T) { `Certificate has correct source repository visibility extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 22}, "public"), }, Principal: ciPrincipal{ - ClaimsMetadata: config.DefaultTemplateValues{ + ClaimsMetadata: config.IssuerMetadata{ ClaimsTemplates: certificate.Extensions{ GithubWorkflowTrigger: "event_name", GithubWorkflowSHA: "sha", @@ -258,7 +258,7 @@ func TestEmbed(t *testing.T) { RunInvocationURI: "{{ .url }}/{{ .repository }}/actions/runs/{{ .run_id }}/attempts/{{ .run_attempt }}", SourceRepositoryVisibilityAtSigning: "repository_visibility", }, - Defaults: map[string]string{ + DefaultTemplateValues: map[string]string{ "url": "https://github.com", }, SubjectAlternativeNameTemplate: "{{.url}}/{{.job_workflow_ref}}", From 04ef3c73d21408da06bb137cc5478f828b61a99b Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Sun, 30 Jun 2024 15:59:54 +0000 Subject: [PATCH 52/56] update SubjectAlternativeNameTemplate comment Signed-off-by: Javan lacerda --- pkg/config/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/config/config.go b/pkg/config/config.go index 6b601a28b..3181fdfbf 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -83,7 +83,7 @@ type IssuerMetadata struct { // It expects strings with templates syntax https://pkg.go.dev/text/template // or raw strings with claims keys to be replaced ClaimsTemplates certificate.Extensions - // A alternative name for the issuer subject + // Template for the Subject Alternative Name extension // It's typically the same value as Build Signer URI SubjectAlternativeNameTemplate string } From 96a66631b712eb17bf822496a7c13709222de318 Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Sun, 30 Jun 2024 16:33:06 +0000 Subject: [PATCH 53/56] several fixes Signed-off-by: Javan lacerda --- pkg/config/config.go | 28 ++++++++++------------- pkg/config/config_network_test.go | 10 ++++---- pkg/identity/ciprovider/principal.go | 4 ++-- pkg/identity/ciprovider/principal_test.go | 4 ++-- 4 files changed, 21 insertions(+), 25 deletions(-) diff --git a/pkg/config/config.go b/pkg/config/config.go index 3181fdfbf..c2d2c36cd 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -76,13 +76,15 @@ type FulcioConfig struct { } type IssuerMetadata struct { - // Default key and values that can be used for filling the templates + // Defaults contains key-value pairs that can be used for filling the templates from ExtensionTemplates // If a key cannot be found on the token claims, the template will use the defaults DefaultTemplateValues map[string]string - // It is a Extensions version which the values are template strigs. - // It expects strings with templates syntax https://pkg.go.dev/text/template - // or raw strings with claims keys to be replaced - ClaimsTemplates certificate.Extensions + // ExtensionTemplates contains a mapping between certificate extension and token claim + // Provide either strings following https://pkg.go.dev/text/template syntax, + // e.g "{{ .url }}/{{ .repository }}" + // or non-templated strings with token claim keys to be replaced, + // e.g "job_workflow_sha" + ExtensionTemplates certificate.Extensions // Template for the Subject Alternative Name extension // It's typically the same value as Build Signer URI SubjectAlternativeNameTemplate string @@ -96,7 +98,7 @@ type OIDCIssuer struct { // Used to determine the subject of the certificate and if additional // certificate values are needed Type IssuerType `json:"Type" yaml:"type,omitempty"` - // Issuers CiProvider type + // CIProvider is an optional configuration to map token claims to extensions for CI workflows CIProvider string `json:"CIProvider,omitempty" yaml:"ci-provider,omitempty"` // Optional, if the issuer is in a different claim in the OIDC token IssuerClaim string `json:"IssuerClaim,omitempty" yaml:"issuer-claim,omitempty"` @@ -416,7 +418,7 @@ func validateConfig(conf *FulcioConfig) error { } } - return nil + return validateCIIssuerMetadata(conf) } var DefaultConfig = &FulcioConfig{ @@ -459,7 +461,7 @@ func FromContext(ctx context.Context) *FulcioConfig { // It checks that the templates defined are parseable // We should check it during the service bootstrap to avoid errors further -func CheckParseTemplates(fulcioConfig *FulcioConfig) error { +func validateCIIssuerMetadata(fulcioConfig *FulcioConfig) error { checkParse := func(temp interface{}) error { t := template.New("").Option("missingkey=error") @@ -469,7 +471,7 @@ func CheckParseTemplates(fulcioConfig *FulcioConfig) error { for _, ciIssuerMetadata := range fulcioConfig.CIIssuerMetadata { claimsTemplates := make(map[string]interface{}) - err := mapstructure.Decode(ciIssuerMetadata.ClaimsTemplates, &claimsTemplates) + err := mapstructure.Decode(ciIssuerMetadata.ExtensionTemplates, &claimsTemplates) if err != nil { return err } @@ -501,13 +503,7 @@ func Load(configPath string) (*FulcioConfig, error) { if err != nil { return nil, fmt.Errorf("read file: %w", err) } - - fulcioConfig, err := Read(b) - if err != nil { - return fulcioConfig, err - } - err = CheckParseTemplates(fulcioConfig) - return fulcioConfig, err + return Read(b) } // Read parses the bytes of a config diff --git a/pkg/config/config_network_test.go b/pkg/config/config_network_test.go index 54a67dc63..093b33df9 100644 --- a/pkg/config/config_network_test.go +++ b/pkg/config/config_network_test.go @@ -75,26 +75,26 @@ func TestParseTemplate(t *testing.T) { invalidTemplate := "{{.foobar}" ciissuerMetadata := make(map[string]IssuerMetadata) ciissuerMetadata["github"] = IssuerMetadata{ - ClaimsTemplates: certificate.Extensions{ + ExtensionTemplates: certificate.Extensions{ BuildTrigger: invalidTemplate, }, } fulcioConfig := &FulcioConfig{ CIIssuerMetadata: ciissuerMetadata, } - err := CheckParseTemplates(fulcioConfig) + err := validateCIIssuerMetadata(fulcioConfig) if err == nil { t.Error("It should raise an error") } ciissuerMetadata["github"] = IssuerMetadata{ - ClaimsTemplates: certificate.Extensions{ + ExtensionTemplates: certificate.Extensions{ BuildTrigger: validTemplate, }, } fulcioConfig = &FulcioConfig{ CIIssuerMetadata: ciissuerMetadata, } - err = CheckParseTemplates(fulcioConfig) + err = validateCIIssuerMetadata(fulcioConfig) if err != nil { t.Error("It shouldn't raise an error") } @@ -104,7 +104,7 @@ func TestParseTemplate(t *testing.T) { fulcioConfig = &FulcioConfig{ CIIssuerMetadata: ciissuerMetadata, } - err = CheckParseTemplates(fulcioConfig) + err = validateCIIssuerMetadata(fulcioConfig) if err == nil { t.Error("It should raise an error") } diff --git a/pkg/identity/ciprovider/principal.go b/pkg/identity/ciprovider/principal.go index ac50c6514..f45068e42 100644 --- a/pkg/identity/ciprovider/principal.go +++ b/pkg/identity/ciprovider/principal.go @@ -69,7 +69,7 @@ func applyTemplateOrReplace(extValueTemplate string, tokenClaims map[string]stri // for the template t := template.New("").Option("missingkey=error") // It shouldn't raise error since we already checked all - // templates in CheckParseTemplates functions in config.go + // templates in validateCIIssuerMetadata functions in config.go p, err := t.Parse(extValueTemplate) if err != nil { return "", err @@ -111,7 +111,7 @@ func (principal ciPrincipal) Name(_ context.Context) string { func (principal ciPrincipal) Embed(_ context.Context, cert *x509.Certificate) error { - claimsTemplates := principal.ClaimsMetadata.ClaimsTemplates + claimsTemplates := principal.ClaimsMetadata.ExtensionTemplates defaults := principal.ClaimsMetadata.DefaultTemplateValues claims, err := getTokenClaims(principal.Token) if err != nil { diff --git a/pkg/identity/ciprovider/principal_test.go b/pkg/identity/ciprovider/principal_test.go index 2d70e5959..4e407d82b 100644 --- a/pkg/identity/ciprovider/principal_test.go +++ b/pkg/identity/ciprovider/principal_test.go @@ -38,7 +38,7 @@ func TestWorkflowPrincipalFromIDToken(t *testing.T) { `Github workflow challenge should have all Github workflow extensions and issuer set`: { ExpectedPrincipal: ciPrincipal{ ClaimsMetadata: config.IssuerMetadata{ - ClaimsTemplates: certificate.Extensions{ + ExtensionTemplates: certificate.Extensions{ Issuer: "issuer", GithubWorkflowTrigger: "event_name", GithubWorkflowSHA: "sha", @@ -237,7 +237,7 @@ func TestEmbed(t *testing.T) { }, Principal: ciPrincipal{ ClaimsMetadata: config.IssuerMetadata{ - ClaimsTemplates: certificate.Extensions{ + ExtensionTemplates: certificate.Extensions{ GithubWorkflowTrigger: "event_name", GithubWorkflowSHA: "sha", GithubWorkflowName: "workflow", From 611d5c4fe5d40d0b5f1ad6137aa198e9d66bdade Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Sun, 30 Jun 2024 18:31:31 +0000 Subject: [PATCH 54/56] update for using reflect instead of mapstructure Signed-off-by: Javan lacerda --- go.mod | 2 +- pkg/config/config.go | 15 +++++------ pkg/identity/ciprovider/principal.go | 38 ++++++++++------------------ 3 files changed, 21 insertions(+), 34 deletions(-) diff --git a/go.mod b/go.mod index bf517cd26..8caa0c7bf 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,6 @@ require ( github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 github.com/hashicorp/golang-lru v1.0.2 github.com/magiconair/properties v1.8.7 - github.com/mitchellh/mapstructure v1.5.0 github.com/prometheus/client_golang v1.19.1 github.com/prometheus/client_model v0.6.1 github.com/prometheus/common v0.54.0 @@ -111,6 +110,7 @@ require ( github.com/letsencrypt/boulder v0.0.0-20230907030200-6d76a0f91e1e // indirect github.com/miekg/pkcs11 v1.1.1 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect diff --git a/pkg/config/config.go b/pkg/config/config.go index c2d2c36cd..58a898fc3 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -32,7 +32,6 @@ import ( "github.com/coreos/go-oidc/v3/oidc" lru "github.com/hashicorp/golang-lru" - "github.com/mitchellh/mapstructure" "github.com/sigstore/fulcio/pkg/certificate" fulciogrpc "github.com/sigstore/fulcio/pkg/generated/protobuf" "github.com/sigstore/fulcio/pkg/log" @@ -470,18 +469,16 @@ func validateCIIssuerMetadata(fulcioConfig *FulcioConfig) error { } for _, ciIssuerMetadata := range fulcioConfig.CIIssuerMetadata { - claimsTemplates := make(map[string]interface{}) - err := mapstructure.Decode(ciIssuerMetadata.ExtensionTemplates, &claimsTemplates) - if err != nil { - return err - } - for _, temp := range claimsTemplates { - err := checkParse(temp) + v := reflect.Indirect(reflect.ValueOf(&ciIssuerMetadata.ExtensionTemplates)) + for i := 0; i < v.NumField(); i++ { + s := v.Field(i).String() + err := checkParse(s) if err != nil { return err } } - err = checkParse(ciIssuerMetadata.SubjectAlternativeNameTemplate) + + err := checkParse(ciIssuerMetadata.SubjectAlternativeNameTemplate) if err != nil { return err } diff --git a/pkg/identity/ciprovider/principal.go b/pkg/identity/ciprovider/principal.go index f45068e42..00a963bb9 100644 --- a/pkg/identity/ciprovider/principal.go +++ b/pkg/identity/ciprovider/principal.go @@ -21,11 +21,10 @@ import ( "fmt" "html/template" "net/url" + "reflect" "strings" "github.com/coreos/go-oidc/v3/oidc" - "github.com/mitchellh/mapstructure" - "github.com/sigstore/fulcio/pkg/certificate" "github.com/sigstore/fulcio/pkg/config" "github.com/sigstore/fulcio/pkg/identity" ) @@ -127,33 +126,24 @@ func (principal ciPrincipal) Embed(_ context.Context, cert *x509.Certificate) er } uris := []*url.URL{sanURL} cert.URIs = uris - mapExtensionsForTemplate := make(map[string]interface{}) - err = mapstructure.Decode(claimsTemplates, &mapExtensionsForTemplate) - if err != nil { - return err - } - - for k, v := range mapValuesToString(mapExtensionsForTemplate) { - // It avoids to try applying template or replace for a empty string. - if v != "" { - mapExtensionsForTemplate[k], err = applyTemplateOrReplace(v, claims, defaults) - if err != nil { - return err - } + v := reflect.Indirect(reflect.ValueOf(&claimsTemplates)) + for i := 0; i < v.NumField(); i++ { + s := v.Field(i).String() // value of each field, e.g the template string + if s == "" { + continue } + extValue, err := applyTemplateOrReplace(s, claims, defaults) + if err != nil { + return err + } + v.Field(i).SetString(extValue) } - ext := &certificate.Extensions{ - Issuer: principal.Token.Issuer, - } - err = mapstructure.Decode(mapExtensionsForTemplate, &ext) - if err != nil { - return err - } + // Guarantees to set the extension issuer as the token issuer // regardless of whether this field has been set before - ext.Issuer = principal.Token.Issuer + claimsTemplates.Issuer = principal.Token.Issuer // Embed additional information into custom extensions - cert.ExtraExtensions, err = ext.Render() + cert.ExtraExtensions, err = claimsTemplates.Render() if err != nil { return err } From 1a481ebd3146c25bd2f7001f49d813175357616e Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Mon, 1 Jul 2024 14:46:09 +0000 Subject: [PATCH 55/56] adding test for ciprovider API Signed-off-by: Javan lacerda --- pkg/config/config.go | 4 +- pkg/identity/ciprovider/principal.go | 4 +- pkg/server/grpc_server_test.go | 184 ++++++++++++++++++++++++++- 3 files changed, 186 insertions(+), 6 deletions(-) diff --git a/pkg/config/config.go b/pkg/config/config.go index 58a898fc3..ed77872f3 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -462,9 +462,9 @@ func FromContext(ctx context.Context) *FulcioConfig { // We should check it during the service bootstrap to avoid errors further func validateCIIssuerMetadata(fulcioConfig *FulcioConfig) error { - checkParse := func(temp interface{}) error { + checkParse := func(temp string) error { t := template.New("").Option("missingkey=error") - _, err := t.Parse(temp.(string)) + _, err := t.Parse(temp) return err } diff --git a/pkg/identity/ciprovider/principal.go b/pkg/identity/ciprovider/principal.go index 00a963bb9..55d2f106d 100644 --- a/pkg/identity/ciprovider/principal.go +++ b/pkg/identity/ciprovider/principal.go @@ -97,7 +97,6 @@ func WorkflowPrincipalFromIDToken(ctx context.Context, token *oidc.IDToken) (ide if !ok { return nil, fmt.Errorf("configuration can not be loaded for issuer %v", token.Issuer) } - return ciPrincipal{ token, cfg.CIIssuerMetadata[issuerCfg.CIProvider], @@ -127,9 +126,10 @@ func (principal ciPrincipal) Embed(_ context.Context, cert *x509.Certificate) er uris := []*url.URL{sanURL} cert.URIs = uris v := reflect.Indirect(reflect.ValueOf(&claimsTemplates)) + vType := v.Type() for i := 0; i < v.NumField(); i++ { s := v.Field(i).String() // value of each field, e.g the template string - if s == "" { + if s == "" || vType.Field(i).Name == "Issuer" { continue } extValue, err := applyTemplateOrReplace(s, claims, defaults) diff --git a/pkg/server/grpc_server_test.go b/pkg/server/grpc_server_test.go index 999083160..56f05b71a 100644 --- a/pkg/server/grpc_server_test.go +++ b/pkg/server/grpc_server_test.go @@ -53,6 +53,7 @@ import ( "github.com/sigstore/fulcio/pkg/ca" "github.com/sigstore/fulcio/pkg/ca/ephemeralca" + "github.com/sigstore/fulcio/pkg/certificate" "github.com/sigstore/fulcio/pkg/config" "github.com/sigstore/fulcio/pkg/generated/protobuf" "github.com/sigstore/fulcio/pkg/identity" @@ -199,6 +200,7 @@ func TestGetConfiguration(t *testing.T) { _, gitLabIssuer := newOIDCIssuer(t) _, codefreshIssuer := newOIDCIssuer(t) _, chainguardIssuer := newOIDCIssuer(t) + _, ciProviderIssuer := newOIDCIssuer(t) issuerDomain, err := url.Parse(usernameIssuer) if err != nil { @@ -254,6 +256,11 @@ func TestGetConfiguration(t *testing.T) { "IssuerURL": %q, "ClientID": "sigstore", "Type": "chainguard-identity" + }, + %q: { + "IssuerURL": %q, + "ClientID": "sigstore", + "Type": "ci-provider" } }, "MetaIssuers": { @@ -271,6 +278,7 @@ func TestGetConfiguration(t *testing.T) { gitLabIssuer, gitLabIssuer, codefreshIssuer, codefreshIssuer, chainguardIssuer, chainguardIssuer, + ciProviderIssuer, ciProviderIssuer, k8sIssuer))) if err != nil { t.Fatalf("config.Read() = %v", err) @@ -291,7 +299,7 @@ func TestGetConfiguration(t *testing.T) { t.Fatal("GetConfiguration failed", err) } - if got, want := len(config.Issuers), 10; got != want { + if got, want := len(config.Issuers), 11; got != want { t.Fatalf("expected %d issuers, got %d", want, got) } @@ -299,7 +307,7 @@ func TestGetConfiguration(t *testing.T) { emailIssuer: true, spiffeIssuer: true, uriIssuer: true, usernameIssuer: true, k8sIssuer: true, gitHubIssuer: true, buildkiteIssuer: true, gitLabIssuer: true, codefreshIssuer: true, - chainguardIssuer: true, + chainguardIssuer: true, ciProviderIssuer: true, } for _, iss := range config.Issuers { var issURL string @@ -1123,6 +1131,178 @@ func TestAPIWithGitHub(t *testing.T) { } } +// Tests API for CiProvider subject types +func TestAPIWithCiProvider(t *testing.T) { + ciProviderSigner, ciProviderIssuer := newOIDCIssuer(t) + // Create a FulcioConfig that supports these issuers. + cfg, err := config.Read([]byte(fmt.Sprintf(`{ + "OIDCIssuers": { + %q: { + "IssuerURL": %q, + "ClientID": "sigstore", + "Type": "ci-provider", + "CIProvider": "github-workflow" + } + } + }`, ciProviderIssuer, ciProviderIssuer))) + if err != nil { + t.Fatalf("config.Read() = %v", err) + } + claims := githubClaims{ + JobWorkflowRef: "job/workflow/ref", + Sha: "sha", + EventName: "trigger", + Repository: "sigstore/fulcio", + Workflow: "workflow", + Ref: "refs/heads/main", + JobWorkflowSha: "example-sha", + RunnerEnvironment: "cloud-hosted", + RepositoryID: "12345", + RepositoryOwner: "username", + RepositoryOwnerID: "345", + RepositoryVisibility: "public", + WorkflowRef: "sigstore/other/.github/workflows/foo.yaml@refs/heads/main", + WorkflowSha: "example-sha-other", + RunID: "42", + RunAttempt: "1", + } + githubSubject := fmt.Sprintf("repo:%s:ref:%s", claims.Repository, claims.Ref) + // Create an OIDC token using this issuer's signer. + tok, err := jwt.Signed(ciProviderSigner).Claims(jwt.Claims{ + Issuer: ciProviderIssuer, + IssuedAt: jwt.NewNumericDate(time.Now()), + Expiry: jwt.NewNumericDate(time.Now().Add(30 * time.Minute)), + Subject: githubSubject, + Audience: jwt.Audience{"sigstore"}, + }).Claims(&claims).Serialize() + if err != nil { + t.Fatalf("Serialize() = %v", err) + } + + ctClient, eca := createCA(cfg, t) + ctx := context.Background() + cfg.CIIssuerMetadata = make(map[string]config.IssuerMetadata) + cfg.CIIssuerMetadata["github-workflow"] = config.IssuerMetadata{ + ExtensionTemplates: certificate.Extensions{ + Issuer: "issuer", + GithubWorkflowTrigger: "event_name", + GithubWorkflowSHA: "sha", + GithubWorkflowName: "workflow", + GithubWorkflowRepository: "repository", + GithubWorkflowRef: "ref", + BuildSignerURI: "{{ .url }}/{{ .job_workflow_ref }}", + BuildSignerDigest: "job_workflow_sha", + RunnerEnvironment: "runner_environment", + SourceRepositoryURI: "{{ .url }}/{{ .repository }}", + SourceRepositoryDigest: "sha", + SourceRepositoryRef: "ref", + SourceRepositoryIdentifier: "repository_id", + SourceRepositoryOwnerURI: "{{ .url }}/{{ .repository_owner }}", + SourceRepositoryOwnerIdentifier: "repository_owner_id", + BuildConfigURI: "{{ .url }}/{{ .workflow_ref }}", + BuildConfigDigest: "workflow_sha", + BuildTrigger: "event_name", + RunInvocationURI: "{{ .url }}/{{ .repository }}/actions/runs/{{ .run_id }}/attempts/{{ .run_attempt }}", + SourceRepositoryVisibilityAtSigning: "repository_visibility", + }, + DefaultTemplateValues: map[string]string{ + "url": "https://github.com", + }, + SubjectAlternativeNameTemplate: "{{.url}}/{{.job_workflow_ref}}", + } + + server, conn := setupGRPCForTest(t, cfg, ctClient, eca) + defer func() { + server.Stop() + conn.Close() + }() + client := protobuf.NewCAClient(conn) + pubBytes, proof := generateKeyAndProof(githubSubject, t) + // Hit the API to have it sign our certificate. + resp, err := client.CreateSigningCertificate(ctx, &protobuf.CreateSigningCertificateRequest{ + Credentials: &protobuf.Credentials{ + Credentials: &protobuf.Credentials_OidcIdentityToken{ + OidcIdentityToken: tok, + }, + }, + Key: &protobuf.CreateSigningCertificateRequest_PublicKeyRequest{ + PublicKeyRequest: &protobuf.PublicKeyRequest{ + PublicKey: &protobuf.PublicKey{ + Content: pubBytes, + }, + ProofOfPossession: proof, + }, + }, + }) + if err != nil { + t.Fatalf("SigningCert() = %v", err) + } + leafCert := verifyResponse(resp, eca, ciProviderIssuer, t) + // Expect URI values + if len(leafCert.URIs) != 1 { + t.Fatalf("unexpected length of leaf certificate URIs, expected 1, got %d", len(leafCert.URIs)) + } + githubURL := fmt.Sprintf("https://github.com/%s", claims.JobWorkflowRef) + githubURI, err := url.Parse(githubURL) + if err != nil { + t.Fatalf("failed to parse expected url") + } + if *leafCert.URIs[0] != *githubURI { + t.Fatalf("URIs do not match: Expected %v, got %v", githubURI, leafCert.URIs[0]) + } + // Verify custom OID values + deprecatedExpectedExts := map[int]string{ + 2: claims.EventName, + 3: claims.Sha, + 4: claims.Workflow, + 5: claims.Repository, + 6: claims.Ref, + } + for o, value := range deprecatedExpectedExts { + ext, found := findCustomExtension(leafCert, asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, o}) + if !found { + t.Fatalf("expected extension in custom OID 1.3.6.1.4.1.57264.1.%d", o) + } + if string(ext.Value) != value { + t.Fatalf("unexpected extension value, expected %s, got %s", value, ext.Value) + } + } + url := "https://github.com/" + expectedExts := map[int]string{ + 9: url + claims.JobWorkflowRef, + 10: claims.JobWorkflowSha, + 11: claims.RunnerEnvironment, + 12: url + claims.Repository, + 13: claims.Sha, + 14: claims.Ref, + 15: claims.RepositoryID, + 16: url + claims.RepositoryOwner, + 17: claims.RepositoryOwnerID, + 18: url + claims.WorkflowRef, + 19: claims.WorkflowSha, + 20: claims.EventName, + 21: url + claims.Repository + "/actions/runs/" + claims.RunID + "/attempts/" + claims.RunAttempt, + 22: claims.RepositoryVisibility, + } + for o, value := range expectedExts { + ext, found := findCustomExtension(leafCert, asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, o}) + if !found { + t.Fatalf("expected extension in custom OID 1.3.6.1.4.1.57264.1.%d", o) + } + var extValue string + rest, err := asn1.Unmarshal(ext.Value, &extValue) + if err != nil { + t.Fatalf("error unmarshalling extension: :%v", err) + } + if len(rest) != 0 { + t.Fatal("error unmarshalling extension, rest is not 0") + } + if string(extValue) != value { + t.Fatalf("unexpected extension value, expected %s, got %s", value, extValue) + } + } +} + // gitlabClaims holds the additional JWT claims for GitLab OIDC tokens type gitlabClaims struct { ProjectPath string `json:"project_path"` From 8ab3f2a837ab858c442c33336c2f9eafc78c2775 Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Mon, 1 Jul 2024 15:00:51 +0000 Subject: [PATCH 56/56] adding json tags for Extensions Signed-off-by: Javan lacerda --- pkg/certificate/extensions.go | 38 ++++++++++++++-------------- pkg/identity/ciprovider/principal.go | 2 +- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/pkg/certificate/extensions.go b/pkg/certificate/extensions.go index c07670336..584aac971 100644 --- a/pkg/certificate/extensions.go +++ b/pkg/certificate/extensions.go @@ -69,69 +69,69 @@ type Extensions struct { // Deprecated // Triggering event of the Github Workflow. Matches the `event_name` claim of ID // tokens from Github Actions - GithubWorkflowTrigger string `yaml:"github-workflow-trigger,omitempty"` // OID 1.3.6.1.4.1.57264.1.2 + GithubWorkflowTrigger string `json:"GithubWorkflowTrigger,omitempty" yaml:"github-workflow-trigger,omitempty"` // OID 1.3.6.1.4.1.57264.1.2 // Deprecated // SHA of git commit being built in Github Actions. Matches the `sha` claim of ID // tokens from Github Actions - GithubWorkflowSHA string `yaml:"github-workflow-sha,omitempty"` // OID 1.3.6.1.4.1.57264.1.3 + GithubWorkflowSHA string `json:"GithubWorkflowSHA,omitempty" yaml:"github-workflow-sha,omitempty"` // OID 1.3.6.1.4.1.57264.1.3 // Deprecated // Name of Github Actions Workflow. Matches the `workflow` claim of the ID // tokens from Github Actions - GithubWorkflowName string `yaml:"github-workflow-name,omitempty"` // OID 1.3.6.1.4.1.57264.1.4 + GithubWorkflowName string `json:"GithubWorkflowName,omitempty" yaml:"github-workflow-name,omitempty"` // OID 1.3.6.1.4.1.57264.1.4 // Deprecated // Repository of the Github Actions Workflow. Matches the `repository` claim of the ID // tokens from Github Actions - GithubWorkflowRepository string `yaml:"github-workflow-repository,omitempty"` // OID 1.3.6.1.4.1.57264.1.5 + GithubWorkflowRepository string `json:"GithubWorkflowRepository,omitempty" yaml:"github-workflow-repository,omitempty"` // OID 1.3.6.1.4.1.57264.1.5 // Deprecated // Git Ref of the Github Actions Workflow. Matches the `ref` claim of the ID tokens // from Github Actions - GithubWorkflowRef string `yaml:"github-workflow-ref,omitempty"` // 1.3.6.1.4.1.57264.1.6 + GithubWorkflowRef string `json:"GithubWorkflowRef,omitempty" yaml:"github-workflow-ref,omitempty"` // 1.3.6.1.4.1.57264.1.6 // Reference to specific build instructions that are responsible for signing. - BuildSignerURI string `yaml:"build-signer-uri,omitempty"` // 1.3.6.1.4.1.57264.1.9 + BuildSignerURI string `json:"BuildSignerURI,omitempty" yaml:"build-signer-uri,omitempty"` // 1.3.6.1.4.1.57264.1.9 // Immutable reference to the specific version of the build instructions that is responsible for signing. - BuildSignerDigest string `yaml:"build-signer-digest,omitempty"` // 1.3.6.1.4.1.57264.1.10 + BuildSignerDigest string `json:"BuildSignerDigest,omitempty" yaml:"build-signer-digest,omitempty"` // 1.3.6.1.4.1.57264.1.10 // Specifies whether the build took place in platform-hosted cloud infrastructure or customer/self-hosted infrastructure. - RunnerEnvironment string `yaml:"runner-environment,omitempty"` // 1.3.6.1.4.1.57264.1.11 + RunnerEnvironment string `json:"RunnerEnvironment,omitempty" yaml:"runner-environment,omitempty"` // 1.3.6.1.4.1.57264.1.11 // Source repository URL that the build was based on. - SourceRepositoryURI string `yaml:"source-repository-uri,omitempty"` // 1.3.6.1.4.1.57264.1.12 + SourceRepositoryURI string `json:"SourceRepositoryURI,omitempty" yaml:"source-repository-uri,omitempty"` // 1.3.6.1.4.1.57264.1.12 // Immutable reference to a specific version of the source code that the build was based upon. - SourceRepositoryDigest string `yaml:"source-repository-digest,omitempty"` // 1.3.6.1.4.1.57264.1.13 + SourceRepositoryDigest string `json:"SourceRepositoryDigest,omitempty" yaml:"source-repository-digest,omitempty"` // 1.3.6.1.4.1.57264.1.13 // Source Repository Ref that the build run was based upon. - SourceRepositoryRef string `yaml:"source-repository-ref,omitempty"` // 1.3.6.1.4.1.57264.1.14 + SourceRepositoryRef string `json:"SourceRepositoryRef,omitempty" yaml:"source-repository-ref,omitempty"` // 1.3.6.1.4.1.57264.1.14 // Immutable identifier for the source repository the workflow was based upon. - SourceRepositoryIdentifier string `yaml:"source-repository-identifier,omitempty"` // 1.3.6.1.4.1.57264.1.15 + SourceRepositoryIdentifier string `json:"SourceRepositoryIdentifier,omitempty" yaml:"source-repository-identifier,omitempty"` // 1.3.6.1.4.1.57264.1.15 // Source repository owner URL of the owner of the source repository that the build was based on. - SourceRepositoryOwnerURI string `yaml:"source-repository-owner-uri,omitempty"` // 1.3.6.1.4.1.57264.1.16 + SourceRepositoryOwnerURI string `json:"SourceRepositoryOwnerURI,omitempty" yaml:"source-repository-owner-uri,omitempty"` // 1.3.6.1.4.1.57264.1.16 // Immutable identifier for the owner of the source repository that the workflow was based upon. - SourceRepositoryOwnerIdentifier string `yaml:"source-repository-owner-identifier,omitempty"` // 1.3.6.1.4.1.57264.1.17 + SourceRepositoryOwnerIdentifier string `json:"SourceRepositoryOwnerIdentifier,omitempty" yaml:"source-repository-owner-identifier,omitempty"` // 1.3.6.1.4.1.57264.1.17 // Build Config URL to the top-level/initiating build instructions. - BuildConfigURI string `yaml:"build-config-uri,omitempty"` // 1.3.6.1.4.1.57264.1.18 + BuildConfigURI string `json:"BuildConfigURI,omitempty" yaml:"build-config-uri,omitempty"` // 1.3.6.1.4.1.57264.1.18 // Immutable reference to the specific version of the top-level/initiating build instructions. - BuildConfigDigest string `yaml:"build-config-digest,omitempty"` // 1.3.6.1.4.1.57264.1.19 + BuildConfigDigest string `json:"BuildConfigDigest,omitempty" yaml:"build-config-digest,omitempty"` // 1.3.6.1.4.1.57264.1.19 // Event or action that initiated the build. - BuildTrigger string `yaml:"build-trigger,omitempty"` // 1.3.6.1.4.1.57264.1.20 + BuildTrigger string `json:"BuildTrigger,omitempty" yaml:"build-trigger,omitempty"` // 1.3.6.1.4.1.57264.1.20 // Run Invocation URL to uniquely identify the build execution. - RunInvocationURI string `yaml:"run-invocation-uri,omitempty"` // 1.3.6.1.4.1.57264.1.21 + RunInvocationURI string `json:"RunInvocationURI,omitempty" yaml:"run-invocation-uri,omitempty"` // 1.3.6.1.4.1.57264.1.21 // Source repository visibility at the time of signing the certificate. - SourceRepositoryVisibilityAtSigning string `yaml:"source-repository-visibility-at-signing,omitempty"` // 1.3.6.1.4.1.57264.1.22 + SourceRepositoryVisibilityAtSigning string `json:"SourceRepositoryVisibilityAtSigning,omitempty" yaml:"source-repository-visibility-at-signing,omitempty"` // 1.3.6.1.4.1.57264.1.22 } func (e Extensions) Render() ([]pkix.Extension, error) { diff --git a/pkg/identity/ciprovider/principal.go b/pkg/identity/ciprovider/principal.go index 55d2f106d..44dc0ebc3 100644 --- a/pkg/identity/ciprovider/principal.go +++ b/pkg/identity/ciprovider/principal.go @@ -32,7 +32,7 @@ import ( func mapValuesToString(claims map[string]interface{}) map[string]string { newMap := make(map[string]string) for k, v := range claims { - newMap[k] = fmt.Sprintf("%v", v) + newMap[k] = fmt.Sprintf("%s", v) } return newMap }