Skip to content

Commit

Permalink
Propagate authentication data from parent to child
Browse files Browse the repository at this point in the history
Fix #2331
  • Loading branch information
laeubi committed Jun 21, 2023
1 parent b1761fe commit 77082fc
Show file tree
Hide file tree
Showing 6 changed files with 216 additions and 135 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Stack;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;
Expand All @@ -32,6 +34,7 @@
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
import org.eclipse.tycho.IRepositoryIdManager;
Expand All @@ -46,6 +49,7 @@ public class MavenAuthenticator extends Authenticator implements Initializable {

static final String PROXY_AUTHORIZATION_HEADER = "Proxy-Authorization";
static final String AUTHORIZATION_HEADER = "Authorization";
private ThreadLocal<Stack<URI>> locationStack = ThreadLocal.withInitial(Stack::new);

@Requirement
LegacySupport legacySupport;
Expand All @@ -59,28 +63,63 @@ public class MavenAuthenticator extends Authenticator implements Initializable {
@Requirement
MavenRepositorySettings mavenRepositorySettings;

@Requirement
Logger log;

private List<MavenRepositoryLocation> repositoryLocations;

public Credentials getServerCredentials(URI uri) {
public Credentials getServerCredentials(URI requestUri) {
List<URI> list = new ArrayList<>(locationStack.get());
Collections.reverse(list);
Stream<URI> repoStream = list.stream().takeWhile(repo -> repo.getHost().equals(requestUri.getHost()));
List<MavenRepositoryLocation> locations = getMavenLocations();
return Stream.concat(Stream.of(requestUri), repoStream).flatMap(uri -> {
log.info("Fetching credentials for " + uri);
return locations.stream().filter(loc -> {
String prefix = loc.getURL().normalize().toASCIIString();
String match = uri.normalize().toASCIIString();
if (match.startsWith(prefix)) {
log.info("Found matching " + loc);
return true;
}
log.info(loc + " does not match (prefix = " + prefix + ", to match = " + match + ")");
return false;
});
}).map(mavenRepositorySettings::getCredentials).filter(Objects::nonNull).findFirst().orElse(null);
}

private List<MavenRepositoryLocation> getMavenLocations() {
Stream<MavenRepositoryLocation> locations = repositoryLocations.stream();
locations = Stream.concat(locations, repositoryIdManager.getKnownMavenRepositoryLocations());
String requestUri = uri.normalize().toASCIIString();
return locations.sorted((loc1, loc2) -> {
List<MavenRepositoryLocation> sorted = locations.sorted((loc1, loc2) -> {
// we wan't the longest prefix match, so first sort all uris by their length ...
String s1 = loc1.getURL().normalize().toASCIIString();
String s2 = loc2.getURL().normalize().toASCIIString();
return Long.compare(s2.length(), s1.length());
}).filter(loc -> {
String prefix = loc.getURL().normalize().toASCIIString();
return requestUri.startsWith(prefix);
}).map(mavenRepositorySettings::getCredentials).filter(Objects::nonNull).findFirst().orElse(null);
}).toList();
return sorted;
}

public void preemtiveAuth(BiConsumer<String, String> headerConsumer, URI uri) {
public Authenticator preemtiveAuth(BiConsumer<String, String> headerConsumer, URI uri) {
// as everything is known and we can't ask the user anyways, preemtive auth is a
// good choice here to prevent successive requests
addAuthHeader(headerConsumer, getAuth(RequestorType.PROXY, uri), PROXY_AUTHORIZATION_HEADER);
addAuthHeader(headerConsumer, getAuth(RequestorType.SERVER, uri), AUTHORIZATION_HEADER);
PasswordAuthentication proxyAuth = getAuth(RequestorType.PROXY, uri);
PasswordAuthentication serverAuth = getAuth(RequestorType.SERVER, uri);
addAuthHeader(headerConsumer, proxyAuth, PROXY_AUTHORIZATION_HEADER);
addAuthHeader(headerConsumer, serverAuth, AUTHORIZATION_HEADER);
return new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
RequestorType type = getRequestorType();
if (type == RequestorType.PROXY) {
return proxyAuth;
}
if (type == RequestorType.SERVER) {
return serverAuth;
}
return null;
}
};
}

@Override
Expand Down Expand Up @@ -139,4 +178,14 @@ public void initialize() throws InitializationException {

}

public void enterLoad(URI location) {
log.info("Enter loading repository " + location);
locationStack.get().push(location);
}

public void exitLoad() {
URI pop = locationStack.get().pop();
log.info("Exit loading repository " + pop);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,19 @@ class RemoteArtifactRepositoryManager implements IArtifactRepositoryManager {

private IArtifactRepositoryManager delegate;
private final IRepositoryIdManager loadingHelper;
private MavenAuthenticator authenticator;

RemoteArtifactRepositoryManager(IArtifactRepositoryManager delegate, IRepositoryIdManager loadingHelper) {
RemoteArtifactRepositoryManager(IArtifactRepositoryManager delegate, IRepositoryIdManager loadingHelper,
MavenAuthenticator authenticator) {
this.delegate = delegate;
this.loadingHelper = loadingHelper;
this.authenticator = authenticator;
}

private URI translate(URI location) {
return loadingHelper.getEffectiveLocation(location);
}

private URI translateAndPrepareLoad(URI location) throws ProvisionException {
return loadingHelper.getEffectiveLocationAndPrepareLoad(location);
}

@Override
public void addRepository(URI location) {
delegate.addRepository(translate(location));
Expand Down Expand Up @@ -98,12 +97,12 @@ public boolean isEnabled(URI location) {
@Override
public IArtifactRepository loadRepository(URI location, int flags, IProgressMonitor monitor)
throws ProvisionException {
return delegate.loadRepository(translateAndPrepareLoad(location), flags, monitor);
return accessRepository(location, uri -> delegate.loadRepository(uri, flags, monitor));
}

@Override
public IArtifactRepository loadRepository(URI location, IProgressMonitor monitor) throws ProvisionException {
return delegate.loadRepository(translateAndPrepareLoad(location), monitor);
return accessRepository(location, uri -> delegate.loadRepository(uri, monitor));
}

@Override
Expand All @@ -113,7 +112,7 @@ public IQueryResult<IArtifactKey> query(IQuery<IArtifactKey> query, IProgressMon

@Override
public IArtifactRepository refreshRepository(URI location, IProgressMonitor monitor) throws ProvisionException {
return delegate.refreshRepository(translateAndPrepareLoad(location), monitor);
return accessRepository(location, uri -> delegate.refreshRepository(uri, monitor));
}

@Override
Expand All @@ -131,4 +130,20 @@ public void setRepositoryProperty(URI location, String key, String value) {
delegate.setRepositoryProperty(translate(location), key, value);
}

public <V> V accessRepository(URI initialUri, RepositoryCallable<V> action) throws ProvisionException {
URI effectiveURI = loadingHelper.getEffectiveLocationAndPrepareLoad(initialUri);
authenticator.enterLoad(effectiveURI);
try {
return action.call(effectiveURI);
} finally {
authenticator.exitLoad();
}
}

private static interface RepositoryCallable<V> {

V call(URI effectiveURI) throws ProvisionException;

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ public class RemoteArtifactRepositoryManagerAgentFactory implements IAgentServic
@Requirement
IRepositoryIdManager repositoryIdManager;

@Requirement
MavenAuthenticator authenticator;

@Override
public Object createService(IProvisioningAgent agent) {
IArtifactRepositoryManager plainRepoManager = (IArtifactRepositoryManager) new ArtifactRepositoryComponent()
Expand All @@ -38,7 +41,7 @@ public Object createService(IProvisioningAgent agent) {
plainRepoManager = new P2MirrorDisablingArtifactRepositoryManager(plainRepoManager,
logger);
}
return new RemoteArtifactRepositoryManager(plainRepoManager, repositoryIdManager);
return new RemoteArtifactRepositoryManager(plainRepoManager, repositoryIdManager, authenticator);
}

private boolean getDisableP2MirrorsConfiguration() {
Expand Down
Loading

0 comments on commit 77082fc

Please sign in to comment.