...
...
WORK IN PROGRESS & For Discussion
Background
Some A1-Policy operations require the creator (and owner) of an A1-Policy to be known.
In the pre-R1 A1-Policy API it was required to provide a 'service_id' to link A1-Policies to the client or service that 'owns' them.
...
O-RAN Alliance R1-GAP, R1-AP and Security specifications describe how R1 requests authentication headers should include a bearer-token, which includes the 'ClientID' of the R1-Service invoker. There is an assumption (TBC) that this is the 'rAppID' for R1 invocations by rApps. When creating A1-Polices this 'ClientID' corresponds to the 'owner' and 'creator' of those A1-Policies. ('owner' == 'creator').
When a 'ClientID' is present in a the Auth header of a request, as part of a cryptographically signed/verified JWT token, the 'ClientID' will be the actual service invoker. JWT tokens generally should not be shared, and it should not be possible for one client to masquerade as a different client.
...
In the R1-aligned enhanced ('v3') API introduced for A1-PMS (link currently broken: https://docs.onap.org/projects/onap-ccsdk-oran/en/latest/offeredapis/v3/pms-api-v3.html) when creating A1-Policies the Create-Policy operation retained the 'service_id' parameter as an optional non-spec parameter, with default value as empty string "". In this way we can use either/both 'ClientID' in the header's JWT token and/or the 'service_id' parameter in the create-policy operation.
...
This page discusses how to deal with combinations of 'ClientID' (as "creator" and/or "ownerown
er") in the Header, and 'service_id' ( as "owner") in the request body.
...
Info | ||
---|---|---|
| ||
The discussion below does not consider whether a Create-Policy request (or any other request) should be allowed or not.
Therefore, depending on how the service is deployed and configured, some of the scenarios below may be restricted, and the operation may fail with an 'Unauthorized' error. |
Original pre-spec v2 API:
- Request 'service_id' ❌ absent (null)
Token or its 'ClientID' ❌ absent (null), or
Token's 'ClientID' ✔️ present but blank/empty (""), or
Token's 'ClientID' ✅present
Panel border true Leave parameter 'service_id' as null and continue.
Operation will fail because 'service_id' is mandatory.
- Request 'service_id' ✔️ present but blank/empty ("")
Token or its 'ClientID' ❌ absent (null)
Panel border true Leave parameter 'service_id' as empty ("") and continue.
This policy has no 'owner', so cannot be retrieved using a service-id filter in Get-Instances, and cannot be later inherited by a newly-registered service ("" is not a valid service name when registering a 'Service').
Policy cannot be auto-deleted/garbage-collected, since this functionality is tried to the life-cycle of registered Services only.
Token's 'ClientID' ✔️ present but blank/empty ("")
Panel border true Leave parameter 'service_id' as empty ("") and continue.
This policy has no 'owner', so cannot be retrieved using a service-id filter in Get-Instances, and cannot be later inherited by a newly-registered service ("" is not a valid service name when registering a 'Service').
Policy cannot be auto-deleted/garbage-collected, since this functionality is tried to the life-cycle of registered Services only.
Token's 'ClientID' ✅present
Panel border true Set parameter 'service_id' = 'ClientID' and continue.
This policy's 'owner' is set be its 'creator'.
See options 3.d and 4.d below to understand behavior when 'service_id' == 'ClientID'
- Request 'service_id' ✅present but not NOT a registered 'Service'
Token or its 'ClientID' ❌ absent (null)
Panel border true Leave parameter 'service_id' as is (not-registered Service) and continue.
This policy has an unregistered 'owner', but can be retrieved using that 'service-id' filter in Get-Instances
Policy cannot be auto-deleted/garbage-collected, since this functionality is tried to the life-cycle of registered Services only.
Policy can be later inherited by a newly-registered Service with same 'service_id'.Token's 'ClientID' ✔️ present but blank/empty ("")
Panel border true Leave parameter 'service_id' as is (not-registered Service) and continue.
This policy has an unregistered 'owner', but can be retrieved using that 'service-id' filter in Get-Instances
Policy cannot be auto-deleted/garbage-collected, since this functionality is tried to the life-cycle of registered Services only.
Policy can be later inherited by a newly-registered Service with same 'service_id'.Token's 'ClientID' ✅present but != 'service_id'
Panel border true Leave parameter 'service_id' as is (not-registered Service) and continue.
Policy has an different 'owner' than 'creator'This policy has an unregistered 'owner', but can be retrieved using that 'service-id' filter in Get-Instances
Policy cannot be auto-deleted/garbage-collected, since this functionality is tried to the life-cycle of registered Services only.
Policy can be later inherited by a newly-registered Service with same 'service_id' (see option 4.c below).Warning title To Do! Need to extend functionality to save the additional 'creator' information.
Token's 'ClientID' ✅present and == 'service_id'
Panel border true Leave parameter 'service_id' as is (not-registered Service) and continue.
This policy has an unregistered 'owner', but can be retrieved using that 'service-id' filter in Get-Instances
Policy cannot be auto-deleted/garbage-collected, since this functionality is tried to the life-cycle of registered Services only.
Policy can be later inherited by a newly-registered Service with same 'service_id' (see option 4.d below).
- Request 'service_id' ✅present but is a registered 'Service'
Token or its 'ClientID' ❌ absent (null)
Panel border true Leave parameter 'service_id' as is (pre-registered Service) and continue.
This policy has a registered 'owner', and can be retrieved using that 'service-id' filter in Get-Instances
Policy may be auto-deleted/garbage-collected, depending on the life-cycle and activity registered Service.
Policy will be deleted if Service is deleted or times-out according to however the Service is configured.Token's 'ClientID' ✔️ present but blank/empty ("")
Panel border true Leave parameter 'service_id' as is (pre-registered Service) and continue.
This policy has a registered 'owner', and can be retrieved using that 'service-id' filter in Get-Instances
Policy may be auto-deleted/garbage-collected, depending on the life-cycle and activity registered Service.
Policy will be deleted if Service is deleted or times-out according to however the Service is configured.Token's 'ClientID' ✅present but != 'service_id'
Panel border true Leave parameter 'service_id' as is (pre-registered Service) and continue.
Policy has an different 'owner' than 'creator'This policy has a registered 'owner', and can be retrieved using that 'service-id' filter in Get-Instances
Policy may be auto-deleted/garbage-collected, depending on the life-cycle and activity registered Service.
Policy will be deleted if Service is deleted or times-out according to however the Service is configured.Warning title To Do! Need to extend functionality to save the additional 'creator' information.
Token's 'ClientID' ✅present and == 'service_id'
Panel border true Leave parameter 'service_id' as is (pre-registered Service) and continue.
Policy has same 'owner' than 'creator'This policy has a registered 'owner' - same as 'creator', and can be retrieved using that 'service-id' filter in Get-Instances
Policy may be auto-deleted/garbage-collected, depending on the life-cycle and activity registered Service.
Policy will be deleted if Service is deleted or times-out according to however the Service is configured.
New R1-spec v3 API:
All The main difference between 'v2' API and new 'v3' API is that 'service_id' is now optional instead of mandatory.
So all scenarios are the same as above EXCEPT scenario #1
Request 'service_id' ❌ absent (null)
Panel border true Set parameter 'service_id' as empty ("") and continue.
See option set #2 above
Demo with tokens and
...
ClientID extraction for using it as
...
service_id
To generate a JWT token and parse a value from it demonstration.
Below, I'll outline the steps to achieve this, including generating a JWT, sending it in a request header, and then parsing a value (like `client_id`) from the JWT payload.
...
Code Block | ||||
---|---|---|---|---|
| ||||
2024-07-30 13:32:55 2024-07-30 12:32:55.413 [INFO ] [http-nio-8081-exec-3] o.o.c.o.a.c.v.PolicyController - Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJleGFtcGxlX2lzc3VlciIsInN1YiI6IjEyMzQ1Njc4OTAiLCJhdWQiOiJteWNsaWVudCIsImV4cCI6MzAwMDAwMDAwMCwiY2xpZW50X2lkIjoibXljbGllbnQiLCJyb2xlIjoidXNlciJ9.O5QN_SWN4J1mWKyXk_-PCvOA6GF3ypv1rSdg2uTb_Ls 2024-07-30 13:32:55 2024-07-30 12:32:55.415 [INFO ] [http-nio-8081-exec-3] o.o.c.o.a.c.v.PolicyController - ServiceId: myclient |
...
Summary:
ClientID coming from the JWT, ServiceID coming in from the body request.
v3 | ClientID NULL | ClientID EMPTY | ClientID VALID |
---|---|---|---|
ServiceID NULL | S EMPTY | C EMPTY | C |
ServiceID EMPTY | S | C EMPTY | C |
ServiceID REGISTERED | S | S | S (*) |
ServiceID UNREGISTERED | S | S | S (*) |
(*) Owner (serviceID) != Creator (clientID)