From cac8f4269bec339deb0ea15c628b35fd9bcf3257 Mon Sep 17 00:00:00 2001 From: "Zhang Rong(Jon)" Date: Mon, 5 Aug 2024 16:13:03 +0800 Subject: [PATCH] Update the installation doc This commit update the installation doc for the J-Release Change-Id: Ic39a380c73ce98bb10ffcaa3ceb6bbd1474c21e9 Signed-off-by: Zhang Rong(Jon) --- docs/installation-guide.rst | 131 ++++++++++++++++++++---------------- docs/user-guide.rst | 122 ++++++++++++++++++++++----------- 2 files changed, 154 insertions(+), 99 deletions(-) diff --git a/docs/installation-guide.rst b/docs/installation-guide.rst index 6856ea0a..59b63d9f 100644 --- a/docs/installation-guide.rst +++ b/docs/installation-guide.rst @@ -1,6 +1,6 @@ .. This work is licensed under a Creative Commons Attribution 4.0 International License. .. SPDX-License-Identifier: CC-BY-4.0 -.. Copyright (C) 2021-2022 Wind River Systems, Inc. +.. Copyright (C) 2021-2024 Wind River Systems, Inc. Installation Guide @@ -58,6 +58,11 @@ Configuration and Management: `Enable ReadWriteOnce PVC Support in Additional Namespaces `__. +Set up an OAuth 2.0 server and configure it to use either JWT with +Shared Key or Token Introspection. Since the J-release, OAuth2 has +been mandatory when starting the O2 application. + + 2. Procedure ------------ @@ -95,73 +100,56 @@ You can install O-RAN O2 application on INF from the command line. 6. Prepare the override ``yaml`` file. - 1. Create a service account for SMO application. + a. Create a client on the OAuth Server. - Create a ServiceAccount which can be used to provide SMO - application with minimal access permission credentials. + Create a client on OAuth Server to provide O2 application with + access permission credentials. - :: + Here is a reference 3rd-party OAuth Server (`Keycloak `__) - export SMO_SERVICEACCOUNT=smo1 - - cat < smo-serviceaccount.yaml - apiVersion: rbac.authorization.k8s.io/v1 - kind: Role - metadata: - namespace: default - name: pod-reader - rules: - - apiGroups: [""] # "" indicates the core API group - resources: ["pods"] - verbs: ["get", "watch", "list"] - --- - apiVersion: v1 - kind: ServiceAccount - metadata: - name: ${SMO_SERVICEACCOUNT} - namespace: default - --- - apiVersion: rbac.authorization.k8s.io/v1 - kind: RoleBinding - metadata: - name: read-pods - namespace: default - roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: pod-reader - subjects: - - kind: ServiceAccount - name: ${SMO_SERVICEACCOUNT} - namespace: default - EOF + :: - kubectl apply -f smo-serviceaccount.yaml + docker run \ + --name keycloak \ + -p 8080:8080 \ + -e KEYCLOAK_ADMIN=admin \ + -e KEYCLOAK_ADMIN_PASSWORD=admin \ + -e KC_HOSTNAME=localhost \ + quay.io/keycloak/keycloak:latest \ + start-dev - 2. Create a secret for service account and obtain an access token. + docker exec -it keycloak /bin/bash + bash-5.1$ cd /opt/keycloak/bin + bash-5.1$ ./kcadm.sh config credentials --server http://localhost:8080 --realm master --user admin + bash-5.1$ ./kcadm.sh update realms/master -s sslRequired=NONE - Create a secret with the type service-account-token and pass the - ServiceAccount in the annotation section as shown below: + When you create a client, you will get a client ID and client secret. :: - export SMO_SECRET=smo1-secret + OAUTH2_TOKEN_ENDPOINT=http://<3rd-party OAuth Server Address>:8080/realms/master/protocol/openid-connect/token + OAUTH2_CLIENT_ID= + OAUTH2_CLIENT_SECRET= - cat < smo-secret.yaml - apiVersion: v1 - kind: Secret - metadata: - name: ${SMO_SECRET} - annotations: - kubernetes.io/service-account.name: ${SMO_SERVICEACCOUNT} - type: kubernetes.io/service-account-token - EOF + b. Prepare the OAuth2 variables for authenticate information. + + When using JWT with Shared Key, the following attributes need to be + configured. Here's an example for preparation: - kubectl apply -f smo-secret.yaml + :: + + OAUTH2_ALGORITHM=RS256 + OAUTH2_PUB_KEY=<3rd-party OAuth Server Public Key> - export SMO_TOKEN_DATA=$(kubectl get secrets $SMO_SECRET -o jsonpath='{.data.token}' | base64 -d -w 0) + For Token Introspection, here are examples of the required preparation: - 3. Create certificates for the O2 service. + :: + + OAUTH2_INTROSPECTION_ENDPOINT=http://<3rd-party OAuth Server Address>:8080/realms/master/protocol/openid-connect/token/introspect + OAUTH2_CLIENT_ID= + OAUTH2_CLIENT_SECRET= + + c. Create certificates for the O2 service. Obtain an intermediate or Root CA-signed certificate and key from a trusted intermediate or Root Certificate Authority (CA). Refer @@ -190,7 +178,7 @@ You can install O-RAN O2 application on INF from the command line. shared with the SMO application for the O2 server certificate verification. - 4. Prepare the O2 service application configuration file. + d. Prepare the O2 service application configuration file. As per the Cloudification and Orchestration use case defined in O-RAN Working Group 6, the following information should be @@ -212,7 +200,6 @@ You can install O-RAN O2 application on INF from the command line. ocloud_global_id = ${OCLOUD_GLOBAL_ID} smo_register_url = ${SMO_REGISTER_URL} - smo_token_data = ${SMO_TOKEN_DATA} [OCLOUD] OS_AUTH_URL = ${OS_AUTH_URL} @@ -220,6 +207,17 @@ You can install O-RAN O2 application on INF from the command line. OS_PASSWORD = ${OS_PASSWORD} API_HOST_EXTERNAL_FLOATING = ${API_HOST_EXTERNAL_FLOATING} + [OAUTH2] + oauth2_verify_type = jwt + oauth2_public_key = ${OAUTH2_PUB_KEY} + oauth2_algorithm = ${OAUTH2_ALGORITHM} + + # required if oauth2_verify_type = introspection + #oauth2_verify_type = introspection + #oauth2_introspection_endpoint = ${OAUTH2_INTROSPECTION_ENDPOINT} + #oauth2_client_id = ${OAUTH2_CLIENT_ID} + #oauth2_client_secret = ${OAUTH2_CLIENT_SECRET} + [API] [WATCHER] @@ -227,7 +225,7 @@ You can install O-RAN O2 application on INF from the command line. [PUBSUB] EOF - 5. Retrieve the CA certificate from your SMO vendor. + e. Retrieve the CA certificate from your SMO vendor. If the SMO application provides service via HTTPS, and the server certificate is self-signed, the CA certficate should be retrieved @@ -236,7 +234,21 @@ You can install O-RAN O2 application on INF from the command line. This procedure assumes that the name of the certificate is ``smo-ca.pem`` - 6. Populate the override yaml file. + f. Prepare client certificate for mTLS (Mutual TLS). + + When you request the O2 application from SMO, it needs the + certificate for mTLS. + We assume you have the CA certificate and CA key of the SMO + client, you can follow the guide to generate the client + certficate. + + :: + + openssl genrsa -out client-key.pem 2048 + openssl req -new -key client-key.pem -out client.csr + openssl x509 -req -in client.csr -CA smo-ca.pem -CAkey smo-ca-key.pem -CAcreateserial -out client-cert.pem -days 365 + + j. Populate the override yaml file. Refer to the previous step for the required override values. @@ -288,6 +300,7 @@ You can install O-RAN O2 application on INF from the command line. redis: ${O2SERVICE_IMAGE_REG}/docker.io/library/redis:alpine pullPolicy: IfNotPresent logginglevel: "DEBUG" + useHostCert: true applicationconfig: ${APPLICATION_CONFIG} servercrt: ${SERVER_CERT} diff --git a/docs/user-guide.rst b/docs/user-guide.rst index 5b173c9a..46fe99ee 100644 --- a/docs/user-guide.rst +++ b/docs/user-guide.rst @@ -1,6 +1,6 @@ .. This work is licensed under a Creative Commons Attribution 4.0 International License. .. SPDX-License-Identifier: CC-BY-4.0 -.. Copyright (C) 2021-2022 Wind River Systems, Inc. +.. Copyright (C) 2021-2024 Wind River Systems, Inc. INF O2 Service User Guide ========================= @@ -9,12 +9,35 @@ This guide will introduce the process that make INF O2 interface work with SMO. - Assume you have an O2 service with INF platform environment, and you - have the token of the O2 service. + have the OAuth Server configured with the O2 service. .. code:: bash export OAM_IP= - export SMO_TOKEN_DATA= + + export OAUTH2_TOKEN_ENDPOINT=http://<3rd-party OAuth Server Address>:8080/realms/master/protocol/openid-connect/token + export OAUTH2_CLIENT_ID= + export OAUTH2_CLIENT_SECRET= + + Get berar token from the OAuth Server for request O2 application API. + + .. code:: shell + + curl -k -X POST ${OAUTH2_TOKEN_ENDPOINT} \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "grant_type=client_credentials" \ + -d "client_id=${OAUTH2_CLIENT_ID}" \ + -d "client_secret=${OAUTH2_CLIENT_SECRET}" + + Set "access_token" value from the above step to the bash environment. + And copy the client certificate into the bash folder that you are working on. + + .. code:: bash + + export BEARER_TOKEN= + + ls + client-cert.pem client-key.pem my-root-ca-cert.pem - Discover INF platform inventory @@ -28,9 +51,12 @@ with SMO. .. code:: shell - curl -k -X 'GET' \ - "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/" \ - -H 'accept: application/json' -H "Authorization: Bearer ${SMO_TOKEN_DATA}" + curl -X 'GET' \ + --cacert my-root-ca-cert.pem \ + --cert client-cert.pem --key client-key.pem \ + -H "Authorization: Bearer ${BEARER_TOKEN}" \ + -H 'accept: application/json' + "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/" - Resource pool @@ -44,12 +70,15 @@ with SMO. .. code:: shell - curl -k -X 'GET' \ - "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/resourcePools" \ - -H 'accept: application/json' -H "Authorization: Bearer ${SMO_TOKEN_DATA}" + curl -X 'GET' \ + --cacert my-root-ca-cert.pem \ + --cert client-cert.pem --key client-key.pem \ + -H "Authorization: Bearer ${BEARER_TOKEN}" \ + -H 'accept: application/json' + "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/resourcePools" # export the first resource pool id - export resourcePoolId=`curl -k -X 'GET' "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/resourcePools" -H 'accept: application/json' -H "Authorization: Bearer $SMO_TOKEN_DATA" 2>/dev/null | jq .[0].resourcePoolId | xargs echo` + export resourcePoolId=`curl -k -X 'GET' --cert client-cert.pem --key client-key.pem "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/resourcePools" -H 'accept: application/json' -H "Authorization: Bearer ${BEARER_TOKEN}" 2>/dev/null | jq .[0].resourcePoolId | xargs echo` echo ${resourcePoolId} # check the exported resource pool id @@ -62,9 +91,12 @@ with SMO. .. code:: shell - curl -k -X 'GET' \ - "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/resourceTypes" \ - -H 'accept: application/json' -H "Authorization: Bearer ${SMO_TOKEN_DATA}" + curl -X 'GET' \ + --cacert my-root-ca-cert.pem \ + --cert client-cert.pem --key client-key.pem \ + -H "Authorization: Bearer ${BEARER_TOKEN}" \ + -H 'accept: application/json' + "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/resourceTypes" - Resource @@ -73,9 +105,12 @@ with SMO. .. code:: shell - curl -k -X 'GET' \ - "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/resourcePools/${resourcePoolId}/resources" \ - -H 'accept: application/json' -H "Authorization: Bearer ${SMO_TOKEN_DATA}" + curl -X 'GET' \ + --cacert my-root-ca-cert.pem \ + --cert client-cert.pem --key client-key.pem \ + -H "Authorization: Bearer ${BEARER_TOKEN}" \ + -H 'accept: application/json' + "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/resourcePools/${resourcePoolId}/resources" To get the detail of one resource, need to export one specific resource id that wants to check @@ -83,7 +118,7 @@ with SMO. .. code:: shell # export the first resource id in the resource pool - export resourceId=`curl -k -X 'GET' "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/resourcePools/${resourcePoolId}/resources" -H 'accept: application/json' -H "Authorization: Bearer ${SMO_TOKEN_DATA}" 2>/dev/null | jq .[0].resourceId | xargs echo` + export resourceId=`curl -k -X 'GET' --cert client-cert.pem --key client-key.pem "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/resourcePools/${resourcePoolId}/resources" -H 'accept: application/json' -H "Authorization: Bearer ${BEARER_TOKEN}" 2>/dev/null | jq .[0].resourceId | xargs echo` echo ${resourceId} # check the exported resource id @@ -99,9 +134,12 @@ with SMO. .. code:: shell - curl -k -X 'GET' \ - "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/deploymentManagers" \ - -H 'accept: application/json' -H "Authorization: Bearer ${SMO_TOKEN_DATA}" + curl -X 'GET' \ + --cacert my-root-ca-cert.pem \ + --cert client-cert.pem --key client-key.pem \ + -H "Authorization: Bearer ${BEARER_TOKEN}" \ + -H 'accept: application/json' + "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/deploymentManagers" - Provisioning INF platform with SMO endpoint configuration @@ -139,11 +177,13 @@ with SMO. export SMO_SUBSCRIBE_CALLBACK= export SMO_CONSUMER_SUBSCRIPTION_ID= - curl -k -X 'POST' \ - "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/subscriptions" \ + curl -X 'POST' \ + --cacert my-root-ca-cert.pem \ + --cert client-cert.pem --key client-key.pem \ + -H "Authorization: Bearer ${BEARER_TOKEN}" \ -H 'accept: application/json' \ -H 'Content-Type: application/json' \ - -H "Authorization: Bearer ${SMO_TOKEN_DATA}" \ + "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/subscriptions" \ -d '{ "callback": "'${SMO_SUBSCRIBE_CALLBACK}'", "consumerSubscriptionId": "'${SMO_CONSUMER_SUBSCRIPTION_ID}'", @@ -168,11 +208,13 @@ with SMO. export SMO_SUBSCRIBE_CALLBACK= export SMO_CONSUMER_SUBSCRIPTION_ID= - curl -k -X 'POST' \ - "https://${OAM_IP}:30205/o2ims-infrastructureMonitoring/v1/alarmSubscriptions" \ + curl -X 'POST' \ + --cacert my-root-ca-cert.pem \ + --cert client-cert.pem --key client-key.pem \ + -H "Authorization: Bearer ${BEARER_TOKEN}" \ -H 'accept: application/json' \ -H 'Content-Type: application/json' \ - -H "Authorization: Bearer ${SMO_TOKEN_DATA}" \ + "https://${OAM_IP}:30205/o2ims-infrastructureMonitoring/v1/alarmSubscriptions" \ -d '{ "callback": "'${SMO_SUBSCRIBE_CALLBACK}'", "consumerSubscriptionId": "'${SMO_CONSUMER_SUBSCRIPTION_ID}'", @@ -216,16 +258,16 @@ with SMO. .. code:: bash # Get all DMS ID, and print them with command - dmsIDs=$(curl -k -s -X 'GET' \ + dmsIDs=$(curl -k -s -X 'GET' --cert client-cert.pem --key client-key.pem \ "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/deploymentManagers" \ - -H 'accept: application/json' -H "Authorization: Bearer ${SMO_TOKEN_DATA}" \ + -H 'accept: application/json' -H "Authorization: Bearer ${BEARER_TOKEN}" \ | jq --raw-output '.[]["deploymentManagerId"]') for i in $dmsIDs;do echo ${i};done; # Choose one DMS and set it to bash environment, here I set the first one - export dmsID=$(curl -k -s -X 'GET' \ + export dmsID=$(curl -k -s -X 'GET' --cert client-cert.pem --key client-key.pem \ "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/deploymentManagers" \ - -H 'accept: application/json' -H "Authorization: Bearer ${SMO_TOKEN_DATA}" \ + -H 'accept: application/json' -H "Authorization: Bearer ${BEARER_TOKEN}" \ | jq --raw-output '.[0]["deploymentManagerId"]') echo ${dmsID} # check the exported DMS Id @@ -241,26 +283,26 @@ with SMO. CLUSTER_NAME="o2dmsk8s1" # set the cluster name - K8S_SERVER=$(curl -k -s -X 'GET' \ + K8S_SERVER=$(curl -k -s -X 'GET' --cert client-cert.pem --key client-key.pem \ "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/deploymentManagers/${dmsID}?profile=native_k8sapi" \ - -H 'accept: application/json' -H "Authorization: Bearer ${SMO_TOKEN_DATA}" \ + -H 'accept: application/json' -H "Authorization: Bearer ${BEARER_TOKEN}" \ | jq --raw-output '.["extensions"]["profileData"]["cluster_api_endpoint"]') - K8S_CA_DATA=$(curl -k -s -X 'GET' \ + K8S_CA_DATA=$(curl -k -s -X 'GET' --cert client-cert.pem --key client-key.pem \ "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/deploymentManagers/${dmsID}?profile=native_k8sapi" \ - -H 'accept: application/json' -H "Authorization: Bearer ${SMO_TOKEN_DATA}" \ + -H 'accept: application/json' -H "Authorization: Bearer ${BEARER_TOKEN}" \ | jq --raw-output '.["extensions"]["profileData"]["cluster_ca_cert"]') - K8S_USER_NAME=$(curl -k -s -X 'GET' \ + K8S_USER_NAME=$(curl -k -s -X 'GET' --cert client-cert.pem --key client-key.pem \ "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/deploymentManagers/${dmsID}?profile=native_k8sapi" \ - -H 'accept: application/json' -H "Authorization: Bearer ${SMO_TOKEN_DATA}" \ + -H 'accept: application/json' -H "Authorization: Bearer ${BEARER_TOKEN}" \ | jq --raw-output '.["extensions"]["profileData"]["admin_user"]') - K8S_USER_CLIENT_CERT_DATA=$(curl -k -s -X 'GET' \ + K8S_USER_CLIENT_CERT_DATA=$(curl -k -s -X 'GET' --cert client-cert.pem --key client-key.pem \ "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/deploymentManagers/${dmsID}?profile=native_k8sapi" \ - -H 'accept: application/json' -H "Authorization: Bearer ${SMO_TOKEN_DATA}" \ + -H 'accept: application/json' -H "Authorization: Bearer ${BEARER_TOKEN}" \ | jq --raw-output '.["extensions"]["profileData"]["admin_client_cert"]') - K8S_USER_CLIENT_KEY_DATA=$(curl -k -s -X 'GET' \ + K8S_USER_CLIENT_KEY_DATA=$(curl -k -s -X 'GET' --cert client-cert.pem --key client-key.pem \ "https://${OAM_IP}:30205/o2ims-infrastructureInventory/v1/deploymentManagers/${dmsID}?profile=native_k8sapi" \ - -H 'accept: application/json' -H "Authorization: Bearer ${SMO_TOKEN_DATA}" \ + -H 'accept: application/json' -H "Authorization: Bearer ${BEARER_TOKEN}" \ | jq --raw-output '.["extensions"]["profileData"]["admin_client_key"]') # If you do not want to set up the CA data, you can execute following command without the secure checking