Skip to content

Commit d4531ab

Browse files
authored
feat(keyless): signing use case (chainloop-dev#859)
Signed-off-by: Jose I. Paris <[email protected]>
1 parent 48bc985 commit d4531ab

File tree

5 files changed

+222
-2
lines changed

5 files changed

+222
-2
lines changed

app/controlplane/internal/biz/biz.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ var ProviderSet = wire.NewSet(
4848
NewAPITokenUseCase,
4949
NewAPITokenSyncerUseCase,
5050
NewAttestationStateUseCase,
51+
NewChainloopSigningUseCase,
5152
wire.Struct(new(NewIntegrationUseCaseOpts), "*"),
5253
wire.Struct(new(NewUserUseCaseParams), "*"),
5354
)
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
//
2+
// Copyright 2024 The Chainloop Authors.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
package biz
17+
18+
import (
19+
"context"
20+
"crypto"
21+
"crypto/x509"
22+
"crypto/x509/pkix"
23+
"errors"
24+
"fmt"
25+
26+
"github.com/sigstore/fulcio/pkg/ca"
27+
"github.com/sigstore/fulcio/pkg/identity"
28+
"github.com/sigstore/sigstore/pkg/cryptoutils"
29+
)
30+
31+
type SigningUseCase struct {
32+
CA ca.CertificateAuthority
33+
}
34+
35+
func NewChainloopSigningUseCase(ca ca.CertificateAuthority) *SigningUseCase {
36+
return &SigningUseCase{CA: ca}
37+
}
38+
39+
// CreateSigningCert signs a certificate request with a configured CA, and returns the full certificate chain
40+
func (s *SigningUseCase) CreateSigningCert(ctx context.Context, orgID string, csrRaw []byte) ([]string, error) {
41+
var publicKey crypto.PublicKey
42+
43+
if len(csrRaw) == 0 {
44+
return nil, errors.New("csr cannot be empty")
45+
}
46+
47+
// Parse CSR
48+
csr, err := cryptoutils.ParseCSR(csrRaw)
49+
if err != nil {
50+
return nil, fmt.Errorf("parsing csr: %w", err)
51+
}
52+
53+
// Parse public key and check for weak key parameters
54+
publicKey = csr.PublicKey
55+
if err := cryptoutils.ValidatePubKey(publicKey); err != nil {
56+
return nil, fmt.Errorf("invalid public key: %w", err)
57+
}
58+
59+
// Check the CSR signature is valid
60+
if err := csr.CheckSignature(); err != nil {
61+
return nil, fmt.Errorf("invalid signature: %w", err)
62+
}
63+
64+
// Create certificate from CA provider (no Signed Certificate Timestamps for now)
65+
csc, err := s.CA.CreateCertificate(ctx, newChainloopPrincipal(orgID), publicKey)
66+
if err != nil {
67+
return nil, fmt.Errorf("creating certificate: %w", err)
68+
}
69+
70+
// Generated certificate
71+
finalPEM, err := csc.CertPEM()
72+
if err != nil {
73+
return nil, fmt.Errorf("marshaling certificate to PEM: %w", err)
74+
}
75+
76+
// Certificate chain
77+
finalChainPEM, err := csc.ChainPEM()
78+
if err != nil {
79+
return nil, fmt.Errorf("marshaling chain to PEM: %w", err)
80+
}
81+
82+
return append([]string{finalPEM}, finalChainPEM...), nil
83+
}
84+
85+
type chainloopPrincipal struct {
86+
orgID string
87+
}
88+
89+
var _ identity.Principal = (*chainloopPrincipal)(nil)
90+
91+
func newChainloopPrincipal(orgID string) *chainloopPrincipal {
92+
return &chainloopPrincipal{orgID: orgID}
93+
}
94+
95+
func (p *chainloopPrincipal) Name(_ context.Context) string {
96+
return p.orgID
97+
}
98+
99+
func (p *chainloopPrincipal) Embed(_ context.Context, cert *x509.Certificate) error {
100+
// no op.
101+
// TODO: Chainloop might have their own private enterprise number with the Internet Assigned Numbers Authority
102+
// to embed its own identity information in the resulting certificate
103+
cert.Subject = pkix.Name{Organization: []string{p.orgID}}
104+
105+
return nil
106+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
//
2+
// Copyright 2024 The Chainloop Authors.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
package biz_test
17+
18+
import (
19+
"context"
20+
"crypto/ecdsa"
21+
"crypto/elliptic"
22+
"crypto/rand"
23+
"crypto/x509"
24+
"crypto/x509/pkix"
25+
"encoding/pem"
26+
"fmt"
27+
"testing"
28+
29+
"github.com/chainloop-dev/chainloop/app/controlplane/internal/biz"
30+
"github.com/sigstore/fulcio/pkg/ca/ephemeralca"
31+
"github.com/sigstore/sigstore/pkg/cryptoutils"
32+
"github.com/stretchr/testify/suite"
33+
)
34+
35+
type signingUseCaseTestSuite struct {
36+
suite.Suite
37+
uc *biz.SigningUseCase
38+
csr []byte
39+
}
40+
41+
func (s *signingUseCaseTestSuite) TestSigningUseCase_CreateSigningCert() {
42+
s.Run("with empty certificate", func() {
43+
_, err := s.uc.CreateSigningCert(context.TODO(), "myorgid", make([]byte, 0))
44+
s.Error(err)
45+
})
46+
47+
s.Run("with certificate request", func() {
48+
certChain, err := s.uc.CreateSigningCert(context.TODO(), "myorgid", s.csr)
49+
s.NoError(err)
50+
51+
// assert 2 certificates: signing certificate + chain (only one)
52+
s.Len(certChain, 2)
53+
54+
// check cert contents
55+
cert, err := cryptoutils.UnmarshalCertificatesFromPEM([]byte(certChain[0]))
56+
s.NoError(err)
57+
s.Len(cert, 1)
58+
s.Equal("myorgid", cert[0].Subject.Organization[0])
59+
})
60+
}
61+
62+
func TestSuite(t *testing.T) {
63+
suite.Run(t, new(signingUseCaseTestSuite))
64+
}
65+
66+
func (s *signingUseCaseTestSuite) SetupTest() {
67+
csr, err := createCSR()
68+
s.Require().NoError(err)
69+
s.csr = csr
70+
71+
ca, err := ephemeralca.NewEphemeralCA()
72+
s.Require().NoError(err)
73+
s.uc = &biz.SigningUseCase{CA: ca}
74+
}
75+
76+
func createCSR() ([]byte, error) {
77+
priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
78+
if err != nil {
79+
return nil, fmt.Errorf("generating cert: %w", err)
80+
}
81+
csrTmpl := &x509.CertificateRequest{Subject: pkix.Name{CommonName: "ephemeral certificate"}}
82+
derCSR, err := x509.CreateCertificateRequest(rand.Reader, csrTmpl, priv)
83+
if err != nil {
84+
return nil, fmt.Errorf("generating certificate request: %w", err)
85+
}
86+
87+
// Encode CSR to PEM
88+
pemCSR := pem.EncodeToMemory(&pem.Block{
89+
Type: "CERTIFICATE REQUEST",
90+
Bytes: derCSR,
91+
})
92+
93+
return pemCSR, nil
94+
}

go.mod

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ require (
2929
github.com/google/wire v0.6.0
3030
github.com/googleapis/gax-go/v2 v2.12.3
3131
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0
32-
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
32+
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20210315223345-82c243799c99
3333
github.com/hashicorp/vault/api v1.12.2
3434
github.com/hedwigz/entviz v0.0.0-20221011080911-9d47f6f1d818
3535
github.com/improbable-eng/grpc-web v0.15.0
@@ -80,6 +80,7 @@ require (
8080
github.com/openvex/go-vex v0.2.5
8181
github.com/posthog/posthog-go v0.0.0-20240327112532-87b23fe11103
8282
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1
83+
github.com/sigstore/fulcio v1.4.5
8384
github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.3
8485
github.com/sigstore/sigstore/pkg/signature/kms/azure v1.8.3
8586
github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.8.3
@@ -118,14 +119,17 @@ require (
118119
github.com/go-jose/go-jose/v4 v4.0.1 // indirect
119120
github.com/go-playground/assert/v2 v2.2.0 // indirect
120121
github.com/go-sql-driver/mysql v1.8.1 // indirect
122+
github.com/goadesign/goa v2.2.5+incompatible // indirect
121123
github.com/gobwas/ws v1.2.1 // indirect
122124
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
123125
github.com/google/cel-go v0.20.1 // indirect
124126
github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect
125127
github.com/google/go-github/v55 v55.0.0 // indirect
126128
github.com/google/renameio/v2 v2.0.0 // indirect
127129
github.com/gorilla/handlers v1.5.1 // indirect
130+
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // indirect
128131
github.com/hashicorp/go-hclog v1.5.0 // indirect
132+
github.com/hashicorp/golang-lru v1.0.2 // indirect
129133
github.com/hashicorp/yamux v0.1.1 // indirect
130134
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
131135
github.com/jackc/pgconn v1.14.3 // indirect
@@ -155,11 +159,13 @@ require (
155159
github.com/sergi/go-diff v1.3.1 // indirect
156160
github.com/skeema/knownhosts v1.2.1 // indirect
157161
github.com/sourcegraph/conc v0.3.0 // indirect
162+
github.com/spiffe/go-spiffe/v2 v2.2.0 // indirect
158163
github.com/stoewer/go-strcase v1.3.0 // indirect
159164
github.com/xanzy/ssh-agent v0.3.3 // indirect
160165
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect
161166
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
162167
go.opentelemetry.io/otel/metric v1.24.0 // indirect
168+
goa.design/goa v2.2.5+incompatible // indirect
163169
gopkg.in/go-jose/go-jose.v2 v2.6.3 // indirect
164170
gopkg.in/warnings.v0 v0.1.2 // indirect
165171
)

go.sum

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,8 @@ github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4
557557
github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
558558
github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg=
559559
github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
560+
github.com/goadesign/goa v2.2.5+incompatible h1:SLgzk0V+QfFs7MVz9sbDHelbTDI9B/d4W7Hl5udTynY=
561+
github.com/goadesign/goa v2.2.5+incompatible/go.mod h1:d/9lpuZBK7HFi/7O0oXfwvdoIl+nx2bwKqctZe/lQao=
560562
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
561563
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
562564
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
@@ -732,11 +734,14 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDa
732734
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8=
733735
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk=
734736
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI=
735-
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
736737
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
738+
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20210315223345-82c243799c99 h1:JYghRBlGCZyCF2wNUJ8W0cwaQdtpcssJ4CgC406g+WU=
739+
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20210315223345-82c243799c99/go.mod h1:3bDW6wMZJB7tiONtC/1Xpicra6Wp5GgbTbQWCbI5fkc=
737740
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
738741
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
739742
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
743+
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0QDGLKzqOmktBjT+Is=
744+
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM=
740745
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
741746
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
742747
github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M=
@@ -787,6 +792,8 @@ github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA
787792
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
788793
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
789794
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
795+
github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
796+
github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
790797
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
791798
github.com/hashicorp/hcl v1.0.1-vault-5 h1:kI3hhbbyzr4dldA8UdTb7ZlVVlI2DACdCfz31RPDgJM=
792799
github.com/hashicorp/hcl v1.0.1-vault-5/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM=
@@ -1172,6 +1179,7 @@ github.com/posthog/posthog-go v0.0.0-20240327112532-87b23fe11103/go.mod h1:Qjlpr
11721179
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
11731180
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
11741181
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
1182+
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
11751183
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
11761184
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
11771185
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
@@ -1189,6 +1197,7 @@ github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6T
11891197
github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos=
11901198
github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8=
11911199
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
1200+
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
11921201
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
11931202
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
11941203
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
@@ -1199,6 +1208,7 @@ github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16
11991208
github.com/prometheus/common v0.51.1 h1:eIjN50Bwglz6a/c3hAgSMcofL3nD+nFQkV6Dd4DsQCw=
12001209
github.com/prometheus/common v0.51.1/go.mod h1:lrWtQx+iDfn2mbH5GUzlH9TSHyfZpHkSiG1W7y3sF2Q=
12011210
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
1211+
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
12021212
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
12031213
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
12041214
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
@@ -1482,6 +1492,8 @@ go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
14821492
go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
14831493
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
14841494
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
1495+
goa.design/goa v2.2.5+incompatible h1:mjAtiy7ZdZIkj974hpFxCR6bL69qprfV00Veu3Vybts=
1496+
goa.design/goa v2.2.5+incompatible/go.mod h1:NnzBwdNktihbNek+pPiFMQP9PPFsUt8MMPPyo9opDSo=
14851497
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
14861498
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
14871499
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
@@ -1992,6 +2004,7 @@ google.golang.org/genproto/googleapis/bytestream v0.0.0-20240318140521-94a12d6c2
19922004
google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4=
19932005
google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY=
19942006
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
2007+
google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
19952008
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
19962009
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
19972010
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=

0 commit comments

Comments
 (0)