JCLOUDS-1220: Possibility to change the name of Header of Identity v1 protocol

This commit is contained in:
Etienne CARRIERE 2016-12-28 17:33:53 +01:00 committed by Ignasi Barrera
parent c2cda931a5
commit ac2f746e64
5 changed files with 126 additions and 16 deletions

View File

@ -19,8 +19,13 @@ package org.jclouds.openstack.swift.v1;
import static org.jclouds.Constants.PROPERTY_IDEMPOTENT_METHODS;
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.CREDENTIAL_TYPE;
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_TYPE;
import static org.jclouds.openstack.swift.v1.reference.TempAuthHeaders.TEMP_AUTH_HEADER_USER;
import static org.jclouds.openstack.swift.v1.reference.TempAuthHeaders.TEMP_AUTH_HEADER_PASS;
import static org.jclouds.openstack.swift.v1.reference.TempAuthHeaders.DEFAULT_HEADER_USER;
import static org.jclouds.openstack.swift.v1.reference.TempAuthHeaders.DEFAULT_HEADER_PASS;
import static org.jclouds.reflect.Reflection2.typeToken;
import java.net.URI;
import java.util.Properties;
@ -62,6 +67,8 @@ public class SwiftApiMetadata extends BaseHttpApiMetadata<SwiftApi> {
properties.setProperty(PROPERTY_IDEMPOTENT_METHODS, "DELETE,GET,HEAD,OPTIONS,POST,PUT");
// Can alternatively be set to "tempAuthCredentials"
properties.setProperty(CREDENTIAL_TYPE, CredentialTypes.PASSWORD_CREDENTIALS);
properties.setProperty(TEMP_AUTH_HEADER_USER, DEFAULT_HEADER_USER);
properties.setProperty(TEMP_AUTH_HEADER_PASS, DEFAULT_HEADER_PASS);
return properties;
}

View File

@ -0,0 +1,53 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.openstack.swift.v1.binders;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.openstack.swift.v1.reference.TempAuthHeaders.TEMP_AUTH_HEADER_USER;
import static org.jclouds.openstack.swift.v1.reference.TempAuthHeaders.TEMP_AUTH_HEADER_PASS;
import org.jclouds.domain.Credentials;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.Binder;
import com.google.inject.Inject;
import com.google.inject.name.Named;
/**
* Binder to the tempAuthAuthentication
*
*/
public final class TempAuthBinder implements Binder{
private final String identityHeaderNameUser;
private final String identityHeaderNamePass;
@Inject
TempAuthBinder(@Named(TEMP_AUTH_HEADER_USER) String identityHeaderNameUser, @Named(TEMP_AUTH_HEADER_PASS) String identityHeaderNamePass) {
this.identityHeaderNameUser = identityHeaderNameUser;
this.identityHeaderNamePass = identityHeaderNamePass;
}
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
checkNotNull(request, "request");
checkArgument(input instanceof Credentials, "input must be a non-null org.jclouds.domain.Credentials");
return (R) request.toBuilder().replaceHeader(identityHeaderNameUser, ((Credentials) input).identity)
.replaceHeader(identityHeaderNamePass, ((Credentials) input).credential).build();
}
}

View File

@ -21,6 +21,8 @@ import static org.jclouds.http.Uris.uriBuilder;
import static org.jclouds.openstack.v2_0.ServiceType.OBJECT_STORE;
import static org.jclouds.openstack.v2_0.reference.AuthHeaders.AUTH_TOKEN;
import static org.jclouds.rest.config.BinderUtils.bindHttpApi;
import static org.jclouds.openstack.swift.v1.reference.TempAuthHeaders.STORAGE_URL;
import static org.jclouds.openstack.swift.v1.reference.TempAuthHeaders.TEMP_AUTH_HEADER_USER;
import java.io.Closeable;
import java.net.URI;
@ -31,7 +33,6 @@ import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import org.jclouds.ContextBuilder;
import org.jclouds.domain.Credentials;
@ -44,9 +45,11 @@ import org.jclouds.openstack.keystone.v2_0.domain.Endpoint;
import org.jclouds.openstack.keystone.v2_0.domain.Service;
import org.jclouds.openstack.keystone.v2_0.domain.Token;
import org.jclouds.openstack.keystone.v2_0.domain.User;
import org.jclouds.openstack.swift.v1.binders.TempAuthBinder;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.InvocationContext;
import org.jclouds.rest.annotations.ApiVersion;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.VirtualHost;
@ -62,10 +65,6 @@ import com.google.inject.name.Named;
* in {@code auth/v1.0/}.
*/
public final class SwiftAuthenticationModule extends KeystoneAuthenticationModule {
private static final String STORAGE_USER = "X-Storage-User";
private static final String STORAGE_PASS = "X-Storage-Pass";
private static final String STORAGE_URL = "X-Storage-Url";
@Override
protected void configure() {
super.configure();
@ -78,7 +77,7 @@ public final class SwiftAuthenticationModule extends KeystoneAuthenticationModul
.putAll(super.authenticationMethods(i))
.put("tempAuthCredentials", i.getInstance(TempAuth.class)).build();
}
static final class TempAuth implements Function<Credentials, Access> {
private final TempAuthApi delegate;
@ -87,7 +86,7 @@ public final class SwiftAuthenticationModule extends KeystoneAuthenticationModul
}
@Override public Access apply(Credentials input) {
return delegate.auth(input.identity, input.credential);
return delegate.auth(input);
}
}
@ -98,19 +97,22 @@ public final class SwiftAuthenticationModule extends KeystoneAuthenticationModul
@GET
@Consumes
@ResponseParser(AdaptTempAuthResponseToAccess.class)
Access auth(@HeaderParam(STORAGE_USER) String user, @HeaderParam(STORAGE_PASS) String key);
Access auth(@BinderParam(TempAuthBinder.class) Credentials credentials);
}
static final class AdaptTempAuthResponseToAccess
implements Function<HttpResponse, Access>, InvocationContext<AdaptTempAuthResponseToAccess> {
private final String identityHeaderNameUser;
private final String apiVersion;
private String host;
private String username;
@Inject AdaptTempAuthResponseToAccess(@ApiVersion String apiVersion) {
@Inject AdaptTempAuthResponseToAccess(@ApiVersion String apiVersion, @Named(TEMP_AUTH_HEADER_USER) String identityHeaderNameUser) {
this.apiVersion = apiVersion;
this.identityHeaderNameUser = identityHeaderNameUser;
}
@Override public Access apply(HttpResponse from) {
@ -153,7 +155,7 @@ public final class SwiftAuthenticationModule extends KeystoneAuthenticationModul
public AdaptTempAuthResponseToAccess setContext(HttpRequest request) {
String host = request.getEndpoint().getHost();
this.host = host;
this.username = request.getFirstHeaderOrNull(STORAGE_USER);
this.username = request.getFirstHeaderOrNull(identityHeaderNameUser);
return this;
}
}

View File

@ -0,0 +1,33 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.openstack.swift.v1.reference;
/**
* Headers for TempAuth authentication
*/
public final class TempAuthHeaders {
public static final String TEMP_AUTH_HEADER_USER = "jclouds.swift.tempAuth.headerUser";
public static final String TEMP_AUTH_HEADER_PASS = "jclouds.swift.tempAuth.headerPass";
public static final String DEFAULT_HEADER_USER = "X-Storage-User";
public static final String DEFAULT_HEADER_PASS = "X-Storage-Pass";
public static final String STORAGE_URL = "X-Storage-Url";
private TempAuthHeaders() {
throw new AssertionError("intentionally unimplemented");
}
}

View File

@ -28,6 +28,7 @@ import java.util.Properties;
import org.jclouds.ContextBuilder;
import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.openstack.swift.v1.reference.TempAuthHeaders;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
@ -43,15 +44,30 @@ public class TempAuthMockTest {
private MockWebServer swiftServer;
private MockWebServer tempAuthServer;
public void testTempAuthRequestWithCustomHeader() throws Exception {
final String headerName = "X-Auth-User";
final String headerPass = "X-Auth-Pass";
Properties overrides = new Properties();
overrides.setProperty(TempAuthHeaders.TEMP_AUTH_HEADER_USER , headerName);
overrides.setProperty(TempAuthHeaders.TEMP_AUTH_HEADER_PASS , headerPass);
// with specific Header Name values
test(overrides, headerName, headerPass);
}
public void testTempAuthRequest() throws Exception {
tempAuthServer.enqueue(new MockResponse().setResponseCode(204)
Properties overrides = new Properties();
// with default values
test(overrides, "X-Storage-User", "X-Storage-Pass");
}
private void test(Properties overrides, String identityHeaderName, String identityHeaderPass) throws Exception{
tempAuthServer.enqueue(new MockResponse().setResponseCode(204)
.addHeader("X-Auth-Token", "token")
.addHeader("X-Storage-Url", swiftServer.getUrl("").toString()));
swiftServer.enqueue(new MockResponse().setBody("[{\"name\":\"test_container_1\",\"count\":2,\"bytes\":78}]"));
SwiftApi api = api(tempAuthServer.getUrl("").toString());
SwiftApi api = api(tempAuthServer.getUrl("").toString(), overrides);
// Region name is derived from the swift server host.
assertEquals(api.getConfiguredRegions(), ImmutableSet.of(tempAuthServer.getHostName()));
@ -60,8 +76,8 @@ public class TempAuthMockTest {
RecordedRequest auth = tempAuthServer.takeRequest();
assertEquals(auth.getMethod(), "GET");
assertEquals(auth.getHeader("X-Storage-User"), "user");
assertEquals(auth.getHeader("X-Storage-Pass"), "password");
assertEquals(auth.getHeader(identityHeaderName), "user");
assertEquals(auth.getHeader(identityHeaderPass), "password");
// list request went to the destination specified in X-Storage-Url.
RecordedRequest listContainers = swiftServer.takeRequest();
@ -71,8 +87,7 @@ public class TempAuthMockTest {
assertEquals(listContainers.getHeader("X-Auth-Token"), "token");
}
private SwiftApi api(String authUrl) throws IOException {
Properties overrides = new Properties();
private SwiftApi api(String authUrl, Properties overrides) throws IOException {
overrides.setProperty(CREDENTIAL_TYPE, "tempAuthCredentials");
return ContextBuilder.newBuilder(new SwiftApiMetadata())
.credentials("user", "password")