+# -
+# ========================LICENSE_START=================================
+# Copyright (C) 2024: 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===================================
+#
FROM curlimages/curl:7.78.0 AS build
# Get OPA
#\r
# ========================LICENSE_START=================================\r
-# Copyright (C) 2024: Deutsche Telecom\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
# 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.0\r
+ version: 1.0.2\r
x-component: Policy Framework\r
x-planned-retirement-date: tbd\r
contact:\r
tags:\r
- Statistics\r
summary: Fetch current statistics\r
- description: Provides current statistics of the Policy OPA PDP component \r
+ description: Provides current statistics of the Policy OPA PDP component\r
operationId: statistics\r
parameters:\r
- name: X-ONAP-RequestID\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
- 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
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
\ No newline at end of file
+ scheme: basic\r
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
// Package api provides HTTP handlers for the policy-opa-pdp service.
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
//
+# -
+# ========================LICENSE_START=================================
+# Copyright (C) 2024: 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===================================
+#
+
FROM curlimages/curl:7.78.0 AS build
# Get OPA
#!/bin/bash
# -
# ========================LICENSE_START=================================
-# Copyright (C) 2024: Deutsche Telecom
+# Copyright (C) 2024: Deutsche Telekom
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# 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===================================
-#
+
export IMAGE_NAME="nexus3.onap.org:10003/onap/policy-opa-pdp"
VERSION_FILE="version"
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
// Package cfg provides configuration settings for the policy-opa-pdp service.
package cfg
import (
+ "fmt"
log "github.com/sirupsen/logrus"
"os"
+ "regexp"
"strconv"
)
UseSASLForKAFKA string
KAFKA_USERNAME string
KAFKA_PASSWORD string
+ JAASLOGIN string
)
// Initializes the configuration settings.
Username = getEnv("API_USER", "policyadmin")
Password = getEnv("API_PASSWORD", "zb!XztG34")
UseSASLForKAFKA = getEnv("UseSASLForKAFKA", "false")
- KAFKA_USERNAME = getEnv("KAFKA_USERNAME", "strimzi-kafka-user")
- KAFKA_PASSWORD = getEnv("KAFKA_PASSWORD", "kafkaSecretPassword123")
+ KAFKA_USERNAME, KAFKA_PASSWORD = getSaslJAASLOGINFromEnv(JAASLOGIN)
+ log.Debugf("Username: %s", KAFKA_USERNAME)
+ log.Debugf("Password: %s", KAFKA_PASSWORD)
+
log.Debug("Configuration module: environment initialised")
}
return log.DebugLevel
}
}
+
+func getSaslJAASLOGINFromEnv(JAASLOGIN string) (string, string) {
+ // Retrieve the value of the environment variable
+ decodingConfigBytes := getEnv("JAASLOGIN", "JAASLOGIN")
+ if decodingConfigBytes == "" {
+ return "", ""
+ }
+
+ decodedConfig := string(decodingConfigBytes)
+ fmt.Println("decodedConfig", decodedConfig)
+
+ // Extract username and password using regex
+ usernamePattern := `username=["'](.+?)["']`
+ passwordPattern := `password=["'](.+?)["']`
+
+ // Extract username
+ usernameMatch := regexp.MustCompile(usernamePattern).FindStringSubmatch(decodedConfig)
+ if len(usernameMatch) < 2 {
+ return "", ""
+ }
+ username := usernameMatch[1]
+
+ // Extract password
+ passwordMatch := regexp.MustCompile(passwordPattern).FindStringSubmatch(decodedConfig)
+ if len(passwordMatch) < 2 {
+ return "", ""
+ }
+ password := passwordMatch[1]
+
+ return username, password
+}
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
//
import (
log "github.com/sirupsen/logrus"
+ "github.com/stretchr/testify/assert"
"os"
"testing"
)
t.Errorf("Expected %v, got %v", log.InfoLevel, val)
}
}
+
+func TestGetSaslJAASLOGINFromEnv(t *testing.T) {
+ // Define mock JAASLOGIN value
+ mockJAASLOGIN := `username="mockUser" password="mockPassword"`
+
+ // Set the mock environment variable
+ os.Setenv("JAASLOGIN", mockJAASLOGIN)
+ defer os.Unsetenv("JAASLOGIN") // Ensure the environment variable is unset after the test
+
+ // Call the function
+ username, password := getSaslJAASLOGINFromEnv("JAASLOGIN")
+
+ // Validate the result
+ assert.Equal(t, "mockUser", username, "Expected username to match mock value")
+ assert.Equal(t, "mockPassword", password, "Expected password to match mock value")
+}
+
+func TestGetSaslJAASLOGINFromEnv_InvalidEnv(t *testing.T) {
+ // Set the mock environment variable with an invalid format
+ mockJAASLOGIN := `username="mockUser" password=mockPassword`
+ os.Setenv("JAASLOGIN", mockJAASLOGIN)
+ defer os.Unsetenv("JAASLOGIN") // Ensure the environment variable is unset after the test
+
+ // Call the function
+ username, password := getSaslJAASLOGINFromEnv("JAASLOGIN")
+
+ // Validate that the function returns empty strings for invalid input
+ assert.Empty(t, username, "Expected username to be empty for invalid format")
+ assert.Empty(t, password, "Expected password to be empty for invalid format")
+}
+
+func TestGetSaslJAASLOGINFromEnv_EmptyEnv(t *testing.T) {
+ // Set an empty environment variable
+ os.Setenv("JAASLOGIN", "")
+ defer os.Unsetenv("JAASLOGIN") // Ensure the environment variable is unset after the test
+
+ // Call the function
+ username, password := getSaslJAASLOGINFromEnv("JAASLOGIN")
+
+ // Validate that the function returns empty strings for an empty value
+ assert.Empty(t, username, "Expected username to be empty for empty environment variable")
+ assert.Empty(t, password, "Expected password to be empty for empty environment variable")
+}
+
+func TestGetSaslJAASLOGINFromEnv_MissingEnv(t *testing.T) {
+ // Unset the environment variable to simulate missing variable
+ os.Unsetenv("JAASLOGIN")
+
+ // Call the function
+ username, password := getSaslJAASLOGINFromEnv("JAASLOGIN")
+
+ // Validate that the function returns empty strings for a missing environment variable
+ assert.Empty(t, username, "Expected username to be empty for missing environment variable")
+ assert.Empty(t, password, "Expected password to be empty for missing environment variable")
+}
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
// Package main is the entry point for the policy-opa-pdp service.
func main() {
log.Debugf("Starting OPA PDP Service")
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
// Initialize Handlers and Build Bundle
initializeHandlersFunc()
if err := initializeBundleFunc(exec.Command); err != nil {
// Start Kafka Consumer and producer
kc, producer, err := startKafkaConsAndProdFunc()
- if err != nil {
+ if err != nil || kc == nil {
log.Warnf("Kafka consumer initialization failed: %v", err)
}
defer producer.Close()
return
}
-
// start pdp message handler in a seperate routine
- handleMessagesFunc(kc, sender)
+ handleMessagesFunc(ctx, kc, sender)
// Handle OS Interrupts and Graceful Shutdown
interruptChannel := make(chan os.Signal, 1)
signal.Notify(interruptChannel, os.Interrupt, syscall.SIGTERM, syscall.SIGINT, syscall.SIGHUP)
- handleShutdownFunc(kc, interruptChannel)
+ handleShutdownFunc(kc, interruptChannel, cancel)
}
// starts pdpMessage Handler in a seperate routine which handles incoming messages on Kfka topic
-func handleMessages(kc *kafkacomm.KafkaConsumer, sender *publisher.RealPdpStatusSender) {
- go handler.PdpMessageHandler(kc, topic, sender)
+func handleMessages(ctx context.Context, kc *kafkacomm.KafkaConsumer, sender *publisher.RealPdpStatusSender) {
+
+ go func() {
+ err := handler.PdpMessageHandler(ctx, kc, topic, sender)
+ if err != nil {
+ log.Warnf("Erro in PdpUpdate Message Handler: %v", err)
+ }
+ }()
}
// register pdp with PAP
return kc, producer, nil
}
-func handleShutdown(kc *kafkacomm.KafkaConsumer, interruptChannel chan os.Signal) {
+func handleShutdown(kc *kafkacomm.KafkaConsumer, interruptChannel chan os.Signal, cancel context.CancelFunc) {
myLoop:
for {
break myLoop
}
}
-
+ cancel()
+ log.Debugf("Loop Exited and shutdown started")
signal.Stop(interruptChannel)
- if kc != nil {
- kc.Consumer.Unsubscribe()
- kc.Consumer.Close()
- log.Debug("Consumer Unsubscribed and Closed......")
+ if kc == nil {
+ log.Debugf("kc is nil so skipping")
+ return
+ }
+
+ if err := kc.Consumer.Unsubscribe(); err != nil {
+ log.Warnf("Failed to unsubscribe consumer: %v", err)
+ } else {
+ log.Debugf("Consumer Unsubscribed....")
+ }
+ if err := kc.Consumer.Close(); err != nil {
+ log.Debug("Failed to close consumer......")
+ } else {
+ log.Debugf("Consumer closed....")
}
+ handler.SetShutdownFlag()
publisher.StopTicker()
time.Sleep(time.Duration(consts.SHUTDOWN_WAIT_TIME) * time.Second)
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
//
Consumer: mockConsumer,
}
interruptChannel := make(chan os.Signal, 1)
+ _, cancel := context.WithCancel(context.Background())
+ defer cancel()
go func() {
time.Sleep(500 * time.Millisecond)
interruptChannel <- os.Interrupt
}()
-
done := make(chan bool)
go func() {
- handleShutdown(mockKafkaConsumer, interruptChannel)
+ handleShutdown(mockKafkaConsumer, interruptChannel, cancel)
done <- true
}()
return false // Simulate successful registration
}
- handleMessagesFunc = func(kc *kafkacomm.KafkaConsumer, sender *publisher.RealPdpStatusSender) {
+ handleMessagesFunc = func(ctx context.Context, kc *kafkacomm.KafkaConsumer, sender *publisher.RealPdpStatusSender) {
return
}
// Mock handleShutdown
interruptChannel := make(chan os.Signal, 1)
- handleShutdownFunc = func(kc *kafkacomm.KafkaConsumer, interruptChan chan os.Signal) {
+ handleShutdownFunc = func(kc *kafkacomm.KafkaConsumer, interruptChan chan os.Signal, cancel context.CancelFunc) {
interruptChannel <- os.Interrupt
+ cancel()
}
// Run main function in a goroutine
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
// Package consts provides constant values used throughout the policy-opa-pdp service.
// OkCode - The Code for HealthCheck response
// HealthCheckMessage - The Healtcheck Message
var (
- LogFilePath = "/var/logs/logs.log"
- LogMaxSize = 10
- LogMaxBackups = 3
- OpasdkConfigPath = "/app/config/config.json"
- Opa = "/app/opa"
- BuildBundle = "build"
- Policies = "/app/policies"
- Data = "/app/policies/data"
- Output = "-o"
- BundleTarGz = "bundle.tar.gz"
- BundleTarGzFile = "/app/bundles/bundle.tar.gz"
- PdpGroup = "defaultGroup"
+ LogFilePath = "/var/logs/logs.log"
+ LogMaxSize = 10
+ LogMaxBackups = 3
+ OpasdkConfigPath = "/app/config/config.json"
+ Opa = "/app/opa"
+ BuildBundle = "build"
+ Policies = "/opt/policies"
+ Data = "/opt/data"
+ Output = "-o"
+ BundleTarGz = "bundle.tar.gz"
+ BundleTarGzFile = "/app/bundles/bundle.tar.gz"
+ PdpGroup = "opaGroup"
+ //This is a workaround as currently opa-pdp is not defined in the PapDB defaultGroup configuration and creating it manually overrides the existing configuration, so currently PdpGroup is opaGroup and it will be changed to defaultGroup once added in the configuration.
PdpType = "opa"
ServerPort = ":8282"
SERVER_WAIT_UP_TIME = 5
// 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===================================
// Package bundleserver provides functionalities for serving and building OPA bundles.
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
//
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
// Package decision provides functionalities for handling decision requests using OPA (Open Policy Agent).
"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 decision response based on the provided parameters
-func createSuccessDecisionResponse(statusMessage, decision, policyName string) *oapicodegen.OPADecisionResponse {
+func createSuccessDecisionResponse(statusMessage, decision, policyName string, output map[string]interface{}) *oapicodegen.OPADecisionResponse {
return &oapicodegen.OPADecisionResponse{
StatusMessage: &statusMessage,
Decision: (*oapicodegen.OPADecisionResponseDecision)(&decision),
PolicyName: &policyName,
+ Output: &output,
}
}
log.Debugf("SDK making a decision")
options := sdk.DecisionOptions{Path: *decisionReq.PolicyName, Input: decisionReq.Input}
+
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 err != nil {
if strings.Contains(err.Error(), "opa_undefined_error") {
- decisionRes := createSuccessDecisionResponse(err.Error(), string(oapicodegen.INDETERMINATE), *decisionReq.PolicyName)
+ decisionRes := createSuccessDecisionResponse(err.Error(), string(oapicodegen.INDETERMINATE),
+ *decisionReq.PolicyName, nil)
writeOpaJSONResponse(res, http.StatusOK, *decisionRes)
metrics.IncrementIndeterminantDecisionsCount()
return
}
}
- // Check the decision result
- if decisionExcult, ok := decision.Result.(bool); !ok || !decisionExcult {
- decisionRes := createSuccessDecisionResponse("OPA Denied", string(oapicodegen.DENY), *decisionReq.PolicyName)
+ 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)
+ return
+ }
+
+ // If "allow" is false
+ decisionRes := createSuccessDecisionResponse("OPA Denied", string(oapicodegen.DENY), *decisionReq.PolicyName, nil)
metrics.IncrementDenyDecisionsCount()
writeOpaJSONResponse(res, http.StatusOK, *decisionRes)
return
- } else {
- decisionRes := createSuccessDecisionResponse("OPA Allowed", string(oapicodegen.PERMIT), *decisionReq.PolicyName)
- metrics.IncrementPermitDecisionsCount()
+
+ 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
+ }
+
+ }
+
+ // 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)
+ } else {
+ decisionRes := createSuccessDecisionResponse(
+ "No Decision: Result is Empty",
+ string(oapicodegen.NOTAPPLICABLE),
+ *decisionReq.PolicyName, nil)
+ metrics.IncrementQueryFailureCount()
+ writeOpaJSONResponse(res, http.StatusOK, *decisionRes)
+ }
+ return
+
+ default:
+ // Handle unexpected types in decision.Result
+ decisionRes := createSuccessDecisionResponse("Invalid decision result format", string(oapicodegen.DENY), *decisionReq.PolicyName, nil)
+ metrics.IncrementDenyDecisionsCount()
writeOpaJSONResponse(res, http.StatusOK, *decisionRes)
+ return
+ }
+
+}
+
+// Function to apply policy filter to decision result
+func applyPolicyFilter(result map[string]interface{}, filters []string) interface{} {
+
+ // Assuming filter matches specific keys or values
+ filteredOutput := make(map[string]interface{})
+ for key, value := range result {
+ for _, filter := range filters {
+ if strings.Contains(key, filter) {
+ filteredOutput[key] = value
+ break
+ }
+
+ }
}
+
+ return filteredOutput
}
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
//
"os"
"policy-opa-pdp/consts"
"policy-opa-pdp/pkg/model"
+ "policy-opa-pdp/pkg/model/oapicodegen"
"policy-opa-pdp/pkg/pdpstate"
"testing"
assert.Equal(t, http.StatusInternalServerError, rec.Code)
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
+}
+
+// Utility function to return a pointer to a map
+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"}),
+ }
+
+ 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"`)
+}
+
+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"),
+ }
+
+ writeErrorJSONResponse(rec, http.StatusBadRequest, "Bad Request", errorResponse)
+
+ assert.Equal(t, http.StatusBadRequest, rec.Code)
+ assert.Contains(t, rec.Body.String(), `"errorMessage":"Bad Request"`)
+}
+
+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)
+
+ // 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")
+
+ // Check the Output field
+ assert.Equal(t, *response.Output, output, "Output should match")
+}
+
+func TestApplyPolicyFilter(t *testing.T) {
+ originalPolicy := map[string]interface{}{
+ "policy1": map[string]interface{}{"key1": "value1"},
+ "policy2": map[string]interface{}{"key2": "value2"},
+ }
+ filter := []string{"policy1"}
+ result := applyPolicyFilter(originalPolicy, filter)
+
+ assert.NotNil(t, result)
+ assert.Len(t, result, 1)
+ assert.Contains(t, result, "policy1")
+}
+
+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")
+}
+
+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"},
+ }
+
+ // Create a mock HTTP response writer
+ res := httptest.NewRecorder()
+
+ // Call the function
+ writeOpaJSONResponse(res, http.StatusOK, decisionRes)
+
+ // Assert HTTP status
+ if res.Code != http.StatusOK {
+ t.Errorf("Expected status %d, got %d", http.StatusOK, res.Code)
+ }
+
+ // Assert headers
+ if res.Header().Get("Content-Type") != "application/json" {
+ t.Errorf("Expected Content-Type 'application/json', got '%s'", res.Header().Get("Content-Type"))
+ }
+
+ // Assert body
+ var result oapicodegen.OPADecisionResponse
+ 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)
+ }
+}
+
+func TestWriteOpaJSONResponse_EncodingError(t *testing.T) {
+ // 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)},
+ }
+
+ // Create a mock HTTP response writer
+ res := httptest.NewRecorder()
+
+ // Call the function
+ writeOpaJSONResponse(res, http.StatusInternalServerError, decisionRes)
+
+ // Assert HTTP status
+ if res.Code != http.StatusInternalServerError {
+ t.Errorf("Expected status %d, got %d", http.StatusInternalServerError, res.Code)
+ }
+
+ // Assert error message in body
+ if !bytes.Contains(res.Body.Bytes(), []byte("json: unsupported type")) {
+ t.Errorf("Expected encoding error message, got '%s'", res.Body.String())
+ }
+}
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
// Package healthcheck provides functionalities for handling health check requests.
+// -
+// ========================LICENSE_START=================================
+// Copyright (C) 2024: 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===================================
+
+// Package healthcheck provides functionalities for handling health check requests.
+// This package includes a function to handle HTTP requests for health checks
+// and respond with the health status of the service.
package healthcheck
import (
assert.Equal(t, pdpattributes.PdpName, *response.Name)
assert.Equal(t, "self", *response.Url)
assert.True(t, *response.Healthy)
- assert.Equal(t,int32(200), *response.Code)
+ assert.Equal(t, int32(200), *response.Code)
assert.Equal(t, "alive", *response.Message)
}
}
+func TestHealthCheckHandler_ValidUUID(t *testing.T) {
+ // Prepare a request with a valid UUID in the header
+ req := httptest.NewRequest(http.MethodGet, "/healthcheck", nil)
+ validUUID := "123e4567-e89b-12d3-a456-426614174000"
+ req.Header.Set("X-ONAP-RequestID", validUUID)
+ w := httptest.NewRecorder()
+
+ // Call the HealthCheckHandler
+ HealthCheckHandler(w, req)
+
+ // Check if the status code is OK (200)
+ assert.Equal(t, http.StatusOK, w.Code)
+
+ // Check the response headers
+ assert.Equal(t, validUUID, w.Header().Get("X-ONAP-RequestID"))
+
+ // Check the response body
+ var response oapicodegen.HealthCheckReport
+ err := json.NewDecoder(w.Body).Decode(&response)
+ assert.NoError(t, err)
+ assert.Equal(t, pdpattributes.PdpName, *response.Name)
+ assert.Equal(t, "self", *response.Url)
+ assert.True(t, *response.Healthy)
+ assert.Equal(t, int32(200), *response.Code)
+ assert.Equal(t, "alive", *response.Message)
+}
+
+func TestHealthCheckHandler_InvalidUUID(t *testing.T) {
+ // Prepare a request with an invalid UUID in the header
+ req := httptest.NewRequest(http.MethodGet, "/healthcheck", nil)
+ req.Header.Set("X-ONAP-RequestID", "invalid-uuid")
+ w := httptest.NewRecorder()
+
+ // Call the HealthCheckHandler
+ HealthCheckHandler(w, req)
+
+ // Check if the status code is OK (200)
+ assert.Equal(t, http.StatusOK, w.Code)
+
+ // Check the fallback request ID
+ assert.Equal(t, "000000000000", w.Header().Get("X-ONAP-RequestID"))
+}
+
+func TestHealthCheckHandler_MissingUUID(t *testing.T) {
+ // Prepare a request with no UUID header
+ req := httptest.NewRequest(http.MethodGet, "/healthcheck", nil)
+ w := httptest.NewRecorder()
+
+ // Call the HealthCheckHandler
+ HealthCheckHandler(w, req)
+
+ // Check if the status code is OK (200)
+ assert.Equal(t, http.StatusOK, w.Code)
+
+ // Check the fallback request ID
+ assert.Equal(t, "000000000000", w.Header().Get("X-ONAP-RequestID"))
+}
+
+func TestHealthCheckHandler_EmptyResponseBody(t *testing.T) {
+ // Simulate a case where the handler fails to set the response body
+ EmptyResponseHandler := func(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(http.StatusOK)
+ }
+
+ // Prepare a request to the health check endpoint
+ req := httptest.NewRequest(http.MethodGet, "/healthcheck", nil)
+ w := httptest.NewRecorder()
+
+ // Call the modified handler
+ EmptyResponseHandler(w, req)
+
+ // Check if the status code is OK (200)
+ assert.Equal(t, http.StatusOK, w.Code)
+
+ // Try decoding the empty body
+ var response oapicodegen.HealthCheckReport
+ err := json.NewDecoder(w.Body).Decode(&response)
+ assert.Error(t, err)
+}
+
func strPtr(s string) *string {
- return &s
+ return &s
}
func boolPtr(b bool) *bool {
- return &b
+ return &b
}
func int32Ptr(i int32) *int32 {
- return &i
+ return &i
}
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
// The handler package is responsible for processing messages from Kafka, specifically targeting the OPA
package handler
import (
+ "context"
"encoding/json"
"policy-opa-pdp/consts"
"policy-opa-pdp/pkg/kafkacomm"
"policy-opa-pdp/pkg/kafkacomm/publisher"
"policy-opa-pdp/pkg/log"
"policy-opa-pdp/pkg/pdpattributes"
+ "sync"
)
+var (
+ shutdownFlag bool
+ mu sync.Mutex
+)
+
+// SetShutdownFlag sets the shutdown flag
+func SetShutdownFlag() {
+ mu.Lock()
+ shutdownFlag = true
+ mu.Unlock()
+}
+
+// IsShutdown checks if the consumer has already been shut down
+func IsShutdown() bool {
+ mu.Lock()
+ defer mu.Unlock()
+ return shutdownFlag
+}
+
type OpaPdpMessage struct {
Name string `json:"name"` // Name of the PDP (optional for broadcast messages).
MessageType string `json:"MessageName"` // Type of the message (e.g., PDP_UPDATE, PDP_STATE_CHANGE, etc.)
// Handles incoming Kafka messages, validates their relevance to the current PDP,
// and dispatches them for further processing based on their type.
-func PdpMessageHandler(kc *kafkacomm.KafkaConsumer, topic string, p publisher.PdpStatusSender) error {
+func PdpMessageHandler(ctx context.Context, kc *kafkacomm.KafkaConsumer, topic string, p publisher.PdpStatusSender) error {
log.Debug("Starting PDP Message Listener.....")
var stopConsuming bool
for !stopConsuming {
- message, err := kafkacomm.ReadKafkaMessages(kc)
- if err != nil {
- log.Warnf("Failed to Read Kafka Messages: %v\n", err)
- continue
- }
- log.Debugf("[IN|KAFKA|%s]\n%s", topic, string(message))
-
- if message != nil {
-
- var opaPdpMessage OpaPdpMessage
-
- err = json.Unmarshal(message, &opaPdpMessage)
+ select {
+ case <-ctx.Done():
+ log.Debug("Stopping PDP Listener.....")
+ return nil
+ stopConsuming = true ///Loop Exits
+ default:
+ message, err := kafkacomm.ReadKafkaMessages(kc)
if err != nil {
- log.Warnf("Failed to UnMarshal Messages: %v\n", err)
continue
}
+ log.Debugf("[IN|KAFKA|%s]\n%s", topic, string(message))
- if !checkIfMessageIsForOpaPdp(opaPdpMessage) {
-
- log.Warnf("Not a valid Opa Pdp Message")
- continue
- }
+ if message != nil {
- switch opaPdpMessage.MessageType {
+ var opaPdpMessage OpaPdpMessage
- case "PDP_UPDATE":
- err = PdpUpdateMessageHandler(message, p)
+ err = json.Unmarshal(message, &opaPdpMessage)
if err != nil {
- log.Warnf("Error processing Update Message: %v", err)
+ log.Warnf("Failed to UnMarshal Messages: %v\n", err)
+ continue
}
- case "PDP_STATE_CHANGE":
- err = PdpStateChangeMessageHandler(message, p)
- if err != nil {
- log.Warnf("Error processing Update Message: %v", err)
+ if !checkIfMessageIsForOpaPdp(opaPdpMessage) {
+
+ log.Warnf("Not a valid Opa Pdp Message")
+ continue
}
- case "PDP_STATUS":
- log.Debugf("discarding event of type PDP_STATUS")
- continue
- default:
- log.Errorf("This is not a valid Message Type: %s", opaPdpMessage.MessageType)
- continue
+ switch opaPdpMessage.MessageType {
- }
+ case "PDP_UPDATE":
+ err = PdpUpdateMessageHandler(message, p)
+ if err != nil {
+ log.Warnf("Error processing Update Message: %v", err)
+ }
+ case "PDP_STATE_CHANGE":
+ err = PdpStateChangeMessageHandler(message, p)
+ if err != nil {
+ log.Warnf("Error processing Update Message: %v", err)
+ }
+
+ case "PDP_STATUS":
+ log.Debugf("discarding event of type PDP_STATUS")
+ continue
+ default:
+ log.Errorf("This is not a valid Message Type: %s", opaPdpMessage.MessageType)
+ continue
+
+ }
+
+ }
}
+
}
return nil
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
//
import (
"github.com/stretchr/testify/assert"
+ "policy-opa-pdp/consts"
"policy-opa-pdp/pkg/pdpattributes"
"testing"
+ // "context"
+ // "encoding/json"
+ // "errors"
+ // "policy-opa-pdp/pkg/kafkacomm/mocks"
)
/*
opapdpMessage.Name = "opa-3a318049-813f-4172-b4d3-7d4f466e5b80"
opapdpMessage.MessageType = "PDP_STATUS"
- opapdpMessage.PdpGroup = "defaultGroup"
+ opapdpMessage.PdpGroup = "opaGroup"
opapdpMessage.PdpSubgroup = "opa"
assert.False(t, checkIfMessageIsForOpaPdp(opapdpMessage), "Its a valid Opa Pdp Message")
opapdpMessage.Name = ""
opapdpMessage.MessageType = "PDP_STATUS"
- opapdpMessage.PdpGroup = "defaultGroup"
+ opapdpMessage.PdpGroup = "opaGroup"
opapdpMessage.PdpSubgroup = "opa"
assert.False(t, checkIfMessageIsForOpaPdp(opapdpMessage), "Not a valid Opa Pdp Message")
opapdpMessage.Name = ""
opapdpMessage.MessageType = "PDP_STATUS"
- opapdpMessage.PdpGroup = "defaultGroup"
+ opapdpMessage.PdpGroup = "opaGroup"
opapdpMessage.PdpSubgroup = "opa"
pdpattributes.PdpSubgroup = "opa"
opapdpMessage.Name = ""
opapdpMessage.MessageType = "PDP_STATUS"
- opapdpMessage.PdpGroup = "defaultGroup"
+ opapdpMessage.PdpGroup = "opaGroup"
opapdpMessage.PdpSubgroup = "opa"
pdpattributes.PdpSubgroup = "opa"
opapdpMessage.Name = ""
opapdpMessage.MessageType = "PDP_STATUS"
- opapdpMessage.PdpGroup = "defaultGroup"
+ opapdpMessage.PdpGroup = "opaGroup"
opapdpMessage.PdpSubgroup = "o"
pdpattributes.PdpSubgroup = "opa"
assert.False(t, checkIfMessageIsForOpaPdp(opapdpMessage), "Not a valid Opa Pdp Message")
}
+
+func TestCheckIfMessageIsForOpaPdp_EmptyPdpSubgroupAndGroup(t *testing.T) {
+ var opapdpMessage OpaPdpMessage
+ opapdpMessage.Name = ""
+ opapdpMessage.MessageType = "PDP_STATUS"
+ opapdpMessage.PdpGroup = ""
+ opapdpMessage.PdpSubgroup = ""
+
+ assert.False(t, checkIfMessageIsForOpaPdp(opapdpMessage), "Message should be invalid when PdpGroup and PdpSubgroup are empty")
+}
+
+func TestCheckIfMessageIsForOpaPdp_ValidBroadcastMessage(t *testing.T) {
+ var opapdpMessage OpaPdpMessage
+ opapdpMessage.Name = ""
+ opapdpMessage.MessageType = "PDP_UPDATE"
+ opapdpMessage.PdpGroup = "opaGroup"
+ opapdpMessage.PdpSubgroup = ""
+
+ pdpattributes.PdpSubgroup = "opa"
+ consts.PdpGroup = "opaGroup"
+
+ assert.True(t, checkIfMessageIsForOpaPdp(opapdpMessage), "Valid broadcast message should pass the check")
+}
+
+func TestCheckIfMessageIsForOpaPdp_InvalidGroupMismatch(t *testing.T) {
+ var opapdpMessage OpaPdpMessage
+ opapdpMessage.Name = ""
+ opapdpMessage.MessageType = "PDP_STATUS"
+ opapdpMessage.PdpGroup = "wrongGroup"
+ opapdpMessage.PdpSubgroup = ""
+
+ consts.PdpGroup = "opaGroup"
+
+ assert.False(t, checkIfMessageIsForOpaPdp(opapdpMessage), "Message with mismatched PdpGroup should fail")
+}
+
+// Test SetShutdownFlag and IsShutdown
+func TestSetAndCheckShutdownFlag(t *testing.T) {
+ assert.False(t, IsShutdown(), "Shutdown flag should be false initially")
+
+ SetShutdownFlag()
+ assert.True(t, IsShutdown(), "Shutdown flag should be true after calling SetShutdownFlag")
+}
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
// will process the state change message from pap and send the pdp status response.
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
//
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
// will process the update message from pap and send the pdp status response.
-// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
//
"requestId":"41c117db-49a0-40b0-8586-5580d042d0a1",
"timestampMs":1730722305297,
"name":"opa-21cabb3e-f652-4ca6-b498-a77e62fcd059",
- "pdpGroup":"defaultGroup",
+ "pdpGroup":"opaGroup",
"pdpSubgroup":"opa"
}`
"requestId":"41c117db-49a0-40b0-8586-5580d042d0a1",
"timestampMs":1730722305297,
"name":"opa-21cabb3e-f652-4ca6-b498-a77e62fcd059",
- "pdpGroup":"defaultGroup"
+ "pdpGroup":"opaGroup"
}`
mockSender := new(mocks.PdpStatusSender)
"requestId":"41c117db-49a0-40b0-8586-5580d042d0a1",
"timestampMs":1730722305297,
"name":"opa-21cabb3e-f652-4ca6-b498-a77e62fcd059",
- "pdpGroup":"defaultGroup",
+ "pdpGroup":"opaGroup",
"pdpSubgroup":"opa"
}`
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
// kafkacomm package provides a structured way to create and manage Kafka consumers,
package kafkacomm
import (
+ "fmt"
"github.com/confluentinc/confluent-kafka-go/kafka"
"policy-opa-pdp/cfg"
"policy-opa-pdp/pkg/log"
+ "sync"
"time"
)
+var (
+ // Declare a global variable to hold the singleton KafkaConsumer
+ consumerInstance *KafkaConsumer
+ consumerOnce sync.Once // sync.Once ensures that the consumer is created only once
+)
+
// KafkaConsumerInterface defines the interface for a Kafka consumer.
type KafkaConsumerInterface interface {
Close() error
// Close closes the KafkaConsumer
func (kc *KafkaConsumer) Close() {
- kc.Consumer.Close()
+ if kc.Consumer != nil {
+ kc.Consumer.Close()
+ }
}
// Unsubscribe unsubscribes the KafkaConsumer
func (kc *KafkaConsumer) Unsubscribe() error {
- if err := kc.Consumer.Unsubscribe(); err != nil {
- log.Warnf("Error Unsubscribing :%v", err)
+ if kc.Consumer == nil {
+ return fmt.Errorf("Kafka Consumer is nil so cannot Unsubscribe")
+ }
+ err := kc.Consumer.Unsubscribe()
+ if err != nil {
+ log.Warnf("Error Unsubscribing: %v", err)
return err
}
- log.Debug("Unsubscribe From Topic")
+ log.Debug("Unsubscribed From Topic")
return nil
}
-// creates a new Kafka consumer and returns it
+// NewKafkaConsumer creates a new Kafka consumer and returns it
func NewKafkaConsumer() (*KafkaConsumer, error) {
- brokers := cfg.BootstrapServer
- groupid := cfg.GroupId
- topic := cfg.Topic
- useSASL := cfg.UseSASLForKAFKA
- username := cfg.KAFKA_USERNAME
- password := cfg.KAFKA_PASSWORD
+ // Initialize the consumer instance only once
+ consumerOnce.Do(func() {
+ log.Debugf("Creating Kafka Consumer singleton instance")
+ brokers := cfg.BootstrapServer
+ groupid := cfg.GroupId
+ topic := cfg.Topic
+ useSASL := cfg.UseSASLForKAFKA
+ username := cfg.KAFKA_USERNAME
+ password := cfg.KAFKA_PASSWORD
- // Add Kafka Connection Properties ....
- configMap := &kafka.ConfigMap{
- "bootstrap.servers": brokers,
- "group.id": groupid,
- "auto.offset.reset": "earliest",
- }
- //for STRIMZI-KAFKA in case sasl is enabled
- if useSASL == "true" {
- configMap.SetKey("sasl.mechanism", "SCRAM-SHA-512")
- configMap.SetKey("sasl.username", username)
- configMap.SetKey("sasl.password", password)
- configMap.SetKey("security.protocol", "SASL_PLAINTEXT")
- }
+ // Add Kafka connection properties
+ configMap := &kafka.ConfigMap{
+ "bootstrap.servers": brokers,
+ "group.id": groupid,
+ "auto.offset.reset": "latest",
+ }
- // create new Kafka Consumer
- consumer, err := kafka.NewConsumer(configMap)
- if err != nil {
- log.Warnf("Error creating consumer: %v\n", err)
- return nil, err
- }
- //subscribe to topic
- err = consumer.SubscribeTopics([]string{topic}, nil)
- if err != nil {
- log.Warnf("Error subcribing to topic: %v\n", err)
- return nil, err
+ // If SASL is enabled, add SASL properties
+ if useSASL == "true" {
+ configMap.SetKey("sasl.mechanism", "SCRAM-SHA-512")
+ configMap.SetKey("sasl.username", username)
+ configMap.SetKey("sasl.password", password)
+ configMap.SetKey("security.protocol", "SASL_PLAINTEXT")
+ configMap.SetKey("session.timeout.ms", "30000")
+ configMap.SetKey("max.poll.interval.ms", "300000")
+ configMap.SetKey("enable.partition.eof", true)
+ configMap.SetKey("enable.auto.commit", true)
+ // configMap.SetKey("debug", "all") // Uncomment for debug
+ }
+
+ // Create a new Kafka consumer
+ consumer, err := kafka.NewConsumer(configMap)
+ if err != nil {
+ log.Warnf("Error creating consumer: %v", err)
+ return
+ }
+ if consumer == nil {
+ log.Warnf("Kafka Consumer is nil after creation")
+ return
+ }
+
+ // Subscribe to the topic
+ err = consumer.SubscribeTopics([]string{topic}, nil)
+ if err != nil {
+ log.Warnf("Error subscribing to topic: %v", err)
+ return
+ }
+ log.Debugf("Topic Subscribed: %v", topic)
+
+ // Assign the consumer instance
+ consumerInstance = &KafkaConsumer{Consumer: consumer}
+ log.Debugf("Created SIngleton consumer instance")
+ })
+
+ // Return the singleton consumer instance
+ if consumerInstance == nil {
+ return nil, fmt.Errorf("Kafka Consumer instance not created")
}
- log.Debugf("Topic Subscribed... : %v", topic)
- return &KafkaConsumer{Consumer: consumer}, nil
+ return consumerInstance, nil
}
-// gets the Kafka messages on the subscribed topic
+// ReadKafkaMessages gets the Kafka messages on the subscribed topic
func ReadKafkaMessages(kc *KafkaConsumer) ([]byte, error) {
- msg, err := kc.Consumer.ReadMessage(-1)
+ msg, err := kc.Consumer.ReadMessage(100 * time.Millisecond)
if err != nil {
- log.Warnf("Error reading Kafka message: %v", err)
return nil, err
}
return msg.Value, nil
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
//
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
// Package kafkacomm provides utilities for producing messages to a Kafka topic
import (
"github.com/confluentinc/confluent-kafka-go/kafka"
+ "log"
"policy-opa-pdp/cfg"
"sync"
- "log"
)
type KafkaProducerInterface interface {
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
//
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
// The publisher package is responsible for managing periodic heartbeat messages for the
if ticker != nil {
ticker.Stop()
}
- // StopTicker()
+ // StopTicker()
currentInterval = intervalMs
ticker = time.NewTicker(time.Duration(intervalMs) * time.Millisecond)
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
//
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
// allows to send the pdp registartion message with unique transaction id and timestamp to topic
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
//
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
//
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
//
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
//
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
//
+// -
+// ========================LICENSE_START=================================
+// Copyright (C) 2024: 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===================================
+//
+
package metrics
import "sync"
-//global counter variables
+// global counter variables
var IndeterminantDecisionsCount int64
var PermitDecisionsCount int64
var DenyDecisionsCount int64
var TotalErrorCount int64
+var QuerySuccessCount int64
+var QueryFailureCount int64
var mu sync.Mutex
// Increment counter
defer mu.Unlock()
return &TotalErrorCount
}
+
+// Increment counter
+func IncrementQuerySuccessCount() {
+ mu.Lock()
+ QuerySuccessCount++
+ mu.Unlock()
+}
+
+// returns pointer to the counter
+func TotalQuerySuccessCountRef() *int64 {
+ mu.Lock()
+ defer mu.Unlock()
+ return &QuerySuccessCount
+
+}
+
+// Increment counter
+func IncrementQueryFailureCount() {
+ mu.Lock()
+ QueryFailureCount++
+ mu.Unlock()
+}
+
+// returns pointer to the counter
+func TotalQueryFailureCountRef() *int64 {
+ mu.Lock()
+ defer mu.Unlock()
+ return &QueryFailureCount
+
+}
+// -
+// ========================LICENSE_START=================================
+// Copyright (C) 2024: 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===================================
+//
+
package metrics
import (
+// -
+// ========================LICENSE_START=================================
+// Copyright (C) 2024: 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===================================
+//
+
// Handles an HTTP request to fetch the current system statistics.
// It aggregates various decision counts (e.g., indeterminate, permit, deny)
// and error counts into a structured response and sends it back to the client in JSON format.
statReport.PermitDecisionsCount = PermitDecisionsCountRef()
statReport.DenyDecisionsCount = DenyDecisionsCountRef()
statReport.TotalErrorCount = TotalErrorCountRef()
+ statReport.QuerySuccessCount = TotalQuerySuccessCountRef()
+ statReport.QueryFailureCount = TotalQueryFailureCountRef()
// not implemented hardcoding the values to zero
// will be implemeneted in phase-2
+// -
+// ========================LICENSE_START=================================
+// Copyright (C) 2024: 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===================================
+//
+
package metrics
import (
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
//
-
+
package model
-
+
type HealthCheckResponse struct {
- Name string `json:"name"`
- Url string `json:"url"`
- Healthy bool `json:"healthy"`
- Code int `json:"code"`
- Message string `json:"message"`
+ Name string `json:"name"`
+ Url string `json:"url"`
+ Healthy bool `json:"healthy"`
+ Code int `json:"code"`
+ Message string `json:"message"`
}
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
// Defines structure for messages exchanged between PDP and PAP
// https://github.com/onap/policy-models
// models-pdp/src/main/java/org/onap/policy/models/pdp/concepts/PdpStatus.java
type PdpStatus struct {
- MessageType PdpMessageType `json:"messageName"`
- PdpType string `json:"pdpType"`
- State PdpState `json:"state"`
- Healthy PdpHealthStatus `json:"healthy"`
- Description string `json:"description"`
- PdpResponse *PdpResponseDetails `json:"response"`
- Policies []ToscaConceptIdentifier `json:"policies"`
- Name string `json:"name"`
- RequestID string `json:"requestId"`
- PdpGroup string `json:"pdpGroup"`
- PdpSubgroup *string `json:"pdpSubgroup"`
- TimestampMs string `json:"timestampMs"`
- DeploymentInstanceInfo string `json:"deploymentInstanceInfo"`
+ MessageType PdpMessageType `json:"messageName"`
+ PdpType string `json:"pdpType"`
+ State PdpState `json:"state"`
+ Healthy PdpHealthStatus `json:"healthy"`
+ Description string `json:"description"`
+ PdpResponse *PdpResponseDetails `json:"response"`
+ Policies []ToscaConceptIdentifier `json:"policies"`
+ Name string `json:"name"`
+ RequestID string `json:"requestId"`
+ PdpGroup string `json:"pdpGroup"`
+ PdpSubgroup *string `json:"pdpSubgroup"`
+ TimestampMs string `json:"timestampMs"`
+ DeploymentInstanceInfo string `json:"deploymentInstanceInfo"`
}
// PDP_UPDATE sent by PAP to PDP.
// https://github.com/onap/policy-models
// models-pdp/src/main/java/org/onap/policy/models/pdp/concepts/PdpUpdate.java
type PdpUpdate struct {
- Source string `json:"source" validate:"required"`
- PdpHeartbeatIntervalMs int64 `json:"pdpHeartbeatIntervalMs" validate:"required"`
- MessageType string `json:"messageName" validate:"required"`
- PoliciesToBeDeloyed []string `json:"policiesToBeDeployed" validate:"required"`
- policiesToBeUndeployed []ToscaConceptIdentifier `json:"policiesToBeUndeployed"`
- Name string `json:"name" validate:"required"`
- TimestampMs int64 `json:"timestampMs" validate:"required"`
- PdpGroup string `json:"pdpGroup" validate:"required"`
- PdpSubgroup string `json:"pdpSubgroup" validate:"required"`
- RequestId string `json:"requestId" validate:"required"`
+ Source string `json:"source" validate:"required"`
+ PdpHeartbeatIntervalMs int64 `json:"pdpHeartbeatIntervalMs" validate:"required"`
+ MessageType string `json:"messageName" validate:"required"`
+ PoliciesToBeDeloyed []string `json:"policiesToBeDeployed" validate:"required"`
+ policiesToBeUndeployed []ToscaConceptIdentifier `json:"policiesToBeUndeployed"`
+ Name string `json:"name" validate:"required"`
+ TimestampMs int64 `json:"timestampMs" validate:"required"`
+ PdpGroup string `json:"pdpGroup" validate:"required"`
+ PdpSubgroup string `json:"pdpSubgroup" validate:"required"`
+ RequestId string `json:"requestId" validate:"required"`
}
// PDP_STATE_CHANGE sent by PAP to PDP.
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
//
-// Package api provides primitives to interact with the openapi HTTP API.
+// Package oapicodegen provides primitives to interact with the openapi HTTP API.
//
// Code generated by github.com/deepmap/oapi-codegen version v1.16.3 DO NOT EDIT.
package oapicodegen
const (
DENY OPADecisionResponseDecision = "DENY"
INDETERMINATE OPADecisionResponseDecision = "INDETERMINATE"
+ NOTAPPLICABLE OPADecisionResponseDecision = "NOTAPPLICABLE"
PERMIT OPADecisionResponseDecision = "PERMIT"
)
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"`
// TimeOffset Time offset in hours and minutes, e.g., '+02:00' or '-05:00'
// 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"`
}
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"`
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
// the possible values for health status of PDP.
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
//
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
// represent PDP response details.
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
//
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
// hold the possible values for state of PDP.
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
//
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
// Identifies a concept. Both the name and version must be non-null.
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
//
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
// The opasdk package provides functionalities for integrating with the Open Policy Agent
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
//
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
// The pdpattributes package provides utilities for managing and configuring attributes related to the
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
//
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
// The pdpstate package manages the state of the Policy Decision Point (PDP), allowing for dynamic updates
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
//
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
// Package utils provides common functionalities
// -
// ========================LICENSE_START=================================
-// Copyright (C) 2024: Deutsche Telecom
+// Copyright (C) 2024: Deutsche Telekom
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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===================================
package utils
{"decision":"DENY","policyName":"organization/allow","statusMessage":"OPA Denied"}
+## DENY for policy:abac(output)
+
+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/pdpx/v1/decision
+{"decision":"DENY","output":{},"policyName":"abac","statusMessage":"OPA Denied"}
+
+## PERMIT for policy:abac
+
+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/pdpx/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"}
+
+## 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/pdpx/v1/decision
+{"decision":"PERMIT","output":{"has_zone_access":[{"access":"granted","user":"user1"}]},"policyName":"zone","statusMessage":"OPA Allowed"}
+
+## DENY 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": ["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/pdpx/v1/decision
+{"decision":"DENY","output":{"has_zone_access":[]},"policyName":"zone","statusMessage":"OPA Denied"}
+
+## 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":"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/pdpx/v1/decision
+
+{"decision":"PERMIT","output":{"user_has_vehicle_access":[{"status":"available","type":"car"}]},"policyName":"vehicle","statusMessage":"OPA Allowed"}
+
+## 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":"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/pdpx/v1/decision
+
+{"decision":"PERMIT","output":{"has_access_to_file":[{"owner":"user1","size":"10MB"}]},"policyName":"docs","statusMessage":"OPA Allowed"}`
+
+## 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":"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/pdpx/v1/decision
+
+{"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/pdpx/v1/healthcheck
--- /dev/null
+{
+ "sensor_data": [
+ {
+ "id": "0001",
+ "location": "Sri Lanka",
+ "temperature": "28 C",
+ "precipitation": "1000 mm",
+ "windspeed": "5.5 m/s",
+ "humidity": "40%",
+ "particle_density": "1.3 g/l",
+ "timestamp": "2024-02-26"
+ },
+ {
+ "id": "0002",
+ "location": "Colombo",
+ "temperature": "30 C",
+ "precipitation": "1200 mm",
+ "windspeed": "6.0 m/s",
+ "humidity": "45%",
+ "particle_density": "1.5 g/l",
+ "timestamp": "2024-02-26"
+ },
+ {
+ "id": "0003",
+ "location": "Kandy",
+ "temperature": "25 C",
+ "precipitation": "800 mm",
+ "windspeed": "4.5 m/s",
+ "humidity": "60%",
+ "particle_density": "1.1 g/l",
+ "timestamp": "2024-02-26"
+ },
+ {
+ "id": "0004",
+ "location": "Galle",
+ "temperature": "35 C",
+ "precipitation": "500 mm",
+ "windspeed": "7.2 m/s",
+ "humidity": "30%",
+ "particle_density": "1.8 g/l",
+ "timestamp": "2024-02-27"
+ },
+ {
+ "id": "0005",
+ "location": "Jaffna",
+ "temperature": "-5 C",
+ "precipitation": "300 mm",
+ "windspeed": "3.8 m/s",
+ "humidity": "20%",
+ "particle_density": "0.9 g/l",
+ "timestamp": "2024-02-27"
+ },
+ {
+ "id": "0006",
+ "location": "Trincomalee",
+ "temperature": "20 C",
+ "precipitation": "1000 mm",
+ "windspeed": "5.0 m/s",
+ "humidity": "55%",
+ "particle_density": "1.2 g/l",
+ "timestamp": "2024-02-28"
+ },
+ {
+ "id": "0007",
+ "location": "Nuwara Eliya",
+ "temperature": "25 C",
+ "precipitation": "600 mm",
+ "windspeed": "4.0 m/s",
+ "humidity": "50%",
+ "particle_density": "1.3 g/l",
+ "timestamp": "2024-02-28"
+ },
+ {
+ "id": "0008",
+ "location": "Anuradhapura",
+ "temperature": "28 C",
+ "precipitation": "700 mm",
+ "windspeed": "5.8 m/s",
+ "humidity": "40%",
+ "particle_density": "1.4 g/l",
+ "timestamp": "2024-02-29"
+ },
+ {
+ "id": "0009",
+ "location": "Matara",
+ "temperature": "32 C",
+ "precipitation": "900 mm",
+ "windspeed": "6.5 m/s",
+ "humidity": "65%",
+ "particle_density": "1.6 g/l",
+ "timestamp": "2024-02-29"
+ }
+ ]
+}
--- /dev/null
+{
+ "account_attributes":{
+ "11111":{
+ "owner":"alice",
+ "amount":10000
+ },
+ "22222":{
+ "owner":"bob",
+ "amount":10000
+ },
+ "33333":{
+ "owner":"cam",
+ "amount":10000
+ }
+ }
+}
--- /dev/null
+{
+ "user_roles": {
+ "alice": [
+ "admin"
+ ],
+ "bob": [
+ "editor"
+ ],
+ "charlie": [
+ "viewer"
+ ]
+ },
+ "role_permissions": {
+ "admin": {
+ "actions": [
+ "read",
+ "write",
+ "delete"
+ ],
+ "resources": [
+ "server",
+ "database"
+ ]
+ },
+ "editor": {
+ "actions": [
+ "read",
+ "write"
+ ],
+ "resources": [
+ "server"
+ ]
+ },
+ "viewer": {
+ "actions": [
+ "read"
+ ],
+ "resources": [
+ "server"
+ ]
+ }
+ }
+}
--- /dev/null
+{
+ "acls": [
+ {
+ "user": "alice",
+ "actions": [
+ "edit",
+ "read"
+ ],
+ "component": "component_A",
+ "project": "project_A",
+ "organization": "org_A"
+ },
+ {
+ "user": "bob",
+ "actions": ["read"],
+ "organization": "org_A"
+ },
+ {
+ "user": "bob",
+ "action": ["edit"],
+ "component": "component_A",
+ "project": "project_B",
+ "organization": "org_A"
+ },
+ {
+ "user": "charlie",
+ "action": ["read"],
+ "project": "project_B",
+ "organization": "org_A"
+ }
+ ]
+}
--- /dev/null
+{
+ "user_roles": {
+ "alice": [
+ "admin"
+ ],
+ "bob": [
+ "employee",
+ "billing"
+ ],
+ "eve": [
+ "customer"
+ ]
+ },
+ "role_grants": {
+ "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"
+ }
+ ],
+ "billing": [
+ {
+ "action": "read",
+ "type": "finance"
+ },
+ {
+ "action": "update",
+ "type": "finance"
+ }
+ ]
+ }
+}
+
- ./policy-new.yaml:/app/policy-new.yaml
- type: bind
source: ./policies
- target: /app/policies
+ target: /opt/policies
+ - type: bind
+ source: ./data
+ target: /opt/data
environment:
LOG_LEVEL: debug
GROUPID: opa-pdp
API_USER: policyadmin
API_PASSWORD: "zb!XztG34"
+ JAASLOGIN: org.apache.kafka.common.security.scram.ScramLoginModule required username="policy-opa-pdp-ku" password="pzmdwfFvBhv21mSD7dieHoUZf2aobdqR"
entrypoint: sh wait_for_port.sh
command: [
'-c', './policy-opa-pdp.sh',