配置 gNOI 服务
总结 将远程网络管理系统配置为可在网络设备上执行 gNOI 操作的 gRPC 客户端。
gRPC 网络操作接口 (gNOI) 使用 gRPC 远程过程调用 (gRPC) 框架在网络设备上执行操作。网络管理系统必须安装 gRPC 堆栈。
OpenConfig 为 gNOI 服务定义了原型定义文件。原型定义文件定义给定服务的操作 (RPC) 和数据结构(消息)。这些定义与语言无关。gRPC 支持使用许多不同的语言来执行服务操作。您必须为所选语言编译原型定义文件。然后,创建使用已编译文件中的对象(类、函数、方法等)的应用程序,以连接到网络设备上的 gRPC 服务器并执行所需的操作。
有关将 gRPC 与不同的受支持语言一起使用的信息,请参阅 gRPC 文档。以下部分提供了用于设置 gRPC 客户端以及下载和编译 Python 的 gNOI 原型定义文件的示例命令。必须使用适用于所选操作系统、环境和 gRPC 语言的命令。
在配置 gRPC 客户端之前,请按照 配置 gRPC 服务中的定义配置 gRPC 服务器。
设置 gRPC 客户端
gNOI 使用 gRPC 框架在网络设备上执行操作。gRPC 支持使用许多不同的语言。在使用所选语言执行 gNOI 操作之前,必须在网络管理系统上安装 gRPC 堆栈。
例如,要在运行 Ubuntu 20.04 LTS 的网络管理系统上安装 Python 的 gRPC 堆栈(在适当的情况下使用 sudo ):
编译原型定义文件
gRPC 支持使用多种语言。若要在网络设备上执行 gRPC 操作,必须针对所选语言编译相应的原型定义文件。OpenConfig 在 OpenConfig GitHub 存储库中提供了必要的原型定义文件。您可以使用协议缓冲区编译器(protoc 或等效应用程序)来编译 .proto 文件。
对于此设置,我们执行一个脚本,将所有所需的 .proto 文件复制到目录中,更新文件以使用相对导入语句,然后编译文件。
要下载并编译 Python 的 gNOI 原型定义文件,请执行以下操作:
创建 gNOI 应用程序
编译原型定义文件后,将创建使用已编译文件中的对象的应用程序。应用程序连接到网络设备上的 gRPC 服务器并执行所需的操作。本节提供了两个示例 Python 模块,它们在各自的部分中进行了介绍。
grpc_channel.py
Python grpc_channel.py 模块提供了示例函数,这些函数使用为所选身份验证方法(仅限服务器或相互)提供的参数创建 gRPC 通道。
import grpc
from os.path import isfile
def grpc_authenticate_channel_mutual(server, port, root_ca_cert="", client_key="", client_cert=""):
if not isfile(root_ca_cert):
raise Exception("Error: root_ca_cert file does not exist")
if (client_key == "") or (not isfile(client_key)):
raise Exception(
"Error: client_key option is missing or target file does not exist")
elif (client_cert == "") or (not isfile(client_cert)):
raise Exception(
"Error: client_cert option is empty or target file does not exist")
print("Creating channel")
creds = grpc.ssl_channel_credentials(open(root_ca_cert, 'rb').read(),
open(client_key, 'rb').read(),
open(client_cert, 'rb').read())
channel = grpc.secure_channel('%s:%s' % (server, port), creds)
return channel
def grpc_authenticate_channel_server_only(server, port, root_ca_cert=""):
if isfile(root_ca_cert):
print("Creating channel")
creds = grpc.ssl_channel_credentials(open(root_ca_cert, 'rb').read(),
None,
None)
channel = grpc.secure_channel('%s:%s' % (server, port), creds)
return channel
else:
raise Exception("root_ca_cert file does not exist")
gnoi_connect_cert_auth_mutual.py
gnoi_connect_cert_auth_mutual.py Python 应用程序与给定的 gRPC 服务器建立 gRPC 通道,并执行简单的 gNOI System 服务操作。用户提供必要的连接和相互身份验证信息作为应用程序的输入。应用程序调用模块中的grpc_channel.py相应函数,以在客户端和服务器之间建立 gRPC 通道。如果应用程序成功建立了 gRPC 通道,它将执行一个简单的系统服务 RPC 以从网络设备检索时间。
"""gRPC gNOI Time request utility."""
from __future__ import print_function
import argparse
import logging
from getpass import getpass
import system_pb2
import system_pb2_grpc
from grpc_channel import grpc_authenticate_channel_mutual
def get_args(parser):
parser.add_argument('--server',
dest='server',
type=str,
default='localhost',
help='Server IP or name. Default is localhost')
parser.add_argument('--port',
dest='port',
nargs='?',
type=int,
default=50051,
help='The server port. Default is 50051')
parser.add_argument('--client_key',
dest='client_key',
type=str,
default='',
help='Full path of the client private key. Default ""')
parser.add_argument('--client_cert',
dest='client_cert',
type=str,
default='',
help='Full path of the client certificate. Default ""')
parser.add_argument('--root_ca_cert',
dest='root_ca_cert',
required=True,
type=str,
help='Full path of the Root CA certificate.')
parser.add_argument('--user_id',
dest='user_id',
required=True,
type=str,
help='User ID for RPC call credentials.')
args = parser.parse_args()
return args
def send_rpc(channel, metadata):
stub = system_pb2_grpc.SystemStub(channel)
print("Executing GNOI::System::Time RPC")
req = system_pb2.TimeRequest()
try:
response = stub.Time(request=req, metadata=metadata, timeout=60)
except Exception as e:
logging.error('Error executing RPC: %s', e)
print(e)
else:
logging.info('Received message: %s', response)
return response
def main():
parser = argparse.ArgumentParser()
args = get_args(parser)
grpc_server_password = getpass("gRPC server password for executing RPCs: ")
metadata = [('username', args.user_id),
('password', grpc_server_password)]
try:
# Establish grpc channel to network device
channel = grpc_authenticate_channel_mutual(
args.server, args.port, args.root_ca_cert, args.client_key, args.client_cert)
response = send_rpc(channel, metadata)
print("Response received: time since last epoch in nanoseconds is ", str(response))
except Exception as e:
logging.error('Received error: %s', e)
print(e)
if __name__ == '__main__':
logging.basicConfig(filename='gnoi-testing.log',
format='%(asctime)s %(levelname)-8s %(message)s',
level=logging.INFO,
datefmt='%Y-%m-%d %H:%M:%S')
main()
执行应用程序
创建应用程序以执行 gNOI 服务操作后,可以执行应用程序并提供任何必要的参数。下面的示例使用上一节中提供的脚本连接到网络设备上的 gRPC 服务器并请求时间。gRPC 服务器配置为需要并验证客户端的证书。
-
对于相互身份验证,除了服务器的 IP 地址、gRPC 端口和根 CA 证书外,客户端还提供自己的密钥和 PEM 格式的 X.509 公钥证书。客户端还提供用于 RPC 调用的凭据:
user_id参数提供用户名,应用程序提示输入用户密码。lab@gnoi-client:~/src/proto$ python3 gnoi_connect_cert_auth_mutual.py --server 10.53.52.169 --port 50051 --root_ca_cert /etc/pki/certs/serverRootCA.crt --client_key /home/lab/certs/client.key --client_cert /home/lab/certs/client.crt --user_id gnoi-user gRPC server password for executing RPCs: Creating channel Executing GNOI::System::Time RPC Response received: time since last epoch in nanoseconds is time: 1650061065769701762