Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ares: ArchUnit Command Execution #23

Merged
merged 35 commits into from
Sep 22, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
950d3a7
ArchUnit Command Execution tests
sarpsahinalp Aug 30, 2024
7e7376b
Merge branch 'main' into feature/archrule-command-execution
sarpsahinalp Sep 11, 2024
108d1fa
Fix command execution tests
sarpsahinalp Sep 11, 2024
5289805
Fix resource path
sarpsahinalp Sep 11, 2024
bf286d2
Fix tests
sarpsahinalp Sep 11, 2024
e7d8cb8
Fixes
sarpsahinalp Sep 11, 2024
a88ad58
Remove unused error message
sarpsahinalp Sep 12, 2024
2a08e65
Improve class resolver for efficiency
sarpsahinalp Sep 12, 2024
592b4c6
Also don't allow class.forName method
sarpsahinalp Sep 12, 2024
cbb9b01
Fix package import for ArchUnit
sarpsahinalp Sep 12, 2024
6a5af61
Add default import for the packages
sarpsahinalp Sep 12, 2024
caf5092
Enable aopMode switch.
Sep 12, 2024
4d39776
Remove default dependencies from example policy files
sarpsahinalp Sep 13, 2024
aa7c85e
Various bugfixes:
Sep 16, 2024
8bdbbaa
Added pointcut definitions for Instrumentation
sarpsahinalp Sep 16, 2024
3340efc
Instrument constructors
Sep 17, 2024
e1e11a5
Merge remote-tracking branch 'origin/feature/archrule-command-executi…
Sep 17, 2024
c673617
1. Disincluded java.io.FileInputStream.read() and java.io.FileOutputS…
Sep 17, 2024
2f5ea9f
Improve maven plugin and implement the Instrumentation YAML
sarpsahinalp Sep 20, 2024
59fa8de
Changes to the pom.xml and the workflow
sarpsahinalp Sep 21, 2024
22cc11d
added tests and some pointcuts for aspectJ
az108 Sep 22, 2024
5875d81
Change aomMode to aopMode in each instance
sarpsahinalp Sep 22, 2024
b7d44b6
added tests and some pointcuts for aspectJ
az108 Sep 22, 2024
2042017
Restructured FileSystemAccessPenguin.java and FileSystemAccessTest.java
Sep 22, 2024
4946c8c
Added comment and removed imports.
Sep 22, 2024
eb1048e
added tests from todo
az108 Sep 22, 2024
c5df1c4
Merge remote-tracking branch 'origin/feature/archrule-command-executi…
az108 Sep 22, 2024
41a202e
Refactored FileSystemAccessPenguin.java
Sep 22, 2024
747a6c2
Merge remote-tracking branch 'origin/feature/archrule-command-executi…
Sep 22, 2024
0e73830
Fixed issue in FileSystemAccessTest.java
Sep 22, 2024
f5ed883
Resorted FileSystemAccessTest.java
Sep 22, 2024
20d86c9
Fix tests
sarpsahinalp Sep 22, 2024
8f19339
Deleted empty lines.
Sep 22, 2024
9ec6049
Aligned EverythingForbiddenPolicy.yaml with the other policies.
Sep 22, 2024
860c537
Add File pointcut for AspectJ
sarpsahinalp Sep 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public class FileHandlerConstants {
public static final Path JAVA_NETWORK_ACCESS_METHODS = Path.of(JAVA_METHODS_DIRECTORY + "network-access-methods.txt");
public static final Path JAVA_JVM_TERMINATION_METHODS = Path.of(JAVA_METHODS_DIRECTORY + "jvm-termination-methods.txt");
public static final Path JAVA_REFLECTION_METHODS = Path.of(JAVA_METHODS_DIRECTORY + "reflection-methods.txt");
public static final Path JAVA_COMMAND_EXECUTION_METHODS = Path.of(JAVA_METHODS_DIRECTORY + "command-execution-methods.txt");

private FileHandlerConstants() {
throw new IllegalArgumentException("FileHandlerConstants is a utility class and should not be instantiated");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@
import de.tum.cit.ase.ares.api.policy.PackageImport;

import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -78,7 +75,7 @@ public void runArchitectureTestCase(JavaClasses classes) {
case PACKAGE_IMPORT -> JavaArchitectureTestCaseCollection.noClassesShouldImportForbiddenPackages(allowedPackages).check(classes);
case THREAD_CREATION -> throw new UnsupportedOperationException("Thread creation not implemented yet");
case COMMAND_EXECUTION ->
throw new UnsupportedOperationException("Command execution not implemented yet");
JavaArchitectureTestCaseCollection.NO_CLASSES_SHOULD_EXECUTE_COMMANDS.check(classes);
case NETWORK_CONNECTION ->
JavaArchitectureTestCaseCollection.NO_CLASSES_SHOULD_ACCESS_NETWORK.check(classes);
default -> throw new UnsupportedOperationException("Not implemented yet");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
package de.tum.cit.ase.ares.api.architecturetest.java.postcompile;

import com.google.common.collect.ImmutableMap;
import com.tngtech.archunit.base.DescribedPredicate;
import com.tngtech.archunit.core.domain.JavaAccess;
import com.tngtech.archunit.core.domain.JavaClass;
import com.tngtech.archunit.lang.ArchRule;
import com.tngtech.archunit.lang.syntax.ArchRuleDefinition;
import de.tum.cit.ase.ares.api.architecturetest.java.FileHandlerConstants;
import de.tum.cit.ase.ares.api.architecturetest.java.JavaSupportedArchitectureTestCase;

import java.io.IOException;
import java.nio.file.Files;
Expand All @@ -16,9 +14,6 @@
import java.util.HashSet;
import java.util.Set;

import static de.tum.cit.ase.ares.api.architecturetest.java.JavaSupportedArchitectureTestCase.FILESYSTEM_INTERACTION;
import static de.tum.cit.ase.ares.api.architecturetest.java.JavaSupportedArchitectureTestCase.NETWORK_CONNECTION;

/**
* This class runs the security rules on the architecture for the post-compile mode.
*/
Expand All @@ -28,26 +23,16 @@ private JavaArchitectureTestCaseCollection() {
throw new IllegalArgumentException("This class should not be instantiated");
}

public static final String LOAD_FORBIDDEN_METHODS_FROM_FILE_FAILED = "Could not load the architecture rule file content";
/**
* Map to store the forbidden methods for the supported architectural test cases
* Error message for when the forbidden methods could not be loaded from the file
*/
private static final ImmutableMap.Builder<String, Set<String>> FORBIDDEN_METHODS_FOR_SUPPORTED_ARCHITECTURAL_TEST_CASE = ImmutableMap.builder();


/**
* Load pre file contents
*/
public static void loadForbiddenMethodsFromFile(Path filePath, String key) throws IOException {
Set<String> content = new HashSet<>(Files.readAllLines(filePath));
FORBIDDEN_METHODS_FOR_SUPPORTED_ARCHITECTURAL_TEST_CASE.put(key, content);
}
public static final String LOAD_FORBIDDEN_METHODS_FROM_FILE_FAILED = "Could not load the architecture rule file content";

/**
* Get the content of a file from the architectural rules storage
* Load forbidden methods from a file
*/
public static Set<String> getForbiddenMethods(String key) {
return FORBIDDEN_METHODS_FOR_SUPPORTED_ARCHITECTURAL_TEST_CASE.build().get(key);
public static Set<String> getForbiddenMethods(Path filePath) throws IOException {
return new HashSet<>(Files.readAllLines(filePath));
}

/**
Expand All @@ -68,11 +53,10 @@ public static String getArchitectureRuleFileContent(String key) throws IOExcepti
public boolean test(JavaAccess<?> javaAccess) {
if (forbiddenMethods == null) {
try {
loadForbiddenMethodsFromFile(FileHandlerConstants.JAVA_FILESYSTEM_INTERACTION_METHODS, JavaSupportedArchitectureTestCase.FILESYSTEM_INTERACTION.name());
forbiddenMethods = getForbiddenMethods(FileHandlerConstants.JAVA_FILESYSTEM_INTERACTION_METHODS);
} catch (IOException e) {
throw new IllegalStateException(LOAD_FORBIDDEN_METHODS_FROM_FILE_FAILED, e);
}
forbiddenMethods = getForbiddenMethods(FILESYSTEM_INTERACTION.name());
}

return forbiddenMethods.stream().anyMatch(method -> javaAccess.getTarget().getFullName().startsWith(method));
Expand All @@ -90,11 +74,10 @@ public boolean test(JavaAccess<?> javaAccess) {
public boolean test(JavaAccess<?> javaAccess) {
if (forbiddenMethods == null) {
try {
loadForbiddenMethodsFromFile(FileHandlerConstants.JAVA_NETWORK_ACCESS_METHODS, JavaSupportedArchitectureTestCase.NETWORK_CONNECTION.name());
forbiddenMethods = getForbiddenMethods(FileHandlerConstants.JAVA_NETWORK_ACCESS_METHODS);
} catch (IOException e) {
throw new IllegalStateException(LOAD_FORBIDDEN_METHODS_FROM_FILE_FAILED, e);
}
forbiddenMethods = getForbiddenMethods(NETWORK_CONNECTION.name());
}

return forbiddenMethods.stream().anyMatch(method -> javaAccess.getTarget().getFullName().startsWith(method));
Expand All @@ -120,10 +103,19 @@ public boolean test(JavaClass javaClass) {
*/
public static final ArchRule NO_CLASSES_SHOULD_USE_REFLECTION = ArchRuleDefinition.noClasses()
.should(new TransitivelyAccessesMethodsCondition(new DescribedPredicate<>("uses reflection") {
private Set<String> forbiddenMethods;

@Override
public boolean test(JavaAccess<?> javaAccess) {
return javaAccess.getTarget().getFullName().startsWith("java.lang.reflect")
|| javaAccess.getTarget().getFullName().startsWith("sun.reflect.misc");
if (forbiddenMethods == null) {
try {
forbiddenMethods = getForbiddenMethods(FileHandlerConstants.JAVA_REFLECTION_METHODS);
} catch (IOException e) {
throw new IllegalStateException(LOAD_FORBIDDEN_METHODS_FROM_FILE_FAILED, e);
}
}

return forbiddenMethods.stream().anyMatch(method -> javaAccess.getTarget().getFullName().startsWith(method));
}
}));

Expand All @@ -138,14 +130,31 @@ public boolean test(JavaAccess<?> javaAccess) {
public boolean test(JavaAccess<?> javaAccess) {
if (forbiddenMethods == null) {
try {
loadForbiddenMethodsFromFile(FileHandlerConstants.JAVA_JVM_TERMINATION_METHODS, "JVM_TERMINATION");
forbiddenMethods = getForbiddenMethods(FileHandlerConstants.JAVA_JVM_TERMINATION_METHODS);
} catch (IOException e) {
throw new IllegalStateException(LOAD_FORBIDDEN_METHODS_FROM_FILE_FAILED, e);
}
forbiddenMethods = getForbiddenMethods("JVM_TERMINATION");
}

return forbiddenMethods.stream().anyMatch(method -> javaAccess.getTarget().getFullName().startsWith(method));
}
})));

public static final ArchRule NO_CLASSES_SHOULD_EXECUTE_COMMANDS = ArchRuleDefinition.noClasses()
.should(new TransitivelyAccessesMethodsCondition(new DescribedPredicate<>("executes commands") {
private Set<String> forbiddenMethods;

@Override
public boolean test(JavaAccess<?> javaAccess) {
if (forbiddenMethods == null) {
try {
forbiddenMethods = getForbiddenMethods(FileHandlerConstants.JAVA_COMMAND_EXECUTION_METHODS);
} catch (IOException e) {
throw new IllegalStateException(LOAD_FORBIDDEN_METHODS_FROM_FILE_FAILED, e);
}
}

return forbiddenMethods.stream().anyMatch(method -> javaAccess.getTarget().getFullName().startsWith(method));
}
}));
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public JavaSecurityTestCaseFactoryAndBuilder(SecurityPolicy securityPolicy, Path
private void parseTestCasesToBeCreated() {
Supplier<List<?>>[] methods = new Supplier[]{securityPolicy::iAllowTheFollowingFileSystemInteractionsForTheStudents,
securityPolicy::iAllowTheFollowingNetworkConnectionsForTheStudents,
// securityPolicy::iAllowTheFollowingCommandExecutionsForTheStudents,
securityPolicy::iAllowTheFollowingCommandExecutionsForTheStudents,
// securityPolicy::iAllowTheFollowingThreadCreationsForTheStudents,
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
java.lang.Runtime.exec
java.lang.ProcessBuilder
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package de.tum.cit.ase.ares.integration.testuser;

import de.tum.cit.ase.ares.api.*;
import de.tum.cit.ase.ares.api.jupiter.Public;
import de.tum.cit.ase.ares.api.jupiter.PublicTest;
import de.tum.cit.ase.ares.api.localization.UseLocale;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.TestMethodOrder;

import java.io.IOException;

@Public
@UseLocale("en")
@AllowThreads(maxActiveCount = 100)
@MirrorOutput(MirrorOutput.MirrorOutputPolicy.DISABLED)
@StrictTimeout(5)
@TestMethodOrder(MethodOrderer.MethodName.class)
@WhitelistPath(value = "target/**", type = PathType.GLOB)
@BlacklistPath(value = "**Test*.{java,class}", type = PathType.GLOB)
public class CommandExecutionUser {

@PublicTest
@Policy(value = "src/test/resources/de/tum/cit/ase/ares/integration/testuser/securitypolicies/EverythingForbiddenPolicy.yaml", withinPath = "test-classes/de/tum/cit/ase/ares/integration/testuser/subject/commandexecution")
void executeCommand() throws IOException {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package de.tum.cit.ase.ares.integration.testuser.subject.commandexecution;

import java.io.IOException;

public class CommandExecutingStudent {

public void method() throws IOException {
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.start();
}

public void method2() throws IOException {
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.command("ls");
processBuilder.start();
}

public void method3() throws IOException {
Runtime.getRuntime().exec("ls");
}

public void method4() throws IOException {
Runtime.getRuntime().exec(new String[] {"ls"});
}
}
Loading