/* * * 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) } }