Skip to content

Commit 95f8a59

Browse files
committed
Fix ConnectTo, ConnectTLS and downstream methods/functions to handle CA certificate if provided
1 parent 4b37808 commit 95f8a59

File tree

2 files changed

+51
-28
lines changed

2 files changed

+51
-28
lines changed

client.go

+16-10
Original file line numberDiff line numberDiff line change
@@ -464,12 +464,14 @@ type fn func(transport string, host string, username string,
464464
password string, port int) EapiConnectionEntity
465465

466466
// transports provides the method
467+
// "https_certs" is also a transport method but it can't be found in the below map
468+
// as it is separately handled through ConnectTLS.
469+
// NewHTTPSCertsEapiConnection is the construtor method
467470
var transports = map[string]fn{
468-
"socket": NewSocketEapiConnection,
469-
"http_local": NewHTTPLocalEapiConnection,
470-
"http": NewHTTPEapiConnection,
471-
"https": NewHTTPSEapiConnection,
472-
"https_certs": NewHTTPSCertsEapiConnection,
471+
"socket": NewSocketEapiConnection,
472+
"http_local": NewHTTPLocalEapiConnection,
473+
"http": NewHTTPEapiConnection,
474+
"https": NewHTTPSEapiConnection,
473475
}
474476

475477
// EapiConfig provides the instance for managing of eapi.conf file.
@@ -743,6 +745,10 @@ func ConnectTo(name string) (*Node, error) {
743745
enablepwd := section["enablepwd"]
744746
keyFile := section["keyfile"]
745747
certFile := section["certfile"]
748+
749+
// CA Certificate file is optional
750+
caCertFile := section["cacertfile"]
751+
746752
var port = UseDefaultPortNum
747753
_, ok := section["port"]
748754
if ok {
@@ -751,7 +757,7 @@ func ConnectTo(name string) (*Node, error) {
751757
var node *Node
752758
var err error
753759
if transport == "https_certs" {
754-
node, err = ConnectTLS(transport, host, keyFile, certFile, port)
760+
node, err = ConnectTLS(transport, host, keyFile, certFile, caCertFile, port)
755761
} else {
756762
node, err = Connect(transport, host, username, passwd, port)
757763
}
@@ -801,8 +807,8 @@ func Connect(transport string, host string, username string, passwd string,
801807
return node, nil
802808
}
803809

804-
func ConnectTLS(transport string, host string, keyFile string, certFile string, port int) (*Node, error) {
805-
conn, err := ConnectionTLS(transport, host, keyFile, certFile, port)
810+
func ConnectTLS(transport, host, keyFile, certFile, caCertFile string, port int) (*Node, error) {
811+
conn, err := ConnectionTLS(transport, host, keyFile, certFile, caCertFile, port)
806812
if err != nil {
807813
return nil, err
808814
}
@@ -859,8 +865,8 @@ func Connection(transport string, host string, username string, passwd string,
859865
return obj, nil
860866
}
861867

862-
func ConnectionTLS(transport string, host string, keyFile string, certFile string, port int) (EapiConnectionEntity, error) {
863-
obj := NewHTTPSCertsEapiConnection(transport, host, keyFile, certFile, port)
868+
func ConnectionTLS(transport, host, keyFile, certFile, caCertFile string, port int) (EapiConnectionEntity, error) {
869+
obj := NewHTTPSCertsEapiConnection(transport, host, keyFile, certFile, caCertFile, port)
864870
return obj, nil
865871
}
866872

eapilib.go

+35-18
Original file line numberDiff line numberDiff line change
@@ -660,36 +660,38 @@ func (conn *HTTPSEapiConnection) enableCertificateVerification() {
660660
// HTTPSCertsEapiConnection is an EapiConnection suited for HTTPS connection
661661
type HTTPSCertsEapiConnection struct {
662662
EapiConnection
663-
path string // Request URL
664-
keyFile string // Path to the Client Private Key file
665-
certFile string // Path to the Client Certificate file
663+
path string // Request URL
664+
keyFile string // Path to the Client Private Key file
665+
certFile string // Path to the Client Certificate file
666+
caCertFile string // Path to the CA certificate file
666667
}
667668

668669
// NewHTTPSCertsEapiConnection initializes an HTTPSCertsEapiConnection.
669670
//
670671
// Args:
671672
//
672-
// transport (string): The transport to use to create the instance,
673-
// which is "https_certs"
674-
// host (string): The IP address or DNS host name of the connection device.
675-
// keyFile(string): The path to the keyfile which will be pass to the device
676-
// to authenticate the eAPI connection.
677-
// certFile(string): The path to the certFile which will be pass to the device
678-
// to authenticate the eAPI connection.
679-
// port(int): The TCP port of the endpoint for the eAPI connection.
673+
// transport (string): The transport to use to create the instance,
674+
// which is "https_certs"
675+
// host (string): The IP address or DNS host name of the connection device.
676+
// keyFile(string): The path to the Client's Private Key file which will be pass to the device
677+
// certFile(string): The path to the Client's Certificate which will be pass to the device
678+
// to authenticate the eAPI connection.
679+
// caCertFile(string): The path to the CA Certificate file which will be used to verify against's
680+
// switch's certificate.
681+
// port(int): The TCP port of the endpoint for the eAPI connection.
680682
//
681683
// Returns:
682684
//
683685
// Newly created HTTPSCertsEapiConnection
684-
func NewHTTPSCertsEapiConnection(transport string, host string, keyFile string, certFile string, port int) EapiConnectionEntity {
686+
func NewHTTPSCertsEapiConnection(transport, host, keyFile, certFile, caCertFile string, port int) EapiConnectionEntity {
685687
if port == UseDefaultPortNum {
686688
port = DefaultHTTPSPort
687689
}
688690
path := DefaultHTTPSPath
689691

690692
conn := EapiConnection{transport: transport, host: host, port: port, timeOut: 60, disableKeepAlive: false}
691693

692-
return &HTTPSCertsEapiConnection{path: path, EapiConnection: conn, keyFile: keyFile, certFile: certFile}
694+
return &HTTPSCertsEapiConnection{path: path, EapiConnection: conn, keyFile: keyFile, certFile: certFile, caCertFile: caCertFile}
693695
}
694696

695697
// send the eAPI request to the destination node
@@ -720,12 +722,27 @@ func (conn *HTTPSCertsEapiConnection) send(data []byte) (*JSONRPCResponse, error
720722
return nil, err
721723
}
722724

725+
tlsConfig := &tls.Config{
726+
InsecureSkipVerify: true,
727+
Certificates: []tls.Certificate{cert},
728+
RootCAs: x509.NewCertPool(),
729+
}
730+
731+
// Handle CA Certificate if provided
732+
if conn.caCertFile != "" {
733+
caCert, err := os.ReadFile(conn.caCertFile)
734+
if err != nil {
735+
conn.SetError(err)
736+
return nil, fmt.Errorf("failed to read CA certificate file: %v", err)
737+
}
738+
if ok := tlsConfig.RootCAs.AppendCertsFromPEM(caCert); !ok {
739+
conn.SetError(fmt.Errorf("failed to append CA certificate to pool"))
740+
return nil, fmt.Errorf("failed to append CA certificate to pool")
741+
}
742+
}
743+
723744
tr := &http.Transport{
724-
TLSClientConfig: &tls.Config{
725-
InsecureSkipVerify: true,
726-
Certificates: []tls.Certificate{cert},
727-
RootCAs: x509.NewCertPool(),
728-
},
745+
TLSClientConfig: tlsConfig,
729746
DisableKeepAlives: conn.disableKeepAlive,
730747
}
731748
client := &http.Client{

0 commit comments

Comments
 (0)