1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.aether.internal.impl.resolution;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.nio.file.Files;
24 import java.nio.file.Paths;
25 import java.util.Collection;
26 import java.util.Collections;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.concurrent.atomic.AtomicReference;
30
31 import org.eclipse.aether.DefaultRepositorySystemSession;
32 import org.eclipse.aether.RepositorySystemSession;
33 import org.eclipse.aether.artifact.Artifact;
34 import org.eclipse.aether.artifact.DefaultArtifact;
35 import org.eclipse.aether.internal.impl.checksum.Sha1ChecksumAlgorithmFactory;
36 import org.eclipse.aether.internal.test.util.TestUtils;
37 import org.eclipse.aether.repository.ArtifactRepository;
38 import org.eclipse.aether.repository.RemoteRepository;
39 import org.eclipse.aether.resolution.ArtifactRequest;
40 import org.eclipse.aether.resolution.ArtifactResult;
41 import org.eclipse.aether.spi.checksums.TrustedChecksumsSource;
42 import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactory;
43 import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactorySelector;
44 import org.eclipse.aether.util.artifact.ArtifactIdUtils;
45 import org.junit.jupiter.api.BeforeEach;
46 import org.junit.jupiter.api.Test;
47
48 import static java.util.stream.Collectors.toList;
49 import static org.junit.jupiter.api.Assertions.*;
50
51
52
53
54 public class TrustedChecksumsArtifactResolverPostProcessorTest implements TrustedChecksumsSource {
55 private static final String TRUSTED_SOURCE_NAME = "test";
56
57 private Artifact artifactWithoutTrustedChecksum;
58
59 private Artifact artifactWithTrustedChecksum;
60
61 private String artifactTrustedChecksum;
62
63 protected DefaultRepositorySystemSession session;
64
65 protected ChecksumAlgorithmFactory checksumAlgorithmFactory = new Sha1ChecksumAlgorithmFactory();
66
67 private TrustedChecksumsArtifactResolverPostProcessor subject;
68
69 private TrustedChecksumsSource.Writer trustedChecksumsWriter;
70
71 @BeforeEach
72 void prepareSubject() throws IOException {
73 Files.createDirectories(Paths.get(System.getProperty("java.io.tmpdir")));
74
75 File tmp = Files.createTempFile("artifact", "tmp").toFile();
76 artifactWithoutTrustedChecksum = new DefaultArtifact("test:test:1.0").setFile(tmp);
77 artifactWithTrustedChecksum = new DefaultArtifact("test:test:2.0").setFile(tmp);
78 artifactTrustedChecksum = "da39a3ee5e6b4b0d3255bfef95601890afd80709";
79
80 session = TestUtils.newSession();
81 ChecksumAlgorithmFactorySelector selector = new ChecksumAlgorithmFactorySelector() {
82 @Override
83 public ChecksumAlgorithmFactory select(String algorithmName) {
84 if (checksumAlgorithmFactory.getName().equals(algorithmName)) {
85 return checksumAlgorithmFactory;
86 }
87 throw new IllegalArgumentException("no alg factory for " + algorithmName);
88 }
89
90 @Override
91 public List<ChecksumAlgorithmFactory> selectList(Collection<String> algorithmNames) {
92 return algorithmNames.stream().map(this::select).collect(toList());
93 }
94
95 @Override
96 public Collection<ChecksumAlgorithmFactory> getChecksumAlgorithmFactories() {
97 return Collections.singletonList(checksumAlgorithmFactory);
98 }
99
100 @Override
101 public boolean isChecksumExtension(String extension) {
102 throw new RuntimeException("not implemented");
103 }
104 };
105 subject = new TrustedChecksumsArtifactResolverPostProcessor(
106 selector, Collections.singletonMap(TRUSTED_SOURCE_NAME, this));
107 trustedChecksumsWriter = null;
108 session.setConfigProperty("aether.artifactResolver.postProcessor.trustedChecksums", Boolean.TRUE.toString());
109 }
110
111
112
113 @Override
114 public Map<String, String> getTrustedArtifactChecksums(
115 RepositorySystemSession session,
116 Artifact artifact,
117 ArtifactRepository artifactRepository,
118 List<ChecksumAlgorithmFactory> checksumAlgorithmFactories) {
119 if (ArtifactIdUtils.toId(artifactWithTrustedChecksum).equals(ArtifactIdUtils.toId(artifact))) {
120 return Collections.singletonMap(checksumAlgorithmFactory.getName(), artifactTrustedChecksum);
121 } else {
122 return Collections.emptyMap();
123 }
124 }
125
126 @Override
127 public Writer getTrustedArtifactChecksumsWriter(RepositorySystemSession session) {
128 return trustedChecksumsWriter;
129 }
130
131
132
133 private ArtifactResult createArtifactResult(Artifact artifact) {
134 ArtifactResult artifactResult = new ArtifactResult(new ArtifactRequest().setArtifact(artifact));
135 artifactResult.setArtifact(artifact);
136 artifactResult.setRepository(
137 new RemoteRepository.Builder("central", "default", "https://repo.maven.apache.org/maven2/").build());
138 return artifactResult;
139 }
140
141
142
143 @Test
144 void haveMatchingChecksumPass() {
145 ArtifactResult artifactResult = createArtifactResult(artifactWithTrustedChecksum);
146 assertTrue(artifactResult.isResolved());
147
148 subject.postProcess(session, Collections.singletonList(artifactResult));
149 assertTrue(artifactResult.isResolved());
150 }
151
152 @Test
153 void haveNoChecksumPass() {
154 ArtifactResult artifactResult = createArtifactResult(artifactWithoutTrustedChecksum);
155 assertTrue(artifactResult.isResolved());
156
157 subject.postProcess(session, Collections.singletonList(artifactResult));
158 assertTrue(artifactResult.isResolved());
159 }
160
161 @Test
162 void haveNoChecksumFailIfMissingEnabledFail() {
163 session.setConfigProperty(
164 "aether.artifactResolver.postProcessor.trustedChecksums.failIfMissing", Boolean.TRUE.toString());
165 ArtifactResult artifactResult = createArtifactResult(artifactWithoutTrustedChecksum);
166 assertTrue(artifactResult.isResolved());
167
168 subject.postProcess(session, Collections.singletonList(artifactResult));
169 assertFalse(artifactResult.isResolved());
170 assertFalse(artifactResult.getExceptions().isEmpty());
171 assertTrue(artifactResult
172 .getExceptions()
173 .get(0)
174 .getMessage()
175 .contains("Missing from " + TRUSTED_SOURCE_NAME + " trusted"));
176 }
177
178 @Test
179 void haveMismatchingChecksumFail() {
180 artifactTrustedChecksum = "foobar";
181 ArtifactResult artifactResult = createArtifactResult(artifactWithTrustedChecksum);
182 assertTrue(artifactResult.isResolved());
183
184 subject.postProcess(session, Collections.singletonList(artifactResult));
185 assertFalse(artifactResult.isResolved());
186 assertFalse(artifactResult.getExceptions().isEmpty());
187 assertTrue(artifactResult.getExceptions().get(0).getMessage().contains("trusted checksum mismatch"));
188 assertTrue(artifactResult
189 .getExceptions()
190 .get(0)
191 .getMessage()
192 .contains(TRUSTED_SOURCE_NAME + "=" + artifactTrustedChecksum));
193 }
194
195 @Test
196 void recordCalculatedChecksum() {
197 AtomicReference<String> recordedChecksum = new AtomicReference<>(null);
198 this.trustedChecksumsWriter = new Writer() {
199 @Override
200 public void addTrustedArtifactChecksums(
201 Artifact artifact,
202 ArtifactRepository artifactRepository,
203 List<ChecksumAlgorithmFactory> checksumAlgorithmFactories,
204 Map<String, String> trustedArtifactChecksums) {
205 recordedChecksum.set(trustedArtifactChecksums.get(checksumAlgorithmFactory.getName()));
206 }
207 };
208 session.setConfigProperty(
209 "aether.artifactResolver.postProcessor.trustedChecksums.record", Boolean.TRUE.toString());
210 ArtifactResult artifactResult = createArtifactResult(artifactWithTrustedChecksum);
211 assertTrue(artifactResult.isResolved());
212
213 subject.postProcess(session, Collections.singletonList(artifactResult));
214 assertTrue(artifactResult.isResolved());
215
216 String checksum = recordedChecksum.get();
217 assertNotNull(checksum);
218 assertEquals(checksum, artifactTrustedChecksum);
219 }
220 }