Securing eAPI

Introduction

In this article we will talk about a few tips to secure our eAPI access, for example, HTTPS, changing port, certificate, ACL, on-box, AAA, vrf etc.

Turning on/off eAPI

First of all, the most secure way is turning off eAPI, which is by default.

myswitch#configure
myswitch(config)#management api http-commands
myswitch(config-mgmt-api-http-cmds)#shutdown

To turn eAPI on by “no shutdown”, by default the HTTPS protocol is running and HTTP is turned off for secure purpose, because HTTP send user and password in clear text. HTTP can be used by “protocol http”, however, we recommend using HTTPS. Both HTTP and HTTPS can be used concurrently.

myswitch#configure terminal
myswitch(config)#management api http-commands
myswitch(config-mgmt-api-http-cmds)#no shutdown
myswitch(config-mgmt-api-http-cmds)#show management api http-commands
Enabled: Yes
HTTPS server: running, set to use port 443
HTTP server: shutdown, set to use port 80
Local HTTP server: shutdown, no authentication, set to use port 8080
Unix Socket server: shutdown, no authentication
VRF: default

HTTPS Certificate

By default a self-signed certificate will be used. We can view the current certificate using “show management api http-commands https certificate”

myswitch(config)#show management api http-commands https certificate
Certificate:
-----BEGIN CERTIFICATE-----
……
-----END CERTIFICATE-----

Private Key:
-----BEGIN PRIVATE KEY-----
……
-----END PRIVATE KEY-----

If you want to use other certificates, HTTPS certificates and key can be changed with “[no] protocol https certificate” as below:

myswitch#configure terminal
myswitch(config)#management api http-commands
myswitch(config-mgmt-api-http-cmds)#protocol https certificate
Enter TEXT certificate. Type ’EOF’ on its own line to end.
...
EOF
Enter TEXT private key. Type ’EOF’ on its own line to end.
...
EOF

Changing the Port

By default 443 is used for HTTPS access, we can change other port number for better security by “protocol https port xxx”.

myswitch#configure
myswitch(config)#management api http-commands
myswitch(config-mgmt-api-http-cmds)#protocol https port 8888
myswitch(config-mgmt-api-http-cmds)#show management api http-commands
Enabled: Yes
HTTPS server: running, set to use port 8888
HTTP server: shutdown, set to use port 80
...SKIP...
...SKIP...
URLs
-----------------------------------------------
Management1 : https://192.168.100.11:8888

If we open a browser to access https://192.168.100.11:8888, we will find it unreachable. The reason is the default EOS control plane ACL doesn’t allow port 8888 access for security purpose. We can display the default EOS control plane ACL by “show ip access-lists default-control-plane-acl”:

myswitch#show ip access-lists default-control-plane-acl
IP Access List default-control-plane-acl [readonly]
statistics per-entry
10 permit icmp any any [match 1143, 7:58:59 ago]
20 permit ip any any tracked [match 9896, 0:00:05 ago]
30 permit udp any any eq bfd ttl eq 255
40 permit udp any any eq bfd-echo ttl eq 254
50 permit ospf any any
60 permit tcp any any eq ssh telnet www snmp bgp https msdp [match 128, 0:54:55 ago]
70 permit udp any any eq bootps bootpc snmp rip ntp
80 permit tcp any any eq mlag ttl eq 255
90 permit udp any any eq mlag ttl eq 255
100 permit vrrp any any
110 permit ahp any any
120 permit pim any any
130 permit igmp any any
140 permit tcp any any range 5900 5910
150 permit tcp any any range 50000 50100
160 permit udp any any range 51000 51100

We need to modify the control plane ACL so that the new port 8888 can be permitted. We can define a new ACL to include all the existing ACL entries plus the new entry allowing port 8888.

ip access-list new-control-plane-acl
10 permit icmp any any
20 permit ip any any tracked
30 permit udp any any eq bfd ttl eq 255
40 permit udp any any eq bfd-echo ttl eq 254
50 permit ospf any any
60 permit tcp any any eq ssh telnet www snmp bgp https msdp
70 permit udp any any eq bootps bootpc snmp rip ntp
80 permit tcp any any eq mlag ttl eq 255
90 permit udp any any eq mlag ttl eq 255
100 permit vrrp any any
110 permit ahp any any
120 permit pim any any
130 permit igmp any any
140 permit tcp any any range 5900 5910
150 permit tcp any any range 50000 50100
160 permit udp any any range 51000 51100
170 permit tcp any any eq 8888

Then, we can apply it in the control plane:

myswitch#configure 
myswitch(config)#control-plane 
myswitch(config-cp)#ip access-group new-control-plane-acl in

Users Control by ACL

Following the example of changing ports, we can use the control plane ACL to control remote access as well. For example, instead of allowing anyone to access port 8888, we can limit only a subset of IP ranges to access eAPI for control management.

myswitch(config)#ip access-list new-control-plane-acl
myswitch(config-acl-new-control-plane-acl)#no 170
myswitch(config-acl-new-control-plane-acl)#170 permit tcp 192.168.100.0/24 any eq 8888

In this example, we limit only the users in the subnet of 192.168.100.0/24 can access the eAPI remotely via port 8888.

If eAPI uses the default port 443 for HTTPS or 80 for HTTP, and we want to apply the ACL control as well, we can add the desired entries before entry 60. In the default control plane ACL, the entry 60 includes port match 80 (www) and 443 (https). The below example limit only the users in the subnet of 192.168.100.0/24 can access the eAPI remotely via port 443 (https).

ip access-list new-control-plane-acl
10 permit icmp any any
20 permit ip any any tracked
30 permit udp any any eq bfd ttl eq 255
40 permit udp any any eq bfd-echo ttl eq 254
50 permit ospf any any
51 permit tcp 192.168.100.0/24 any eq https
52 deny tcp any any eq https
60 permit tcp any any eq ssh telnet www snmp bgp https msdp
70 permit udp any any eq bootps bootpc snmp rip ntp
80 permit tcp any any eq mlag ttl eq 255
90 permit udp any any eq mlag ttl eq 255
100 permit vrrp any any
110 permit ahp any any
120 permit pim any any
130 permit igmp any any
140 permit tcp any any range 5900 5910
150 permit tcp any any range 50000 50100
160 permit udp any any range 51000 51100
!

VRF

Normally the management port is used for eAPI remote access and the management port is put in to dedicated management VRF. In this case, we can configure the eAPI to use VRF by

myswitch(config)#management api http-commands
myswitch(config-mgmt-api-http-cmds)#vrf mgmt
myswitch(config-mgmt-api-http-cmds-vrf-mgmt)#no shutdown

 Command control via AAA

Sometimes, if we don’t want eAPI to run any commands, we can use AAA together to limit the commands can be run through eAPI. We can define the role for eAPI to include what can be executed and what can’t. For example, the below api role disable any configuration mode commands.

myswitch(config)#role api
myswitch(config-role-api)#deny mode config-all command .*
myswitch(config-role-api)#permit command .*

For eAPI access, we can define a dedicated user say “eapi” and assign the defined role “api” by “username eapi role api secret eapipassword”. If AAA is not defined before, we can configure “aaa authorization commands all default local” to enable it. Now the eAPI call will be limited to “show” commands only.

On-box Programming

Finally, if the script doesn’t require remote call, you can use on-box methods to limit the eAPI from local only. EOS provides two mechanisms to accomplish this. The first is an HTTP server bound to localhost (on port 8080 by default), which only accepts connections arriving from the same machine. The other solution is a Unix domain socket (more efficient). To enable one or both, use the following commands:

myswitch#configure terminal
myswitch(config)#management api http-commands
myswitch(config-mgmt-api-http-cmds)#protocol http localhost
myswitch(config-mgmt-api-http-cmds)#protocol unix-socket
myswitch(config-mgmt-api-http-cmds)#no shutdown

Once Command API is enabled then you access via the local domain socket unix:/var/run/command-api.sock

switch = Server( "unix:/var/run/command-api.sock" )

If configured to use HTTP over localhost, your script can access the API as follows:

switch = Server( "http://localhost:8080/command-api" )

Now, you can turn off the remote call by “no protocol https” and “no protocol http”.

myswitch#configure
myswitch(config)#management api http-commands
myswitch(config-mgmt-api-http-cmds)#no protocol http
myswitch(config-mgmt-api-http-cmds)#no protocol https
myswitch(config-mgmt-api-http-cmds)#show management api http-commands
Enabled: Yes
HTTPS server: shutdown, set to use port 443
HTTP server: shutdown, set to use port 80
Local HTTP server: running, no authentication, set to use port 8080
Unix Socket server: running, no authentication
VRF: mgmt
Hits: 2
Last hit: 2968 seconds ago
Bytes in: 216
Bytes out: 260
Requests: 0
Commands: 0
Duration: 0.000 seconds
User Requests Bytes in Bytes out Last hit
----------- -------------- -------------- --------------- ----------------
admin 0 216 260 2968 seconds ago

URLs
-----------------------------------------------
Unix Socket : unix:/var/run/command-api.sock
Local : http://localhost:8080/command-api