Wednesday, 7 March 2012

CloudStack LDAP

References:

First you need to configure LDAP by making an API call with an URL like this:
http://127.0.0.1:8096/client/api?command=ldapConfig&hostname=127.0.0.1&searchbase=ou%3Dpeople%2Co%3DsevenSeas&queryfilter=%28%26%28uid%3D%25u%29%29&binddn=%20cn%3DJohn+Fryer%2Cou%3Dpeople%2Co%3DsevenSeas&bindpass=secret&port=10389&response=json
Or in a more readable format:
http://127.0.0.1:8096/client/api?command=ldapConfig
&hostname=127.0.0.1
&searchbase=ou%3Dpeople%2Co%3DsevenSeas
&queryfilter=%28%26%28uid%3D%25u%29%29
&binddn=%20cn%3DJohn+Fryer%2Cou%3Dpeople%2Co%3DsevenSeas
&bindpass=secret
&port=10389
&response=json
Note the URL encoded values, here you have the decoded version:
http://127.0.0.1:8096/client/api?command=ldapConfig
&hostname=127.0.0.1
&searchbase=ou=people,o=sevenSeas
&queryfilter=(&(uid=%u))
&binddn= cn=John Fryer,ou=people,o=sevenSeas
&bindpass=secret
&port=10389
&response=json
You can use this link to encode/decode your url -> http://meyerweb.com/eric/tools/dencoder/

After you've created your URL (with encoded values) open your browser, login into cloudstack and then fire up your ldap config URL.
Now if you go back to cloudstack and under "Global Settings" search for LDAP and you should see that LDAP is configured.

Now you have to manually create the user accounts with the same logins as in your LDAP server or you can use the CloudStack API to make a script and "sync" your LDAP users into CloudStack, I've written a PHP script that does this.
You'll have to modify it to match your LDAP schema and you can get it after the break.

<?php
//For the LDAP server info:
$ldaphost = "10.10.10.89";
$ldapport = 10389;
$ldaprdn = 'cn=admin,dc=your-domain,dc=com'; // ldap rdn or dn
$ldappass = 'scretpass'; // associated password
/**
* Searches haystack for needle and returns an array of the key path if it is found in the (multidimensional) array, FALSE otherwise.
*
* mixed array_searchRecursive ( mixed needle, array haystack [, bool strict[, array path]] )
*/
function array_searchRecursive( $needle, $haystack, $strict=false, $path=array() )
{
if( !is_array($haystack) ) {
return false;
}
foreach( $haystack as $key => $val ) {
if( is_array($val) && $subPath = array_searchRecursive($needle, $val, $strict, $path) ) {
$path = array_merge($path, array($key), $subPath);
return $path;
} elseif( (!$strict && $val == $needle) || ($strict && $val === $needle) ) {
$path[] = $key;
return $path;
}
}
return false;
}
?>
function getSignature($queryString) {
$secretKey = "-i-RK0waCnGX8RuH_4bFWqc8BHW6c_QfpUjZu4_axwTPz5OW3ILdtO1fH9Q1AvE8-H2HlekeMWI3qlnLF5XBMg";
$hash = @hash_hmac("SHA1", $queryString, $secretKey, true);
$base64encoded = base64_encode($hash);
return urlencode($base64encoded);
}
function request($command, $args = array()) {
$cloudServer = "10.39.31.200:8096";
$apiKey = "ixgpdRFzVI7_JUmRzN45bIZ2hweuBmexlD8WbvcztaDbzv3aWjQ3M450MJuhwAMAvhPtn1A1zOT8AUIc38qctQ";
foreach ($args as $key => $value) {
if ($value == "") {
unset($args[$key]);
}
}
// Building the query
$args['apikey'] = $apiKey;
$args['command'] = $command;
$args['response'] = "json";
ksort($args);
$query = http_build_query($args);
$query = str_replace("+", "%20", $query);
$query .= "&signature=" . getSignature(strtolower($query));
$httpRequest = new HttpRequest();
$httpRequest->setMethod(HTTP_METH_POST);
$url = "http://" . $cloudServer . "?" . $query;
//die($url."\n");
$httpRequest->setUrl($url);
$httpRequest->send();
$code =$httpRequest->getResponseCode();
$data = $httpRequest->getResponseData();
if (empty($data)) {
die("NO_DATA_RECEIVED");
}
//echo $data['body'] . "\n";
$result = @json_decode($data['body']);
if (empty($result)) {
die("NO_VALID_JSON_RECEIVED");
}
//print_r($result);
//die();
$propertyResponse = strtolower($command) . "response";
if (!property_exists($result, $propertyResponse)) {
if (property_exists($result, "errorresponse") && property_exists($result->errorresponse, "errortext")) {
die($result->errorresponse->errortext);
} else {
die("Unable to parse the response. Got code ".$code." and message: " . $data['body']);
}
}
$response = $result->{$propertyResponse};
// list handling : most of lists are on the same pattern as listVirtualMachines :
// { "listvirtualmachinesresponse" : { "virtualmachine" : [ ... ] } }
preg_match('/list(\w+)s/', strtolower($command), $listMatches);
//print_r($listMatches);
//die();
if (!empty($listMatches)) {
$objectName = $listMatches[1];
//echo $objectName."\n";
if (property_exists($response, $objectName)) {
$resultArray = $response->{$objectName};
if (is_array($resultArray)) {
return $resultArray;
}
} else {
// sometimes, the 's' is kept, as in :
// { "listasyncjobsresponse" : { "asyncjobs" : [ ... ] } }
$objectName = $listMatches[1] . "s";
//echo $objectName."\n";
if (property_exists($response, $objectName)) {
$resultArray = $response->{$objectName};
if (is_array($resultArray)) {
return $resultArray;
}
}
}
}
return $response;
}
//Get users from CloudStack
$cloudAccounts = request("listAccounts", array("listall" => "true"));
//print_r($cloudAccounts);
//die();
// Connecting to LDAP
$ldapconn = ldap_connect($ldaphost, $ldapport)
or die("Could not connect to {$ldaphost}");
if ($ldapconn) {
ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ldapconn, LDAP_OPT_REFERRALS, 0);
// binding to ldap server
$ldapbind = ldap_bind($ldapconn, $ldaprdn, $ldappass);
// verify binding
if ($ldapbind) {
echo "LDAP bind successful...\n";
$basedn = "dc=your-domain,dc=com";
$filter="(&(accountstatus=active))";
#$justthese = array("dn","uid", "cn", "mail", "mobile");
#$search = ldap_search($ldapconn, $basedn, $filter, $justthese);
$search = ldap_search($ldapconn, $basedn, $filter);
$info = ldap_get_entries($ldapconn, $search);
if ($info['count'] > 0 ){
//die("Found ".$info['count']. " users!\n");
for ($i = 0; $i < $info['count']; $i++)
{
echo "Porcessing user [" . $info[$i]['uid'][0]."]\n";
//do stuff here
if (array_searchRecursive($info[$i]['uid'][0],$cloudAccounts) === false)
{
//Create user account
$result = request("createAccount", array(
"accounttype" => "0",
"email" => $info[$i]['mail'][0],
"firstname" => $info[$i]['givenname'][0],
"lastname" => $info[$i]['sn'][0],
"password" => $info[$i]['userpassword'][0],
"username" => $info[$i]['uid'][0],
"networkdomain" => "yourdomain",
"timezone" => "Etc/UTC",
));
} else {
echo "User alredy exists!\n";
}
}
} else {
echo "No users found...\n";
}
//Unbind
ldap_unbind($ldapconn);
} else {
echo "LDAP bind failed...\n";
}
}
?>


Possibly Related Posts

No comments:

Post a Comment