Running Third-Party Applications Natively With Signing Keys
Signing Keys Overview
Starting in Junos OS Evolved Release 22.4R1, you can generate signing keys and use them to sign executable files or shared objects. Signing an executable file gives it permission to run on the device, allowing you to approve trusted applications to run alongside authorized Juniper Networks software.
Junos OS Evolved requires users to sign all files that will be mapped into memory for execution. This includes the following file types:
-
Executable and Linkable Format (ELF) files
-
Shared Objects (.so) files
The following types of files do not need to be signed:
-
Docker containers
-
Applications inside containers
-
Scripts
Note:Although scripts don’t need to be signed, they do need to be passed through a signed interpreter for execution. Junos OS Evolved comes installed with signed Python 2 and Python 3 interpreters that can be used through the
python script-name
shell command.
Signing keys are controlled by a Linux subsystem called Integrity Measurement Architecture (IMA). IMA policy consists of rules that define which actions needs to be taken before a file can be executed. IMA measurement policy will measure and store a file’s hash, and IMA appraisal policy will make sure that the file has a valid hash or digital signature. IMA will only allow a file to run if this validation succeeds. For more information about IMA, see Protecting the Integrity of Junos OS Evolved with IMA.
Signing keys are stored in the system keystore, and the certificates used the verify signing keys are stored in the IMA extended keyring. Keep reading to learn how to generate, import, view, and use signing keys.
Generating Signing Keys
Keys can be generated through the OpenSSL command-line or a OpenSSL configuration file.
- Generating Signing Keys Using the OpenSSL Command-Line
- Generating Signing Keys Using an OpenSSL Configuration File
Generating Signing Keys Using the OpenSSL Command-Line
The following example OpenSSL command can be used to generate signing keys:
openssl req -new \ -newkey rsa:3072 \ # Create an RSA 3072 key -x509 \ # Need an X509 certificates -sha256 \ # Strong hashing algorithm -nodes \ # No encrypted private-key -out ima-cert.x509 \ # Name of the certificate file -outform DER \ # Key in DER format -keyout privkey.pem \ # Name of the private key
This command will generate 2 files:
-
privkey.pem
- The PEM encoded private key that can be used to sign executable files. -
ima-cert.x509
- The DER encoded certificate to be loaded into the IMA extended keyring.
The OpenSSL command-line is limited in its functionality. It does not allow you to set values for the X509v3 extensions. All keys generated using the command above can be used as Certificate Authorities (CAs), and therefore can be used to sign other certificates. To prevent this, we can use an OpenSSL Configuration File.
Generating Signing Keys Using an OpenSSL Configuration File
Create a file named ima-x509.cnf
and
paste the following contents:
# Begining of ima-x509.cnf [ req ] default_bits = 2048 distinguished_name = custom_distinguished_name prompt = no string_mask = utf8only x509_extensions = custom_exts [ custom_distinguished_name ] O = Juniper Networks, Inc. CN = IMA extended signing key emailAddress = john.smith@juniper.net [ custom_exts ] basicConstraints=critical,CA:FALSE keyUsage=digitalSignature subjectKeyIdentifier=hash authorityKeyIdentifier=keyid # EOF
After the configuration file is created, use the
following OpenSSL command to create the
ima-privkey.pem
and
ima-cert.x509
files:
openssl req -new \ -nodes \ -utf8 \ -sha1 \ -days 36500 \ -batch \ -x509 \ -config ima-x509.cnf \ -outform DER -out ima-cert.x509 \ -keyout ima-privkey.pem
The private key file ima-privkey.pem
is
used to generate signing keys, and the certificate
file ima-cert.x509
is used to
verify the signature. Both files are used during the
process of importing signing keys into the system
keystore and IMA extended keyring.
Importing Signing Keys into the System Keystore and IMA Extended Keyring
Signing keys need to be imported into the system keystore prior to use. Keys that are imported into the system keystore are automatically imported into the IMA extended keyring. Keys will be imported on both Routing Engines.
To import a signing key into the system keystore, use the
request security system-keystore
import
command with the following 2 mandatory arguments:
-
key-name
- A unique name for the key -
x509-cert
- Path to the DER encoded certificate file
The following example command will create a key named
ima-test-key by using the certificate
file ima-cert.x509
:
user@host> request security system-keystore import key-name ima-test-key x509-cert ima-cert.x509 Key Name: ima-test-key X509 Cert Path: /etc/ima-ext/ima-test-key/ima-cert.x509 Key SKI: b71b35e380517cd224b46072dadeb6c53e0a58a1
When the key is successfully imported into the
system-keystore
you will see the above
output displaying the name of the key, the path to the certificate
on disk, and the Subject Key Identifier (SKI) for the key. You can
check if this SKI matches with the key loaded into the IMA Extended
keyring with the following command:
user@host> show security integrity extended-keyring Keyring 351716837 ---lswrv 0 0 keyring: ima_ext 684930381 --als--v 0 0 \_ asymmetric: Juniper Extended Signing Key: b71b35e380517cd224b46072dadeb6c53e0a58a1
Viewing the System Keystore and IMA Extended Keyring
You can view the contents of the system keystore and the IMA extended
keyring through Junos OS Evolved CLI show
commands.
Use the
show security integrity
system-keystore
command to view the available
signing keys in the system keystore:
user@host> show security integrity system-keystore Available signing keys: --- Key Name: ima-test-key X509 Cert Path: /etc/ima-ext/ima-test-key/ima-cert.x509 Key SKI: b71b35e380517cd224b46072dadeb6c53e0a58a1 --- Key Name: test-key1 X509 Cert Path: /etc/ima-ext/test-key1/ima-cert.x509 Key SKI: 332f173d61bba03fed5399a609523cbd3cfe66b3 --- Key Name: test-key2 X509 Cert Path: /etc/ima-ext/test-key2/ima-cert.x509 Key SKI: 26ebafd58b54f7b8b530d0311503fd84873ee754 ---
The information in the Key SKI field can be used to map these keys to the IMA extended keyring.
Use the show security integrity extended-keyring
command
to view the contents of the IMA extended keyring:
user@host> show security integrity extended-keyring Keyring 351716837 ---lswrv 0 0 keyring: ima_ext 684930381 --als--v 0 0 \_ asymmetric: Juniper Extended Signing Key: b71b35e380517cd224b46072dadeb6c53e0a58a1 316767440 --als--v 0 0 \_ asymmetric: Juniper Extended Signing Key: 26ebafd58b54f7b8b530d0311503fd84873ee754 950431262 --als--v 0 0 \_ asymmetric: Juniper Extended Signing Key: 332f173d61bba03fed5399a609523cbd3cfe66b3
How to Sign Applications
After a signing key has been imported into the system keystore, it can be used to sign executable binaries.
Use the
request security integrity
measure file filename key
key-name
command to sign
a file.
The following example command shows a file named ima-test being signed by a key named ima-test-key:
user@host> request security integrity measure file ima-test key ima-test-key Successfully signed file /data/var/home/root/ima-test
You can verify that your file was successfully signed by using the
request security integrity appraise file
filename key
key-name
command, as
follows:
user@host> request security integrity appraise file ima-test key ima-test-key File /data/var/home/root/ima-test has a valid IMA signature
If the file was not signed properly, the following message will display:
user@host> request security integrity appraise file ima-test key ima-test-key warning: IMA signature verification failed for /data/var/home/root/ima-test using ima-test-key IMA appraisal for /data/var/home/root/ima-test failed.
After a file has been signed, it can be run natively on your Junos OS Evolved device.