diff --git a/pom.xml b/pom.xml
index 15c61ea..d9e7ee6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -75,12 +75,13 @@
11
1.77
- 1.26.0
+ 1.26.1
1.16.1
33.0.0-jre
5.8.2
1.5.0
2.0.12
+ 1.19.7
1.9
3.2.5
@@ -201,6 +202,22 @@
pom
import
+
+ org.testcontainers
+ junit-jupiter
+ ${testcontainers.version}
+ test
+
+
+ commons-codec
+ commons-codec
+
+
+ org.apache.commons
+ commons-compress
+
+
+
diff --git a/rpm/pom.xml b/rpm/pom.xml
index 37aba2d..45637de 100644
--- a/rpm/pom.xml
+++ b/rpm/pom.xml
@@ -24,6 +24,10 @@
org.apache.commons
commons-compress
+
+ commons-codec
+ commons-codec
+
com.google.guava
guava
@@ -53,6 +57,11 @@
junit-jupiter-params
test
+
+ org.testcontainers
+ junit-jupiter
+ test
+
diff --git a/rpm/src/test/java/org/eclipse/packager/rpm/WriterTest.java b/rpm/src/test/java/org/eclipse/packager/rpm/WriterTest.java
index eda8104..67e7c0b 100644
--- a/rpm/src/test/java/org/eclipse/packager/rpm/WriterTest.java
+++ b/rpm/src/test/java/org/eclipse/packager/rpm/WriterTest.java
@@ -14,6 +14,9 @@
package org.eclipse.packager.rpm;
import static java.util.EnumSet.of;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.testcontainers.images.builder.Transferable.DEFAULT_FILE_MODE;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
@@ -42,22 +45,24 @@
import org.eclipse.packager.rpm.parse.RpmInputStream;
import org.eclipse.packager.rpm.signature.RsaHeaderSignatureProcessor;
import org.eclipse.packager.security.pgp.PgpHelper;
-import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import org.testcontainers.containers.Container.ExecResult;
+import org.testcontainers.containers.GenericContainer;
+import org.testcontainers.images.builder.Transferable;
+import org.testcontainers.utility.DockerImageName;
public class WriterTest {
- private static final Path OUT_BASE = Path.of("target", "data", "out");
-
private static final Path IN_BASE = Path.of("src", "test", "resources", "data", "in");
- @BeforeAll
- public static void setup() throws IOException {
- Files.createDirectories(OUT_BASE);
- }
+ private static final String COMMAND = "sleep infinity";
+
+ @TempDir
+ Path outBase;
@Test
public void test1() throws IOException {
- final Path rpm1 = OUT_BASE.resolve("test1-1.0.0.rpm");
+ final Path rpm1 = outBase.resolve("test1-1.0.0.rpm");
final Header header = new Header<>();
@@ -88,7 +93,7 @@ public void test1() throws IOException {
requirements.add(new Dependency("rpmlib(CompressedFileNames)", "3.0.4-1", RpmDependencyFlags.LESS, RpmDependencyFlags.EQUAL, RpmDependencyFlags.RPMLIB));
Dependencies.putRequirements(header, requirements);
- try (PayloadRecorder.Finished finished = new PayloadRecorder().finish()) {
+ try (PayloadRecorder payloadRecorder = new PayloadRecorder(); PayloadRecorder.Finished finished = payloadRecorder.finish()) {
try (RpmWriter writer = new RpmWriter(rpm1, new LeadBuilder("test1", new RpmVersion("1.0.0")), header)) {
writer.setPayload(finished);
}
@@ -101,7 +106,7 @@ public void test1() throws IOException {
@Test
public void test2() throws IOException {
- final Path outFile = OUT_BASE.resolve("test2-1.0.0.1.rpm");
+ final Path outFile = outBase.resolve("test2-1.0.0.1.rpm");
try (PayloadRecorder payload = new PayloadRecorder()) {
final Header header = new Header<>();
@@ -134,13 +139,12 @@ public void test2() throws IOException {
requirements.add(new Dependency("rpmlib(CompressedFileNames)", "3.0.4-1", RpmDependencyFlags.LESS, RpmDependencyFlags.EQUAL, RpmDependencyFlags.RPMLIB));
Dependencies.putRequirements(header, requirements);
- int installedSize = 0;
- installedSize += payload.addFile("/etc/test3/file1", IN_BASE.resolve("file1")).getSize();
+ int installedSize = (int) payload.addFile("/etc/test3/file1", IN_BASE.resolve("file1")).getSize();
header.putInt(RpmTag.SIZE, installedSize);
try (final PayloadRecorder.Finished finished = payload.finish();
- final RpmWriter writer = new RpmWriter(outFile, new LeadBuilder("test3", new RpmVersion("1.0.0", "1")), header);) {
+ final RpmWriter writer = new RpmWriter(outFile, new LeadBuilder("test3", new RpmVersion("1.0.0", "1")), header)) {
writer.setPayload(finished);
}
}
@@ -154,7 +158,7 @@ public void test2() throws IOException {
public void test3() throws IOException, PGPException {
Path outFile;
- try (RpmBuilder builder = new RpmBuilder("test3", "1.0.0", "1", "noarch", OUT_BASE)) {
+ try (RpmBuilder builder = new RpmBuilder("test3", "1.0.0", "1", "noarch", outBase)) {
final PackageInformation pinfo = builder.getInformation();
pinfo.setLicense("EPL");
@@ -170,13 +174,9 @@ public void test3() throws IOException, PGPException {
ctx.addDirectory("//etc/test3/b");
ctx.addDirectory("/etc/");
- ctx.addDirectory("/var/lib/test3", finfo -> {
- finfo.setUser("");
- });
+ ctx.addDirectory("/var/lib/test3", finfo -> finfo.setUser(""));
- ctx.addFile("/etc/test3/file1", IN_BASE.resolve("file1"), BuilderContext.pathProvider().customize(finfo -> {
- finfo.setFileFlags(of(FileFlags.CONFIGURATION));
- }));
+ ctx.addFile("/etc/test3/file1", IN_BASE.resolve("file1"), BuilderContext.pathProvider().customize(finfo -> finfo.setFileFlags(of(FileFlags.CONFIGURATION))));
ctx.addFile("/etc/test3/file2", new ByteArrayInputStream("foo".getBytes(StandardCharsets.UTF_8)), finfo -> {
finfo.setTimestamp(LocalDateTime.of(2014, 1, 1, 0, 0).toInstant(ZoneOffset.UTC));
@@ -213,7 +213,7 @@ public void test3() throws IOException, PGPException {
public void test4() throws IOException, InterruptedException {
final Path outFile;
- try (RpmBuilder builder = new RpmBuilder("test4", "1.0.0", "1", "noarch", OUT_BASE)) {
+ try (RpmBuilder builder = new RpmBuilder("test4", "1.0.0", "1", "noarch", outBase)) {
final PackageInformation pinfo = builder.getInformation();
pinfo.setLicense("EPL");
@@ -247,9 +247,22 @@ public void test4() throws IOException, InterruptedException {
Dumper.dumpAll(in);
}
- final ProcessBuilder pb = new ProcessBuilder("rpm", "-q", "--qf", "%{conflicts}\n%{requires}\n%{obsoletes}\n%{provides}\\n%{suggests}\\n%{recommends}\\n%{supplements}\\n%{enhances}", "-p", outFile.toAbsolutePath().toString());
- pb.inheritIO();
- pb.start().waitFor();
+ try (final GenericContainer> container = new GenericContainer<>(DockerImageName.parse("registry.access.redhat.com/ubi9/ubi-minimal:latest"))) {
+ container.setCommand(COMMAND);
+ container.withCopyToContainer(Transferable.of(Files.readAllBytes(outFile), DEFAULT_FILE_MODE), "/" + outFile.getFileName());
+ container.start();
+ final ExecResult rpmResult = container.execInContainer("rpm", "-q", "--qf", "%{conflicts}\n%{requires}\n%{obsoletes}\n%{provides}\\n%{suggests}\\n%{recommends}\\n%{supplements}\\n%{enhances}", "-p", "/" + outFile.getFileName());
+ assertEquals(0, rpmResult.getExitCode());
+ final String stdout = rpmResult.getStdout();
+ assertTrue(stdout.contains("name-conflicts"));
+ assertTrue(stdout.contains("name-requires"));
+ assertTrue(stdout.contains("name-obsoletes"));
+ assertTrue(stdout.contains("name-provides"));
+ assertTrue(stdout.contains("name-suggests"));
+ assertTrue(stdout.contains("name-recommends"));
+ assertTrue(stdout.contains("name-supplements"));
+ assertTrue(stdout.contains("name-enhances"));
+ }
}
}
diff --git a/rpm/src/test/java/org/eclipse/packager/rpm/signature/RpmFileSignatureProcessorTest.java b/rpm/src/test/java/org/eclipse/packager/rpm/signature/RpmFileSignatureProcessorTest.java
index 9961e4e..59bb034 100644
--- a/rpm/src/test/java/org/eclipse/packager/rpm/signature/RpmFileSignatureProcessorTest.java
+++ b/rpm/src/test/java/org/eclipse/packager/rpm/signature/RpmFileSignatureProcessorTest.java
@@ -18,15 +18,16 @@
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
+import static org.testcontainers.containers.Container.ExecResult;
+import static org.testcontainers.images.builder.Transferable.DEFAULT_FILE_MODE;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.util.Arrays;
import java.util.List;
-import java.util.Optional;
+import java.util.stream.Collectors;
import org.bouncycastle.openpgp.PGPException;
import org.eclipse.packager.rpm.HashAlgorithm;
@@ -34,152 +35,100 @@
import org.eclipse.packager.rpm.Rpms;
import org.eclipse.packager.rpm.parse.InputHeader;
import org.eclipse.packager.rpm.parse.RpmInputStream;
-import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
-import org.junit.jupiter.api.Order;
+import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.TestMethodOrder;
-import com.google.common.io.ByteStreams;
+import org.junit.jupiter.api.io.TempDir;
+import org.testcontainers.containers.GenericContainer;
+import org.testcontainers.images.builder.Transferable;
+import org.testcontainers.junit.jupiter.Testcontainers;
+import org.testcontainers.utility.DockerImageName;
-@TestMethodOrder(OrderAnnotation.class)
+@Testcontainers
public class RpmFileSignatureProcessorTest {
+ private static final Path RPM = Path.of("src/test/resources/data/org.eclipse.scada-0.2.1-1.noarch.rpm");
- private static final String SOURCE_FILE_PATH = "src/test/resources/data/org.eclipse.scada-0.2.1-1.noarch.rpm";
+ private static final Path PRIVATE_KEY = Path.of("src/test/resources/key/private_key.txt");
- private static final String PRIVATE_KEY_PATH = "src/test/resources/key/private_key.txt";
+ private static final Path PUBLIC_KEY = Path.of("src/test/resources/key/public_key.txt");
- private static final String PUBLIC_KEY_PATH = "src/test/resources/key/public_key.txt";
+ private static final String COMMAND = "sleep infinity";
- private static final String RESULT_DIR = "target/test-data/signature";
+ private static Path signedRpm;
- private static final String RESULT_FILE_PATH = RESULT_DIR + "/org.eclipse.scada-0.2.1-1.noarch.rpm";
+ @TempDir
+ static Path resultDirectory;
- private static final String CONTAINER = System.getenv().getOrDefault("CONTAINER_RUNTIME", "podman");
-
- private static final Optional MOUNT_SUFFIX = Optional.ofNullable(System.getenv().get("CONTAINER_MOUNT_SUFFIX"));
-
- @Test
- @Order(1)
- public void testSigningExistingRpm() throws IOException, PGPException {
+ @BeforeAll
+ static void testSigningExistingRpm() throws IOException, PGPException {
// Read files
final String passPhrase = "testkey"; // Do not change
- Path rpm = Path.of(SOURCE_FILE_PATH);
- Path private_key = Path.of(PRIVATE_KEY_PATH);
- if (!Files.exists(rpm) || !Files.exists(private_key)) {
+
+ if (!Files.exists(RPM) || !Files.exists(PRIVATE_KEY)) {
fail("Input files rpm or private_key does not exist");
}
+
// Init the signed RPM
- Path resultDirectory = Path.of(RESULT_DIR);
- Files.createDirectories(resultDirectory);
- Path signedRpm = Path.of(RESULT_FILE_PATH);
+ signedRpm = resultDirectory.resolve("org.eclipse.scada-0.2.1-1.noarch.rpm");
- try (OutputStream resultOut = Files.newOutputStream(signedRpm, CREATE_NEW);
- InputStream privateKeyStream = Files.newInputStream(private_key)) {
+ try (final OutputStream resultOut = Files.newOutputStream(signedRpm, CREATE_NEW);
+ final InputStream privateKeyStream = Files.newInputStream(PRIVATE_KEY)) {
// Sign the RPM
- RpmFileSignatureProcessor.perform(rpm, privateKeyStream, passPhrase, resultOut, HashAlgorithm.SHA256);
-
- // Read the initial (unsigned) rpm file
- RpmInputStream initialRpm = new RpmInputStream(Files.newInputStream(rpm));
- initialRpm.available();
- initialRpm.close();
- InputHeader initialHeader = initialRpm.getSignatureHeader();
+ RpmFileSignatureProcessor.perform(RPM, privateKeyStream, passPhrase, resultOut, HashAlgorithm.SHA256);
// Read the signed rpm file
- RpmInputStream rpmSigned = new RpmInputStream(Files.newInputStream(signedRpm));
- rpmSigned.available();
- rpmSigned.close();
- InputHeader signedHeader = rpmSigned.getSignatureHeader();
-
- // Get information of the initial rpm file
- int initialSize = (int) initialHeader.getEntry(RpmSignatureTag.SIZE).get().getValue();
- int initialPayloadSize = (int) initialHeader.getEntry(RpmSignatureTag.PAYLOAD_SIZE).get().getValue();
- String initialSha1 = initialHeader.getEntry(RpmSignatureTag.SHA1HEADER).get().getValue().toString();
- String initialMd5 = Rpms.dumpValue(initialHeader.getEntry(RpmSignatureTag.MD5).get().getValue());
-
- // Get information of the signed rpm file
- int signedSize = (int) signedHeader.getEntry(RpmSignatureTag.SIZE).get().getValue();
- int signedPayloadSize = (int) signedHeader.getEntry(RpmSignatureTag.PAYLOAD_SIZE).get().getValue();
- String signedSha1 = signedHeader.getEntry(RpmSignatureTag.SHA1HEADER).get().getValue().toString();
- String signedMd5 = Rpms.dumpValue(signedHeader.getEntry(RpmSignatureTag.MD5).get().getValue());
- String pgpSignature = Rpms.dumpValue(signedHeader.getEntry(RpmSignatureTag.PGP).get().getValue());
-
- // Compare information values of initial rpm and signed rpm
- assertEquals(initialSize, signedSize);
- assertEquals(initialPayloadSize, signedPayloadSize);
- assertEquals(initialSha1, signedSha1);
- assertEquals(initialMd5, signedMd5);
-
- // Verify if signature is present
- assertNotNull(pgpSignature);
+ try (RpmInputStream initialRpm = new RpmInputStream(Files.newInputStream(RPM)); RpmInputStream rpmSigned = new RpmInputStream(Files.newInputStream(signedRpm))) {
+ InputHeader initialHeader = initialRpm.getSignatureHeader();
+ InputHeader signedHeader = rpmSigned.getSignatureHeader();
+ // Get information of the signed rpm file
+ int signedSize = (int) signedHeader.getEntry(RpmSignatureTag.SIZE).get().getValue();
+ int signedPayloadSize = (int) signedHeader.getEntry(RpmSignatureTag.PAYLOAD_SIZE).get().getValue();
+ String signedSha1 = signedHeader.getEntry(RpmSignatureTag.SHA1HEADER).get().getValue().toString();
+ String signedMd5 = Rpms.dumpValue(signedHeader.getEntry(RpmSignatureTag.MD5).get().getValue());
+ String pgpSignature = Rpms.dumpValue(signedHeader.getEntry(RpmSignatureTag.PGP).get().getValue());
+ // Get information of the initial rpm file
+ int initialSize = (int) initialHeader.getEntry(RpmSignatureTag.SIZE).get().getValue();
+ int initialPayloadSize = (int) initialHeader.getEntry(RpmSignatureTag.PAYLOAD_SIZE).get().getValue();
+ String initialSha1 = initialHeader.getEntry(RpmSignatureTag.SHA1HEADER).get().getValue().toString();
+ String initialMd5 = Rpms.dumpValue(initialHeader.getEntry(RpmSignatureTag.MD5).get().getValue());
+
+ // Compare information values of initial rpm and signed rpm
+ assertEquals(initialSize, signedSize);
+ assertEquals(initialPayloadSize, signedPayloadSize);
+ assertEquals(initialSha1, signedSha1);
+ assertEquals(initialMd5, signedMd5);
+
+ // Verify if signature is present
+ assertNotNull(pgpSignature);
+ }
}
}
@Test
- @Order(2)
- public void verifyRpmSignature() throws Exception {
- // get the files, as absolute paths, as podman will need absolute paths
- Path publicKey = Path.of(PUBLIC_KEY_PATH).toAbsolutePath();
- Path signedRpm = Path.of(RESULT_FILE_PATH).toAbsolutePath();
-
+ void verifyRpmSignature() throws Exception {
// check if the output from the previous test is found
- if (!Files.exists(publicKey) || !Files.exists(signedRpm)) {
+ if (!Files.exists(PUBLIC_KEY) || !Files.exists(signedRpm)) {
fail("Input files signedRpm or publicKey does not exist");
}
// extract the plain file name
- String publicKeyName = publicKey.getFileName().toString();
- String rpmFileName = signedRpm.getFileName().toString();
-
- // prepare the script for validating the signature, this includes importing the key and running a verbose check
- String script = String.format("rpm --import /%s && rpm --verbose --checksig /%s", publicKeyName, rpmFileName);
-
- // SElinux labeling
- String mountSuffix = MOUNT_SUFFIX.orElseGet(() -> {
- if (CONTAINER.equals("podman")) {
- return ":z";
- } else {
- return "";
- }
- });
-
-
- // create the actual command, which we run inside a container, to not mess up the host systems RPM configuration and
- // because this gives us a predictable RPM version.
- String[] command = new String[] {
- CONTAINER, "run", "-tiq", "--rm",
- "-v", publicKey + ":/" + publicKeyName + mountSuffix,
- "-v", signedRpm + ":/" + rpmFileName + mountSuffix,
- "registry.access.redhat.com/ubi9/ubi-minimal:latest", "bash", "-c", script
- };
-
- // dump command for local testing
- dumpCommand(command);
-
- // run the command and capture the output
- String output = run(command);
-
- // split into lines
- List lines = Arrays.asList(output.split("\\R"));
-
- // ensure that we find a valid signature for our key
- assertTrue(lines.contains(" V4 RSA/SHA256 Signature, key ID 679f5723: OK"));
-
- System.out.println(output);
- }
-
- private static void dumpCommand(String[] command) {
- for (String c : command) {
- System.out.format("\"%s\" ", c);
+ Path publicKeyName = PUBLIC_KEY.getFileName();
+ Path rpmFileName = signedRpm.getFileName();
+
+ try (final GenericContainer> container = new GenericContainer<>(DockerImageName.parse("registry.access.redhat.com/ubi9/ubi-minimal:latest"))) {
+ container.setCommand(COMMAND);
+ container.withCopyToContainer(Transferable.of(Files.readAllBytes(PUBLIC_KEY), DEFAULT_FILE_MODE), "/" + publicKeyName);
+ container.withCopyToContainer(Transferable.of(Files.readAllBytes(signedRpm), DEFAULT_FILE_MODE), "/" + rpmFileName);
+ container.start();
+ ExecResult importResult = container.execInContainer("rpm", "--import", "/" + publicKeyName);
+ assertEquals(0, importResult.getExitCode());
+ ExecResult checksigResult = container.execInContainer("rpm", "--verbose", "--checksig", "/" + rpmFileName);
+ assertEquals(0, checksigResult.getExitCode());
+ String stdout = checksigResult.getStdout();
+ List lines = stdout.lines().collect(Collectors.toList());
+ // ensure that we find a valid signature for our key
+ assertTrue(lines.contains(" V4 RSA/SHA256 Signature, key ID 679f5723: OK"));
+ System.out.println(stdout);
}
- System.out.println();
}
-
- private static String run(String... command) throws IOException, InterruptedException {
- Process process = new ProcessBuilder(command)
- .start();
- String stdout = new String(ByteStreams.toByteArray(process.getInputStream()));
- process.waitFor();
- return stdout;
- }
-
}