-#\r
-# ========================LICENSE_START=================================\r
-# Copyright (C) 2024: Deutsche Telekom\r
-#\r
-# Licensed under the Apache License, Version 2.0 (the "License");\r
-# you may not use this file except in compliance with the License.\r
-# You may obtain a copy of the License at\r
-#\r
-# http://www.apache.org/licenses/LICENSE-2.0\r
-#\r
-# Unless required by applicable law or agreed to in writing, software\r
-# distributed under the License is distributed on an "AS IS" BASIS,\r
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-# See the License for the specific language governing permissions and\r
-# limitations under the License.\r
-# SPDX-License-Identifier: Apache-2.0\r
-# ========================LICENSE_END===================================\r
-#\r
-openapi: 3.0.3\r
-info:\r
- title: "Policy OPA PDP Documentation"\r
- description: Policy OPA PDP Service\r
- version: 1.0.2\r
- x-component: Policy Framework\r
- x-planned-retirement-date: tbd\r
- contact:\r
- name: Deena Mukundan\r
- email: dm00536893@techmahindra.com\r
-servers:\r
-- url: http://policy-opa-pdp:8282/policy/pdpo/v1\r
-- url: https://policy-opa-pdp:8282/policy/pdpo/v1\r
-tags:\r
-- name: Decision\r
-- name: Statistics\r
-- name: HealthCheck\r
-paths:\r
- /decision:\r
- post:\r
- tags:\r
- - Decision\r
- summary: Fetch the decision using specified decision parameters\r
- description: Returns the policy decision from Policy OPA PDP\r
- operationId: decision\r
- parameters:\r
- - name: X-ONAP-RequestID\r
- in: header\r
- description: RequestID for http transaction\r
- schema:\r
- type: string\r
- format: uuid\r
- requestBody:\r
- content:\r
- application/json:\r
- schema:\r
- $ref: '#/components/schemas/OPADecisionRequest'\r
- application/yaml:\r
- schema:\r
- $ref: '#/components/schemas/OPADecisionRequest'\r
- required: false\r
- responses:\r
- 200:\r
- description: successful operation\r
- headers:\r
- X-LatestVersion:\r
- description: Used only to communicate an API's latest version\r
- schema:\r
- type: string\r
- X-PatchVersion:\r
- description: Used only to communicate a PATCH version in a response\r
- for troubleshooting purposes only, and will not be provided by the\r
- client on request\r
- schema:\r
- type: string\r
- X-MinorVersion:\r
- description: Used to request or communicate a MINOR version back from\r
- the client to the server, and from the server back to the client\r
- schema:\r
- type: string\r
- X-ONAP-RequestID:\r
- description: Used to track REST transactions for logging purpose\r
- schema:\r
- type: string\r
- format: uuid\r
- content:\r
- application/json:\r
- schema:\r
- $ref: '#/components/schemas/OPADecisionResponse'\r
- application/yaml:\r
- schema:\r
- $ref: '#/components/schemas/OPADecisionResponse'\r
- 400:\r
- description: Bad Request\r
- content:\r
- application/json:\r
- schema:\r
- $ref: '#/components/schemas/ErrorResponse'\r
- application/yaml:\r
- schema:\r
- $ref: '#/components/schemas/ErrorResponse'\r
- 401:\r
- description: Authentication Error\r
- content: {}\r
- 403:\r
- description: Authorization Error\r
- content: {}\r
- 500:\r
- description: Internal Server Error\r
- content: {}\r
- security:\r
- - basicAuth: []\r
- x-interface info:\r
- last-mod-release: Paris\r
- pdpo-version: 1.0.0\r
- x-codegen-request-body-name: body\r
- /healthcheck:\r
- get:\r
- tags:\r
- - HealthCheck\r
- summary: Perform a system healthcheck\r
- description: Provides healthy status of the Policy OPA PDP component\r
- operationId: healthcheck\r
- parameters:\r
- - name: X-ONAP-RequestID\r
- in: header\r
- description: RequestID for http transaction\r
- schema:\r
- type: string\r
- format: uuid\r
- responses:\r
- 200:\r
- description: successful operation\r
- headers:\r
- X-LatestVersion:\r
- description: Used only to communicate an API's latest version\r
- schema:\r
- type: string\r
- X-PatchVersion:\r
- description: Used only to communicate a PATCH version in a response\r
- for troubleshooting purposes only, and will not be provided by the\r
- client on request\r
- schema:\r
- type: string\r
- X-MinorVersion:\r
- description: Used to request or communicate a MINOR version back from\r
- the client to the server, and from the server back to the client\r
- schema:\r
- type: string\r
- X-ONAP-RequestID:\r
- description: Used to track REST transactions for logging purpose\r
- schema:\r
- type: string\r
- format: uuid\r
- content:\r
- application/json:\r
- schema:\r
- $ref: '#/components/schemas/HealthCheckReport'\r
- application/yaml:\r
- schema:\r
- $ref: '#/components/schemas/HealthCheckReport'\r
- 401:\r
- description: Authentication Error\r
- content: {}\r
- 403:\r
- description: Authorization Error\r
- content: {}\r
- 500:\r
- description: Internal Server Error\r
- content: {}\r
- security:\r
- - basicAuth: []\r
- x-interface info:\r
- last-mod-release: Paris\r
- pdpo-version: 1.0.0\r
- /statistics:\r
- get:\r
- tags:\r
- - Statistics\r
- summary: Fetch current statistics\r
- description: Provides current statistics of the Policy OPA PDP component \r
- operationId: statistics\r
- parameters:\r
- - name: X-ONAP-RequestID\r
- in: header\r
- description: RequestID for http transaction\r
- schema:\r
- type: string\r
- format: uuid\r
- responses:\r
- 200:\r
- description: successful operation\r
- headers:\r
- X-LatestVersion:\r
- description: Used only to communicate an API's latest version\r
- schema:\r
- type: string\r
- X-PatchVersion:\r
- description: Used only to communicate a PATCH version in a response\r
- for troubleshooting purposes only, and will not be provided by the\r
- client on request\r
- schema:\r
- type: string\r
- X-MinorVersion:\r
- description: Used to request or communicate a MINOR version back from\r
- the client to the server, and from the server back to the client\r
- schema:\r
- type: string\r
- X-ONAP-RequestID:\r
- description: Used to track REST transactions for logging purpose\r
- schema:\r
- type: string\r
- format: uuid\r
- content:\r
- application/json:\r
- schema:\r
- $ref: '#/components/schemas/StatisticsReport'\r
- application/yaml:\r
- schema:\r
- $ref: '#/components/schemas/StatisticsReport'\r
- 401:\r
- description: Authentication Error\r
- content: {}\r
- 403:\r
- description: Authorization Error\r
- content: {}\r
- 500:\r
- description: Internal Server Error\r
- content: {}\r
- security:\r
- - basicAuth: []\r
- x-interface info:\r
- last-mod-release: Paris\r
- pdpo-version: 1.0.0\r
-components:\r
- schemas:\r
- ErrorResponse:\r
- type: object\r
- properties:\r
- responseCode:\r
- type: string\r
- enum:\r
- - BAD_REQUEST\r
- - UNAUTHORIZED\r
- - METHOD_NOT_ALLOWED\r
- - NOT_ACCEPTABLE\r
- - REQUEST_TIMEOUT\r
- - CONFLICT\r
- - GONE\r
- - LENGTH_REQUIRED\r
- - PRECONDITION_FAILED\r
- - REQUEST_ENTITY_TOO_LARGE\r
- - REQUEST_URI_TOO_LONG\r
- - UNSUPPORTED_MEDIA_TYPE\r
- - REQUESTED_RANGE_NOT_SATISFIABLE\r
- - EXPECTATION_FAILED\r
- - PRECONDITION_REQUIRED\r
- - TOO_MANY_REQUESTS\r
- - REQUEST_HEADER_FIELDS_TOO_LARGE\r
- - INTERNAL_SERVER_ERROR\r
- - NOT_IMPLEMENTED\r
- - BAD_GATEWAY\r
- - SERVICE_UNAVAILABLE\r
- - GATEWAY_TIMEOUT\r
- - HTTP_VERSION_NOT_SUPPORTED\r
- - NETWORK_AUTHENTICATION_REQUIRED\r
- errorMessage:\r
- type: string\r
- policyName:\r
- type: string\r
- errorDetails:\r
- type: array\r
- items:\r
- type: string\r
- OPADecisionRequest:\r
- type: object\r
- properties:\r
- onapName:\r
- type: string\r
- onapComponent:\r
- type: string\r
- onapInstance:\r
- type: string\r
- currentDateTime:\r
- type: string\r
- format: date-time\r
- currentDate:\r
- type: string\r
- format: date\r
- currentTime:\r
- type: string\r
- format: date-time\r
- timeZone:\r
- type: string\r
- description: "Timezone in IANA format (e.g., 'America/NewYork', 'Europe/Paris', 'UTC')"\r
- timeOffset:\r
- type: string\r
- pattern: '^[+-]?\d{2}:\d{2}$'\r
- description: "Time offset in hours and minutes, e.g., '+02:00' or '-05:00'"\r
- policyName:\r
- type: string\r
- policyFilter:\r
- type: array\r
- items:\r
- type: string\r
- input:\r
- type: object\r
- additionalProperties: true\r
- example:\r
- user: alice\r
- action: read\r
- object: id123\r
- type: dog\r
- HealthCheckReport:\r
- type: object\r
- properties:\r
- name:\r
- type: string\r
- url:\r
- type: string\r
- healthy:\r
- type: boolean\r
- code:\r
- type: integer\r
- format: int32\r
- message:\r
- type: string\r
- OPADecisionResponse:\r
- type: object\r
- properties:\r
- statusMessage:\r
- type: string\r
- decision:\r
- type: string\r
- enum:\r
- - PERMIT\r
- - DENY\r
- - INDETERMINATE\r
- - NOTAPPLICABLE\r
- policyName:\r
- type: string\r
- output:\r
- type: object\r
- additionalProperties: true\r
- StatisticsReport:\r
- type: object\r
- properties:\r
- code:\r
- type: integer\r
- format: int32\r
- totalPolicyTypesCount:\r
- type: integer\r
- format: int64\r
- totalPoliciesCount:\r
- type: integer\r
- format: int64\r
- totalErrorCount:\r
- type: integer\r
- format: int64\r
- permitDecisionsCount:\r
- type: integer\r
- format: int64\r
- denyDecisionsCount:\r
- type: integer\r
- format: int64\r
- deploySuccessCount:\r
- type: integer\r
- format: int64\r
- deployFailureCount:\r
- type: integer\r
- format: int64\r
- undeploySuccessCount:\r
- type: integer\r
- format: int64\r
- undeployFailureCount:\r
- type: integer\r
- format: int64\r
- indeterminantDecisionsCount:\r
- type: integer\r
- format: int64\r
- querySuccessCount:\r
- type: integer\r
- format: int64\r
- queryFailureCount:\r
- type: integer\r
- format: int64\r
- securitySchemes:\r
- basicAuth:\r
- type: http\r
- description: ""\r
- scheme: basic\r
+#
+# ========================LICENSE_START=================================
+# Copyright (C) 2024-2025: Deutsche Telekom
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# SPDX-License-Identifier: Apache-2.0
+# ========================LICENSE_END===================================
+#
+openapi: 3.0.3
+info:
+ title: "Policy OPA PDP Documentation"
+ description: Policy OPA PDP Service
+ version: 1.0.2
+ x-component: Policy Framework
+ x-planned-retirement-date: tbd
+ contact:
+ name: Deena Mukundan
+ email: dm00536893@techmahindra.com
+servers:
+- url: http://policy-opa-pdp:8282/policy/pdpo/v1
+- url: https://policy-opa-pdp:8282/policy/pdpo/v1
+tags:
+- name: Decision
+- name: Statistics
+- name: HealthCheck
+
+paths:
+ /decision:
+ post:
+ tags:
+ - Decision
+ summary: Fetch the decision using specified decision parameters
+ description: Returns the policy decision from Policy OPA PDP
+ operationId: decision
+ parameters:
+ - name: X-ONAP-RequestID
+ in: header
+ description: RequestID for http transaction
+ schema:
+ type: string
+ format: uuid
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/OPADecisionRequest'
+ application/yaml:
+ schema:
+ $ref: '#/components/schemas/OPADecisionRequest'
+ required: true
+ responses:
+ 200:
+ description: successful operation
+ headers:
+ X-LatestVersion:
+ description: Used only to communicate an API's latest version
+ schema:
+ type: string
+ X-PatchVersion:
+ description: Used only to communicate a PATCH version in a response
+ for troubleshooting purposes only, and will not be provided by the
+ client on request
+ schema:
+ type: string
+ X-MinorVersion:
+ description: Used to request or communicate a MINOR version back from
+ the client to the server, and from the server back to the client
+ schema:
+ type: string
+ X-ONAP-RequestID:
+ description: Used to track REST transactions for logging purpose
+ schema:
+ type: string
+ format: uuid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/OPADecisionResponse'
+ application/yaml:
+ schema:
+ $ref: '#/components/schemas/OPADecisionResponse'
+
+ 400:
+ description: Bad Request
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErrorResponse'
+ application/yaml:
+ schema:
+ $ref: '#/components/schemas/ErrorResponse'
+ 401:
+ description: Authentication Error
+ content: {}
+ 403:
+ description: Authorization Error
+ content: {}
+ 500:
+ description: Internal Server Error
+ content: {}
+ security:
+ - basicAuth: []
+ x-interface info:
+ last-mod-release: Paris
+ pdpo-version: 1.0.0
+ x-codegen-request-body-name: body
+ /healthcheck:
+ get:
+ tags:
+ - HealthCheck
+ summary: Perform a system healthcheck
+ description: Provides healthy status of the Policy OPA PDP component
+ operationId: healthcheck
+ parameters:
+ - name: X-ONAP-RequestID
+ in: header
+ description: RequestID for http transaction
+ schema:
+ type: string
+ format: uuid
+ responses:
+ 200:
+ description: successful operation
+ headers:
+ X-LatestVersion:
+ description: Used only to communicate an API's latest version
+ schema:
+ type: string
+ X-PatchVersion:
+ description: Used only to communicate a PATCH version in a response
+ for troubleshooting purposes only, and will not be provided by the
+ client on request
+ schema:
+ type: string
+ X-MinorVersion:
+ description: Used to request or communicate a MINOR version back from
+ the client to the server, and from the server back to the client
+ schema:
+ type: string
+ X-ONAP-RequestID:
+ description: Used to track REST transactions for logging purpose
+ schema:
+ type: string
+ format: uuid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/HealthCheckReport'
+ application/yaml:
+ schema:
+ $ref: '#/components/schemas/HealthCheckReport'
+ 401:
+ description: Authentication Error
+ content: {}
+ 403:
+ description: Authorization Error
+ content: {}
+ 500:
+ description: Internal Server Error
+ content: {}
+ security:
+ - basicAuth: []
+ x-interface info:
+ last-mod-release: Paris
+ pdpo-version: 1.0.0
+ /statistics:
+ get:
+ tags:
+ - Statistics
+ summary: Fetch current statistics
+ description: Provides current statistics of the Policy OPA PDP component
+ operationId: statistics
+ parameters:
+ - name: X-ONAP-RequestID
+ in: header
+ description: RequestID for http transaction
+ schema:
+ type: string
+ format: uuid
+ responses:
+ 200:
+ description: successful operation
+ headers:
+ X-LatestVersion:
+ description: Used only to communicate an API's latest version
+ schema:
+ type: string
+ X-PatchVersion:
+ description: Used only to communicate a PATCH version in a response
+ for troubleshooting purposes only, and will not be provided by the
+ client on request
+ schema:
+ type: string
+ X-MinorVersion:
+ description: Used to request or communicate a MINOR version back from
+ the client to the server, and from the server back to the client
+ schema:
+ type: string
+ X-ONAP-RequestID:
+ description: Used to track REST transactions for logging purpose
+ schema:
+ type: string
+ format: uuid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/StatisticsReport'
+ application/yaml:
+ schema:
+ $ref: '#/components/schemas/StatisticsReport'
+ 401:
+ description: Authentication Error
+ content: {}
+ 403:
+ description: Authorization Error
+ content: {}
+ 500:
+ description: Internal Server Error
+ content: {}
+ security:
+ - basicAuth: []
+ x-interface info:
+ last-mod-release: Paris
+ pdpo-version: 1.0.0
+
+components:
+ schemas:
+ ErrorResponse:
+ type: object
+ properties:
+ responseCode:
+ type: string
+ enum:
+ - internal_error
+ - bad_request
+ - evaluation_error
+ - unauthorized
+ - invalid_parameter
+ - invalid_operation
+ - resource_not_found
+ - resource_conflict
+ - undefined_document
+ - opa_undefined_error
+ errorMessage:
+ type: string
+ policyName:
+ type: string
+ OPADecisionRequest:
+ type: object
+ properties:
+ onapName:
+ type: string
+ onapComponent:
+ type: string
+ onapInstance:
+ type: string
+ currentDateTime:
+ type: string
+ format: date-time
+ currentDate:
+ type: string
+ format: date
+ currentTime:
+ type: string
+ format: time
+ timeZone:
+ type: string
+ description: "Timezone in IANA format (e.g., 'America/NewYork', 'Europe/Paris', 'UTC')"
+ timeOffset:
+ type: string
+ pattern: '^[+-]?\d{2}:\d{2}$'
+ description: "Time offset in hours and minutes, e.g., '+02:00' or '-05:00'"
+ policyName:
+ type: string
+ policyFilter:
+ type: array
+ items:
+ type: string
+ input:
+ type: object
+ additionalProperties: true
+ example:
+ user: alice
+ action: read
+ object: id123
+ type: dog
+ required:
+ - policyName
+ - policyFilter
+ - input
+
+ HealthCheckReport:
+ type: object
+ properties:
+ name:
+ type: string
+ url:
+ type: string
+ healthy:
+ type: boolean
+ code:
+ type: integer
+ format: int32
+ message:
+ type: string
+ OPADecisionResponse:
+ type: object
+ properties:
+ policyName:
+ type: string
+ statusMessage:
+ type: string
+ output:
+ type: object
+ additionalProperties: true
+ required:
+ - policyName
+ - output
+
+ StatisticsReport:
+ type: object
+ properties:
+ code:
+ type: integer
+ format: int32
+ totalPolicyTypesCount:
+ type: integer
+ format: int64
+ totalPoliciesCount:
+ type: integer
+ format: int64
+ totalErrorCount:
+ type: integer
+ format: int64
+ deploySuccessCount:
+ type: integer
+ format: int64
+ deployFailureCount:
+ type: integer
+ format: int64
+ undeploySuccessCount:
+ type: integer
+ format: int64
+ undeployFailureCount:
+ type: integer
+ format: int64
+ decisionSuccessCount:
+ type: integer
+ format: int64
+ decisionFailureCount:
+ type: integer
+ format: int64
+
+ securitySchemes:
+ basicAuth:
+ type: http
+ description: ""
+ scheme: basic
+
defer producer.Close()
sender := &publisher.RealPdpStatusSender{Producer: producer}
+ // start pdp message handler in a seperate routine
+ handleMessagesFunc(ctx, kc, sender)
+
+ time.Sleep(10 * time.Second)
+
// pdp registration
isRegistered := registerPDPFunc(sender)
if !isRegistered {
return
}
- // start pdp message handler in a seperate routine
- handleMessagesFunc(ctx, kc, sender)
-
+ time.Sleep(10 * time.Second)
+ log.Debugf("After registration successful delay")
// Handle OS Interrupts and Graceful Shutdown
interruptChannel := make(chan os.Signal, 1)
signal.Notify(interruptChannel, os.Interrupt, syscall.SIGTERM, syscall.SIGINT, syscall.SIGHUP)
module policy-opa-pdp
-go 1.23.4
+go 1.23.3
require (
+ bou.ke/monkey v1.0.2
github.com/confluentinc/confluent-kafka-go v1.9.2
- github.com/go-playground/validator/v10 v10.23.0
+ github.com/go-playground/validator/v10 v10.24.0
github.com/google/uuid v1.6.0
github.com/oapi-codegen/runtime v1.1.1
github.com/open-policy-agent/opa v0.70.0
)
require (
- bou.ke/monkey v1.0.2 // indirect
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect
github.com/OneOfOne/xxhash v1.2.8 // indirect
github.com/agnivade/levenshtein v1.2.0 // indirect
+ github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bytecodealliance/wasmtime-go/v3 v3.0.2 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/containerd/platforms v0.2.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
- github.com/deepmap/oapi-codegen v1.16.3 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
- github.com/gabriel-vasile/mimetype v1.4.3 // indirect
+ github.com/gabriel-vasile/mimetype v1.4.8 // indirect
github.com/go-ini/ini v1.67.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
go.opentelemetry.io/otel/metric v1.28.0 // indirect
go.opentelemetry.io/otel/sdk v1.28.0 // indirect
go.opentelemetry.io/otel/trace v1.28.0 // indirect
- golang.org/x/crypto v0.28.0 // indirect
- golang.org/x/net v0.30.0 // indirect
- golang.org/x/sync v0.8.0 // indirect
- golang.org/x/sys v0.26.0 // indirect
- golang.org/x/text v0.19.0 // indirect
+ golang.org/x/crypto v0.32.0 // indirect
+ golang.org/x/net v0.34.0 // indirect
+ golang.org/x/sync v0.10.0 // indirect
+ golang.org/x/sys v0.29.0 // indirect
+ golang.org/x/text v0.21.0 // indirect
golang.org/x/time v0.7.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect
google.golang.org/grpc v1.67.1 // indirect
github.com/Microsoft/hcsshim v0.11.7/go.mod h1:MV8xMfmECjl5HdO7U/3/hFVnkmSBjAjmA09d4bExKcU=
github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8=
github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
+github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk=
github.com/actgardner/gogen-avro/v10 v10.1.0/go.mod h1:o+ybmVjEa27AAr35FRqU98DJu1fXES56uXniYFv4yDA=
github.com/actgardner/gogen-avro/v10 v10.2.1/go.mod h1:QUhjeHPchheYmMDni/Nx7VB0RsT/ee8YIgGY/xpEQgQ=
github.com/actgardner/gogen-avro/v9 v9.1.0/go.mod h1:nyTj6wPqDJoxM3qdnjcLv+EnMDSDFqE0qDpva2QRmKc=
github.com/agnivade/levenshtein v1.2.0 h1:U9L4IOT0Y3i0TIlUIDJ7rVUziKi/zPbrJGaFrtYH3SY=
github.com/agnivade/levenshtein v1.2.0/go.mod h1:QVVI16kDrtSuwcpd0p1+xMC6Z/VfhtCyDIjcwga4/DU=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
+github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ=
+github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk=
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q=
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
+github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
github.com/bytecodealliance/wasmtime-go/v3 v3.0.2 h1:3uZCA/BLTIu+DqCfguByNMJa2HVHpXvjfy0Dy7g6fuA=
github.com/bytecodealliance/wasmtime-go/v3 v3.0.2/go.mod h1:RnUjnIXxEJcL6BgCvNyzCCRzZcxCgsZCi+RNlvYor5Q=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/deepmap/oapi-codegen v1.16.3 h1:GT9G86SbQtT1r8ZB+4Cybi9VGdu1P5ieNvNdEoCSbrA=
-github.com/deepmap/oapi-codegen v1.16.3/go.mod h1:JD6ErqeX0nYnhdciLc61Konj3NBASREMlkHOgHn8WAM=
github.com/dgraph-io/badger/v3 v3.2103.5 h1:ylPa6qzbjYRQMU6jokoj4wzcaweHylt//CH0AKt0akg=
github.com/dgraph-io/badger/v3 v3.2103.5/go.mod h1:4MPiseMeDQ3FNCYwRbbcBOGJLf5jsE0PPFzRiKjtcdw=
github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8=
github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
-github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
-github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
+github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
+github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
-github.com/go-playground/validator/v10 v10.23.0 h1:/PwmTwZhS0dPkav3cdK9kV1FsAmrL8sThn8IHr/sO+o=
-github.com/go-playground/validator/v10 v10.23.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
+github.com/go-playground/validator/v10 v10.24.0 h1:KHQckvo8G6hlWnrPX4NJJ+aBfWNAE/HH+qdL2cBpCmg=
+github.com/go-playground/validator/v10 v10.24.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus=
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/jhump/protoreflect v1.11.0/go.mod h1:U7aMIjN0NWq9swDP7xDdoMfRHb35uiuTd3Z9nFXJf5E=
github.com/jhump/protoreflect v1.12.0/go.mod h1:JytZfP5d0r8pVNLZvai7U/MCuTWITgrI4tTg7puQFKI=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE=
github.com/juju/qthttptest v0.1.1/go.mod h1:aTlAv8TYaflIiTDIQYzxnl1QdPjAg8Q8qJMErpKy6A4=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/santhosh-tekuri/jsonschema/v5 v5.0.0/go.mod h1:FKdcjfQW6rpZSnxxUvEA5H/cDPdvJ/SZJQLWWXWGrZ0=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
+github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
-golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
+golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
+golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
-golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
-golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
+golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
+golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
-golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
+golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
-golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
+golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
-golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
+golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
+golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telekom
+// Copyright (C) 2024-2025: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
import (
"context"
"encoding/json"
+ "github.com/google/uuid"
+ openapi_types "github.com/oapi-codegen/runtime/types"
+ "github.com/open-policy-agent/opa/sdk"
"net/http"
"policy-opa-pdp/consts"
"policy-opa-pdp/pkg/log"
"policy-opa-pdp/pkg/pdpstate"
"policy-opa-pdp/pkg/utils"
"strings"
- "fmt"
- "github.com/google/uuid"
- openapi_types "github.com/oapi-codegen/runtime/types"
- "github.com/open-policy-agent/opa/sdk"
)
// creates a response code map to ErrorResponseResponseCode
var httpToResponseCode = map[int]oapicodegen.ErrorResponseResponseCode{
- 400: oapicodegen.BADREQUEST,
- 401: oapicodegen.UNAUTHORIZED,
- 500: oapicodegen.INTERNALSERVERERROR,
+ 400: oapicodegen.BadRequest,
+ 401: oapicodegen.Unauthorized,
+ 500: oapicodegen.InternalError,
}
// Gets responsecode from map
if code, exists := httpToResponseCode[httpStatus]; exists {
return code
}
- return oapicodegen.INTERNALSERVERERROR
+ return oapicodegen.InternalError
}
// writes a Successful JSON response to the HTTP response writer
}
}
+// creates a success decision response
+func createSuccessDecisionResponse(policyName string, output map[string]interface{}) *oapicodegen.OPADecisionResponse {
+ return &oapicodegen.OPADecisionResponse{
+ PolicyName: policyName,
+ Output: output,
+ }
+}
+
// creates a decision response based on the provided parameters
-func createSuccessDecisionResponse(statusMessage, decision, policyName string, output map[string]interface{}) *oapicodegen.OPADecisionResponse {
+func createSuccessDecisionResponseWithStatus(policyName string, output map[string]interface{}, statusMessage string) *oapicodegen.OPADecisionResponse {
return &oapicodegen.OPADecisionResponse{
- StatusMessage: &statusMessage,
- Decision: (*oapicodegen.OPADecisionResponseDecision)(&decision),
- PolicyName: &policyName,
- Output: &output,
+ PolicyName: policyName,
+ Output: output,
+ StatusMessage: &statusMessage,
}
}
// creates a decision response based on the provided parameters
-func createDecisionExceptionResponse(statusCode int, errorMessage string, errorDetails []string, policyName string) *oapicodegen.ErrorResponse {
+func createDecisionExceptionResponse(statusCode int, errorMessage string, policyName string) *oapicodegen.ErrorResponse {
responseCode := GetErrorResponseResponseCode(statusCode)
return &oapicodegen.ErrorResponse{
ResponseCode: (*oapicodegen.ErrorResponseResponseCode)(&responseCode),
ErrorMessage: &errorMessage,
- ErrorDetails: &errorDetails,
PolicyName: &policyName,
}
}
-// handles HTTP requests for decisions using OPA.
+// handles HTTP requests for decisions using OPA.
func OpaDecision(res http.ResponseWriter, req *http.Request) {
log.Debugf("PDP received a decision request.")
+ var errorDtls string
+ var httpStatus int
+ var policyId = ""
+
+ requestId, _ := processRequestHeaders(req, res)
+ log.Debugf("Headers processed for requestId: %s", requestId)
+
+ if !isSystemActive() {
+ errorDtls = "System Is In PASSIVE State, error handling request."
+ httpStatus = http.StatusInternalServerError
+ } else if req.Method != http.MethodPost {
+ errorDtls = req.Method + " MethodNotAllowed"
+ httpStatus = http.StatusMethodNotAllowed
+ } else {
+ decisionReq, err := parseRequestBody(req)
+ if err != nil {
+ errorDtls = err.Error()
+ httpStatus = http.StatusBadRequest
+ } else if (decisionReq.PolicyName == "") {
+ errorDtls = "Policy Name is nil which is invalid."
+ httpStatus = http.StatusBadRequest
+ } else if (decisionReq.PolicyFilter == nil || len(decisionReq.PolicyFilter) == 0) {
+ errorDtls = "Policy Filter is nil."
+ httpStatus = http.StatusBadRequest
+ } else {
+ opa, err := getOpaInstance()
+ if err != nil {
+ errorDtls = "Failed to get OPA instance."
+ httpStatus = http.StatusInternalServerError
+ policyId = decisionReq.PolicyName
+ } else {
+ processOpaDecision(res, opa, decisionReq)
+ return
+ }
+ }
+ }
+ //If it comes here then there will be error
+ sendErrorResponse(errorDtls, res, httpStatus, policyId)
+}
+//This function processes the request headers
+func processRequestHeaders(req *http.Request, res http.ResponseWriter) (string, *oapicodegen.DecisionParams) {
requestId := req.Header.Get("X-ONAP-RequestID")
var parsedUUID *uuid.UUID
var decisionParams *oapicodegen.DecisionParams
- var err error
if requestId != "" && utils.IsValidUUID(requestId) {
tempUUID, err := uuid.Parse(requestId)
- if err != nil {
- log.Warnf("Error Parsing the requestID: %v", err)
- } else {
+ if err == nil {
parsedUUID = &tempUUID
decisionParams = &oapicodegen.DecisionParams{
XONAPRequestID: (*openapi_types.UUID)(parsedUUID),
}
res.Header().Set("X-ONAP-RequestID", decisionParams.XONAPRequestID.String())
+ } else {
+ log.Warnf("Error Parsing the requestID: %v", err)
}
} else {
requestId = "Unknown"
res.Header().Set("X-PatchVersion", consts.PatchVersion)
res.Header().Set("X-MinorVersion", consts.MinorVersion)
- log.Debugf("Headers..")
- for key, value := range res.Header() {
- log.Debugf("%s: %s", key, value)
- }
- // Check if the system is in an active state
-
- if pdpstate.GetCurrentState() != model.Active {
- msg := " System Is In PASSIVE State so Unable To Handle Decision wait until it becomes ACTIVE"
- errorMsg := " System Is In PASSIVE State so error Handling the request"
- decisionExc := createDecisionExceptionResponse(http.StatusInternalServerError, msg, []string{errorMsg}, "")
- metrics.IncrementTotalErrorCount()
- writeErrorJSONResponse(res, http.StatusInternalServerError, msg, *decisionExc)
- return
- }
- ctx := context.Background()
+ return requestId, decisionParams
+}
- // Check if the request method is POST
- if req.Method != http.MethodPost {
- msg := " MethodNotAllowed"
- decisionExc := createDecisionExceptionResponse(http.StatusMethodNotAllowed, "Only POST Method Allowed",
- []string{req.Method + msg}, "")
- metrics.IncrementTotalErrorCount()
- writeErrorJSONResponse(res, http.StatusMethodNotAllowed, req.Method+msg, *decisionExc)
- return
- }
+// This returns whether the system is active or not
+func isSystemActive() bool {
+ return pdpstate.GetCurrentState() == model.Active
+}
+//This method parses the body and checks whether it is properly formatted JSON or not
+func parseRequestBody(req *http.Request) (*oapicodegen.OPADecisionRequest, error) {
var decisionReq oapicodegen.OPADecisionRequest
-
- // Decode the request body into a DecisionRequest struct
if err := json.NewDecoder(req.Body).Decode(&decisionReq); err != nil {
- decisionExc := createDecisionExceptionResponse(http.StatusBadRequest, "Error decoding the request",
- []string{err.Error()}, "")
- metrics.IncrementTotalErrorCount()
- writeErrorJSONResponse(res, http.StatusBadRequest, err.Error(), *decisionExc)
- return
+ return nil, err
}
+ return &decisionReq, nil
+}
- // Check if the policy is provided in the request
- if decisionReq.PolicyName == nil || *decisionReq.PolicyName == "" {
- msg := "Policy used to make decision is nil"
- decisionExc := createDecisionExceptionResponse(http.StatusBadRequest, "policy details not provided",
- []string{msg}, "")
- metrics.IncrementTotalErrorCount()
- writeErrorJSONResponse(res, http.StatusBadRequest, msg, *decisionExc)
- return
- }
+//This function sends the error response
+func sendErrorResponse(msg string, res http.ResponseWriter, httpStatus int, policyName string) {
+ log.Warnf("%s", msg)
+ decisionExc := createDecisionExceptionResponse(httpStatus, msg, policyName)
+ metrics.IncrementTotalErrorCount()
+ writeErrorJSONResponse(res, httpStatus, msg, *decisionExc)
+}
- // Get the OPA singleton instance
- opa, err := opasdk.GetOPASingletonInstance()
- if err != nil {
- msg := "Failed to get OPA instance"
- log.Warnf("Failed to get OPA instance: %s", err)
- decisionExc := createDecisionExceptionResponse(http.StatusInternalServerError, "OPA instance creation error", []string{msg},
- *decisionReq.PolicyName)
- metrics.IncrementTotalErrorCount()
- writeErrorJSONResponse(res, http.StatusInternalServerError, msg, *decisionExc)
- return
- }
+//This function returns the opasdk instance
+func getOpaInstance() (*sdk.OPA, error) {
+ return opasdk.GetOPASingletonInstance()
+}
+//This function processes the OPA decision
+func processOpaDecision(res http.ResponseWriter, opa *sdk.OPA, decisionReq *oapicodegen.OPADecisionRequest) {
+ ctx := context.Background()
log.Debugf("SDK making a decision")
- options := sdk.DecisionOptions{Path: *decisionReq.PolicyName, Input: decisionReq.Input}
-
- decision, decision_err := opa.Decision(ctx, options)
-
- jsonOutput, err := json.MarshalIndent(decision, "", " ")
- if err != nil {
- log.Warnf("Error serializing decision output: %v\n", err)
- return
- }
- log.Debugf("RAW opa Decision output:\n%s\n", string(jsonOutput))
-
- // Check for errors in the OPA decision
- if decision_err != nil {
- if strings.Contains(decision_err.Error(), "opa_undefined_error") {
- decisionRes := createSuccessDecisionResponse(decision_err.Error(), string(oapicodegen.INDETERMINATE),
- *decisionReq.PolicyName, nil)
- writeOpaJSONResponse(res, http.StatusOK, *decisionRes)
- metrics.IncrementIndeterminantDecisionsCount()
- return
- } else {
- decisionExc := createDecisionExceptionResponse(http.StatusBadRequest, "Error from OPA while making decision",
- []string{decision_err.Error()}, *decisionReq.PolicyName)
- metrics.IncrementTotalErrorCount()
- writeErrorJSONResponse(res, http.StatusBadRequest, decision_err.Error(), *decisionExc)
+ var decisionRes *oapicodegen.OPADecisionResponse
+ //OPA is seding success with a warning message if "input" parameter is missing, so we need to send success response
+ if (decisionReq.Input == nil) {
+ statusMessage := "{\"warning\":{\"code\":\"api_usage_warning\",\"message\":\"'input' key missing from the request\"}}"
+ decisionRes = createSuccessDecisionResponseWithStatus(decisionReq.PolicyName, nil, statusMessage)
+ } else {
+ options := sdk.DecisionOptions{Path: decisionReq.PolicyName, Input: decisionReq.Input}
+ decisionResult, decisionErr := opa.Decision(ctx, options)
+ jsonOutput, err := json.MarshalIndent(decisionResult, "", " ")
+ if err != nil {
+ log.Warnf("Error serializing decision output: %v\n", err)
return
}
- }
-
- var policyFilter []string
- if decisionReq.PolicyFilter != nil {
- policyFilter = *decisionReq.PolicyFilter
- }
-
- // Decision Result Processing
- outputMap := make(map[string]interface{})
- // Check if the decision result is a bool or a map
- switch result := decision.Result.(type) {
- case bool:
- // If the result is a boolean (true/false)
- if result {
- // If "allow" is true, process filters if they exist
- if len(policyFilter) > 0 {
- // If filters are present, we apply them
- decisionRes := createSuccessDecisionResponse("OPA Allowed", string(oapicodegen.PERMIT), *decisionReq.PolicyName, nil)
- metrics.IncrementPermitDecisionsCount()
- writeOpaJSONResponse(res, http.StatusOK, *decisionRes)
- return
- }
-
- // No filters provided, just allow the decision
- decisionRes := createSuccessDecisionResponse("OPA Allowed", string(oapicodegen.PERMIT), *decisionReq.PolicyName, nil)
- metrics.IncrementPermitDecisionsCount()
- writeOpaJSONResponse(res, http.StatusOK, *decisionRes)
+ log.Debugf("RAW opa Decision output:\n%s\n", string(jsonOutput))
+
+ if decisionErr != nil {
+ handleOpaDecisionError(res, decisionErr, decisionReq.PolicyName)
return
}
-
- // If "allow" is false
- decisionRes := createSuccessDecisionResponse("OPA Denied", string(oapicodegen.DENY), *decisionReq.PolicyName, nil)
- metrics.IncrementDenyDecisionsCount()
- writeOpaJSONResponse(res, http.StatusOK, *decisionRes)
- return
-
- case map[string]interface{}:
- if len(policyFilter) > 0 {
- // Apply the policy filter if present
- filteredResult := applyPolicyFilter(result, policyFilter)
- if filteredResultMap, ok := filteredResult.(map[string]interface{}); ok && len(filteredResultMap) > 0 {
- outputMap = filteredResultMap
- } else {
- decisionRes := createSuccessDecisionResponse(
- "No Decision: Result is Empty after applying filter",
- string(oapicodegen.NOTAPPLICABLE),
- *decisionReq.PolicyName, nil)
- metrics.IncrementQueryFailureCount()
- writeOpaJSONResponse(res, http.StatusOK, *decisionRes)
- return
- }
- } else {
- // Process result without filters
- var statusMessage string
- boolValueFound := false
- for key, value := range result {
- if len(statusMessage) == 0 {
- statusMessage = fmt.Sprintf("%s: %v", key, value)
- } else {
- statusMessage = fmt.Sprintf("%s ,%s: %v", statusMessage, key, value)
- }
- if boolVal, ok := value.(bool); ok {
- boolValueFound = boolVal
- }
- }
- // Return decision based on boolean value
- if boolValueFound {
- decisionRes := createSuccessDecisionResponse(statusMessage, string(oapicodegen.PERMIT),
- *decisionReq.PolicyName, nil)
- metrics.IncrementPermitDecisionsCount()
- writeOpaJSONResponse(res, http.StatusOK, *decisionRes)
- return
- } else {
- decisionRes := createSuccessDecisionResponse(statusMessage, string(oapicodegen.DENY),
- *decisionReq.PolicyName, nil)
- metrics.IncrementDenyDecisionsCount()
- writeOpaJSONResponse(res, http.StatusOK, *decisionRes)
- return
- }
-
+
+ var policyFilter []string
+ if decisionReq.PolicyFilter != nil {
+ policyFilter = decisionReq.PolicyFilter
}
-
- // If only non-boolean values were collected
- if len(outputMap) > 0 {
- decisionRes := createSuccessDecisionResponse(
- "Decision Not Applicable, Output Only",
- string(oapicodegen.NOTAPPLICABLE),
- *decisionReq.PolicyName, outputMap)
- metrics.IncrementQuerySuccessCount()
- writeOpaJSONResponse(res, http.StatusOK, *decisionRes)
+ result, _ := decisionResult.Result.(map[string]interface{})
+ outputMap := processPolicyFilter(result, policyFilter)
+ if outputMap == nil {
+ decisionRes = createSuccessDecisionResponseWithStatus(decisionReq.PolicyName, outputMap, "Policy Filter is not matching.")
} else {
- decisionRes := createSuccessDecisionResponse(
- "No Decision: Result is Empty",
- string(oapicodegen.NOTAPPLICABLE),
- *decisionReq.PolicyName, nil)
- metrics.IncrementQueryFailureCount()
- writeOpaJSONResponse(res, http.StatusOK, *decisionRes)
+ decisionRes = createSuccessDecisionResponse(decisionReq.PolicyName, outputMap)
}
- return
+ }
+ metrics.IncrementDecisionSuccessCount()
+ writeOpaJSONResponse(res, http.StatusOK, *decisionRes)
+}
- default:
- // Handle unexpected types in decision.Result
- decisionRes := createSuccessDecisionResponse("Invalid decision result format", string(oapicodegen.INDETERMINATE), *decisionReq.PolicyName, nil)
- metrics.IncrementIndeterminantDecisionsCount()
- writeOpaJSONResponse(res, http.StatusOK, *decisionRes)
- return
+//This function validates the errors during decision process
+func handleOpaDecisionError(res http.ResponseWriter, err error, policyName string) {
+ //As per the opa documentation in https://www.openpolicyagent.org/docs/latest/rest-api/#get-a-document-with-input
+ //when the path refers to an undefined document it will return 200 with no result.
+ //opasdk is returning opa_undefined_error for such case, so need to give sucess for such case and
+ //for other cases we have to send error response
+ if strings.Contains(err.Error(), string(oapicodegen.OpaUndefinedError)) {
+ decisionExc := createSuccessDecisionResponse(policyName, nil)
+ metrics.IncrementDecisionSuccessCount()
+ writeOpaJSONResponse(res, http.StatusOK, *decisionExc)
+ } else {
+ decisionExc := createDecisionExceptionResponse(http.StatusInternalServerError, err.Error(), policyName)
+ metrics.IncrementTotalErrorCount()
+ writeErrorJSONResponse(res, http.StatusInternalServerError, err.Error(), *decisionExc)
}
+}
+//This function processes the policy filters
+func processPolicyFilter(result map[string]interface{}, policyFilter []string) map[string]interface{} {
+ if len(policyFilter) > 0 {
+ filteredResult := applyPolicyFilter(result, policyFilter)
+ if filteredMap, ok := filteredResult.(map[string]interface{}); ok && len(filteredMap) > 0 {
+ return filteredMap
+ }
+ }
+ return nil
}
+
// Function to apply policy filter to decision result
func applyPolicyFilter(result map[string]interface{}, filters []string) interface{} {
return filteredOutput
}
+
"context"
"encoding/json"
"errors"
+ "fmt"
"github.com/open-policy-agent/opa/sdk"
"net/http"
"net/http/httptest"
"policy-opa-pdp/pkg/pdpstate"
"reflect"
"testing"
-
"github.com/stretchr/testify/assert"
)
+//Test for Invalid request method
func TestOpaDecision_MethodNotAllowed(t *testing.T) {
originalGetState := pdpstate.GetCurrentState
pdpstate.GetCurrentState = func() model.PdpState {
assert.Contains(t, rec.Body.String(), "MethodNotAllowed")
}
+//Test for invalid JSON request
func TestOpaDecision_InvalidJSON(t *testing.T) {
originalGetState := pdpstate.GetCurrentState
pdpstate.GetCurrentState = func() model.PdpState {
assert.Equal(t, http.StatusBadRequest, rec.Code)
}
+//Test for Missing Policy
func TestOpaDecision_MissingPolicyPath(t *testing.T) {
originalGetState := pdpstate.GetCurrentState
pdpstate.GetCurrentState = func() model.PdpState {
OpaDecision(rec, req)
assert.Equal(t, http.StatusBadRequest, rec.Code)
- assert.Contains(t, rec.Body.String(), "Policy used to make decision is nil")
+ assert.Contains(t, rec.Body.String(), "Policy Name is nil which is invalid")
+}
+
+//Test for Missing Policy Filter
+func TestOpaDecision_MissingPolicyFilter(t *testing.T) {
+ originalGetState := pdpstate.GetCurrentState
+ pdpstate.GetCurrentState = func() model.PdpState {
+ return model.Active
+ }
+ defer func() { pdpstate.GetCurrentState = originalGetState }()
+ body := map[string]interface{}{"onapName": "CDS", "policyName": "data.policy", "onapComponent": "CDS", "onapInstance": "CDS", "requestId": "8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1", "input": nil}
+
+ jsonBody, _ := json.Marshal(body)
+ req := httptest.NewRequest(http.MethodPost, "/", bytes.NewBuffer(jsonBody))
+ rec := httptest.NewRecorder()
+
+ OpaDecision(rec, req)
+
+ assert.Equal(t, http.StatusBadRequest, rec.Code)
+ assert.Contains(t, rec.Body.String(), "Policy Filter is nil")
}
+//Test for OPA Instance Error
func TestOpaDecision_GetInstanceError(t *testing.T) {
originalGetState := pdpstate.GetCurrentState
pdpstate.GetCurrentState = func() model.PdpState {
assert.Equal(t, http.StatusBadRequest, rec.Code)
}
+//Test for OPA decision Error
func TestOpaDecision_OPADecisionError(t *testing.T) {
originalGetState := pdpstate.GetCurrentState
pdpstate.GetCurrentState = func() model.PdpState {
assert.Equal(t, http.StatusBadRequest, rec.Code)
}
+//Test for system in passive State
func TestOpaDecision_PassiveState(t *testing.T) {
originalGetState := pdpstate.GetCurrentState
pdpstate.GetCurrentState = func() model.PdpState {
OpaDecision(rec, req)
assert.Equal(t, http.StatusInternalServerError, rec.Code)
- assert.Contains(t, rec.Body.String(), " System Is In PASSIVE State")
+ assert.Contains(t, rec.Body.String(), "System Is In PASSIVE State")
}
-// New
// TestOpaDecision_ValidRequest tests if the request is handled correctly
// Utility function to return a pointer to a string
-func ptrString(s string) *string {
- return &s
+func ptrString(s string) string {
+ return s
}
+func ptrStringEx(s string) *string {
+ return &s
+}
// Utility function to return a pointer to a map
-func ptrMap(m map[string]interface{}) *map[string]interface{} {
- return &m
+func ptrMap(m map[string]interface{}) map[string]interface{} {
+ return m
}
// Utility function to return a pointer to a OPADecisionResponseDecision
-func ptrOPADecisionResponseDecision(decision oapicodegen.OPADecisionResponseDecision) *oapicodegen.OPADecisionResponseDecision {
- return &decision
-}
-
func TestWriteOpaJSONResponse(t *testing.T) {
rec := httptest.NewRecorder()
- // Use correct type for Decision, which is a pointer to OPADecisionResponseDecision
- decision := oapicodegen.OPADecisionResponseDecision("PERMIT")
data := &oapicodegen.OPADecisionResponse{
- Decision: ptrOPADecisionResponseDecision(decision), // Correct use of pointer
- PolicyName: ptrString("test-policy"),
- Output: ptrMap(map[string]interface{}{"key": "value"}),
+ PolicyName: ptrString("test-policy"),
+ Output: ptrMap(map[string]interface{}{"key": "value"}),
}
writeOpaJSONResponse(rec, http.StatusOK, *data)
assert.Equal(t, http.StatusOK, rec.Code)
- assert.Contains(t, rec.Body.String(), `"decision":"PERMIT"`)
assert.Contains(t, rec.Body.String(), `"policyName":"test-policy"`)
}
+//Test for JSON response error
func TestWriteErrorJSONResponse(t *testing.T) {
rec := httptest.NewRecorder()
// ErrorResponse struct uses pointers for string fields, so we use ptrString()
errorResponse := oapicodegen.ErrorResponse{
- ErrorMessage: ptrString("Bad Request"),
+ ErrorMessage: ptrStringEx("Bad Request"),
}
writeErrorJSONResponse(rec, http.StatusBadRequest, "Bad Request", errorResponse)
assert.Contains(t, rec.Body.String(), `"errorMessage":"Bad Request"`)
}
+//Test for Success Decision Response
func TestCreateSuccessDecisionResponse(t *testing.T) {
// Input values for creating the response
- statusMessage := "Success"
- decision := oapicodegen.OPADecisionResponseDecision("PERMIT")
policyName := "policy-name"
output := map[string]interface{}{"key": "value"}
// Call the createSuccessDecisionResponse function
- response := createSuccessDecisionResponse(statusMessage, string(decision), policyName, output)
+ response := createSuccessDecisionResponse(
+ policyName, output)
// Assertions
- // Check the StatusMessage field
- assert.Equal(t, *response.StatusMessage, statusMessage, "StatusMessage should match")
-
- // Check the Decision field (it should be a pointer to the string "PERMIT")
- assert.Equal(t, *response.Decision, decision, "Decision should match")
-
// Check the PolicyName field
- assert.Equal(t, *response.PolicyName, policyName, "PolicyName should match")
+ assert.Equal(t, response.PolicyName, policyName, "PolicyName should match")
// Check the Output field
- assert.Equal(t, *response.Output, output, "Output should match")
+ assert.Equal(t, response.Output, output, "Output should match")
}
+//Test for policy filter
func TestApplyPolicyFilter(t *testing.T) {
originalPolicy := map[string]interface{}{
"policy1": map[string]interface{}{"key1": "value1"},
assert.Contains(t, result, "policy1")
}
+//Test for Opa response error
func TestWriteOpaJSONResponse_Error(t *testing.T) {
rec := httptest.NewRecorder()
// Simulate an error response
- statusMessage := "Error processing request"
- decision := oapicodegen.OPADecisionResponseDecision("DENY")
policyName := "error-policy"
output := map[string]interface{}{"errorDetail": "Invalid input"}
// Create a response object for error scenario
data := &oapicodegen.OPADecisionResponse{
- Decision: ptrOPADecisionResponseDecision(decision), // Use correct pointer
PolicyName: ptrString(policyName),
Output: ptrMap(output),
- StatusMessage: ptrString(statusMessage),
}
writeOpaJSONResponse(rec, http.StatusBadRequest, *data)
// Assertions
assert.Equal(t, http.StatusBadRequest, rec.Code, "Expected HTTP 400 status code")
- assert.Contains(t, rec.Body.String(), `"decision":"DENY"`, "Response should contain 'DENY' decision")
assert.Contains(t, rec.Body.String(), `"policyName":"error-policy"`, "Response should contain the policy name")
- assert.Contains(t, rec.Body.String(), `"statusMessage":"Error processing request"`, "Response should contain the status message")
assert.Contains(t, rec.Body.String(), `"errorDetail":"Invalid input"`, "Response should contain the error detail")
}
+//Test for JSON response success
func TestWriteOpaJSONResponse_Success(t *testing.T) {
// Prepare test data
decisionRes := oapicodegen.OPADecisionResponse{
- StatusMessage: ptrString("Success"),
- Decision: (*oapicodegen.OPADecisionResponseDecision)(ptrString("PERMIT")),
PolicyName: ptrString("TestPolicy"),
- Output: &map[string]interface{}{"key": "value"},
+ Output: map[string]interface{}{"key": "value"},
}
// Create a mock HTTP response writer
if err := json.NewDecoder(res.Body).Decode(&result); err != nil {
t.Fatalf("Failed to decode response body: %v", err)
}
- if *result.StatusMessage != "Success" {
- t.Errorf("Expected StatusMessage 'Success', got '%s'", *result.StatusMessage)
- }
}
+// Test for JSON encoding errors
func TestWriteOpaJSONResponse_EncodingError(t *testing.T) {
- // Prepare invalid test data to trigger JSON encoding error
- decisionRes := oapicodegen.OPADecisionResponse{
+ // Prepare invalid test data to trigger JSON encoding error
+ decisionRes := oapicodegen.OPADecisionResponse {
// Introducing an invalid type to cause encoding failure
- Output: &map[string]interface{}{"key": make(chan int)},
+ Output: map[string]interface{}{"key": make(chan int)},
}
// Create a mock HTTP response writer
var GetOPASingletonInstance = opasdk.GetOPASingletonInstance
var mockDecisionResult = &sdk.DecisionResult{
- Result: map[string]interface{}{
- "allowed": true,
- },
-}
-
-var mockDecisionResult2 = &sdk.DecisionResult{
Result: map[string]interface{}{
"allow": "true",
},
123: 123,
},
}
-var mockDecisionResultBoolFalse = &sdk.DecisionResult{
- Result: false,
-}
var mockDecisionResultBool = &sdk.DecisionResult{
Result: true,
var mockDecisionReq = oapicodegen.OPADecisionRequest{
PolicyName: ptrString("mockPolicy"),
- PolicyFilter: &[]string{"filter1", "filter2"},
- //Input: map[string]interface{}{"key": "value"},
+ PolicyFilter: []string{"filter1", "filter2"},
}
var mockDecisionReq2 = oapicodegen.OPADecisionRequest{
PolicyName: ptrString("mockPolicy"),
- PolicyFilter: &[]string{"allow", "filter2"},
- //Input: map[string]interface{}{"key": "value"},
+ PolicyFilter: []string{"allow", "filter2"},
}
// Test to check invalid UUID in request
return model.Active
}
defer func() { pdpstate.GetCurrentState = originalGetState }()
- body := map[string]interface{}{"PolicyName": "data.policy"}
+ jsonString := `{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "2024-11-22T11:34:56Z", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z","policyName":"s3","policyFilter":["allow"],"input":{"content" : "content"}}`
+ var decisionReq oapicodegen.OPADecisionRequest
+ json.Unmarshal([]byte(jsonString), &decisionReq)
+ body := map[string]interface{}{"PolicyName": decisionReq.PolicyName, "PolicyFilter": decisionReq.PolicyFilter,}
jsonBody, _ := json.Marshal(body)
req := httptest.NewRequest(http.MethodPost, "/opa/decision", bytes.NewBuffer(jsonBody))
req.Header.Set("X-ONAP-RequestID", "valid-uuid")
)
defer patch.Unpatch()
- body := map[string]interface{}{"PolicyName": jsonString}
+ var decisionReq oapicodegen.OPADecisionRequest
+ json.Unmarshal([]byte(jsonString), &decisionReq)
+ body := map[string]interface{}{"PolicyName": decisionReq.PolicyName, "PolicyFilter": decisionReq.PolicyFilter,}
jsonBody, _ := json.Marshal(body)
req := httptest.NewRequest(http.MethodPost, "/opa/decision", bytes.NewBuffer(jsonBody))
res := httptest.NewRecorder()
OpaDecision(res, req)
assert.Equal(t, http.StatusOK, res.Code)
- assert.Contains(t, res.Body.String(), "PERMIT")
}
// Test for Marshalling error in Decision Result
},
)
defer patch.Unpatch()
- body := map[string]interface{}{"PolicyName": jsonString}
- jsonBody, _ := json.Marshal(body)
- req := httptest.NewRequest(http.MethodPost, "/opa/decision", bytes.NewBuffer(jsonBody))
- res := httptest.NewRecorder()
-
- OpaDecision(res, req)
- assert.Equal(t, http.StatusOK, res.Code)
- assert.Empty(t, res.Body.String())
-}
-// Test for Policy filter with invalid/not applicable Decision result
-func Test_Policy_Filter_with_invalid_decision_result(t *testing.T) {
- originalGetState := pdpstate.GetCurrentState
- pdpstate.GetCurrentState = func() model.PdpState {
- return model.Active
- }
- defer func() { pdpstate.GetCurrentState = originalGetState }()
- jsonString := `{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "2024-11-22T11:34:56Z", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z","policyName":"s3","policyFilter":["allow"],"input":{"content" : "content"}}`
-
- var patch *monkey.PatchGuard
-
- patch = monkey.PatchInstanceMethod(
- reflect.TypeOf(&sdk.OPA{}), "Decision",
- func(_ *sdk.OPA, _ context.Context, _ sdk.DecisionOptions) (*sdk.DecisionResult, error) {
- return mockDecisionResult, nil
- },
- )
- defer patch.Unpatch()
- body := map[string]interface{}{"PolicyName": jsonString}
+ var decisionReq oapicodegen.OPADecisionRequest
+ json.Unmarshal([]byte(jsonString), &decisionReq)
+ body := map[string]interface{}{"PolicyName": decisionReq.PolicyName, "PolicyFilter": decisionReq.PolicyFilter,}
jsonBody, _ := json.Marshal(body)
req := httptest.NewRequest(http.MethodPost, "/opa/decision", bytes.NewBuffer(jsonBody))
res := httptest.NewRecorder()
- var patch1 *monkey.PatchGuard
- patch1 = monkey.PatchInstanceMethod(
- reflect.TypeOf(&json.Decoder{}), "Decode",
- func(_ *json.Decoder, v interface{}) error {
- if req, ok := v.(*oapicodegen.OPADecisionRequest); ok {
- *req = mockDecisionReq
- }
- return nil
- },
- )
- defer patch1.Unpatch()
OpaDecision(res, req)
-
assert.Equal(t, http.StatusOK, res.Code)
- assert.Contains(t, res.Body.String(), "NOTAPPLICABLE")
+ assert.NotEmpty(t, res.Body.String())
}
-// Test with OPA Decision of boolean type true
-func Test_with_boolean_OPA_Decision(t *testing.T) {
+// Test for Invalid Decision error in Decision Result
+func Test_Invalid_Decision(t *testing.T) {
+ // Mock PDP state
originalGetState := pdpstate.GetCurrentState
pdpstate.GetCurrentState = func() model.PdpState {
return model.Active
}
defer func() { pdpstate.GetCurrentState = originalGetState }()
- jsonString := `{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "2024-11-22T11:34:56Z", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z","policyName":"s3","policyFilter":["allow"],"input":{"content" : "content"}}`
- var patch *monkey.PatchGuard
- patch = monkey.PatchInstanceMethod(
+ // Define a request body that matches expected input format
+ jsonString := `{
+ "policyName": "s3",
+ "policyFilter": ["allow"],
+ "input": {"content": "content"}
+ }`
+
+ // Patch the OPA Decision method to return an error
+ patch := monkey.PatchInstanceMethod(
reflect.TypeOf(&sdk.OPA{}), "Decision",
func(_ *sdk.OPA, _ context.Context, _ sdk.DecisionOptions) (*sdk.DecisionResult, error) {
- return mockDecisionResultBool, nil
+ // Return an explicit error
+ return nil, fmt.Errorf("opa_undefined_error")
},
)
defer patch.Unpatch()
- body := map[string]interface{}{"PolicyName": jsonString}
- jsonBody, _ := json.Marshal(body)
- req := httptest.NewRequest(http.MethodPost, "/opa/decision", bytes.NewBuffer(jsonBody))
+ // Create a test HTTP request
+ req := httptest.NewRequest(http.MethodPost, "/opa/decision", bytes.NewBuffer([]byte(jsonString)))
+ req.Header.Set("Content-Type", "application/json")
res := httptest.NewRecorder()
+
+ // Call the handler function that processes OPA decision
OpaDecision(res, req)
- assert.Equal(t, http.StatusOK, res.Code)
- assert.Contains(t, res.Body.String(), "PERMIT")
+ // Assert that the response status code is 400
+ assert.Equal(t, 200, res.Code)
}
-// Test with OPA Decision of boolean type with false
-func Test_Successful_decision_allow_false(t *testing.T) {
+// Test for Invalid Decision error in Decision Result
+func Test_Valid_Decision_String(t *testing.T) {
+ // Mock PDP state
originalGetState := pdpstate.GetCurrentState
pdpstate.GetCurrentState = func() model.PdpState {
return model.Active
}
defer func() { pdpstate.GetCurrentState = originalGetState }()
- jsonString := `{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "2024-11-22T11:34:56Z", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z","policyName":"s3","policyFilter":["allow"],"input":{"content" : "content"}}`
- var patch *monkey.PatchGuard
- patch = monkey.PatchInstanceMethod(
+ // Define a request body that matches expected input format
+ jsonString := `{
+ "policyName": "s3",
+ "policyFilter": ["allow"],
+ "input": {"content": "content"}
+ }`
+
+ // Patch the OPA Decision method to return an error
+ patch := monkey.PatchInstanceMethod(
reflect.TypeOf(&sdk.OPA{}), "Decision",
func(_ *sdk.OPA, _ context.Context, _ sdk.DecisionOptions) (*sdk.DecisionResult, error) {
- return mockDecisionResultBool, nil
+ // Return an explicit error
+ mockDecisionResult := &sdk.DecisionResult{
+ Result: map[string]interface{}{
+ "allowed": "true",
+ },
+ }
+ return mockDecisionResult, nil
},
)
+
defer patch.Unpatch()
- body := map[string]interface{}{"PolicyName": jsonString}
- jsonBody, _ := json.Marshal(body)
- req := httptest.NewRequest(http.MethodPost, "/opa/decision", bytes.NewBuffer(jsonBody))
+ // Create a test HTTP request
+ req := httptest.NewRequest(http.MethodPost, "/opa/decision", bytes.NewBuffer([]byte(jsonString)))
+ req.Header.Set("Content-Type", "application/json")
res := httptest.NewRecorder()
+ // Call the handler function that processes OPA decision
OpaDecision(res, req)
- assert.Equal(t, http.StatusOK, res.Code)
- assert.Contains(t, res.Body.String(), "OPA Allowed")
+ // Assert that the response status code is 400
+ assert.Equal(t, 200, res.Code)
}
-// Test with OPA Decision of boolean type with false having filter
-func Test_decision_result_false_with_Filter(t *testing.T) {
+// Test for Policy filter with invalid/not applicable Decision result
+func Test_Policy_Filter_with_invalid_decision_result(t *testing.T) {
originalGetState := pdpstate.GetCurrentState
pdpstate.GetCurrentState = func() model.PdpState {
return model.Active
patch = monkey.PatchInstanceMethod(
reflect.TypeOf(&sdk.OPA{}), "Decision",
func(_ *sdk.OPA, _ context.Context, _ sdk.DecisionOptions) (*sdk.DecisionResult, error) {
- // Simulate an error to trigger the second error block
- return mockDecisionResultBool, nil
+ return mockDecisionResult, nil
},
)
defer patch.Unpatch()
OpaDecision(res, req)
assert.Equal(t, http.StatusOK, res.Code)
- assert.Contains(t, res.Body.String(), "OPA Allowed")
}
-// Test with OPA Decision of boolean type with true having filter
-func Test_decision_result_true_with_Filter(t *testing.T) {
+// Test with OPA Decision of boolean type true
+func Test_with_boolean_OPA_Decision(t *testing.T) {
originalGetState := pdpstate.GetCurrentState
pdpstate.GetCurrentState = func() model.PdpState {
return model.Active
jsonString := `{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "2024-11-22T11:34:56Z", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z","policyName":"s3","policyFilter":["allow"],"input":{"content" : "content"}}`
var patch *monkey.PatchGuard
-
patch = monkey.PatchInstanceMethod(
reflect.TypeOf(&sdk.OPA{}), "Decision",
func(_ *sdk.OPA, _ context.Context, _ sdk.DecisionOptions) (*sdk.DecisionResult, error) {
- return mockDecisionResultBoolFalse, nil
+ return mockDecisionResultBool, nil
},
)
defer patch.Unpatch()
- body := map[string]interface{}{"PolicyName": jsonString}
+
+ var decisionReq oapicodegen.OPADecisionRequest
+ json.Unmarshal([]byte(jsonString), &decisionReq)
+ body := map[string]interface{}{"PolicyName": decisionReq.PolicyName, "PolicyFilter": decisionReq.PolicyFilter,}
jsonBody, _ := json.Marshal(body)
req := httptest.NewRequest(http.MethodPost, "/opa/decision", bytes.NewBuffer(jsonBody))
res := httptest.NewRecorder()
- var patch1 *monkey.PatchGuard
- patch1 = monkey.PatchInstanceMethod(
- reflect.TypeOf(&json.Decoder{}), "Decode",
- func(_ *json.Decoder, v interface{}) error {
- if req, ok := v.(*oapicodegen.OPADecisionRequest); ok {
- *req = mockDecisionReq
- }
- return nil
- },
- )
- defer patch1.Unpatch()
OpaDecision(res, req)
assert.Equal(t, http.StatusOK, res.Code)
- assert.Contains(t, res.Body.String(), "Denied")
}
+
// Test with OPA Decision with String type
func Test_decision_Result_String(t *testing.T) {
originalGetState := pdpstate.GetCurrentState
return model.Active
}
defer func() { pdpstate.GetCurrentState = originalGetState }()
- jsonString := `{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "2024-11-22T11:34:56Z", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z","policyName":"s3","policyFilter":["allow"],"input":{"content" : "content"}}`
+ jsonString := `{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "2024-11-22T11:34:56Z", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z","policyName":"s3","policyFilter":["allowed"],"input":{"content" : "content"}}`
var patch *monkey.PatchGuard
// Create a mock result with an incompatible field (e.g., a channel)
mockDecisionResult := &sdk.DecisionResult{
Result: map[string]interface{}{
- "allowed": "deny",
+ "allowed": "true",
},
}
return mockDecisionResult, nil
},
)
defer patch.Unpatch()
- body := map[string]interface{}{"PolicyName": jsonString}
+ var decisionReq oapicodegen.OPADecisionRequest
+ json.Unmarshal([]byte(jsonString), &decisionReq)
+ body := map[string]interface{}{"PolicyName": decisionReq.PolicyName, "PolicyFilter": decisionReq.PolicyFilter,}
jsonBody, _ := json.Marshal(body)
req := httptest.NewRequest(http.MethodPost, "/opa/decision", bytes.NewBuffer(jsonBody))
res := httptest.NewRecorder()
OpaDecision(res, req)
assert.Equal(t, http.StatusOK, res.Code)
- assert.Contains(t, res.Body.String(), "DENY")
}
// Test with OPA Decision with String type wth filtered result
reflect.TypeOf(&sdk.OPA{}), "Decision",
func(_ *sdk.OPA, _ context.Context, _ sdk.DecisionOptions) (*sdk.DecisionResult, error) {
// Simulate an error to trigger the second error block
- return mockDecisionResult2, nil
+ return mockDecisionResult, nil
},
)
defer patch.Unpatch()
OpaDecision(res, req)
assert.Equal(t, http.StatusOK, res.Code)
- assert.Contains(t, res.Body.String(), "NOTAPPLICABLE")
}
OpaDecision(res, req)
assert.Equal(t, http.StatusOK, res.Code)
- assert.Contains(t, res.Body.String(), "INDETERMINATE")
}
// Test with OPA Decision with Error in response
errorMessage := "Test error message"
policyName := "TestPolicy"
responseCode := oapicodegen.ErrorResponseResponseCode("500")
- errorDetails := []string{"Detail 1", "Detail 2"}
mockDecisionExc := oapicodegen.ErrorResponse{
- ErrorDetails: &errorDetails,
ErrorMessage: &errorMessage,
PolicyName: &policyName,
ResponseCode: &responseCode,
for {
select {
case <-ticker.C:
- sendPDPHeartBeat(s)
+ if err := sendPDPHeartBeat(s); err != nil {
+ log.Errorf("Failed to send PDP Heartbeat: %v", err)
+ }
case <-stopChan:
ticker.Stop()
return
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telekom
+// Copyright (C) 2024-2025: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
import "sync"
// global counter variables
-var IndeterminantDecisionsCount int64
-var PermitDecisionsCount int64
-var DenyDecisionsCount int64
var TotalErrorCount int64
-var QuerySuccessCount int64
-var QueryFailureCount int64
+var DecisionSuccessCount int64
+var DecisionFailureCount int64
var mu sync.Mutex
-// Increment counter
-func IncrementIndeterminantDecisionsCount() {
- mu.Lock()
- IndeterminantDecisionsCount++
- mu.Unlock()
-}
-
-// returns pointer to the counter
-func IndeterminantDecisionsCountRef() *int64 {
- mu.Lock()
- defer mu.Unlock()
- return &IndeterminantDecisionsCount
-}
-
-// Increment counter
-func IncrementPermitDecisionsCount() {
- mu.Lock()
- PermitDecisionsCount++
- mu.Unlock()
-}
-// returns pointer to the counter
-func PermitDecisionsCountRef() *int64 {
- mu.Lock()
- defer mu.Unlock()
- return &PermitDecisionsCount
-}
-// Increment counter
-func IncrementDenyDecisionsCount() {
- mu.Lock()
- DenyDecisionsCount++
- mu.Unlock()
-}
-// returns pointer to the counter
-func DenyDecisionsCountRef() *int64 {
- mu.Lock()
- defer mu.Unlock()
- return &DenyDecisionsCount
-}
// Increment counter
func IncrementTotalErrorCount() {
}
// Increment counter
-func IncrementQuerySuccessCount() {
+func IncrementDecisionSuccessCount() {
mu.Lock()
- QuerySuccessCount++
+ DecisionSuccessCount++
mu.Unlock()
}
// returns pointer to the counter
-func TotalQuerySuccessCountRef() *int64 {
+func TotalDecisionSuccessCountRef() *int64 {
mu.Lock()
defer mu.Unlock()
- return &QuerySuccessCount
+ return &DecisionSuccessCount
}
// Increment counter
-func IncrementQueryFailureCount() {
+func IncrementDecisionFailureCount() {
mu.Lock()
- QueryFailureCount++
+ DecisionFailureCount++
mu.Unlock()
}
// returns pointer to the counter
-func TotalQueryFailureCountRef() *int64 {
+func TotalDecisionFailureCountRef() *int64 {
mu.Lock()
defer mu.Unlock()
- return &QueryFailureCount
+ return &DecisionFailureCount
}
func TestCounters(t *testing.T) {
var wg sync.WaitGroup
- // Test IncrementIndeterminantDecisionsCount and IndeterminantDecisionsCountRef
- IndeterminantDecisionsCount = 0
- wg.Add(10)
- for i := 0; i < 10; i++ {
- go func() {
- defer wg.Done()
- IncrementIndeterminantDecisionsCount()
- }()
- }
- wg.Wait()
- assert.Equal(t, int64(10), *IndeterminantDecisionsCountRef())
-
- // Test IncrementPermitDecisionsCount and PermitDecisionsCountRef
- PermitDecisionsCount = 0
- wg.Add(15)
- for i := 0; i < 15; i++ {
- go func() {
- defer wg.Done()
- IncrementPermitDecisionsCount()
- }()
- }
- wg.Wait()
- assert.Equal(t, int64(15), *PermitDecisionsCountRef())
-
- // Test IncrementDenyDecisionsCount and DenyDecisionsCountRef
- DenyDecisionsCount = 0
- wg.Add(20)
- for i := 0; i < 20; i++ {
- go func() {
- defer wg.Done()
- IncrementDenyDecisionsCount()
- }()
- }
- wg.Wait()
- assert.Equal(t, int64(20), *DenyDecisionsCountRef())
-
// Test IncrementTotalErrorCount and TotalErrorCountRef
TotalErrorCount = 0
wg.Add(5)
// Test IncrementQuerySuccessCount and TotalQuerySuccessCountRef
- QuerySuccessCount = 0
+ DecisionSuccessCount = 0
wg.Add(7)
defer wg.Done()
- IncrementQuerySuccessCount()
+ IncrementDecisionSuccessCount()
}()
wg.Wait()
- assert.Equal(t, int64(7), *TotalQuerySuccessCountRef())
+ assert.Equal(t, int64(7), *TotalDecisionSuccessCountRef())
- // Test IncrementQueryFailureCount and TotalQueryFailureCountRef
+ // Test IncrementDecisionFailureCount and TotalDecisionFailureCountRef
- QueryFailureCount = 0
+ DecisionFailureCount = 0
wg.Add(3)
defer wg.Done()
- IncrementQueryFailureCount()
+ IncrementDecisionFailureCount()
}()
wg.Wait()
- assert.Equal(t, int64(3), *TotalQueryFailureCountRef())
+ assert.Equal(t, int64(3), *TotalDecisionFailureCountRef())
}
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telekom
+// Copyright (C) 2024-2025: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// ========================LICENSE_END===================================
//
-// Handles an HTTP request to fetch the current system statistics.
-// It aggregates various decision counts (e.g., indeterminate, permit, deny)
+// Handles an HTTP request to fetch the current system statistics
// and error counts into a structured response and sends it back to the client in JSON format.
package metrics
var statReport oapicodegen.StatisticsReport
- statReport.IndeterminantDecisionsCount = IndeterminantDecisionsCountRef()
- statReport.PermitDecisionsCount = PermitDecisionsCountRef()
- statReport.DenyDecisionsCount = DenyDecisionsCountRef()
+ statReport.DecisionSuccessCount = TotalDecisionSuccessCountRef()
+ statReport.DecisionFailureCount = TotalDecisionFailureCountRef()
statReport.TotalErrorCount = TotalErrorCountRef()
- statReport.QuerySuccessCount = TotalQuerySuccessCountRef()
- statReport.QueryFailureCount = TotalQueryFailureCountRef()
// not implemented hardcoding the values to zero
// will be implemeneted in phase-2
res.Header().Set("Content-Type", "application/json")
res.WriteHeader(http.StatusOK)
- json.NewEncoder(res).Encode(statReport)
-
+ if err := json.NewEncoder(res).Encode(statReport); err != nil {
+ log.Errorf("Failed to encode JSON response: %v", err)
+ http.Error(res, "Internal Server Error", http.StatusInternalServerError)
+ return
+ }
}
func TestFetchCurrentStatistics(t *testing.T) {
- IndeterminantDecisionsCount = 10
- PermitDecisionsCount = 15
- DenyDecisionsCount = 20
TotalErrorCount = 5
// Create a new HTTP request
assert.NoError(t, err)
// Verify the response body
- assert.Equal(t, int64(10), *statReport.IndeterminantDecisionsCount)
- assert.Equal(t, int64(15), *statReport.PermitDecisionsCount)
- assert.Equal(t, int64(20), *statReport.DenyDecisionsCount)
assert.Equal(t, int64(5), *statReport.TotalErrorCount)
assert.Equal(t, int64(0), *statReport.TotalPoliciesCount)
assert.Equal(t, int64(1), *statReport.TotalPolicyTypesCount)
// Defines values for ErrorResponseResponseCode.
const (
- BADGATEWAY ErrorResponseResponseCode = "BAD_GATEWAY"
- BADREQUEST ErrorResponseResponseCode = "BAD_REQUEST"
- CONFLICT ErrorResponseResponseCode = "CONFLICT"
- EXPECTATIONFAILED ErrorResponseResponseCode = "EXPECTATION_FAILED"
- GATEWAYTIMEOUT ErrorResponseResponseCode = "GATEWAY_TIMEOUT"
- GONE ErrorResponseResponseCode = "GONE"
- HTTPVERSIONNOTSUPPORTED ErrorResponseResponseCode = "HTTP_VERSION_NOT_SUPPORTED"
- INTERNALSERVERERROR ErrorResponseResponseCode = "INTERNAL_SERVER_ERROR"
- LENGTHREQUIRED ErrorResponseResponseCode = "LENGTH_REQUIRED"
- METHODNOTALLOWED ErrorResponseResponseCode = "METHOD_NOT_ALLOWED"
- NETWORKAUTHENTICATIONREQUIRED ErrorResponseResponseCode = "NETWORK_AUTHENTICATION_REQUIRED"
- NOTACCEPTABLE ErrorResponseResponseCode = "NOT_ACCEPTABLE"
- NOTIMPLEMENTED ErrorResponseResponseCode = "NOT_IMPLEMENTED"
- PRECONDITIONFAILED ErrorResponseResponseCode = "PRECONDITION_FAILED"
- PRECONDITIONREQUIRED ErrorResponseResponseCode = "PRECONDITION_REQUIRED"
- REQUESTEDRANGENOTSATISFIABLE ErrorResponseResponseCode = "REQUESTED_RANGE_NOT_SATISFIABLE"
- REQUESTENTITYTOOLARGE ErrorResponseResponseCode = "REQUEST_ENTITY_TOO_LARGE"
- REQUESTHEADERFIELDSTOOLARGE ErrorResponseResponseCode = "REQUEST_HEADER_FIELDS_TOO_LARGE"
- REQUESTTIMEOUT ErrorResponseResponseCode = "REQUEST_TIMEOUT"
- REQUESTURITOOLONG ErrorResponseResponseCode = "REQUEST_URI_TOO_LONG"
- SERVICEUNAVAILABLE ErrorResponseResponseCode = "SERVICE_UNAVAILABLE"
- TOOMANYREQUESTS ErrorResponseResponseCode = "TOO_MANY_REQUESTS"
- UNAUTHORIZED ErrorResponseResponseCode = "UNAUTHORIZED"
- UNSUPPORTEDMEDIATYPE ErrorResponseResponseCode = "UNSUPPORTED_MEDIA_TYPE"
-)
-
-// Defines values for OPADecisionResponseDecision.
-const (
- DENY OPADecisionResponseDecision = "DENY"
- INDETERMINATE OPADecisionResponseDecision = "INDETERMINATE"
- NOTAPPLICABLE OPADecisionResponseDecision = "NOTAPPLICABLE"
- PERMIT OPADecisionResponseDecision = "PERMIT"
+ BadRequest ErrorResponseResponseCode = "bad_request"
+ EvaluationError ErrorResponseResponseCode = "evaluation_error"
+ InternalError ErrorResponseResponseCode = "internal_error"
+ InvalidOperation ErrorResponseResponseCode = "invalid_operation"
+ InvalidParameter ErrorResponseResponseCode = "invalid_parameter"
+ OpaUndefinedError ErrorResponseResponseCode = "opa_undefined_error"
+ ResourceConflict ErrorResponseResponseCode = "resource_conflict"
+ ResourceNotFound ErrorResponseResponseCode = "resource_not_found"
+ Unauthorized ErrorResponseResponseCode = "unauthorized"
+ UndefinedDocument ErrorResponseResponseCode = "undefined_document"
)
// ErrorResponse defines model for ErrorResponse.
type ErrorResponse struct {
- ErrorDetails *[]string `json:"errorDetails,omitempty"`
ErrorMessage *string `json:"errorMessage,omitempty"`
PolicyName *string `json:"policyName,omitempty"`
ResponseCode *ErrorResponseResponseCode `json:"responseCode,omitempty"`
// OPADecisionRequest defines model for OPADecisionRequest.
type OPADecisionRequest struct {
- CurrentDate *openapi_types.Date `json:"currentDate,omitempty"`
- CurrentDateTime *time.Time `json:"currentDateTime,omitempty"`
- CurrentTime *time.Time `json:"currentTime,omitempty"`
- Input *map[string]interface{} `json:"input,omitempty"`
- OnapComponent *string `json:"onapComponent,omitempty"`
- OnapInstance *string `json:"onapInstance,omitempty"`
- OnapName *string `json:"onapName,omitempty"`
- PolicyFilter *[]string `json:"policyFilter,omitempty"`
- PolicyName *string `json:"policyName,omitempty"`
+ CurrentDate *openapi_types.Date `json:"currentDate,omitempty"`
+ CurrentDateTime *time.Time `json:"currentDateTime,omitempty"`
+ CurrentTime *string `json:"currentTime,omitempty"`
+ Input map[string]interface{} `json:"input"`
+ OnapComponent *string `json:"onapComponent,omitempty"`
+ OnapInstance *string `json:"onapInstance,omitempty"`
+ OnapName *string `json:"onapName,omitempty"`
+ PolicyFilter []string `json:"policyFilter"`
+ PolicyName string `json:"policyName"`
// TimeOffset Time offset in hours and minutes, e.g., '+02:00' or '-05:00'
TimeOffset *string `json:"timeOffset,omitempty"`
// OPADecisionResponse defines model for OPADecisionResponse.
type OPADecisionResponse struct {
- Decision *OPADecisionResponseDecision `json:"decision,omitempty"`
- Output *map[string]interface{} `json:"output,omitempty"`
- PolicyName *string `json:"policyName,omitempty"`
- StatusMessage *string `json:"statusMessage,omitempty"`
+ Output map[string]interface{} `json:"output"`
+ PolicyName string `json:"policyName"`
+ StatusMessage *string `json:"statusMessage,omitempty"`
}
-// OPADecisionResponseDecision defines model for OPADecisionResponse.Decision.
-type OPADecisionResponseDecision string
-
// StatisticsReport defines model for StatisticsReport.
type StatisticsReport struct {
- Code *int32 `json:"code,omitempty"`
- DenyDecisionsCount *int64 `json:"denyDecisionsCount,omitempty"`
- DeployFailureCount *int64 `json:"deployFailureCount,omitempty"`
- DeploySuccessCount *int64 `json:"deploySuccessCount,omitempty"`
- IndeterminantDecisionsCount *int64 `json:"indeterminantDecisionsCount,omitempty"`
- PermitDecisionsCount *int64 `json:"permitDecisionsCount,omitempty"`
- QueryFailureCount *int64 `json:"queryFailureCount,omitempty"`
- QuerySuccessCount *int64 `json:"querySuccessCount,omitempty"`
- TotalErrorCount *int64 `json:"totalErrorCount,omitempty"`
- TotalPoliciesCount *int64 `json:"totalPoliciesCount,omitempty"`
- TotalPolicyTypesCount *int64 `json:"totalPolicyTypesCount,omitempty"`
- UndeployFailureCount *int64 `json:"undeployFailureCount,omitempty"`
- UndeploySuccessCount *int64 `json:"undeploySuccessCount,omitempty"`
+ Code *int32 `json:"code,omitempty"`
+ DecisionFailureCount *int64 `json:"decisionFailureCount,omitempty"`
+ DecisionSuccessCount *int64 `json:"decisionSuccessCount,omitempty"`
+ DeployFailureCount *int64 `json:"deployFailureCount,omitempty"`
+ DeploySuccessCount *int64 `json:"deploySuccessCount,omitempty"`
+ TotalErrorCount *int64 `json:"totalErrorCount,omitempty"`
+ TotalPoliciesCount *int64 `json:"totalPoliciesCount,omitempty"`
+ TotalPolicyTypesCount *int64 `json:"totalPolicyTypesCount,omitempty"`
+ UndeployFailureCount *int64 `json:"undeployFailureCount,omitempty"`
+ UndeploySuccessCount *int64 `json:"undeploySuccessCount,omitempty"`
}
// DecisionParams defines parameters for Decision.
## Verification API Calls
-curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22", "currentTime": "2024-11-22T11:34:56Z", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z","policyName":"example/allow","input":{"method":"POST","path":["users"]}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
+curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22", "currentTime": "11:34:56", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z", "policyFilter" : [""], "policyName":"example","input":{"method":"POST","path":["users"]}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
-curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22", "currentTime": "2024-11-22T11:34:56Z", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z", "policyName":"role/allow","input":{"user":"alice","action":"write","object":"id123","type":"dog"}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
+{"output":{"allow":true},"policyName":"example"}
-## PERMIT for policy:action
+curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22", "currentTime": "11:34:56", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z", "policyName":"role", "policyFilter": ["role_grants"], "input":{"user":"alice","action":"write","object":"id123","type":"dog"}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
-curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "2024-11-22T11:34:56Z", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z","policyName":"action/allow","input":{"user":"alice","action":"delete","type":"server"}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
+{"output":{"role_grants":{"billing":[{"action":"read","type":"finance"},{"action":"update","type":"finance"}],"customer":[{"action":"read","type":"dog"},{"action":"read","type":"cat"},{"action":"adopt","type":"dog"},{"action":"adopt","type":"cat"}],"employee":[{"action":"read","type":"dog"},{"action":"read","type":"cat"},{"action":"update","type":"dog"},{"action":"update","type":"cat"}]}},"policyName":"role"}
-{"decision":"PERMIT","policyName":"action/allow","statusMessage":"OPA Allowed"}
+## OUTPUT for policy:action with filter role_permissions
-## DENY for policy:action
+curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "11:34:56", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z",__"policyFilter": ["role_permissions"]__, "policyName":"action","input":{"user":"alice","action":"delete","type":"server"}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
-curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "2024-11-22T11:34:56Z", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z","policyName":"action/allow","input":{"user":"charlie","action":"delete","type":"server"}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
+{"output":{"role_permissions":{"admin":{"actions":["read","write","delete"],"resources":["server","database"]},"editor":{"actions":["read","write"],"resources":["server"]},"viewer":{"actions":["read"],"resources":["server"]}}},"policyName":"action"}
-{"decision":"DENY","policyName":"action/allow","statusMessage":"OPA Denied"}
+## OUTPUT for policy:action with empty filters
-## PERMIT for policy:account
+curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "11:34:56", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z",__"policyFilter": [""]__, "policyName":"action","input":{"user":"alice","action":"delete","type":"server"}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
-curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "2024-11-22T11:34:56Z", "timeZone": "UTC","timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z","policyName":"account/allow", "input":{"creditor_account":11111,"creditor":"alice","debtor_account":22222,"debtor":"bob","period":30,"amount":1000}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
+{"output":{"allow":true,"role_permissions":{"admin":{"actions":["read","write","delete"],"resources":["server","database"]},"editor":{"actions":["read","write"],"resources":["server"]},"viewer":{"actions":["read"],"resources":["server"]}},"user_roles":{"alice":["admin"],"bob":["editor"],"charlie":["viewer"]}},"policyName":"action"}
-{"decision":"PERMIT","policyName":"account/allow","statusMessage":"OPA Allowed"}
+## OUTPUT for policy:action without filter
-## DENY for policy:account
+curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "11:34:56", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z","policyName":"action","input":{"user":"charlie","action":"delete","type":"server"}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
-curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "2024-11-22T11:34:56Z", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z","policyName":"account/allow", "input":{"creditor_account":11111,"creditor":"alice","debtor_account":22222,"debtor":"bob","period":31,"amount":1000}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
+{"errorMessage":"Policy Filter is nil.","policyName":"","responseCode":"bad_request"}
-{"decision":"DENY","policyName":"account/allow","statusMessage":"OPA Denied"}
+## OUTPUT for policy:account with filter account_attributes
-## PERMIT for policy:organization
+curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "11:34:56", "timeZone": "UTC","timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z",__"policyFilter": ["account_attributes"]__, "policyName":"account", "input":{"creditor_account":11111,"creditor":"alice","debtor_account":22222,"debtor":"bob","period":30,"amount":1000}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
-curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "2024-11-22T11:34:56Z", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z","policyName":"organization/allow", "input":{"user":"alice","action": "read","component": "component_A","project": "project_A", "organization": "org_A"}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
-{"decision":"PERMIT","policyName":"organization/allow","statusMessage":"OPA Allowed"}
+{"output":{"account_attributes":{"11111":{"amount":10000,"owner":"alice"},"22222":{"amount":10000,"owner":"bob"},"33333":{"amount":10000,"owner":"cam"}}},"policyName":"account"}
-## DENY for policy:organization
+## OUTPUT for policy:account with empty filter
-curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "2024-11-22T11:34:56Z", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z","policyName":"organization/allow", "input":{"user":"charlie","action": "edit","component": "component_A","project": "project_A", "organization": "org_A"}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
+curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "11:34:56", "timeZone": "UTC","timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z",__"policyFilter": [""]__, "policyName":"account", "input":{"creditor_account":11111,"creditor":"alice","debtor_account":22222,"debtor":"bob","period":30,"amount":1000}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
-{"decision":"DENY","policyName":"organization/allow","statusMessage":"OPA Denied"}
+{"output":{"account_attributes":{"11111":{"amount":10000,"owner":"alice"},"22222":{"amount":10000,"owner":"bob"},"33333":{"amount":10000,"owner":"cam"}},"allow":true,"amount_is_valid":true,"creditor_is_valid":true,"debtor_is_valid":true,"period_is_valid":true},"policyName":"account"}
-## DENY for policy:abac(output)
+## OUTPUT for policy:organization with filter acls
-curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22","policyName":"abac", "policyFilter": ["action_is_read"], "input":{"actions": ["write"],"datatypes": ["location","temperature","precipitation","windspeed"],"time_period": {"from": "2024-03-27","to": "2024-03-31"}}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
-{"decision":"DENY","output":{},"policyName":"abac","statusMessage":"OPA Denied"}
+curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "11:34:56", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z",__"policyFilter": ["acls"]__, "policyName":"organization", "input":{"user":"alice","action": "read","component": "component_A","project": "project_A", "organization": "org_A"}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
-## PERMIT for policy:abac
+{"output":{"acls":[{"actions":["edit","read"],"component":"component_A","organization":"org_A","project":"project_A","user":"alice"},{"actions":["read"],"organization":"org_A","user":"bob"},{"action":["edit"],"component":"component_A","organization":"org_A","project":"project_B","user":"bob"},{"action":["read"],"organization":"org_A","project":"project_B","user":"charlie"}]},"policyName":"organization"}
-curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22","policyName":"abac", "policyFilter": ["viewable_sensor_data"], "input":{"actions": ["read"],"datatypes": ["location","temperature","precipitation","windspeed"],"time_period": {"from": "2024-02-27","to": "2024-02-29"}}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
-{"decision":"PERMIT","output":{"viewable_sensor_data":[{"location":"Galle","precipitation":"500 mm","temperature":"35 C","windspeed":"7.2 m/s"},{"location":"Jaffna","precipitation":"300 mm","temperature":"-5 C","windspeed":"3.8 m/s"},{"location":"Nuwara Eliya","precipitation":"600 mm","temperature":"25 C","windspeed":"4.0 m/s"},{"location":"Trincomalee","precipitation":"1000 mm","temperature":"20 C","windspeed":"5.0 m/s"}]},"policyName":"abac","statusMessage":"OPA Allowed"}
+## OUTPUT for policy:organization with empty filter
-## PERMIT for policy:zone
-curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22","policyName":"zone", "policyFilter": ["has_zone_access"], "input":{"actions": ["view"],"log_id": "log1", "datatypes": ["access", "user"],"time_period": {"from": "2024-11-01T09:00:00Z","to": "2024-11-01T10:00:00Z"},"zone_id": "zoneA"}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
-{"decision":"PERMIT","output":{"has_zone_access":[{"access":"granted","user":"user1"}]},"policyName":"zone","statusMessage":"OPA Allowed"}
+curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS", "currentDate": "2024-11-22", "currentTime": "11:34:56", "timeZone": "UTC", "timeOffset": "+05:30", "currentDateTime": "2024-11-22T12:08:00Z",__"policyFilter": [""]__, "policyName":"organization", "input":{"user":"alice","action": "read","component": "component_A","project": "project_A", "organization": "org_A"}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
-## DENY for policy: zone
+{"output":{"acls":[{"actions":["edit","read"],"component":"component_A","organization":"org_A","project":"project_A","user":"alice"},{"actions":["read"],"organization":"org_A","user":"bob"},{"action":["edit"],"component":"component_A","organization":"org_A","project":"project_B","user":"bob"},{"action":["read"],"organization":"org_A","project":"project_B","user":"charlie"}],"allow":true},"policyName":"organization"}
-curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22","policyName":"zone", "policyFilter": ["has_zone_access"], "input":{"actions": ["edit"],"log_id": "log1", "datatypes": ["access", "user"],"time_period": {"from": "2024-11-01T00:00:00Z","to": "2024-11-01T00:00:00Z"},"zone_id": "zoneA"}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
-{"decision":"DENY","output":{"has_zone_access":[]},"policyName":"zone","statusMessage":"OPA Denied"}
+## OUTPUT for policy:abac with filter viewable_sensor_data
-## PERMIT for policy:vehicle
+curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22","policyName":"abac", __"policyFilter": ["viewable_sensor_data"]__, "input":{"actions": ["write"],"datatypes": ["location","temperature","precipitation","windspeed"],"time_period": {"from": "2024-03-27","to": "2024-03-31"}}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
-curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22","policyName":"vehicle", "policyFilter": ["user_has_vehicle_access"], "input":{"actions": ["use"],"user":"user1", "vehicle_id": "v1", "attributes": ["type", "status"]}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
+{"output":{"viewable_sensor_data":[]},"policyName":"abac"}
-{"decision":"PERMIT","output":{"user_has_vehicle_access":[{"status":"available","type":"car"}]},"policyName":"vehicle","statusMessage":"OPA Allowed"}
+## OUTPUT for policy:abac with empty filter
-## PERMIT for policy:docs
+curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22","policyName":"abac", __"policyFilter": [""]__, "input":{"actions": ["write"],"datatypes": ["location","temperature","precipitation","windspeed"],"time_period": {"from": "2024-03-27","to": "2024-03-31"}}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
-`curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22","policyName":"docs", "policyFilter": ["has_access_to_file"], "input":{"action": "read","file_id": "file1","access_level": "admin","attributes": ["owner", "size"]}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
+{"output":{"allow":false,"sensor_data":[{"humidity":"40%","id":"0001","location":"Sri Lanka","particle_density":"1.3 g/l","precipitation":"1000 mm","temperature":"28 C","timestamp":"2024-02-26","windspeed":"5.5 m/s"},{"humidity":"45%","id":"0002","location":"Colombo","particle_density":"1.5 g/l","precipitation":"1200 mm","temperature":"30 C","timestamp":"2024-02-26","windspeed":"6.0 m/s"},{"humidity":"60%","id":"0003","location":"Kandy","particle_density":"1.1 g/l","precipitation":"800 mm","temperature":"25 C","timestamp":"2024-02-26","windspeed":"4.5 m/s"},{"humidity":"30%","id":"0004","location":"Galle","particle_density":"1.8 g/l","precipitation":"500 mm","temperature":"35 C","timestamp":"2024-02-27","windspeed":"7.2 m/s"},{"humidity":"20%","id":"0005","location":"Jaffna","particle_density":"0.9 g/l","precipitation":"300 mm","temperature":"-5 C","timestamp":"2024-02-27","windspeed":"3.8 m/s"},{"humidity":"55%","id":"0006","location":"Trincomalee","particle_density":"1.2 g/l","precipitation":"1000 mm","temperature":"20 C","timestamp":"2024-02-28","windspeed":"5.0 m/s"},{"humidity":"50%","id":"0007","location":"Nuwara Eliya","particle_density":"1.3 g/l","precipitation":"600 mm","temperature":"25 C","timestamp":"2024-02-28","windspeed":"4.0 m/s"},{"humidity":"40%","id":"0008","location":"Anuradhapura","particle_density":"1.4 g/l","precipitation":"700 mm","temperature":"28 C","timestamp":"2024-02-29","windspeed":"5.8 m/s"},{"humidity":"65%","id":"0009","location":"Matara","particle_density":"1.6 g/l","precipitation":"900 mm","temperature":"32 C","timestamp":"2024-02-29","windspeed":"6.5 m/s"}],"viewable_sensor_data":[]},"policyName":"abac"}
-{"decision":"PERMIT","output":{"has_access_to_file":[{"owner":"user1","size":"10MB"}]},"policyName":"docs","statusMessage":"OPA Allowed"}`
+## OUTPUT for policy:zone with filter has_zone_access
-## DENY for policy:docs
+curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22","policyName":"zone", __"policyFilter": ["has_zone_access"]__, "input":{"actions": ["view"],"log_id": "log1", "datatypes": ["access", "user"],"time_period": {"from": "2024-11-01T09:00:00Z","to": "2024-11-01T10:00:00Z"},"zone_id": "zoneA"}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
-`curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22","policyName":"docs", "policyFilter": ["has_access_to_file"], "input":{"action": "view","file_id": "file1","access_level": "employee","attributes": ["owner", "size"]}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
+{"output":{"has_zone_access":[{"access":"granted","user":"user1"}]},"policyName":"zone"}
+
+## OUTPUT for policy:zone with empty filter
+
+curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22","policyName":"zone", __"policyFilter": [""]__, "input":{"actions": ["view"],"log_id": "log1", "datatypes": ["access", "user"],"time_period": {"from": "2024-11-01T09:00:00Z","to": "2024-11-01T10:00:00Z"},"zone_id": "zoneA"}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
+
+{"output":{"action_is_log_view":true,"allow":true,"has_zone_access":[{"access":"granted","user":"user1"}],"zone":{"zone_access_logs":[{"access":"granted","log_id":"log1","timestamp":"2024-11-01T09:00:00Z","user":"user1","zone_id":"zoneA"},{"access":"denied","log_id":"log2","timestamp":"2024-11-01T10:30:00Z","user":"user2","zone_id":"zoneA"},{"access":"granted","log_id":"log3","timestamp":"2024-11-01T11:00:00Z","user":"user3","zone_id":"zoneB"}]}},"policyName":"zone"}
+
+## OUTPUT for policy:vehicle with filter user_has_vehicle_access
+
+curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22","policyName":"vehicle", __"policyFilter": ["user_has_vehicle_access"]__, "input":{"actions": ["use"],"user":"user1", "vehicle_id": "v1", "attributes": ["type", "status"]}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
+
+{"output":{"user_has_vehicle_access":[{"status":"available","type":"car"}]},"policyName":"vehicle"}
+
+## OUTPUT for policy:vehicle with empty filter
+
+curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22","policyName":"vehicle", __"policyFilter": [""]__, "input":{"actions": ["use"],"user":"user1", "vehicle_id": "v1", "attributes": ["type", "status"]}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
+
+{"output":{"action_is_granted":true,"allow":true,"user_has_vehicle_access":[{"status":"available","type":"car"}],"vehicles":[{"owner":"user1","status":"available","type":"car","vehicle_id":"v1"},{"owner":"user2","status":"in use","type":"bike","vehicle_id":"v2"}]},"policyName":"vehicle"}
+
+## OUTPUT for policy:docs with filter has_access_to_file
+
+curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22","policyName":"docs", __"policyFilter": ["has_access_to_file"]__, "input":{"action": "read","file_id": "file1","access_level": "admin","attributes": ["owner", "size"]}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
+
+{"output":{"has_access_to_file":[{"owner":"user1","size":"10MB"}]},"policyName":"docs"}
+
+## OUTPUT for policy:docs with empty filter
+
+curl -u 'policyadmin:zb!XztG34' -H 'Content-Type: application/json' -H 'Accept: application/json' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -d '{"onapName":"CDS","onapComponent":"CDS","onapInstance":"CDS","currentDate": "2024-11-22","policyName":"docs", __"policyFilter": [""]__, "input":{"action": "read","file_id": "file1","access_level": "admin","attributes": ["owner", "size"]}}' -X POST http://0.0.0.0:8282/policy/pdpo/v1/decision
+
+{"output":{"action_is_read_or_write":true,"allow":true,"files":[{"access_level":"admin","file_id":"file1","owner":"user1","size":"10MB"},{"access_level":"user","file_id":"file2","owner":"user2","size":"5MB"}],"has_access_to_file":[{"owner":"user1","size":"10MB"}]},"policyName":"docs"}
-{"decision":"DENY","output":{"has_access_to_file":[]},"policyName":"docs","statusMessage":"OPA Denied"}`
## HealthCheck API Call With Response
curl -u 'policyadmin:zb!XztG34' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -X GET http://0.0.0.0:8282/policy/pdpo/v1/healthcheck
-{"code":200,"healthy":true,"message":"alive","name":"opa-9f0248ea-807e-45f6-8e0f-935e570b75cc","url":"self"}
+{"code":200,"healthy":true,"message":"alive","name":"opa-ea84b1ff-00de-4bf6-a039-222e4511d0a1","url":"self"}
## Statistics API Call With Response
curl -u 'policyadmin:zb!XztG34' --header 'X-ONAP-RequestID:8e6f784e-c9cb-42f6-bcc9-edb5d0af1ce1' -X GET http://0.0.0.0:8282/policy/pdpo/v1/statistics
-{"code":200,"denyDecisionsCount":10,"deployFailureCount":0,"deploySuccessCount":0,"indeterminantDecisionsCount":0,"permitDecisionsCount":18,"totalErrorCount":4,"totalPoliciesCount":0,"totalPolicyTypesCount":1,"undeployFailureCount":0,"undeploySuccessCount":0}
+{"code":200,"decisionFailureCount":0,"decisionSuccessCount":9,"deployFailureCount":0,"deploySuccessCount":0,"totalErrorCount":5,"totalPoliciesCount":0,"totalPolicyTypesCount":1,"undeployFailureCount":0,"undeploySuccessCount":0}
-1.0.1-SNAPSHOT
+1.0.2-SNAPSHOT
major=1
minor=0
-patch=1
+patch=2
base_version=${major}.${minor}.${patch}