mirror of https://github.com/apache/cloudstack.git
cloudian: refactor code around SSO and url handling
Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
This commit is contained in:
parent
7bc74bc442
commit
bc0bb89e97
|
|
@ -52,6 +52,7 @@ import com.cloud.utils.nio.TrustAllManager;
|
|||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
public class CloudianClient {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(CloudianClient.class);
|
||||
|
||||
private final HttpClient httpClient;
|
||||
|
|
@ -120,7 +121,7 @@ public class CloudianClient {
|
|||
//////////////// Public APIs: User /////////////////////
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
public boolean addUser(final UserInfo user) {
|
||||
public boolean addUser(final CloudianUser user) {
|
||||
try {
|
||||
final HttpResponse response = put("/user", user);
|
||||
return response.getStatusLine().getStatusCode() == HttpStatus.SC_OK;
|
||||
|
|
@ -130,35 +131,35 @@ public class CloudianClient {
|
|||
return false;
|
||||
}
|
||||
|
||||
public UserInfo listUser(final String userId, final String groupId) {
|
||||
public CloudianUser listUser(final String userId, final String groupId) {
|
||||
try {
|
||||
final HttpResponse response = get(String.format("/user?userId=%s&groupId=%s", userId, groupId));
|
||||
final ObjectMapper mapper = new ObjectMapper();
|
||||
if (response.getEntity() == null || response.getEntity().getContent() == null) {
|
||||
return null;
|
||||
}
|
||||
return mapper.readValue(response.getEntity().getContent(), UserInfo.class);
|
||||
return mapper.readValue(response.getEntity().getContent(), CloudianUser.class);
|
||||
} catch (final IOException e) {
|
||||
LOG.error("Failed to list Cloudian user due to:", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<UserInfo> listUsers(final String groupId) {
|
||||
public List<CloudianUser> listUsers(final String groupId) {
|
||||
try {
|
||||
final HttpResponse response = get(String.format("/user/list?groupId=%s&userType=all&userStatus=active", groupId));
|
||||
final ObjectMapper mapper = new ObjectMapper();
|
||||
if (response.getEntity() == null || response.getEntity().getContent() == null) {
|
||||
return null;
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return Arrays.asList(mapper.readValue(response.getEntity().getContent(), UserInfo[].class));
|
||||
return Arrays.asList(mapper.readValue(response.getEntity().getContent(), CloudianUser[].class));
|
||||
} catch (final IOException e) {
|
||||
LOG.error("Failed to list Cloudian users due to:", e);
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public boolean updateUser(final UserInfo user) {
|
||||
public boolean updateUser(final CloudianUser user) {
|
||||
try {
|
||||
final HttpResponse response = post("/user", user);
|
||||
return response.getStatusLine().getStatusCode() == HttpStatus.SC_OK;
|
||||
|
|
@ -182,7 +183,7 @@ public class CloudianClient {
|
|||
//////////////// Public APIs: Group /////////////////////
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
public boolean addGroup(final GroupInfo group) {
|
||||
public boolean addGroup(final CloudianGroup group) {
|
||||
try {
|
||||
final HttpResponse response = put("/group", group);
|
||||
return response.getStatusLine().getStatusCode() == HttpStatus.SC_OK;
|
||||
|
|
@ -192,35 +193,35 @@ public class CloudianClient {
|
|||
return false;
|
||||
}
|
||||
|
||||
public GroupInfo listGroup(final String groupId) {
|
||||
public CloudianGroup listGroup(final String groupId) {
|
||||
try {
|
||||
final HttpResponse response = get(String.format("/group?groupId=%s", groupId));
|
||||
final ObjectMapper mapper = new ObjectMapper();
|
||||
if (response.getEntity() == null || response.getEntity().getContent() == null) {
|
||||
return null;
|
||||
}
|
||||
return mapper.readValue(response.getEntity().getContent(), GroupInfo.class);
|
||||
return mapper.readValue(response.getEntity().getContent(), CloudianGroup.class);
|
||||
} catch (final IOException e) {
|
||||
LOG.error("Failed to list Cloudian group due to:", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<GroupInfo> listGroups() {
|
||||
public List<CloudianGroup> listGroups() {
|
||||
try {
|
||||
final HttpResponse response = get("/group/list");
|
||||
final ObjectMapper mapper = new ObjectMapper();
|
||||
if (response.getEntity() == null || response.getEntity().getContent() == null) {
|
||||
return null;
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return Arrays.asList(mapper.readValue(response.getEntity().getContent(), GroupInfo[].class));
|
||||
return Arrays.asList(mapper.readValue(response.getEntity().getContent(), CloudianGroup[].class));
|
||||
} catch (final IOException e) {
|
||||
LOG.error("Failed to list Cloudian groups due to:", e);
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public boolean updateGroup(final GroupInfo group) {
|
||||
public boolean updateGroup(final CloudianGroup group) {
|
||||
try {
|
||||
final HttpResponse response = post("/group", group);
|
||||
return response.getStatusLine().getStatusCode() == HttpStatus.SC_OK;
|
||||
|
|
|
|||
|
|
@ -20,11 +20,17 @@ package com.cloudian.client;
|
|||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class GroupInfo {
|
||||
public class CloudianGroup {
|
||||
|
||||
String groupId;
|
||||
String groupName;
|
||||
Boolean active;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("Cloudian Group [id=%s, name=%s, active=%s]", groupId, groupName, active);
|
||||
}
|
||||
|
||||
public String getGroupId() {
|
||||
return groupId;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,8 @@ package com.cloudian.client;
|
|||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class UserInfo {
|
||||
public class CloudianUser {
|
||||
|
||||
public static final String USER = "User";
|
||||
|
||||
String userId;
|
||||
|
|
@ -32,7 +33,7 @@ public class UserInfo {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("User [id=%s, group id=%s, type=%s, active=%s, name=%s]", userId, groupId, userType, active, fullName);
|
||||
return String.format("Cloudian User [id=%s, group id=%s, type=%s, active=%s, name=%s]", userId, groupId, userType, active, fullName);
|
||||
}
|
||||
|
||||
public String getUserId() {
|
||||
|
|
|
|||
|
|
@ -59,6 +59,18 @@ public interface CloudianConnector extends PluggableService {
|
|||
ConfigKey<String> CloudianSsoKey = new ConfigKey<>("Advanced", String.class, "cloudian.sso.key", "ss0sh5r3dk3y",
|
||||
"The shared single sign-on key as configured in Cloudian CMC.", true);
|
||||
|
||||
String getAdminUrl();
|
||||
String getCmcUrl();
|
||||
|
||||
/**
|
||||
* Checks if the Cloudian Connector is disabled
|
||||
* @return returns true is connector is disabled
|
||||
*/
|
||||
boolean isConnectorDisabled();
|
||||
|
||||
/**
|
||||
* Generates single-sign on URL for logged in user
|
||||
* @return returns the SSO URL string
|
||||
*/
|
||||
String generateSsoUrl();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,8 +47,8 @@ import com.cloud.user.dao.UserDao;
|
|||
import com.cloud.utils.component.ComponentLifecycleBase;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloudian.client.CloudianClient;
|
||||
import com.cloudian.client.GroupInfo;
|
||||
import com.cloudian.client.UserInfo;
|
||||
import com.cloudian.client.CloudianGroup;
|
||||
import com.cloudian.client.CloudianUser;
|
||||
import com.cloudian.cloudstack.api.CloudianIsEnabledCmd;
|
||||
import com.cloudian.cloudstack.api.CloudianSsoLoginCmd;
|
||||
|
||||
|
|
@ -71,16 +71,6 @@ public class CloudianConnectorImpl extends ComponentLifecycleBase implements Clo
|
|||
//////////////// Plugin Methods /////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
private String getAdminUrl() {
|
||||
return String.format("%s://%s:%s", CloudianAdminProtocol.value(),
|
||||
CloudianAdminHost.value(), CloudianAdminPort.value());
|
||||
}
|
||||
|
||||
private String getCmcUrl() {
|
||||
return String.format("%s://%s:%s/Cloudian/ssosecurelogin.htm?", CloudianCmcProtocol.value(),
|
||||
CloudianCmcHost.value(), CloudianCmcPort.value());
|
||||
}
|
||||
|
||||
private CloudianClient getClient() {
|
||||
try {
|
||||
return new CloudianClient(getAdminUrl(),
|
||||
|
|
@ -97,7 +87,7 @@ public class CloudianConnectorImpl extends ComponentLifecycleBase implements Clo
|
|||
return false;
|
||||
}
|
||||
final CloudianClient client = getClient();
|
||||
final GroupInfo existingGroup = client.listGroup(domain.getUuid());
|
||||
final CloudianGroup existingGroup = client.listGroup(domain.getUuid());
|
||||
if (existingGroup != null) {
|
||||
if (!existingGroup.getActive() || !existingGroup.getGroupName().equals(domain.getPath())) {
|
||||
LOG.debug("Updating Cloudian group for domain uuid=" + domain.getUuid() + " name=" + domain.getName() + " path=" + domain.getPath());
|
||||
|
|
@ -109,7 +99,7 @@ public class CloudianConnectorImpl extends ComponentLifecycleBase implements Clo
|
|||
}
|
||||
|
||||
LOG.debug("Adding Cloudian group for domain uuid=" + domain.getUuid() + " name=" + domain.getName() + " path=" + domain.getPath());
|
||||
final GroupInfo group = new GroupInfo();
|
||||
final CloudianGroup group = new CloudianGroup();
|
||||
group.setGroupId(domain.getUuid());
|
||||
group.setGroupName(domain.getPath());
|
||||
group.setActive(true);
|
||||
|
|
@ -122,7 +112,7 @@ public class CloudianConnectorImpl extends ComponentLifecycleBase implements Clo
|
|||
}
|
||||
final CloudianClient client = getClient();
|
||||
LOG.debug("Removing Cloudian group for domain uuid=" + domain.getUuid() + " name=" + domain.getName() + " path=" + domain.getPath());
|
||||
for (final UserInfo user: client.listUsers(domain.getUuid())) {
|
||||
for (final CloudianUser user: client.listUsers(domain.getUuid())) {
|
||||
if (client.removeUser(user.getUserId(), domain.getUuid())) {
|
||||
LOG.error(String.format("Failed to remove Cloudian user id=%s, while removing Cloudian group id=%s", user.getUserId(), domain.getUuid()));
|
||||
}
|
||||
|
|
@ -137,7 +127,7 @@ public class CloudianConnectorImpl extends ComponentLifecycleBase implements Clo
|
|||
final User accountUser = userDao.listByAccount(account.getId()).get(0);
|
||||
final String fullName = String.format("%s %s (%s)", accountUser.getFirstname(), accountUser.getLastname(), account.getAccountName());
|
||||
final CloudianClient client = getClient();
|
||||
final UserInfo existingUser = client.listUser(account.getUuid(), domain.getUuid());
|
||||
final CloudianUser existingUser = client.listUser(account.getUuid(), domain.getUuid());
|
||||
if (existingUser != null) {
|
||||
if (!existingUser.getActive() || !existingUser.getFullName().equals(fullName)) {
|
||||
LOG.debug("Updating Cloudian user for account with uuid=" + account.getUuid() + " name=" + account.getAccountName());
|
||||
|
|
@ -150,12 +140,12 @@ public class CloudianConnectorImpl extends ComponentLifecycleBase implements Clo
|
|||
}
|
||||
|
||||
LOG.debug("Adding Cloudian user for account with uuid=" + account.getUuid() + " name=" + account.getAccountName());
|
||||
final UserInfo user = new UserInfo();
|
||||
final CloudianUser user = new CloudianUser();
|
||||
user.setUserId(account.getUuid());
|
||||
user.setGroupId(domain.getUuid());
|
||||
user.setFullName(fullName);
|
||||
user.setEmailAddr(accountUser.getEmail());
|
||||
user.setUserType(UserInfo.USER);
|
||||
user.setUserType(CloudianUser.USER);
|
||||
user.setActive(true);
|
||||
return client.addUser(user);
|
||||
}
|
||||
|
|
@ -174,6 +164,18 @@ public class CloudianConnectorImpl extends ComponentLifecycleBase implements Clo
|
|||
//////////////// Plugin APIs /////////////////////
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public String getAdminUrl() {
|
||||
return String.format("%s://%s:%s", CloudianAdminProtocol.value(),
|
||||
CloudianAdminHost.value(), CloudianAdminPort.value());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCmcUrl() {
|
||||
return String.format("%s://%s:%s/Cloudian/", CloudianCmcProtocol.value(),
|
||||
CloudianCmcHost.value(), CloudianCmcPort.value());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnectorDisabled() {
|
||||
return !CloudianConnectorEnabled.value();
|
||||
|
|
@ -195,12 +197,7 @@ public class CloudianConnectorImpl extends ComponentLifecycleBase implements Clo
|
|||
addOrUpdateUserAccount(caller, domain);
|
||||
}
|
||||
|
||||
final String ssoParams = CloudianUtils.generateSSOUrlParams(user, group, CloudianSsoKey.value());
|
||||
if (ssoParams == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return getCmcUrl() + ssoParams;
|
||||
return CloudianUtils.generateSSOUrl(getCmcUrl(), user, group, CloudianSsoKey.value());
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ public class CloudianUtils {
|
|||
* @param ssoKey
|
||||
* @return returns SSO URL parameters or null on error
|
||||
*/
|
||||
public static String generateSSOUrlParams(final String user, final String group, final String ssoKey) {
|
||||
public static String generateSSOUrl(final String cmcUrlPath, final String user, final String group, final String ssoKey) {
|
||||
final StringBuilder stringBuilder = new StringBuilder();
|
||||
stringBuilder.append("user=").append(user);
|
||||
stringBuilder.append("&group=").append(group);
|
||||
|
|
@ -87,6 +87,6 @@ public class CloudianUtils {
|
|||
stringBuilder.append("explorer.htm");
|
||||
}
|
||||
|
||||
return stringBuilder.toString();
|
||||
return cmcUrlPath + "ssosecurelogin.htm?" + stringBuilder.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,13 +22,13 @@ import javax.inject.Inject;
|
|||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.response.SuccessResponse;
|
||||
|
||||
import com.cloud.user.Account;
|
||||
import com.cloudian.cloudstack.CloudianConnector;
|
||||
import com.cloudian.cloudstack.response.CloudianEnabledResponse;
|
||||
|
||||
@APICommand(name = CloudianIsEnabledCmd.APINAME, description = "Checks if the Cloudian Connector is enabled",
|
||||
responseObject = SuccessResponse.class,
|
||||
responseObject = CloudianEnabledResponse.class,
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
|
||||
since = "4.11.0",
|
||||
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
|
||||
|
|
@ -55,9 +55,10 @@ public class CloudianIsEnabledCmd extends BaseCmd {
|
|||
|
||||
@Override
|
||||
public void execute() {
|
||||
final boolean isEnabled = !connector.isConnectorDisabled();
|
||||
final SuccessResponse response = new SuccessResponse();
|
||||
response.setSuccess(isEnabled);
|
||||
final CloudianEnabledResponse response = new CloudianEnabledResponse();
|
||||
response.setEnabled(!connector.isConnectorDisabled());
|
||||
response.setCmcUrl(connector.getCmcUrl());
|
||||
response.setObjectName(APINAME.toLowerCase());
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,5 +17,34 @@
|
|||
|
||||
package com.cloudian.cloudstack.response;
|
||||
|
||||
public class CloudianEnabledResponse {
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseResponse;
|
||||
|
||||
import com.cloud.serializer.Param;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class CloudianEnabledResponse extends BaseResponse {
|
||||
@SerializedName(ApiConstants.ENABLED)
|
||||
@Param(description = "the Cloudian connector enabled state")
|
||||
private Boolean enabled;
|
||||
|
||||
@SerializedName(ApiConstants.URL)
|
||||
@Param(description = "the Cloudian Management Console base URL")
|
||||
private String cmcUrl;
|
||||
|
||||
public Boolean getEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(Boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public String getCmcUrl() {
|
||||
return cmcUrl;
|
||||
}
|
||||
|
||||
public void setCmcUrl(String cmcUrl) {
|
||||
this.cmcUrl = cmcUrl;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ import org.junit.Before;
|
|||
import org.junit.Test;
|
||||
|
||||
import com.cloudian.client.CloudianClient;
|
||||
import com.cloudian.client.GroupInfo;
|
||||
import com.cloudian.client.UserInfo;
|
||||
import com.cloudian.client.CloudianGroup;
|
||||
import com.cloudian.client.CloudianUser;
|
||||
|
||||
public class CloudianClientTest {
|
||||
|
||||
|
|
@ -29,7 +29,7 @@ public class CloudianClientTest {
|
|||
|
||||
@Test
|
||||
public void listUserAccount() throws Exception {
|
||||
List<UserInfo> users = client.listUsers("0");
|
||||
List<CloudianUser> users = client.listUsers("0");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -38,7 +38,7 @@ public class CloudianClientTest {
|
|||
|
||||
@Test
|
||||
public void removeUserAccount() throws Exception {
|
||||
for (UserInfo user : client.listUsers("2ddabedc-4733-4cdf-80b1-abbd9d027005")) {
|
||||
for (CloudianUser user : client.listUsers("2ddabedc-4733-4cdf-80b1-abbd9d027005")) {
|
||||
boolean result = client.removeUser(user.getUserId(), user.getGroupId());
|
||||
}
|
||||
}
|
||||
|
|
@ -49,7 +49,7 @@ public class CloudianClientTest {
|
|||
|
||||
@Test
|
||||
public void listGroup() throws Exception {
|
||||
List<GroupInfo> groups = client.listGroups();
|
||||
List<CloudianGroup> groups = client.listGroups();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
Loading…
Reference in New Issue