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

Commit

Permalink
feat: Refactoring, re-creating secondary groups fixed (#78)
Browse files Browse the repository at this point in the history
Creating groups refactored to a reusable function
Issue when secondary groups were not correctly re-created upon container restart is fixed
  • Loading branch information
lholota committed Sep 1, 2021
1 parent a747d26 commit 5fec309
Show file tree
Hide file tree
Showing 14 changed files with 233 additions and 47 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
* text=auto
*.sh eol=lf
**/sbin/** eol=lf
**/run eol=lf
*/services.d/* eol=lf
**/run eol=lf
Expand Down
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"files.eol": "\n"
}
1 change: 1 addition & 0 deletions alpine/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ services:
build: .
image: homecentr/base:alpine-local
environment:
PUID_ADDITIONAL_GROUPS: "9005:test-group"
FILE__TEST_VAR: "/var-value.txt"
UNRELATED: "some-var"
volumes:
Expand Down
22 changes: 13 additions & 9 deletions alpine/fs/etc/cont-init.d/01-env.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#!/usr/bin/with-contenv ash

source homecentr_set_s6_env_var

MATCHING_FILES=$(find /var/run/s6/container_environment/ -name "FILE__*" | wc -l)

if [ $MATCHING_FILES -le 0 ]; then
Expand All @@ -9,14 +11,16 @@ fi
for FULL_FILENAME in /var/run/s6/container_environment/FILE__*; do
FILENAME="${FULL_FILENAME#'/var/run/s6/container_environment/'}"

#if [[ $FILENAME = "FILE__"* ]]; then
VAR_VALUE_FILE=$(cat ${FULL_FILENAME})
VAR_NAME="${FILENAME#'FILE__'}"
VAR_VALUE_FILE=$(cat ${FULL_FILENAME})
VAR_NAME="${FILENAME#'FILE__'}"

if [ -f "$VAR_VALUE_FILE" ]; then
VAR_VALUE=$(cat "$VAR_VALUE_FILE")

homecentr_set_s6_env_var "$VAR_NAME" "$VAR_VALUE"

if [ -f "$VAR_VALUE_FILE" ]; then
cat "$VAR_VALUE_FILE" > "/var/run/s6/container_environment/${VAR_NAME}"
echo "[env-vars] Variable $VAR_NAME set from ${VAR_VALUE_FILE}"
else
echo "[env-vars] Variable $VAR_NAME could not be set from ${VAR_VALUE_FILE}. File not found."
fi
echo "[env-vars] Variable $VAR_NAME set from ${VAR_VALUE_FILE}"
else
echo "[env-vars] Variable $VAR_NAME could not be set from ${VAR_VALUE_FILE}. File not found."
fi
done
58 changes: 21 additions & 37 deletions alpine/fs/etc/cont-init.d/10-init.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
#!/usr/bin/with-contenv ash
source homecentr_create_group
source homecentr_print_banner
source homecentr_print_context
source homecentr_set_s6_env_var

EXEC_GROUP="root"
EXEC_USER="root"

Expand All @@ -15,16 +20,6 @@ then
exit 2
fi

### Verify required packages are available
if [ "$PGID" != "0" ] || [ "$PUID" != "0" ]
then
if ( ! type "addgroup" > /dev/null; ) || ( ! type "adduser" > /dev/null; )
then
>&2 echo "Cannot create user/group, please install shadow package!"
exit 1
fi
fi

### Create primary group
if [ "$PGID" -ne "0" ]
then
Expand All @@ -37,16 +32,8 @@ then
deluser nonroot
fi

# Check if the group exists already
cat /etc/group | grep ^nonroot: > /dev/null
homecentr_create_group "nonroot" "$PGID"

if [ $? == 0 ]
then
# Group already exists, delete it
delgroup nonroot
fi

addgroup -g $PGID nonroot
EXEC_GROUP="nonroot"
fi

Expand All @@ -61,6 +48,13 @@ fi
### Create groups
if [[ ! -z $PUID_ADDITIONAL_GROUPS ]]
then
echo "$PUID_ADDITIONAL_GROUPS" | egrep '^[0-9]+\:[a-zA-Z0-9_-]+(,[0-9]+\:[a-zA-Z0-9_-]+)*$' > /dev/null

if [ "$?" != "0" ]; then
>&2 echo "The value $PUID_ADDITIONAL_GROUPS is invalid. Valid format is <gid1>:<group-name1>,<gid2>:<group-name2>"
exit 2
fi

# Expecting string in format "gid:name,gid:name"
GROUPS=$(echo $PUID_ADDITIONAL_GROUPS | tr "," "\n")

Expand All @@ -69,27 +63,17 @@ then
GRP_ID=$(echo $GROUP | cut -d ':' -f 1)
GRP_NAME=$(echo $GROUP | cut -d ':' -f 2)

# Create group
addgroup -g "$GRP_ID" "$GRP_NAME"
# Create group (delete if already exists)
homecentr_create_group "$GRP_NAME" "$GRP_ID"

# Add user to the group
addgroup "$EXEC_USER" "$GRP_NAME"
done
fi

echo '
__ __ __
/ / / /___ ____ ___ ___ ________ ____ / /______
/ /_/ / __ \/ __ `__ \/ _ \/ ___/ _ \/ __ \/ __/ ___/
/ __ / /_/ / / / / / / __/ /__/ __/ / / / /_/ /
/_/ /_/\____/_/ /_/ /_/\___/\___/\___/_/ /_/\__/_/
'
echo "
-------------------------------------
User uid: $(id -u $EXEC_USER)
User gid: $(id -g $EXEC_GROUP)
-------------------------------------
"

# Write the variable so that the runas script can use it
echo "$EXEC_USER" > /var/run/s6/container_environment/EXEC_USER
homecentr_print_banner

# Write the variable so that other scripts can use it
homecentr_set_s6_env_var "EXEC_USER" "$EXEC_USER"

homecentr_print_context
17 changes: 17 additions & 0 deletions alpine/fs/usr/sbin/homecentr_create_group
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/with-contenv ash

homecentr_create_group() {
# $1 = Group name
# $2 = Group ID

# Check if the group exists already
cat /etc/group | grep "^$1:" > /dev/null

if [ $? == 0 ]
then
# Group already exists, delete it
delgroup "$1"
fi

addgroup -g "$2" "$1"
}
13 changes: 13 additions & 0 deletions alpine/fs/usr/sbin/homecentr_print_banner
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/with-contenv ash

homecentr_print_banner() {

echo '
__ __ __
/ / / /___ ____ ___ ___ ________ ____ / /______
/ /_/ / __ \/ __ `__ \/ _ \/ ___/ _ \/ __ \/ __/ ___/
/ __ / /_/ / / / / / / __/ /__/ __/ / / / /_/ /
/_/ /_/\____/_/ /_/ /_/\___/\___/\___/_/ /_/\__/_/
'

}
15 changes: 15 additions & 0 deletions alpine/fs/usr/sbin/homecentr_print_context
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/with-contenv ash

homecentr_print_context() {

# The gids script filters out the primary group so it matches the structure of the env vars passed to the container

echo "
-------------------------------------
User uid: $(id -u $EXEC_USER)
User gid: $(id -g $EXEC_USER)
User additional gids: $(id -G $EXEC_USER | tr ' ' '\n' | grep -v "^$(id -g $EXEC_USER)$" | tr '\n' ',' | sed 's/,*$//g')
-------------------------------------
"

}
8 changes: 8 additions & 0 deletions alpine/fs/usr/sbin/homecentr_set_s6_env_var
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/usr/bin/with-contenv ash

homecentr_set_s6_env_var() {
# $1 = Variable name
# $2 = Variable value

echo "$2" > "/var/run/s6/container_environment/$1"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import helpers.BaseDockerImageTagResolver;
import helpers.Image;
import io.homecentr.testcontainers.containers.GenericContainerEx;
import io.homecentr.testcontainers.containers.wait.strategy.WaitEx;
import io.homecentr.testcontainers.images.PullPolicyEx;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testcontainers.containers.ContainerLaunchException;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.output.Slf4jLogConsumer;

import java.nio.file.Paths;
import java.time.Duration;

import static io.homecentr.testcontainers.WaitLoop.waitFor;

public class BaseRunningWithInvalidSecondaryGroupsAsNonRootShould {
private static final Logger logger = LoggerFactory.getLogger(BaseRunningAsRootShould.class);

private static GenericContainerEx _container;

@BeforeClass
public static void before(){
_container = new GenericContainerEx<>(new BaseDockerImageTagResolver())
.withEnv("PUID", "7000")
.withEnv("PGID", "8000")
.withEnv("PUID_ADDITIONAL_GROUPS", "8005=grp1") // valid delimiter is :
.withRelativeFileSystemBind(Paths.get(Image.getExamplesDir(), "loop").toString(), "/usr/sbin/loop")
.withRelativeFileSystemBind(Paths.get(Image.getExamplesDir(), "run").toString(), "/etc/services.d/env-test/run")
.withImagePullPolicy(PullPolicyEx.never())
.waitingFor(WaitEx.forS6OverlayStart());

try
{
_container.start();
}
catch (ContainerLaunchException ex) {
// Expected
}
}

@AfterClass
public static void after() {
_container.close();
}

@Test
public void printErrorMessage() throws Exception {
waitFor(Duration.ofSeconds(10), () -> _container.getLogsAnalyzer().matches(".*Valid format is <gid1>:<group-name1>,<gid2>:<group-name2>.*"));
}

@Test
public void exitFromInitScript() throws Exception {
// This checks the container stopped on the init script and not because of other failure
waitFor(Duration.ofSeconds(10), () -> _container.getLogsAnalyzer().matches(".*\\[cont\\-init\\.d\\] 10-init\\.sh: exited.*"));
}

@Test
public void exit() throws Exception {
waitFor(Duration.ofSeconds(5), () -> !_container.isRunning());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import helpers.BaseDockerImageTagResolver;
import helpers.Image;
import io.homecentr.testcontainers.containers.GenericContainerEx;
import io.homecentr.testcontainers.containers.wait.strategy.WaitEx;
import io.homecentr.testcontainers.images.PullPolicyEx;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testcontainers.containers.ContainerLaunchException;

import java.nio.file.Paths;
import java.time.Duration;

import static io.homecentr.testcontainers.WaitLoop.waitFor;

public class BaseRunningWithInvalidSecondaryGroupsAsRootShould {
private static final Logger logger = LoggerFactory.getLogger(BaseRunningAsRootShould.class);

private static GenericContainerEx _container;

@BeforeClass
public static void before(){
_container = new GenericContainerEx<>(new BaseDockerImageTagResolver())
.withEnv("PUID", "0")
.withEnv("PGID", "0")
.withEnv("PUID_ADDITIONAL_GROUPS", "8005=grp1") // valid delimiter is :
.withRelativeFileSystemBind(Paths.get(Image.getExamplesDir(), "loop").toString(), "/usr/sbin/loop")
.withRelativeFileSystemBind(Paths.get(Image.getExamplesDir(), "run").toString(), "/etc/services.d/env-test/run")
.withImagePullPolicy(PullPolicyEx.never())
.waitingFor(WaitEx.forS6OverlayStart());

try
{
_container.start();
}
catch (ContainerLaunchException ex) {
// Expected
}
}

@AfterClass
public static void after() {
_container.close();
}

@Test
public void printErrorMessage() throws Exception {
waitFor(Duration.ofSeconds(10), () -> _container.getLogsAnalyzer().matches(".*Valid format is <gid1>:<group-name1>,<gid2>:<group-name2>.*"));
}

@Test
public void exitFromInitScript() throws Exception {
// This checks the container stopped on the init script and not because of other failure
waitFor(Duration.ofSeconds(10), () -> _container.getLogsAnalyzer().matches(".*\\[cont\\-init\\.d\\] 10-init\\.sh: exited.*"));
}

@Test
public void exit() throws Exception {
waitFor(Duration.ofSeconds(5), () -> !_container.isRunning());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,10 @@ public void loadGroupsToPuidUserContext() throws Exception {
waitFor(Duration.ofSeconds(10), () -> _container.getLogsAnalyzer().matches(".*ID=.*8005\\(grp1\\).*"));
waitFor(Duration.ofSeconds(10), () -> _container.getLogsAnalyzer().matches(".*ID=.*8006\\(grp2\\).*"));
}

@Test
public void printGroupsToOutput() throws Exception {
// Root is automatically member of other groups
waitFor(Duration.ofSeconds(10), () -> _container.getLogsAnalyzer().matches(".*User additional gids:\\W*8005,8006.*"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,9 @@ public void loadGroupsToPuidUserContext() throws Exception {
waitFor(Duration.ofSeconds(10), () -> _container.getLogsAnalyzer().matches(".*ID=.*8005\\(grp1\\).*"));
waitFor(Duration.ofSeconds(10), () -> _container.getLogsAnalyzer().matches(".*ID=.*8006\\(grp2\\).*"));
}

@Test
public void printGroupsToOutput() throws Exception {
waitFor(Duration.ofSeconds(10), () -> _container.getLogsAnalyzer().matches(".*User additional gids:\\W*.*8005,8006.*"));
}
}
3 changes: 2 additions & 1 deletion tests/src/test/java/helpers/Image.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public static String getShell() {
}

private static String getBase() {
return System.getProperty("base");
return "alpine";
//return System.getProperty("base");
}
}

0 comments on commit 5fec309

Please sign in to comment.