This repository was archived by the owner on Aug 31, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 96
[telemetry] Reload telemetry server configuration. #92
Open
yozhao101
wants to merge
5
commits into
master
Choose a base branch
from
telemetry_server_reload_configuration
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
c40f036
[telemetry server] Reloads telemetry server configuration once receiv…
yozhao101 063239a
[telemetry server] Remove extra spaces.
yozhao101 2051071
[telemetry server] Remove extra spaces.
yozhao101 c2b10cd
[telemetry] Fix the typoes.
yozhao101 d396fe4
[telemetry] Fix the indentation issue.
yozhao101 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,146 +1,168 @@ | ||
| package main | ||
|
|
||
| import ( | ||
| "crypto/tls" | ||
| "crypto/x509" | ||
| "flag" | ||
| "io/ioutil" | ||
| "time" | ||
|
|
||
| log "github.com/golang/glog" | ||
| "google.golang.org/grpc" | ||
| "google.golang.org/grpc/credentials" | ||
|
|
||
| gnmi "github.com/Azure/sonic-telemetry/gnmi_server" | ||
| testcert "github.com/Azure/sonic-telemetry/testdata/tls" | ||
| "crypto/tls" | ||
| "crypto/x509" | ||
| "flag" | ||
| "io/ioutil" | ||
| "os" | ||
| "os/signal" | ||
| "syscall" | ||
| "time" | ||
|
|
||
| log "github.com/golang/glog" | ||
| "google.golang.org/grpc" | ||
| "google.golang.org/grpc/credentials" | ||
|
|
||
| gnmi "github.com/Azure/sonic-telemetry/gnmi_server" | ||
| testcert "github.com/Azure/sonic-telemetry/testdata/tls" | ||
| ) | ||
|
|
||
| var ( | ||
| userAuth = gnmi.AuthTypes{"password": false, "cert": false, "jwt": false} | ||
| port = flag.Int("port", -1, "port to listen on") | ||
| // Certificate files. | ||
| caCert = flag.String("ca_crt", "", "CA certificate for client certificate validation. Optional.") | ||
| serverCert = flag.String("server_crt", "", "TLS server certificate") | ||
| serverKey = flag.String("server_key", "", "TLS server private key") | ||
| insecure = flag.Bool("insecure", false, "Skip providing TLS cert and key, for testing only!") | ||
| noTLS = flag.Bool("noTLS", false, "disable TLS, for testing only!") | ||
| allowNoClientCert = flag.Bool("allow_no_client_auth", false, "When set, telemetry server will request but not require a client certificate.") | ||
| jwtRefInt = flag.Uint64("jwt_refresh_int", 900, "Seconds before JWT expiry the token can be refreshed.") | ||
| jwtValInt = flag.Uint64("jwt_valid_int", 3600, "Seconds that JWT token is valid for.") | ||
| userAuth = gnmi.AuthTypes{"password": false, "cert": false, "jwt": false} | ||
| port = flag.Int("port", -1, "port to listen on") | ||
| // Certificate files. | ||
| caCert = flag.String("ca_crt", "", "CA certificate for client certificate validation. Optional.") | ||
| serverCert = flag.String("server_crt", "", "TLS server certificate") | ||
| serverKey = flag.String("server_key", "", "TLS server private key") | ||
| insecure = flag.Bool("insecure", false, "Skip providing TLS cert and key, for testing only!") | ||
| noTLS = flag.Bool("noTLS", false, "disable TLS, for testing only!") | ||
| allowNoClientCert = flag.Bool("allow_no_client_auth", false, "When set, telemetry server will request but not require a client certificate.") | ||
| jwtRefInt = flag.Uint64("jwt_refresh_int", 900, "Seconds before JWT expiry the token can be refreshed.") | ||
| jwtValInt = flag.Uint64("jwt_valid_int", 3600, "Seconds that JWT token is valid for.") | ||
| ) | ||
|
|
||
| // SignalHandler will block and wait for the signal `SIGHUP`. Once it receives signal, | ||
| // the gRPC server will be stopped and new gRPC server instance will be created with | ||
| // updated certificate and key files. | ||
| func SignalHandler(server *gnmi.Server, signalChannel <-chan os.Signal) { | ||
| signalReceiver := <-signalChannel | ||
| log.V(1).Infof("gRPC server receives signal: %s and will be stopped!", signalReceiver) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should check that the signal received from channel is sighup before stopping server in case we want to reuse signal handler |
||
| log.V(1).Infof("gRPC server is being stopped ...") | ||
| server.Stop() | ||
| log.V(1).Infof("gRPC server is stopped!") | ||
| } | ||
|
|
||
| func main() { | ||
| flag.Var(userAuth, "client_auth", "Client auth mode(s) - none,cert,password") | ||
| flag.Parse() | ||
| flag.Var(userAuth, "client_auth", "Client auth mode(s) - none,cert,password") | ||
| flag.Parse() | ||
|
|
||
| var defUserAuth gnmi.AuthTypes | ||
| if gnmi.READ_WRITE_MODE { | ||
| //In read/write mode we want to enable auth by default. | ||
| defUserAuth = gnmi.AuthTypes{"password": true, "cert": false, "jwt": true} | ||
| }else { | ||
| defUserAuth = gnmi.AuthTypes{"jwt": false, "password": false, "cert": false} | ||
| } | ||
| signalChannel := make(chan os.Signal, 1) | ||
| signal.Notify(signalChannel, syscall.SIGHUP) | ||
|
|
||
| if isFlagPassed("client_auth") { | ||
| log.V(1).Infof("client_auth provided") | ||
| for { | ||
| var defUserAuth gnmi.AuthTypes | ||
| if gnmi.READ_WRITE_MODE { | ||
| //In read/write mode we want to enable auth by default. | ||
| defUserAuth = gnmi.AuthTypes{"password": true, "cert": false, "jwt": true} | ||
| }else { | ||
| log.V(1).Infof("client_auth not provided, using defaults.") | ||
| userAuth = defUserAuth | ||
| defUserAuth = gnmi.AuthTypes{"jwt": false, "password": false, "cert": false} | ||
| } | ||
|
|
||
| switch { | ||
| case *port <= 0: | ||
| log.Errorf("port must be > 0.") | ||
| return | ||
| } | ||
| gnmi.JwtRefreshInt = time.Duration(*jwtRefInt*uint64(time.Second)) | ||
| gnmi.JwtValidInt = time.Duration(*jwtValInt*uint64(time.Second)) | ||
|
|
||
| cfg := &gnmi.Config{} | ||
| cfg.Port = int64(*port) | ||
| var opts []grpc.ServerOption | ||
|
|
||
| if !*noTLS { | ||
| var certificate tls.Certificate | ||
| var err error | ||
| if *insecure { | ||
| certificate, err = testcert.NewCert() | ||
| if err != nil { | ||
| log.Exitf("could not load server key pair: %s", err) | ||
| } | ||
| } else { | ||
| switch { | ||
| case *serverCert == "": | ||
| log.Errorf("serverCert must be set.") | ||
| return | ||
| case *serverKey == "": | ||
| log.Errorf("serverKey must be set.") | ||
| return | ||
| } | ||
| certificate, err = tls.LoadX509KeyPair(*serverCert, *serverKey) | ||
| if err != nil { | ||
| log.Exitf("could not load server key pair: %s", err) | ||
| } | ||
| } | ||
| if isFlagPassed("client_auth") { | ||
| log.V(1).Infof("client_auth provided") | ||
| }else { | ||
| log.V(1).Infof("client_auth not provided, using defaults.") | ||
| userAuth = defUserAuth | ||
| } | ||
|
|
||
| tlsCfg := &tls.Config{ | ||
| ClientAuth: tls.RequireAndVerifyClientCert, | ||
| Certificates: []tls.Certificate{certificate}, | ||
| MinVersion: tls.VersionTLS12, | ||
| CurvePreferences: []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256}, | ||
| PreferServerCipherSuites: true, | ||
| CipherSuites: []uint16{ | ||
| tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, | ||
| tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, | ||
| tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, | ||
| tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, | ||
| tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, | ||
| tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, | ||
| }, | ||
| } | ||
|
|
||
| if *allowNoClientCert { | ||
| // RequestClientCert will ask client for a certificate but won't | ||
| // require it to proceed. If certificate is provided, it will be | ||
| // verified. | ||
| tlsCfg.ClientAuth = tls.RequestClientCert | ||
| } | ||
|
|
||
| if *caCert != "" { | ||
| ca, err := ioutil.ReadFile(*caCert) | ||
| if err != nil { | ||
| log.Exitf("could not read CA certificate: %s", err) | ||
| } | ||
| certPool := x509.NewCertPool() | ||
| if ok := certPool.AppendCertsFromPEM(ca); !ok { | ||
| log.Exit("failed to append CA certificate") | ||
| } | ||
| tlsCfg.ClientCAs = certPool | ||
| } else { | ||
| if userAuth.Enabled("cert") { | ||
| userAuth.Unset("cert") | ||
| log.Warning("client_auth mode cert requires ca_crt option. Disabling cert mode authentication.") | ||
| switch { | ||
| case *port <= 0: | ||
| log.Errorf("port must be > 0.") | ||
| return | ||
| } | ||
| } | ||
|
|
||
| opts = []grpc.ServerOption{grpc.Creds(credentials.NewTLS(tlsCfg))} | ||
| cfg := &gnmi.Config{} | ||
| cfg.Port = int64(*port) | ||
| cfg.UserAuth = userAuth | ||
| gnmi.JwtRefreshInt = time.Duration(*jwtRefInt*uint64(time.Second)) | ||
| gnmi.JwtValidInt = time.Duration(*jwtValInt*uint64(time.Second)) | ||
|
|
||
| cfg := &gnmi.Config{} | ||
| cfg.Port = int64(*port) | ||
| var opts []grpc.ServerOption | ||
|
|
||
| if !*noTLS { | ||
| var certificate tls.Certificate | ||
| var err error | ||
| if *insecure { | ||
| certificate, err = testcert.NewCert() | ||
| if err != nil { | ||
| log.Exitf("could not load server key pair: %s", err) | ||
| } | ||
| } else { | ||
| switch { | ||
| case *serverCert == "": | ||
| log.Errorf("serverCert must be set.") | ||
| return | ||
| case *serverKey == "": | ||
| log.Errorf("serverKey must be set.") | ||
| return | ||
| } | ||
| certificate, err = tls.LoadX509KeyPair(*serverCert, *serverKey) | ||
| if err != nil { | ||
| log.Exitf("could not load server key pair: %s", err) | ||
| } | ||
| } | ||
|
|
||
| tlsCfg := &tls.Config{ | ||
| ClientAuth: tls.RequireAndVerifyClientCert, | ||
| Certificates: []tls.Certificate{certificate}, | ||
| MinVersion: tls.VersionTLS12, | ||
| CurvePreferences: []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256}, | ||
| PreferServerCipherSuites: true, | ||
| CipherSuites: []uint16{ | ||
| tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, | ||
| tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, | ||
| tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, | ||
| tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, | ||
| tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, | ||
| tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, | ||
| }, | ||
| } | ||
|
|
||
| if *allowNoClientCert { | ||
| // RequestClientCert will ask client for a certificate but won't | ||
| // require it to proceed. If certificate is provided, it will be | ||
| // verified. | ||
| tlsCfg.ClientAuth = tls.RequestClientCert | ||
| } | ||
|
|
||
| if *caCert != "" { | ||
| ca, err := ioutil.ReadFile(*caCert) | ||
| if err != nil { | ||
| log.Exitf("could not read CA certificate: %s", err) | ||
| } | ||
| certPool := x509.NewCertPool() | ||
| if ok := certPool.AppendCertsFromPEM(ca); !ok { | ||
| log.Exit("failed to append CA certificate") | ||
| } | ||
| tlsCfg.ClientCAs = certPool | ||
| } else { | ||
| if userAuth.Enabled("cert") { | ||
| userAuth.Unset("cert") | ||
| log.Warning("client_auth mode cert requires ca_crt option. Disabling cert mode authentication.") | ||
| } | ||
| } | ||
|
|
||
| opts = []grpc.ServerOption{grpc.Creds(credentials.NewTLS(tlsCfg))} | ||
| cfg := &gnmi.Config{} | ||
| cfg.Port = int64(*port) | ||
| cfg.UserAuth = userAuth | ||
|
|
||
| gnmi.GenerateJwtSecretKey() | ||
| } | ||
|
|
||
| gnmi.GenerateJwtSecretKey() | ||
| } | ||
| s, err := gnmi.NewServer(cfg, opts) | ||
| if err != nil { | ||
| log.Errorf("Failed to create gNMI server: %v", err) | ||
| return | ||
| } | ||
|
|
||
| s, err := gnmi.NewServer(cfg, opts) | ||
| if err != nil { | ||
| log.Errorf("Failed to create gNMI server: %v", err) | ||
| return | ||
| } | ||
| go SignalHandler(s, signalChannel) | ||
|
|
||
| log.V(1).Infof("Auth Modes: ", userAuth) | ||
| log.V(1).Infof("Starting RPC server on address: %s", s.Address()) | ||
| s.Serve() // blocks until close | ||
| log.Flush() | ||
| log.V(1).Infof("Auth Modes: ", userAuth) | ||
| log.V(1).Infof("Starting RPC server on address: %s", s.Address()) | ||
| s.Serve() // blocks until close | ||
| log.Flush() | ||
| } | ||
| } | ||
|
|
||
| func isFlagPassed(name string) bool { | ||
|
|
||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a sonic-mgmt test case and test the process of certificate rotation.