com.codacy.scoobydoo.configuration.Configuration Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of scooby-doo-fwk Show documentation
Show all versions of scooby-doo-fwk Show documentation
Automated testing framework
package com.codacy.scoobydoo.configuration;
import com.codacy.scoobydoo.Constant.Key;
import com.codacy.scoobydoo.Constant.Status;
import com.codacy.scoobydoo.Decryptor;
import com.codacy.scoobydoo.LoggingHelper;
import software.amazon.awssdk.services.ssm.model.ParameterNotFoundException;
import software.amazon.awssdk.services.sts.model.ExpiredTokenException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.Duration;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Properties;
public class Configuration {
public static class Timeout {
public Duration DEFAULT_TIMEOUT;
public Duration DEFAULT_POLLING;
public Duration ENDPOINT_MEDIUM_WAIT;
public Duration ENDPOINT_HIGH_WAIT;
public Duration ENDPOINT_MAX_WAIT;
public Duration FIND_ELEMENT_WAIT_TIMEOUT;
public Duration LONG_POLLING;
public Duration LONG_WAIT_TIMEOUT;
public Duration PAGE_LOAD_TIMEOUT;
public Duration SCRIPT_TIMEOUT;
public Timeout(Properties properties) {
final List timeoutConfigKeys = Arrays.asList(
Key.TIMEOUT_DEFAULT,
Key.TIMEOUT_POLLING_DEFAULT,
Key.TIMEOUT_ENDPOINT_MEDIUM_WAIT,
Key.TIMEOUT_ENDPOINT_HIGH_WAIT,
Key.TIMEOUT_ENDPOINT_MAX_WAIT,
Key.TIMEOUT_FIND_ELEMENT_WAIT,
Key.TIMEOUT_LONG_POLLING,
Key.TIMEOUT_LONG_WAIT,
Key.TIMEOUT_PAGE_LOAD,
Key.TIMEOUT_SCRIPT);
timeoutConfigKeys.forEach(key -> {
String value = Objects.requireNonNull(properties.getProperty(key),
"Value for key [" + key + "] was not found.");
Duration duration = Duration.ofSeconds(Long.parseLong(value));
switch (key) {
case Key.TIMEOUT_DEFAULT -> DEFAULT_TIMEOUT = duration;
case Key.TIMEOUT_POLLING_DEFAULT -> DEFAULT_POLLING = duration;
case Key.TIMEOUT_ENDPOINT_MEDIUM_WAIT -> ENDPOINT_MEDIUM_WAIT = duration;
case Key.TIMEOUT_ENDPOINT_HIGH_WAIT -> ENDPOINT_HIGH_WAIT = duration;
case Key.TIMEOUT_ENDPOINT_MAX_WAIT -> ENDPOINT_MAX_WAIT = duration;
case Key.TIMEOUT_FIND_ELEMENT_WAIT -> FIND_ELEMENT_WAIT_TIMEOUT = duration;
case Key.TIMEOUT_LONG_POLLING -> LONG_POLLING = duration;
case Key.TIMEOUT_LONG_WAIT -> LONG_WAIT_TIMEOUT = duration;
case Key.TIMEOUT_PAGE_LOAD -> PAGE_LOAD_TIMEOUT = duration;
case Key.TIMEOUT_SCRIPT -> SCRIPT_TIMEOUT = duration;
default -> {
final String errorMessage = "Key [" + key + "] was not expected.";
IllegalArgumentException exception = new IllegalArgumentException(errorMessage);
LoggingHelper.error(errorMessage, exception);
throw exception;
}
}
});
}
}
private final Decryptor decryptor;
private final Properties properties;
private SsmClientWrapper ssmClientWrapper;
private final Timeout timeout;
public Configuration(String environment, String aws) {
Objects.requireNonNull(environment);
Objects.requireNonNull(aws);
properties = loadProperties(environment);
timeout = new Timeout(properties);
decryptor = new Decryptor(getEnvironmentVariableRawValue("ENCRYPTION_KEY", false));
setAWSConfiguration(aws);
setRateLimitCookieProperty();
setHeadlessModeValue();
}
public void addProperty(String key, String value) {
if (key == null || value == null || key.isEmpty() || value.isEmpty()) {
IllegalArgumentException illegalArgumentException = new IllegalArgumentException("Key or value is empty.");
LoggingHelper.error("Error adding property.", illegalArgumentException);
throw illegalArgumentException;
} else {
properties.setProperty(key, value);
}
}
public Properties getConfiguration() {
return properties;
}
public String getData(String key) {
return getData(key, false);
}
public String getEncryptedData(String key) {
return getData(key, true);
}
// Use this instead of getEncryptedData to improve speed when you already know that the value you're looking for is
// loaded in the Properties object.
public String getEncryptedProperty(String key) {
return getDecryptedValue(properties.getProperty(key), true);
}
// Use this instead of getData to improve speed when you already know that the value you're looking for is
// loaded in the Properties object.
public String getProperty(String key) {
return properties.getProperty(key);
}
public String getSsmParameter(String key, Boolean encrypted) {
assertSsmClientIsDefined();
return ssmClientWrapper.getParameter(key, encrypted, true);
}
public Timeout getTimeout() {
return timeout;
}
// use this to retrieve properties values that only accept "enabled" and "disabled" values (like an on/off
// switch), converting them to boolean values, and ensuring that they are properly set.
public boolean isSwitchConfigValueOn(String parameterName) {
return isSwitchConfigValueOn(getData(parameterName), parameterName);
}
public void setAWSConfiguration(String aws) {
String awsParameterStoreConfiguration = getEnvironmentVariableValue("AWS_PARAMETER_STORE", false);
if (awsParameterStoreConfiguration == null) {
awsParameterStoreConfiguration = Status.ENABLED;
}
boolean awsConfigIsEnabled = isSwitchConfigValueOn(aws, "aws");
boolean awsParameterStorConfigurationIsEnabled = isSwitchConfigValueOn(awsParameterStoreConfiguration, "awsParameterStoreConfiguration");
if (awsConfigIsEnabled && awsParameterStorConfigurationIsEnabled) {
this.addProperty("awsParameterStore", Status.ENABLED);
this.ssmClientWrapper = getSsmClient();
assertAWSTokenHasNotExpired();
} else {
this.addProperty("awsParameterStore", Status.DISABLED);
}
}
public void setRateLimitCookieProperty() {
try {
String cookieRateLimit = "cookieratelimit=" + getData("cookieRateLimitSsm");
this.addProperty("cookieRateLimit", cookieRateLimit);
} catch (IllegalArgumentException ignored) {
LoggingHelper.info("Cookie Rate Limit was not found in the configuration file and will not be set.");
}
}
public void setSsmParameter(String key, String value, Boolean secure) {
assertSsmClientIsDefined();
ssmClientWrapper.putParameter(key, value, secure);
}
private void assertAWSTokenHasNotExpired() {
try {
ssmClientWrapper.getParameter("justToTestIfTokenHasExpired", false, true);
} catch(ExpiredTokenException e) {
LoggingHelper.error("The AWS token has expired. Login (or re-login) in AWS and try again.", e);
throw e;
} catch(ParameterNotFoundException ignored) {}
}
private void assertSsmClientIsDefined() {
if(ssmClientWrapper == null) {
final String errorMessage = "The SSM Client wrapper was not configured and therefore it does not exist, so no SSM operations are possible.";
IllegalStateException exception = new IllegalStateException(errorMessage);
LoggingHelper.error(errorMessage, exception);
throw exception;
}
}
private String getData(String key, boolean isEncrypted) {
String valueFromEnvFile = getEnvironmentVariableValue(key, isEncrypted);
if (valueFromEnvFile != null) {
return valueFromEnvFile;
} else {
return getDataFromConfigurationFile(key, isEncrypted);
}
}
private String getDataFromConfigurationFile(String key, boolean isEncrypted) {
Object value = properties.get(key);
if (value == null) {
IllegalArgumentException illegalArgumentException =
new IllegalArgumentException("Property [" + key + "] is not defined on the properties file.");
LoggingHelper.error("Error getting key." + key, illegalArgumentException);
throw illegalArgumentException;
} else {
String valueStr = value.toString();
String[] valueSpliced = valueStr.split(":");
String outputValue;
if (valueSpliced[0].equals("ssm")) {
outputValue = getSsmParameter(valueSpliced[1], isEncrypted);
if(outputValue == null || outputValue.isEmpty()) {
final String errorMessage = "SSM value for key [" + key + "] was empty.";
RuntimeException exception = new RuntimeException(errorMessage);
LoggingHelper.error(errorMessage, exception);
throw exception;
}
} else {
outputValue = getDecryptedValue(valueStr, isEncrypted);
if(outputValue == null || outputValue.isEmpty()) {
final String errorMessage = "Value for key [" + key + "] was empty.";
RuntimeException exception = new RuntimeException(errorMessage);
LoggingHelper.error(errorMessage, exception);
throw exception;
}
}
return outputValue;
}
}
private String getDecryptedValue(String value, boolean isEncrypted) {
if (isEncrypted) {
return decryptor.decrypt(value);
} else {
return value;
}
}
private String getEnv(String key) {
return System.getenv(key.toUpperCase());
}
private String getEnvironmentVariableRawValue(String key, boolean canBeNull) {
String value = getEnv(key);
if (!canBeNull && value == null) {
final String errorMessage = "Environment Variable [" + key + "] is not defined.";
IllegalArgumentException exception = new IllegalArgumentException(errorMessage);
LoggingHelper.error("Error getting environment variable.", exception);
throw exception;
} else {
return value;
}
}
private String getEnvironmentVariableValue(String key, boolean isEncrypted) {
String value = getEnvironmentVariableRawValue(key, true);
if (value == null) {
LoggingHelper.debug("No environment variable found for value [" + key + "]. Going to search for it on the configuration file.");
return null;
} else {
return getDecryptedValue(value, isEncrypted);
}
}
private SsmClientWrapper getSsmClient() {
return new SsmClientWrapper(getEnvironmentVariableRawValue("AWS_PROFILE", false));
}
private boolean isSwitchConfigValueOn(String value, String valueName) {
if(value == null) {
throw new IllegalArgumentException("No value was found for parameter [" + valueName + "].");
} else if(!value.equals(Status.ENABLED) && !value.equals(Status.DISABLED)) {
throw new IllegalArgumentException(
"Invalid value [" + value + "] for parameter [" + valueName + "]. It should be ["
+ Status.ENABLED + "] or [" + Status.DISABLED + "] (case-sensitive).");
} else {
return value.equals(Status.ENABLED);
}
}
private Properties loadProperties(String environment) {
InputStream input;
try {
input = Files.newInputStream(Paths.get("src/test/resources/" + environment + ".properties"));
Properties properties = new Properties();
properties.load(input);
return properties;
} catch (IOException e) {
final String errorMessage = "Failed to load properties file for environment ["
+ environment + "]. Check if the target environment and corresponding file exist.";
LoggingHelper.error(errorMessage, e);
throw new IllegalArgumentException(errorMessage, e);
}
}
private void setHeadlessModeValue() {
String headlessMode = getEnvironmentVariableValue("HEADLESS_MODE", false);
String status = (headlessMode != null && headlessMode.equals(Status.ENABLED)) ? Status.ENABLED : Status.DISABLED;
properties.setProperty("headlessMode", status);
}
}