cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Announcements

Securing your Secrets with the CLI NEDs

557
Views
10
Helpful
0
Comments
vleijon
Cisco Employee

It is best practice to avoid storing your secrets (e.g., passwords and shared keys) in plain text, either on NSO or on the device. In NSO, we support multiple encrypted data types that are encrypted using a local key. Similarly, many devices such as Cisco IOS XE support automatically encrypting all passwords stored on the device. On Cisco IOS, this can be done using commands like these:

key config-key password-encryption SUPERSECRET
service password-encryption
password encryption aes

which makes the system automatically encrypt all passwords using the key SUPERSECRET and show them encrypted in the output of show running.

Naturally, for security reasons, NSO, in general, has no way of encrypting/decrypting passwords with the secret key on the device. If nothing is done about this, we will become out of sync once we write secrets to the device. Looking at just the cisco-ios NED, there are over 500 paths that contain such secrets.

Luckily, many of our CLI NEDs support various levels of security and secrets management. For example, the NED handles auto-encryption by reading back auto-encrypted values immediately after writing them and storing the encrypted value in a special secrets table. This allows the NED to replace any future occurrences of the encrypted value with the known plaintext from NSO.

This re-reading handles the device-side encryption, but passwords are still unencrypted in NSO. So, in addition to managing device-side encryption, we support using NSO-encrypted strings instead of plaintext passwords in the NSO data model.

NED support

The following NED has at least some support for secrets: cisco-asa, cisco-ios, cisco-iosxr, cisco-nx, cisco-staros, and huawei-vrp. This document aims to be generic but will use cisco-ios for the examples. Please look at the README file for each NED for specific details; some NEDs have additional ned-settings or features available. 

Handling auto-encryption

Let us say that we have password-encryption on and we want to write a new user to our device:

admin@ncs(config)# devices device ios0 config username newuser password 0 magic
admin@ncs(config-config)# commit

this will be automatically encrypted by the device

Router#show running-config | sec userna
username newuser password 6 _Ab[PDCO[fQDJhDfMIciONMedifAAB

But the secrets management will store this new encrypted value in our secrets table:

admin@ncs# show devices device ios0 ned-settings secrets
ID                                      ENCRYPTED                         REGEX
---------------------------------------------------------------------------------
ios:username(newuser)/password/secret   6 _Ab[PDCO[fQDJhDfMIciONMedifAAB

which means that no compare-config or sync-from will update our CDB. In fact, we can still see the unencrypted value in the device tree:

admin@ncs# show running-config devices device ios0 config username
devices device ios0
 config
  username admin password 6 S]iVZERdHTgVdf_KVQYOMXQRR^QHM^
  username cisco privilege 15 password 6 "Y]i`\ZegLUiB[EMPYUAKhOBK]VRAAB"
  username newuser password 0 magic
 !
!

 

Increasing security with NSO-side encryption

We have two alternatives, we can either manually encrypt our values using one of the NSO-encrypted types (e.g., aes-256-cfb-128-encrypted-string) and set them to the tree, or we can recompile the NED to always encrypt secrets.

Setting encrypted value

Let us say we know that the NSO-encrypted string $9$T963R76+wgaQuZCtcGC/Nreo75FigP+znmOln8XDFK0= (admin), we can then set it in the device tree as normal

admin@ncs(config)# devices device ios0 config username newuser2 password 0 $9$T963R76+wgaQuZCtcGC/Nreo75FigP+znmOln8XDFK0=
admin@ncs(config-config)# commit

when committing this value, it will be decrypted by the NED, and the plaintext will be sent to the device. However, for security reasons, the encrypted value will be used in the device traces.

Unlike the previous example, the plaintext is not visible in the device tree:

admin@ncs# show running-config devices device ios0 config username
devices device ios0
 config
  username admin password 6 S]iVZERdHTgVdf_KVQYOMXQRR^QHM^
  username cisco privilege 15 password 6 "Y]i`\ZegLUiB[EMPYUAKhOBK]VRAAB"
  username newuser password 0 magic
  username newuser2 password 0 $9$T963R76+wgaQuZCtcGC/Nreo75FigP+znmOln8XDFK0=
 !
!

On the device side, this plaintext value is, of course, encrypted with the device key, and just as before, we store it in our secrets table:

admin@ncs# show devices device ios0 ned-settings secrets
ID                                      ENCRYPTED                         REGEX
---------------------------------------------------------------------------------
ios:username(newuser)/password/secret   6 _Ab[PDCO[fQDJhDfMIciONMedifAAB
ios:username(newuser2)/password/secret  6 XTXfOVUcYDZKd`FBH\S]XEJ_FcIAAB

We can see that this corresponds to the value set on the device:

Router#show running-config | sec userna
username admin password 6 S]iVZERdHTgVdf_KVQYOMXQRR^QHM^
username cisco privilege 15 password 6 Y]i`\ZegLUiB[EMPYUAKhOBK]VRAAB
username newuser password 6 _Ab[PDCO[fQDJhDfMIciONMedifAAB
username newuser2 password 6 XTXfOVUcYDZKd`FBH\S]XEJ_FcIAAB

Note that we do not have entries for admin or cisco because these values were set directly on NSO and not on the device, we do not know the corresponding plaintext value, and they are handled entirely as encrypted values.

Auto-encrypting passwords in NSO

You can rebuild your NED with an encrypted type for secrets using a command like NEDCOM_SECRET_TYPE="tailf:aes-cfb-128-encrypted-string" make -C src/ or by setting NED_EXTRA_BUILDFLAGS ?= NEDCOM_SECRET_TYPE=tailf:aes-cfb-128-encrypted-string in the Makefile. Doing this means that even if the input to a password is a plaintext string, NSO will always encrypt it, and you will never see plaintext secrets in the device tree.

 

NOTE: This will work only for leafs in the YANG model which has the type NEDCOM_SECRET_TYPE.

 

If we reload our example with the new NED all of the secrets are now encrypted:

admin@ncs# show running-config devices device ios0 config username
devices device ios0
 config
  username admin password 6 $8$LkeTpiWvR2fm0P0DK0FXPg61LAOw5TACkB1y7FYvZIYYNE2CqMyQOwZ7uDeod7oR
  username cisco privilege 15 password 6 $8$0D4JYVCvfoLqu5u77OImrdzWuP4hp9HzcAXbQPAoQUmNNWjF0VoOPVeaPRfoRqrI
  username newuser password 0 $8$IpJZaKg3HZ+7JMdhmcVlbdw2P+htNdThDuYKdldDAqM=
  username newuser2 password 0 "$8$BVzY1FLE47Wum5WXokAVZ3UqaeJQt4s7ksGyiWKOLxGZIUrhp92KqBG4R2zINyMFl+L71TOk\naT8u3/l4L/p4Xg=="
 !
!

and if we create yet another user we get the desired result:

admin@ncs(config)# devices device ios0 config username newuser3 password 0 automatic
admin@ncs(config-config)# commit dry-run outformat native
native {
    device {
        name ios0
        data username newuser3 password 0 $8$s3EN60QdR5flGa1cv0K3/50iHX4wBcRkjrhFaok7ALg=
    }
}
admin@ncs(config-config)# commit
Commit complete.
admin@ncs(config-config)# end
admin@ncs# show running-config devices device ios0 config username newuser3
devices device ios0
 config
  username newuser3 password 0 $8$s3EN60QdR5flGa1cv0K3/50iHX4wBcRkjrhFaok7ALg=
 !
!
admin@ncs# show devices device ios0 ned-settings secrets
ID                                      ENCRYPTED                               REGEX
---------------------------------------------------------------------------------------
ios:username(newuser)/password/secret   6 _Ab[PDCO[fQDJhDfMIciONMedifAAB
ios:username(newuser2)/password/secret  6 XTXfOVUcYDZKd`FBH\S]XEJ_FcIAAB
ios:username(newuser3)/password/secret  6 QFVNW\__Pc[gDG_Fi_ccEQQWHA[DIHJhTAAB