Skip to content

Commit b57f358

Browse files
wagnerluis1982wilkinsona
authored andcommitted
Allow the user that runs the app to be specified via an env var
See gh-16973
1 parent ea6d9f3 commit b57f358

File tree

7 files changed

+94
-0
lines changed

7 files changed

+94
-0
lines changed

spring-boot-project/spring-boot-docs/src/main/asciidoc/deployment.adoc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,11 @@ The following environment properties are supported with the default script:
708708
The default depends on the way the jar was built but is usually `auto` (meaning it tries to guess if it is an init script by checking if it is a symlink in a directory called `init.d`).
709709
You can explicitly set it to `service` so that the `stop\|start\|status\|restart` commands work or to `run` if you want to run the script in the foreground.
710710

711+
| `RUN_AS_USER`
712+
| If set, the application will be executed as the informed user.
713+
For security reasons, you should never run an user space application as `root`, therefore it's recommended to set this property.
714+
Defaults to the user who owns the jar file.
715+
711716
| `USE_START_STOP_DAEMON`
712717
| Whether the `start-stop-daemon` command, when it's available, should be used to control the process.
713718
Defaults to `true`.

spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/resources/org/springframework/boot/loader/tools/launch.script

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,26 @@ log_file="$LOG_FOLDER/$LOG_FILENAME"
128128
# shellcheck disable=SC2012
129129
[[ $(id -u) == "0" ]] && run_user=$(ls -ld "$jarfile" | awk '{print $3}')
130130

131+
# Force run as informed user (from environment variable)
132+
if [[ -n "$RUN_AS_USER" ]]; then
133+
# checks performed for all actions except 'status' and 'run'
134+
if ! [[ "$action" =~ ^(status|run)$ ]]; then
135+
# Issue a error if informed user is not valid
136+
id -u "$RUN_AS_USER" || {
137+
echoRed "Cannot run as '$RUN_AS_USER': no such user"
138+
exit 5
139+
}
140+
141+
# Issue a error if we are not root
142+
[[ $(id -u) == 0 ]] || {
143+
echoRed "root required to run as '$RUN_AS_USER'"
144+
exit 6
145+
}
146+
fi
147+
148+
run_user="$RUN_AS_USER"
149+
fi
150+
131151
# Issue a warning if the application will run as root
132152
[[ $(id -u ${run_user}) == "0" ]] && { echoYellow "Application is running as root (UID 0). This is considered insecure."; }
133153

spring-boot-tests/spring-boot-integration-tests/spring-boot-launch-script-tests/src/test/java/org/springframework/boot/launchscript/SysVinitLaunchScriptIT.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,36 @@ public void launchWithRelativeLogFolder(String os, String version) throws Except
267267
assertThat(output).contains("Log written");
268268
}
269269

270+
@ParameterizedTest(name = "{0} {1}")
271+
@MethodSource("parameters")
272+
public void launchWithRunAs(String os, String version) throws Exception {
273+
String output = doTest(os, version, "launch-with-run-as.sh");
274+
assertThat(output).contains("wagner root");
275+
}
276+
277+
@ParameterizedTest(name = "{0} {1}")
278+
@MethodSource("parameters")
279+
public void launchWithRunAsInvalidUser(String os, String version) throws Exception {
280+
String output = doTest(os, version, "launch-with-run-as-invalid-user.sh");
281+
assertThat(output).contains("Status: 5");
282+
assertThat(output).has(coloredString(AnsiColor.RED, "Cannot run as 'johndoe': no such user"));
283+
}
284+
285+
@ParameterizedTest(name = "{0} {1}")
286+
@MethodSource("parameters")
287+
public void launchWithRunAsPreferUserInformed(String os, String version) throws Exception {
288+
String output = doTest(os, version, "launch-with-run-as-prefer-user-informed.sh");
289+
assertThat(output).contains("wagner root");
290+
}
291+
292+
@ParameterizedTest(name = "{0} {1}")
293+
@MethodSource("parameters")
294+
public void launchWithRunAsRootRequired(String os, String version) throws Exception {
295+
String output = doTest(os, version, "launch-with-run-as-root-required.sh");
296+
assertThat(output).contains("Status: 6");
297+
assertThat(output).has(coloredString(AnsiColor.RED, "root required to run as 'wagner'"));
298+
}
299+
270300
static List<Object[]> parameters() {
271301
List<Object[]> parameters = new ArrayList<>();
272302
for (File os : new File("src/test/resources/conf").listFiles()) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
source ./test-functions.sh
2+
install_service
3+
4+
echo 'RUN_AS_USER=johndoe' > /test-service/spring-boot-app.conf
5+
6+
start_service
7+
echo "Status: $?"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
source ./test-functions.sh
2+
install_service
3+
4+
useradd wagner
5+
echo 'RUN_AS_USER=wagner' > /test-service/spring-boot-app.conf
6+
7+
useradd phil
8+
chown phil /test-service/spring-boot-app.jar
9+
10+
start_service
11+
await_app
12+
13+
ls -la /var/log/spring-boot-app.log
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
source ./test-functions.sh
2+
install_service
3+
4+
useradd wagner
5+
echo 'RUN_AS_USER=wagner' > /test-service/spring-boot-app.conf
6+
echo "JAVA_HOME='$JAVA_HOME'" >> /test-service/spring-boot-app.conf
7+
8+
su - wagner -c "$(which service) spring-boot-app start"
9+
echo "Status: $?"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
source ./test-functions.sh
2+
install_service
3+
4+
useradd wagner
5+
echo 'RUN_AS_USER=wagner' > /test-service/spring-boot-app.conf
6+
7+
start_service
8+
await_app
9+
10+
ls -la /var/log/spring-boot-app.log

0 commit comments

Comments
 (0)