package io.fathom.cloud.openstack.client.identity; import io.fathom.cloud.openstack.client.OpenstackServiceClientBase; import io.fathom.cloud.openstack.client.RestClientException; import io.fathom.cloud.openstack.client.identity.model.ClientApp; import io.fathom.cloud.openstack.client.identity.model.RegisterRequest; import io.fathom.cloud.openstack.client.identity.model.RegisterResponse; import io.fathom.cloud.openstack.client.identity.model.Token; import io.fathom.cloud.openstack.client.identity.model.V2AuthRequest; import io.fathom.cloud.openstack.client.identity.model.V2AuthResponse; import io.fathom.cloud.openstack.client.identity.model.V2ProjectList; import io.fathom.cloud.openstack.client.identity.model.V3Project; import io.fathom.cloud.openstack.client.identity.model.WrappedV3Project; import io.fathom.http.HttpClient; import io.fathom.http.HttpMethod; import io.fathom.http.HttpRequest; import io.fathom.http.SslConfiguration; import io.fathom.http.jre.JreHttpClient; import java.io.IOException; import java.net.URI; import javax.inject.Singleton; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fathomdb.crypto.CertificateAndKey; import com.fathomdb.crypto.SimpleClientCertificateKeyManager; import com.google.common.io.ByteSource; // If we're injected, we should be a singleton @Singleton public class OpenstackIdentityClient extends OpenstackServiceClientBase { private static final Logger log = LoggerFactory.getLogger(OpenstackIdentityClient.class); public static final String SERVICE_TYPE = "identity"; public OpenstackIdentityClient(HttpClient httpClient, URI uri, TokenProvider tokenProvider) { super(httpClient, uri, tokenProvider); } // @Inject // public OpenstackIdentityClient(HttpClient httpClient, Configuration // config) { // super(httpClient, URI.create(config.get("identity.url"))); // } public V2AuthResponse doLogin(V2AuthRequest request) throws RestClientException { return doPost("v2.0/tokens", request, V2AuthResponse.class); } public V2AuthResponse doLogin(V2AuthRequest authRequest, CertificateAndKey certificateAndKey) throws RestClientException { URI uri = resolve("v2.0/tokens"); HttpClient httpClient = getHttpClient(certificateAndKey); HttpRequest httpRequest = httpClient.buildRequest(HttpMethod.POST, uri); addHeaders(httpRequest); addHeaders(httpRequest, certificateAndKey); setEntityJson(httpRequest, authRequest); return doJsonRequest(httpRequest, V2AuthResponse.class); } private void addHeaders(HttpRequest httpRequest, CertificateAndKey certificateAndKey) { // Until haproxy can pass through the key, we'll need this hack // String keysig = // OpenSshUtils.getSignatureString(certificateAndKey.getPublicKey()).toUpperCase(); // httpRequest.setHeader("X-SSL-Client-Key-SHA1", keysig); // byte[] pubkey = certificateAndKey.getPublicKey().getEncoded(); // httpRequest.setHeader("X-SSL-Client-Key", // BaseEncoding.base16().encode(pubkey).toUpperCase()); } public RegisterResponse register(RegisterRequest request, CertificateAndKey certificateAndKey) throws RestClientException { URI uri = resolve("extensions/register"); HttpClient httpClient = getHttpClient(certificateAndKey); HttpRequest httpRequest = httpClient.buildRequest(HttpMethod.POST, uri); addHeaders(httpRequest); addHeaders(httpRequest, certificateAndKey); setEntityJson(httpRequest, request); return doJsonRequest(httpRequest, RegisterResponse.class); } private HttpClient getHttpClient(CertificateAndKey certificateAndKey) { SimpleClientCertificateKeyManager keyManager = new SimpleClientCertificateKeyManager(certificateAndKey); SslConfiguration sslConfiguration = getHttpClient().getSslConfiguration().copyWithNewKeyManager(keyManager); HttpClient httpClient = getHttpClient().withSsl(sslConfiguration); return httpClient; } public Token validateToken(String token) throws RestClientException { HttpRequest request = buildGet("v3/auth/tokens"); request.setHeader("X-Auth-Token", token); request.setHeader("X-Subject-Token", token); return doRequest(request, Token.class); } public ClientApp getClientApp(ClientApp app) throws RestClientException { return doPost("extensions/client", app, ClientApp.class); } public byte[] getClientData(String secret, String token, String appId, String userId) throws RestClientException { HttpRequest request = buildGet("extensions/attachment/user/" + urlEscape(userId) + "/" + urlEscape(appId) + "?secret=" + urlEscape(secret)); request.setHeader("X-Auth-Token", token); return doByteArrayRequest(request); } public void setClientData(String secret, String token, String appId, String userId, byte[] data) throws RestClientException { HttpRequest request = buildPut("extensions/attachment/user/" + urlEscape(userId) + "/" + urlEscape(appId) + "?secret=" + urlEscape(secret)); request.setHeader("X-Auth-Token", token); try { request.setRequestContent(ByteSource.wrap(data)); } catch (IOException e) { throw new RestClientException("Error setting request content", e); } doStringRequest(request); } public static OpenstackIdentityClient build(URI uri) { return new OpenstackIdentityClient(JreHttpClient.create(), uri, null); } public V2ProjectList listProjects() throws RestClientException { HttpRequest request = buildGet("v2.0/tenants"); return doRequest(request, V2ProjectList.class); } public OpenstackIdentityClient withTokenProvider(TokenProvider tokenProvider) { return new OpenstackIdentityClient(getHttpClient(), getBaseUri(), tokenProvider); } public V3Project createProject(V3Project project) throws RestClientException { WrappedV3Project request = new WrappedV3Project(); request.project = project; WrappedV3Project response = doPost("v3/projects", request, WrappedV3Project.class); return response.project; } public Identity getUtils() { return new Identity(this); } }