Part of the issue has to do with the way GoGrid provisions administrator passwords – on a newly provisioned machine, the administrator account will have a new password, which you would expect, but also, any additional administrators you create are on the image aren’t valid after provisioning. So the GoGrid-provisioned password is pretty much all you have. This is OK if you can interactively logon to the machine after provisioning, but not so OK if you want to do this automatically. To solve this problem, I came up with a method to fetch the admin password from GoGrid itself from the machine after launch. We trigger this via a web service call after the machine is launched, but presumably you could do this on a startup event as well – I haven’t experimented with that as of yet, but presumably it should work.
The difficulty in the solution is simply due to the limited information you have about your machine from your machine. The basic approach is to call the GoGrid API to get the list of passwords from all your machines, and then find the password that matches the public IP of your machine. In order to use this code, the first thing you need to do is to go to your GoGrid account page and add an API key which you will use to securely interact with the GoGrid service. The type of API key should be System User, as that is required to fetch passwords. This key will be embedded in your code on the GoGrid image, so you should take necessary steps to protect it.
In this solution I use the GoGridClient class from the GoGrid Wiki Documentation – copy that code and specify your api_key and shared secret.
The first task is to write a function to get the passwords from GoGrid (we wrote the GoGridIPType and GoGridIPState enums – they contain the values in the code):
public static string GetPasswordsRaw() // returns the raw XML as provided by GoGrid
{
string returnValue = String.Empty; try
{
GoGridClient grid = new GoGridClient(); System.Collections.Hashtable parameters = new System.Collections.Hashtable();
parameters.Add("format", "xml");
string requestUrl = grid.getAPIRequestURL("/support/password/list", parameters);
returnValue = grid.sendAPIRequest(requestUrl);
}
catch(Exception)
{
} return returnValue;
}
After you have this function, you need a function to get the list of ip addresses from your machine and compare it to the ip addresses from GoGrid. The function first grabs all of the ipaddresses from the local machine and then uses Xpath queries to isolate and iterate the password objects from the GoGrid response. Then it uses more Xpath queries to grab the ipaddress and password from each object. Finally it checks to see if the ipaddress matches any ipaddress on the machine and returns the associated password.
private string GetAdminPassword()
{
// Fetch ip addresses for the local machine and store into a list
List<string> ipaddresses = new List<string>();
System.Net.IPHostEntry IPHost = System.Net.Dns.GetHostEntry(System.Net.Dns.GetHostName());
foreach (System.Net.IPAddress ip in IPHost.AddressList)
{
// Only take the IPv4 addresses
if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
Report("Found ip: {0}", ip.ToString());
ipaddresses.Add(ip.ToString());
}
}
// Get the password information from GoGrid and load into an XML document
string xml = GetPasswordsRaw();
XmlDocument d = new XmlDocument();
d.LoadXml(xml);
// Use Xpath to select the "password" objects
string path = "/gogrid/response/list/object[@name='password']";
XmlNodeList nodes = d.SelectNodes(path);
foreach (XmlNode node in nodes)
{
// Extract the password and ipaddress from the password object
XmlNode pwdnode = node.SelectSingleNode("attribute[@name='password']");
XmlNode ipnode = node.SelectSingleNode
("attribute[@name='server']/object[@name='server']/attribute[@name='ip']" +
"/object[@name='ip']/attribute[@name='ip']");
// API Key passwords will not have an ipnode
if (pwdnode == null || ipnode == null)
continue;
string password = pwdnode.FirstChild.Value;
string ipaddress = ipnode.FirstChild.Value;
// Check to see if the ipaddress belongs to this machine
if (ipaddresses.Contains(ipaddress))
return password;
}
throw(new SystemException("Did not find password"));
}
Once you have the admin password, you can use it to impersonate the box admin as necessary to run additional code requiring such privileges. It really helps in allowing us to automatically deploy boxes on GoGrid. Given the creative commons license of the GoGrid API, the same technique should apply to other cloud providers as necessary.
Hope this helps with your cloud infrastructure deployments – love to hear your comments.
We definitely appreciate the time that you have take to document your processes. If there is anything that we can do to assist in this matter, please let us know.
ReplyDeleteAnd yes, you are correct about the creation of the admin passwords from MyGSIs. Upon initial creation of the virtual server, we automatically create a root user and password which you can find within your portal. You can then create additional users within the VM itself, however, those will not automatically appear within the password section of the GoGrid portal. Also, if you change your root password, that change will not be reflected within the portal. The Password section of the portal is essentially a "notepad" for you to add additional users/passwords manually for other users within your GoGrid account to see, but changes/adds/deletes do not affect the server itself.
But obviously, you are talking about scaling out "clones" of MyGSIs automatically and working with root/passwords within those individual instances.
I have not tested what you propose above but I will be sure to share with others in our organization.
Here to help if you need it.
Best,
Michael Sheehan
Technology Evangelist for GoGrid
Tes, the this is necessary only because we need to launch new instances automatically. If you can do things interactively, then there's no problem!
ReplyDeleteJamie:
ReplyDeleteWe appreciate your thoughtful evaluation and your inspirational comments. You can be sure we are taking your feedback to heart.
Warm regards and thank you for your business,
John Keagy
CEO
GoGrid