Skip to content

Instantly share code, notes, and snippets.

@chgeuer
Created April 13, 2015 15:04
Show Gist options
  • Save chgeuer/f93e2a632578bbbe63f3 to your computer and use it in GitHub Desktop.
Save chgeuer/f93e2a632578bbbe63f3 to your computer and use it in GitHub Desktop.
namespace Microsoft.ChGeuer
{
using Microsoft.Azure;
using Microsoft.WindowsAzure.Management.Compute;
using Microsoft.WindowsAzure.Management.Compute.Models;
using Microsoft.WindowsAzure.Management.Storage;
using Microsoft.WindowsAzure.Management.Storage.Models;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.WindowsAzure.Storage.Blob;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.IO;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using System.Xml.Linq;
public static class ScriptCSAzureExtensionsChGeuer
{
public static List<string> GetSubscriptionIdsFromPublishSettingsFile(string publishSettingsFilename)
{
var xmlText = File.ReadAllText(publishSettingsFilename);
return XDocument.Parse(xmlText)
.Element("PublishData")
.Element("PublishProfile")
.Elements("Subscription")
.Select(_ => _.Attribute("Id").Value)
.ToList();
}
public static CertificateCloudCredentials CreateCertificateCloudCredentialsFromPublishSettingsFile(string publishSettingsFilename, string subscriptionId)
{
var xmlText = File.ReadAllText(publishSettingsFilename);
var subscriptionElem = XDocument.Parse(xmlText)
.Element("PublishData")
.Element("PublishProfile")
.Elements("Subscription")
.First(_ => _.Attribute("Id").Value == subscriptionId);
if (subscriptionElem == null)
{
throw new ArgumentException(string.Format("Could not locate subscription ID {0} in file \"{1}\"", subscriptionId, publishSettingsFilename));
}
var certBase64 = subscriptionElem.Attribute("ManagementCertificate").Value;
var bytes = Convert.FromBase64String(certBase64);
var managementCert = new X509Certificate2(bytes, (string)null, X509KeyStorageFlags.Exportable);
return new CertificateCloudCredentials(subscriptionId, managementCert);
}
public static CertificateCloudCredentials CreateCertificateCloudCredentials(string subscriptionID, string subscriptionManagementCertificateThumbprint, StoreLocation storeLocation)
{
X509Certificate2 managementCert = subscriptionManagementCertificateThumbprint.FindX509CertificateByThumbprint(storeLocation);
return new CertificateCloudCredentials(subscriptionID, managementCert);
}
private static ConfigurationSet GetConfigurationSet(this Role role, string configurationSetType)
{
if (role.ConfigurationSets == null)
{
role.ConfigurationSets = new List<ConfigurationSet>();
}
var configurationSet = role.ConfigurationSets.FirstOrDefault(_ => _.ConfigurationSetType == configurationSetType);
if (configurationSet == null)
{
configurationSet = new ConfigurationSet
{
ConfigurationSetType = configurationSetType
};
role.ConfigurationSets.Add(configurationSet);
}
return configurationSet;
}
public static Role AddWindowsProvisioningConfiguration(this Role role,
string computerName, string adminUserName, string adminPassword,
bool resetPasswordOnFirstLogon = false,
bool enableAutomaticUpdates = true,
string timeZone = "")
{
var configurationSet = role.GetConfigurationSet("WindowsProvisioningConfiguration");
configurationSet.HostName = computerName;
configurationSet.ComputerName = computerName;
configurationSet.AdminUserName = adminUserName;
configurationSet.AdminPassword = adminPassword;
configurationSet.ResetPasswordOnFirstLogon |= resetPasswordOnFirstLogon;
configurationSet.EnableAutomaticUpdates |= enableAutomaticUpdates;
//configurationSet.TimeZone = "";
//configurationSet.DomainJoin = new DomainJoinSettings
//{
// Credentials = new DomainJoinCredentials
// {
// Domain = "",
// UserName = "...",
// Password = "..."
// },
// DomainToJoin = "...",
// LdapMachineObjectOU = "O=...",
// Provisioning = new DomainJoinProvisioning
// {
// AccountData = "..."
// }
//};
//configurationSet.StoredCertificateSettings = new List<StoredCertificateSettings> { new StoredCertificateSettings { StoreName = "My", Thumbprint = "..." }},
//configurationSet.WindowsRemoteManagement = new WindowsRemoteManagementSettings { Listeners = new List<WindowsRemoteManagementListener> { new WindowsRemoteManagementListener { ListenerType = VirtualMachineWindowsRemoteManagementListenerType.Https, CertificateThumbprint = "... "}}},
//configurationSet.CustomData = System.Convert.ToBase64String(), // Optional in WindowsProvisioningConfiguration. Specifies a base-64 encoded string of custom data. The base-64 encoded string is decoded to a binary array that is saved as a file on the Virtual Machine. The maximum length of the binary array is 65535 bytes. The file is saved to %SYSTEMDRIVE%\AzureData\CustomData.bin. If the file exists, it is overwritten. The security on directory is set to System:Full Control and Administrators:Full Control.
return role;
}
public static Role AddLinuxProvisioningConfiguration(this Role role,
string hostName, string userName, string password, bool disableSshPasswordAuthentication = true, SshSettings sshSettings = null, byte[] customData = null)
{
var configurationSet = role.GetConfigurationSet("LinuxProvisioningConfiguration");
configurationSet.HostName = hostName;
configurationSet.UserName = userName;
configurationSet.UserPassword = password;
configurationSet.DisableSshPasswordAuthentication = disableSshPasswordAuthentication;
if (sshSettings != null) { configurationSet.SshSettings = sshSettings; }
// The base-64 encoded string is located in the ovf-env.xml file on the ISO of the Virtual Machine.
// The file is copied to /var/lib/waagent/ovf-env.xml by the Azure Linux Agent.
// The Azure Linux Agent will also place the base-64 encoded data in /var/lib/waagent/CustomData during provisioning.
// The maximum length of the binary array is 65535 bytes.
if (customData != null) { configurationSet.CustomData = Convert.ToBase64String(customData); }
return role;
}
public static Role AddInputEndpoint(this Role role, InputEndpoint inputEndpoint)
{
var configurationSet = role.GetConfigurationSet("NetworkConfiguration");
if (configurationSet.InputEndpoints == null)
{
configurationSet.InputEndpoints = new List<InputEndpoint>();
}
var existingInputEndpoint = configurationSet.InputEndpoints.FirstOrDefault(_ => _.LocalPort == inputEndpoint.LocalPort);
if (existingInputEndpoint != null)
{
configurationSet.InputEndpoints.Remove(existingInputEndpoint);
}
configurationSet.InputEndpoints.Add(inputEndpoint);
return role;
}
public static Role AddPublicIPs(this Role role, ConfigurationSet.PublicIP publicIP)
{
var configurationSet = role.GetConfigurationSet("NetworkConfiguration");
if (configurationSet.PublicIPs == null) { configurationSet.PublicIPs = new List<ConfigurationSet.PublicIP>(); }
if (!configurationSet.PublicIPs.Contains(publicIP)) { configurationSet.PublicIPs.Add(publicIP); }
return role;
}
public static Role AddExtension(this Role role, ResourceExtensionReference reference)
{
if (role.ResourceExtensionReferences == null) { role.ResourceExtensionReferences = new List<ResourceExtensionReference>(); }
var existingExtension = role.ResourceExtensionReferences.FirstOrDefault(_ => _.ReferenceName == reference.ReferenceName);
if (existingExtension != null) { role.ResourceExtensionReferences.Remove(existingExtension); }
role.ResourceExtensionReferences.Add(reference);
return role;
}
public static Role AddDataDisk(this Role role, DataVirtualHardDisk dataVirtualHardDisk)
{
if (role.DataVirtualHardDisks == null) { role.DataVirtualHardDisks = new List<DataVirtualHardDisk>(); }
role.DataVirtualHardDisks.Add(dataVirtualHardDisk);
return role;
}
public static Role AddDataDisk(this Role role, string name = null, string label = null, string hostCaching = null,
Uri mediaLink = null, Uri sourceMediaLink = null, int? logicalDiskSizeInGB = 0, int? logicalUnitNumber = 0)
{
return role.AddDataDisk(new DataVirtualHardDisk
{
HostCaching = hostCaching,
Name = name,
Label = label,
MediaLink = mediaLink,
LogicalDiskSizeInGB = logicalDiskSizeInGB,
LogicalUnitNumber = logicalUnitNumber,
SourceMediaLink = sourceMediaLink
});
}
public static Role AddBGInfoExtension(this Role role)
{
return role.AddExtension(new ResourceExtensionReference
{
State = "Enable",
Name = "BGInfo",
ReferenceName = "BGInfo",
Publisher = "Microsoft.Compute",
Version = "1.*"
});
}
public static Role AddCustomScriptExtensionPowershell(this Role role,
CloudStorageAccount storageAccount, string containerName, string filename, string scriptContents, string arguments)
{
if (!filename.EndsWith(".ps1")) { filename = filename + ".ps1"; }
string commandToExecute = string.Format("powershell -ExecutionPolicy Unrestricted -file {0} {1}", filename, arguments);
return AddCustomScriptExtension(role: role,
extensionPublisher: "Microsoft.Compute", extensionName: "CustomScriptExtension", extensionVersion: "1.3", // "1.*"
storageAccount: storageAccount, containerName: containerName, filename: filename,
scriptContents: scriptContents, commandToExecute: commandToExecute);
}
public static Role AddCustomScriptExtensionLinux(this Role role,
CloudStorageAccount storageAccount, string containerName, string filename, string scriptContents, string arguments)
{
if (!filename.EndsWith(".sh")) { filename = filename + ".sh"; }
string commandToExecute = string.Format("sh {0} {1}", filename, arguments);
// http://azure.microsoft.com/blog/2014/08/20/automate-linux-vm-customization-tasks-using-customscript-extension/
return AddCustomScriptExtension(role: role,
extensionPublisher: "Microsoft.OSTCExtensions", extensionName: "CustomScriptForLinux", extensionVersion: "1.2",
storageAccount: storageAccount, containerName: containerName, filename: filename,
scriptContents: scriptContents, commandToExecute: commandToExecute);
}
private static Role AddCustomScriptExtension(Role role,
string extensionPublisher, string extensionName, string extensionVersion,
CloudStorageAccount storageAccount, string containerName,
string filename, string scriptContents, string commandToExecute)
{
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference(containerName);
container.CreateIfNotExists();
CloudBlockBlob script = container.GetBlockBlobReference(filename);
script.UploadText(scriptContents);
dynamic publicCfg = new ExpandoObject();
publicCfg.fileUris = new string[]
{
string.Format("{0}{1}",
script.Uri.ToString(),
script.GetSharedAccessSignature(
new SharedAccessBlobPolicy
{
Permissions = SharedAccessBlobPermissions.Read,
SharedAccessExpiryTime = DateTime.UtcNow.Add(TimeSpan.FromMinutes(55))
}))
};
publicCfg.commandToExecute = commandToExecute;
string customScriptExtensionPublicConfigParameter = JsonConvert.SerializeObject(publicCfg);
dynamic privateCfg = new ExpandoObject();
privateCfg.storageAccountName = storageAccount.Credentials.AccountName;
privateCfg.storageAccountKey = storageAccount.Credentials.ExportBase64EncodedKey();
var customScriptExtensionPrivateConfigParameter = JsonConvert.SerializeObject(privateCfg);
return role.AddExtension(new ResourceExtensionReference
{
Publisher = extensionPublisher,
ReferenceName = extensionName,
Name = extensionName,
Version = extensionVersion,
State = "Enable",
ResourceExtensionParameterValues = new List<ResourceExtensionParameterValue>
{
new ResourceExtensionParameterValue
{
Type = "Public",
Key = "CustomScriptExtensionPublicConfigParameter",
Value = customScriptExtensionPublicConfigParameter
},
new ResourceExtensionParameterValue
{
Type = "Private",
Key = "CustomScriptExtensionPrivateConfigParameter",
Value = customScriptExtensionPrivateConfigParameter
}
}
});
}
public static async Task<CloudStorageAccount> ToCloudStorageAccountAsync(this StorageManagementClient managementClient, StorageAccount storageAccountFromManagementAPI)
{
var keys = await managementClient.StorageAccounts.GetKeysAsync(storageAccountFromManagementAPI.Name);
return new CloudStorageAccount(new StorageCredentials(storageAccountFromManagementAPI.Name, keys.PrimaryKey), useHttps: true);
}
public static X509Certificate2 FindX509CertificateByThumbprint(this string managementCertThumbprint, StoreLocation storeLocation)
{
return FindX509Certificate(managementCertThumbprint,
X509FindType.FindByThumbprint,
StoreName.My,
storeLocation);
}
public static X509Certificate2 FindX509Certificate(this string findValue, X509FindType findType, StoreName storeName, StoreLocation storeLocation)
{
X509Store store = null;
try
{
store = new X509Store(
storeName: storeName,
storeLocation: storeLocation);
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
X509Certificate2Collection certs = store.Certificates.Find(
findType: findType,
findValue: findValue,
validOnly: false);
if (certs.Count == 0)
{
return null;
}
return certs[0];
}
finally
{
if (store != null) store.Close();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment