snapshot of https://github.com/grpc/grpc-go.git (master, 2026-09-15; blobs > 131072B omitted)
Some checks failed
codecov / upload (push) Failing after 13m59s
CodeQL / Analyze (push) Failing after 1s
Testing / vet-proto (push) Failing after 1s
Testing / tests (arm, latest) (push) Waiting to run
Testing / extras (latest) (push) Failing after 1s
Testing / static checks (latest-1) (push) Failing after 1s
Testing / tests (-race, latest) (push) Failing after 1s
Testing / tests (i386, latest) (push) Failing after 1s
Testing / tests (latest) (push) Failing after 1s
Testing / tests (latest-1) (push) Failing after 1s
Lock Threads / lock (push) Failing after 1s
govulncheck / govulncheck (.) (push) Failing after 1s
govulncheck / govulncheck (./cmd/protoc-gen-go-grpc) (push) Failing after 1s
govulncheck / govulncheck (./gcp/observability) (push) Failing after 1s
govulncheck / govulncheck (./security/advancedtls) (push) Failing after 1s
govulncheck / govulncheck (./stats/opencensus) (push) Failing after 1s
Stale bot / stale (push) Failing after 1s

This commit is contained in:
upstream-mirror
2026-09-15 20:40:15 +05:00
commit e241b33f26
1365 changed files with 339570 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
# Credential Reloading From Files
Credential reloading is a feature supported in the advancedtls library.
A very common way to achieve this is to reload from files.
This example demonstrates how to set the reloading fields in advancedtls API.
Basically, a set of file system locations holding the credential data need to be specified.
Once the credential data needs to be updated, users just change the credential data in the file system, and gRPC will pick up the changes automatically.
A couple of things to note:
1. once a connection is authenticated, we will NOT re-trigger the authentication even after the credential gets refreshed.
2. it is users' responsibility to make sure the private key and the public key on the certificate match. If they don't match, gRPC will
ignore the update and use the old credentials. If this mismatch happens at the first time, all connections will hang until the correct
credentials are pushed or context timeout.
## Try it
In directory `security/advancedtls/examples`:
```
go run server/main.go
```
```
go run client/main.go
```

View File

@@ -0,0 +1,111 @@
/*
*
* Copyright 2020 gRPC 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.
*
*/
// The client demonstrates how to use the credential reloading feature in
// advancedtls to make a mTLS connection to the server.
package main
import (
"context"
"flag"
"log"
"time"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/tls/certprovider/pemfile"
pb "google.golang.org/grpc/examples/helloworld/helloworld"
"google.golang.org/grpc/security/advancedtls"
"google.golang.org/grpc/security/advancedtls/testdata"
)
var address = "localhost:50051"
const (
// Default timeout for normal connections.
defaultTimeout = 2 * time.Second
// Intervals that set to monitor the credential updates.
credRefreshingInterval = 500 * time.Millisecond
)
func main() {
tmpKeyFile := flag.String("key", "", "temporary key file path")
tmpCertFile := flag.String("cert", "", "temporary cert file path")
flag.Parse()
if tmpKeyFile == nil || *tmpKeyFile == "" {
log.Fatalf("tmpKeyFile is nil or empty.")
}
if tmpCertFile == nil || *tmpCertFile == "" {
log.Fatalf("tmpCertFile is nil or empty.")
}
// Initialize credential struct using reloading API.
identityOptions := pemfile.Options{
CertFile: *tmpCertFile,
KeyFile: *tmpKeyFile,
RefreshDuration: credRefreshingInterval,
}
identityProvider, err := pemfile.NewProvider(identityOptions)
if err != nil {
log.Fatalf("pemfile.NewProvider(%v) failed: %v", identityOptions, err)
}
rootOptions := pemfile.Options{
RootFile: testdata.Path("client_trust_cert_1.pem"),
RefreshDuration: credRefreshingInterval,
}
rootProvider, err := pemfile.NewProvider(rootOptions)
if err != nil {
log.Fatalf("pemfile.NewProvider(%v) failed: %v", rootOptions, err)
}
options := &advancedtls.Options{
IdentityOptions: advancedtls.IdentityCertificateOptions{
IdentityProvider: identityProvider,
},
AdditionalPeerVerification: func(*advancedtls.HandshakeVerificationInfo) (*advancedtls.PostHandshakeVerificationResults, error) {
return &advancedtls.PostHandshakeVerificationResults{}, nil
},
RootOptions: advancedtls.RootCertificateOptions{
RootProvider: rootProvider,
},
VerificationType: advancedtls.CertVerification,
}
clientTLSCreds, err := advancedtls.NewClientCreds(options)
if err != nil {
log.Fatalf("advancedtls.NewClientCreds(%v) failed: %v", options, err)
}
// Make a connection using the credentials.
conn, err := grpc.NewClient(address, grpc.WithTransportCredentials(clientTLSCreds))
if err != nil {
log.Fatalf("grpc.NewClient to %s failed: %v", address, err)
}
client := pb.NewGreeterClient(conn)
// Send the requests every 0.5s. The credential is expected to be changed in
// the bash script. We don't cancel the context nor call conn.Close() here,
// since the bash script is expected to close the client goroutine.
for {
ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout)
_, err = client.SayHello(ctx, &pb.HelloRequest{Name: "gRPC"}, grpc.WaitForReady(true))
if err != nil {
log.Fatalf("client.SayHello failed: %v", err)
}
cancel()
time.Sleep(500 * time.Millisecond)
}
}

View File

@@ -0,0 +1,112 @@
/*
*
* Copyright 2020 gRPC 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.
*
*/
// The server demonstrates how to use the credential reloading feature in
// advancedtls to serve mTLS connections from the client.
package main
import (
"context"
"flag"
"fmt"
"log"
"net"
"time"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/tls/certprovider/pemfile"
"google.golang.org/grpc/keepalive"
"google.golang.org/grpc/security/advancedtls"
"google.golang.org/grpc/security/advancedtls/testdata"
pb "google.golang.org/grpc/examples/helloworld/helloworld"
)
var port = ":50051"
// Intervals that set to monitor the credential updates.
const credRefreshingInterval = 1 * time.Minute
type greeterServer struct {
pb.UnimplementedGreeterServer
}
// sayHello is a simple implementation of the pb.GreeterServer SayHello method.
func (greeterServer) SayHello(_ context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
return &pb.HelloReply{Message: "Hello " + in.Name}, nil
}
func main() {
flag.Parse()
fmt.Printf("server starting on port %s...\n", port)
identityOptions := pemfile.Options{
CertFile: testdata.Path("server_cert_1.pem"),
KeyFile: testdata.Path("server_key_1.pem"),
RefreshDuration: credRefreshingInterval,
}
identityProvider, err := pemfile.NewProvider(identityOptions)
if err != nil {
log.Fatalf("pemfile.NewProvider(%v) failed: %v", identityOptions, err)
}
defer identityProvider.Close()
rootOptions := pemfile.Options{
RootFile: testdata.Path("server_trust_cert_1.pem"),
RefreshDuration: credRefreshingInterval,
}
rootProvider, err := pemfile.NewProvider(rootOptions)
if err != nil {
log.Fatalf("pemfile.NewProvider(%v) failed: %v", rootOptions, err)
}
defer rootProvider.Close()
// Start a server and create a client using advancedtls API with Provider.
options := &advancedtls.Options{
IdentityOptions: advancedtls.IdentityCertificateOptions{
IdentityProvider: identityProvider,
},
RootOptions: advancedtls.RootCertificateOptions{
RootProvider: rootProvider,
},
RequireClientCert: true,
AdditionalPeerVerification: func(params *advancedtls.HandshakeVerificationInfo) (*advancedtls.PostHandshakeVerificationResults, error) {
// This message is to show the certificate under the hood is actually reloaded.
fmt.Printf("Client common name: %s.\n", params.Leaf.Subject.CommonName)
return &advancedtls.PostHandshakeVerificationResults{}, nil
},
VerificationType: advancedtls.CertVerification,
}
serverTLSCreds, err := advancedtls.NewServerCreds(options)
if err != nil {
log.Fatalf("advancedtls.NewServerCreds(%v) failed: %v", options, err)
}
s := grpc.NewServer(grpc.Creds(serverTLSCreds), grpc.KeepaliveParams(keepalive.ServerParameters{
// Set the max connection time to be 0.5 s to force the client to
// re-establish the connection, and hence re-invoke the verification
// callback.
MaxConnectionAge: 500 * time.Millisecond,
}))
lis, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
pb.RegisterGreeterServer(s, greeterServer{})
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}