.. 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
Additional
Namespaces <https://docs.starlingx.io/storage/kubernetes/enable-readwriteonce-pvc-support-in-additional-namespaces.html#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
------------
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 <https://github.com/keycloak/keycloak>`__)
- export SMO_SERVICEACCOUNT=smo1
-
- cat <<EOF > 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=<oran-o2-client-id>
+ OAUTH2_CLIENT_SECRET=<oran-o2-client-secret>
- cat <<EOF > 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=<oran-o2-client-id>
+ OAUTH2_CLIENT_SECRET=<oran-o2-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
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
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}
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]
[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
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.
redis: ${O2SERVICE_IMAGE_REG}/docker.io/library/redis:alpine
pullPolicy: IfNotPresent
logginglevel: "DEBUG"
+ useHostCert: true
applicationconfig: ${APPLICATION_CONFIG}
servercrt: ${SERVER_CERT}
.. 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
=========================
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=<INF_OAM_IP>
- export SMO_TOKEN_DATA=<TOKEN of O2 Service>
+
+ export OAUTH2_TOKEN_ENDPOINT=http://<3rd-party OAuth Server Address>:8080/realms/master/protocol/openid-connect/token
+ export OAUTH2_CLIENT_ID=<oran-o2-client-id>
+ export OAUTH2_CLIENT_SECRET=<oran-o2-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=<access_token>
+
+ ls
+ client-cert.pem client-key.pem my-root-ca-cert.pem
- Discover INF platform inventory
.. 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
.. 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
.. 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
.. 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
.. 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
.. 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
export SMO_SUBSCRIBE_CALLBACK=<The Callback URL for SMO Subscribe resource>
export SMO_CONSUMER_SUBSCRIPTION_ID=<The Subscription ID of the SMO Consumer>
- 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}'",
export SMO_SUBSCRIBE_CALLBACK=<The Callback URL for SMO Subscribe alarm>
export SMO_CONSUMER_SUBSCRIPTION_ID=<The Subscription ID of the SMO Consumer>
- 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}'",
.. 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
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