Add encrypt/decrypt functionality for sensitive fields 86/140286/2
authorrameshiyer27 <ramesh.murugan.iyer@est.tech>
Sun, 16 Feb 2025 10:24:55 +0000 (10:24 +0000)
committerrameshiyer27 <ramesh.murugan.iyer@est.tech>
Mon, 24 Feb 2025 11:18:52 +0000 (11:18 +0000)
Issue-ID: POLICY-5134
Signed-off-by: rameshiyer27 <ramesh.murugan.iyer@est.tech>
Change-Id: If564f01900fbc51496b9ba6f9cea05bab93d44f9

16 files changed:
runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProvider.java
runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/parameters/AcmParameters.java
runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/utils/EncryptionUtils.java [new file with mode: 0644]
runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/scanner/AbstractScanner.java
runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/scanner/PhaseScanner.java
runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/scanner/SimpleScanner.java
runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/scanner/StageScanner.java
runtime-acm/src/main/resources/application.yaml
runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProviderTest.java
runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/main/utils/EncryptionUtilTest.java [new file with mode: 0644]
runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/scanner/PhaseScannerTest.java
runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/scanner/SimpleScannerTest.java
runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/scanner/StageScannerTest.java
runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/util/CommonTestData.java
runtime-acm/src/test/resources/providers/AcDefinitionEncryptTest.yaml [new file with mode: 0644]
runtime-acm/src/test/resources/providers/AcInstantiateEncryptTest.json [new file with mode: 0644]

index 0979a81..eacd07f 100644 (file)
@@ -1,6 +1,6 @@
 /*-
  * ============LICENSE_START=======================================================
- * Copyright (C) 2021-2024 Nordix Foundation.
+ * Copyright (C) 2021-2025 Nordix Foundation.
  * Modifications Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -29,6 +29,7 @@ import java.util.stream.Collectors;
 import lombok.NonNull;
 import lombok.RequiredArgsConstructor;
 import org.onap.policy.clamp.acm.runtime.main.parameters.AcRuntimeParameterGroup;
+import org.onap.policy.clamp.acm.runtime.main.utils.EncryptionUtils;
 import org.onap.policy.clamp.acm.runtime.supervision.SupervisionAcHandler;
 import org.onap.policy.clamp.models.acm.concepts.AcTypeState;
 import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
@@ -79,6 +80,7 @@ public class AutomationCompositionInstantiationProvider {
     private final SupervisionAcHandler supervisionAcHandler;
     private final ParticipantProvider participantProvider;
     private final AcRuntimeParameterGroup acRuntimeParameterGroup;
+    private final EncryptionUtils encryptionUtils;
 
     /**
      * Create automation composition.
@@ -104,6 +106,7 @@ public class AutomationCompositionInstantiationProvider {
         if (!validationResult.isValid()) {
             throw new PfModelRuntimeException(Status.BAD_REQUEST, validationResult.getResult());
         }
+        encryptInstanceProperties(automationComposition, compositionId);
         automationComposition = automationCompositionProvider.createAutomationComposition(automationComposition);
 
         return createInstantiationResponse(automationComposition);
@@ -141,6 +144,7 @@ public class AutomationCompositionInstantiationProvider {
             if (!validationResult.isValid()) {
                 throw new PfModelRuntimeException(Status.BAD_REQUEST, validationResult.getResult());
             }
+            encryptInstanceProperties(acToUpdate, compositionId);
             automationComposition = automationCompositionProvider.updateAutomationComposition(acToUpdate);
             return createInstantiationResponse(automationComposition);
 
@@ -200,6 +204,8 @@ public class AutomationCompositionInstantiationProvider {
         // Publish property update event to the participants
         supervisionAcHandler.update(acToBeUpdated);
 
+        encryptInstanceProperties(acToBeUpdated, acToBeUpdated.getCompositionId());
+
         automationComposition = automationCompositionProvider.updateAutomationComposition(acToBeUpdated);
         return createInstantiationResponse(automationComposition);
     }
@@ -242,6 +248,8 @@ public class AutomationCompositionInstantiationProvider {
         // Publish migrate event to the participants
         supervisionAcHandler.migrate(acToBeUpdated, acDefinition.getServiceTemplate());
 
+        encryptInstanceProperties(acToBeUpdated, acToBeUpdated.getCompositionTargetId());
+
         var ac = automationCompositionProvider.updateAutomationComposition(acToBeUpdated);
         elementsRemoved.forEach(automationCompositionProvider::deleteAutomationCompositionElement);
         return createInstantiationResponse(ac);
@@ -356,6 +364,15 @@ public class AutomationCompositionInstantiationProvider {
         return result;
     }
 
+
+    private void encryptInstanceProperties(AutomationComposition automationComposition, UUID compositionId) {
+        if (encryptionUtils.encryptionEnabled()) {
+            var acDefinitionOpt = acDefinitionProvider.findAcDefinition(compositionId);
+            acDefinitionOpt.ifPresent(acDefinition
+                    -> encryptionUtils.findAndEncryptSensitiveData(acDefinition, automationComposition));
+        }
+    }
+
     /**
      * Get Automation Composition.
      *
index 3ae21e5..554edea 100644 (file)
@@ -1,6 +1,6 @@
 /*-
  * ============LICENSE_START=======================================================
- *  Copyright (C) 2023 Nordix Foundation.
+ *  Copyright (C) 2023,2025 Nordix Foundation.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -35,4 +35,8 @@ public class AcmParameters {
 
     private String toscaCompositionName = "org.onap.policy.clamp.acm.AutomationComposition";
 
+    private String passPhrase;
+
+    private String salt;
+
 }
diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/utils/EncryptionUtils.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/utils/EncryptionUtils.java
new file mode 100644 (file)
index 0000000..565adb0
--- /dev/null
@@ -0,0 +1,199 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2025 Nordix Foundation.
+ * ================================================================================
+ * 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 org.onap.policy.clamp.acm.runtime.main.utils;
+
+import jakarta.ws.rs.core.Response;
+import java.nio.ByteBuffer;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.spec.InvalidKeySpecException;
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.List;
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.GCMParameterSpec;
+import javax.crypto.spec.PBEKeySpec;
+import javax.crypto.spec.SecretKeySpec;
+import org.onap.policy.clamp.acm.runtime.main.parameters.AcRuntimeParameterGroup;
+import org.onap.policy.clamp.common.acm.exception.AutomationCompositionRuntimeException;
+import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
+import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionDefinition;
+import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaProperty;
+import org.springframework.stereotype.Component;
+
+/**
+ * Class to encrypt/decrypt sensitive fields in the database.
+ */
+
+@Component
+public class EncryptionUtils {
+
+    private static final String ALGORITHM = "AES/GCM/NoPadding";
+    private static final String PBK_ALGORITHM = "PBKDF2WithHmacSHA256";
+    private static final String MARKER = "ENCRYPTED:";
+    private static final String SENSITIVE_METADATA = "sensitive";
+    private static final int GCM_TAG = 128;
+    private static final int IV_LENGTH = 12;
+    private static final SecureRandom SECURE_RANDOM = new SecureRandom();
+    private final String passPhrase;
+    private final String salt;
+
+
+    private static byte[] generateIV() {
+        var iv = new byte[IV_LENGTH];
+        SECURE_RANDOM.nextBytes(iv); //random iv
+        return iv;
+    }
+
+    /**
+     * Constructor EncryptionUtils.
+     * @param acRuntimeParameterGroup acRuntimeParameterGroup
+     */
+    public EncryptionUtils(AcRuntimeParameterGroup acRuntimeParameterGroup) {
+        this.passPhrase = acRuntimeParameterGroup.getAcmParameters().getPassPhrase();
+        this.salt = acRuntimeParameterGroup.getAcmParameters().getSalt();
+    }
+
+    /**
+     * Check encryption is enabled.
+     * @return boolean result
+     */
+    public boolean encryptionEnabled() {
+        return passPhrase != null && salt != null;
+    }
+
+
+    /**
+     * Find and encrypt sensitive fields in an AC instance.
+     * @param acDefinition acDefinition
+     * @param automationComposition acInstance
+     */
+    public void findAndEncryptSensitiveData(AutomationCompositionDefinition acDefinition,
+                                            AutomationComposition automationComposition) {
+        try {
+            for (var acInstanceElement: automationComposition.getElements().values()) {
+                var sensitiveProperties = findSensitiveElementFields(acDefinition, acInstanceElement);
+                for (var property : sensitiveProperties) {
+                    var elementProperties = acInstanceElement.getProperties();
+                    var sensitiveVal = elementProperties.get(property.getName());
+                    if (sensitiveVal instanceof String sensitiveStr && !sensitiveStr.startsWith(MARKER)) {
+                        var encryptedVal = encrypt(sensitiveStr);
+                        elementProperties.put(property.getName(), encryptedVal);
+                    }
+                }
+            }
+        } catch (Exception e) {
+            throw new AutomationCompositionRuntimeException(Response.Status.fromStatusCode(500),
+                    "Failed to encrypt instance field ", e);
+        }
+    }
+
+
+    /**
+     * Find and decrypt sensitive fields in an AC instance.
+     * @param automationComposition acInstance
+     */
+    public void findAndDecryptSensitiveData(AutomationComposition automationComposition) {
+        try {
+            for (var acInstanceElement: automationComposition.getElements().values()) {
+                for (var property : acInstanceElement.getProperties().entrySet()) {
+                    var propertyVal = property.getValue();
+                    if (propertyVal instanceof String propertyValStr && propertyValStr.startsWith(MARKER)) {
+                        var decryptedVal = decrypt(propertyValStr);
+                        acInstanceElement.getProperties().put(property.getKey(), decryptedVal);
+                    }
+                }
+            }
+        } catch (Exception e) {
+            throw new AutomationCompositionRuntimeException(Response.Status.fromStatusCode(500),
+                    "Failed to decrypt instance field ", e);
+        }
+    }
+
+
+    private List<ToscaProperty> findSensitiveElementFields(AutomationCompositionDefinition acDefinition,
+                                                           AutomationCompositionElement acInstanceElement) {
+
+        List<ToscaProperty> sensitiveProperties = new ArrayList<>();
+
+        // Fetch the node template element
+        var acDefElementOpt = acDefinition.getServiceTemplate().getToscaTopologyTemplate().getNodeTemplates()
+                .values().stream().filter(acDefElement -> acDefElement.getName()
+                        .equals(acInstanceElement.getDefinition().getName())).findFirst();
+
+        // Fetch node type
+        if (acDefElementOpt.isPresent()) {
+            var toscaNodeTypeOpt = acDefinition.getServiceTemplate().getNodeTypes().values().stream()
+                    .filter(toscaNodeType -> toscaNodeType.getName()
+                            .equals(acDefElementOpt.get().getType())).findFirst();
+
+            toscaNodeTypeOpt.ifPresent(toscaNodeType -> toscaNodeType.getProperties().values()
+                    .stream().filter(property -> property.getMetadata() != null
+                            && property.getMetadata().containsKey(SENSITIVE_METADATA))
+                    .forEach(sensitiveProperties::add));
+        }
+        return sensitiveProperties;
+    }
+
+
+    private SecretKey getSecretKey() throws NoSuchAlgorithmException, InvalidKeySpecException {
+        var factory = SecretKeyFactory.getInstance(PBK_ALGORITHM);
+        var spec = new PBEKeySpec(passPhrase.toCharArray(), salt.getBytes(), 65536, 256);
+        return new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
+    }
+
+    private String encrypt(String input) throws IllegalBlockSizeException, BadPaddingException,
+            NoSuchAlgorithmException, InvalidKeySpecException, InvalidAlgorithmParameterException, InvalidKeyException,
+            NoSuchPaddingException {
+        var iv = generateIV();
+        var parameterSpec = new GCMParameterSpec(GCM_TAG, iv);
+        var cipher = Cipher.getInstance(ALGORITHM);
+        cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(), parameterSpec);
+        var cipherText = cipher.doFinal(input.getBytes());
+        var cipherByte = ByteBuffer.allocate(iv.length + cipherText.length).put(iv).put(cipherText).array();
+        return MARKER + Base64.getEncoder().encodeToString(cipherByte);
+    }
+
+    private String decrypt(String cipherText) throws IllegalBlockSizeException, BadPaddingException,
+            NoSuchAlgorithmException, InvalidKeySpecException,
+            InvalidAlgorithmParameterException, InvalidKeyException, NoSuchPaddingException {
+        var decodedText = Base64.getDecoder().decode(cipherText.substring(MARKER.length()).getBytes());
+        var byteBuffer = ByteBuffer.wrap(decodedText);
+        var iv = new byte[IV_LENGTH];
+        byteBuffer.get(iv);
+        var encryptedByte = new byte[byteBuffer.remaining()];
+        byteBuffer.get(encryptedByte);
+
+        var parameterSpec = new GCMParameterSpec(GCM_TAG, iv);
+        var cipher = Cipher.getInstance(ALGORITHM);
+        cipher.init(Cipher.DECRYPT_MODE, getSecretKey(), parameterSpec);
+        var plainText = cipher.doFinal(encryptedByte);
+        return new String(plainText);
+    }
+}
index 136276e..0f9b941 100644 (file)
@@ -21,6 +21,7 @@
 package org.onap.policy.clamp.acm.runtime.supervision.scanner;
 
 import org.onap.policy.clamp.acm.runtime.main.parameters.AcRuntimeParameterGroup;
+import org.onap.policy.clamp.acm.runtime.main.utils.EncryptionUtils;
 import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantSyncPublisher;
 import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
 import org.onap.policy.clamp.models.acm.concepts.DeployState;
@@ -40,13 +41,15 @@ public abstract class AbstractScanner {
 
     protected final AutomationCompositionProvider acProvider;
     private final ParticipantSyncPublisher participantSyncPublisher;
+    private final EncryptionUtils encryptionUtils;
 
     protected AbstractScanner(final AutomationCompositionProvider acProvider,
             final ParticipantSyncPublisher participantSyncPublisher,
-            final AcRuntimeParameterGroup acRuntimeParameterGroup) {
+            final AcRuntimeParameterGroup acRuntimeParameterGroup, final EncryptionUtils encryptionUtils) {
         this.acProvider = acProvider;
         this.participantSyncPublisher = participantSyncPublisher;
         this.maxStatusWaitMs = acRuntimeParameterGroup.getParticipantParameters().getMaxStatusWaitMs();
+        this.encryptionUtils = encryptionUtils;
     }
 
     protected void complete(final AutomationComposition automationComposition, UpdateSync updateSync) {
@@ -118,7 +121,14 @@ public abstract class AbstractScanner {
             acProvider.deleteAutomationComposition(automationComposition.getInstanceId());
         }
         if (updateSync.isToBeSync()) {
+            decryptInstanceProperties(automationComposition);
             participantSyncPublisher.sendSync(automationComposition);
         }
     }
+
+    protected void decryptInstanceProperties(AutomationComposition automationComposition) {
+        if (encryptionUtils.encryptionEnabled()) {
+            encryptionUtils.findAndDecryptSensitiveData(automationComposition);
+        }
+    }
 }
index de56040..18bdb55 100644 (file)
@@ -21,6 +21,7 @@
 package org.onap.policy.clamp.acm.runtime.supervision.scanner;
 
 import org.onap.policy.clamp.acm.runtime.main.parameters.AcRuntimeParameterGroup;
+import org.onap.policy.clamp.acm.runtime.main.utils.EncryptionUtils;
 import org.onap.policy.clamp.acm.runtime.supervision.comm.AutomationCompositionDeployPublisher;
 import org.onap.policy.clamp.acm.runtime.supervision.comm.AutomationCompositionStateChangePublisher;
 import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantSyncPublisher;
@@ -52,8 +53,9 @@ public class PhaseScanner extends AbstractScanner {
             final ParticipantSyncPublisher participantSyncPublisher,
             final AutomationCompositionStateChangePublisher acStateChangePublisher,
             final AutomationCompositionDeployPublisher acDeployPublisher,
-            final AcRuntimeParameterGroup acRuntimeParameterGroup) {
-        super(acProvider, participantSyncPublisher, acRuntimeParameterGroup);
+            final AcRuntimeParameterGroup acRuntimeParameterGroup,
+            final EncryptionUtils encryptionUtils) {
+        super(acProvider, participantSyncPublisher, acRuntimeParameterGroup, encryptionUtils);
         this.acStateChangePublisher = acStateChangePublisher;
         this.acDeployPublisher = acDeployPublisher;
     }
@@ -115,7 +117,9 @@ public class PhaseScanner extends AbstractScanner {
 
         if (DeployState.DEPLOYING.equals(automationComposition.getDeployState())) {
             LOGGER.debug("retry message AutomationCompositionDeploy");
-            acDeployPublisher.send(automationComposition, startPhase, false);
+            var acToSend = new AutomationComposition(automationComposition);
+            decryptInstanceProperties(acToSend);
+            acDeployPublisher.send(acToSend, startPhase, false);
         } else {
             LOGGER.debug("retry message AutomationCompositionStateChange");
             acStateChangePublisher.send(automationComposition, startPhase, false);
index c102412..51dadfa 100644 (file)
@@ -21,6 +21,7 @@
 package org.onap.policy.clamp.acm.runtime.supervision.scanner;
 
 import org.onap.policy.clamp.acm.runtime.main.parameters.AcRuntimeParameterGroup;
+import org.onap.policy.clamp.acm.runtime.main.utils.EncryptionUtils;
 import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantSyncPublisher;
 import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
 import org.onap.policy.clamp.models.acm.concepts.StateChangeResult;
@@ -45,9 +46,10 @@ public class SimpleScanner extends AbstractScanner {
      * @param acRuntimeParameterGroup the parameters for the automation composition runtime
      */
     public SimpleScanner(final AutomationCompositionProvider acProvider,
-            final ParticipantSyncPublisher participantSyncPublisher,
-            final AcRuntimeParameterGroup acRuntimeParameterGroup) {
-        super(acProvider, participantSyncPublisher, acRuntimeParameterGroup);
+                         final ParticipantSyncPublisher participantSyncPublisher,
+                         final AcRuntimeParameterGroup acRuntimeParameterGroup,
+                         final EncryptionUtils encryptionUtils) {
+        super(acProvider, participantSyncPublisher, acRuntimeParameterGroup, encryptionUtils);
     }
 
     /**
index 18717cc..7893032 100644 (file)
@@ -22,6 +22,7 @@ package org.onap.policy.clamp.acm.runtime.supervision.scanner;
 
 import java.util.Comparator;
 import org.onap.policy.clamp.acm.runtime.main.parameters.AcRuntimeParameterGroup;
+import org.onap.policy.clamp.acm.runtime.main.utils.EncryptionUtils;
 import org.onap.policy.clamp.acm.runtime.supervision.comm.AutomationCompositionMigrationPublisher;
 import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantSyncPublisher;
 import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
@@ -45,10 +46,11 @@ public class StageScanner extends AbstractScanner {
      * @param acRuntimeParameterGroup the parameters for the automation composition runtime
      */
     public StageScanner(final AutomationCompositionProvider acProvider,
-            final ParticipantSyncPublisher participantSyncPublisher,
-            final AutomationCompositionMigrationPublisher acMigrationPublisher,
-            final AcRuntimeParameterGroup acRuntimeParameterGroup) {
-        super(acProvider, participantSyncPublisher, acRuntimeParameterGroup);
+                        final ParticipantSyncPublisher participantSyncPublisher,
+                        final AutomationCompositionMigrationPublisher acMigrationPublisher,
+                        final AcRuntimeParameterGroup acRuntimeParameterGroup,
+                        final EncryptionUtils encryptionUtils) {
+        super(acProvider, participantSyncPublisher, acRuntimeParameterGroup, encryptionUtils);
         this.acMigrationPublisher = acMigrationPublisher;
     }
 
@@ -87,7 +89,9 @@ public class StageScanner extends AbstractScanner {
                 updateSync.setUpdated(true);
                 saveAndSync(automationComposition, updateSync);
                 LOGGER.debug("retry message AutomationCompositionMigration");
-                acMigrationPublisher.send(automationComposition, minStageNotCompleted);
+                var acToSend = new AutomationComposition(automationComposition);
+                decryptInstanceProperties(acToSend);
+                acMigrationPublisher.send(acToSend, minStageNotCompleted);
             } else {
                 handleTimeout(automationComposition, updateSync);
             }
index 1bc529a..247cd24 100644 (file)
@@ -62,6 +62,8 @@ runtime:
   acmParameters:
     toscaElementName: org.onap.policy.clamp.acm.AutomationCompositionElement
     toscaCompositionName: org.onap.policy.clamp.acm.AutomationComposition
+    passPhrase: 1234AbCEncryptionPassPhrase
+    salt: runtimeFixedSalt
 
 management:
   endpoints:
index 21ad2f6..d53f700 100644 (file)
@@ -1,6 +1,6 @@
 /*-
  * ============LICENSE_START=======================================================
- *  Copyright (C) 2021-2024 Nordix Foundation.
+ *  Copyright (C) 2021-2025 Nordix Foundation.
  *  Modifications Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -39,6 +39,7 @@ import java.util.UUID;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 import org.onap.policy.clamp.acm.runtime.main.parameters.AcRuntimeParameterGroup;
+import org.onap.policy.clamp.acm.runtime.main.utils.EncryptionUtils;
 import org.onap.policy.clamp.acm.runtime.supervision.SupervisionAcHandler;
 import org.onap.policy.clamp.acm.runtime.util.CommonTestData;
 import org.onap.policy.clamp.models.acm.concepts.AcTypeState;
@@ -93,6 +94,8 @@ class AutomationCompositionInstantiationProviderTest {
 
     private static final String DO_NOT_MATCH = " do not match with ";
 
+
+
     private static ToscaServiceTemplate serviceTemplate = new ToscaServiceTemplate();
 
     @BeforeAll
@@ -113,9 +116,10 @@ class AutomationCompositionInstantiationProviderTest {
         var acProvider = mock(AutomationCompositionProvider.class);
         var supervisionAcHandler = mock(SupervisionAcHandler.class);
         var participantProvider = mock(ParticipantProvider.class);
+        var encryptionUtils = new EncryptionUtils(CommonTestData.getTestParamaterGroup());
         var instantiationProvider = new AutomationCompositionInstantiationProvider(acProvider, acDefinitionProvider,
                 null, supervisionAcHandler, participantProvider,
-                CommonTestData.getTestParamaterGroup());
+                CommonTestData.getTestParamaterGroup(), encryptionUtils);
         var automationCompositionCreate =
                 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Crud");
         automationCompositionCreate.setCompositionId(compositionId);
@@ -179,9 +183,10 @@ class AutomationCompositionInstantiationProviderTest {
 
         var supervisionAcHandler = mock(SupervisionAcHandler.class);
         var participantProvider = mock(ParticipantProvider.class);
+        var encryptionUtils = new EncryptionUtils(CommonTestData.getTestParamaterGroup());
         var instantiationProvider = new AutomationCompositionInstantiationProvider(acProvider, acDefinitionProvider,
                 new AcInstanceStateResolver(), supervisionAcHandler, participantProvider,
-                CommonTestData.getTestParamaterGroup());
+                CommonTestData.getTestParamaterGroup(), encryptionUtils);
         var instantiationResponse = instantiationProvider.updateAutomationComposition(
                 automationCompositionUpdate.getCompositionId(), automationCompositionUpdate);
 
@@ -207,13 +212,14 @@ class AutomationCompositionInstantiationProviderTest {
         automationCompositionUpdate.setDeployState(DeployState.DEPLOYING);
         automationCompositionUpdate.setLockState(LockState.NONE);
         var acProvider = mock(AutomationCompositionProvider.class);
+        var encryptionUtils = mock(EncryptionUtils.class);
         when(acProvider.getAutomationComposition(automationCompositionUpdate.getInstanceId()))
                 .thenReturn(automationCompositionUpdate);
 
         var instantiationProvider =
             new AutomationCompositionInstantiationProvider(acProvider, mock(AcDefinitionProvider.class),
                 new AcInstanceStateResolver(), mock(SupervisionAcHandler.class), mock(ParticipantProvider.class),
-                mock(AcRuntimeParameterGroup.class));
+                mock(AcRuntimeParameterGroup.class), encryptionUtils);
 
         var compositionId = automationCompositionUpdate.getCompositionId();
         assertThatThrownBy(
@@ -279,9 +285,10 @@ class AutomationCompositionInstantiationProviderTest {
 
         var supervisionAcHandler = mock(SupervisionAcHandler.class);
         var participantProvider = mock(ParticipantProvider.class);
+        var encryptionUtils = new EncryptionUtils(CommonTestData.getTestParamaterGroup());
         var instantiationProvider = new AutomationCompositionInstantiationProvider(acProvider, acDefinitionProvider,
                 new AcInstanceStateResolver(), supervisionAcHandler, participantProvider,
-                new AcRuntimeParameterGroup());
+                new AcRuntimeParameterGroup(), encryptionUtils);
 
         automationCompositionTarget.setPrecheck(true);
         var preCheckResponse = instantiationProvider.updateAutomationComposition(compositionId,
@@ -311,7 +318,7 @@ class AutomationCompositionInstantiationProviderTest {
 
         var instantiationProvider = new AutomationCompositionInstantiationProvider(acProvider, acDefinitionProvider,
                 new AcInstanceStateResolver(), supervisionAcHandler, participantProvider,
-                new AcRuntimeParameterGroup());
+                new AcRuntimeParameterGroup(), null);
         var instanceId = UUID.randomUUID();
         assertDoesNotThrow(() -> {
             instantiationProvider.checkCompatibility(newDefinition, oldDefinition, instanceId);
@@ -346,8 +353,10 @@ class AutomationCompositionInstantiationProviderTest {
 
         var supervisionAcHandler = mock(SupervisionAcHandler.class);
         var participantProvider = mock(ParticipantProvider.class);
+        var encryptionUtils = new EncryptionUtils(CommonTestData.getTestParamaterGroup());
         var instantiationProvider = new AutomationCompositionInstantiationProvider(acProvider, acDefinitionProvider,
-            new AcInstanceStateResolver(), supervisionAcHandler, participantProvider, new AcRuntimeParameterGroup());
+            new AcInstanceStateResolver(), supervisionAcHandler, participantProvider, new AcRuntimeParameterGroup(),
+                encryptionUtils);
 
         assertThatThrownBy(() -> instantiationProvider
                 .updateAutomationComposition(automationComposition.getCompositionId(), automationComposition))
@@ -390,8 +399,10 @@ class AutomationCompositionInstantiationProviderTest {
 
         var supervisionAcHandler = mock(SupervisionAcHandler.class);
         var acmParticipantProvider = mock(ParticipantProvider.class);
+        var encryptionUtils = mock(EncryptionUtils.class);
         var instantiationProvider = new AutomationCompositionInstantiationProvider(acProvider, acDefinitionProvider,
-            new AcInstanceStateResolver(), supervisionAcHandler, acmParticipantProvider, new AcRuntimeParameterGroup());
+            new AcInstanceStateResolver(), supervisionAcHandler, acmParticipantProvider, new AcRuntimeParameterGroup(),
+                encryptionUtils);
 
         assertThatThrownBy(() -> instantiationProvider
             .updateAutomationComposition(automationComposition.getCompositionId(), automationComposition))
@@ -439,9 +450,10 @@ class AutomationCompositionInstantiationProviderTest {
 
         var supervisionAcHandler = mock(SupervisionAcHandler.class);
         var participantProvider = mock(ParticipantProvider.class);
+        var encryptionUtils = mock(EncryptionUtils.class);
         var instantiationProvider = new AutomationCompositionInstantiationProvider(acProvider, acDefinitionProvider,
                 new AcInstanceStateResolver(), supervisionAcHandler, participantProvider,
-                new AcRuntimeParameterGroup());
+                new AcRuntimeParameterGroup(), encryptionUtils);
 
         assertThatThrownBy(() -> instantiationProvider
                 .updateAutomationComposition(automationComposition.getCompositionId(), acMigrate))
@@ -449,7 +461,7 @@ class AutomationCompositionInstantiationProviderTest {
     }
 
     @Test
-    void testMigratePrecheckBadRequest() {
+    void testMigratePreCheckBadRequest() {
         var acDefinitionProvider = mock(AcDefinitionProvider.class);
         var acDefinition = CommonTestData.createAcDefinition(serviceTemplate, AcTypeState.PRIMED);
         var compositionId = acDefinition.getCompositionId();
@@ -477,9 +489,10 @@ class AutomationCompositionInstantiationProviderTest {
 
         var supervisionAcHandler = mock(SupervisionAcHandler.class);
         var participantProvider = mock(ParticipantProvider.class);
+        var encryptionUtils = mock(EncryptionUtils.class);
         var instantiationProvider = new AutomationCompositionInstantiationProvider(acProvider, acDefinitionProvider,
                 new AcInstanceStateResolver(), supervisionAcHandler, participantProvider,
-                new AcRuntimeParameterGroup());
+                new AcRuntimeParameterGroup(), encryptionUtils);
 
         assertThatThrownBy(() -> instantiationProvider
                 .updateAutomationComposition(automationComposition.getCompositionId(), acMigrate))
@@ -500,9 +513,11 @@ class AutomationCompositionInstantiationProviderTest {
         var supervisionAcHandler = mock(SupervisionAcHandler.class);
         var participantProvider = mock(ParticipantProvider.class);
         var acRuntimeParameterGroup = mock(AcRuntimeParameterGroup.class);
+        var encryptionUtils = mock(EncryptionUtils.class);
 
         var instantiationProvider = new AutomationCompositionInstantiationProvider(acProvider, acDefinitionProvider,
-                null, supervisionAcHandler, participantProvider, acRuntimeParameterGroup);
+                null, supervisionAcHandler, participantProvider, acRuntimeParameterGroup,
+                encryptionUtils);
 
         when(acProvider.getAutomationComposition(automationComposition.getInstanceId()))
                 .thenReturn(automationComposition);
@@ -535,7 +550,7 @@ class AutomationCompositionInstantiationProviderTest {
 
         var instantiationProvider =
                 new AutomationCompositionInstantiationProvider(acProvider, acDefinitionProvider, null, null, null,
-                        acRuntimeParamaterGroup);
+                        acRuntimeParamaterGroup, null);
 
         when(acProvider.getAutomationComposition(automationComposition.getInstanceId()))
                 .thenReturn(automationComposition);
@@ -562,10 +577,11 @@ class AutomationCompositionInstantiationProviderTest {
         when(acProvider.createAutomationComposition(automationCompositionCreate))
                 .thenReturn(automationCompositionCreate);
         var participantProvider = mock(ParticipantProvider.class);
+        var encryptionUtils = new EncryptionUtils(CommonTestData.getTestParamaterGroup());
 
         var instantiationProvider = new AutomationCompositionInstantiationProvider(acProvider, acDefinitionProvider,
                 null, null, participantProvider,
-                CommonTestData.getTestParamaterGroup());
+                CommonTestData.getTestParamaterGroup(), encryptionUtils);
 
         var instantiationResponse = instantiationProvider.createAutomationComposition(
                 automationCompositionCreate.getCompositionId(), automationCompositionCreate);
@@ -591,8 +607,9 @@ class AutomationCompositionInstantiationProviderTest {
         automationComposition.setCompositionId(compositionId);
 
         var acProvider = mock(AutomationCompositionProvider.class);
+        var encryptionUtils = mock(EncryptionUtils.class);
         var provider = new AutomationCompositionInstantiationProvider(acProvider, acDefinitionProvider, null, null,
-                participantProvider, CommonTestData.getTestParamaterGroup());
+                participantProvider, CommonTestData.getTestParamaterGroup(), encryptionUtils);
 
         assertThatThrownBy(() -> provider.createAutomationComposition(compositionId, automationComposition))
                 .hasMessageMatching(AC_ELEMENT_NAME_NOT_FOUND);
@@ -614,7 +631,7 @@ class AutomationCompositionInstantiationProviderTest {
                 .thenReturn(automationComposition);
         var provider = new AutomationCompositionInstantiationProvider(acProvider, mock(AcDefinitionProvider.class),
                 null, null, null,
-                mock(AcRuntimeParameterGroup.class));
+                mock(AcRuntimeParameterGroup.class), null);
 
         var compositionId = automationComposition.getCompositionId();
         assertThatThrownBy(() -> provider.createAutomationComposition(compositionId, automationComposition))
@@ -634,7 +651,7 @@ class AutomationCompositionInstantiationProviderTest {
                 .thenReturn(automationComposition);
         var provider = new AutomationCompositionInstantiationProvider(acProvider, mock(AcDefinitionProvider.class),
                 null, null, null,
-                mock(AcRuntimeParameterGroup.class));
+                mock(AcRuntimeParameterGroup.class), null);
 
         var compositionId = automationComposition.getCompositionId();
         var wrongCompositionId = UUID.randomUUID();
@@ -670,7 +687,7 @@ class AutomationCompositionInstantiationProviderTest {
         var acProvider = mock(AutomationCompositionProvider.class);
         var provider =
                 new AutomationCompositionInstantiationProvider(acProvider, acDefinitionProvider, null, null, null,
-                        null);
+                        null, null);
 
         var automationComposition =
                 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Crud");
@@ -704,7 +721,7 @@ class AutomationCompositionInstantiationProviderTest {
         var participantProvider = mock(ParticipantProvider.class);
         var provider = new AutomationCompositionInstantiationProvider(acProvider, acDefinitionProvider,
                 new AcInstanceStateResolver(), supervisionAcHandler, participantProvider,
-                mock(AcRuntimeParameterGroup.class));
+                mock(AcRuntimeParameterGroup.class), null);
 
         var acInstanceStateUpdate = new AcInstanceStateUpdate();
         acInstanceStateUpdate.setDeployOrder(DeployOrder.DEPLOY);
diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/main/utils/EncryptionUtilTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/main/utils/EncryptionUtilTest.java
new file mode 100644 (file)
index 0000000..ae6066a
--- /dev/null
@@ -0,0 +1,69 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2025 Nordix Foundation.
+ * ================================================================================
+ * 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 org.onap.policy.clamp.acm.runtime.main.utils;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.onap.policy.clamp.acm.runtime.instantiation.InstantiationUtils;
+import org.onap.policy.clamp.acm.runtime.util.CommonTestData;
+import org.onap.policy.clamp.models.acm.concepts.AcTypeState;
+import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionDefinition;
+import org.onap.policy.clamp.models.acm.persistence.provider.ProviderUtils;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
+import org.onap.policy.models.tosca.simple.concepts.JpaToscaServiceTemplate;
+
+class EncryptionUtilTest {
+
+    private static ToscaServiceTemplate serviceTemplateEncrypt;
+    public static final String TOSCA_TEMPLATE_YAML = "src/test/resources/providers/AcDefinitionEncryptTest.yaml";
+    public static final String INSTANTIATE_JSON = "src/test/resources/providers/AcInstantiateEncryptTest.json";
+    private static AutomationCompositionDefinition acDefinition;
+
+    @BeforeAll
+    static void setUpBeforeClass() {
+        serviceTemplateEncrypt = InstantiationUtils.getToscaServiceTemplate(TOSCA_TEMPLATE_YAML);
+        var jpa2 = ProviderUtils.getJpaAndValidate(serviceTemplateEncrypt, JpaToscaServiceTemplate::new,
+                "toscaServiceTemplate");
+        serviceTemplateEncrypt = jpa2.toAuthorative();
+        acDefinition = CommonTestData.createAcDefinition(serviceTemplateEncrypt, AcTypeState.PRIMED);
+    }
+
+    @Test
+    void testEncryptAcInstanceProperties() {
+        var automationComposition =
+                InstantiationUtils.getAutomationCompositionFromResource(INSTANTIATE_JSON, "Crud");
+        var encryptionUtils = new EncryptionUtils(CommonTestData.getEncryptionParamaterGroup());
+        assertTrue(encryptionUtils.encryptionEnabled());
+        assertDoesNotThrow(()
+                -> {
+            assert automationComposition != null;
+            encryptionUtils.findAndEncryptSensitiveData(acDefinition, automationComposition);
+        });
+        assertDoesNotThrow(() -> {
+            assert automationComposition != null;
+            encryptionUtils.findAndDecryptSensitiveData(automationComposition);
+        });
+    }
+
+}
index 6958fe4..c2860a8 100644 (file)
@@ -35,6 +35,7 @@ import java.util.Map;
 import java.util.UUID;
 import org.junit.jupiter.api.Test;
 import org.onap.policy.clamp.acm.runtime.instantiation.InstantiationUtils;
+import org.onap.policy.clamp.acm.runtime.main.utils.EncryptionUtils;
 import org.onap.policy.clamp.acm.runtime.supervision.comm.AutomationCompositionDeployPublisher;
 import org.onap.policy.clamp.acm.runtime.supervision.comm.AutomationCompositionStateChangePublisher;
 import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantSyncPublisher;
@@ -68,9 +69,10 @@ class PhaseScannerTest {
         var acDeployPublisher = mock(AutomationCompositionDeployPublisher.class);
         var acStateChangePublisher = mock(AutomationCompositionStateChangePublisher.class);
         var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner");
+        var encryptionUtils = new EncryptionUtils(acRuntimeParameterGroup);
 
         var phaseScanner = new PhaseScanner(automationCompositionProvider, mock(ParticipantSyncPublisher.class),
-                acStateChangePublisher, acDeployPublisher, acRuntimeParameterGroup);
+                acStateChangePublisher, acDeployPublisher, acRuntimeParameterGroup, encryptionUtils);
         var serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML);
         phaseScanner.scanWithPhase(automationComposition, serviceTemplate, new UpdateSync());
 
@@ -88,9 +90,10 @@ class PhaseScannerTest {
         var acDeployPublisher = mock(AutomationCompositionDeployPublisher.class);
         var acStateChangePublisher = mock(AutomationCompositionStateChangePublisher.class);
         var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner");
+        var encryptionUtils = new EncryptionUtils(acRuntimeParameterGroup);
 
         var phaseScanner = new PhaseScanner(automationCompositionProvider, mock(ParticipantSyncPublisher.class),
-                acStateChangePublisher, acDeployPublisher, acRuntimeParameterGroup);
+                acStateChangePublisher, acDeployPublisher, acRuntimeParameterGroup, encryptionUtils);
         var serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML);
         phaseScanner.scanWithPhase(automationComposition, serviceTemplate, new UpdateSync());
 
@@ -119,10 +122,11 @@ class PhaseScannerTest {
         var participantSyncPublisher = mock(ParticipantSyncPublisher.class);
         var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner");
         acRuntimeParameterGroup.getParticipantParameters().setMaxStatusWaitMs(-1);
+        var encryptionUtils = new EncryptionUtils(acRuntimeParameterGroup);
 
         // verify timeout scenario
         var phaseScanner = new PhaseScanner(automationCompositionProvider, participantSyncPublisher,
-                acStateChangePublisher, acDeployPublisher, acRuntimeParameterGroup);
+                acStateChangePublisher, acDeployPublisher, acRuntimeParameterGroup, encryptionUtils);
 
         automationComposition.setStateChangeResult(StateChangeResult.NO_ERROR);
         automationComposition.setLastMsg(TimestampHelper.now());
@@ -173,9 +177,10 @@ class PhaseScannerTest {
         var acDeployPublisher = mock(AutomationCompositionDeployPublisher.class);
         var acStateChangePublisher = mock(AutomationCompositionStateChangePublisher.class);
         var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner");
+        var encryptionUtils = new EncryptionUtils(acRuntimeParameterGroup);
 
         var phaseScanner = new PhaseScanner(automationCompositionProvider, mock(ParticipantSyncPublisher.class),
-                acStateChangePublisher, acDeployPublisher, acRuntimeParameterGroup);
+                acStateChangePublisher, acDeployPublisher, acRuntimeParameterGroup, encryptionUtils);
 
         var serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML);
         phaseScanner.scanWithPhase(automationComposition, serviceTemplate, new UpdateSync());
@@ -207,10 +212,11 @@ class PhaseScannerTest {
         var acProvider = mock(AutomationCompositionProvider.class);
         var acDeployPublisher = mock(AutomationCompositionDeployPublisher.class);
         var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner");
+        var encryptionUtils = new EncryptionUtils(acRuntimeParameterGroup);
 
         var phaseScanner = new PhaseScanner(acProvider, mock(ParticipantSyncPublisher.class),
                 mock(AutomationCompositionStateChangePublisher.class), acDeployPublisher,
-                acRuntimeParameterGroup);
+                acRuntimeParameterGroup, encryptionUtils);
 
         var serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML);
         phaseScanner.scanWithPhase(automationComposition, serviceTemplate, new UpdateSync());
@@ -241,9 +247,10 @@ class PhaseScannerTest {
         var acDeployPublisher = mock(AutomationCompositionDeployPublisher.class);
         var acStateChangePublisher = mock(AutomationCompositionStateChangePublisher.class);
         var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner");
+        var encryptionUtils = new EncryptionUtils(acRuntimeParameterGroup);
 
         var phaseScanner = new PhaseScanner(acProvider, mock(ParticipantSyncPublisher.class),
-                acStateChangePublisher, acDeployPublisher, acRuntimeParameterGroup);
+                acStateChangePublisher, acDeployPublisher, acRuntimeParameterGroup, encryptionUtils);
 
         var serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML);
         phaseScanner.scanWithPhase(automationComposition, serviceTemplate, new UpdateSync());
index b422f13..c82969d 100644 (file)
@@ -33,6 +33,7 @@ import java.util.UUID;
 import java.util.function.Consumer;
 import org.junit.jupiter.api.Test;
 import org.onap.policy.clamp.acm.runtime.instantiation.InstantiationUtils;
+import org.onap.policy.clamp.acm.runtime.main.utils.EncryptionUtils;
 import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantSyncPublisher;
 import org.onap.policy.clamp.acm.runtime.util.CommonTestData;
 import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
@@ -69,8 +70,9 @@ class SimpleScannerTest {
         docMessage.setStateChangeResult(StateChangeResult.FAILED);
         var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner");
         var acProvider = mock(AutomationCompositionProvider.class);
+        var encryptionUtils = new EncryptionUtils(acRuntimeParameterGroup);
         var simpleScanner = new SimpleScanner(acProvider, mock(ParticipantSyncPublisher.class),
-                acRuntimeParameterGroup);
+                acRuntimeParameterGroup, encryptionUtils);
         var result = simpleScanner.scanMessage(automationComposition, docMessage);
         assertTrue(result.isUpdated());
         assertTrue(result.isToBeSync());
@@ -93,8 +95,9 @@ class SimpleScannerTest {
         docMessage.setLockState(LockState.LOCKED);
         var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner");
         var acProvider = mock(AutomationCompositionProvider.class);
+        var encryptionUtils = new EncryptionUtils(acRuntimeParameterGroup);
         var simpleScanner = new SimpleScanner(acProvider, mock(ParticipantSyncPublisher.class),
-                acRuntimeParameterGroup);
+                acRuntimeParameterGroup, encryptionUtils);
 
         // wrong MessageType
         docMessage.setMessageType(ParticipantMessageType.PARTICIPANT_PRIME_ACK);
@@ -128,8 +131,9 @@ class SimpleScannerTest {
         docMessage.setOutProperties(Map.of("key", "value"));
         var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner");
         var acProvider = mock(AutomationCompositionProvider.class);
+        var encryptionUtils = new EncryptionUtils(acRuntimeParameterGroup);
         var simpleScanner = new SimpleScanner(acProvider, mock(ParticipantSyncPublisher.class),
-                acRuntimeParameterGroup);
+                acRuntimeParameterGroup, encryptionUtils);
         var result = simpleScanner.scanMessage(automationComposition, docMessage);
         assertTrue(result.isUpdated());
         assertTrue(result.isToBeSync());
@@ -150,8 +154,9 @@ class SimpleScannerTest {
         docMessage.setLockState(LockState.LOCKED);
         var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner");
         var acProvider = mock(AutomationCompositionProvider.class);
+        var encryptionUtils = new EncryptionUtils(acRuntimeParameterGroup);
         var simpleScanner = new SimpleScanner(acProvider, mock(ParticipantSyncPublisher.class),
-                acRuntimeParameterGroup);
+                acRuntimeParameterGroup, encryptionUtils);
         var result = simpleScanner.scanMessage(automationComposition, docMessage);
         assertTrue(result.isUpdated());
         assertFalse(result.isToBeSync());
@@ -234,8 +239,9 @@ class SimpleScannerTest {
         automationComposition.setLastMsg(TimestampHelper.now());
         var acProvider = mock(AutomationCompositionProvider.class);
         var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner");
+        var encryptionUtils = new EncryptionUtils(acRuntimeParameterGroup);
         var simpleScanner = new SimpleScanner(acProvider, mock(ParticipantSyncPublisher.class),
-                acRuntimeParameterGroup);
+                acRuntimeParameterGroup, encryptionUtils);
         simpleScanner.simpleScan(automationComposition, new UpdateSync());
         verify(acProvider, times(0)).updateAutomationComposition(any());
 
index 1cff25f..077580d 100644 (file)
@@ -34,6 +34,7 @@ import java.util.Map;
 import java.util.UUID;
 import org.junit.jupiter.api.Test;
 import org.onap.policy.clamp.acm.runtime.instantiation.InstantiationUtils;
+import org.onap.policy.clamp.acm.runtime.main.utils.EncryptionUtils;
 import org.onap.policy.clamp.acm.runtime.supervision.comm.AutomationCompositionMigrationPublisher;
 import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantSyncPublisher;
 import org.onap.policy.clamp.acm.runtime.util.CommonTestData;
@@ -70,8 +71,9 @@ class StageScannerTest {
         when(acProvider.updateAutomationComposition(any())).thenReturn(automationComposition);
 
         var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner");
+        var encryptionUtils = new EncryptionUtils(acRuntimeParameterGroup);
         var supervisionScanner = new StageScanner(acProvider, mock(ParticipantSyncPublisher.class),
-                mock(AutomationCompositionMigrationPublisher.class), acRuntimeParameterGroup);
+                mock(AutomationCompositionMigrationPublisher.class), acRuntimeParameterGroup, encryptionUtils);
 
         var serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML);
         supervisionScanner.scanStage(automationComposition, serviceTemplate, new UpdateSync());
index c3b5ff9..0392596 100644 (file)
@@ -1,6 +1,6 @@
 /*-
  * ============LICENSE_START=======================================================
- *  Copyright (C) 2021-2024 Nordix Foundation.
+ *  Copyright (C) 2021-2025 Nordix Foundation.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -165,4 +165,16 @@ public class CommonTestData {
         return acRuntimeParameterGroup;
     }
 
+    /**
+     * Create a new Test parameter group for Encryption.
+     *
+     * @return a new AutomationCompositionDefinition
+     */
+    public static AcRuntimeParameterGroup getEncryptionParamaterGroup() {
+        var acRuntimeParameterGroup = getTestParamaterGroup();
+        acRuntimeParameterGroup.getAcmParameters().setSalt("randomSalt");
+        acRuntimeParameterGroup.getAcmParameters().setPassPhrase("randomPhrase");
+        return acRuntimeParameterGroup;
+    }
+
 }
diff --git a/runtime-acm/src/test/resources/providers/AcDefinitionEncryptTest.yaml b/runtime-acm/src/test/resources/providers/AcDefinitionEncryptTest.yaml
new file mode 100644 (file)
index 0000000..0e93728
--- /dev/null
@@ -0,0 +1,160 @@
+# ============LICENSE_START=======================================================
+# Copyright (C) 2025 Nordix Foundation.
+# ================================================================================
+# 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=========================================================
+tosca_definitions_version: tosca_simple_yaml_1_3
+name: Migration-From
+data_types:
+  onap.datatypes.ToscaConceptIdentifier:
+    derived_from: tosca.datatypes.Root
+    properties:
+      name:
+        type: string
+        required: true
+      version:
+        type: string
+        required: true
+
+node_types:
+  org.onap.policy.clamp.acm.Participant:
+    version: 1.0.1
+    derived_from: tosca.nodetypes.Root
+    properties:
+      provider:
+        type: string
+        required: false
+  org.onap.policy.clamp.acm.AutomationCompositionElement:
+    version: 1.0.1
+    derived_from: tosca.nodetypes.Root
+    properties:
+      provider:
+        type: string
+        required: false
+        metadata:
+          common: true
+        description: Specifies the organization that provides the automation composition element
+      startPhase:
+        type: integer
+        required: false
+        constraints:
+          - greater_or_equal: 0
+        metadata:
+          common: true
+        description: A value indicating the start phase in which this automation composition element will be started, the
+          first start phase is zero. Automation Composition Elements are started in their start_phase order and stopped
+          in reverse start phase order. Automation Composition Elements with the same start phase are started and
+          stopped simultaneously
+      stage:
+        type: list
+        description: A list indicating the stages in which this automation composition element will be started, the
+          first stage is zero. Automation Composition Elements are started in their stage order.
+          Automation Composition Elements with the same stage are started simultaneously.
+
+  org.onap.policy.clamp.acm.AutomationComposition:
+    version: 1.0.1
+    derived_from: tosca.nodetypes.Root
+    properties:
+      provider:
+        type: string
+        required: false
+        metadata:
+          common: true
+        description: Specifies the organization that provides the automation composition element
+      elements:
+        type: list
+        required: true
+        metadata:
+          common: true
+        entry_schema:
+          type: onap.datatypes.ToscaConceptIdentifier
+        description: Specifies a list of automation composition element definitions that make up this automation composition definition
+
+  org.onap.policy.clamp.acm.SimAutomationCompositionElement:
+    version: 1.0.0
+    derived_from: org.onap.policy.clamp.acm.AutomationCompositionElement
+    properties:
+      password:
+        type: String
+        metadata:
+          sensitive: true
+      credential:
+        type: String
+        metadata:
+          sensitive: true
+      baseUrl:
+        type: string
+        required: true
+        description: The base URL to be prepended to each path, identifies the host for the REST endpoints.
+      httpHeaders:
+        type: map
+        required: false
+        entry_schema:
+          type: string
+        description: HTTP headers to send on REST requests
+      configurationEntities:
+        type: map
+        required: true
+        entry_schema:
+          type: map
+        metadata:
+          sensitive: true
+        description: The configuration entities the Automation Composition Element is managing and their associated REST requests
+
+
+topology_template:
+
+  node_templates:
+
+    org.onap.policy.clamp.acm.SimParticipant:
+      version: 2.3.4
+      type: org.onap.policy.clamp.acm.Participant
+      type_version: 1.0.1
+      description: Participant Simulator
+      properties:
+        provider: ONAP
+
+    onap.policy.clamp.ac.element.Sim_StarterAutomationCompositionElement:
+      version: 1.2.3
+      type: org.onap.policy.clamp.acm.SimAutomationCompositionElement
+      type_version: 1.0.0
+      description: Automation composition element for the http requests of AC Element Starter microservice
+      properties:
+        provider: ONAP
+        startPhase: 0
+        stage: [1,2]
+
+    onap.policy.clamp.ac.element.Sim_BridgeAutomationCompositionElement:
+      version: 1.2.3
+      type: org.onap.policy.clamp.acm.SimAutomationCompositionElement
+      type_version: 1.0.0
+      description: Automation composition element for the http requests of AC Element Bridge microservice
+      properties:
+        provider: ONAP
+        startPhase: 0
+        stage: [0,1]
+
+    onap.policy.clamp.ac.element.AutomationCompositionDefinition:
+      version: 1.2.3
+      type: org.onap.policy.clamp.acm.AutomationComposition
+      type_version: 1.0.1
+      description: Automation composition for Demo
+      properties:
+        provider: ONAP
+        elements:
+          - name: onap.policy.clamp.ac.element.Sim_StarterAutomationCompositionElement
+            version: 1.2.3
+          - name: onap.policy.clamp.ac.element.Sim_BridgeAutomationCompositionElement
+            version: 1.2.3
\ No newline at end of file
diff --git a/runtime-acm/src/test/resources/providers/AcInstantiateEncryptTest.json b/runtime-acm/src/test/resources/providers/AcInstantiateEncryptTest.json
new file mode 100644 (file)
index 0000000..acf2a9b
--- /dev/null
@@ -0,0 +1,84 @@
+{
+  "name": "Instance-Migration-From",
+  "version": "1.0.1",
+  "compositionId": "709c62b3-8918-41b9-a747-d21eb79c6c40",
+  "description": "Demo automation composition instance 0",
+  "elements": {
+    "709c62b3-8918-41b9-a747-d21eb79c6c34": {
+      "id": "709c62b3-8918-41b9-a747-d21eb79c6c34",
+      "definition": {
+        "name": "onap.policy.clamp.ac.element.Sim_StarterAutomationCompositionElement",
+        "version": "1.2.3"
+      },
+      "description": "Starter Automation Composition Element for the Demo",
+      "properties": {
+        "credential": "mycred1",
+        "password": "mypass1",
+        "baseUrl": "http://address:30800",
+        "httpHeaders": {
+          "Content-Type": "application/json",
+          "Authorization": "Basic YWNtVXNlcjp6YiFYenRHMzQ="
+        },
+        "configurationEntities": [
+          {
+            "configurationEntityId": {
+              "name": "onap.policy.clamp.ac.starter",
+              "version": "1.0.0"
+            },
+            "restSequence": [
+              {
+                "restRequestId": {
+                  "name": "request1",
+                  "version": "1.0.1"
+                },
+                "httpMethod": "POST",
+                "path": "/onap/policy/clamp/acelement/v2/activate",
+                "body": "{ \"receiverId\": { \"name\": \"onap.policy.clamp.ac.startertobridge\", \"version\": \"1.0.0\" }, \"timerMs\": 20000, \"elementType\": \"STARTER\", \"topicParameterGroup\": { \"server\": \"message-router:3904\", \"listenerTopic\": \"POLICY_UPDATE_MSG\", \"publisherTopic\": \"AC_ELEMENT_MSG\", \"fetchTimeout\": 15000, \"topicCommInfrastructure\": \"dmaap\" } }",
+                "expectedResponse": 201
+              }
+            ],
+            "myParameterToUpdate": "text1"
+          }
+        ]
+      }
+    },
+    "709c62b3-8918-41b9-a747-d21eb79c6c35": {
+      "id": "709c62b3-8918-41b9-a747-d21eb79c6c35",
+      "definition": {
+        "name": "onap.policy.clamp.ac.element.Sim_BridgeAutomationCompositionElement",
+        "version": "1.2.3"
+      },
+      "description": "Bridge Automation Composition Element for the Demo",
+      "properties": {
+        "baseUrl": "http://address:30801",
+        "password": "mypass2",
+        "credential": "mycred2",
+        "httpHeaders": {
+          "Content-Type": "application/json",
+          "Authorization": "Basic YWNtVXNlcjp6YiFYenRHMzQ="
+        },
+        "configurationEntities": [
+          {
+            "configurationEntityId": {
+              "name": "onap.policy.clamp.ac.bridge",
+              "version": "1.0.0"
+            },
+            "restSequence": [
+              {
+                "restRequestId": {
+                  "name": "request2",
+                  "version": "1.0.1"
+                },
+                "httpMethod": "POST",
+                "path": "/onap/policy/clamp/acelement/v2/activate",
+                "body": "{ \"receiverId\": { \"name\": \"onap.policy.clamp.ac.bridgetosink\", \"version\": \"1.0.0\" }, \"timerMs\": 20000, \"elementType\": \"BRIDGE\", \"topicParameterGroup\": { \"server\": \"message-router:3904\", \"listenerTopic\": \"POLICY_UPDATE_MSG\", \"publisherTopic\": \"AC_ELEMENT_MSG\", \"fetchTimeout\": 15000, \"topicCommInfrastructure\": \"dmaap\" } }",
+                "expectedResponse": 201
+              }
+            ],
+            "myParameterToUpdate": "text2"
+          }
+        ]
+      }
+    }
+  }
+}
\ No newline at end of file