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

[ISSUE 606] Discard signatures from jar file that was mutated #607

Merged
merged 9 commits into from
Aug 20, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ void options_test() throws Exception {
try (Processor processor = new Processor()) {
processor.setProperty("-transformer", "tb;arg=value1");
processor.setProperty("-transformer.overwrite", "overwrite");
processor.setProperty("-transformer.stripSignatures", "stripSignatures");
processor.setProperty("-transformer.morebundles", "bundles;arg=value2");
processor.setProperty("-transformer.immediate",
"immediate;option=tv;package=org.eclipse.transformer.test.api;version=\"[2.0\\,3.0);Export-Package=2.0.0\"");
Expand All @@ -253,6 +254,11 @@ void options_test() throws Exception {
assertThat(options.getOptionValues(AppOption.WIDEN_ARCHIVE_NESTING)).isNull();
assertThat(options.getOptionValue(AppOption.WIDEN_ARCHIVE_NESTING)).isNull();

assertThat(options.getDefaultValue(AppOption.STRIP_SIGNATURES)).isNull();
assertThat(options.hasOption(AppOption.STRIP_SIGNATURES)).isTrue();
assertThat(options.getOptionValues(AppOption.STRIP_SIGNATURES)).isEmpty();
assertThat(options.getOptionValue(AppOption.STRIP_SIGNATURES)).isNull();

assertThat(options.getOptionValues(AppOption.RULES_IMMEDIATE_DATA)).containsExactly("tv",
"org.eclipse.transformer.test.api", "[2.0\\,3.0);Export-Package=2.0.0");
}
Expand Down
3 changes: 2 additions & 1 deletion maven-plugins/transformer-maven-plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,9 @@ A list value of `-` (Hyphen-minus) is ignored. This can be used to configure an
|`immediates` | A list of immediate options. |
|`invert` | If `true`, invert the rename rules. _Defaults to `false`_. |
|`overwrite` | If `true`, the items which transform to the same path as an existing item overwrite the existing item. _Defaults to `false`_. |
|`widen` | If `true`, By default, archive nesting is restricted to JavaEE active locations. This may be relaxed to enable JAR and ZIP within JAR, ZIP within ZIP, and ZIP within EAR, WAR, and RAR. _Defaults to `false`_. |
|`widen` | If `true`, by default, archive nesting is restricted to JavaEE active locations. This may be relaxed to enable JAR and ZIP within JAR, ZIP within ZIP, and ZIP within EAR, WAR, and RAR. _Defaults to `false`_. |
|`jakartaDefaults` | If `true`, the Jakarta rule defaults are included. _Defaults to `false`_. |
|`stripSignatures` | If `true`, signature files will be removed from signed JAR files. _Defaults to `false`_. |

```xml
<rules>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public abstract class AbstractTransformerMojo extends AbstractMojo {
* <p>
* The rules configuration includes: selections, renames, versions, bundles,
* directs, texts, perClassConstants, immediates, invert, overwrite, widen,
* and jakartaDefaults.
* jakartaDefaults, and stripSignatures.
*/
@Parameter
private TransformerRules rules = new TransformerRules();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ public boolean hasOption(AppOption option) {
case WIDEN_ARCHIVE_NESTING :
has = rules.isWiden();
break;
case STRIP_SIGNATURES :
has = rules.isStripSignatures();
break;
default :
has = TransformOptions.super.hasOption(option);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ public class TransformerRunMojo extends AbstractMojo {
@Parameter(defaultValue = "true", property = "transformer-plugin.overwrite", required = true)
private boolean overwrite;

@Parameter(defaultValue = "false", property = "transformer-plugin.stripSignatures", required = false)
private boolean stripSignatures;

@Parameter(defaultValue = "true", property = "transformer-plugin.attach", required = true)
private boolean attach;

Expand Down Expand Up @@ -131,6 +134,8 @@ public boolean hasOption(AppOption option) {
return overwrite;
case INVERT :
return invert;
case STRIP_SIGNATURES:
return stripSignatures;
default :
return TransformOptions.super.hasOption(option);
}
Expand Down Expand Up @@ -257,4 +262,7 @@ void setAttach(boolean attach) {
this.attach = attach;
}

void setStripSignatures(boolean stripSignatures) {
this.stripSignatures = stripSignatures;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class TransformerRules {
private boolean overwrite;
private boolean widen;
private boolean jakartaDefaults;
private boolean stripSignatures;

public TransformerRules() {}

Expand Down Expand Up @@ -134,12 +135,26 @@ public void setWiden(boolean widen) {
this.widen = widen;
}

/**
* @return the stripSignatures
*/
public boolean isStripSignatures() {
return stripSignatures;
}

/**
* @param stripSignatures the stripSignatures to set
*/
public void setStripSignatures(boolean stripSignatures) {
this.stripSignatures = stripSignatures;
}

@Override
public String toString() {
return String.format(
"selections=%s, renames=%s, versions=%s, bundles=%s, directs=%s, texts=%s, perClassConstants=%s, immediates=%s, invert=%s, overwrite=%s, widen=%s, jakartaDefaults=%s",
"selections=%s, renames=%s, versions=%s, bundles=%s, directs=%s, texts=%s, perClassConstants=%s, immediates=%s, invert=%s, overwrite=%s, widen=%s, jakartaDefaults=%s, stripSignatures=%s",
getSelections(), getRenames(), getVersions(), getBundles(), getDirects(), getTexts(),
getPerClassConstants(), getImmediates(), isInvert(), isOverwrite(), isWiden(), isJakartaDefaults());
getPerClassConstants(), getImmediates(), isInvert(), isOverwrite(), isWiden(), isJakartaDefaults(), isStripSignatures());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,19 @@

package org.eclipse.transformer.maven;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.DefaultArtifact;
Expand All @@ -28,8 +32,12 @@
import org.apache.maven.plugin.testing.stubs.DefaultArtifactHandlerStub;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectHelper;
import org.eclipse.transformer.action.ElementAction;
import org.jboss.shrinkwrap.api.Archive;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.FileAsset;
import org.jboss.shrinkwrap.api.exporter.ZipExporter;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.Rule;
import org.junit.Test;
Expand Down Expand Up @@ -58,15 +66,13 @@ public void testProjectArtifactTransformerPlugin() throws Exception {
mojo.setOutputDirectory(tmp.newFolder(name.getMethodName()));
mojo.setAttach(true);

assertNotNull(mojo);

final File targetDirectory = this.resources.getBasedir("transform-build-artifact");
final File modelDirectory = new File(targetDirectory, "target/model");
final File pom = new File(targetDirectory, "pom.xml");

final MavenProject mavenProject = createMavenProject(modelDirectory, pom, "war", "rest-sample");
mavenProject.getArtifact()
.setFile(createService());
.setFile(createService("war", targetDirectory));

mojo.setProject(mavenProject);
mojo.setClassifier("transformed");
Expand Down Expand Up @@ -100,8 +106,6 @@ public void testMultipleArtifactTransformerPlugin() throws Exception {
mojo.setProjectHelper(this.rule.lookup(MavenProjectHelper.class));
mojo.setAttach(true);

assertNotNull(mojo);

final File targetDirectory = this.resources.getBasedir("transform-build-artifact");
final File modelDirectory = new File(targetDirectory, "target/model");
final File pom = new File(targetDirectory, "pom.xml");
Expand All @@ -113,11 +117,11 @@ public void testMultipleArtifactTransformerPlugin() throws Exception {
mojo.setOutputDirectory(tmp.newFolder(name.getMethodName()));

mojo.getProjectHelper()
.attachArtifact(mavenProject, "zip", "test1", createService());
.attachArtifact(mavenProject, "zip", "test1", createService("war", targetDirectory));
mojo.getProjectHelper()
.attachArtifact(mavenProject, "zip", "test2", createService());
.attachArtifact(mavenProject, "zip", "test2", createService("war", targetDirectory));
mojo.getProjectHelper()
.attachArtifact(mavenProject, "zip", "test3", createService());
.attachArtifact(mavenProject, "zip", "test3", createService("war", targetDirectory));

final Artifact[] sourceArtifacts = mojo.getSourceArtifacts();
assertEquals(3, sourceArtifacts.length);
Expand Down Expand Up @@ -163,15 +167,13 @@ public void testProjectArtifactTransformerPluginNoAttach() throws Exception {
mojo.setOutputDirectory(tmp.newFolder(name.getMethodName()));
mojo.setAttach(false);

assertNotNull(mojo);

final File targetDirectory = this.resources.getBasedir("transform-build-artifact");
final File modelDirectory = new File(targetDirectory, "target/model");
final File pom = new File(targetDirectory, "pom.xml");

final MavenProject mavenProject = createMavenProject(modelDirectory, pom, "war", "rest-sample");
mavenProject.getArtifact()
.setFile(createService());
.setFile(createService("war", targetDirectory));

mojo.setProject(mavenProject);
mojo.setClassifier("transformed");
Expand All @@ -190,6 +192,51 @@ public void testProjectArtifactTransformerPluginNoAttach() throws Exception {
.size());
}

@Test
public void testProjectArtifactTransformerPluginStripSignatureFiles() throws Exception {
final TransformerRunMojo mojo = new TransformerRunMojo();
mojo.setProjectHelper(this.rule.lookup(MavenProjectHelper.class));
mojo.setOverwrite(true);
mojo.setOutputDirectory(tmp.newFolder(name.getMethodName()));
mojo.setAttach(true);
mojo.setStripSignatures(true);

final File targetDirectory = this.resources.getBasedir("transform-build-jar-artifact");
final File modelDirectory = new File(targetDirectory, "target/model");
final File pom = new File(targetDirectory, "pom.xml");

final MavenProject mavenProject = createMavenProject(modelDirectory, pom, "jar", "rest-sample");
mavenProject.getArtifact()
.setFile(createService("jar", targetDirectory));

mojo.setProject(mavenProject);
mojo.setClassifier("transformed");

final Artifact[] sourceArtifacts = mojo.getSourceArtifacts();
assertEquals(1, sourceArtifacts.length);
final Artifact sourceArtifact = sourceArtifacts[0];
assertEquals("org.superbiz.rest", sourceArtifact.getGroupId());
assertEquals("rest-sample", sourceArtifact.getArtifactId());
assertEquals("1.0-SNAPSHOT", sourceArtifact.getVersion());
assertEquals("jar", sourceArtifact.getType());
assertNull(sourceArtifact.getClassifier());
assertThat(getSignatureFileEntries(sourceArtifact.getFile())).containsExactly("META-INF/MYKEY.SF", "META-INF/MYKEY.DSA");

mojo.transform(sourceArtifacts[0]);

assertEquals(1, mavenProject.getAttachedArtifacts()
.size());
final Artifact transformedArtifact = mavenProject.getAttachedArtifacts()
.get(0);

assertEquals("org.superbiz.rest", transformedArtifact.getGroupId());
assertEquals("rest-sample", transformedArtifact.getArtifactId());
assertEquals("1.0-SNAPSHOT", transformedArtifact.getVersion());
assertEquals("jar", transformedArtifact.getType());
assertEquals("transformed", transformedArtifact.getClassifier());
assertThat(getSignatureFileEntries(transformedArtifact.getFile())).isEmpty();
}

public MavenProject createMavenProject(final File modelDirectory, final File pom, final String packaging,
final String artfifactId) {
final MavenProject mavenProject = new MavenProject();
Expand All @@ -205,19 +252,44 @@ public MavenProject createMavenProject(final File modelDirectory, final File pom
.setOutputDirectory(modelDirectory.getAbsolutePath());
mavenProject.setArtifact(
new DefaultArtifact(mavenProject.getGroupId(), mavenProject.getArtifactId(), mavenProject.getVersion(),
(String) null, "war", (String) null, new DefaultArtifactHandlerStub(packaging, null)));
null, packaging, null, new DefaultArtifactHandlerStub(packaging, null)));
return mavenProject;
}

public File createService() throws IOException {
final File tempFile = File.createTempFile("service", ".war");
private static File createService(String packaging, File targetDirectory) throws IOException {
final File tempFile = File.createTempFile("service", "." + packaging);
tempFile.delete();

final WebArchive webArchive = ShrinkWrap.create(WebArchive.class, "service.war")
.addClass(EchoService.class);
final Archive archive;
if (packaging.equals("jar")) {
archive = ShrinkWrap.create(JavaArchive.class, "service." + packaging)
.addClass(EchoService.class);
} else {
archive = ShrinkWrap.create(WebArchive.class, "service." + packaging)
.addClass(EchoService.class);
}

if (packaging.equals("jar")) {
archive.add(new FileAsset(new File(targetDirectory, "META-INF/MYKEY.SF")), "META-INF/MYKEY.SF");
archive.add(new FileAsset(new File(targetDirectory, "META-INF/MYKEY.DSA")), "META-INF/MYKEY.DSA");
}

webArchive.as(ZipExporter.class)
archive.as(ZipExporter.class)
.exportTo(tempFile, true);
return tempFile;
}

private static Set<String> getSignatureFileEntries(File file) throws IOException {
try (ZipFile zipFile = new ZipFile(file)) {
final Enumeration<? extends ZipEntry> entries = zipFile.entries();
final Set<String> signatureFiles = new HashSet<>();
while (entries.hasMoreElements()) {
final ZipEntry zipEntry = entries.nextElement();
if (ElementAction.SIGNATURE_FILE_PATTERN.matcher(zipEntry.getName()).matches()) {
signatureFiles.add(zipEntry.getName());
}
}
return signatureFiles;
}
}
}
Binary file not shown.
Loading