grpc-go/examples/features/advancedtls/server/main.go

178 lines
4.9 KiB
Go

/*
*
* Copyright 2024 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.
*
*/
// Binary server is an example client demonstrating how to set up a secure gRPC
// server using advancedtls.
package main
import (
"context"
"flag"
"fmt"
"net"
"os"
"path/filepath"
"time"
pb "google.golang.org/grpc/examples/features/proto/echo"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/credentials/tls/certprovider"
"google.golang.org/grpc/credentials/tls/certprovider/pemfile"
"google.golang.org/grpc/security/advancedtls"
)
type server struct {
pb.UnimplementedEchoServer
name string
}
const credRefreshInterval = 1 * time.Minute
const goodServerWithCRLPort int = 50051
const revokedServerWithCRLPort int = 50053
const insecurePort int = 50054
func (s *server) UnaryEcho(_ context.Context, req *pb.EchoRequest) (*pb.EchoResponse, error) {
return &pb.EchoResponse{Message: req.Message}, nil
}
func insecureServer() {
createAndRunInsecureServer(insecurePort)
}
func createAndRunInsecureServer(port int) {
creds := insecure.NewCredentials()
s := grpc.NewServer(grpc.Creds(creds))
lis, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
if err != nil {
fmt.Printf("Failed to listen: %v\n", err)
}
pb.RegisterEchoServer(s, &server{name: "Insecure Server"})
if err := s.Serve(lis); err != nil {
fmt.Printf("Failed to serve: %v\n", err)
os.Exit(1)
}
}
func createAndRunTLSServer(credsDirectory string, useRevokedCert bool, port int) {
identityProvider := makeIdentityProvider(useRevokedCert, credsDirectory)
defer identityProvider.Close()
rootProvider := makeRootProvider(credsDirectory)
defer rootProvider.Close()
crlProvider := makeCRLProvider(filepath.Join(credsDirectory, "crl"))
defer crlProvider.Close()
options := &advancedtls.Options{
IdentityOptions: advancedtls.IdentityCertificateOptions{
IdentityProvider: identityProvider,
},
RootOptions: advancedtls.RootCertificateOptions{
RootProvider: rootProvider,
},
RequireClientCert: true,
VerificationType: advancedtls.CertVerification,
}
options.RevocationOptions = &advancedtls.RevocationOptions{
CRLProvider: crlProvider,
}
serverTLSCreds, err := advancedtls.NewServerCreds(options)
if err != nil {
fmt.Printf("Error %v\n", err)
os.Exit(1)
}
s := grpc.NewServer(grpc.Creds(serverTLSCreds))
lis, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
if err != nil {
fmt.Printf("Failed to listen: %v\n", err)
}
name := "Good TLS Server"
if useRevokedCert {
name = "Revoked TLS Server"
}
pb.RegisterEchoServer(s, &server{name: name})
if err := s.Serve(lis); err != nil {
fmt.Printf("Failed to serve: %v\n", err)
os.Exit(1)
}
}
func makeRootProvider(credsDirectory string) certprovider.Provider {
rootOptions := pemfile.Options{
RootFile: filepath.Join(credsDirectory, "/ca_cert.pem"),
RefreshDuration: credRefreshInterval,
}
rootProvider, err := pemfile.NewProvider(rootOptions)
if err != nil {
fmt.Printf("Error %v\n", err)
os.Exit(1)
}
return rootProvider
}
func makeIdentityProvider(useRevokedCert bool, credsDirectory string) certprovider.Provider {
certFilePath := ""
if useRevokedCert {
certFilePath = filepath.Join(credsDirectory, "server_cert_revoked.pem")
} else {
certFilePath = filepath.Join(credsDirectory, "server_cert.pem")
}
identityOptions := pemfile.Options{
CertFile: certFilePath,
KeyFile: filepath.Join(credsDirectory, "server_key.pem"),
RefreshDuration: credRefreshInterval,
}
identityProvider, err := pemfile.NewProvider(identityOptions)
if err != nil {
fmt.Printf("Error %v\n", err)
os.Exit(1)
}
return identityProvider
}
func makeCRLProvider(crlDirectory string) *advancedtls.FileWatcherCRLProvider {
options := advancedtls.FileWatcherOptions{
CRLDirectory: crlDirectory,
}
provider, err := advancedtls.NewFileWatcherCRLProvider(options)
if err != nil {
fmt.Printf("Error making CRL Provider: %v\nExiting...", err)
os.Exit(1)
}
return provider
}
func main() {
credentialsDirectory := flag.String("credentials_directory", "", "Path to the creds directory of this repo")
flag.Parse()
if *credentialsDirectory == "" {
fmt.Println("Must set credentials_directory argument")
os.Exit(1)
}
go createAndRunTLSServer(*credentialsDirectory, false, goodServerWithCRLPort)
go createAndRunTLSServer(*credentialsDirectory, true, revokedServerWithCRLPort)
insecureServer()
}