diff --git a/cmd/inventory/inventory-get.go b/cmd/inventory/inventory-get.go index 2fe1caf..0153f1a 100644 --- a/cmd/inventory/inventory-get.go +++ b/cmd/inventory/inventory-get.go @@ -16,7 +16,8 @@ import ( // NewGetCommand returns the inventory get command func NewGetCommand() *cobra.Command { var ( - addr string + addr string + tlsFiles string ) cmd := &cobra.Command{ Use: "get", @@ -24,7 +25,7 @@ func NewGetCommand() *cobra.Command { Short: "Gets DPU inventory information", Args: cobra.NoArgs, Run: func(_ *cobra.Command, _ []string) { - invClient, err := inventory.New(addr) + invClient, err := inventory.New(addr, tlsFiles) if err != nil { log.Fatalf("could create gRPC client: %v", err) } @@ -41,6 +42,7 @@ func NewGetCommand() *cobra.Command { } flags := cmd.Flags() flags.StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + flags.StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") return cmd } diff --git a/cmd/ipsec/ipsec-stats.go b/cmd/ipsec/ipsec-stats.go index a26e91b..e9fafd9 100644 --- a/cmd/ipsec/ipsec-stats.go +++ b/cmd/ipsec/ipsec-stats.go @@ -15,7 +15,8 @@ import ( // NewStatsCommand returns the ipsec stats command func NewStatsCommand() *cobra.Command { var ( - addr string + addr string + tlsFiles string ) cmd := &cobra.Command{ Use: "stats", @@ -29,6 +30,7 @@ func NewStatsCommand() *cobra.Command { } flags := cmd.Flags() flags.StringVar(&addr, "addr", "localhost:50151", "address or OPI gRPC server") + flags.StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") return cmd } diff --git a/cmd/ipsec/ipsec-test.go b/cmd/ipsec/ipsec-test.go index 088c93e..9f4e0f1 100644 --- a/cmd/ipsec/ipsec-test.go +++ b/cmd/ipsec/ipsec-test.go @@ -16,6 +16,7 @@ func NewTestCommand() *cobra.Command { var ( addr string pingaddr string + tlsFiles string ) cmd := &cobra.Command{ Use: "test", @@ -30,5 +31,6 @@ func NewTestCommand() *cobra.Command { flags := cmd.Flags() flags.StringVar(&addr, "addr", "localhost:50151", "address or OPI gRPC server") flags.StringVar(&pingaddr, "pingaddr", "localhost", "address of other tunnel end to Ping") + flags.StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") return cmd } diff --git a/cmd/network/evpn-bridge-port.go b/cmd/network/evpn-bridge-port.go index a6ae33c..02d3e86 100644 --- a/cmd/network/evpn-bridge-port.go +++ b/cmd/network/evpn-bridge-port.go @@ -22,6 +22,7 @@ func CreateBridgePort() *cobra.Command { var mac string var bridgePortType string var logicalBridges []string + var tlsFiles string cmd := &cobra.Command{ Use: "create-bp", @@ -29,7 +30,7 @@ func CreateBridgePort() *cobra.Command { Long: "Create a BridgePort with the specified name, MAC address, type, and VLAN IDs", Run: func(_ *cobra.Command, _ []string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewBridgePort(addr) + evpnClient, err := network.NewBridgePort(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -50,6 +51,7 @@ func CreateBridgePort() *cobra.Command { cmd.Flags().StringVarP(&bridgePortType, "type", "t", "", "Specify the type (access or trunk)") cmd.Flags().StringSliceVar(&logicalBridges, "logicalBridges", []string{}, "Specify VLAN IDs (multiple values supported)") cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + cmd.Flags().StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") if err := cmd.MarkFlagRequired("mac"); err != nil { log.Fatalf("Error marking flag as required: %v", err) @@ -73,6 +75,7 @@ func DeleteBridgePort() *cobra.Command { var addr string var name string var allowMissing bool + var tlsFiles string cmd := &cobra.Command{ Use: "delete-bp", @@ -80,7 +83,7 @@ func DeleteBridgePort() *cobra.Command { Long: "Delete a BridgePort with the specified name", Run: func(_ *cobra.Command, _ []string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewBridgePort(addr) + evpnClient, err := network.NewBridgePort(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -98,6 +101,7 @@ func DeleteBridgePort() *cobra.Command { cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the BridgePort") cmd.Flags().BoolVarP(&allowMissing, "allowMissing", "a", false, "Specify if missing allowed") cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + cmd.Flags().StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") return cmd } @@ -106,6 +110,7 @@ func DeleteBridgePort() *cobra.Command { func GetBridgePort() *cobra.Command { var addr string var name string + var tlsFiles string cmd := &cobra.Command{ Use: "get-bp", @@ -113,7 +118,7 @@ func GetBridgePort() *cobra.Command { Long: "Show details of a BridgePort with the specified name", Run: func(_ *cobra.Command, _ []string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewBridgePort(addr) + evpnClient, err := network.NewBridgePort(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -131,6 +136,7 @@ func GetBridgePort() *cobra.Command { cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the BridgePort") cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + cmd.Flags().StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") if err := cmd.MarkFlagRequired("name"); err != nil { log.Fatalf("Error marking flag as required: %v", err) @@ -143,13 +149,14 @@ func ListBridgePorts() *cobra.Command { var addr string var pageSize int32 var pageToken string + var tlsFiles string cmd := &cobra.Command{ Use: "list-bps", Short: "Show details of all bridge ports", Run: func(_ *cobra.Command, _ []string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewBridgePort(addr) + evpnClient, err := network.NewBridgePort(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -179,6 +186,8 @@ func ListBridgePorts() *cobra.Command { cmd.Flags().Int32VarP(&pageSize, "pagesize", "s", 0, "Specify page size") cmd.Flags().StringVarP(&pageToken, "pagetoken", "t", "", "Specify the token") cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + cmd.Flags().StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") + return cmd } @@ -188,6 +197,7 @@ func UpdateBridgePort() *cobra.Command { var name string var updateMask []string var allowMissing bool + var tlsFiles string cmd := &cobra.Command{ Use: "update-bp", @@ -195,7 +205,7 @@ func UpdateBridgePort() *cobra.Command { Long: "updates the Bridge Port with updated mask", Run: func(_ *cobra.Command, _ []string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewBridgePort(addr) + evpnClient, err := network.NewBridgePort(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -215,5 +225,7 @@ func UpdateBridgePort() *cobra.Command { cmd.Flags().StringSliceVar(&updateMask, "update-mask", nil, "update mask") cmd.Flags().BoolVarP(&allowMissing, "allowMissing", "a", false, "allow the missing") cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + cmd.Flags().StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") + return cmd } diff --git a/cmd/network/evpn-logical-brige.go b/cmd/network/evpn-logical-brige.go index ffc0ade..5502175 100644 --- a/cmd/network/evpn-logical-brige.go +++ b/cmd/network/evpn-logical-brige.go @@ -22,6 +22,7 @@ func CreateLogicalBridge() *cobra.Command { var vlanID uint32 var vni uint32 var vtep string + var tlsFiles string cmd := &cobra.Command{ Use: "create-lb", @@ -30,7 +31,7 @@ func CreateLogicalBridge() *cobra.Command { Run: func(_ *cobra.Command, _ []string) { var vniparam *uint32 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewLogicalBridge(addr) + evpnClient, err := network.NewLogicalBridge(addr, tlsFiles) if err != nil { log.Fatalf("could create gRPC client: %v", err) } @@ -54,6 +55,7 @@ func CreateLogicalBridge() *cobra.Command { cmd.Flags().Uint32VarP(&vlanID, "vlan-id", "v", 0, "Specify the VLAN ID") cmd.Flags().Uint32VarP(&vni, "vni", "i", 0, "Specify the VNI") cmd.Flags().StringVar(&vtep, "vtep", "", "VTEP IP address") + cmd.Flags().StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") if err := cmd.MarkFlagRequired("addr"); err != nil { log.Fatalf("Error marking flag as required: %v", err) @@ -75,6 +77,7 @@ func DeleteLogicalBridge() *cobra.Command { var addr string var name string var allowMissing bool + var tlsFiles string cmd := &cobra.Command{ Use: "delete-lb", @@ -82,7 +85,7 @@ func DeleteLogicalBridge() *cobra.Command { Long: "Delete a logical bridge with the specified name", Run: func(_ *cobra.Command, _ []string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewLogicalBridge(addr) + evpnClient, err := network.NewLogicalBridge(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -100,6 +103,7 @@ func DeleteLogicalBridge() *cobra.Command { cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the BridgePort") cmd.Flags().BoolVarP(&allowMissing, "allowMissing", "a", false, "Specify allow missing") cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + cmd.Flags().StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") if err := cmd.MarkFlagRequired("name"); err != nil { log.Fatalf("Error marking flag as required: %v", err) @@ -111,6 +115,7 @@ func DeleteLogicalBridge() *cobra.Command { func GetLogicalBridge() *cobra.Command { var addr string var name string + var tlsFiles string cmd := &cobra.Command{ Use: "get-lb", @@ -118,7 +123,7 @@ func GetLogicalBridge() *cobra.Command { Long: "Show details of a logical bridge with the specified name", Run: func(_ *cobra.Command, _ []string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewLogicalBridge(addr) + evpnClient, err := network.NewLogicalBridge(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -136,6 +141,8 @@ func GetLogicalBridge() *cobra.Command { cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the BridgePort") cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + cmd.Flags().StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") + if err := cmd.MarkFlagRequired("name"); err != nil { log.Fatalf("Error marking flag as required: %v", err) } @@ -148,12 +155,14 @@ func ListLogicalBridges() *cobra.Command { var addr string var pageSize int32 var pageToken string + var tlsFiles string + cmd := &cobra.Command{ Use: "list-lbs", Short: "Show details of all logical bridges", Run: func(_ *cobra.Command, _ []string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewLogicalBridge(addr) + evpnClient, err := network.NewLogicalBridge(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -185,6 +194,8 @@ func ListLogicalBridges() *cobra.Command { cmd.Flags().Int32VarP(&pageSize, "pagesize", "s", 0, "Specify page size") cmd.Flags().StringVarP(&pageToken, "pagetoken", "t", "", "Specify the token") cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + cmd.Flags().StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") + return cmd } @@ -194,12 +205,14 @@ func UpdateLogicalBridge() *cobra.Command { var name string var allowMissing bool var updateMask []string + var tlsFiles string + cmd := &cobra.Command{ Use: "update-lb", Short: "update the logical bridge", Run: func(_ *cobra.Command, _ []string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewLogicalBridge(addr) + evpnClient, err := network.NewLogicalBridge(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -217,6 +230,7 @@ func UpdateLogicalBridge() *cobra.Command { cmd.Flags().StringSliceVar(&updateMask, "update-mask", nil, "update mask") cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") cmd.Flags().BoolVarP(&allowMissing, "allowMissing", "a", false, "Specify allow missing") + cmd.Flags().StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") return cmd } diff --git a/cmd/network/evpn-svi.go b/cmd/network/evpn-svi.go index a48f937..054a27a 100644 --- a/cmd/network/evpn-svi.go +++ b/cmd/network/evpn-svi.go @@ -25,6 +25,7 @@ func CreateSVI() *cobra.Command { var gwIPs []string var ebgp bool var remoteAS uint32 + var tlsFiles string cmd := &cobra.Command{ Use: "create-svi", @@ -32,7 +33,7 @@ func CreateSVI() *cobra.Command { Long: "Create an using name, vrf,logical bridges, mac, gateway ip's and enable bgp ", Run: func(_ *cobra.Command, _ []string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewSVI(addr) + evpnClient, err := network.NewSVI(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -55,6 +56,7 @@ func CreateSVI() *cobra.Command { cmd.Flags().BoolVar(&ebgp, "ebgp", false, "Enable eBGP in VRF for tenants connected through this SVI") cmd.Flags().Uint32VarP(&remoteAS, "remote-as", "", 0, "The remote AS") cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + cmd.Flags().StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") if err := cmd.MarkFlagRequired("vrf"); err != nil { log.Fatalf("Error marking flag as required: %v", err) @@ -79,13 +81,14 @@ func DeleteSVI() *cobra.Command { var addr string var name string var allowMissing bool + var tlsFiles string cmd := &cobra.Command{ Use: "delete-svi", Short: "Delete a SVI", Run: func(_ *cobra.Command, _ []string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewSVI(addr) + evpnClient, err := network.NewSVI(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -103,6 +106,7 @@ func DeleteSVI() *cobra.Command { cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the BridgePort") cmd.Flags().BoolVarP(&allowMissing, "allowMissing", "a", false, "Specify the name of the BridgePort") cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + cmd.Flags().StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") if err := cmd.MarkFlagRequired("name"); err != nil { log.Fatalf("Error marking flag as required: %v", err) @@ -114,13 +118,14 @@ func DeleteSVI() *cobra.Command { func GetSVI() *cobra.Command { var addr string var name string + var tlsFiles string cmd := &cobra.Command{ Use: "get-svi", Short: "Show details of a SVI", Run: func(_ *cobra.Command, _ []string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewSVI(addr) + evpnClient, err := network.NewSVI(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -137,6 +142,7 @@ func GetSVI() *cobra.Command { cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the BridgePort") cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + cmd.Flags().StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") if err := cmd.MarkFlagRequired("name"); err != nil { log.Fatalf("Error marking flag as required: %v", err) @@ -149,13 +155,14 @@ func ListSVIs() *cobra.Command { var addr string var pageSize int32 var pageToken string + var tlsFiles string cmd := &cobra.Command{ Use: "list-svis", Short: "Show details of all SVIs", Run: func(_ *cobra.Command, _ []string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewSVI(addr) + evpnClient, err := network.NewSVI(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -186,6 +193,8 @@ func ListSVIs() *cobra.Command { cmd.Flags().Int32VarP(&pageSize, "pageSize", "s", 0, "Specify the name of the BridgePort") cmd.Flags().StringVarP(&pageToken, "pageToken", "p", "", "Specify the page token") cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + cmd.Flags().StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") + return cmd } @@ -195,13 +204,14 @@ func UpdateSVI() *cobra.Command { var name string var updateMask []string var allowMissing bool + var tlsFiles string cmd := &cobra.Command{ Use: "update-svi", Short: "update the SVI", Run: func(_ *cobra.Command, _ []string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewSVI(addr) + evpnClient, err := network.NewSVI(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -219,5 +229,7 @@ func UpdateSVI() *cobra.Command { cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") cmd.Flags().StringSliceVar(&updateMask, "update-mask", nil, "update mask") cmd.Flags().BoolVarP(&allowMissing, "allowMissing", "a", false, "allow the missing") + cmd.Flags().StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") + return cmd } diff --git a/cmd/network/evpn-vrf.go b/cmd/network/evpn-vrf.go index 5f5e0a3..90ad295 100644 --- a/cmd/network/evpn-vrf.go +++ b/cmd/network/evpn-vrf.go @@ -22,14 +22,15 @@ func CreateVRF() *cobra.Command { var vni uint32 var loopback string var vtep string - + var tlsFiles string cmd := &cobra.Command{ Use: "create-vrf", Short: "Create a VRF", Run: func(_ *cobra.Command, _ []string) { var vniparam *uint32 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewVRF(addr) + log.Printf("[tls files list vrfs] %s", tlsFiles) + evpnClient, err := network.NewVRF(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -51,6 +52,7 @@ func CreateVRF() *cobra.Command { cmd.Flags().StringVar(&loopback, "loopback", "", "Loopback IP address") cmd.Flags().StringVar(&vtep, "vtep", "", "VTEP IP address") cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + cmd.Flags().StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") if err := cmd.MarkFlagRequired("loopback"); err != nil { log.Fatalf("Error marking flag as required: %v", err) @@ -63,13 +65,13 @@ func DeleteVRF() *cobra.Command { var addr string var name string var allowMissing bool - + var tlsFiles string cmd := &cobra.Command{ Use: "delete-vrf", Short: "Delete a VRF", Run: func(_ *cobra.Command, _ []string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewVRF(addr) + evpnClient, err := network.NewVRF(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -87,7 +89,7 @@ func DeleteVRF() *cobra.Command { cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the BridgePort") cmd.Flags().BoolVarP(&allowMissing, "allowMissing", "a", false, "Specify the name of the BridgePort") cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") - + cmd.Flags().StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") return cmd } @@ -95,13 +97,13 @@ func DeleteVRF() *cobra.Command { func GetVRF() *cobra.Command { var addr string var name string - + var tlsFiles string cmd := &cobra.Command{ Use: "get-vrf", Short: "Show details of a VRF", Run: func(_ *cobra.Command, _ []string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewVRF(addr) + evpnClient, err := network.NewVRF(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -120,7 +122,7 @@ func GetVRF() *cobra.Command { cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the vrf") cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") - + cmd.Flags().StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") if err := cmd.MarkFlagRequired("name"); err != nil { log.Fatalf("Error marking flag as required: %v", err) } @@ -132,13 +134,13 @@ func ListVRFs() *cobra.Command { var addr string var pageSize int32 var pageToken string - + var tlsFiles string cmd := &cobra.Command{ Use: "list-vrfs", Short: "Show details of all Vrfs", Run: func(_ *cobra.Command, _ []string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewVRF(addr) + evpnClient, err := network.NewVRF(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -168,6 +170,7 @@ func ListVRFs() *cobra.Command { cmd.Flags().Int32VarP(&pageSize, "pagesize", "s", 0, "Specify page size") cmd.Flags().StringVarP(&pageToken, "pagetoken", "t", "", "Specify the token") cmd.Flags().StringVar(&addr, "addr", "localhost:50151", "address of OPI gRPC server") + cmd.Flags().StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") return cmd } @@ -177,13 +180,13 @@ func UpdateVRF() *cobra.Command { var name string var updateMask []string var allowMissing bool - + var tlsFiles string cmd := &cobra.Command{ Use: "update-vrf", Short: "update the VRF", Run: func(_ *cobra.Command, _ []string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - evpnClient, err := network.NewVRF(addr) + evpnClient, err := network.NewVRF(addr, tlsFiles) if err != nil { log.Fatalf("could not create gRPC client: %v", err) } @@ -202,6 +205,6 @@ func UpdateVRF() *cobra.Command { cmd.Flags().StringVarP(&name, "name", "n", "", "Specify the name of the vrf") cmd.Flags().StringSliceVar(&updateMask, "update-mask", nil, "update mask") cmd.Flags().BoolVarP(&allowMissing, "allowMissing", "a", false, "allow the missing") - + cmd.Flags().StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") return cmd } diff --git a/cmd/storage/backend/nvme_controller.go b/cmd/storage/backend/nvme_controller.go index ece917b..a8b9790 100644 --- a/cmd/storage/backend/nvme_controller.go +++ b/cmd/storage/backend/nvme_controller.go @@ -19,6 +19,7 @@ import ( func newCreateNvmeControllerCommand() *cobra.Command { id := "" multipath := "" + tlsFiles := "" cmd := &cobra.Command{ Use: "controller", Aliases: []string{"c"}, @@ -31,7 +32,7 @@ func newCreateNvmeControllerCommand() *cobra.Command { timeout, err := c.Flags().GetDuration(common.TimeoutCmdLineArg) cobra.CheckErr(err) - client, err := backendclient.New(addr) + client, err := backendclient.New(addr, tlsFiles) cobra.CheckErr(err) ctx, cancel := context.WithTimeout(context.Background(), timeout) @@ -57,6 +58,7 @@ func newCreateNvmeControllerCommand() *cobra.Command { cmd.Flags().StringVar(&id, "id", "", "id for created resource. Assigned by server if omitted.") cmd.Flags().StringVar(&multipath, "multipath", "disable", "multipath mode (disable, failover, enable)") + cmd.Flags().StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") return cmd } @@ -64,6 +66,7 @@ func newCreateNvmeControllerCommand() *cobra.Command { func newDeleteNvmeControllerCommand() *cobra.Command { name := "" allowMissing := false + tlsFiles := "" cmd := &cobra.Command{ Use: "controller", Aliases: []string{"c"}, @@ -76,7 +79,7 @@ func newDeleteNvmeControllerCommand() *cobra.Command { timeout, err := c.Flags().GetDuration(common.TimeoutCmdLineArg) cobra.CheckErr(err) - client, err := backendclient.New(addr) + client, err := backendclient.New(addr, tlsFiles) cobra.CheckErr(err) ctx, cancel := context.WithTimeout(context.Background(), timeout) @@ -89,6 +92,7 @@ func newDeleteNvmeControllerCommand() *cobra.Command { cmd.Flags().StringVar(&name, "name", "", "name of deleted remote controller") cmd.Flags().BoolVar(&allowMissing, "allowMissing", false, "cmd succeeds if attempts to delete a resource that is not present") + cmd.Flags().StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") cobra.CheckErr(cmd.MarkFlagRequired("name")) @@ -97,6 +101,8 @@ func newDeleteNvmeControllerCommand() *cobra.Command { func newGetNvmeControllerCommand() *cobra.Command { name := "" + tlsFiles := "" + cmd := &cobra.Command{ Use: "controller", Aliases: []string{"c"}, @@ -109,7 +115,7 @@ func newGetNvmeControllerCommand() *cobra.Command { timeout, err := c.Flags().GetDuration(common.TimeoutCmdLineArg) cobra.CheckErr(err) - client, err := backendclient.New(addr) + client, err := backendclient.New(addr, tlsFiles) cobra.CheckErr(err) ctx, cancel := context.WithTimeout(context.Background(), timeout) @@ -123,6 +129,7 @@ func newGetNvmeControllerCommand() *cobra.Command { } cmd.Flags().StringVar(&name, "name", "", "name of remote controller to get") + cmd.Flags().StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") cobra.CheckErr(cmd.MarkFlagRequired("name")) diff --git a/cmd/storage/backend/nvme_path.go b/cmd/storage/backend/nvme_path.go index 79e1bb2..8bb0ea8 100644 --- a/cmd/storage/backend/nvme_path.go +++ b/cmd/storage/backend/nvme_path.go @@ -39,6 +39,8 @@ func newCreateNvmePathTCPCommand() *cobra.Command { controller := "" var ip net.IP var port uint16 + tlsFiles := "" + cmd := &cobra.Command{ Use: "tcp", Aliases: []string{"t"}, @@ -51,7 +53,7 @@ func newCreateNvmePathTCPCommand() *cobra.Command { timeout, err := c.Flags().GetDuration(common.TimeoutCmdLineArg) cobra.CheckErr(err) - client, err := backendclient.New(addr) + client, err := backendclient.New(addr, tlsFiles) cobra.CheckErr(err) ctx, cancel := context.WithTimeout(context.Background(), timeout) @@ -70,6 +72,7 @@ func newCreateNvmePathTCPCommand() *cobra.Command { cmd.Flags().Uint16Var(&port, "port", 0, "port of the path to connect to.") cmd.Flags().StringVar(&nqn, "nqn", "", "nqn of the target subsystem.") cmd.Flags().StringVar(&hostnqn, "hostnqn", "", "host nqn") + cmd.Flags().StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") cobra.CheckErr(cmd.MarkFlagRequired("controller")) cobra.CheckErr(cmd.MarkFlagRequired("ip")) @@ -83,6 +86,8 @@ func newCreateNvmePathPcieCommand() *cobra.Command { id := "" controller := "" bdf := "" + tlsFiles := "" + cmd := &cobra.Command{ Use: "pcie", Aliases: []string{"p"}, @@ -95,7 +100,7 @@ func newCreateNvmePathPcieCommand() *cobra.Command { timeout, err := c.Flags().GetDuration(common.TimeoutCmdLineArg) cobra.CheckErr(err) - client, err := backendclient.New(addr) + client, err := backendclient.New(addr, tlsFiles) cobra.CheckErr(err) ctx, cancel := context.WithTimeout(context.Background(), timeout) @@ -111,6 +116,7 @@ func newCreateNvmePathPcieCommand() *cobra.Command { cmd.Flags().StringVar(&id, "id", "", "id for created resource. Assigned by server if omitted.") cmd.Flags().StringVar(&controller, "controller", "", "backend controller name for this path") cmd.Flags().StringVar(&bdf, "bdf", "", "bdf PCI address of NVMe/PCIe controller") + cmd.Flags().StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") cobra.CheckErr(cmd.MarkFlagRequired("controller")) cobra.CheckErr(cmd.MarkFlagRequired("bdf")) @@ -120,6 +126,8 @@ func newCreateNvmePathPcieCommand() *cobra.Command { func newDeleteNvmePathCommand() *cobra.Command { name := "" + tlsFiles := "" + allowMissing := false cmd := &cobra.Command{ Use: "path", @@ -133,7 +141,7 @@ func newDeleteNvmePathCommand() *cobra.Command { timeout, err := c.Flags().GetDuration(common.TimeoutCmdLineArg) cobra.CheckErr(err) - client, err := backendclient.New(addr) + client, err := backendclient.New(addr, tlsFiles) cobra.CheckErr(err) ctx, cancel := context.WithTimeout(context.Background(), timeout) @@ -146,6 +154,7 @@ func newDeleteNvmePathCommand() *cobra.Command { cmd.Flags().StringVar(&name, "name", "", "name of deleted nvme path") cmd.Flags().BoolVar(&allowMissing, "allowMissing", false, "cmd succeeds if attempts to delete a resource that is not present") + cmd.Flags().StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") cobra.CheckErr(cmd.MarkFlagRequired("name")) @@ -154,6 +163,8 @@ func newDeleteNvmePathCommand() *cobra.Command { func newGetNvmePathCommand() *cobra.Command { name := "" + tlsFiles := "" + cmd := &cobra.Command{ Use: "path", Aliases: []string{"p"}, @@ -166,7 +177,7 @@ func newGetNvmePathCommand() *cobra.Command { timeout, err := c.Flags().GetDuration(common.TimeoutCmdLineArg) cobra.CheckErr(err) - client, err := backendclient.New(addr) + client, err := backendclient.New(addr, tlsFiles) cobra.CheckErr(err) ctx, cancel := context.WithTimeout(context.Background(), timeout) @@ -180,7 +191,7 @@ func newGetNvmePathCommand() *cobra.Command { } cmd.Flags().StringVar(&name, "name", "", "name of path to get") - + cmd.Flags().StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") cobra.CheckErr(cmd.MarkFlagRequired("name")) return cmd diff --git a/cmd/storage/frontend/nvme_controller.go b/cmd/storage/frontend/nvme_controller.go index 0b79a9e..6c28590 100644 --- a/cmd/storage/frontend/nvme_controller.go +++ b/cmd/storage/frontend/nvme_controller.go @@ -36,6 +36,8 @@ func newCreateNvmeControllerTCPCommand() *cobra.Command { subsystem := "" var ip net.IP var port uint16 + tlsFiles := "" + cmd := &cobra.Command{ Use: "tcp", Aliases: []string{"t"}, @@ -48,7 +50,7 @@ func newCreateNvmeControllerTCPCommand() *cobra.Command { timeout, err := c.Flags().GetDuration(common.TimeoutCmdLineArg) cobra.CheckErr(err) - client, err := frontendclient.New(addr) + client, err := frontendclient.New(addr, tlsFiles) cobra.CheckErr(err) ctx, cancel := context.WithTimeout(context.Background(), timeout) @@ -65,6 +67,7 @@ func newCreateNvmeControllerTCPCommand() *cobra.Command { cmd.Flags().StringVar(&subsystem, "subsystem", "", "subsystem name to attach the controller to") cmd.Flags().IPVar(&ip, "ip", nil, "ip address of the created controller") cmd.Flags().Uint16Var(&port, "port", 0, "port of the created controller") + cmd.Flags().StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") cobra.CheckErr(cmd.MarkFlagRequired("subsystem")) cobra.CheckErr(cmd.MarkFlagRequired("ip")) @@ -79,6 +82,8 @@ func newCreateNvmeControllerPcieCommand() *cobra.Command { var port uint var pf uint var vf uint + tlsFiles := "" + cmd := &cobra.Command{ Use: "pcie", Aliases: []string{"p"}, @@ -91,7 +96,7 @@ func newCreateNvmeControllerPcieCommand() *cobra.Command { timeout, err := c.Flags().GetDuration(common.TimeoutCmdLineArg) cobra.CheckErr(err) - client, err := frontendclient.New(addr) + client, err := frontendclient.New(addr, tlsFiles) cobra.CheckErr(err) ctx, cancel := context.WithTimeout(context.Background(), timeout) @@ -109,6 +114,7 @@ func newCreateNvmeControllerPcieCommand() *cobra.Command { cmd.Flags().UintVar(&port, "port", 0, "port_id address part of the created controller") cmd.Flags().UintVar(&pf, "pf", 0, "physical_function address part of the created controller") cmd.Flags().UintVar(&vf, "vf", 0, "virtual_function address part of the created controller") + cmd.Flags().StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") cobra.CheckErr(cmd.MarkFlagRequired("subsystem")) cobra.CheckErr(cmd.MarkFlagRequired("pf")) @@ -120,6 +126,8 @@ func newCreateNvmeControllerPcieCommand() *cobra.Command { func newDeleteNvmeControllerCommand() *cobra.Command { name := "" allowMissing := false + tlsFiles := "" + cmd := &cobra.Command{ Use: "controller", Aliases: []string{"c"}, @@ -132,7 +140,7 @@ func newDeleteNvmeControllerCommand() *cobra.Command { timeout, err := c.Flags().GetDuration(common.TimeoutCmdLineArg) cobra.CheckErr(err) - client, err := frontendclient.New(addr) + client, err := frontendclient.New(addr, tlsFiles) cobra.CheckErr(err) ctx, cancel := context.WithTimeout(context.Background(), timeout) @@ -145,6 +153,7 @@ func newDeleteNvmeControllerCommand() *cobra.Command { cmd.Flags().StringVar(&name, "name", "", "name of deleted controller") cmd.Flags().BoolVar(&allowMissing, "allowMissing", false, "cmd succeeds if attempts to delete a resource that is not present") + cmd.Flags().StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") cobra.CheckErr(cmd.MarkFlagRequired("name")) diff --git a/cmd/storage/frontend/nvme_namespace.go b/cmd/storage/frontend/nvme_namespace.go index f581add..d0ab3c3 100644 --- a/cmd/storage/frontend/nvme_namespace.go +++ b/cmd/storage/frontend/nvme_namespace.go @@ -16,6 +16,8 @@ func newCreateNvmeNamespaceCommand() *cobra.Command { id := "" subsystem := "" volume := "" + tlsFiles := "" + cmd := &cobra.Command{ Use: "namespace", Aliases: []string{"n"}, @@ -28,7 +30,7 @@ func newCreateNvmeNamespaceCommand() *cobra.Command { timeout, err := c.Flags().GetDuration(common.TimeoutCmdLineArg) cobra.CheckErr(err) - client, err := frontendclient.New(addr) + client, err := frontendclient.New(addr, tlsFiles) cobra.CheckErr(err) ctx, cancel := context.WithTimeout(context.Background(), timeout) @@ -44,6 +46,7 @@ func newCreateNvmeNamespaceCommand() *cobra.Command { cmd.Flags().StringVar(&id, "id", "", "id for created resource. Assigned by server if omitted.") cmd.Flags().StringVar(&subsystem, "subsystem", "", "subsystem name to attach the namespace to") cmd.Flags().StringVar(&volume, "volume", "", "volume name to attach as a namespace") + cmd.Flags().StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") cobra.CheckErr(cmd.MarkFlagRequired("subsystem")) cobra.CheckErr(cmd.MarkFlagRequired("volume")) @@ -54,6 +57,8 @@ func newCreateNvmeNamespaceCommand() *cobra.Command { func newDeleteNvmeNamespaceCommand() *cobra.Command { name := "" allowMissing := false + tlsFiles := "" + cmd := &cobra.Command{ Use: "namespace", Aliases: []string{"d"}, @@ -66,7 +71,7 @@ func newDeleteNvmeNamespaceCommand() *cobra.Command { timeout, err := c.Flags().GetDuration(common.TimeoutCmdLineArg) cobra.CheckErr(err) - client, err := frontendclient.New(addr) + client, err := frontendclient.New(addr, tlsFiles) cobra.CheckErr(err) ctx, cancel := context.WithTimeout(context.Background(), timeout) @@ -79,6 +84,7 @@ func newDeleteNvmeNamespaceCommand() *cobra.Command { cmd.Flags().StringVar(&name, "name", "", "name of deleted namespace") cmd.Flags().BoolVar(&allowMissing, "allowMissing", false, "cmd succeeds if attempts to delete a resource that is not present") + cmd.Flags().StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") cobra.CheckErr(cmd.MarkFlagRequired("name")) diff --git a/cmd/storage/frontend/nvme_subsystem.go b/cmd/storage/frontend/nvme_subsystem.go index 0ea38b1..bec470e 100644 --- a/cmd/storage/frontend/nvme_subsystem.go +++ b/cmd/storage/frontend/nvme_subsystem.go @@ -16,6 +16,8 @@ func newCreateNvmeSubsystemCommand() *cobra.Command { id := "" nqn := "" hostnqn := "" + tlsFiles := "" + cmd := &cobra.Command{ Use: "subsystem", Aliases: []string{"s"}, @@ -28,7 +30,7 @@ func newCreateNvmeSubsystemCommand() *cobra.Command { timeout, err := c.Flags().GetDuration(common.TimeoutCmdLineArg) cobra.CheckErr(err) - client, err := frontendclient.New(addr) + client, err := frontendclient.New(addr, tlsFiles) cobra.CheckErr(err) ctx, cancel := context.WithTimeout(context.Background(), timeout) @@ -44,6 +46,7 @@ func newCreateNvmeSubsystemCommand() *cobra.Command { cmd.Flags().StringVar(&id, "id", "", "id for created resource. Assigned by server if omitted.") cmd.Flags().StringVar(&nqn, "nqn", "", "nqn for created subsystem") cmd.Flags().StringVar(&hostnqn, "hostnqn", "", "hostnqn for created subsystem") + cmd.Flags().StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") cobra.CheckErr(cmd.MarkFlagRequired("nqn")) @@ -53,6 +56,8 @@ func newCreateNvmeSubsystemCommand() *cobra.Command { func newDeleteNvmeSubsystemCommand() *cobra.Command { name := "" allowMissing := false + tlsFiles := "" + cmd := &cobra.Command{ Use: "subsystem", Aliases: []string{"s"}, @@ -65,7 +70,7 @@ func newDeleteNvmeSubsystemCommand() *cobra.Command { timeout, err := c.Flags().GetDuration(common.TimeoutCmdLineArg) cobra.CheckErr(err) - client, err := frontendclient.New(addr) + client, err := frontendclient.New(addr, tlsFiles) cobra.CheckErr(err) ctx, cancel := context.WithTimeout(context.Background(), timeout) @@ -78,6 +83,7 @@ func newDeleteNvmeSubsystemCommand() *cobra.Command { cmd.Flags().StringVar(&name, "name", "", "name of deleted subsystem") cmd.Flags().BoolVar(&allowMissing, "allowMissing", false, "cmd succeeds if attempts to delete a resource that is not present") + cmd.Flags().StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") cobra.CheckErr(cmd.MarkFlagRequired("name")) diff --git a/cmd/storage/frontend/virtio_blk.go b/cmd/storage/frontend/virtio_blk.go index b1abb7e..ba7d8e2 100644 --- a/cmd/storage/frontend/virtio_blk.go +++ b/cmd/storage/frontend/virtio_blk.go @@ -19,6 +19,8 @@ func newCreateVirtioBlkCommand() *cobra.Command { var pf uint var vf uint var maxIoQPS uint + tlsFiles := "" + cmd := &cobra.Command{ Use: "blk", Aliases: []string{"b"}, @@ -31,7 +33,7 @@ func newCreateVirtioBlkCommand() *cobra.Command { timeout, err := c.Flags().GetDuration(common.TimeoutCmdLineArg) cobra.CheckErr(err) - client, err := frontendclient.New(addr) + client, err := frontendclient.New(addr, tlsFiles) cobra.CheckErr(err) ctx, cancel := context.WithTimeout(context.Background(), timeout) @@ -50,6 +52,7 @@ func newCreateVirtioBlkCommand() *cobra.Command { cmd.Flags().UintVar(&pf, "pf", 0, "physical_function address part of the created controller") cmd.Flags().UintVar(&vf, "vf", 0, "virtual_function address part of the created controller") cmd.Flags().UintVar(&maxIoQPS, "max-io-qps", 0, "max io queue pairs") + cmd.Flags().StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") cobra.CheckErr(cmd.MarkFlagRequired("volume")) cobra.CheckErr(cmd.MarkFlagRequired("pf")) @@ -61,6 +64,8 @@ func newCreateVirtioBlkCommand() *cobra.Command { func newDeleteVirtioBlkCommand() *cobra.Command { name := "" allowMissing := false + tlsFiles := "" + cmd := &cobra.Command{ Use: "blk", Aliases: []string{"b"}, @@ -73,7 +78,7 @@ func newDeleteVirtioBlkCommand() *cobra.Command { timeout, err := c.Flags().GetDuration(common.TimeoutCmdLineArg) cobra.CheckErr(err) - client, err := frontendclient.New(addr) + client, err := frontendclient.New(addr, tlsFiles) cobra.CheckErr(err) ctx, cancel := context.WithTimeout(context.Background(), timeout) @@ -86,6 +91,7 @@ func newDeleteVirtioBlkCommand() *cobra.Command { cmd.Flags().StringVar(&name, "name", "", "name of deleted virtio-blk controller") cmd.Flags().BoolVar(&allowMissing, "allowMissing", false, "cmd succeeds if attempts to delete a resource that is not present") + cmd.Flags().StringVar(&tlsFiles, "tls", "", "TLS files in client_cert:client_key:ca_cert format.") cobra.CheckErr(cmd.MarkFlagRequired("name")) diff --git a/cmd/storage/test.go b/cmd/storage/test.go index 9148fb6..c111f4c 100644 --- a/cmd/storage/test.go +++ b/cmd/storage/test.go @@ -155,7 +155,7 @@ func runTests( } // Set up a connection to the server. - client, err := grpc.New(addr) + client, err := grpc.New(addr, "") if err != nil { log.Fatalf("error creating new client: %v", err) } diff --git a/grpc/client.go b/grpc/client.go index a933bc3..a671b64 100644 --- a/grpc/client.go +++ b/grpc/client.go @@ -6,6 +6,7 @@ package grpc import ( "errors" + "fmt" "log" "google.golang.org/grpc" @@ -13,8 +14,9 @@ import ( ) type clientImpl struct { - addr string // address of OPI gRPC server - d Dialler + addr string // address of OPI gRPC server + d Dialler + tlsfile string } // Dialler defines the function type that creates a gRPC connection @@ -29,12 +31,12 @@ type Connector interface { } // New returns a new gRPC connector for the server at the given address -func New(address string) (Connector, error) { - return NewWithDialler(address, grpc.Dial) +func New(address string, tlsfile string) (Connector, error) { + return NewWithDialler(address, grpc.Dial, tlsfile) } // NewWithDialler returns a new gRPC client for the server at the given address using the gRPC dialler provided -func NewWithDialler(address string, d Dialler) (Connector, error) { +func NewWithDialler(address string, d Dialler, tls string) (Connector, error) { if len(address) == 0 { return nil, errors.New("cannot use empty address") } @@ -44,13 +46,36 @@ func NewWithDialler(address string, d Dialler) (Connector, error) { } return clientImpl{ - addr: address, - d: d, + addr: address, + d: d, + tlsfile: tls, }, nil } // NewConn creates a new gRPC connection func (c clientImpl) NewConn() (grpc.ClientConnInterface, Closer, error) { + log.Println("files", c.tlsfile) + if c.tlsfile != "" { + config, err := ParseTLSFiles(c.tlsfile) + if err != nil { + return nil, nil, fmt.Errorf("failed to parse TLS files: %w", err) + } + option, err := SetupTLSCredentials(config) + if err != nil { + return nil, nil, fmt.Errorf("failed to setup TLS credentials: %w", err) + } + conn, err := c.d(c.addr, grpc.WithTransportCredentials(option)) + if err != nil { + return nil, nil, err + } + closer := func() { + err := conn.Close() + if err != nil { + log.Fatalf("did not close connection: %v", err) + } + } + return conn, closer, nil + } conn, err := c.d(c.addr, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { return nil, nil, err diff --git a/grpc/client_test.go b/grpc/client_test.go index 3527b77..927128e 100644 --- a/grpc/client_test.go +++ b/grpc/client_test.go @@ -23,7 +23,7 @@ var _ = Describe("gRPC", func() { Context("using a non-empty address", func() { BeforeEach(func() { addr = "localhost:1234" - c, err = grpcOpi.New(addr) + c, err = grpcOpi.New(addr, "") }) It("should return a client", func() { @@ -36,7 +36,7 @@ var _ = Describe("gRPC", func() { Context("and specifying a valid dialler", func() { BeforeEach(func() { dialler = diallerNoError - c, err = grpcOpi.NewWithDialler(addr, dialler) + c, err = grpcOpi.NewWithDialler(addr, dialler, "") }) It("should return a client", func() { @@ -49,7 +49,7 @@ var _ = Describe("gRPC", func() { Context("and specifying an invalid dialler", func() { BeforeEach(func() { dialler = nil - c, err = grpcOpi.NewWithDialler(addr, dialler) + c, err = grpcOpi.NewWithDialler(addr, dialler, "") }) It("should not return a client", func() { @@ -64,7 +64,7 @@ var _ = Describe("gRPC", func() { Context("using an empty address", func() { BeforeEach(func() { addr = "" - c, err = grpcOpi.New(addr) + c, err = grpcOpi.New(addr, "") }) It("should not return a client", func() { @@ -77,7 +77,7 @@ var _ = Describe("gRPC", func() { Context("and specifying a valid dialler", func() { BeforeEach(func() { dialler = diallerNoError - c, err = grpcOpi.NewWithDialler(addr, dialler) + c, err = grpcOpi.NewWithDialler(addr, dialler, "") }) It("should not return a client", func() { @@ -91,7 +91,7 @@ var _ = Describe("gRPC", func() { Context("and specifying an invalid dialler", func() { BeforeEach(func() { dialler = nil - c, err = grpcOpi.NewWithDialler(addr, dialler) + c, err = grpcOpi.NewWithDialler(addr, dialler, "") }) It("should not return a client", func() { @@ -116,7 +116,7 @@ var _ = Describe("gRPC", func() { Context("and a connection can be created", func() { BeforeEach(func() { dialler = diallerNoError - c, _ := grpcOpi.NewWithDialler(addr, dialler) + c, _ := grpcOpi.NewWithDialler(addr, dialler, "") conn, closer, err = c.NewConn() }) @@ -136,7 +136,7 @@ var _ = Describe("gRPC", func() { Context("and a connection cannot be created", func() { BeforeEach(func() { dialler = diallerWithError - c, _ := grpcOpi.NewWithDialler(addr, dialler) + c, _ := grpcOpi.NewWithDialler(addr, dialler, "") conn, closer, err = c.NewConn() }) diff --git a/grpc/tls.go b/grpc/tls.go new file mode 100644 index 0000000..74704d8 --- /dev/null +++ b/grpc/tls.go @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Intel Corporation + +// Package grpc contains utility functions +package grpc + +import ( + "crypto/tls" + "crypto/x509" + "errors" + "fmt" + "log" + "os" + "strings" + + "google.golang.org/grpc/credentials" +) + +// TLSConfig contains information required to enable TLS for gRPC client. +type TLSConfig struct { + ClientCertPath string + ClientKeyPath string + CaCertPath string +} + +// ParseTLSFiles parses a string containing server certificate, +// server key and CA certificate separated by `:` +func ParseTLSFiles(tlsFiles string) (TLSConfig, error) { + files := strings.Split(tlsFiles, ":") + + numOfFiles := len(files) + if numOfFiles != 3 { + return TLSConfig{}, errors.New("wrong number of path entries provided." + + "Expect :: are provided separated by `:`") + } + + tls := TLSConfig{} + + const emptyPathErr = "empty %s path is not allowed" + tls.ClientCertPath = files[0] + if tls.ClientCertPath == "" { + return TLSConfig{}, fmt.Errorf(emptyPathErr, "server cert") + } + + tls.ClientKeyPath = files[1] + if tls.ClientKeyPath == "" { + return TLSConfig{}, fmt.Errorf(emptyPathErr, "server key") + } + + tls.CaCertPath = files[2] + if tls.CaCertPath == "" { + return TLSConfig{}, fmt.Errorf(emptyPathErr, "CA cert") + } + + return tls, nil +} + +// SetupTLSCredentials returns a service options to enable TLS for gRPC client +func SetupTLSCredentials(config TLSConfig) (credentials.TransportCredentials, error) { + return setupTLSCredentials(config, tls.LoadX509KeyPair, os.ReadFile) +} + +func setupTLSCredentials(config TLSConfig, + loadX509KeyPair func(string, string) (tls.Certificate, error), + readFile func(string) ([]byte, error), +) (credentials.TransportCredentials, error) { + clientCert, err := loadX509KeyPair(config.ClientCertPath, config.ClientKeyPath) + if err != nil { + return nil, err + } + c := &tls.Config{ + Certificates: []tls.Certificate{clientCert}, + MinVersion: tls.VersionTLS12, + CipherSuites: []uint16{ + tls.TLS_AES_256_GCM_SHA384, + tls.TLS_AES_128_GCM_SHA256, + tls.TLS_CHACHA20_POLY1305_SHA256, + tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + }, + } + + c.RootCAs = x509.NewCertPool() + log.Println("Loading client ca certificate:", config.CaCertPath) + + clientCaCert, err := readFile(config.CaCertPath) + if err != nil { + return nil, fmt.Errorf("failed to read certificate: %v. error: %v", config.CaCertPath, err) + } + + if !c.RootCAs.AppendCertsFromPEM(clientCaCert) { + return nil, fmt.Errorf("failed to add client CA's certificate: %v", config.CaCertPath) + } + + return credentials.NewTLS(c), nil +} diff --git a/inventory/client.go b/inventory/client.go index ca5bef6..2d541ce 100644 --- a/inventory/client.go +++ b/inventory/client.go @@ -28,8 +28,8 @@ type InvClient interface { } // New creates an inventory client for use with OPI server at the given address -func New(addr string) (InvClient, error) { - c, err := grpcOpi.New(addr) +func New(addr string, tls string) (InvClient, error) { + c, err := grpcOpi.New(addr, tls) if err != nil { return nil, err } diff --git a/inventory/client_test.go b/inventory/client_test.go index e712d3b..0487c6b 100644 --- a/inventory/client_test.go +++ b/inventory/client_test.go @@ -31,7 +31,7 @@ var _ = Describe("Inventory", func() { Context("using a non-empty address", func() { BeforeEach(func() { addr = "localhost:1234" - c, err = inventory.New(addr) + c, err = inventory.New(addr, "") }) It("should return a client", func() { @@ -45,7 +45,7 @@ var _ = Describe("Inventory", func() { Context("using an empty address", func() { BeforeEach(func() { addr = "" - c, err = inventory.New(addr) + c, err = inventory.New(addr, "") }) It("should not return a client", func() { diff --git a/network/evpn.go b/network/evpn.go index bbdeb44..bbd7c5c 100644 --- a/network/evpn.go +++ b/network/evpn.go @@ -77,8 +77,8 @@ func resourceIDToFullName(container string, resourceID string) string { } // NewLogicalBridge creates an evpn Logical Bridge client for use with OPI server at the given address -func NewLogicalBridge(addr string) (EvpnClient, error) { - c, err := grpcOpi.New(addr) +func NewLogicalBridge(addr string, tls string) (EvpnClient, error) { + c, err := grpcOpi.New(addr, tls) if err != nil { return nil, err } @@ -106,8 +106,8 @@ func NewLogicalBridgeWithArgs(c grpcOpi.Connector, getter PbEvpnLogicalBridgeCli } // NewBridgePort creates an evpn Bridge Port client for use with OPI server at the given address -func NewBridgePort(addr string) (EvpnClient, error) { - c, err := grpcOpi.New(addr) +func NewBridgePort(addr string, tls string) (EvpnClient, error) { + c, err := grpcOpi.New(addr, tls) if err != nil { return nil, err } @@ -135,8 +135,8 @@ func NewBridgePortWithArgs(c grpcOpi.Connector, getter PbEvpnBridgePortClientGet } // NewVRF creates an evpn VRF client for use with OPI server at the given address -func NewVRF(addr string) (EvpnClient, error) { - c, err := grpcOpi.New(addr) +func NewVRF(addr string, tls string) (EvpnClient, error) { + c, err := grpcOpi.New(addr, tls) if err != nil { return nil, err } @@ -164,8 +164,8 @@ func NewVRFWithArgs(c grpcOpi.Connector, getter PbEvpnVRFClientGetter) (EvpnClie } // NewSVI creates an evpn SVI client for use with OPI server at the given address -func NewSVI(addr string) (EvpnClient, error) { - c, err := grpcOpi.New(addr) +func NewSVI(addr string, tls string) (EvpnClient, error) { + c, err := grpcOpi.New(addr, tls) if err != nil { return nil, err } diff --git a/network/evpn_test.go b/network/evpn_test.go index 5542626..1c858bc 100644 --- a/network/evpn_test.go +++ b/network/evpn_test.go @@ -29,7 +29,7 @@ func TestNewLogicalBridge(t *testing.T) { for testName, tt := range tests { t.Run(testName, func(t *testing.T) { - client, err := NewLogicalBridge(tt.address) + client, err := NewLogicalBridge(tt.address, "") if (err != nil) == !tt.wantErr { t.Errorf("expected err: %v, received: %v", tt.wantErr, err) } @@ -60,7 +60,7 @@ func TestNewBridgePort(t *testing.T) { for testName, tt := range tests { t.Run(testName, func(t *testing.T) { - client, err := NewBridgePort(tt.address) + client, err := NewBridgePort(tt.address, "") if (err != nil) == !tt.wantErr { t.Errorf("expected err: %v, received: %v", tt.wantErr, err) } @@ -91,7 +91,7 @@ func TestNewVRF(t *testing.T) { for testName, tt := range tests { t.Run(testName, func(t *testing.T) { - client, err := NewVRF(tt.address) + client, err := NewVRF(tt.address, "") if (err != nil) == !tt.wantErr { t.Errorf("expected err: %v, received: %v", tt.wantErr, err) } @@ -122,7 +122,7 @@ func TestNewSVI(t *testing.T) { for testName, tt := range tests { t.Run(testName, func(t *testing.T) { - client, err := NewSVI(tt.address) + client, err := NewSVI(tt.address, "") if (err != nil) == !tt.wantErr { t.Errorf("expected err: %v, received: %v", tt.wantErr, err) } diff --git a/storage/backend/client.go b/storage/backend/client.go index f4e155f..2609861 100644 --- a/storage/backend/client.go +++ b/storage/backend/client.go @@ -20,8 +20,8 @@ type Client struct { } // New creates a new instance of Client -func New(addr string) (*Client, error) { - connector, err := grpcOpi.New(addr) +func New(addr string, tls string) (*Client, error) { + connector, err := grpcOpi.New(addr, tls) if err != nil { return nil, err } diff --git a/storage/backend/client_test.go b/storage/backend/client_test.go index 385826a..ead31e2 100644 --- a/storage/backend/client_test.go +++ b/storage/backend/client_test.go @@ -28,7 +28,7 @@ func TestNewClient(t *testing.T) { for testName, tt := range tests { t.Run(testName, func(t *testing.T) { - client, err := New(tt.address) + client, err := New(tt.address, "") if (err != nil) == !tt.wantErr { t.Errorf("expected err: %v, received: %v", tt.wantErr, err) } diff --git a/storage/frontend/client.go b/storage/frontend/client.go index 15b80ff..e65ec02 100644 --- a/storage/frontend/client.go +++ b/storage/frontend/client.go @@ -24,8 +24,8 @@ type Client struct { } // New creates a new instance of Client -func New(addr string) (*Client, error) { - connector, err := grpcOpi.New(addr) +func New(addr string, tls string) (*Client, error) { + connector, err := grpcOpi.New(addr, tls) if err != nil { return nil, err } diff --git a/storage/frontend/client_test.go b/storage/frontend/client_test.go index 7e6d0a7..0f32fa6 100644 --- a/storage/frontend/client_test.go +++ b/storage/frontend/client_test.go @@ -28,7 +28,7 @@ func TestNewClient(t *testing.T) { for testName, tt := range tests { t.Run(testName, func(t *testing.T) { - client, err := New(tt.address) + client, err := New(tt.address, "") if (err != nil) == !tt.wantErr { t.Errorf("expected err: %v, received: %v", tt.wantErr, err) }