diff --git a/nexus-core/src/main/java/org/sonatype/nexus/proxy/maven/AbstractChecksumContentValidator.java b/nexus-core/src/main/java/org/sonatype/nexus/proxy/maven/AbstractChecksumContentValidator.java index a3ff37f982..ea24f9ba61 100644 --- a/nexus-core/src/main/java/org/sonatype/nexus/proxy/maven/AbstractChecksumContentValidator.java +++ b/nexus-core/src/main/java/org/sonatype/nexus/proxy/maven/AbstractChecksumContentValidator.java @@ -40,6 +40,14 @@ public boolean isRemoteItemContentValid(final ProxyRepository proxy, final Reso return true; } + final ChecksumPolicy requestChecksumPolicy = + (ChecksumPolicy) req.getRequestContext().get( ChecksumPolicy.REQUEST_CHECKSUM_POLICY_KEY ); + if ( requestChecksumPolicy != null ) + { + // found, it overrides the repository-set checksum policy then + checksumPolicy = requestChecksumPolicy; + } + RemoteHashResponse remoteHash = retrieveRemoteHash( item, proxy, baseUrl ); // let compiler make sure I did not forget to populate validation results diff --git a/nexus-core/src/main/java/org/sonatype/nexus/proxy/maven/ChecksumPolicy.java b/nexus-core/src/main/java/org/sonatype/nexus/proxy/maven/ChecksumPolicy.java index de5030d8ac..ad7d74a485 100644 --- a/nexus-core/src/main/java/org/sonatype/nexus/proxy/maven/ChecksumPolicy.java +++ b/nexus-core/src/main/java/org/sonatype/nexus/proxy/maven/ChecksumPolicy.java @@ -12,6 +12,9 @@ */ package org.sonatype.nexus.proxy.maven; +import org.sonatype.nexus.proxy.RequestContext; +import org.sonatype.nexus.proxy.ResourceStoreRequest; + /** * Checksum policies known in Maven1/2 repositories where checksums are available according to maven layout. * @@ -39,6 +42,21 @@ public enum ChecksumPolicy */ STRICT; + /** + * Key to be used in {@link ResourceStoreRequest} context to mark per-request "override" of the + * {@link MavenProxyRepository} checksum policy. The policy put with this key into request context will be applied + * to given request execution (and all sub-requests, as {@link RequestContext} hierarchy is used). The use of this + * key has effect only on Maven1/2 proxy repositories, as {@link ChecksumPolicy} itself is a Maven specific + * property, and is globally (on repository level) controlled by getters and setters on {@link MavenProxyRepository} + * interface. This "request override" - usually to relax the policy - should be used sparingly, for cases when it's + * known that global repository level checksum policy might pose a blocker to the tried content retrieval, but even + * a corrupted content would not pose any downstream problems (as Nexus would shield downstream consumers by some + * other means, like processing and checking content in-situ). + * + * @since 2.5 + */ + public static String REQUEST_CHECKSUM_POLICY_KEY = "request.maven.checksumPolicy"; + public boolean shouldCheckChecksum() { return !IGNORE.equals( this ); diff --git a/nexus-core/src/main/java/org/sonatype/nexus/proxy/maven/routing/internal/RemotePrefixFileStrategy.java b/nexus-core/src/main/java/org/sonatype/nexus/proxy/maven/routing/internal/RemotePrefixFileStrategy.java index 1d86e4436e..b8949781d2 100644 --- a/nexus-core/src/main/java/org/sonatype/nexus/proxy/maven/routing/internal/RemotePrefixFileStrategy.java +++ b/nexus-core/src/main/java/org/sonatype/nexus/proxy/maven/routing/internal/RemotePrefixFileStrategy.java @@ -29,6 +29,7 @@ import org.sonatype.nexus.proxy.item.RepositoryItemUid; import org.sonatype.nexus.proxy.item.StorageFileItem; import org.sonatype.nexus.proxy.item.StorageItem; +import org.sonatype.nexus.proxy.maven.ChecksumPolicy; import org.sonatype.nexus.proxy.maven.MavenProxyRepository; import org.sonatype.nexus.proxy.maven.routing.Config; import org.sonatype.nexus.proxy.maven.routing.Manager; @@ -147,8 +148,14 @@ protected StorageFileItem retrieveFromRemoteIfExists( final MavenProxyRepository throws IOException { final ResourceStoreRequest request = new ResourceStoreRequest( path ); - request.getRequestContext().put( Manager.ROUTING_INITIATED_FILE_OPERATION_FLAG_KEY, Boolean.TRUE ); request.setRequestRemoteOnly( true ); + request.getRequestContext().put( Manager.ROUTING_INITIATED_FILE_OPERATION_FLAG_KEY, Boolean.TRUE ); + if ( ChecksumPolicy.STRICT == mavenProxyRepository.getChecksumPolicy() ) + { + // NXCM-5188: Relax checksum policy for prefix file request, if needed + request.getRequestContext().put( ChecksumPolicy.REQUEST_CHECKSUM_POLICY_KEY, + ChecksumPolicy.STRICT_IF_EXISTS ); + } // check for remote presence, as fetching with setRequestRemoteOnly has a side effect of // DELETING the file from local cache if not present remotely. In this case, prefix diff --git a/nexus-core/src/test/java/org/sonatype/nexus/proxy/maven/routing/internal/RemotePrefixFileStrategyTest.java b/nexus-core/src/test/java/org/sonatype/nexus/proxy/maven/routing/internal/RemotePrefixFileStrategyTest.java index c775268850..ceb31fb3d6 100644 --- a/nexus-core/src/test/java/org/sonatype/nexus/proxy/maven/routing/internal/RemotePrefixFileStrategyTest.java +++ b/nexus-core/src/test/java/org/sonatype/nexus/proxy/maven/routing/internal/RemotePrefixFileStrategyTest.java @@ -275,4 +275,48 @@ public boolean execute( HttpServletRequest request, HttpServletResponse response } } + /** + * https://issues.sonatype.org/browse/NXCM-5188 Strict Checksum enforcement breaks Automatic Routing + *

+ * Prefix file retrieval uses plain Proxy transport to get the file from remote peer. This causes problems (actually + * prevents happening it) if following conditions are met: Proxy repository has STRICT checksum policy and remote + * prefix file has no checksum published. In this case, relaxing the policy for this request only is okay to do, + * since "this" Nexus will properly process the prefix file anyway, detecting any problems with it, thus protecting + * downstream clients too. + * + * @throws Exception + */ + @Test + public void discoverPlaintextPrefixFileWithoutChecksumsWithStrictChecksumPolicy() + throws Exception + { + server.stop(); + server = + Server.withPort( remoteServerPort ).serve( "/.meta/prefixes.txt" ).withBehaviours( + Behaviours.content( prefixFile1( true ) ) ).start(); + try + { + // setting the policy to String, and note that server set up above publishes + // the prefix file only, no checksums! + final MavenProxyRepository mavenProxyRepository = + getRepositoryRegistry().getRepositoryWithFacet( PROXY_REPO_ID, MavenProxyRepository.class ); + mavenProxyRepository.setChecksumPolicy( ChecksumPolicy.STRICT ); + getApplicationConfiguration().saveConfiguration(); + + final RemoteStrategy subject = lookup( RemoteStrategy.class, RemotePrefixFileStrategy.ID ); + final StrategyResult result = subject.discover( mavenProxyRepository ); + assertThat( result.getMessage(), + equalTo( "Remote publishes prefix file (is less than a day old), using it." ) ); + + final PrefixSource entrySource = result.getPrefixSource(); + assertThat( entrySource.supported(), is( true ) ); + assertThat( entrySource.readEntries(), contains( "/org/apache/maven", "/org/sonatype", "/eu/flatwhite" ) ); + assertThat( entrySource.readEntries().size(), equalTo( 3 ) ); + } + finally + { + server.stop(); + } + } + }