オフデバイス JET アプリケーションの開発
概要
JET を使用して、オフデバイスで実行されるアプリケーションを開発できます。これにより、ネットワーク上のすべてのデバイスで JET のメリットを活用できます。開発を容易にするために、オフデバイス JET アプリケーションを好みの言語で書き込むことができます。オフデバイス アプリケーションを開発するには、次の手順に従います。
IDL ファイルをダウンロードしてコンパイルします。
選択した言語を使用してアプリケーションを開発します。
アプリケーションをパッケージ化します。
外部サーバーにアプリケーション パッケージを展開するか、JET VM から直接アプリケーションを実行します。
図 1 は、オフデバイス アプリケーション開発ワークフローを示しています。
アプリケーションの開発とパッケージ化
アプリケーションを開発する前に、「 JET VM のセットアップ 」の指示に従って JET VM をセットアップし、IDL ファイルをダウンロードしていることを確認してください。
「」も参照
アプリケーション導入の準備
外部サーバー上または JET VM から直接、アプリケーションを実行します。外部サーバーにアプリケーションを展開する前に、JET と Junos OS の連携を設定する必要があります。
Junos OS との JET インタラクションを設定する
オフデバイス アプリケーションを実行するには、Junos OS またはJunos OS Evolvedで設定を有効にする request-response 必要があります。要求応答サービスを使用する場合、クライアント アプリケーションは要求を発行し、Junos サーバーからの応答を同期的に待機します。このセクションを使用して、SSL(Secure Sockets Layer)モードで実行する要求応答サービスの JET サービス プロセス(jsd)を設定します。これにより、セキュリティが強化され、SSL ベースの API 接続が可能になります。
現在、JET は証明書交換用に Transport Layer Security(TLS)バージョン 1.2 をサポートし、複数の暗号化アルゴリズムをサポートしていますが、相互認証はサポートしていません。つまり、クライアントはサーバーを認証できますが、サーバーは SSL/TLS 証明書を使用してクライアントを認証できません。クライアント認証の場合は、認証サービス API から LoginCheck() 手順を使用します。
-
証明書名をローカルに追加して設定することで、jsdがSSLを使用できるようにします。この証明書は RSA 証明書である必要があります。ECDSA および DSA SSL 証明書はサポートされていません。
この方法は、xnm-sslなどのJunos OSの他のSSLベースのサービスと同じです。証明書の生成中に指定した証明書名エントリーを追跡します。次のセクションの
HOST_OVERRIDEPython アプリケーションの例の オプションで使用します。この例では、証明書名はrouter.user@jet-vm:~ jet$ openssl genrsa -aes256 -out router.key.orig 2048 user@jet-vm:~ jet$ openssl req -new -key router.key.orig -out router.csr user@jet-vm:~ jet$ openssl rsa -in router.key.orig -out router.key user@jet-vm:~ jet$ openssl x509 -req -days 365 -in router.csr -signkey router.key -out router.crt user@jet-vm:~ jet$ cat router.crt router.key > router.pem
メモ:証明書が同じ識別子で更新された場合、jsdの変更は反映されません。変更を反映するには、jsd階層で新しい識別子を持つ証明書を設定するか、jsd再起動を実行する必要があります。
-
SSL 証明書 の .pem ファイルを Junos デバイスにコピーします。
user@device% scp pem-file-name device-name:/var/tmp
例えば:
user@device% scp router.pem device:/var/tmp
-
Junos デバイスのキーチェーンに証明書を読み込みます。例えば、SSL 証明書のローカル名が 以下の場合は、以下のようになります
sslcert。[edit] user@device# set security certificates local sslcert load-key-file /var/tmp/router.pem
-
読み込まれた証明書の SSL のサポートを有効にします。
[edit system services extension-service request-response grpc] user@device# set ssl local-certificate cert-name
例えば:
[edit system services extension-service request-response grpc] user@device# set ssl local-certificate sslcert
-
(オプション)SSL を使用する特定の IP アドレスまたはポートを指定します。SSLはそのアドレスまたはポートを安全なチャネルにします。
[edit system services extension-service request-response grpc] user@device# set ssl address address user@device# set ssl port port-number
アドレスを 0.0.0.0 に設定すると、デバイスはすべてのポートで SSL を使用します。例えば、すべてのポートとデフォルトのTCPポート51051で、gRPCエンドポイントでSSLのサポートを有効にするには:
[edit system services extension-service request-response grpc] user@device# set ssl address 0.0.0.0 user@device# set ssl port 51051
-
jsdに添付できるリクエストレスポンスの同時接続の最大数を指定します。数が多いほど、クライアントのパフォーマンスへの影響が高くなります。
[edit system services extension-service request-response grpc] user@device# set max-connections 8
要求応答サービスが SSL モードで実行されるように jsd を設定しました。JET オフデバイス アプリケーションを導入する準備ができました。
-
使用するスクリプトを指定します。
[edit] user@device# set system scripts language python3
メモ:Junos OS リリース 21.1R1 およびリリース 22.3R1 Junos OS Evolved以降、Python 2.7 はサポートされ
set system scripts language pythonなくなり、 ステートメントは非推奨になりました。代わりに ステートメントをset system scripts language python3使用します。
例:Python JET アプリケーション
この例を使用して、Python で記述されたオフデバイス JET アプリケーションを開発します。gRPC でサポートされている他の言語についても同じガイダンスに従うことができます。この Python JET アプリケーションは、 コマンドを XML 形式で実行します get-system-uptime-information 。
この例では、 オプションは HOST_OVERRIDE 証明書生成時に指定した証明書名を使用します。 「アプリケーション導入の準備」を参照してください。
ジュニパーネットワークスは、XML の開始タグと終了タグ <xml-tag/> を表す次の形式と <xml-tag></xml-tag>. の両方をサポートしています。
Junos OS リリース 18.4R1 以降
Junos OS リリース 18.4R1 以降を使用する場合は、このセクションに示す Python アプリケーションの例をガイドとして使用します。
Python 3 を使用してアプリケーションを作成する場合は、スクリプトの例外ブロックに PASS キーワードを含めます。
except Exception as tx:
pass
#!/usr/bin/env python
# A simple Python client to run XML OP command 'get-system-uptime-information'
# Environment
# Python 2.7.12
# grpcio (1.12.0)
# grpcio-tools (1.12.0)
# Following files should be available in current working directory
# jnx_authentication_service_pb2_grpc.py
# jnx_authentication_service_pb2.py
# jnx_management_service_pb2_grpc.py
# jnx_management_service_pb2.py
import argparse
import grpc
import os
import stat
import jnx_authentication_service_pb2
import jnx_authentication_service_pb2_grpc
import jnx_management_service_pb2
import jnx_management_service_pb2_grpc
import jnx_common_base_types_pb2
_HOST_OVERRIDE = 'router'
def Main():
try:
parser = argparse.ArgumentParser()
parser.add_argument('-d','--device', help='Input hostname',
required=True)
parser.add_argument('-t','--timeout', help='Input time_out value',
required=True,type=int)
parser.add_argument('-u', '--user', help='Input username',
required=True)
parser.add_argument('-pw', '--password', help='Input password',
required=True)
args = parser.parse_args()
#Establish grpc channel to jet router
creds = grpc.ssl_channel_credentials(open('/tmp/router.pem').read(),
None, None)
channel = grpc.secure_channel(args.device + ":32767", creds,
options=(('grpc.ssl_target_name_override', _HOST_OVERRIDE,),))
#create stub for authentication services
stub = jnx_authentication_service_pb2_grpc.AuthenticationStub(channel)
#Authenticate
login_request = jnx_authentication_service_pb2.LoginRequest(
username=args.user, password=args.password, client_id="SampleApp")
login_response = stub.Login(login_request, args.timeout)
#Check if authentication is successful
if login_response.status.code == jnx_common_base_types_pb2.SUCCESS:
print "[INFO] Connected to gRPC Server"
else:
print "[ERROR] gRPC Server Connection failed:"
print login_response.status.message
#Create stub for management services
stub = jnx_management_service_pb2_grpc.ManagementStub(channel)
print "[INFO] Connected to management service"
for i in range(1):
#Provide API request details
op_xml_command = "<get-system-uptime-information></get-system-uptime-information>"
op = jnx_management_service_pb2.OpCommandGetRequest(
xml_command=op_xml_command, out_format=2)
# Invoke API
op_response = stub.OpCommandGet(op, args.timeout)
# Check API response like status and output
for resp in op_response:
if resp.status.code == jnx_common_base_types_pb2.SUCCESS:
print "[INFO] Invoked OpCommandGetRequest succeeded"
print "[INFO] Return output in CLI format = "
print resp.data
else:
print "[ERROR] Invoked OpCommandGetRequest failed"
print "[ERROR] " + resp.status.message
except Exception as ex:
print ex
if __name__ == '__main__':
Main()
user@jet-vm:~ jet$ python mgd_api_new_doc_example_ssl.py -d JUNOS_DEVICE -t TIMEOUT -u USER -pw PASSWORD [INFO] Connected to gRPC Server [INFO] Connected to management service [INFO] Invoked OpCommandGetRequest succeeded [INFO] Return output in CLI format = Current time: 2018-11-08 09:36:40 PST Time Source: NTP CLOCK System booted: 2018-10-09 17:02:56 PDT (4w1d 17:33 ago) Protocols started: 2018-10-09 17:05:09 PDT (4w1d 17:31 ago) Last configured: 2018-11-08 09:30:28 PST (00:06:12 ago) by root 9:36AM up 29 days, 17:34, 2 users, load averages: 1.05, 0.77, 0.57
Junos OS リリース 18.4R1 より前
18.4R1 より前の Junos OS リリースを使用している場合は、このセクションの Python アプリケーションの例をガイドとして使用してください。
#!/usr/bin/env python
# A simple Python client to run XML OP command 'get-system-uptime-information'
# Environment
# Python 2.7.12
# grpcio (1.12.0)
# grpcio-tools (1.12.0)
# Following files should be available in current working directory
# authentication_service_pb2_grpc.py
# authentication_service_pb2.py
# management_service_pb2_grpc.py
# management_service_pb2.py
import argparse
import grpc
import authentication_service_pb2
import authentication_service_pb2_grpc
import management_service_pb2
import management_service_pb2_grpc
_HOST_OVERRIDE = 'router'
def Main():
try:
parser = argparse.ArgumentParser()
parser.add_argument('-d','-device', help='Input hostname',
required=True)
parser.add_argument('-t','-timeout', help='Input time_out value',
required=True,type=int)
parser.add_argument('-u', '-user', help='Input username',
required=True)
parser.add_argument('-pw', '-password', help='Input password',
required=True)
args = parser.parse_args()
#Establish grpc channel to jet router
creds = grpc.ssl_channel_credentials(open('/tmp/router.pem').read(),
None, None)
channel = grpc.secure_channel(args.device + ":51051", creds,
options=(('grpc.ssl_target_name_override', _HOST_OVERRIDE,),))
#create stub for authentication services
stub = authentication_service_pb2_grpc.LoginStub(channel)
#Authenticate
login_request = authentication_service_pb2.LoginRequest(
user_name=args.user, password=args.password, client_id="SampleApp")
login_response = stub.LoginCheck(login_request, args.timeout)
#Check if authentication is successful
if login_response.result == True:
print "[INFO] Connected to gRPC Server:"
print login_response.result
else:
print "[ERROR] gRPC Server Connection failed!!!"
print login_response.result
#Create stub for management services
stub = management_service_pb2_grpc.ManagementRpcApiStub(channel)
print "[INFO] Connected to JSD and created handle to mgd services"
for i in range(1):
#Provide API request details
op_xml_command = "<get-system-uptime-information>" \
"</get-system-uptime-information>"
op = management_service_pb2.ExecuteOpCommandRequest(
xml_command=op_xml_command, out_format=2, request_id=1000)
# Invoke API
result = stub.ExecuteOpCommand(op, 100)
# Check API response like status and output
for i in result:
print "[INFO] Invoked ExecuteOpCommand API return code = "
print i.status
print "[INFO] Return output in CLI format = "
print i.data
except Exception as ex:
print ex
if __name__ == '__main__':
Main()
user@jet-vm:~ jet$ python mgd_api_doc_example_ssl.py -d JUNOS_DEVICE -t TIMEOUT_VAL -u USER -pw PASSWORD [INFO] Connected to gRPC Server: True [INFO] Connected to JSD and created handle to mgd services [INFO] Invoked ExecuteOpCommand API return code = 0 [INFO] Return output in CLI format = Current time: 2018-09-04 11:24:36 PDT Time Source: NTP CLOCK System booted: 2018-08-31 10:58:22 PDT (4d 00:26 ago) Protocols started: 2018-08-31 11:00:52 PDT (4d 00:23 ago) Last configured: 2018-08-31 14:21:32 PDT (3d 21:03 ago) by root 11:24AM up 4 days, 26 mins, 0 users, load averages: 1.20, 1.27, 1.10