Skip to content

Commit

Permalink
completely disable networking stack inside containers and restrict pe…
Browse files Browse the repository at this point in the history
…rmissions inside the execution container
  • Loading branch information
zakariamaaraki committed Jan 23, 2024
1 parent 3922d2d commit e271bbf
Show file tree
Hide file tree
Showing 16 changed files with 265 additions and 18 deletions.
15 changes: 14 additions & 1 deletion executions/utility_c/Dockerfile.execution
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,20 @@ RUN groupadd -r user -g 111 && \

ADD . .

RUN chmod a+x entrypoint-*.sh
RUN chmod 700 /bin/ls && \
chown root:user /bin/ls

RUN chmod 700 /bin/cat && \
chown root:user /bin/cat

RUN chmod 700 /bin/rm && \
chown root:user /bin/rm

# Set the appropriate permissions
RUN chmod 711 /app

# The user should have only the rights to execute the script
RUN chmod a+x ./entrypoint-*.sh

USER user

Expand Down
15 changes: 14 additions & 1 deletion executions/utility_cpp/Dockerfile.execution
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,20 @@ RUN groupadd -r user -g 111 && \

ADD . .

RUN chmod a+x ./entrypoint-*.sh
RUN chmod 700 /bin/ls && \
chown root:user /bin/ls

RUN chmod 700 /bin/cat && \
chown root:user /bin/cat

RUN chmod 700 /bin/rm && \
chown root:user /bin/rm

# Set the appropriate permissions
RUN chmod 711 /app

# The user should have only the rights to execute the script
RUN chmod a+x entrypoint-*.sh

USER user

Expand Down
15 changes: 14 additions & 1 deletion executions/utility_cs/Dockerfile.execution
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,20 @@ RUN groupadd -r user -g 111 && \

ADD . .

RUN chmod a+x ./entrypoint-*.sh
RUN chmod 700 /bin/ls && \
chown root:user /bin/ls

RUN chmod 700 /bin/cat && \
chown root:user /bin/cat

RUN chmod 700 /bin/rm && \
chown root:user /bin/rm

# Set the appropriate permissions
RUN chmod 711 /app

# The user should have only the rights to execute the script
RUN chmod a+x entrypoint-*.sh

USER user

Expand Down
15 changes: 14 additions & 1 deletion executions/utility_go/Dockerfile.execution
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,20 @@ RUN groupadd -r user -g 111 && \

ADD . .

RUN chmod a+x ./entrypoint-*.sh
RUN chmod 700 /bin/ls && \
chown root:user /bin/ls

RUN chmod 700 /bin/cat && \
chown root:user /bin/cat

RUN chmod 700 /bin/rm && \
chown root:user /bin/rm

# Set the appropriate permissions
RUN chmod 711 /app

# The user should have only the rights to execute the script
RUN chmod a+x entrypoint-*.sh

USER user

Expand Down
15 changes: 14 additions & 1 deletion executions/utility_hs/Dockerfile.execution
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,20 @@ RUN groupadd -r user -g 111 && \

ADD . .

RUN chmod a+x ./entrypoint-*.sh
RUN chmod 700 /bin/ls && \
chown root:user /bin/ls

RUN chmod 700 /bin/cat && \
chown root:user /bin/cat

RUN chmod 700 /bin/rm && \
chown root:user /bin/rm

# Set the appropriate permissions
RUN chmod 711 /app

# The user should have only the rights to execute the script
RUN chmod a+x entrypoint-*.sh

USER user

Expand Down
15 changes: 14 additions & 1 deletion executions/utility_java/Dockerfile.execution
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,20 @@ RUN groupadd -r user -g 111 && \

ADD . .

RUN chmod a+x ./entrypoint-*.sh
RUN chmod 700 /bin/ls && \
chown root:user /bin/ls

RUN chmod 700 /bin/cat && \
chown root:user /bin/cat

RUN chmod 700 /bin/rm && \
chown root:user /bin/rm

# Set the appropriate permissions
RUN chmod 711 /app

# The user should have only the rights to execute the script
RUN chmod a+x entrypoint-*.sh

USER user

Expand Down
15 changes: 14 additions & 1 deletion executions/utility_kt/Dockerfile.execution
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,20 @@ RUN groupadd -r user -g 111 && \

ADD . .

RUN chmod a+x ./entrypoint-*.sh
RUN chmod 700 /bin/ls && \
chown root:user /bin/ls

RUN chmod 700 /bin/cat && \
chown root:user /bin/cat

RUN chmod 700 /bin/rm && \
chown root:user /bin/rm

# Set the appropriate permissions
RUN chmod 711 /app

# The user should have only the rights to execute the script
RUN chmod a+x entrypoint-*.sh

USER user

Expand Down
15 changes: 14 additions & 1 deletion executions/utility_py/Dockerfile.execution
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,20 @@ RUN groupadd -r user -g 111 && \

ADD . .

RUN chmod a+x ./entrypoint-*.sh
RUN chmod 700 /bin/ls && \
chown root:user /bin/ls

RUN chmod 700 /bin/cat && \
chown root:user /bin/cat

RUN chmod 700 /bin/rm && \
chown root:user /bin/rm

# Set the appropriate permissions
RUN chmod 711 /app

# The user should have only the rights to execute the script
RUN chmod a+x entrypoint-*.sh

USER user

Expand Down
15 changes: 14 additions & 1 deletion executions/utility_rb/Dockerfile.execution
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,20 @@ RUN groupadd -r user -g 111 && \

ADD . .

RUN chmod a+x ./entrypoint-*.sh
RUN chmod 700 /bin/ls && \
chown root:user /bin/ls

RUN chmod 700 /bin/cat && \
chown root:user /bin/cat

RUN chmod 700 /bin/rm && \
chown root:user /bin/rm

# Set the appropriate permissions
RUN chmod 711 /app

# The user should have only the rights to execute the script
RUN chmod a+x entrypoint-*.sh

USER user

Expand Down
15 changes: 14 additions & 1 deletion executions/utility_rs/Dockerfile.execution
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,20 @@ RUN groupadd -r user -g 111 && \

ADD . .

RUN chmod a+x ./entrypoint-*.sh
RUN chmod 700 /bin/ls && \
chown root:user /bin/ls

RUN chmod 700 /bin/cat && \
chown root:user /bin/cat

RUN chmod 700 /bin/rm && \
chown root:user /bin/rm

# Set the appropriate permissions
RUN chmod 711 /app

# The user should have only the rights to execute the script
RUN chmod a+x entrypoint-*.sh

USER user

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ private void buildExecutionEnvironment(Execution execution) {
log.info("Creating execution directory: {}", execution.getExecutionFolderName());
execution.createExecutionDirectory();
} catch (Throwable e) {
log.error("Error while building execution environment: {}", e);
log.error("Error while building execution environment", e);
throw new CompilerServerInternalException(e.getMessage());
}
}
Expand All @@ -136,7 +136,7 @@ private void deleteExecutionEnvironment(Execution execution) {
execution.deleteExecutionDirectory();
log.info("Execution directory {} has been deleted", execution.getExecutionFolderName());
} catch (IOException e) {
log.warn("Error while trying to delete execution directory, {}", e);
log.warn("Error while trying to delete execution directory", e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public String getAllContainersStats() {

@Override
public String buildImage(String contextPath, String imageName, String dockerfileName) {
log.info("Start building the docker image: ", imageName);
log.info("Start building the docker image: {}", imageName);
String buildLogs = "";
try {
buildLogs = buildContainerImageInternal(contextPath, imageName, dockerfileName);
Expand All @@ -86,7 +86,7 @@ public ProcessOutput runContainer(String imageName,
// TLE
throw new ContainerOperationTimeoutException(processExecutionException.getMessage());
}
log.error("Error: {}", processExecutionException);
log.error("Error while running the container: ", processExecutionException);
throw new ContainerFailedDependencyException(processExecutionException.getMessage());
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,13 +123,32 @@ private String[] buildDockerCommand(String containerName,
float cpus,
String imageName) {
/**
* docker run --name [containerName] (-e [envKey=envValue])* --cpus=[cpu] [imageName]
* docker run --read only --name [containerName] (-e [envKey=envValue])* --cpus=[cpu] [imageName]
*
* When running the Docker container, we can use security-related options to further restrict the container's capabilities.
* For example, we can use the --read-only flag to make the container's filesystem read-only.
*
* To completely disable the networking stack on a container, we can use the --network none flag when starting the container.
* Within the container, only the loopback device is created. This effectively isolates the container from any network,
* including the host and the internet.
*
* Docker allows you to drop certain capabilities within a container to reduce the set of permissions available to processes inside the container.
* This is achieved using the --cap-drop option.
*/
List<String> dockerCommandList = new ArrayList<>(Arrays.asList("docker", "run", "--name", containerName));
List<String> dockerCommandList = new ArrayList<>(Arrays.asList(
"docker",
"run",
"--read-only",
"--cap-drop=ALL",
"--network=none", // The container doesn't need network access, let's disable it:
"--name",
containerName));

for (String key : envVariables.keySet()) {
dockerCommandList.add("-e");
dockerCommandList.add(key + "=" + envVariables.get(key));
}

var cpuParam = "--cpus=" + cpus;
dockerCommandList.add(cpuParam);
dockerCommandList.add(imageName);
Expand All @@ -144,7 +163,7 @@ public ContainerInfo inspect(String containerName) {
try {
ci = ContainerInfoMapper.toContainerInfo(containerInfo);
} catch (JsonProcessingException e) {
log.warn("Error during json deserialization, while trying to retrieve container info, ex: {}", e);
log.warn("Error during json deserialization, while trying to retrieve container info", e);
}
return ci;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,5 +97,5 @@ private WellKnownFiles() {}
/**
* The constant EXECUTION_DOCKERFILE_NAME.
*/
public static final String EXECUTION_DOCKERFILE_NAME ="Dockerfile.execution";
public static final String EXECUTION_DOCKERFILE_NAME = "Dockerfile.execution";
}
79 changes: 79 additions & 0 deletions src/test/java/com/cp/compiler/security/CSecurityTests.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package com.cp.compiler.security;

import com.cp.compiler.contract.Language;
import com.cp.compiler.contract.RemoteCodeCompilerResponse;
import com.cp.compiler.contract.testcases.TestCaseResult;
import com.cp.compiler.controllers.CompilerController;
import com.cp.compiler.models.Verdict;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;

@Slf4j
@DirtiesContext
@SpringBootTest
class CSecurityTests {

@Autowired
private CompilerController compilerController;

/**
* Running a system level command should return runtime error statusResponse.
*
* @throws Exception the exception
*/
@DisplayName("C Security Command Line execution Should Return Runtime Error")
@Test
void RunningASystemCommandShouldReturnRuntimeErrorVerdict() throws Exception {
// Given
File sourceCodeFile = new File("src/test/resources/sources/security/c/CommandLine.c");
MultipartFile sourceCode = new MockMultipartFile(
"Test1.c",
"Test1.c",
null,
new FileInputStream(sourceCodeFile));

// Dummy expected output
File expectedOutputFile = new File("src/test/resources/outputs/Test1.txt");
MultipartFile expectedOutput = new MockMultipartFile(
"Test1.txt",
"Test1.txt",
null,
new FileInputStream(expectedOutputFile));

// When
ResponseEntity<RemoteCodeCompilerResponse> responseEntity = compilerController.compile(
Language.C,
sourceCode,
null,
expectedOutput,
10,
500,
null,
null,
"");

for (TestCaseResult testCaseResult: responseEntity.getBody().getExecution().getTestCasesResult().values()) {
log.info("Container std output = {}", testCaseResult.getOutput());
log.info("Container stderr output = {}", testCaseResult.getError());
}

// Then
Assertions.assertFalse(
responseEntity
.getBody()
.getExecution()
.getError()
.isEmpty());
}
}
Loading

0 comments on commit e271bbf

Please sign in to comment.