mirror of https://github.com/apache/cloudstack.git
cloudian: port sso signature generation code
Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
This commit is contained in:
parent
ceb0b9f71d
commit
a61c43055e
|
|
@ -17,10 +17,16 @@
|
|||
|
||||
package com.cloudian.cloudstack;
|
||||
|
||||
import static com.amazonaws.services.s3.internal.Constants.HMAC_SHA1_ALGORITHM;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
|
|
@ -28,6 +34,7 @@ import org.apache.cloudstack.framework.config.ConfigKey;
|
|||
import org.apache.cloudstack.framework.config.Configurable;
|
||||
import org.apache.cloudstack.framework.messagebus.MessageBus;
|
||||
import org.apache.cloudstack.framework.messagebus.MessageSubscriber;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.domain.Domain;
|
||||
|
|
@ -40,6 +47,7 @@ import com.cloud.user.dao.AccountDao;
|
|||
import com.cloud.utils.component.ComponentLifecycleBase;
|
||||
import com.cloudian.cloudstack.api.CloudianIsEnabledCmd;
|
||||
import com.cloudian.cloudstack.api.CloudianSsoLoginCmd;
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
public class CloudianConnectorImpl extends ComponentLifecycleBase implements CloudianConnector, Configurable {
|
||||
private static final Logger LOG = Logger.getLogger(CloudianConnectorImpl.class);
|
||||
|
|
@ -58,11 +66,74 @@ public class CloudianConnectorImpl extends ComponentLifecycleBase implements Clo
|
|||
return !CloudianConnectorEnabled.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes RFC 2104-compliant HMAC signature.
|
||||
*
|
||||
* @param data The data to be signed.
|
||||
* @param key The signing key.
|
||||
* @return The Base64-encoded RFC 2104-compliant HMAC signature.
|
||||
*/
|
||||
public static String calculateRFC2104HMAC(String data, String key) {
|
||||
try {
|
||||
// get an hmac_sha1 key from the raw key bytes
|
||||
SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), HMAC_SHA1_ALGORITHM);
|
||||
|
||||
// get an hmac_sha1 Mac instance and initialize with the signing key
|
||||
Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);
|
||||
mac.init(signingKey);
|
||||
|
||||
// compute the hmac on input data bytes
|
||||
byte[] rawHmac = mac.doFinal(data.getBytes());
|
||||
|
||||
// return the base64-encode the hmac
|
||||
return Base64.encodeBase64String(rawHmac);
|
||||
} catch (Exception e) {
|
||||
// LOG?
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String genSSOParams(String userId, String groupId, String key) {
|
||||
StringBuilder sts = new StringBuilder();
|
||||
sts.append("user=");
|
||||
sts.append(userId);
|
||||
sts.append("&group=");
|
||||
sts.append(groupId);
|
||||
sts.append("×tamp=");
|
||||
sts.append(System.currentTimeMillis());
|
||||
|
||||
String signature = calculateRFC2104HMAC(sts.toString(), key);
|
||||
if (Strings.isNullOrEmpty(signature)) {
|
||||
return null;
|
||||
}
|
||||
sts.append("&signature=");
|
||||
try {
|
||||
sts.append(URLEncoder.encode(signature, "UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
sts.append("&redirect=");
|
||||
if (groupId.equals("0")) {
|
||||
sts.append("admin.htm");
|
||||
} else {
|
||||
sts.append("explorer.htm");
|
||||
}
|
||||
|
||||
return sts.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateSsoUrl() {
|
||||
// add user/group in CMC if not available
|
||||
// return generated login url using sso shared key
|
||||
return "https://cmc.hs.yadav.xyz:8443/Cloudian/ssosecurelogin.htm?user=admin&group=0×tamp=1505293165230&signature=UbSDimMwSHkKrWgPDrdUpruA%2FGA%3D&redirect=admin.htm";
|
||||
|
||||
String ssoparams = genSSOParams("admin", "0", CloudianSsoKey.value());
|
||||
if (ssoparams == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return "https://cmc.hs.yadav.xyz:8443/Cloudian/ssosecurelogin.htm?" + ssoparams;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -21,11 +21,14 @@ import javax.inject.Inject;
|
|||
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
|
||||
import com.cloud.user.Account;
|
||||
import com.cloudian.cloudstack.CloudianConnector;
|
||||
import com.cloudian.cloudstack.response.CloudianSsoLoginResponse;
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
@APICommand(name = CloudianSsoLoginCmd.APINAME, description = "Generates single-sign-on login url for logged-in CloudStack user to access the Cloudian Management Console",
|
||||
responseObject = CloudianSsoLoginResponse.class,
|
||||
|
|
@ -54,8 +57,12 @@ public class CloudianSsoLoginCmd extends BaseCmd {
|
|||
|
||||
@Override
|
||||
public void execute() {
|
||||
final String ssoUrl = connector.generateSsoUrl();
|
||||
if (Strings.isNullOrEmpty(ssoUrl)) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to generate Cloudian single-sign on URL for the user");
|
||||
}
|
||||
final CloudianSsoLoginResponse response = new CloudianSsoLoginResponse();
|
||||
response.setSsoRedirectUrl(connector.generateSsoUrl());
|
||||
response.setSsoRedirectUrl(ssoUrl);
|
||||
response.setResponseName(getCommandName());
|
||||
response.setObjectName(APINAME.toLowerCase());
|
||||
setResponseObject(response);
|
||||
|
|
|
|||
Loading…
Reference in New Issue