Author: tmaret Date: Wed Jun 21 09:03:42 2017 New Revision: 1799406 URL: http://svn.apache.org/viewvc?rev=1799406&view=rev Log: SLING-6969 - Support OAuth 2.0 server to server authentication in Distribution transport
* Add support for authorization header provided via the DistributionTransportSecret's credential map Modified: sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/transport/impl/SimpleHttpDistributionTransport.java Modified: sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/transport/impl/SimpleHttpDistributionTransport.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/transport/impl/SimpleHttpDistributionTransport.java?rev=1799406&r1=1799405&r2=1799406&view=diff ============================================================================== --- sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/transport/impl/SimpleHttpDistributionTransport.java (original) +++ sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/transport/impl/SimpleHttpDistributionTransport.java Wed Jun 21 09:03:42 2017 @@ -22,10 +22,12 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.io.InputStream; import java.net.URI; +import java.util.Collections; import java.util.Map; import java.util.UUID; import org.apache.commons.io.IOUtils; +import org.apache.http.HttpHeaders; import org.apache.http.HttpHost; import org.apache.http.client.HttpResponseException; import org.apache.http.client.fluent.Executor; @@ -33,6 +35,9 @@ import org.apache.http.client.fluent.Req import org.apache.http.client.fluent.Response; import org.apache.http.conn.HttpHostConnectException; import org.apache.http.entity.ContentType; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.message.BasicHeader; import org.apache.http.protocol.HTTP; import org.apache.sling.api.resource.ResourceResolver; import org.apache.sling.distribution.DistributionRequest; @@ -53,8 +58,24 @@ import org.apache.sling.distribution.uti */ public class SimpleHttpDistributionTransport implements DistributionTransport { + /** + * The key name of an entry holding a username associated to the #PASSWORD in + * the {@link DistributionTransportSecret}'s credentials map. + */ private static final String USERNAME = "username"; + + /** + * The key name of an entry holding a password associated to the #USERNAME in + * the {@link DistributionTransportSecret}'s credentials map. + */ private static final String PASSWORD = "password"; + + /** + * The key name of an entry holding an Authorization header in + * the {@link DistributionTransportSecret}'s credentials map. + */ + private static final String AUTHORIZATION = "authorization"; + private static final String EXECUTOR_CONTEXT_KEY_PREFIX = "ExecutorContextKey"; /** @@ -179,36 +200,50 @@ public class SimpleHttpDistributionTrans return null; } - private Executor authenticate(DistributionTransportSecret secret, Executor executor) { - Map<String, String> credentialsMap = secret.asCredentialsMap(); - if (credentialsMap != null) { - URI uri = distributionEndpoint.getUri(); - executor = executor.auth(new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme()), - credentialsMap.get(USERNAME), credentialsMap.get(PASSWORD)).authPreemptive( - new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme())); - log.debug("authenticate user={}, endpoint={}", secret.asCredentialsMap().get(USERNAME), distributionEndpoint.getUri()); - } - return executor; - } - private String getHostAndPort(URI uri) { return uri.getHost() + ":" + uri.getPort(); } private Executor getExecutor(DistributionTransportContext distributionContext) { - if (distributionContext.containsKey(contextKeyExecutor)) { - return distributionContext.get(contextKeyExecutor, Executor.class); + Executor executor = distributionContext.get(contextKeyExecutor, Executor.class); + if (executor == null) { + executor = buildExecutor(); + distributionContext.put(contextKeyExecutor, executor); } + return executor; + } - Executor executor = Executor.newInstance(); + private Executor buildAuthExecutor(String username, String password) { + URI uri = distributionEndpoint.getUri(); + Executor executor = Executor.newInstance() + .auth(new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme()), username, password) + .authPreemptive(new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme())); + log.debug("authenticate user={}, endpoint={}", username, uri); + return executor; + } - DistributionTransportSecret secret = secretProvider.getSecret(distributionEndpoint.getUri()); - executor = authenticate(secret, executor); + private Executor buildAuthExecutor(String authorizationHeader) { + HttpClientBuilder builder = HttpClients.custom(); + builder.setDefaultHeaders(Collections.singletonList(new BasicHeader(HttpHeaders.AUTHORIZATION, authorizationHeader))); + Executor executor = Executor.newInstance(builder.build()); + log.debug("set Authorization header, endpoint={}", distributionEndpoint.getUri()); + return executor; + } - distributionContext.put(contextKeyExecutor, executor); + private Executor buildAuthExecutor(@Nonnull Map<String, String> credentialsMap) { + return (credentialsMap.containsKey(AUTHORIZATION)) + ? buildAuthExecutor(credentialsMap.get(AUTHORIZATION)) + : buildAuthExecutor(credentialsMap.get(USERNAME), credentialsMap.get(PASSWORD)); + } - return executor; + private Executor buildExecutor() { + DistributionTransportSecret secret = secretProvider.getSecret(distributionEndpoint.getUri()); + Map<String, String> credentialsMap = secret.asCredentialsMap(); + return (credentialsMap != null) + ? buildAuthExecutor(credentialsMap) + : Executor.newInstance(); } + }