Skip to content

Commit

Permalink
Add go-git based signer implementation. (#454)
Browse files Browse the repository at this point in the history
Adds a git.Signer implementation + e2e test to demonstrate how signing
is done. Verify still WIP upstream, so commit marshalling + verification
still done manually for now.

Signed-off-by: Billy Lynch <billy@chainguard.dev>
  • Loading branch information
wlynch committed Feb 21, 2024
1 parent 66e0ff5 commit 6f20ffd
Show file tree
Hide file tree
Showing 10 changed files with 279 additions and 37 deletions.
27 changes: 12 additions & 15 deletions .github/workflows/ci.yaml
Expand Up @@ -2,29 +2,26 @@ name: CI

on:
push:
branches: ['main']
branches: ["main"]
pull_request:
branches: ['main']
branches: ["main"]
workflow_dispatch:

jobs:
ci:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1

- name: Set up Go
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
with:
go-version: '1.21'
check-latest: true
- name: Set up Go
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
with:
go-version: "1.21"
check-latest: true

- name: Build
run: make build-all
- name: Build
run: make build-all

- name: Unit Tests
run: make unit-test

- name: Live dependency tests
run: make e2e-test
- name: Unit Tests
run: make unit-test
15 changes: 11 additions & 4 deletions .github/workflows/e2e.yaml
Expand Up @@ -3,14 +3,14 @@ name: E2E
on:
push:
pull_request_target:
branches: ['main']
branches: ["main"]
workflow_dispatch:

jobs:
e2e:
runs-on: ubuntu-latest
permissions:
id-token: write # Enable OIDC
id-token: write # Enable OIDC

# The rest of these are sanity-check settings, since I'm not sure if the
# org default is permissive or restricted.
Expand Down Expand Up @@ -43,12 +43,14 @@ jobs:
# for the e2e tests, so insert our own logic here.
# This is effectively a ternary of the form ${{ <condition> && <true> || <false> }}.
# See https://docs.github.com/en/actions/learn-github-actions/expressions for more details.
ref: ${{ startsWith(github.event_name, 'pull_request') && format('refs/pull/{0}/merge', github.event.number) || github.ref }}
ref:
${{ startsWith(github.event_name, 'pull_request') &&
format('refs/pull/{0}/merge', github.event.number) || github.ref }}

- name: Set up Go
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
with:
go-version: '1.21'
go-version: "1.21"
check-latest: true

- name: Install Gitsign
Expand Down Expand Up @@ -146,3 +148,8 @@ jobs:
- name: Debug log
if: failure()
run: cat "${GITSIGN_LOG}"

- name: e2e unit tests
run: |
set -e
make e2e-test
118 changes: 118 additions & 0 deletions e2e/sign_test.go
@@ -0,0 +1,118 @@
// 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.

//go:build e2e
// +build e2e

package e2e

import (
"context"
"encoding/json"
"os"
"testing"
"time"

"github.com/go-git/go-billy/v5/memfs"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/go-git/go-git/v5/storage/memory"
"github.com/sigstore/cosign/v2/pkg/providers"
"github.com/sigstore/gitsign/internal/git/gittest"
"github.com/sigstore/gitsign/pkg/fulcio"
gsgit "github.com/sigstore/gitsign/pkg/git"
"github.com/sigstore/gitsign/pkg/gitsign"
"github.com/sigstore/gitsign/pkg/rekor"
"github.com/sigstore/sigstore/pkg/oauth"
"github.com/sigstore/sigstore/pkg/oauthflow"

// Enable OIDC providers
_ "github.com/sigstore/cosign/v2/pkg/providers/all"
)

func TestSign(t *testing.T) {
ctx := context.Background()

var flow oauthflow.TokenGetter = &oauthflow.InteractiveIDTokenGetter{
HTMLPage: oauth.InteractiveSuccessHTML,
}
if providers.Enabled(ctx) {
// If automatic token provisioning is enabled, use it.
token, err := providers.Provide(ctx, "sigstore")
if err != nil {
t.Fatal(err)
}
flow = &oauthflow.StaticTokenGetter{
RawToken: token,
}
}
fulcio, err := fulcio.NewClient("https://fulcio.sigstore.dev", fulcio.OIDCOptions{
ClientID: "sigstore",
Issuer: "https://oauth2.sigstore.dev/auth",
TokenGetter: flow,
})
if err != nil {
t.Fatal(err)
}
rekor, err := rekor.NewWithOptions(ctx, "https://rekor.sigstore.dev")
if err != nil {
t.Fatal(err)
}
signer, err := gitsign.NewSigner(ctx, fulcio, rekor)
if err != nil {
t.Fatal(err)
}

// Make a commit + sign it
storage := memory.NewStorage()
repo, err := git.Init(storage, memfs.New())
if err != nil {
panic(err)
}
w, err := repo.Worktree()
if err != nil {
panic(err)
}
sha, err := w.Commit("example commit", &git.CommitOptions{
Author: &object.Signature{
Name: "John Doe",
Email: "john@example.com",
When: time.UnixMicro(1234567890).UTC(),
},
Signer: signer,
AllowEmptyCommits: true,
})
if err != nil {
t.Fatal(err)
}
commit, err := repo.CommitObject(sha)
if err != nil {
t.Fatal(err)
}
body := gittest.MarshalCommitBody(t, commit)
sig := []byte(commit.PGPSignature)

// Verify the commit
verifier, err := gsgit.NewDefaultVerifier(ctx)
if err != nil {
t.Fatal(err)
}
summary, err := gsgit.Verify(ctx, verifier, rekor, body, sig, true)
if err != nil {
t.Fatal(err)
}
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")
enc.Encode(summary.LogEntry)
}
11 changes: 6 additions & 5 deletions go.mod
Expand Up @@ -9,7 +9,7 @@ require (
github.com/coreos/go-systemd/v22 v22.5.0
github.com/github/smimesign v0.2.0
github.com/go-git/go-billy/v5 v5.5.0
github.com/go-git/go-git/v5 v5.11.0
github.com/go-git/go-git/v5 v5.11.1-0.20240221104814-686a0f7a4928
github.com/go-openapi/runtime v0.27.1
github.com/go-openapi/strfmt v0.22.0
github.com/go-openapi/swag v0.22.9
Expand All @@ -18,6 +18,7 @@ require (
github.com/jonboulle/clockwork v0.4.0
github.com/mattn/go-tty v0.0.5
github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/psanford/memfs v0.0.0-20230130182539-4dbf7e3e865e
github.com/secure-systems-lab/go-securesystemslib v0.8.0
github.com/sigstore/cosign/v2 v2.2.3
github.com/sigstore/fulcio v1.4.3
Expand Down Expand Up @@ -48,7 +49,7 @@ require (
github.com/Azure/go-autorest/logger v0.2.1 // indirect
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c // indirect
github.com/ProtonMail/go-crypto v1.0.0 // indirect
github.com/ThalesIgnite/crypto11 v1.2.5 // indirect
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.4 // indirect
github.com/alibabacloud-go/cr-20160607 v1.0.1 // indirect
Expand Down Expand Up @@ -168,7 +169,7 @@ require (
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sassoftware/relic v7.2.1+incompatible // indirect
github.com/segmentio/ksuid v1.0.4 // indirect
github.com/sergi/go-diff v1.3.1 // indirect
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
github.com/shibumi/go-pathspec v1.3.0 // indirect
github.com/sigstore/timestamp-authority v1.2.1 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
Expand Down Expand Up @@ -200,14 +201,14 @@ require (
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.26.0 // indirect
golang.org/x/exp v0.0.0-20231108232855-2478ac86f678 // indirect
golang.org/x/mod v0.14.0 // indirect
golang.org/x/mod v0.15.0 // indirect
golang.org/x/net v0.21.0 // indirect
golang.org/x/sync v0.6.0 // indirect
golang.org/x/sys v0.17.0 // indirect
golang.org/x/term v0.17.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.16.1 // indirect
golang.org/x/tools v0.18.0 // indirect
google.golang.org/api v0.159.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac // indirect
Expand Down
19 changes: 13 additions & 6 deletions go.sum
Expand Up @@ -57,8 +57,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c h1:kMFnB0vCcX7IL/m9Y5LO+KQYv+t1CQOiFe6+SV2J7bE=
github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78=
github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
github.com/ThalesIgnite/crypto11 v1.2.5 h1:1IiIIEqYmBvUYFeMnHqRft4bwf/O36jryEUpY+9ef8E=
github.com/ThalesIgnite/crypto11 v1.2.5/go.mod h1:ILDKtnCKiQ7zRoNxcp36Y1ZR8LBPmR2E23+wTQe/MlE=
github.com/alessio/shellescape v1.4.1 h1:V7yhSDDn8LP4lc4jS8pFkt0zCnzVJlG5JXy9BVKJUX0=
Expand Down Expand Up @@ -253,8 +253,8 @@ github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+
github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
github.com/go-git/go-git/v5 v5.11.0 h1:XIZc1p+8YzypNr34itUfSvYJcv+eYdTnTvOZ2vD3cA4=
github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY=
github.com/go-git/go-git/v5 v5.11.1-0.20240221104814-686a0f7a4928 h1:KhFQZmW7PuR0d4GySsCkCPlLXbAUCBlcKxcnd6e0ATA=
github.com/go-git/go-git/v5 v5.11.1-0.20240221104814-686a0f7a4928/go.mod h1:bjjasRHBEKHquuJUiVxAokJncx14xMhH6v/iguEEPTc=
github.com/go-jose/go-jose/v3 v3.0.1 h1:pWmKFVtt+Jl0vBZTIpz/eAKwsm6LkIxDVVbFHKkchhA=
github.com/go-jose/go-jose/v3 v3.0.1/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
Expand Down Expand Up @@ -338,6 +338,7 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
Expand Down Expand Up @@ -534,6 +535,8 @@ github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lne
github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY=
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
github.com/psanford/memfs v0.0.0-20230130182539-4dbf7e3e865e h1:51xcRlSMBU5rhM9KahnJGfEsBPVPz3182TgFRowA8yY=
github.com/psanford/memfs v0.0.0-20230130182539-4dbf7e3e865e/go.mod h1:tcaRap0jS3eifrEEllL6ZMd9dg8IlDpi2S1oARrQ+NI=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
Expand All @@ -552,8 +555,8 @@ github.com/secure-systems-lab/go-securesystemslib v0.8.0 h1:mr5An6X45Kb2nddcFlbm
github.com/secure-systems-lab/go-securesystemslib v0.8.0/go.mod h1:UH2VZVuJfCYR8WgMlCU1uFsOUU+KeyrTWcSS73NBOzU=
github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c=
github.com/segmentio/ksuid v1.0.4/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE=
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
github.com/shibumi/go-pathspec v1.3.0 h1:QUyMZhFo0Md5B8zV8x2tesohbb5kfbpTi9rBnKh5dkI=
github.com/shibumi/go-pathspec v1.3.0/go.mod h1:Xutfslp817l2I1cZvgcfeMQJG5QnU2lh5tVaaMCl3jE=
github.com/sigstore/cosign/v2 v2.2.3 h1:WX7yawI+EXu9h7S5bZsfYCbB9XW6Jc43ctKy/NoOSiA=
Expand Down Expand Up @@ -716,6 +719,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
Expand Down Expand Up @@ -827,6 +832,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA=
golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ=
golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
Expand Down
5 changes: 3 additions & 2 deletions internal/fulcio/identity.go
Expand Up @@ -34,6 +34,7 @@ import (
"github.com/sigstore/gitsign/internal/config"
"github.com/sigstore/gitsign/internal/fulcio/fulcioroots"
"github.com/sigstore/gitsign/internal/signerverifier"
"github.com/sigstore/gitsign/pkg/fulcio"
"github.com/sigstore/sigstore/pkg/oauth"
"github.com/sigstore/sigstore/pkg/oauthflow"
"github.com/sigstore/sigstore/pkg/signature"
Expand Down Expand Up @@ -233,8 +234,8 @@ func (f *IdentityFactory) NewIdentity(ctx context.Context, cfg *config.Config) (
return nil, fmt.Errorf("generating private key: %w", err)
}

client, err := NewClient(cfg.Fulcio,
OIDCOptions{
client, err := fulcio.NewClient(cfg.Fulcio,
fulcio.OIDCOptions{
Issuer: cfg.Issuer,
ClientID: clientID,
RedirectURL: cfg.RedirectURL,
Expand Down
12 changes: 8 additions & 4 deletions internal/fulcio/fulcio.go → pkg/fulcio/fulcio.go
Expand Up @@ -27,9 +27,13 @@ import (
"github.com/sigstore/sigstore/pkg/oauthflow"
)

type Client interface {
GetCert(crypto.Signer) (*api.CertificateResponse, error)
}

// Client provides a fulcio client with helpful options for configuring OIDC
// flows.
type Client struct {
type ClientImpl struct {
api.LegacyClient
oidc OIDCOptions
}
Expand All @@ -43,20 +47,20 @@ type OIDCOptions struct {
TokenGetter oauthflow.TokenGetter
}

func NewClient(fulcioURL string, opts OIDCOptions) (*Client, error) {
func NewClient(fulcioURL string, opts OIDCOptions) (*ClientImpl, error) {
u, err := url.Parse(fulcioURL)
if err != nil {
return nil, err
}
client := api.NewClient(u, api.WithUserAgent("gitsign"))
return &Client{
return &ClientImpl{
LegacyClient: client,
oidc: opts,
}, nil
}

// GetCert exchanges the given private key for a Fulcio certificate.
func (c *Client) GetCert(priv crypto.Signer) (*api.CertificateResponse, error) {
func (c *ClientImpl) GetCert(priv crypto.Signer) (*api.CertificateResponse, error) {
pubBytes, err := x509.MarshalPKIXPublicKey(priv.Public())
if err != nil {
return nil, err
Expand Down
Expand Up @@ -120,7 +120,7 @@ func TestGetCert(t *testing.T) {
key, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
email := "foo@example.com"

client := &Client{
client := &ClientImpl{
// fakeFulcio is what will be doing the validation.
LegacyClient: &fakeFulcio{
signer: key,
Expand Down

0 comments on commit 6f20ffd

Please sign in to comment.