
org.jclouds.openstack.swift.v1.config.SwiftAuthenticationModule Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jclouds-shaded Show documentation
Show all versions of jclouds-shaded Show documentation
Provides a shaded jclouds with relocated guava and guice
The newest version!
/*
* 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.config;
import static org.jclouds.http.HttpUtils.releasePayload;
import static org.jclouds.http.Uris.uriBuilder;
import static org.jclouds.openstack.keystone.auth.AuthHeaders.AUTH_TOKEN;
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 static org.jclouds.openstack.v2_0.ServiceType.OBJECT_STORE;
import static org.jclouds.rest.config.BinderUtils.bindHttpApi;
import java.io.Closeable;
import java.net.URI;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import org.jclouds.ContextBuilder;
import org.jclouds.domain.Credentials;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.openstack.keystone.auth.config.AuthenticationModule;
import org.jclouds.openstack.keystone.auth.domain.AuthInfo;
import org.jclouds.openstack.keystone.v2_0.domain.Access;
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;
import shaded.com.google.common.base.Function;
import shaded.com.google.common.collect.ImmutableMap;
import shaded.com.google.inject.Injector;
import shaded.com.google.inject.name.Named;
/**
* When {@link org.jclouds.openstack.keystone.config.KeystoneProperties#CREDENTIAL_TYPE} is set to {@code
* tempAuthCredentials}, do not use Keystone. Instead, bridge TempAuth to Keystone by faking a service catalog out of
* the storage url. The {@link ContextBuilder#endpoint(String) endpoint} must be set to the TempAuth url, usually ending
* in {@code auth/v1.0/}.
*/
public final class SwiftAuthenticationModule extends AuthenticationModule {
@Override
protected void configure() {
super.configure();
bindHttpApi(binder(), TempAuthApi.class);
}
@Override
protected Map> authenticationMethods(Injector i) {
return ImmutableMap.> builder()
.putAll(super.authenticationMethods(i))
.put("tempAuthCredentials", i.getInstance(TempAuth.class))
.build();
}
static final class TempAuth implements Function {
private final TempAuthApi delegate;
@Inject TempAuth(TempAuthApi delegate) {
this.delegate = delegate;
}
@Override public AuthInfo apply(Credentials input) {
return delegate.auth(input);
}
}
@VirtualHost
interface TempAuthApi extends Closeable {
@Named("TempAuth")
@GET
@Consumes
@ResponseParser(AdaptTempAuthResponseToAccess.class)
Access auth(@BinderParam(TempAuthBinder.class) Credentials credentials);
}
static final class AdaptTempAuthResponseToAccess
implements Function, InvocationContext {
private final String identityHeaderNameUser;
private final String apiVersion;
private String host;
private String username;
@Inject AdaptTempAuthResponseToAccess(@ApiVersion String apiVersion, @Named(TEMP_AUTH_HEADER_USER) String identityHeaderNameUser) {
this.apiVersion = apiVersion;
this.identityHeaderNameUser = identityHeaderNameUser;
}
@Override public Access apply(HttpResponse from) {
releasePayload(from);
URI storageUrl = null;
String authToken = null;
for (Map.Entry entry : from.getHeaders().entries()) {
String header = entry.getKey();
if (header.equalsIgnoreCase(STORAGE_URL)) {
storageUrl = getURI(entry.getValue());
} else if (header.equalsIgnoreCase(AUTH_TOKEN)) {
authToken = entry.getValue();
}
}
if (storageUrl == null || authToken == null) {
throw new AuthorizationException("Invalid headers in TempAuth response " + from);
}
// For portability with keystone, based on common knowledge that these tokens tend to expire in 24 hours
// http://docs.openstack.org/api/openstack-object-storage/1.0/content/authentication-object-dev-guide.html
Date expires = new Date(System.currentTimeMillis() + TimeUnit.HOURS.toMillis(24));
return Access.builder()
.user(User.builder().id(username).name(username).build())
.token(Token.builder().id(authToken).expires(expires).build())
.service(Service.builder().name("Object Storage").type(OBJECT_STORE)
.endpoint(Endpoint.builder().publicURL(storageUrl).id(apiVersion).region(storageUrl.getHost()).build())
.build()).build();
}
// TODO: find the swift configuration or bug related to returning localhost
private URI getURI(String headerValue) {
if (headerValue == null)
return null;
URI toReturn = URI.create(headerValue);
if (!"127.0.0.1".equals(toReturn.getHost()))
return toReturn;
return uriBuilder(toReturn).host(host).build();
}
@Override
public AdaptTempAuthResponseToAccess setContext(HttpRequest request) {
String host = request.getEndpoint().getHost();
this.host = host;
this.username = request.getFirstHeaderOrNull(identityHeaderNameUser);
return this;
}
}
}