gNSI
gRPC Network Security Interface (gNSI) is a set of RPCs that allow a client to define the security configuration of a device and to retrieve security information. gNSI is maintained by the OpenConfig project on Github, and contains a set of RPCs as well as extensions to gNMI and the OpenConfig YANG modules.
SR Linux supports the following gNSI services:
gNSI Authz service
The gNSI Authz service allows clients to configure and manage a gRPC-level authorization policy that defines which users can access which gRPCs on the target node. This policy is defined by a JSON string and controls access to all gRPC servers to prevent access from malicious actors.
Unlike role-based access control, which provides authorization of system YANG paths, the Authz service authorizes the use of individual gRPCs; for example access to the /gnmi.gNMI/Get RPC, rather than to any individual path that the Get RPC can retrieve.
Typical Authz service steps
In the typical Authz service process, the client performs the following steps:
- Upload the authorization policy by sending an UploadRequest to the target node using the Rotate RPC.
- Verify that the authorized users can access the required gRPCs (and that non-authorized users are denied) by sending a ProbeRequest using the Probe RPC.
- Lock in the updates by sending a FinalizeRequest using the Rotate RPC.
- As required, retrieve details of the currently active policy by sending a GetRequest using the Get RPC.
Authz policy
The Authz policy consists of the following:
- name: name for the policy defined by the client
- allow_rules list (mandatory): list of allow rules for the policy
- deny_rules list (optional): list of deny rules for the policy
Allow and deny rules
Each allow or deny list is comprised of instances of rules. Each rule consists of the following:
- name: name for the rule defined by the client; similar to the policy name
- source: a holding container with a single source type of
principals:
- principals: a list of principals that must match against user objects, be it one of the users defined in system aaa authentication user, a remotely resolved user from a system aaa server-group, or the admin
- request contains:
- paths: a list of gRPC RPC paths (in format pkg.Service/Rpc) that this policy applies to; for example: /gnoi.os.OS/Install (if no paths are provided, all paths are matched)
- headers: a list of key/value pairs matching HTTP
headersNote: SR Linux does not support matching on headers.
Matching source and request
Both the source and request fields must match in order for a rule to match. If both source and request are empty, the rule always matches. Empty source and request can serve as a wildcard in a deny_rules list to deny all RPCs or in an allow_list to accept all RPCs except those matching in the deny_rules list.
If only the source is empty, the paths provided in the request field apply to all users system wide. Similarly if only the request is empty then the action (deny or allow) is applied to all users provided in the source. If no paths are specified in the request, all paths are matched.
Authz policy example
The following shows an example policy in which two administrators Alice and Bob have the ability to execute any of the gNSI Authz RPCs.
{
"name": "gNSI.authz policy",
"allow_rules": [{
"name": "admin-access",
"source": {
"principals": [
"spiffe://nokia.com/sa/alice",
"spiffe://nokia.com/sa/bob"
]
},
"request": {
"paths": [
"/gnsi.authz.Authz/*"
]
}
}]
}
Authz policy persistence
As it is a requirement to persist a policy after it has been finalized, on finalization the current policy is written to /etc/opt/srlinux/gnsi/authz-policy.json. This policy is read by the SR Linux gNSI server on startup and exposed as the active policy.
It is an Authz requirement that if a policy is configured, no gRPC servers (this includes P4RT, gRIBI, gNOI, gNMI, and gNSI externally) can start until the policy is successfully activated. The Authz scope is to protect access to system RPCs from malicious entities, so a policy must be active before ports are opened.
Default Authz policy
As part of the default SR Linux configuration, the Authz service is running, and a default Authz policy controls access to every active gRPC service. The result of the default policy is that any authenticated user is permitted full access to any currently active service and gRPC. This does not overrule any subsequent role-based access control that exists on the system.
{
"name": "Default policy",
"deny_rules": [],
"allow_rules": [
{
"name": "admin-access",
"source": {
"principals": [
"*"
]
},
"request": {
"paths": [
"/*",
""
],
"headers": []
}
}
]
}
Authz authorization logic and interactions
To validate a gRPC authorization, gNSI performs the following actions:
- Check the user and RPC combination against any deny_rules. If a match is found, the request is denied. If no match is found or there are no deny_rules, execute the next step.
- Check for a match against any allow_rules. If a match is found, the request is permitted. If no match is found, deny the request.
Authz interactions with role-based access control and service authorization
The Authz service operates in addition to existing role-based access control and service authorization. As a result, to provide a user access to a gRPC, you must configure their access under role-based access control and service authorization (for example, system aaa authorization role services gnmi) in addition to enabling access using the Authz service. The system aaa authorization role services command also supports defining service authorization for gnsi.
Order of authorization
The order of authorization is as follows:
- Check service authorization first; only if the user is authorized for the service are they admitted.
- If the interface is a gRPC interface, check the Authz policy to see if the user is authorized for the specified RPC.
- If the user is configuring or reading any paths, perform role-based access control.
Default TLS profile
To allow the gNMI (and gNSI) server to start as part of the default configuration, the factory default configuration includes a TLS profile named __default__. This default policy does not authenticate the identity of connecting clients. You can view the policy using the info from state system tls server-profile __default__ command.
# info from state system tls server-profile __default__
system {
tls {
server-profile __default__ {
key $aes1$4lL6SVq5G8=$FqANWbk8TQmrGYB1cTuaplFUZTZlAP992Debrq4X2ZjfOde4wA
...
certificate "-----BEGIN CERTIFICATE-----
MIIFLzCCAxegAwIBAgIUBQFYPrWyBalNUfTNCBUAMiWrk2kwDQYJKoZIhvcNAQEL
BQAwHTEOMAwGA1UEAwwFc3JsZDUxCzAJBgNVBAYTAlVTMCAXDTI0MDIyMDIzNTY0
...
-----END CERTIFICATE-----
"
authenticate-client false
dynamic true
cipher-list [
ecdhe-ecdsa-aes256-gcm-sha384
ecdhe-ecdsa-aes128-gcm-sha256
ecdhe-rsa-aes256-gcm-sha384
ecdhe-rsa-aes128-gcm-sha256
]
}
}
}
SR Linux also supports a default TLS configuration option for the gRPC server (system grpc-server name default-tls-profile [true | false]) that controls whether the system uses the default TLS profile if none are configured using the tls-profile option. If default-tls-profile is set to false (the default value), and no tls-profile is defined, then TLS is disabled entirely from the system.
Supported RPCs
SR Linux supports the following Authz service RPCs:
Rotate RPC
The Authz Rotate RPC allows a client to replace an existing gRPC authorization policy on the target node.
If any steps in the Rotate RPC process fail, the target node rolls back any changes made by the RPC.
Only one Rotate RPC can be in progress at a time. If a client attempts to call the RPC while another call is already in progress, the second call is rejected with a gRPC error of UNAVAILABLE.
Rotate RPC structure
rpc Rotate(stream RotateAuthzRequest) returns (stream RotateAuthzResponse);
Probe RPC
The Authz Probe RPC tests the currently active policy. It allows the Authz policy engine on the target node to provide a response to a specified gRPC call without actually performing the gRPC operation. The current policy can be one that has not been finalized, but this is not a requirement.
The Probe RPC expects a single ProbeRequest message, and returns a ProbeResponse. The ProbeRequest does not result in an actual gRPC call being made; it simply validates whether the call can succeed with the provided user and RPC information.
Probe RPC structure
rpc Probe(ProbeRequest) returns (ProbeResponse);
Get RPC
The Authz Get RPC returns the currently active gRPC authorization policy, as well as the policy version and created-on timestamp.
Get RPC structure
rpc Get(GetRequest) returns (GetResponse);
gNSI Authz tools and state commands
To allow the gNSI Authz behavior to be invoked in the CLI or by a gNMI or JSON-RPC client, SR Linux supports the following tools commands:
- tools system aaa authorization authz-policy clear
- tools system aaa authorization authz-policy probe
- tools system aaa authorization authz-policy remove
- tools system aaa authorization authz-policy rotate
Clearing Authz policy counters using the tools command
To clear Authz policy counters, use the tools system aaa authorization authz-policy clear command.
Clear Authz policy counters
--{ candidate shared default }--[ ]--
# tools system aaa authorization authz-policy clear
Probing Authz policy counters using the tools command
To probe an Authz policy, use the tools system aaa authorization authz-policy probe command. The rpc parameter specifies which RPC to test, and the user parameter specifies which user to use for the test.
Probe Authz policy counters
--{ candidate shared default }--[ ]--
# /tools system aaa authorization authz-policy probe rpc /gnmi.gNMI/Get user admin
/system/aaa:
Authz authorization policy version '1' action for user 'admin' and rpc '/gnmi.gNMI/Get' is ACTION_PERMIT
Removing an Authz policy using the tools command
To remove an Authz policy, use the tools system aaa authorization authz-policy remove command.
Given that there is only one system-wide gRPC authorization policy, this command reverts to the factory default authorization policy, which authorizes any gRPC call for every authenticate user.
Remove Authz policy
--{ candidate shared default }--[ ]--
# tools system aaa authorization authz-policy remove
Rotating an Authz policy using the tools command
To rotate an Authz policy, use the tools system aaa authorization authz-policy rotate command, which supports the following parameters:
- created-on: sets the created-on value for the new policy
- policy: specifies the gRPC authorization policy as a JSON-formatted string
- version: specifies a version string to store with the policy
Unlike the Rotate RPC, the tools system aaa authorization authz-policy rotate command triggers an immediate finalization.
Rotate Authz policy
--{ candidate shared default }--[ ]--
# / tools system aaa authorization authz-policy rotate policy "{\"name\": \"foo\", \"allow_rules\": { \"name\": \"dev\", \"source\": { \"principals\": [
\"admin\", \"foo\", \"bar\" ] }, \"request\": { \"pat hs\": [ \"/*\", \"\" ] } } }" created-on 10 version 1
/system/aaa:
Authz authorization policy has been rotated and finalized (version '' created on '1970-01-01T00:00:10.000Z')
Displaying the currently installed Authz policy
To display the currently installed Authz policy, use the info from state system aaa authorization authz-policy command.
Display the currently installed Authz policy
# info from state system aaa authorization authz-policy
system {
aaa {
authorization {
authz-policy {
version 2023-06-01
created-on "2024-02-16T17:29:08.721Z (40 minutes ago)"
policy "{
\"name\": \"Default policy\",
\"deny_rules\": [],
\"allow_rules\": [
{
\"name\": \"admin-access\",
\"source\": {
\"principals\": [
\"*\"
]
},
\"request\": {
\"paths\": [
\"/*\",
\"\"
],
\"headers\": []
}
}
]
}
"
}
}
}
}
gNSI Certz service
The gNSI Certz service allows a client to replace a certificate, trust bundle, certificate revocation list (CRL), or some combination of these artifacts on a target node.
Typical Certz service steps
In the typical certificate rotation process, the client performs the following steps using the Rotate RPC:
- Either generate the CSR on the client side, or direct the target node to generate the CSR using a GenerateCSRRequest.
- Obtain a signature for the certificate from the CA (out of band of the RPC).
- Upload the signed certificate to the target node using an UploadRequest.
- Verify (out of band of the RPC) that the services that use the new certificate bundle continue to operate normally.
- Send a FinalizeRequest to the target node to lock in the updates.
Entity messages
The Certz service uses Entity messages to define the Certz artifacts, which can be any of the following:
- Certificate: An X.509 certificate and optional private key that is either PEM or DER encoded. The specific encoding is indicated in fields carried in children of the Entity message. A certificate also specifies any intermediate parent certificates. It is equivalent to the certificate displayed using the system tls server-profile name certificate command.
-
Trust bundle: The certificate bundle used to validate outbound connections, and inbound clients when mTLS is enabled. This is a typical system trust bundle available in /etc/ssl/certs. It is equivalent to the trust anchor displayed using the system tls server-profile name trust-anchor command.
- CRL: The CRL bundle, which lists certificates that have been revoked and can no longer be used to validate connections. It is equivalent to the CRL displayed using the system tls server-profile name certificate-revocation-list command.
All together, these artifacts make up a single profile. In a single Rotate RPC call, a client can rotate all artifacts, or only specific artifacts.
Default TLS profile
The default TLS profile is available at system startup and uses system-generated self-signed certificates and private keys. The default profile is saved to disk with other TLS profiles at /etc/opt/srlinux/tls. This default profile allows the gRPC server to start as part of the default configuration to meet the requirements of the Authz service.
TLS profiles can be populated using the Certz service or configured via the CLI using the system tls server-profile command. If a conflict exists in the configuration, the CLI configuration takes precedence.
Certz state paths
Certz state paths are available under system tls server-profile certz. These paths indicate the certificate, trust bundle, and CRL in use by each specific instance of a gRPC server.
The Certz JSON files are stored in /etc/opt/srlinux/gnsi, while the CRL PEM files are stored in /etc/opt/srlinux/tls.
Only users in the tls group can read these artifacts, and only the srlinux user can modify them.
Supported RPCs
SR Linux supports the following Certz service RPCs:
Rotate RPC
The Certz Rotate RPC allows a client to replace an existing certificate, trust bundle, CRL, or some combination of these artifacts on the target node. Either the target node or the client can generate the CSR for the new device certificate. If the client generates the CSR, it must also provide the corresponding private key with the signed certificate.
Only one Rotate RPC can be active at once. If SR Linux detects an additional Rotate RPC, it returns an error.
The Rotate RPC accepts a stream of RotateCertificateRequest messages and returns a stream of RotateCertificateResponse messages in response. A client uses the RPC to upload a certificate by specifying the certificate in a rotate_request before testing the new certificate (out of band of the RPC) and finalizing the result with a finalize_rotation. Until the target node receives the finalize_rotation, the change is transient and not persistent on disk. If the RPC is canceled for any reason before a finalize_rotation is received, then the system reverts all services using TLS to the previous values.
If the stream is broken or any of the steps fail, the target node rolls back to the original state, reverting any changes to any artifact.
Rotate RPC structure
rpc Rotate(stream RotateCertificateRequest) returns (stream RotateCertificateResponse);
Rotate RPC use cases
The following sections describe a number of Rotate RPC use cases each presenting the expected sequence of message exchange.
Case 1: Client generates the CSR and gets it signed
-
The Rotate RPC stream begins.
Client <------ Rotate() RPC stream begins ------> Target node
-
The client generates the CSR and gets the certificate signed by the CA (typically done before initiating the stream).
-
The client sends the signed certificate with private key to the target node.
The client can optionally include a trust bundle, a CRL, or both.
Client ------> UploadRequest(certificate, [trust_bundle], ------> Target node [certificate_revocation_list]) Client <------ UploadResponse <------ Target node
-
To validate that the certificate works, the client attempts to create new connections to the target node using the new certificate. If the new connections fail, the client cancels the RPC, forcing the target node to roll back all certificates included in the RPC.
If a new CRL bundle is included in the UploadRequest in step 3, the client also attempts to establish new connections to the target node using the revoked certificates. In this case, failed connections validate that the certificates have been revoked.
-
After successful validation, the client sends a final commit.
Client ------> FinalizeRequest ------> Target node
Case 2: Target node generates the CSR and the client gets it signed
-
Rotate RPC stream begins:
Client <------ Rotate() RPC stream begin ------> Target node
-
The client sends a GenerateCSRRequest to the target node, and the target node provides the CSR in response:
Client ------> GenerateCSRRequest ------> Target node Client <------ GenerateCSRResponse <------ Target node
-
The client obtains a signature for the certificate from the CA.
-
The client sends the signed certificate without private key to the target node (the target node already has the private key because it generated the CSR).
The client can optionally include a trust bundle, a CRL, or both.
Client ------> UploadRequest(certificate, [trust_bundle], ------> Target node [certificate_revocation_list]) Client <------ UploadResponse <------ Target node
-
The client tests and validates the certificate, using the same validation step as in Case 1.
-
After successful validation, the client sends a final commit.
Client ------> FinalizeRequest ------> Target node
Case 3: Client changes only the trust bundle
-
The Rotate RPC stream begins:
Client <------ Rotate() RPC stream begin ------> Target node
-
The client sends a Certificate Authority Bundle chain to the target node.
The client can optionally include a CRL.
Client ------> UploadRequest(trust_bundle, ------> Target node [certificate_revocation_list]) Client <------ UploadResponse <------ Target node
-
The client tests and validates the certificate, using the same validation step as in Case 1.
-
After successful validation, the client sends a final commit.
Client ------> FinalizeRequest ------> Target node
Case 4: Client uploads a CRL
-
The Rotate RPC stream begins:
Client <------ Rotate() RPC stream begin ------> Target node
-
The client sends a CRL bundle to the target node.
Client ------> UploadRequest([certificate_revocation_list]) ------> Target node Client <------ UploadResponse <------ Target node
-
The client validates the CRL by attempting to establish a new connection to the target node using the revoked certificates. Failed connections validate that the certificates have been revoked.
-
After successful validation, the client sends a final commit.
Client ------> FinalizeRequest ------> Target node
CanGenerateCSR RPC
The Certz CanGenerateCSR RPC tests whether the target node is able to generate a CSR given provided parameters. The CanGenerateCSR RPC consists of a single CanGenerateCSRRequest message and returns a CanGenerateCSRResponse. The client includes the parameters that it wants the target node to test for the CSR generation, including:
- key_type: the algorithm used for generation of the key pair (for example, KEY_TYPE_RSA)
- signature_algorithm_type: the signature algorithm used to generate the key pair (for example: SIGNATURE_ALGORITHM_SHA512_WITH_RSA)
- certificate_type: the type of certificate to create (for example, CERTIFICATE_TYPE_X509)
- key_size_bits: a uint32, indicating the size of the key in bits (for example, 2048)
CanGenerateCSR RPC structure
rpc CanGenerateCSR(CanGenerateCSRRequest) returns (CanGenerateCSRResponse);
AddProfile RPC
The Certz AddProfile RPC allows a client to add a new TLS profile to the target node. All elements of the added profile (certificate, CA trust bundle, and CRLs) are initially empty. The client must subsequently populate the artifacts using a Rotate RPC.
If a client attempts to add a pre-existing profile, the attempt is rejected with an error.
AddProfile RPC structure
rpc AddProfile(AddProfileRequest) returns (AddProfileResponse);
DeleteProfile RPC
The Certz DeleteProfile allows a client to remove an existing TLS profile.
The __default__ profile used by the gRPC server cannot be deleted. If a client attempts to delete the __default__ profile, the attempt is rejected with an error.
DeleteProfile RPC structure
rpc DeleteProfile(DeleteProfileRequest) returns (DeleteProfileResponse);
GetProfileList RPC
The Certz GetProfileList RPC allows a client to retrieve a list of the TLS profile IDs that are present on a target node.
GetProfileList RPC structure
rpc GetProfileList(GetProfileListRequest) returns (GetProfileListResponse);
gNSI Certz tools commands
To allow the gNSI Certz RPC behavior to be invoked in the CLI or by a gNMI or JSON-RPC client, SR Linux supports the following tools commands:
- tools system tls server-profile <name> certz rotate
- tools system tls server-profile <name> certz remove
Rotating a Certz profile using the tools command
To rotate a profile on the system, use the tools system tls server-profile <name> certz rotate command, which supports the following parameters:
- certificate: specifies the new certificate to use
- created-on: sets the created on value for the new policy
- crl: specifies a bundle of certificates to add to the CRL
- key: specifies the new private key to use
- trust-anchor: specifies a certificate chain to use as a trust anchor
- version: specifies the version string to store with the policy
Rotate Certz profile using tools command
The following example rotates the test-certz-profile with certificate test-cert, key test-key, CRL test-crl, trust anchor test-anchor, and assigned version of 1.
--{ candidate shared default }--[ ]--
# tools system tls server-profile test-certz-profile certz rotate certificate test-cert key test-key crl test-crl trust-anchor test-anchor version 1
/system/tls/server-profile[name=test-certz-profile]:
Certz SSL profile 'test-certz-profile' has been added
/system/tls/server-profile[name=test-certz-profile]:
Certz SSL profile 'test-certz-profile' has been rotated and finalized (version '1' created on '2024-02-16T16:20:03.000Z')
Removing a Certz profile using the tools command
To remove a profile from the system, use the tools system tls server-profile certz remove command.
Remove a Certz SSL profile using tools command
--{ candidate shared default }--[ ]--
# tools system tls server-profile test-certz-profile certz remove
/system/tls/server-profile[name=test-certz-profile]:
Certz SSL profile 'test-certz-profile' has been removed
gNSI Certz state commands
Certz state paths are available under system tls server-profile. These paths indicate the certificate, trust bundle, and CRL in use by each specific instance of a gRPC server.
- info from state system tls server-profile <name> certz certificate
- info from state system tls server-profile <name> certz crl
- info from state system tls server-profile <name> certz ssl-profile-id
- info from state system tls server-profile <name> certz trust-anchor
Info from state for empty TLS server profile dyn
--{ running }--[ ]--
# info from state system tls server-profile dyn
system {
tls {
server-profile dyn {
dynamic true
certz {
ssl-profile-id dyn
}
}
}
}
Info from state for rotated TLS server profile dyn
--{ running }--[ ]--
# info from state system tls server-profile dyn
system {
tls {
server-profile dyn {
key $aes1$ATQxUhdz4QGeu28=$HrE...
certificate "-----BEGIN CERTIFICATE----- MIIGW... ----END CERTIFICATE-----"
authenticate-client true
trust-anchor "-----BEGIN CERTIFICATE----- MIIFe... -----END CERTIFICATE-----"
dynamic true
cipher-list [
ecdhe-ecdsa-aes256-gcm-sha384
ecdhe-ecdsa-aes128-gcm-sha256
ecdhe-rsa-aes256-gcm-sha384
ecdhe-rsa-aes128-gcm-sha256
]
certz {
ssl-profile-id dyn
certificate {
version 7
created-on "2023-08-19T08:56:45.000Z (6 months ago)"
}
trust-anchor {
version 9
created-on "2023-08-19T14:53:09.000Z (6 months ago)"
}
}
}
}
}
gNSI configuration
SR Linux supports gNSI services using the gRPC server configuration. To enable gNSI support, enable the gRPC server and specify gNSI as one of the enabled gRPC services for a specified network instance (enabled by default on the mgmt network instance).
Like gNMI, the session between the gNSI client and SR Linux can be encrypted using TLS.
gNMI and gNSI servers enabled by default
By default, the gNMI and gNSI servers are enabled in the mgmt network instance.
# info system grpc-server mgmt system {
grpc-server mgmt {
admin-state enable
default-tls-profile true
network-instance mgmt
services [
gnmi
gnsi
]
}
}
Configuring gNSI services
As part of the gRPC server configuration, you can also specify which individual gNSI services to enable.
Enable gNSI services
# info system grpc-server mgmt
system {
grpc-server mgmt {
admin-state enable
network-instance mgmt
services [
gnsi
]
}
}
See the "Management servers" chapter in the SR Linux Configuration Basics Guide for related information about how to configure the gRPC server.