-
-
Save chgeuer/f93e2a632578bbbe63f3 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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