Added a set of changes as requested by Adrian

This commit is contained in:
Andrei Savu 2012-01-31 13:12:37 +02:00
parent b6d106c7a1
commit 2b8e2a4c01
6 changed files with 44 additions and 120 deletions

View File

@ -21,16 +21,13 @@ package org.jclouds.cloudstack.features;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import org.jclouds.cloudstack.domain.Account; import org.jclouds.cloudstack.domain.Account;
import org.jclouds.cloudstack.domain.LoginResponse; import org.jclouds.cloudstack.domain.LoginResponse;
import org.jclouds.cloudstack.functions.HashToMD5;
import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.ParamParser;
import org.jclouds.rest.annotations.QueryParams; import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.SelectJson; import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404; import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
import javax.ws.rs.Consumes; import javax.ws.rs.Consumes;
import javax.ws.rs.CookieParam;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam; import javax.ws.rs.HeaderParam;
import javax.ws.rs.QueryParam; import javax.ws.rs.QueryParam;
@ -49,30 +46,18 @@ import javax.ws.rs.core.MediaType;
public interface SessionAsyncClient { public interface SessionAsyncClient {
/** /**
* @see SessionClient#loginWithHashedPassword * @see SessionClient#loginUserInDomainWithHashOfPassword
*/ */
@GET @GET
@QueryParams(keys = "command", values = "login") @QueryParams(keys = "command", values = "login")
@SelectJson("loginresponse") @SelectJson("loginresponse")
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnNullOnNotFoundOr404.class) @ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<LoginResponse> loginWithHashedPassword(@QueryParam("username") String userName, ListenableFuture<LoginResponse> loginUserInDomainWithHashOfPassword(@QueryParam("username") String userName,
@QueryParam("password") String hashedPassword, @QueryParam("domain") String domainOrEmpty); @QueryParam("domain") String domain, @QueryParam("password") String hashedPassword);
/** /**
* @see SessionClient#loginWithPlainTextPassword * @see SessionClient#getAccountByNameUsingSession
*/
@GET
@QueryParams(keys = "command", values = "login")
@SelectJson("loginresponse")
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<LoginResponse> loginWithPlainTextPassword(@QueryParam("username") String userName,
@QueryParam("password") @ParamParser(HashToMD5.class) String plainTextPassword,
@QueryParam("domain") String domainOrEmpty);
/**
* @see SessionClient#getAccountByName
*/ */
@GET @GET
@QueryParams(keys = "comand", values = "listAccounts") @QueryParams(keys = "comand", values = "listAccounts")
@ -80,14 +65,14 @@ public interface SessionAsyncClient {
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnNullOnNotFoundOr404.class) @ExceptionParser(ReturnNullOnNotFoundOr404.class)
@HeaderParam(HttpHeaders.COOKIE) @HeaderParam(HttpHeaders.COOKIE)
ListenableFuture<Account> getAccountByName(@QueryParam("name") String accountName, ListenableFuture<Account> getAccountByNameUsingSession(@QueryParam("name") String accountName,
@CookieParam("sessionKey") @QueryParam("sessionkey") String sessionKey); @QueryParam("sessionkey") String sessionKey);
/** /**
* @see SessionClient#logout * @see SessionClient#logoutUser
*/ */
@GET @GET
@QueryParams(keys = "command", values = "logout") @QueryParams(keys = "command", values = "logout")
@ExceptionParser(ReturnVoidOnNotFoundOr404.class) @ExceptionParser(ReturnVoidOnNotFoundOr404.class)
ListenableFuture<Void> logout(@QueryParam("sessionkey") String sessionKey); ListenableFuture<Void> logoutUser(@QueryParam("sessionkey") String sessionKey);
} }

View File

@ -39,32 +39,18 @@ public interface SessionClient {
* cookie value that can be passed in subsequent Query command calls until the "logout" * cookie value that can be passed in subsequent Query command calls until the "logout"
* command has been issued or the session has expired. * command has been issued or the session has expired.
* *
* @param userName *
* user account name
* @param hashedPassword
* hashed password (by default MD5)
* @param domainOrEmpty
* domain name, if empty defaults to ROOT
* @return
* login response with session key or null
*/
LoginResponse loginWithHashedPassword(String userName, String hashedPassword, String domainOrEmpty);
/**
* Logs a user into Cloudstack. A successful login attempt will generate a session key
* cookie value that can be passed in subsequent Query command calls until the "logout"
* command has been issued or the session has expired.
* *
* @param userName * @param userName
* user account name * user account name
* @param plainTextPassword * @param domain
* plain text password
* @param domainOrEmpty
* domain name, if empty defaults to ROOT * domain name, if empty defaults to ROOT
* @param hashedPassword
* hashed password (by default MD5)
* @return * @return
* login response with session key or null * login response with session key or null
*/ */
LoginResponse loginWithPlainTextPassword(String userName, String plainTextPassword, String domainOrEmpty); LoginResponse loginUserInDomainWithHashOfPassword(String userName, String domain, String hashedPassword);
/** /**
* Retrieve an account by name using the session key for login * Retrieve an account by name using the session key for login
@ -76,7 +62,7 @@ public interface SessionClient {
* @return * @return
* account instance or null * account instance or null
*/ */
Account getAccountByName(String accountName, String sessionKey); Account getAccountByNameUsingSession(String accountName, String sessionKey);
/** /**
* Logs out the user by invalidating the session key * Logs out the user by invalidating the session key
@ -84,6 +70,6 @@ public interface SessionClient {
* @param sessionKey * @param sessionKey
* user session key * user session key
*/ */
Void logout(String sessionKey); void logoutUser(String sessionKey);
} }

View File

@ -1,49 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.cloudstack.functions;
import com.google.common.base.Function;
import com.google.common.io.InputSupplier;
import org.jclouds.crypto.CryptoStreams;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* Hash a string to MD5 (hex representation)
*
* @author Andrei Savu
*/
public class HashToMD5 implements Function<Object, String> {
@Override
public String apply(final Object input) {
try {
return CryptoStreams.md5Hex(new InputSupplier<InputStream>() {
@Override
public InputStream getInput() throws IOException {
return new ByteArrayInputStream(String.class.cast(input).getBytes());
}
});
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -25,7 +25,7 @@ import java.net.URI;
/** /**
* @author Andrei Savu * @author Andrei Savu
*/ */
public class CloudStackUtil { public class ApiKeyPairs {
/** /**
* Retrieve the API key pair for a given CloudStack user * Retrieve the API key pair for a given CloudStack user

View File

@ -25,6 +25,7 @@ import org.jclouds.cloudstack.domain.User;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import static com.google.common.collect.Iterables.find; import static com.google.common.collect.Iterables.find;
import static org.jclouds.crypto.CryptoStreams.md5Hex;
import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNotNull;
import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertEquals;
@ -38,24 +39,14 @@ public class SessionClientLiveTest extends BaseCloudStackClientLiveTest {
private final String USER = "jcloud"; private final String USER = "jcloud";
private final String PLAIN_TEXT_PASSWORD = "jcl0ud"; private final String PLAIN_TEXT_PASSWORD = "jcl0ud";
private final String PASSWORD_MD5_HASH = "30e14b3727225d833aad2206acea1275"; private final String DOMAIN = "Partners/jCloud";
private final String DOMAIN = "/Partners/jCloud";
private LoginResponse loginResponse; private LoginResponse loginResponse;
@Test(enabled = true)
public void testLoginWithPlainTextPassword() throws Exception {
LoginResponse response = client.getSessionClient()
.loginWithPlainTextPassword(USER, PLAIN_TEXT_PASSWORD, DOMAIN);
assertNotNull(response);
assertNotNull(response.getSessionKey());
}
@Test(enabled = true) @Test(enabled = true)
public void testLoginWithHashedPassword() throws Exception { public void testLoginWithHashedPassword() throws Exception {
loginResponse = client.getSessionClient() loginResponse = client.getSessionClient()
.loginWithHashedPassword(USER, PASSWORD_MD5_HASH, DOMAIN); .loginUserInDomainWithHashOfPassword(USER, DOMAIN, md5Hex(PLAIN_TEXT_PASSWORD));
assertNotNull(loginResponse); assertNotNull(loginResponse);
assertNotNull(loginResponse.getSessionKey()); assertNotNull(loginResponse.getSessionKey());
@ -64,7 +55,7 @@ public class SessionClientLiveTest extends BaseCloudStackClientLiveTest {
@Test(dependsOnMethods = "testLoginWithHashedPassword") @Test(dependsOnMethods = "testLoginWithHashedPassword")
public void testRetrieveUserInfoWithSessionKey() throws Exception { public void testRetrieveUserInfoWithSessionKey() throws Exception {
Account account = client.getSessionClient() Account account = client.getSessionClient()
.getAccountByName(loginResponse.getAccountName(), loginResponse.getSessionKey()); .getAccountByNameUsingSession(loginResponse.getAccountName(), loginResponse.getSessionKey());
assertNotNull(account); assertNotNull(account);
assertEquals(account.getName(), loginResponse.getAccountName()); assertEquals(account.getName(), loginResponse.getAccountName());
@ -82,6 +73,6 @@ public class SessionClientLiveTest extends BaseCloudStackClientLiveTest {
@Test(dependsOnMethods = "testRetrieveUserInfoWithSessionKey") @Test(dependsOnMethods = "testRetrieveUserInfoWithSessionKey")
public void testLogout() throws Exception { public void testLogout() throws Exception {
client.getSessionClient().logout(loginResponse.getSessionKey()); client.getSessionClient().logoutUser(loginResponse.getSessionKey());
} }
} }

View File

@ -18,8 +18,17 @@
*/ */
package org.jclouds.crypto; package org.jclouds.crypto;
import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.annotations.Beta;
import com.google.common.base.Charsets;
import com.google.common.base.Throwables;
import com.google.common.io.ByteProcessor;
import com.google.common.io.ByteStreams;
import com.google.common.io.InputSupplier;
import org.jclouds.encryption.internal.Base64;
import org.jclouds.io.InputSuppliers;
import javax.crypto.Mac;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -28,17 +37,7 @@ import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.Arrays; import java.util.Arrays;
import javax.crypto.Mac; import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.encryption.internal.Base64;
import org.jclouds.io.InputSuppliers;
import com.google.common.annotations.Beta;
import com.google.common.base.Charsets;
import com.google.common.base.Throwables;
import com.google.common.io.ByteProcessor;
import com.google.common.io.ByteStreams;
import com.google.common.io.InputSupplier;
/** /**
* functions related to but not in {@link com.google.common.io.ByteStreams} * functions related to but not in {@link com.google.common.io.ByteStreams}
@ -89,6 +88,18 @@ public class CryptoStreams {
return hex(md5(supplier)); return hex(md5(supplier));
} }
/**
* @see #md5Hex
*/
public static String md5Hex(final String in) throws IOException {
return md5Hex(new InputSupplier<InputStream>() {
@Override
public InputStream getInput() throws IOException {
return new ByteArrayInputStream(in.getBytes());
}
});
}
/** /**
* @see #md5 * @see #md5
* @see #base64 * @see #base64