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

Add GalasaSecret resource type in resources route and add secrets encryption/decryption #660

Merged
merged 2 commits into from
Oct 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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