Refactoring log-protect for hiding sensitive data in logs 27/99827/4
authorJozsef Csongvai <jozsef.csongvai@bell.ca>
Thu, 19 Dec 2019 16:05:33 +0000 (11:05 -0500)
committerKAPIL SINGAL <ks220y@att.com>
Tue, 24 Dec 2019 14:55:41 +0000 (14:55 +0000)
Issue-ID: CCSDK-2010
Signed-off-by: Jozsef Csongvai <jozsef.csongvai@bell.ca>
Change-Id: I72a4d8d49a202cea0fa1a200c7466300de1ff0b0

ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionConstants.kt
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionService.kt
ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtils.kt
ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BluePrintConstants.kt
ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/common/ApplicationConstants.kt
ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintRuntimeService.kt
ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/PropertyDefinitionUtils.kt [new file with mode: 0644]
ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/test/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/PropertyDefinitionUtilsTest.kt [new file with mode: 0644]

index 14e60bc..51e93a3 100644 (file)
@@ -32,9 +32,11 @@ import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive
 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonType
 import org.onap.ccsdk.cds.controllerblueprints.core.checkNotEmpty
+import org.onap.ccsdk.cds.controllerblueprints.core.common.ApplicationConstants.LOG_REDACTED
 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeService
 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintTemplateService
 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
+import org.onap.ccsdk.cds.controllerblueprints.core.utils.PropertyDefinitionUtils.Companion.hasLogProtect
 import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment
 import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceDefinition
 import org.onap.ccsdk.cds.controllerblueprints.resource.dict.utils.BulkResourceSequencingUtils
@@ -395,7 +397,8 @@ open class ResourceResolutionServiceImpl(
             if (resourceResolution.status == BluePrintConstants.STATUS_SUCCESS) {
                 resourceAssignmentList.forEach {
                     if (compareOne(resourceResolution, it)) {
-                        log.info("Resource ({}) already resolve: value=({})", it.name, resourceResolution.value)
+                        log.info("Resource ({}) already resolved: value=({})", it.name,
+                            if (hasLogProtect(it.property)) LOG_REDACTED else resourceResolution.value)
 
                         // Make sure to recreate value as per the defined type.
                         val value = resourceResolution.value!!.asJsonType(it.property!!.type)
index b818cc2..a813c00 100644 (file)
@@ -31,6 +31,7 @@ import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintTypes
 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonType
 import org.onap.ccsdk.cds.controllerblueprints.core.checkFileExists
 import org.onap.ccsdk.cds.controllerblueprints.core.checkNotEmpty
+import org.onap.ccsdk.cds.controllerblueprints.core.common.ApplicationConstants.LOG_REDACTED
 import org.onap.ccsdk.cds.controllerblueprints.core.isComplexType
 import org.onap.ccsdk.cds.controllerblueprints.core.isNotEmpty
 import org.onap.ccsdk.cds.controllerblueprints.core.isNullOrMissing
@@ -40,6 +41,7 @@ import org.onap.ccsdk.cds.controllerblueprints.core.rootFieldsToMap
 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeService
 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonReactorUtils
 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
+import org.onap.ccsdk.cds.controllerblueprints.core.utils.PropertyDefinitionUtils.Companion.hasLogProtect
 import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment
 import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceDefinition
 import org.slf4j.LoggerFactory
@@ -159,9 +161,7 @@ class ResourceAssignmentUtils {
                         val type = nullToEmpty(it.property?.type).toLowerCase()
                         val value = useDefaultValueIfNull(it, rName)
                         val valueToPrint = getValueToLog(metadata, value)
-                        if (checkIfLogIsProtected(metadata)) {
-                            containsLogProtected = true
-                        }
+                        containsLogProtected = hasLogProtect(metadata)
                         logger.trace("Generating Resource name ($rName), type ($type), value ($valueToPrint)")
                         root.set(rName, value)
                     }
@@ -593,25 +593,7 @@ class ResourceAssignmentUtils {
             return (outputKeyMapping.size == 1)
         }
 
-        fun getValueToLog(metadata: MutableMap<String, String>?, value: Any): Any {
-            return if (checkIfLogIsProtected(metadata)) {
-                "******REDACTED******"
-            } else {
-                value
-            }
-        }
-
-        private fun checkIfLogIsProtected(metadata: MutableMap<String, String>?): Boolean {
-            var checkProtected = false
-            if (metadata != null &&
-                metadata.containsKey(ResourceResolutionConstants.RESOURCE_RESOLUTION_LOG_PROTECTED_METADATA)
-            ) {
-                val protectedMetadata = metadata[ResourceResolutionConstants.RESOURCE_RESOLUTION_LOG_PROTECTED_METADATA]
-                if (protectedMetadata == "yes" || protectedMetadata == "y") {
-                    checkProtected = true
-                }
-            }
-            return checkProtected
-        }
+        fun getValueToLog(metadata: MutableMap<String, String>?, value: Any): Any =
+                if (hasLogProtect(metadata)) LOG_REDACTED else value
     }
 }
index 571f0a1..5aaf6cc 100644 (file)
@@ -218,6 +218,8 @@ object BluePrintConstants {
 
     val USE_SCRIPT_COMPILE_CACHE: Boolean = (System.getenv("USE_SCRIPT_COMPILE_CACHE") ?: "true").toBoolean()
 
+    const val LOG_PROTECT: String = "log-protect"
+
     /** Cluster Properties */
     val CLUSTER_ENABLED = (System.getenv("CLUSTER_ENABLED") ?: "false").toBoolean()
     const val PROPERTY_CLUSTER_ID = "CLUSTER_ID"
index a6d2de4..a7ed577 100644 (file)
@@ -26,12 +26,14 @@ import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintError
 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonNode
 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonType
+import org.onap.ccsdk.cds.controllerblueprints.core.common.ApplicationConstants.LOG_REDACTED
 import org.onap.ccsdk.cds.controllerblueprints.core.data.ArtifactDefinition
 import org.onap.ccsdk.cds.controllerblueprints.core.data.NodeTemplate
 import org.onap.ccsdk.cds.controllerblueprints.core.data.PropertyDefinition
 import org.onap.ccsdk.cds.controllerblueprints.core.returnNullIfMissing
 import org.onap.ccsdk.cds.controllerblueprints.core.rootFieldsToMap
 import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintMetadataUtils
+import org.onap.ccsdk.cds.controllerblueprints.core.utils.PropertyDefinitionUtils.Companion.hasLogProtect
 import org.slf4j.LoggerFactory
 import java.io.File
 
@@ -452,7 +454,6 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl
 
     override fun setInputValue(propertyName: String, value: JsonNode) {
         val path = """${BluePrintConstants.PATH_INPUTS}${BluePrintConstants.PATH_DIVIDER}$propertyName"""
-        log.trace("setting input path ({}), values ({})", path, value)
         put(path, value)
     }
 
@@ -594,34 +595,31 @@ open class DefaultBluePrintRuntimeService(private var id: String, private var bl
     }
 
     override fun assignWorkflowInputs(workflowName: String, jsonNode: JsonNode) {
-        log.info("For workflow ($workflowName) driving input data from ($jsonNode)")
+        log.info("Deriving input data for workflow: ($workflowName)")
+
         val dynamicInputPropertiesName = "$workflowName-properties"
 
         bluePrintContext.workflowByName(workflowName).inputs
-            ?.forEach { propertyName, property ->
-                if (propertyName != dynamicInputPropertiesName) {
-                    val valueNode: JsonNode =
-                        jsonNode.at(BluePrintConstants.PATH_DIVIDER + propertyName).returnNullIfMissing()
-                            ?: property.defaultValue
-                            ?: NullNode.getInstance()
-                    log.trace("Setting input data - attribute:($propertyName) value:($valueNode)")
-                    setInputValue(propertyName, valueNode)
-                }
-            }
+                ?.filter { (propertyName, property) -> propertyName != dynamicInputPropertiesName }
+                ?.forEach { propertyName, property -> findAndSetInputValue(propertyName, property, jsonNode) }
         // Load Dynamic data Types
         jsonNode.get(dynamicInputPropertiesName)?.let {
-            bluePrintContext.dataTypeByName("dt-$dynamicInputPropertiesName")?.properties
-                ?.forEach { propertyName, property ->
-                    val valueNode: JsonNode =
-                        it.at(BluePrintConstants.PATH_DIVIDER + propertyName).returnNullIfMissing()
-                            ?: property.defaultValue
-                            ?: NullNode.getInstance()
-                    log.trace("Setting input data - attribute:($propertyName) value:($valueNode)")
-                    setInputValue(propertyName, valueNode)
-                }
+            bluePrintContext.dataTypeByName("dt-$dynamicInputPropertiesName")
+                    ?.properties
+                    ?.forEach { propertyName, property -> findAndSetInputValue(propertyName, property, it) }
         }
     }
 
+    private fun findAndSetInputValue(propertyName: String, property: PropertyDefinition, jsonNode: JsonNode) {
+        val valueNode = jsonNode.at(BluePrintConstants.PATH_DIVIDER + propertyName)
+                .returnNullIfMissing()
+                ?: property.defaultValue
+                ?: NullNode.getInstance()
+        val loggableValue = if (hasLogProtect(property)) LOG_REDACTED else valueNode.toString()
+        log.info("Setting input data - attribute:($propertyName) value:($loggableValue)")
+        setInputValue(propertyName, valueNode)
+    }
+
     override fun resolveWorkflowOutputs(workflowName: String): MutableMap<String, JsonNode> {
         log.info("resolveWorkflowOutputs for workflow($workflowName)")
         val outputs = bluePrintContext.workflowByName(workflowName).outputs ?: mutableMapOf()
diff --git a/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/PropertyDefinitionUtils.kt b/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/PropertyDefinitionUtils.kt
new file mode 100644 (file)
index 0000000..35f2f6d
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright © 2019 Bell Canada.
+ *
+ * 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.
+ */
+
+package org.onap.ccsdk.cds.controllerblueprints.core.utils
+
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants.LOG_PROTECT
+import org.onap.ccsdk.cds.controllerblueprints.core.data.PropertyDefinition
+
+class PropertyDefinitionUtils {
+    companion object {
+        fun hasLogProtect(metadata: MutableMap<String, String>?) = metadata?.get(LOG_PROTECT)
+                ?.let {
+                    when (it.toLowerCase()) {
+                        "true" -> true
+                        "yes" -> true
+                        "y" -> true
+                        else -> false
+                    }
+                } ?: false
+
+        fun hasLogProtect(propertyDefinition: PropertyDefinition?) = propertyDefinition
+                ?.let { p -> hasLogProtect(p.metadata) } ?: false
+    }
+}
diff --git a/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/test/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/PropertyDefinitionUtilsTest.kt b/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/test/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/PropertyDefinitionUtilsTest.kt
new file mode 100644 (file)
index 0000000..83764c5
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright © 2019 Bell Canada.
+ *
+ * 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.
+ */
+
+package org.onap.ccsdk.cds.controllerblueprints.core.utils
+
+import org.junit.Test
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants.LOG_PROTECT
+import org.onap.ccsdk.cds.controllerblueprints.core.data.PropertyDefinition
+import org.onap.ccsdk.cds.controllerblueprints.core.utils.PropertyDefinitionUtils.Companion.hasLogProtect
+import kotlin.test.assertFalse
+import kotlin.test.assertTrue
+
+class PropertyDefinitionUtilsTest {
+
+    @Test
+    fun testLogProtectMetadata() {
+        val metadata = mutableMapOf<String, String>()
+
+        assertFalse { hasLogProtect(metadata) }
+
+        metadata[LOG_PROTECT] = "true"
+        assertTrue { hasLogProtect(metadata) }
+        metadata.clear()
+
+        metadata[LOG_PROTECT] = "yes"
+        assertTrue { hasLogProtect(metadata) }
+        metadata.clear()
+
+        metadata[LOG_PROTECT] = "y"
+        assertTrue { hasLogProtect(metadata) }
+        metadata.clear()
+
+        metadata[LOG_PROTECT] = "false"
+        assertFalse { hasLogProtect(metadata) }
+        metadata.clear()
+
+        val nullMetadata: MutableMap<String, String>? = null
+        assertFalse { hasLogProtect(nullMetadata) }
+    }
+
+    @Test
+    fun testHasLogProtectPropertyDefinition() {
+        var propertyDefinition: PropertyDefinition? = null
+        assertFalse { hasLogProtect(propertyDefinition) }
+
+        propertyDefinition = PropertyDefinition()
+        assertFalse { hasLogProtect(propertyDefinition) }
+
+        val metadata = mutableMapOf<String, String>()
+        metadata[LOG_PROTECT] = "TRUE"
+        propertyDefinition.metadata = metadata
+
+        assertTrue { hasLogProtect(propertyDefinition) }
+    }
+}