/*
* Copyright 2015 Bounce Storage, Inc. <info@bouncestorage.com>
*
* Licensed 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 com.bouncestorage.swiftproxy.v2;
import static java.util.Objects.requireNonNull;
import static com.google.common.base.Throwables.propagate;
import java.net.MalformedURLException;
import java.net.URL;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import com.bouncestorage.swiftproxy.BlobStoreResource;
import com.bouncestorage.swiftproxy.BounceResourceConfig;
import com.bouncestorage.swiftproxy.v1.InfoResource;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.google.common.base.Strings;
import org.glassfish.grizzly.http.server.Request;
@Path("/v2.0")
public final class Identity extends BlobStoreResource {
@Path("tokens")
@POST
@Produces(MediaType.APPLICATION_JSON)
public Response auth(AuthV2Request payload,
@HeaderParam("Host") Optional<String> host,
@Context Request request) {
String tenant = payload.auth.tenantName;
String identity = payload.auth.passwordCredentials.username;
if (Strings.isNullOrEmpty(tenant)) {
tenant = identity;
}
String credential = payload.auth.passwordCredentials.password;
String authToken = null;
try {
authToken = ((BounceResourceConfig) application).authenticate(tenant + ":" + identity, credential);
} catch (Throwable e) {
e.printStackTrace();
}
if (authToken == null) {
return notAuthorized();
}
String storageURL = host.orElseGet(() -> request.getLocalAddr() + ":" + request.getLocalPort());
String scheme = request.getScheme();
tenant = "AUTH_" + tenant;
storageURL = scheme + "://" + storageURL + "/v1/" + tenant;
AuthV2Response resp = new AuthV2Response();
resp.access.token.id = authToken;
resp.access.token.expires = Instant.now().plusSeconds(InfoResource.CONFIG.tempauth.token_life);
resp.access.token.tenant = new IDAndName(tenant, tenant);
resp.access.user = new AuthV2Response.Access.User(identity, identity);
resp.access.user.roles.add(new IDAndName(identity, identity));
if (!identity.equals(tenant)) {
resp.access.user.roles.add(new IDAndName(tenant, tenant));
}
AuthV2Response.Access.ServiceCatalog.Endpoint endpoint = new AuthV2Response.Access.ServiceCatalog.Endpoint();
try {
endpoint.publicURL = new URL(storageURL);
} catch (MalformedURLException e) {
e.printStackTrace();
throw propagate(e);
}
endpoint.tenantId = tenant;
resp.access.serviceCatalog[0].endpoints.add(endpoint);
org.jclouds.Context c = getBlobStore(authToken).get().getContext().unwrap();
resp.access.serviceCatalog[0].name += String.format(" (%s %s)",
c.getId(), c.getProviderMetadata().getEndpoint());
return Response.ok(resp).build();
}
static class AuthV2Request {
@JsonProperty
Auth auth = new Auth();
static class Auth {
@JsonProperty
PasswordCredentials passwordCredentials = new PasswordCredentials();
@JsonProperty
String tenantName;
static class PasswordCredentials {
@JsonProperty
String username;
@JsonProperty
String password;
}
}
}
static class IDAndName {
@JsonProperty
String id;
@JsonProperty
String name;
IDAndName(String id, String name) {
this.id = requireNonNull(id);
this.name = requireNonNull(name);
}
}
static class AuthV2Response {
@JsonProperty
Access access = new Access();
static class Access {
@JsonProperty
Token token = new Token();
@JsonProperty
User user;
@JsonProperty
ServiceCatalog[] serviceCatalog = {new ServiceCatalog()};
static class Token {
@JsonProperty
String id;
@JsonSerialize(using = ToStringSerializer.class)
Instant expires;
@JsonProperty
IDAndName tenant;
}
static class User extends IDAndName {
@JsonProperty
List<IDAndName> roles = new ArrayList<>();
User(String id, String name) {
super(id, name);
}
}
static class ServiceCatalog {
@JsonProperty
List<Endpoint> endpoints = new ArrayList<>();
@JsonProperty
String name = "Swift Object Storage";
@JsonProperty
String type = "object-store";
static class Endpoint {
@JsonProperty
String region = "default";
@JsonProperty
URL publicURL;
@JsonProperty
String versionId = "1";
@JsonProperty
String tenantId;
}
}
}
}
}