Skip to content
Snippets Groups Projects
Commit 5c87b1be authored by Martin Stiemerling's avatar Martin Stiemerling :speech_balloon:
Browse files

Merge branch '23-tls-support-for-gnmi-target' into 'develop'

Resolve "TLS support for gnmi-target"

Closes #23

See merge request !25
parents 2013da4c 0c889ce5
No related branches found
No related tags found
2 merge requests!30Move from develop to master as default branch,!25Resolve "TLS support for gnmi-target"
Pipeline #158397 passed
...@@ -42,6 +42,11 @@ container: build ...@@ -42,6 +42,11 @@ container: build
container-debug: container-debug:
docker buildx build --rm -t gnmi-target-debug --load -f ./Dockerfile.debug . docker buildx build --rm -t gnmi-target-debug --load -f ./Dockerfile.debug .
self-certs:
mkdir -p ./artifacts/ssl/private
mkdir -p ./artifacts/ssl/certs
openssl req -x509 -nodes -days 365 -newkey rsa:4096 -keyout ./artifacts/ssl/private/gnmi-target-selfsigned.key -out ./artifacts/ssl/certs/gnmi-target-selfsigned.crt
# other targets # other targets
cross: cross:
go build -o ${OUTPUT} go build -o ${OUTPUT}
......
...@@ -8,7 +8,28 @@ To update the generated ygot structs from yang modules you can simply run `make ...@@ -8,7 +8,28 @@ To update the generated ygot structs from yang modules you can simply run `make
To use the target: (after the obligatory `go install`) run `gnmi-target start` to start the gNMI server with default configuration (OS client: ubuntu) To use the target: (after the obligatory `go install`) run `gnmi-target start` to start the gNMI server with default configuration (OS client: ubuntu)
To request all data with `gnmiclient`: run `gnmic -a localhost:7030 -u admin -p admsdsdin --insecure get --path "/"` ### Options to start the gNMI target
To start the target with TLS you have to provide a certificate (command line option `--cert <path-to-cert>`) and a private key (command line option `--key <path-to-key>`)
It is recommended to always use TLS.
For testing purposes the Makefile provides the option `make self-certs`. This generates a self-signed certificate and the corresponding private key. They are both stored under the directory `artifacts/ssl` in the source code directory.
However, you can also run the target with not TLS enabled by specifying the command line option `--insecure`.
## Requesting Data from the target
### With TLS and self-signed certificates
To request all data with `gnmiclient` run this command
`gnmic -a localhost:7030 -u admin -p admsdsdin --skip-verify get --path "/"`
### With no TLS
To request all data with `gnmiclient`: run this command
`gnmic -a localhost:7030 -u admin -p admsdsdin --insecure get --path "/"`
--- ---
......
/* /*
Copyright © 2021 da/net Research Group <danet@h-da.de> Copyright © 2023 da/net Research Group <danet@h-da.de>
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met: modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer. this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, 2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution. and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors 3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software may be used to endorse or promote products derived from this software
without specific prior written permission. without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
......
/* /*
Copyright © 2021 da/net Research Group <danet@h-da.de> Copyright © 2023 da/net Research Group <danet@h-da.de>
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
...@@ -41,23 +41,28 @@ import ( ...@@ -41,23 +41,28 @@ import (
) )
var ( var (
bindAddress string bindAddress string // IP/Port to bind to listen for the gnmi server
configFile string configFile string // my config file to use
osclient string osclient string // TODO unclear
logLevel string logLevel string // which loglevel to use
certFile string // the location of the file containing the X.509 certificates for the gnmi server
keyFile string // the location of the file containing the key for the certificates for the gnmi server
insecure *bool // set to true if insecure operations is needed, i.e., do not use TLS
// Below is qkdn specific information
udpQL1AddrString string udpQL1AddrString string
ql1Name string ql1Name string
udpQL2AddrString string udpQL2AddrString string
ql2Name string ql2Name string
// End of qkdn specific information
) )
// startCmd represents the start command // startCmd represents the start command
var startCmd = &cobra.Command{ var startCmd = &cobra.Command{
Use: "start", Use: "start",
Short: "Start gnmi server", Short: "Start gnmi server",
Long: `A Linux GNMI target that does GNMI target stuff`, Long: `A gNMI target`,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Startup GNMI Target...") fmt.Println("Startup of GNMI Target...")
lvl := viper.GetString("logLevel") lvl := viper.GetString("logLevel")
// parse string, this is built-in feature of logrus // parse string, this is built-in feature of logrus
...@@ -77,7 +82,7 @@ var startCmd = &cobra.Command{ ...@@ -77,7 +82,7 @@ var startCmd = &cobra.Command{
} }
gnmitTarget := gnmitarget.NewGnmiTarget(&qkdnBootInfo) gnmitTarget := gnmitarget.NewGnmiTarget(&qkdnBootInfo)
if err := gnmitTarget.Start(viper.GetString("bindAddress")); err != nil { if err := gnmitTarget.Start(viper.GetString("bindAddress"), viper.GetString("certFile"), viper.GetString("keyFile"), *insecure); err != nil {
logrus.Fatal(err) logrus.Fatal(err)
} }
}, },
...@@ -88,7 +93,9 @@ func init() { ...@@ -88,7 +93,9 @@ func init() {
startCmd.Flags().StringVarP(&configFile, "config", "c", "config/openconfig.json", "system configuration") startCmd.Flags().StringVarP(&configFile, "config", "c", "config/openconfig.json", "system configuration")
startCmd.Flags().StringVarP(&bindAddress, "bind_address", "a", ":7030", "address to bind to") startCmd.Flags().StringVarP(&bindAddress, "bind_address", "a", ":7030", "address to bind to")
startCmd.Flags().StringVarP(&logLevel, "log", "l", "info", "loglevel") startCmd.Flags().StringVarP(&logLevel, "log", "l", "info", "loglevel")
startCmd.Flags().Bool("tls", false, "Use Viper for configuration") insecure = startCmd.Flags().Bool("insecure", false, "If true do not use TLS")
startCmd.Flags().StringVarP(&certFile, "cert", "", "", "location of the cert file")
startCmd.Flags().StringVarP(&keyFile, "key", "", "", "location of the key file")
startCmd.Flags().StringVarP(&osclient, "osclient", "o", "ubuntu", "os client to use by system") startCmd.Flags().StringVarP(&osclient, "osclient", "o", "ubuntu", "os client to use by system")
startCmd.Flags().StringVarP(&udpQL1AddrString, "my_QLE_socket", "", "[::1]:50900", "local quantum element's address") startCmd.Flags().StringVarP(&udpQL1AddrString, "my_QLE_socket", "", "[::1]:50900", "local quantum element's address")
startCmd.Flags().StringVarP(&ql1Name, "my_name", "", "ekms-ql1", "The name of the local quantumlayer") startCmd.Flags().StringVarP(&ql1Name, "my_name", "", "ekms-ql1", "The name of the local quantumlayer")
...@@ -98,7 +105,9 @@ func init() { ...@@ -98,7 +105,9 @@ func init() {
viper.BindPFlag("bindAddress", startCmd.Flags().Lookup("bind_address")) viper.BindPFlag("bindAddress", startCmd.Flags().Lookup("bind_address"))
viper.BindPFlag("configFile", startCmd.Flags().Lookup("config")) viper.BindPFlag("configFile", startCmd.Flags().Lookup("config"))
viper.BindPFlag("logLevel", startCmd.Flags().Lookup("log")) viper.BindPFlag("logLevel", startCmd.Flags().Lookup("log"))
viper.BindPFlag("useTLS", startCmd.Flags().Lookup("tls")) viper.BindPFlag("insecure", startCmd.Flags().Lookup("insecure"))
viper.BindPFlag("certFile", startCmd.Flags().Lookup("cert"))
viper.BindPFlag("keyFile", startCmd.Flags().Lookup("key"))
viper.BindPFlag("osclient", startCmd.Flags().Lookup("osclient")) viper.BindPFlag("osclient", startCmd.Flags().Lookup("osclient"))
viper.BindPFlag("my_QLE_socket", startCmd.Flags().Lookup("my-address")) viper.BindPFlag("my_QLE_socket", startCmd.Flags().Lookup("my-address"))
viper.BindPFlag("my_name", startCmd.Flags().Lookup("my-name")) viper.BindPFlag("my_name", startCmd.Flags().Lookup("my-name"))
......
...@@ -127,5 +127,10 @@ func (gt *GnmiTarget) InitializeConfig() (ygot.ValidatedGoStruct, error) { ...@@ -127,5 +127,10 @@ func (gt *GnmiTarget) InitializeConfig() (ygot.ValidatedGoStruct, error) {
}() }()
} }
return conf, customerrs.CombinedErrListError{Errors: errs} if len(errs) != 0 {
return conf, customerrs.CombinedErrListError{Errors: errs}
} else {
return conf, nil
}
} }
package gnmitarget package gnmitarget
import ( import (
"time"
"code.fbi.h-da.de/danet/gnmi-target/etsiqkdnclient" "code.fbi.h-da.de/danet/gnmi-target/etsiqkdnclient"
"code.fbi.h-da.de/danet/gnmi-target/gnmiserver" "code.fbi.h-da.de/danet/gnmi-target/gnmiserver"
not "code.fbi.h-da.de/danet/gnmi-target/notifications" not "code.fbi.h-da.de/danet/gnmi-target/notifications"
...@@ -13,6 +11,7 @@ import ( ...@@ -13,6 +11,7 @@ import (
"reflect" "reflect"
"google.golang.org/grpc" "google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/reflection" "google.golang.org/grpc/reflection"
"code.fbi.h-da.de/danet/gnmi-target/modeldata" "code.fbi.h-da.de/danet/gnmi-target/modeldata"
...@@ -41,10 +40,7 @@ func NewGnmiTarget(qkdnBootInfo *etsiqkdnclient.EtsiQkdClientInfo) *GnmiTarget { ...@@ -41,10 +40,7 @@ func NewGnmiTarget(qkdnBootInfo *etsiqkdnclient.EtsiQkdClientInfo) *GnmiTarget {
} }
} }
func (gt *GnmiTarget) Start(bindAddress string) error { func (gt *GnmiTarget) Start(bindAddress string, certFile string, keyFile string, insecure bool) error {
//NOTE: This sleep is currently just for testing purposes to play around with
//containerlab.
time.Sleep(5 * time.Second)
schema, err := gnmitargetygot.Schema() schema, err := gnmitargetygot.Schema()
if err != nil { if err != nil {
...@@ -67,6 +63,7 @@ func (gt *GnmiTarget) Start(bindAddress string) error { ...@@ -67,6 +63,7 @@ func (gt *GnmiTarget) Start(bindAddress string) error {
} }
} }
// Initialize ygot structs with the current device configuration
config, err := gt.InitializeConfig() config, err := gt.InitializeConfig()
if err != nil { if err != nil {
log.Error(err) log.Error(err)
...@@ -77,21 +74,35 @@ func (gt *GnmiTarget) Start(bindAddress string) error { ...@@ -77,21 +74,35 @@ func (gt *GnmiTarget) Start(bindAddress string) error {
log.Fatalf("error in creating GNMI target: %v", err) log.Fatalf("error in creating GNMI target: %v", err)
} }
// Create new GRPC Server without service registert var grpcServer *grpc.Server
grpcServer := grpc.NewServer()
if insecure == false {
// Setup credentials for secured message transport
grpcCredentials, err := credentials.NewServerTLSFromFile(certFile, keyFile)
if err != nil {
log.Fatalf("error in opening the TLS certificate: %v", err)
}
// Create new GRPC Server without service registered
grpcServer = grpc.NewServer(grpc.Creds(grpcCredentials))
} else {
log.Infof("\n\n*****WARNING*********WARNING*****\nStarting without secured gnmi server!\nAll gnmi transmissions are unencrypted\n*****WARNING*********WARNING*****\n\n")
// Create new GRPC Server without service registered
grpcServer = grpc.NewServer()
}
// Register GNMI Server // Register GNMI Server
pbGNMI.RegisterGNMIServer(grpcServer, gnmiServer) pbGNMI.RegisterGNMIServer(grpcServer, gnmiServer)
reflection.Register(grpcServer) reflection.Register(grpcServer)
// Start Server // Start Server
log.Infof("Starting target server to listen on %s", bindAddress) log.Infof("Starting gnmi-target server to listen on %s", bindAddress)
listener, err := net.Listen("tcp", bindAddress) listener, err := net.Listen("tcp", bindAddress)
if err != nil { if err != nil {
log.Fatalf("Failed to list due to: %v", err) log.Fatalf("Failed to list due to: %v", err)
} }
log.Info("Target is starting to serve requests") log.Info("gnmi-target is ready to serve requests.")
err = grpcServer.Serve(listener) err = grpcServer.Serve(listener)
if err != nil { if err != nil {
log.Fatalf("Failed to serve requests due to: %v", err) log.Fatalf("Failed to serve requests due to: %v", err)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment