오프 디바이스 JET 애플리케이션 개발
개요
JET를 사용하여 오프 디바이스에서 실행되는 애플리케이션을 개발할 수 있습니다. 이를 통해 네트워크의 모든 디바이스에서 JET의 이점을 활용할 수 있습니다. 개발 용이성을 위해 선택한 언어로 장치 끄기 애플리케이션을 작성할 수 있습니다. 장치 끄기 애플리케이션을 개발하려면 다음을 수행합니다.
IDL 파일을 다운로드하여 컴파일합니다.
선택한 언어를 사용하여 애플리케이션을 개발합니다.
애플리케이션을 패키지화합니다.
외부 서버에 애플리케이션 패키지를 구축하거나 JET VM에서 직접 애플리케이션을 실행합니다.
그림 1 은 오프 디바이스 애플리케이션 개발 워크플로우를 보여줍니다.

애플리케이션 구축 준비
외부 서버 또는 JET VM에서 직접 애플리케이션을 실행하십시오. 외부 서버에 애플리케이션을 구축하기 전에 Junos OS와 JET 상호 작용을 구성해야 합니다.
Junos OS와 JET 상호 작용 구성
오프 디바이스 애플리케이션을 실행하려면 Junos OS 또는 Junos OS Evolved에서 request-response
구성을 활성화해야 합니다. 요청 응답 서비스를 사용할 때 클라이언트 애플리케이션은 요청을 발행하고 Junos 서버의 응답을 동기적으로 대기합니다. 이 섹션을 사용하여 SSL(Secure Sockets Layer) 모드에서 실행되는 요청 응답 서비스에 대한 JET 서비스 프로세스(jsd)를 구성합니다. 이를 통해 보안을 강화하고 SSL 기반 API 연결을 지원합니다.
현재 JET는 인증서 교환을 위해 TLS(Transport Layer Security) 버전 1.2를 지원하고 여러 암호화 알고리즘을 지원하지만 상호 인증을 지원하지는 않습니다. 즉, 클라이언트는 서버를 인증할 수 있지만 서버는 SSL/TLS 인증서를 사용하여 클라이언트를 인증할 수 없습니다. 클라이언트 인증의 경우 인증 서비스 API의 LoginCheck() 절차를 사용합니다.
-
인증서 이름을 로컬로 추가 및 구성하여 jsd가 SSL을 사용할 수 있도록 합니다. 인증서는 RSA 인증서여야 합니다. ECDSA 및 DSA SSL 인증서는 지원되지 않습니다.
이 방법은 xnm-ssl과 같은 Junos OS의 다른 SSL 기반 서비스와 동일합니다. 인증서 생성 중에 사용자가 지정한 인증서 이름 입력을 계속 추적합니다. 다음 섹션에서 Python 애플리케이션 예제의 옵션에 사용할
HOST_OVERRIDE
것입니다. 이 예에서는 인증서 이름이 입니다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 인증서 .펨 파일을 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을 사용합니다. 예를 들어, 모든 포트의 gRPC 단말 장치와 기본 TCP 포트 51051에서 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 Release 21.1R1 및 Junos OS Evolved Release 22.3R1부터 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 Release 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