Skip to content
This repository has been archived by the owner on Nov 11, 2024. It is now read-only.

Commit

Permalink
Add GalasaSecret resource type in resources route and add secrets enc…
Browse files Browse the repository at this point in the history
…ryption/decryption (#660)

* Add credentials encryption and decryption, mount encryption keys in test pods (#658)

* Add initial decryption logic for reading credentials

Signed-off-by: Eamonn Mansour <[email protected]>

* Mount encryption keys secret in test pods, refactor k8s controller settings + unit tests

Signed-off-by: Eamonn Mansour <[email protected]>

* fix: Fix OSGI wiring error, change oldDecryptionKeys to fallbackDecryptionKeys

Signed-off-by: Eamonn Mansour <[email protected]>

* review: Rename RunPoll to TestPodScheduler, parameterise randomiser, separate YAML parsing

Signed-off-by: Eamonn Mansour <[email protected]>

---------

Signed-off-by: Eamonn Mansour <[email protected]>

* Add GalasaSecret resource processing to /resources route (#659)

* Add initial decryption logic for reading credentials

Signed-off-by: Eamonn Mansour <[email protected]>

* Mount encryption keys secret in test pods, refactor k8s controller settings + unit tests

Signed-off-by: Eamonn Mansour <[email protected]>

* Refactor: separate resource processing logic out from resources route

Signed-off-by: Eamonn Mansour <[email protected]>

* Start adding GalasaSecret resource processing

Signed-off-by: Eamonn Mansour <[email protected]>

* feat: Add GalasaSecret resource processing

Signed-off-by: Eamonn Mansour <[email protected]>

* review: Remove unvalidated values from error messages

Signed-off-by: Eamonn Mansour <[email protected]>

---------

Signed-off-by: Eamonn Mansour <[email protected]>

---------

Signed-off-by: Eamonn Mansour <[email protected]>
  • Loading branch information
eamansour authored Oct 21, 2024
1 parent 01a905e commit 329bce6
Show file tree
Hide file tree
Showing 50 changed files with 2,899 additions and 900 deletions.
10 changes: 10 additions & 0 deletions .secrets.baseline
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,16 @@
"verified_result": null
}
],
"galasa-parent/dev.galasa.framework.api.resources/src/test/java/dev/galasa/framework/api/resources/processors/GalasaSecretProcessorTest.java": [
{
"hashed_secret": "0ea7458942ab65e0a340cf4fd28ca00d93c494f3",
"is_secret": false,
"is_verified": false,
"line_number": 321,
"type": "Secret Keyword",
"verified_result": null
}
],
"run-locally.sh": [
{
"hashed_secret": "8cbd3af3de67a89adedc45b1e3d99b7b135a8ca4",
Expand Down
2 changes: 1 addition & 1 deletion galasa-parent/dev.galasa.framework.api.common/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ plugins {

description = 'Framework API - Common Packages'

version = '0.37.0'
version = '0.38.0'

dependencies {
implementation project(':dev.galasa.framework')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public enum ServletErrorMessage {
GAL5022_UNABLE_TO_PARSE_SHARED_ENVIRONMENT_PHASE (5022, "E: Error occurred trying parse the sharedEnvironmentPhase ''{0}''. Valid options are 'BUILD', 'DISCARD'."),

//Galasa Property...
GAL5023_UNABLE_TO_CAST_TO_GALASAPROPERTY (5023, "E: Error occurred trying to interpret resource ''{0}''. P This could indicate a mis-match between client and server levels. Please check with your Ecosystem administrator the level. You may have to upgrade/downgrade your client program."),
GAL5023_UNABLE_TO_CAST_TO_GALASAPROPERTY (5023, "E: Error occurred trying to interpret resource ''{0}''. This could indicate a mis-match between client and server levels. Please check the level with your Ecosystem administrator. You may have to upgrade/downgrade your client program."),
GAL5024_INVALID_GALASAPROPERTY (5024, "E: Error occurred because the Galasa Property is invalid. ''{0}''"),
GAL5031_EMPTY_NAMESPACE (5031, "E: Invalid namespace. Namespace is empty."),
GAL5032_INVALID_FIRST_CHARACTER_NAMESPACE (5032, "E: Invalid namespace name. ''{0}'' must not start with the ''{1}'' character. Allowable first characters are 'a'-'z' or 'A'-'Z'."),
Expand All @@ -83,11 +83,23 @@ public enum ServletErrorMessage {
GAL5044_INVALID_PROPERTY_NAME_TRAILING_DOT (5044, "E: Invalid property name. Property name ''{0}'' must not end with a '.' (dot) separator."),

//Resources APIs...
GAL5025_UNSUPPORTED_ACTION (5025, "E: Error occurred. The field 'action' in the request body is invalid. The 'action' value''{0}'' supplied is not supported. Supported actions are: create, apply and update. This could indicate a mis-match between client and server levels. Please check with your Ecosystem administrator the level. You may have to upgrade/downgrade your client program."),
GAL5026_UNSUPPORTED_RESOURCE_TYPE (5026, "E: Error occurred. The field 'kind' in the request body is invalid. The value ''{0}'' is not supported. This could indicate a mis-match between client and server levels. Please check with your Ecosystem administrator the level. You may have to upgrade/downgrade your client program."),
GAL5027_UNSUPPORTED_API_VERSION (5027, "E: Error occurred. The field 'apiVersion' in the request body is invalid. The value ''{0}'' is not a supported version. Currently the ecosystem accepts the ''{1}'' api version. This could indicate a mis-match between client and server levels. Please check with your Ecosystem administrator the level. You may have to upgrade/downgrade your client program."),
GAL5025_UNSUPPORTED_ACTION (5025, "E: Error occurred. The field ''action'' in the request body is invalid. Supported actions are: create, apply and update. This could indicate a mis-match between client and server levels. Please check the level with your Ecosystem administrator. You may have to upgrade/downgrade your client program so that the levels of client and server match."),
GAL5026_UNSUPPORTED_RESOURCE_TYPE (5026, "E: Error occurred. The field ''kind'' in the request body is invalid. This could indicate a mis-match between client and server levels. Please check the level with your Ecosystem administrator. You may have to upgrade/downgrade your client program so that the levels of client and server match."),
GAL5027_UNSUPPORTED_API_VERSION (5027, "E: Error occurred. The field ''apiVersion'' in the request body is invalid. Currently the ecosystem accepts the ''{0}'' api version. This could indicate a mis-match between client and server levels. Please check the level with your Ecosystem administrator. You may have to upgrade/downgrade your client program so that the levels of client and server match."),
GAL5067_NULL_RESOURCE_IN_BODY (5067, "E: Error occurred. A ''NULL'' value is not a valid resource. Please check the request format, or check with your Ecosystem administrator."),
GAL5068_EMPTY_JSON_RESOURCE_IN_BODY (5068, "E: Error occurred. The JSON element for a resource can not be empty. Please check the request format, or check with your Ecosystem administrator."),
GAL5069_MISSING_REQUIRED_FIELDS (5069, "E: Invalid request body provided. The following mandatory fields are missing from the request body: [{0}]. Please check that your request body contains these fields and try again."),

// GalasaSecret validation...
GAL5070_INVALID_GALASA_SECRET_MISSING_FIELDS (5070, "E: Invalid GalasaSecret provided. One or more of the following mandatory fields are missing from the ''{0}'' field: [{1}]. Check that your request payload is correct and try again."),
GAL5072_INVALID_GALASA_SECRET_MISSING_TYPE_DATA (5072, "E: Invalid GalasaSecret provided. The ''{0}'' type was provided but the following fields are missing from the ''data'' field: [{1}]. Check that your request payload is correct and try again."),
GAL5073_UNSUPPORTED_GALASA_SECRET_ENCODING (5073, "E: Unsupported data encoding scheme provided. Supported encoding schemes are: [{0}]. Check that your request payload is correct and try again."),
GAL5074_UNKNOWN_GALASA_SECRET_TYPE (5074, "E: Unknown GalasaSecret type provided. Supported GalasaSecret types are: [{0}]. Check that your request payload is correct and try again."),
GAL5075_ERROR_SECRET_ALREADY_EXISTS (5075, "E: Error occurred when trying to create a secret with the given ID. A secret with the provided ID already exists."),
GAL5076_ERROR_SECRET_DOES_NOT_EXIST (5076, "E: Error occurred when trying to update a secret with the given ID. A secret with the provided ID does not exist and therefore cannot be updated."),
GAL5077_FAILED_TO_SET_SECRET (5077, "E: Failed to set a secret with the given ID in the credentials store. The credentials store might be experiencing temporary issues. Report the problem to your Galasa Ecosystem owner."),
GAL5078_FAILED_TO_DELETE_SECRET (5078, "E: Failed to delete a secret with the given ID from the credentials store. The credentials store might be experiencing temporary issues. Report the problem to your Galasa Ecosystem owner."),
GAL5079_FAILED_TO_GET_SECRET (5079, "E: Failed to retrieve the secret with the given ID from the credentials store. A secret with the provided ID does not exist and therefore cannot be updated."),

// Auth APIs...
GAL5051_INVALID_GALASA_TOKEN_PROVIDED (5051, "E: Invalid GALASA_TOKEN value provided. Please ensure you have set the correct GALASA_TOKEN property for the targeted ecosystem at ''{0}'' and try again."),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,29 @@
*/
package dev.galasa.framework.api.common.resources;

public enum GalasaResourceType{
GALASAPROPERTY("GalasaProperty"),
;
private String value;
public enum GalasaResourceType {
GALASA_PROPERTY("GalasaProperty"),
GALASA_SECRET("GalasaSecret");

private GalasaResourceType(String type){
this.value = type;
}
private String name;

public static GalasaResourceType getfromString(String typeAsString){
GalasaResourceType match = null;
for (GalasaResourceType type : GalasaResourceType.values()){
if (type.toString().equalsIgnoreCase(typeAsString)){
match = type;
}
}
return match;
}
private GalasaResourceType(String name) {
this.name = name;
}

@Override
public String toString(){
return value;
public static GalasaResourceType getFromString(String resourceAsString) {
GalasaResourceType match = null;
for (GalasaResourceType resource : values()) {
if (resource.toString().equalsIgnoreCase(resourceAsString.trim())) {
match = resource;
break;
}
}
return match;
}

}
@Override
public String toString() {
return name;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright contributors to the Galasa project
*
* SPDX-License-Identifier: EPL-2.0
*/
package dev.galasa.framework.api.common.resources;

public enum GalasaSecretType {
USERNAME_PASSWORD("UsernamePassword", "username", "password"),
USERNAME_TOKEN("UsernameToken", "username", "token"),
USERNAME("Username", "username"),
TOKEN("Token", "token");

private String name;
private String[] requiredDataFields;

private GalasaSecretType(String type, String... requiredDataFields) {
this.name = type;
this.requiredDataFields = requiredDataFields;
}

public static GalasaSecretType getFromString(String typeAsString) {
GalasaSecretType match = null;
for (GalasaSecretType resource : values()) {
if (resource.toString().equalsIgnoreCase(typeAsString.trim())) {
match = resource;
break;
}
}
return match;
}

@Override
public String toString() {
return name;
}

public String[] getRequiredDataFields() {
return requiredDataFields;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright contributors to the Galasa project
*
* SPDX-License-Identifier: EPL-2.0
*/
package dev.galasa.framework.api.common.resources;

public enum ResourceAction {
APPLY("apply"),
CREATE("create"),
UPDATE("update"),
DELETE("delete");

private String actionLabel;

private ResourceAction(String action) {
this.actionLabel = action;
}

public static ResourceAction getFromString(String actionAsString) {
ResourceAction match = null;
for (ResourceAction action : values()) {
if (action.toString().equalsIgnoreCase(actionAsString.trim())) {
match = action;
break;
}
}
return match;
}

@Override
public String toString() {
return actionLabel;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright contributors to the Galasa project
*
* SPDX-License-Identifier: EPL-2.0
*/
package dev.galasa.framework.api.common.resources;

import dev.galasa.ICredentials;
import dev.galasa.framework.api.common.InternalServletException;
import dev.galasa.framework.api.common.ServletError;
import dev.galasa.framework.spi.creds.CredentialsException;
import dev.galasa.framework.spi.creds.ICredentialsService;

import static dev.galasa.framework.api.common.ServletErrorMessage.*;

import javax.servlet.http.HttpServletResponse;

public class Secret {

private String secretId;
private ICredentialsService credentialsService;
private ICredentials value;

public Secret(ICredentialsService credentialsService, String secretName) {
this.secretId = secretName;
this.credentialsService = credentialsService;
}

public boolean existsInCredentialsStore() {
return value != null;
}

public void loadValueFromCredentialsStore() throws InternalServletException {
try {
value = credentialsService.getCredentials(secretId);
} catch (CredentialsException e) {
ServletError error = new ServletError(GAL5079_FAILED_TO_GET_SECRET);
throw new InternalServletException(error, HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}

public void setSecretToCredentialsStore(ICredentials newValue) throws InternalServletException {
try {
credentialsService.setCredentials(secretId, newValue);
} catch (CredentialsException e) {
ServletError error = new ServletError(GAL5077_FAILED_TO_SET_SECRET);
throw new InternalServletException(error, HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}

public void deleteSecretFromCredentialsStore() throws InternalServletException {
try {
credentialsService.deleteCredentials(secretId);
} catch (CredentialsException e) {
ServletError error = new ServletError(GAL5078_FAILED_TO_DELETE_SECRET);
throw new InternalServletException(error, HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class TestGalasaResourceType {
@Test
public void TestResourceTypeGalasaPropertyReturnGalasaProperty(){
//Given...
GalasaResourceType resourceType = GalasaResourceType.GALASAPROPERTY;
GalasaResourceType resourceType = GalasaResourceType.GALASA_PROPERTY;
//When...
String typeValue = resourceType.toString();
//Then...
Expand All @@ -24,7 +24,7 @@ public void TestResourceTypeGalasaPropertyReturnGalasaProperty(){
@Test
public void TestResourceTypeGalasaPropertyLowerCaseFromStringReturnGalasaProperty(){
//Given...
GalasaResourceType resourceType = GalasaResourceType.getfromString("galasaproperty");
GalasaResourceType resourceType = GalasaResourceType.getFromString("galasaproperty");
//When...
String typeValue = resourceType.toString();
//Then...
Expand All @@ -34,7 +34,7 @@ public void TestResourceTypeGalasaPropertyLowerCaseFromStringReturnGalasaPropert
@Test
public void TestResourceTypeGalasaPropertyUpperCaseFromStringReturnGalasaProperty(){
//Given...
GalasaResourceType resourceType = GalasaResourceType.getfromString("GALASAPROPERTY");
GalasaResourceType resourceType = GalasaResourceType.getFromString("GALASAPROPERTY");
//When...
String typeValue = resourceType.toString();
//Then...
Expand All @@ -44,7 +44,7 @@ public void TestResourceTypeGalasaPropertyUpperCaseFromStringReturnGalasaPropert
@Test
public void TestResourceTypeGalasaPropertyMixedCaseFromStringReturnGalasaProperty(){
//Given...
GalasaResourceType resourceType = GalasaResourceType.getfromString("GaLaSaPrOpErTy");
GalasaResourceType resourceType = GalasaResourceType.getFromString("GaLaSaPrOpErTy");
//When...
String typeValue = resourceType.toString();
//Then...
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package dev.galasa.framework.api.common.mocks;

import java.util.HashMap;
import java.util.Map;

import javax.validation.constraints.NotNull;

import dev.galasa.ICredentials;
import dev.galasa.framework.spi.creds.CredentialsException;
import dev.galasa.framework.spi.creds.ICredentialsService;

public class MockCredentialsService implements ICredentialsService {

private Map<String, ICredentials> creds = new HashMap<>();

private boolean throwError = false;

public MockCredentialsService(Map<String, ICredentials> creds) {
this.creds = creds;
}

@Override
public ICredentials getCredentials(@NotNull String credentialsId) throws CredentialsException {
if (throwError) {
throwMockError();
}
return this.creds.get(credentialsId);
}

@Override
public void setCredentials(String credentialsId, ICredentials credentials) throws CredentialsException {
if (throwError) {
throwMockError();
}
this.creds.put(credentialsId, credentials);
}

@Override
public void deleteCredentials(String credentialsId) throws CredentialsException {
if (throwError) {
throwMockError();
}
this.creds.remove(credentialsId);
}

public Map<String, ICredentials> getAllCredentials() {
return creds;
}

public void setThrowError(boolean throwError) {
this.throwError = throwError;
}

private void throwMockError() throws CredentialsException {
throw new CredentialsException("simulating a credentials service error");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import dev.galasa.framework.spi.creds.ICredentialsService;

import java.net.URL;
import java.util.HashMap;
import java.util.Properties;
import java.util.Random;
import javax.validation.constraints.NotNull;
Expand All @@ -34,6 +35,7 @@ public class MockFramework implements IFramework {
IResultArchiveStore archiveStore;
IFrameworkRuns frameworkRuns;
MockIConfigurationPropertyStoreService cpsService = new MockIConfigurationPropertyStoreService("framework");
MockCredentialsService creds = new MockCredentialsService(new HashMap<>());
IAuthStoreService authStoreService;

public MockFramework() {
Expand Down Expand Up @@ -85,6 +87,11 @@ public IFrameworkRuns getFrameworkRuns() throws FrameworkException {
return this.frameworkRuns;
}

@Override
public @NotNull ICredentialsService getCredentialsService() throws CredentialsException {
return this.creds;
}

@Override
public void setFrameworkProperties(Properties overrideProperties) {
throw new UnsupportedOperationException("Unimplemented method 'setFrameworkProperties'");
Expand Down Expand Up @@ -116,11 +123,6 @@ public boolean isInitialised() {
throw new UnsupportedOperationException("Unimplemented method 'getConfidentialTextService'");
}

@Override
public @NotNull ICredentialsService getCredentialsService() throws CredentialsException {
throw new UnsupportedOperationException("Unimplemented method 'getCredentialsService'");
}

@Override
public String getTestRunName() {
throw new UnsupportedOperationException("Unimplemented method 'getTestRunName'");
Expand Down
Loading

0 comments on commit 329bce6

Please sign in to comment.