fix: Add missing variables in env file in config (#7100)
The env config API currently only changes values that are already defined in the env file. It is not capable of adding anything to the file. This commit adds the capability to do so. However, since we don't want to let the client add just any variable, we've switched from a black list to a white list of env variables that can be managed by this API. If the requested variable is present in the whitelist, we add it, if its missing in the env file.
This commit is contained in:
parent
d94408776f
commit
851abd5a06
|
|
@ -10,6 +10,7 @@ import com.appsmith.server.services.SessionUserService;
|
|||
import com.appsmith.server.services.UserService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
|
|
@ -17,6 +18,7 @@ import java.io.IOException;
|
|||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
|
@ -43,9 +45,29 @@ public class EnvManager {
|
|||
"^(?<name>[A-Z0-9_]+)\\s*=\\s*\"?(?<value>.*?)\"?$"
|
||||
);
|
||||
|
||||
private static final Set<String> VARIABLE_BLACKLIST = Set.of(
|
||||
"APPSMITH_ENCRYPTION_PASSWORD",
|
||||
"APPSMITH_ENCRYPTION_SALT"
|
||||
private static final Set<String> VARIABLE_WHITELIST = Set.of(
|
||||
"APPSMITH_INSTANCE_NAME",
|
||||
"APPSMITH_MONGODB_URI",
|
||||
"APPSMITH_REDIS_URL",
|
||||
"APPSMITH_MAIL_ENABLED",
|
||||
"APPSMITH_MAIL_FROM",
|
||||
"APPSMITH_REPLY_TO",
|
||||
"APPSMITH_MAIL_HOST",
|
||||
"APPSMITH_MAIL_PORT",
|
||||
"APPSMITH_MAIL_USERNAME",
|
||||
"APPSMITH_MAIL_PASSWORD",
|
||||
"APPSMITH_MAIL_SMTP_TLS_ENABLED",
|
||||
"APPSMITH_SIGNUP_DISABLED",
|
||||
"APPSMITH_SIGNUP_ALLOWED_DOMAINS",
|
||||
"APPSMITH_ADMIN_EMAILS",
|
||||
"APPSMITH_RECAPTCHA_SITE_KEY",
|
||||
"APPSMITH_RECAPTCHA_SECRET_KEY",
|
||||
"APPSMITH_GOOGLE_MAPS_API_KEY",
|
||||
"APPSMITH_DISABLE_TELEMETRY",
|
||||
"APPSMITH_OAUTH2_GOOGLE_CLIENT_ID",
|
||||
"APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET",
|
||||
"APPSMITH_OAUTH2_GITHUB_CLIENT_ID",
|
||||
"APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET"
|
||||
);
|
||||
|
||||
/**
|
||||
|
|
@ -57,13 +79,24 @@ public class EnvManager {
|
|||
* @return List of string lines for updated env file content.
|
||||
*/
|
||||
public static List<String> transformEnvContent(String envContent, Map<String, String> changes) {
|
||||
for (final String variable : VARIABLE_BLACKLIST) {
|
||||
if (changes.containsKey(variable)) {
|
||||
throw new AppsmithException(AppsmithError.UNAUTHORIZED_ACCESS);
|
||||
}
|
||||
final Set<String> variablesNotInWhitelist = new HashSet<>(changes.keySet());
|
||||
variablesNotInWhitelist.removeAll(VARIABLE_WHITELIST);
|
||||
|
||||
if (!variablesNotInWhitelist.isEmpty()) {
|
||||
throw new AppsmithException(AppsmithError.UNAUTHORIZED_ACCESS);
|
||||
}
|
||||
|
||||
return envContent.lines()
|
||||
if (changes.containsKey("APPSMITH_MAIL_HOST")) {
|
||||
changes.put("APPSMITH_MAIL_ENABLED", Boolean.toString(StringUtils.isEmpty(changes.get("APPSMITH_MAIL_HOST"))));
|
||||
}
|
||||
|
||||
if (changes.containsKey("APPSMITH_MAIL_USERNAME")) {
|
||||
changes.put("APPSMITH_MAIL_SMTP_AUTH", Boolean.toString(StringUtils.isEmpty(changes.get("APPSMITH_MAIL_USERNAME"))));
|
||||
}
|
||||
|
||||
final Set<String> remainingChangedNames = new HashSet<>(changes.keySet());
|
||||
|
||||
final List<String> outLines = envContent.lines()
|
||||
.map(line -> {
|
||||
final Matcher matcher = ENV_VARIABLE_PATTERN.matcher(line);
|
||||
if (!matcher.matches()) {
|
||||
|
|
@ -73,11 +106,18 @@ public class EnvManager {
|
|||
if (!changes.containsKey(name)) {
|
||||
return line;
|
||||
}
|
||||
remainingChangedNames.remove(name);
|
||||
return line.substring(0, matcher.start("value"))
|
||||
+ changes.get(name)
|
||||
+ line.substring(matcher.end("value"));
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
for (final String name : remainingChangedNames) {
|
||||
outLines.add(name + "=" + changes.get(name));
|
||||
}
|
||||
|
||||
return outLines;
|
||||
}
|
||||
|
||||
public Mono<Void> applyChanges(Map<String, String> changes) {
|
||||
|
|
@ -114,7 +154,7 @@ public class EnvManager {
|
|||
final Matcher matcher = ENV_VARIABLE_PATTERN.matcher(line);
|
||||
if (matcher.matches()) {
|
||||
final String name = matcher.group("name");
|
||||
if (!VARIABLE_BLACKLIST.contains(name)) {
|
||||
if (VARIABLE_WHITELIST.contains(name)) {
|
||||
data.put(name, matcher.group("value"));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package com.appsmith.server.solutions;
|
||||
|
||||
import com.appsmith.server.exceptions.AppsmithError;
|
||||
import com.appsmith.server.exceptions.AppsmithException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
|
@ -8,6 +10,7 @@ import org.springframework.test.context.junit4.SpringRunner;
|
|||
import java.util.Map;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@Slf4j
|
||||
|
|
@ -15,117 +18,116 @@ public class EnvManagerTest {
|
|||
|
||||
@Test
|
||||
public void simpleSample() {
|
||||
final String content = "VAR_1=first value\nVAR_2=second value\n\nVAR_3=third value";
|
||||
final String content = "APPSMITH_MONGODB_URI=first value\nAPPSMITH_REDIS_URL=second value\n\nAPPSMITH_INSTANCE_NAME=third value";
|
||||
|
||||
assertThat(EnvManager.transformEnvContent(
|
||||
content,
|
||||
Map.of("VAR_1", "new first value")
|
||||
Map.of("APPSMITH_MONGODB_URI", "new first value")
|
||||
)).containsExactly(
|
||||
"VAR_1=new first value",
|
||||
"VAR_2=second value",
|
||||
"APPSMITH_MONGODB_URI=new first value",
|
||||
"APPSMITH_REDIS_URL=second value",
|
||||
"",
|
||||
"VAR_3=third value"
|
||||
"APPSMITH_INSTANCE_NAME=third value"
|
||||
);
|
||||
|
||||
assertThat(EnvManager.transformEnvContent(
|
||||
content,
|
||||
Map.of("VAR_2", "new second value")
|
||||
Map.of("APPSMITH_REDIS_URL", "new second value")
|
||||
)).containsExactly(
|
||||
"VAR_1=first value",
|
||||
"VAR_2=new second value",
|
||||
"APPSMITH_MONGODB_URI=first value",
|
||||
"APPSMITH_REDIS_URL=new second value",
|
||||
"",
|
||||
"VAR_3=third value"
|
||||
"APPSMITH_INSTANCE_NAME=third value"
|
||||
);
|
||||
|
||||
assertThat(EnvManager.transformEnvContent(
|
||||
content,
|
||||
Map.of("VAR_3", "new third value")
|
||||
Map.of("APPSMITH_INSTANCE_NAME", "new third value")
|
||||
)).containsExactly(
|
||||
"VAR_1=first value",
|
||||
"VAR_2=second value",
|
||||
"APPSMITH_MONGODB_URI=first value",
|
||||
"APPSMITH_REDIS_URL=second value",
|
||||
"",
|
||||
"VAR_3=new third value"
|
||||
"APPSMITH_INSTANCE_NAME=new third value"
|
||||
);
|
||||
|
||||
assertThat(EnvManager.transformEnvContent(
|
||||
content,
|
||||
Map.of(
|
||||
"VAR_1", "new first value",
|
||||
"VAR_3", "new third value"
|
||||
"APPSMITH_MONGODB_URI", "new first value",
|
||||
"APPSMITH_INSTANCE_NAME", "new third value"
|
||||
)
|
||||
)).containsExactly(
|
||||
"VAR_1=new first value",
|
||||
"VAR_2=second value",
|
||||
"APPSMITH_MONGODB_URI=new first value",
|
||||
"APPSMITH_REDIS_URL=second value",
|
||||
"",
|
||||
"VAR_3=new third value"
|
||||
"APPSMITH_INSTANCE_NAME=new third value"
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void emptyValues() {
|
||||
final String content = "VAR_1=first value\nVAR_2=\n\nVAR_3=third value";
|
||||
final String content = "APPSMITH_MONGODB_URI=first value\nAPPSMITH_REDIS_URL=\n\nAPPSMITH_INSTANCE_NAME=third value";
|
||||
|
||||
assertThat(EnvManager.transformEnvContent(
|
||||
content,
|
||||
Map.of("VAR_2", "new second value")
|
||||
Map.of("APPSMITH_REDIS_URL", "new second value")
|
||||
)).containsExactly(
|
||||
"VAR_1=first value",
|
||||
"VAR_2=new second value",
|
||||
"APPSMITH_MONGODB_URI=first value",
|
||||
"APPSMITH_REDIS_URL=new second value",
|
||||
"",
|
||||
"VAR_3=third value"
|
||||
"APPSMITH_INSTANCE_NAME=third value"
|
||||
);
|
||||
|
||||
assertThat(EnvManager.transformEnvContent(
|
||||
content,
|
||||
Map.of("VAR_2", "")
|
||||
Map.of("APPSMITH_REDIS_URL", "")
|
||||
)).containsExactly(
|
||||
"VAR_1=first value",
|
||||
"VAR_2=",
|
||||
"APPSMITH_MONGODB_URI=first value",
|
||||
"APPSMITH_REDIS_URL=",
|
||||
"",
|
||||
"VAR_3=third value"
|
||||
"APPSMITH_INSTANCE_NAME=third value"
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void quotedValues() {
|
||||
final String content = "VAR_1=first value\nVAR_2=\"quoted value\"\n\nVAR_3=third value";
|
||||
final String content = "APPSMITH_MONGODB_URI=first value\nAPPSMITH_REDIS_URL=\"quoted value\"\n\nAPPSMITH_INSTANCE_NAME=third value";
|
||||
|
||||
assertThat(EnvManager.transformEnvContent(
|
||||
content,
|
||||
Map.of(
|
||||
"VAR_1", "new first value",
|
||||
"VAR_2", "new second value"
|
||||
"APPSMITH_MONGODB_URI", "new first value",
|
||||
"APPSMITH_REDIS_URL", "new second value"
|
||||
)
|
||||
)).containsExactly(
|
||||
"VAR_1=new first value",
|
||||
"VAR_2=\"new second value\"",
|
||||
"APPSMITH_MONGODB_URI=new first value",
|
||||
"APPSMITH_REDIS_URL=\"new second value\"",
|
||||
"",
|
||||
"VAR_3=third value"
|
||||
"APPSMITH_INSTANCE_NAME=third value"
|
||||
);
|
||||
|
||||
assertThat(EnvManager.transformEnvContent(
|
||||
content,
|
||||
Map.of("VAR_2", "")
|
||||
Map.of("APPSMITH_REDIS_URL", "")
|
||||
)).containsExactly(
|
||||
"VAR_1=first value",
|
||||
"VAR_2=\"\"",
|
||||
"APPSMITH_MONGODB_URI=first value",
|
||||
"APPSMITH_REDIS_URL=\"\"",
|
||||
"",
|
||||
"VAR_3=third value"
|
||||
"APPSMITH_INSTANCE_NAME=third value"
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseTest() {
|
||||
|
||||
assertThat(EnvManager.parseToMap(
|
||||
"VAR_1=first value\nVAR_2=second value\n\nVAR_3=third value"
|
||||
"APPSMITH_MONGODB_URI=first value\nAPPSMITH_REDIS_URL=second value\n\nAPPSMITH_INSTANCE_NAME=third value"
|
||||
)).containsExactlyInAnyOrderEntriesOf(Map.of(
|
||||
"VAR_1", "first value",
|
||||
"VAR_2", "second value",
|
||||
"VAR_3", "third value"
|
||||
"APPSMITH_MONGODB_URI", "first value",
|
||||
"APPSMITH_REDIS_URL", "second value",
|
||||
"APPSMITH_INSTANCE_NAME", "third value"
|
||||
));
|
||||
|
||||
}
|
||||
|
|
@ -134,11 +136,11 @@ public class EnvManagerTest {
|
|||
public void parseEmptyValues() {
|
||||
|
||||
assertThat(EnvManager.parseToMap(
|
||||
"VAR_1=first value\nVAR_2=\n\nVAR_3=third value"
|
||||
"APPSMITH_MONGODB_URI=first value\nAPPSMITH_REDIS_URL=\n\nAPPSMITH_INSTANCE_NAME=third value"
|
||||
)).containsExactlyInAnyOrderEntriesOf(Map.of(
|
||||
"VAR_1", "first value",
|
||||
"VAR_2", "",
|
||||
"VAR_3", "third value"
|
||||
"APPSMITH_MONGODB_URI", "first value",
|
||||
"APPSMITH_REDIS_URL", "",
|
||||
"APPSMITH_INSTANCE_NAME", "third value"
|
||||
));
|
||||
|
||||
}
|
||||
|
|
@ -147,12 +149,47 @@ public class EnvManagerTest {
|
|||
public void parseQuotedValues() {
|
||||
|
||||
assertThat(EnvManager.parseToMap(
|
||||
"VAR_1=first value\nVAR_2=\"quoted value\"\n\nVAR_3=third value"
|
||||
"APPSMITH_MONGODB_URI=first value\nAPPSMITH_REDIS_URL=\"quoted value\"\n\nAPPSMITH_INSTANCE_NAME=third value"
|
||||
)).containsExactlyInAnyOrderEntriesOf(Map.of(
|
||||
"VAR_1", "first value",
|
||||
"VAR_2", "quoted value",
|
||||
"VAR_3", "third value"
|
||||
"APPSMITH_MONGODB_URI", "first value",
|
||||
"APPSMITH_REDIS_URL", "quoted value",
|
||||
"APPSMITH_INSTANCE_NAME", "third value"
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void disallowedVariable() {
|
||||
final String content = "APPSMITH_MONGODB_URI=first value\nDISALLOWED_NASTY_STUFF=\"quoted value\"\n\nAPPSMITH_INSTANCE_NAME=third value";
|
||||
|
||||
assertThatThrownBy(() -> EnvManager.transformEnvContent(
|
||||
content,
|
||||
Map.of(
|
||||
"APPSMITH_MONGODB_URI", "new first value",
|
||||
"DISALLOWED_NASTY_STUFF", "new second value"
|
||||
)
|
||||
))
|
||||
.matches(value -> value instanceof AppsmithException
|
||||
&& AppsmithError.UNAUTHORIZED_ACCESS.equals(((AppsmithException) value).getError()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addNewVariable() {
|
||||
final String content = "APPSMITH_MONGODB_URI=first value\nAPPSMITH_REDIS_URL=\"quoted value\"\n\nAPPSMITH_INSTANCE_NAME=third value";
|
||||
|
||||
assertThat(EnvManager.transformEnvContent(
|
||||
content,
|
||||
Map.of(
|
||||
"APPSMITH_MONGODB_URI", "new first value",
|
||||
"APPSMITH_DISABLE_TELEMETRY", "false"
|
||||
)
|
||||
)).containsExactly(
|
||||
"APPSMITH_MONGODB_URI=new first value",
|
||||
"APPSMITH_REDIS_URL=\"quoted value\"",
|
||||
"",
|
||||
"APPSMITH_INSTANCE_NAME=third value",
|
||||
"APPSMITH_DISABLE_TELEMETRY=false"
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user