forked from javaswift/joss
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
javaswift#133 Enable support for keystone v3 authentication
- Loading branch information
Kevin Conaway
committed
Oct 10, 2017
1 parent
290dcd9
commit dc47b18
Showing
21 changed files
with
650 additions
and
52 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,7 @@ | |
public enum AuthenticationMethod { | ||
BASIC, | ||
KEYSTONE, | ||
KEYSTONE_V3, | ||
TEMPAUTH, | ||
EXTERNAL; | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
29 changes: 19 additions & 10 deletions
29
src/main/java/org/javaswift/joss/command/impl/factory/AuthenticationCommandFactoryImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
79 changes: 79 additions & 0 deletions
79
...in/java/org/javaswift/joss/command/impl/identity/KeystoneAuthenticationV3CommandImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
package org.javaswift.joss.command.impl.identity; | ||
|
||
import org.apache.http.HttpResponse; | ||
import org.apache.http.client.HttpClient; | ||
import org.apache.http.client.methods.HttpPost; | ||
import org.apache.http.entity.ContentType; | ||
import org.apache.http.entity.StringEntity; | ||
import org.codehaus.jackson.JsonNode; | ||
import org.codehaus.jackson.map.ObjectMapper; | ||
import org.javaswift.joss.client.factory.AccountConfig; | ||
import org.javaswift.joss.command.impl.core.AbstractCommand; | ||
import org.javaswift.joss.command.impl.core.httpstatus.HttpStatusChecker; | ||
import org.javaswift.joss.command.impl.core.httpstatus.HttpStatusRange; | ||
import org.javaswift.joss.command.impl.core.httpstatus.HttpStatusSuccessCondition; | ||
import org.javaswift.joss.command.shared.identity.AuthenticationCommand; | ||
import org.javaswift.joss.command.shared.identity.access.KeystoneV3Access; | ||
import org.javaswift.joss.command.shared.identity.authentication.KeystoneV3Authentication; | ||
import org.javaswift.joss.exception.CommandException; | ||
import org.javaswift.joss.headers.Accept; | ||
import org.javaswift.joss.model.Access; | ||
|
||
import java.io.IOException; | ||
|
||
public class KeystoneAuthenticationV3CommandImpl extends AbstractCommand<HttpPost, Access> implements AuthenticationCommand { | ||
|
||
private final String url; | ||
private final ObjectMapper requestMapper; | ||
private final ObjectMapper responseMapper; | ||
|
||
public KeystoneAuthenticationV3CommandImpl(HttpClient httpClient, AccountConfig config) { | ||
super(httpClient, config.getAuthUrl()); | ||
|
||
this.url = config.getAuthUrl(); | ||
this.requestMapper = createObjectMapper(true); | ||
this.responseMapper = createObjectMapper(false); | ||
|
||
setHeader(new Accept(ContentType.APPLICATION_JSON.getMimeType())); | ||
setRequestBody(config.getUsername(), config.getPassword(), config.getDomain()); | ||
} | ||
|
||
private void setRequestBody(String username, String password, String domain) { | ||
try { | ||
String jsonString = requestMapper.writeValueAsString( | ||
new KeystoneV3Authentication(username, password, domain) | ||
); | ||
request.setEntity( | ||
new StringEntity(jsonString, ContentType.APPLICATION_JSON) | ||
); | ||
} catch (IOException ex) { | ||
throw new CommandException("Unable to set the JSON body on the request", ex); | ||
} | ||
} | ||
|
||
@Override | ||
public Access getReturnObject(HttpResponse response) throws IOException { | ||
String tokenValue = response.getFirstHeader("X-Subject-Token").getValue(); | ||
|
||
JsonNode responseBody = responseMapper.readTree(response.getEntity().getContent()); | ||
|
||
return new KeystoneV3Access(tokenValue, responseBody); | ||
} | ||
|
||
@Override | ||
protected HttpPost createRequest(String url) { | ||
return new HttpPost(url); | ||
} | ||
|
||
@Override | ||
public HttpStatusChecker[] getStatusCheckers() { | ||
return new HttpStatusChecker[] { | ||
new HttpStatusSuccessCondition(new HttpStatusRange(200, 299)) | ||
}; | ||
} | ||
|
||
@Override | ||
public String getUrl() { | ||
return this.url; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 2 additions & 4 deletions
6
src/main/java/org/javaswift/joss/command/shared/factory/AuthenticationCommandFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,11 @@ | ||
package org.javaswift.joss.command.shared.factory; | ||
|
||
import org.apache.http.client.HttpClient; | ||
import org.javaswift.joss.client.factory.AuthenticationMethod; | ||
import org.javaswift.joss.client.factory.AccountConfig; | ||
import org.javaswift.joss.command.shared.identity.AuthenticationCommand; | ||
|
||
public interface AuthenticationCommandFactory { | ||
|
||
AuthenticationCommand createAuthenticationCommand(HttpClient httpClient, AuthenticationMethod authenticationMethod, | ||
String url, String tenantName, String tenantId, | ||
String username, String password, AuthenticationMethod.AccessProvider accessProvier); | ||
AuthenticationCommand createAuthenticationCommand(HttpClient httpClient, AccountConfig accountConfig); | ||
|
||
} |
117 changes: 117 additions & 0 deletions
117
src/main/java/org/javaswift/joss/command/shared/identity/access/KeystoneV3Access.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
package org.javaswift.joss.command.shared.identity.access; | ||
|
||
import org.codehaus.jackson.JsonNode; | ||
import org.javaswift.joss.client.factory.TempUrlHashPrefixSource; | ||
import org.javaswift.joss.model.Access; | ||
|
||
import java.util.Collection; | ||
import java.util.LinkedHashMap; | ||
import java.util.Map; | ||
|
||
public class KeystoneV3Access implements Access { | ||
|
||
private final String token; | ||
private final Collection<EndPoint> endPoints; | ||
|
||
private EndPoint currentEndpoint; | ||
|
||
public KeystoneV3Access(String token, JsonNode response) { | ||
this.token = token; | ||
this.endPoints = getEndPoints(response); | ||
this.currentEndpoint = getEndPoint(null); | ||
} | ||
|
||
@Override | ||
public void setPreferredRegion(String preferredRegion) { | ||
this.currentEndpoint = getEndPoint(preferredRegion); | ||
} | ||
|
||
@Override | ||
public String getToken() { | ||
return token; | ||
} | ||
|
||
@Override | ||
public String getInternalURL() { | ||
return currentEndpoint.internalURL; | ||
} | ||
|
||
@Override | ||
public String getPublicURL() { | ||
return currentEndpoint.publicURL; | ||
} | ||
|
||
/** | ||
* @return Always true, v3 doesn't use the tenant ID for auth | ||
*/ | ||
@Override | ||
public boolean isTenantSupplied() { | ||
return true; | ||
} | ||
|
||
@Override | ||
public String getTempUrlPrefix(TempUrlHashPrefixSource tempUrlHashPrefixSource) { | ||
final String tempUrlPrefix; | ||
if (tempUrlHashPrefixSource == null) { | ||
tempUrlPrefix = ""; | ||
} else if (tempUrlHashPrefixSource == TempUrlHashPrefixSource.PUBLIC_URL_PATH) { | ||
tempUrlPrefix = TempUrlHashPrefixSource.getPath(currentEndpoint.publicURL); | ||
} else if (tempUrlHashPrefixSource == TempUrlHashPrefixSource.INTERNAL_URL_PATH) { | ||
tempUrlPrefix = TempUrlHashPrefixSource.getPath(currentEndpoint.internalURL); | ||
} else { | ||
tempUrlPrefix = TempUrlHashPrefixSource.getPath(currentEndpoint.adminURL); | ||
} | ||
return tempUrlPrefix.endsWith("/") ? tempUrlPrefix.substring(0, tempUrlPrefix.length()-1) : tempUrlPrefix; | ||
} | ||
|
||
private EndPoint getEndPoint(String region) { | ||
if (endPoints.isEmpty()) { | ||
throw new IllegalStateException("No endpoints available"); | ||
} | ||
|
||
if (region == null) { | ||
return endPoints.iterator().next(); | ||
} | ||
|
||
for (EndPoint endPoint : endPoints) { | ||
if (region.equals(endPoint.region)) { | ||
return endPoint; | ||
} | ||
} | ||
|
||
throw new IllegalArgumentException("No endpoint for region: " + region); | ||
} | ||
|
||
private Collection<EndPoint> getEndPoints(JsonNode response) { | ||
Map<String, EndPoint> result = new LinkedHashMap<String, EndPoint>(); | ||
|
||
JsonNode token = response.get("token"); | ||
for (JsonNode catalog : token.get("catalog")) { | ||
if ("object-store".equals(catalog.get("type").asText())) { | ||
for (JsonNode endpointNode : catalog.get("endpoints")) { | ||
String interfaceType = endpointNode.get("interface").asText(); | ||
String url = endpointNode.get("url").asText(); | ||
String region = endpointNode.get("region").asText();; | ||
|
||
EndPoint endPoint = result.get(region); | ||
|
||
if (endPoint == null) { | ||
endPoint = new EndPoint(); | ||
endPoint.region = region; | ||
result.put(region, endPoint); | ||
} | ||
|
||
if ("public".equals(interfaceType)) { | ||
endPoint.publicURL = url; | ||
} else if ("admin".equals(interfaceType)) { | ||
endPoint.adminURL = url; | ||
} else if ("internal".equals(interfaceType)) { | ||
endPoint.internalURL = url; | ||
} | ||
} | ||
} | ||
} | ||
|
||
return result.values(); | ||
} | ||
} |
Oops, something went wrong.