Release K: Testing - K8S Etsi OCF Capif

Release K: Testing - K8S Etsi OCF Capif

Repository: https://labs.etsi.org/rep/ocf/capif

Wiki: https://labs.etsi.org/rep/groups/ocf/-/wikis/home

(Note: This page uses a version of OCF from Dec 2024 - and is likely out of date by now)

Openshift Helm Capif Installation

 

Unpack this helm.tar, and it will have modified scripts to install OCF on OpenShift.
Navigate to scripts folder

export KUBECONFIG="$HOME/.kube" tar xf helm.tar cd helm/scripts/ ./install_vault.sh sed -i 's/export VAULT_TOKEN=""/export VAULT_TOKEN="root"/' vault-job/vault-job.yaml ./install_capif.sh

Or MANUALLY install the main components:
Install Ingress NGINX with RBAC and ssl-passthrough

############################################################# #################### INSTALL CAPIF NGINX #################### ############################################################# helm upgrade --install ingress-nginx ingress-nginx \ --repo https://kubernetes.github.io/ingress-nginx \ --set rbac.create=true \ --set controller.service.type=NodePort \ --set controller.service.nodePorts.http=32080 \ --set controller.service.nodePorts.https=32443 \ --namespace ingress-nginx --create-namespace \ --set controller.extraArgs."enable-ssl-passthrough=true" \ --kubeconfig $KUBECONFIG

OCF uses Vault to do secret management. There are some particular settings for Openshift:
https://developer.hashicorp.com/vault/tutorials/kubernetes/kubernetes-openshift

############################################################# #################### INSTALL CAPIF VAULT #################### ############################################################# helm $KUBECONFIG upgrade --install vault hashicorp/vault -n ocf-vault \ --set server.ingress.enabled=true \ --set server.ingress.hosts[0].host="vault.testbed.develop" \ --set server.ingress.ingressClassName=nginx \ --set server.standalone.enabled=true --create-namespace \ --set "global.openshift=true" \ --set "server.dev.enabled=true" \ --set "server.image.repository=docker.io/hashicorp/vault" \ --set "injector.image.repository=docker.io/hashicorp/vault-k8s"

Log the vault pod and get the tokens, usually on OpenShift the admin token is root, but the unseal key is generated.

kubectl $KUBECONFIG logs vault-0 -n ocf-vault kubectl $KUBECONFIG exec -it vault-0 -n ocf-vault -- vault operator unseal 19zgCoVzIC4665WfRAD7gJmHTTXtqRfYrltjJ7u77AA=

Manually create PV and PVC

kubectl apply -f - <<EOF apiVersion: v1 kind: PersistentVolume metadata: name: tempo-pv spec: capacity: storage: 2Gi accessModes: - ReadWriteOnce hostPath: path: "/mnt/data/tempo" EOF kubectl apply -f - <<EOF apiVersion: v1 kind: PersistentVolumeClaim metadata: name: tempo-pvc spec: accessModes: - ReadWriteOnce resources: requests: storage: 2Gi EOF

Set Some Variables:

$CAPIF_NAMESPACE $CAPIF_NAME_VERSION_CHART $HELM_DIR $CAPIF_DOCKER_REGISTRY $CAPIF_IMAGE_TAG $VAULT_PORT $VAULT_ACCESS_TOKEN $VAULT_INTERNAL_HOSTNAME

 

Install CAPIF

helm $KUBECONFIG upgrade --install -n $CAPIF_NAMESPACE $CAPIF_NAME_VERSION_CHART $HELM_DIR/capif/ \ --set ocf-access-control-policy.image.repository=$CAPIF_DOCKER_REGISTRY/ocf-access-control-policy-api \ --set ocf-access-control-policy.image.tag=$CAPIF_IMAGE_TAG \ --set ocf-access-control-policy.image.env.capifHostname=$CAPIF_HOSTNAME \ --set ocf-access-control-policy.monitoring="true" \ --set ocf-access-control-policy.env.logLevel="DEBUG" \ --set ocf-api-invocation-logs.image.repository=$CAPIF_DOCKER_REGISTRY/ocf-logging-api-invocation-api \ --set ocf-api-invocation-logs.image.tag=$CAPIF_IMAGE_TAG \ --set ocf-api-invocation-logs.env.monitoring="true" \ --set ocf-api-invocation-logs.env.capifHostname=$CAPIF_HOSTNAME \ --set ocf-api-invocation-logs.env.vaultHostname=$VAULT_INTERNAL_HOSTNAME \ --set ocf-api-invocation-logs.env.vaultPort=$VAULT_PORT \ --set ocf-api-invocation-logs.env.vaultAccessToken=$VAULT_ACCESS_TOKEN \ --set ocf-api-invocation-logs.env.logLevel="DEBUG" \ --set ocf-api-invoker-management.image.repository=$CAPIF_DOCKER_REGISTRY/ocf-api-invoker-management-api \ --set ocf-api-invoker-management.image.tag=$CAPIF_IMAGE_TAG \ --set ocf-api-invoker-management.env.monitoring="true" \ --set ocf-api-invoker-management.env.vaultHostname=$VAULT_INTERNAL_HOSTNAME \ --set ocf-api-invoker-management.env.vaultPort=$VAULT_PORT \ --set ocf-api-invoker-management.env.vaultAccessToken=$VAULT_ACCESS_TOKEN \ --set ocf-api-invoker-management.env.logLevel="DEBUG" \ --set ocf-api-provider-management.image.repository=$CAPIF_DOCKER_REGISTRY/ocf-api-provider-management-api \ --set ocf-api-provider-management.image.tag=$CAPIF_IMAGE_TAG \ --set ocf-api-provider-management.env.monitoring="true" \ --set ocf-api-provider-management.env.vaultHostname=$VAULT_INTERNAL_HOSTNAME \ --set ocf-api-provider-management.env.logLevel="DEBUG" \ --set ocf-api-provider-management.env.vaultPort=$VAULT_PORT \ --set ocf-api-provider-management.env.vaultAccessToken=$VAULT_ACCESS_TOKEN \ --set ocf-events.image.repository=$CAPIF_DOCKER_REGISTRY/ocf-events-api \ --set ocf-events.image.tag=$CAPIF_IMAGE_TAG \ --set ocf-events.env.monitoring="true" \ --set ocf-events.env.logLevel="DEBUG" \ --set ocf-routing-info.image.repository=$CAPIF_DOCKER_REGISTRY/ocf-routing-info-api \ --set ocf-routing-info.image.tag=$CAPIF_IMAGE_TAG \ --set ocf-routing-info.env.monitoring="true" \ --set ocf-routing-info.env.logLevel="DEBUG" \ --set ocf-security.image.repository=$CAPIF_DOCKER_REGISTRY/ocf-security-api \ --set ocf-security.image.tag=$CAPIF_IMAGE_TAG \ --set ocf-security.env.monitoring="true" \ --set ocf-security.env.capifHostname=$CAPIF_HOSTNAME \ --set ocf-security.env.vaultHostname=$VAULT_INTERNAL_HOSTNAME \ --set ocf-security.env.vaultPort=$VAULT_PORT \ --set ocf-security.env.vaultAccessToken=$VAULT_ACCESS_TOKEN \ --set ocf-security.env.logLevel="DEBUG" \ --set ocf-register.image.repository=$CAPIF_DOCKER_REGISTRY/register \ --set ocf-register.image.tag=$CAPIF_IMAGE_TAG \ --set ocf-register.env.vaultHostname=$VAULT_INTERNAL_HOSTNAME \ --set ocf-register.env.vaultAccessToken=$VAULT_ACCESS_TOKEN \ --set ocf-register.env.vaultPort=$VAULT_PORT \ --set ocf-register.env.mongoHost=mongo-register \ --set ocf-register.env.mongoPort=27017 \ --set ocf-register.env.capifHostname=$CAPIF_HOSTNAME \ --set ocf-register.ingress.enabled=true \ --set ocf-register.ingress.hosts[0].host=$REGISTER_HOSTNAME \ --set ocf-register.ingress.hosts[0].paths[0].path="/" \ --set ocf-register.ingress.hosts[0].paths[0].pathType="Prefix" \ --set ocf-register.env.logLevel="DEBUG" \ --set ocf-register.extraConfigPod.hostAliases[0].hostnames[0]=$CAPIF_HOSTNAME \ --set ocf-register.extraConfigPod.hostAliases[0].ip=$K8S_IP \ --set ocf-auditing-api-logs.image.repository=$CAPIF_DOCKER_REGISTRY/ocf-auditing-api \ --set ocf-auditing-api-logs.image.tag=$CAPIF_IMAGE_TAG \ --set ocf-auditing-api-logs.env.monitoring="true" \ --set ocf-auditing-api-logs.env.logLevel="DEBUG" \ --set ocf-publish-service-api.image.repository=$CAPIF_DOCKER_REGISTRY/ocf-publish-service-api \ --set ocf-publish-service-api.image.tag=$CAPIF_IMAGE_TAG \ --set ocf-publish-service-api.env.monitoring="true" \ --set ocf-publish-service-api.env.logLevel="DEBUG" \ --set ocf-discover-service-api.image.repository=$CAPIF_DOCKER_REGISTRY/ocf-discover-service-api \ --set ocf-discover-service-api.image.tag=$CAPIF_IMAGE_TAG \ --set ocf-discover-service-api.env.monitoring="true" \ --set ocf-discover-service-api.env.logLevel="DEBUG" \ --set nginx.image.repository=$CAPIF_DOCKER_REGISTRY/nginx \ --set nginx.image.tag=$CAPIF_IMAGE_TAG \ --set nginx.env.capifHostname=$CAPIF_HOSTNAME \ --set nginx.env.vaultHostname=$VAULT_INTERNAL_HOSTNAME \ --set nginx.env.vaultPort=$VAULT_PORT \ --set nginx.env.vaultAccessToken=$VAULT_ACCESS_TOKEN \ --set nginx.ingress.enabled=true \ --set nginx.ingress.hosts[0].host=$CAPIF_HOSTNAME \ --set nginx.ingress.hosts[0].paths[0].path="/" \ --set nginx.ingress.hosts[0].paths[0].pathType="Prefix" \ --set nginx.nginx.env.capifHostname=$CAPIF_HOSTNAME \ --set ingress_ip.oneke="$INGRESS_IP" \ --set nginx.env.logLevel="debug" \ --set ocf-helper.image.repository=$CAPIF_DOCKER_REGISTRY/helper \ --set ocf-helper.image.tag=$CAPIF_IMAGE_TAG \ --set ocf-helper.env.vaultHostname=$VAULT_INTERNAL_HOSTNAME \ --set ocf-helper.env.vaultPort=$VAULT_PORT \ --set ocf-helper.env.vaultAccessToken=$VAULT_ACCESS_TOKEN \ --set ocf-helper.env.capifHostname=$CAPIF_HOSTNAME \ --set ocf-helper.env.logLevel="DEBUG" \ --wait --timeout=10m --create-namespace

Manually Retrieve a Bearer Token

  1. Login as an admin (admin:password123 or encoded “YWRtaW46cGFzc3dvcmQxMjM=“) and retrieve a TOKEN

  2. Use the TOKEN to create a normal user

  3. Get Authorization and ACCESS_TOKEN for the user and the CA_ROOT

  4. Prepare a PROVIDER with keys in body and authenticate with the ACCESS_TOKEN

  5. ONBOARD that PROVIDER

#!/bin/bash if ! command -v "jq" >/dev/null 2>&1; then echo "Error: jq is not installed. Please install jq and try again." exit 1 fi export INGRESS_IP=$(kubectl get svc -n ingress-nginx ingress-nginx-controller | grep ingress | awk '{print $3}') echo "INGRESS_IP: $INGRESS_IP" CAPIF_HOSTNAME=$INGRESS_IP # Retrieve the REGISTER_IP export REGISTER_IP=$(kubectl get svc -n ocf-capif register | grep register | awk '{print $3}') echo "REGISTER_IP: $REGISTER_IP" # Retrieve the NGINX_IP export NGINX_IP=$(kubectl get svc -n ocf-capif nginx | grep nginx | awk '{print $3}') echo "NGINX_IP: $NGINX_IP" echo "###############################################################" echo "###################ADMIN LOGIN#################################" echo "###############################################################" # Log in and extract the Bearer token LOGIN_RESPONSE=$(curl -s -k -X POST https://$REGISTER_IP:8084/login \ --header 'Authorization: Basic YWRtaW46cGFzc3dvcmQxMjM=') BEARER_TOKEN=$(echo $LOGIN_RESPONSE | jq -r .access_token) echo "Bearer Token: $BEARER_TOKEN" echo "###############################################################" echo "###################CREATE A USER###############################" echo "###############################################################" # Create a new user curl -k --location https://$REGISTER_IP:8084/createUser \ --header 'Content-Type: application/json' \ --header "Authorization: Bearer $BEARER_TOKEN" \ --data-raw '{ "username": "custom_user", "password": "user_pass", "enterprise": "EST", "country": "Ireland", "email": "est@est.tech", "purpose": "Use OpenCAPIF", "phone_number": "+123456789", "company_web": "www.est.com", "description": "UserDescription" }' echo "###############################################################" echo "###################GET AUTH####################################" echo "###############################################################" # Retrieve auth credentials for the newly created user GET_AUTH_RESPONSE=$(curl -s -k --location https://$REGISTER_IP:8084/getauth \ --header 'Authorization: Basic Y3VzdG9tX3VzZXI6dXNlcl9wYXNz') # Parse and set environment variables from the response CA_ROOT=$(echo $GET_AUTH_RESPONSE | jq -r .ca_root) ACCESS_TOKEN=$(echo $GET_AUTH_RESPONSE | jq -r .access_token) ONBOARDING_URL=$(echo $GET_AUTH_RESPONSE | jq -r .ccf_api_onboarding_url) PUBLISH_URL=$(echo $GET_AUTH_RESPONSE | jq -r .ccf_publish_url) DISCOVER_URL=$(echo $GET_AUTH_RESPONSE | jq -r .ccf_discover_url) SECURITY_URL=$(echo $GET_AUTH_RESPONSE | jq -r .ccf_security_url) ONBOARDING_URL_INVOKER=$(echo $GET_AUTH_RESPONSE | jq -r .ccf_onboarding_url) # Print extracted values echo "CA_ROOT: $CA_ROOT" echo "ACCESS_TOKEN: $ACCESS_TOKEN" echo "ONBOARDING_URL: $ONBOARDING_URL" echo "PUBLISH_URL: $PUBLISH_URL" echo "DISCOVER_URL: $DISCOVER_URL" echo "SECURITY_URL: $SECURITY_URL" echo "ONBOARDING_URL_INVOKER: $ONBOARDING_URL_INVOKER" # Save CA_ROOT to a file (manual extraction) CA_CERT_PATH="./ca_cert.pem" echo "$CA_ROOT" > $CA_CERT_PATH echo "CA Root Certificate saved to $CA_CERT_PATH" # Extract OpenSSL command for the CAPIF_HOSTNAME if [[ "$CAPIF_HOSTNAME" == *:* ]]; then OPENSSL_COMMAND="openssl s_client -connect $CAPIF_HOSTNAME | openssl x509 -text > $CA_CERT_PATH" else OPENSSL_COMMAND="openssl s_client -connect $CAPIF_HOSTNAME:443 | openssl x509 -text > $CA_CERT_PATH" fi # Execute the OpenSSL command echo "###############################################################" echo "###################OPENSSL COMMAND TO EXTRACT CAROOT###########" echo "###############################################################" echo "Executing OpenSSL command to fetch CA root certificate:" eval $OPENSSL_COMMAND echo "OpenSSL command executed. Certificate updated." echo "###############################################################" echo "###################PREPARE PROVIDER############################" echo "###############################################################" # Initial payload EMPTY_PAYLOAD='{ "apiProvFuncs": [ { "regInfo": { "apiProvPubKey": "" }, "apiProvFuncRole": "AEF", "apiProvFuncInfo": "dummy_aef" }, { "regInfo": { "apiProvPubKey": "" }, "apiProvFuncRole": "APF", "apiProvFuncInfo": "dummy_apf" }, { "regInfo": { "apiProvPubKey": "" }, "apiProvFuncRole": "AMF", "apiProvFuncInfo": "dummy_amf" } ], "apiProvDomInfo": "This is provider", "suppFeat": "fff", "failReason": "string", "regSec": "'"$ACCESS_TOKEN"'" }' # Extract the list of API Provider functions as an array API_PROV_FUNCS=$(echo "$EMPTY_PAYLOAD" | jq -c '.apiProvFuncs[]') # Initialize an updated functions array UPDATED_FUNCS_JSON="[]" # Iterate over each API Provider function for FUNC in $API_PROV_FUNCS; do ROLE=$(echo "$FUNC" | jq -r '.apiProvFuncRole') FUNC_INFO=$(echo "$FUNC" | jq -r '.apiProvFuncInfo') # Generate a private key and save it to a file PRIVATE_KEY_FILE="${ROLE}_key.pem" openssl genpkey -algorithm RSA -out "$PRIVATE_KEY_FILE" -pkeyopt rsa_keygen_bits:2048 # Generate a CSR using the private key CSR_FILE="${ROLE}_csr.pem" openssl req -new -key "$PRIVATE_KEY_FILE" -out "$CSR_FILE" -subj "/CN=${FUNC_INFO}/O=Provider/OU=${ROLE}" # Read the CSR content #CSR=$(cat "$CSR_FILE" | base64 | tr -d '\n') CSR=$(cat "$CSR_FILE") # Update the function's Public Key with the CSR content UPDATED_FUNC=$(echo "$FUNC" | jq --arg csr "$CSR" '.regInfo.apiProvPubKey = $csr') # Add the updated function to the array UPDATED_FUNCS_JSON=$(echo "$UPDATED_FUNCS_JSON" | jq --argjson func "$UPDATED_FUNC" '. + [$func]') done # Create the final payload FINAL_PAYLOAD=$(echo "$EMPTY_PAYLOAD" | jq --argjson funcs "$UPDATED_FUNCS_JSON" '.apiProvFuncs = $funcs') # Print the final payload echo "Final Payload: $FINAL_PAYLOAD" echo "###############################################################" echo "###################ONBOARD PROVIDER############################" echo "###############################################################" curl -k --location https://$NGINX_IP/api-provider-management/v1/registrations \ --header 'Content-Type: application/json' \ --header "Authorization: Bearer $ACCESS_TOKEN" \ --data "$FINAL_PAYLOAD" echo "###############################################################" echo "###################K8S PROVIDER LOGS###########################" echo "###############################################################" kubectl logs -n ocf-capif -l app.kubernetes.io/name=ocf-api-provider-management

TBD

SME only installation

kubectl create ns nonrtric helm install -n nonrtric kongstorage ./kongstorage helm repo add kong https://charts.konghq.com --force-update helm repo update helm install -n nonrtric oran-nonrtric kong/kong -f ./kongstorage/kongvalues.yaml helm install -n nonrtric r3-dev-nonrtric ./servicemanager