From c7e056408a9e472e1ce2f0dbaf09fbef0bf15b07 Mon Sep 17 00:00:00 2001 From: pikumarmsft Date: Mon, 4 Apr 2016 20:46:56 +0530 Subject: [PATCH 01/10] Adding GetAzureRmRecoveryServicesVaultBackupCredentials --- .../Commands.RecoveryServices.csproj | 4 + ...RecoveryServicesVaultExtendedInfoClient.cs | 21 ++ .../Models/PSContracts.cs | 53 ++++- .../Models/PSObjects.cs | 5 + .../Utilities/CertUtils.cs | 11 + ...mRecoveryServicesVaultBackupCredentials.cs | 196 ++++++++++++++++++ 6 files changed, 288 insertions(+), 2 deletions(-) create mode 100644 src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRmRecoveryServicesVaultBackupCredentials.cs diff --git a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Commands.RecoveryServices.csproj b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Commands.RecoveryServices.csproj index 183533657d2f..d67ee0c491c7 100644 --- a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Commands.RecoveryServices.csproj +++ b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Commands.RecoveryServices.csproj @@ -129,6 +129,9 @@ + + Code + @@ -165,4 +168,5 @@ + \ No newline at end of file diff --git a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Common/PSRecoveryServicesVaultExtendedInfoClient.cs b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Common/PSRecoveryServicesVaultExtendedInfoClient.cs index 1020440f6548..ca2ba9b03c26 100644 --- a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Common/PSRecoveryServicesVaultExtendedInfoClient.cs +++ b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Common/PSRecoveryServicesVaultExtendedInfoClient.cs @@ -125,6 +125,27 @@ public ASRVaultCreds GenerateVaultCredential(X509Certificate2 managementCert, AR return asrVaultCreds; } + /// + /// Upload cert to idmgmt + /// + /// + /// + public UploadCertificateResponse UploadCertificate(X509Certificate2 managementCert, ARSVault vault) + { + var certificateArgs = new CertificateArgs(); + certificateArgs.Properties = new Dictionary(); + certificateArgs.Properties.Add("certificate", Convert.ToBase64String(managementCert.GetRawCertData())); + // CertificateArgs.Properties.Add("ContractVersion", "V2012_12"); + + var response = this.recoveryServicesClient.VaultExtendedInfo.UploadCertificateAsync( + vault.ResouceGroupName, + vault.Name, + certificateArgs, managementCert.FriendlyName, + this.GetRequestHeaders()); ; + response.Wait(); + return response.Result; + } + /// /// Changes the Vault context /// diff --git a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Models/PSContracts.cs b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Models/PSContracts.cs index dacd4704d87e..c146dd04920a 100644 --- a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Models/PSContracts.cs +++ b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Models/PSContracts.cs @@ -358,10 +358,10 @@ public VaultCreds() /// resource name /// management cert /// authenticating service namespace - public VaultCreds(string subscriptionId, string resourceName, string managementCert, AcsNamespace acsNamespace) + public VaultCreds(string subscriptionId, string resourceName, string managementCert, AcsNamespace acsNamespace, string resourceType = null) { this.SubscriptionId = subscriptionId; - this.ResourceType = Constants.ASRVaultType; + this.ResourceType = string.IsNullOrEmpty(resourceType) ? Constants.ASRVaultType : resourceType; this.ResourceName = resourceName; this.ManagementCert = managementCert; this.AcsNamespace = acsNamespace; @@ -504,6 +504,55 @@ public ASRVaultCreds( #endregion } + /// + /// Class to define backup vault credentials + /// + [SuppressMessage("Microsoft.StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleClass", Justification = "Grouping classes based on entity")] + [DataContract] + public class BackupVaultCreds : VaultCreds + { + /// + /// Gets or sets the agent links + /// + [DataMember(Order = 0)] + public string AgentLinks { get; set; } + + #region Constructors + + /// + /// Initializes a new instance of the BackupVaultCreds class + /// + public BackupVaultCreds() { } + + /// + /// Initializes a new instance of the BackupVaultCreds class + /// + /// subscription Id + /// resource type + /// resource name + /// management cert + /// acs namespace + public BackupVaultCreds(string subscriptionId, string resourceName, string managementCert, AcsNamespace acsNamespace) + : base(subscriptionId, resourceName, managementCert, acsNamespace, Constants.BackupVaultType) { } + + /// + /// Initializes a new instance of the BackupVaultCreds class + /// + /// subscription Id + /// resource type + /// resource name + /// management cert + /// acs namespace + /// agent links + public BackupVaultCreds(string subscriptionId, string resourceName, string managementCert, AcsNamespace acsNamespace, string agentLinks) + : this(subscriptionId, resourceName, managementCert, acsNamespace) + { + AgentLinks = agentLinks; + } + + #endregion + } + /// /// Class to define ACS name space /// diff --git a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Models/PSObjects.cs b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Models/PSObjects.cs index d9e62e254fd9..8230c4569e86 100644 --- a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Models/PSObjects.cs +++ b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Models/PSObjects.cs @@ -26,6 +26,11 @@ public class Constants /// public const string ASRVaultType = "HyperVRecoveryManagerVault"; + /// + /// Backup vault type + /// + public const string BackupVaultType = "Vaults"; + /// /// Vault Credential version. /// diff --git a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Utilities/CertUtils.cs b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Utilities/CertUtils.cs index eb1b9e2d38bb..0845a32cfb10 100644 --- a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Utilities/CertUtils.cs +++ b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Utilities/CertUtils.cs @@ -221,5 +221,16 @@ private static CngKey Create2048RsaKey() return CngKey.Create(CngAlgorithm2.Rsa, null, keyCreationParameters); } + + /// + /// Returns serialized certificate - Base64 encoded based on the content type + /// + /// The certificate provided + /// Cert content type + /// The serialized cert value in string + public static string SerializeCert(X509Certificate2 cert, X509ContentType contentType) + { + return Convert.ToBase64String(cert.Export(contentType)); + } } } \ No newline at end of file diff --git a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRmRecoveryServicesVaultBackupCredentials.cs b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRmRecoveryServicesVaultBackupCredentials.cs new file mode 100644 index 000000000000..9953ffcc50fc --- /dev/null +++ b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRmRecoveryServicesVaultBackupCredentials.cs @@ -0,0 +1,196 @@ +// ---------------------------------------------------------------------------------- +// +// Copyright Microsoft Corporation +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ---------------------------------------------------------------------------------- + +using Microsoft.Azure.Commands.RecoveryServices; +using Microsoft.Azure.Management.RecoveryServices.Models; +using Microsoft.Azure.Portal.RecoveryServices.Models.Common; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Management.Automation; +using System.Runtime.Serialization; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using System.Xml; + +namespace Microsoft.Azure.Commands.AzureBackup.Cmdlets +{ + /// + /// Command to download an azure backup vault's credentials. + /// + [Cmdlet(VerbsCommon.Get, "AzureRmRecoveryServicesVaultBackupCredentials"), OutputType(typeof(string))] + public class GetAzureRMBackupVaultCredentials : RecoveryServicesCmdletBase + { + [Parameter(Position = 0, Mandatory = true, HelpMessage = "The Azure Recovery Service vault object which is the parent resource.", ValueFromPipeline = true)] + [ValidateNotNullOrEmpty] + public ARSVault Vault { get; set; } + + [Parameter(Position = 2, Mandatory = true, HelpMessage = "The directory where the vault credentials file will be saved. This must be specified as an absolute path.")] + [ValidateNotNullOrEmpty] + public string TargetLocation { get; set; } + + private const int VaultCertificateExpiryInHoursForBackup = 48; + + public override void ExecuteCmdlet() + { + if (!Directory.Exists(TargetLocation)) + { + throw new ArgumentException("The target location provided is not a directory. Please provide a directory."); + } + + string subscriptionId = DefaultContext.Subscription.Id.ToString(); + string displayName = subscriptionId + "_" + Vault.ResouceGroupName + "_" + Vault.Name; + + WriteDebug(string.Format(CultureInfo.InvariantCulture, + "Executing cmdlet with SubscriptionId = {0}, ResourceGroupName = {1}, ResourceName = {2}, TargetLocation = {3}", + subscriptionId, Vault.ResouceGroupName, Vault.Name, TargetLocation)); + + // Generate certificate + X509Certificate2 cert = CertUtils.CreateSelfSignedCertificate(VaultCertificateExpiryInHoursForBackup, subscriptionId.ToString(), this.Vault.Name); + + AcsNamespace acsNamespace = null; + string channelIntegrityKey = string.Empty; + try + { + // Upload cert into ID Mgmt + WriteDebug(string.Format(CultureInfo.InvariantCulture, "RecoveryService - Going to upload the certificate")); + acsNamespace = UploadCert(cert, subscriptionId); + WriteDebug(string.Format(CultureInfo.InvariantCulture, "RecoveryService - Successfully uploaded the certificate")); + } + catch (Exception exception) + { + throw exception; + } + + // generate vault credentials + string vaultCredsFileContent = GenerateVaultCreds(cert, subscriptionId, acsNamespace); + + // NOTE: One of the scenarios for this cmdlet is to generate a file which will be an input to DPM servers. + // We found a bug in the DPM UI which is looking for a particular namespace in the input file. + // The below is a hack to circumvent this issue and this would be removed once the bug can be fixed. + vaultCredsFileContent = vaultCredsFileContent.Replace("Microsoft.Azure.Commands.AzureBackup.Models", + "Microsoft.Azure.Portal.RecoveryServices.Models.Common"); + + // prepare for download + string fileName = string.Format("{0}_{1}.VaultCredentials", displayName, DateTime.UtcNow.ToString("yyyy-dd-M--HH-mm-ss")); + string filePath = Path.Combine(TargetLocation, fileName); + WriteDebug(string.Format("Saving Vault Credentials to file : {0}", filePath)); + + File.WriteAllBytes(filePath, Encoding.UTF8.GetBytes(vaultCredsFileContent)); + + // Output filename back to user + WriteObject(fileName); + } + + /// + /// Method to return the Certificate Expiry time in hours + /// + /// + /// + private int GetCertificateExpiryInHours(string resourceType = null) + { + return VaultCertificateExpiryInHoursForBackup; + } + + /// + /// Upload certificate + /// + /// management certificate + /// subscription Id + /// resource name + /// resource type + /// resource group name + /// acs namespace of the uploaded cert + private AcsNamespace UploadCert(X509Certificate2 cert, string subscriptionId) + { + UploadCertificateResponse response = RecoveryServicesClient.UploadCertificate(cert, this.Vault); + + return new AcsNamespace(response); + } + + /// + /// Generates vault creds file + /// + /// management certificate + /// subscription Id + /// resource type + /// display name + /// acs namespace + /// xml file in string format + private string GenerateVaultCreds(X509Certificate2 cert, string subscriptionId, AcsNamespace acsNamespace) + { + try + { + return GenerateVaultCredsForBackup(cert, subscriptionId, acsNamespace); + } + catch (Exception exception) + { + throw exception; + } + } + + /// + /// Generates vault creds file content for backup Vault + /// + /// management certificate + /// subscription Id + /// resource type + /// display name + /// acs namespace + /// xml file in string format + private string GenerateVaultCredsForBackup(X509Certificate2 cert, string subscriptionId, AcsNamespace acsNamespace) + { + using (var output = new MemoryStream()) + { + using (var writer = XmlWriter.Create(output, GetXmlWriterSettings())) + { + BackupVaultCreds backupVaultCreds = new BackupVaultCreds(subscriptionId, + Vault.Name, + CertUtils.SerializeCert(cert, X509ContentType.Pfx), + acsNamespace, + GetAgentLinks()); + DataContractSerializer serializer = new DataContractSerializer(typeof(BackupVaultCreds)); + serializer.WriteObject(writer, backupVaultCreds); + + WriteDebug(string.Format(CultureInfo.InvariantCulture, "RecoveryService - Backup Vault - Successfully serialized the file content")); + } + + return Encoding.UTF8.GetString(output.ToArray()); + } + } + + private static string GetAgentLinks() + { + return "WABUpdateKBLink,http://go.microsoft.com/fwlink/p/?LinkId=229525;" + + "StorageQuotaPurchaseLink,http://go.microsoft.com/fwlink/?LinkId=205490;" + + "WebPortalLink,http://go.microsoft.com/fwlink/?LinkId=252913;" + + "WABprivacyStatement,http://go.microsoft.com/fwlink/?LinkId=221308"; + } + + /// + /// A set of XmlWriterSettings to use for the publishing profile + /// + /// The XmlWriterSettings set + private XmlWriterSettings GetXmlWriterSettings() + { + return new XmlWriterSettings + { + Encoding = new UTF8Encoding(false), + Indent = true, + NewLineOnAttributes = true + }; + } + } +} From 509afb720ed88e7d79290ef4706bea3e1958c76d Mon Sep 17 00:00:00 2001 From: pikumarmsft Date: Tue, 5 Apr 2016 10:40:07 +0530 Subject: [PATCH 02/10] Changing file name format. --- .../Vault/GetAzureRmRecoveryServicesVaultBackupCredentials.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRmRecoveryServicesVaultBackupCredentials.cs b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRmRecoveryServicesVaultBackupCredentials.cs index 9953ffcc50fc..56a4fcb7168d 100644 --- a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRmRecoveryServicesVaultBackupCredentials.cs +++ b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRmRecoveryServicesVaultBackupCredentials.cs @@ -51,7 +51,7 @@ public override void ExecuteCmdlet() } string subscriptionId = DefaultContext.Subscription.Id.ToString(); - string displayName = subscriptionId + "_" + Vault.ResouceGroupName + "_" + Vault.Name; + string displayName = Vault.Name; WriteDebug(string.Format(CultureInfo.InvariantCulture, "Executing cmdlet with SubscriptionId = {0}, ResourceGroupName = {1}, ResourceName = {2}, TargetLocation = {3}", @@ -84,7 +84,7 @@ public override void ExecuteCmdlet() "Microsoft.Azure.Portal.RecoveryServices.Models.Common"); // prepare for download - string fileName = string.Format("{0}_{1}.VaultCredentials", displayName, DateTime.UtcNow.ToString("yyyy-dd-M--HH-mm-ss")); + string fileName = string.Format("{0}_{1:ddd MMM dd yyyy}.VaultCredentials", displayName, DateTime.UtcNow); string filePath = Path.Combine(TargetLocation, fileName); WriteDebug(string.Format("Saving Vault Credentials to file : {0}", filePath)); From 6d766c7c6c1511a5cd8efd3e3bd550b37158fd06 Mon Sep 17 00:00:00 2001 From: pikumarmsft Date: Tue, 5 Apr 2016 11:40:01 +0530 Subject: [PATCH 03/10] changing namespace in getAzureRmRecoveryServicesVaultBackupCredentials --- .../Vault/GetAzureRmRecoveryServicesVaultBackupCredentials.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRmRecoveryServicesVaultBackupCredentials.cs b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRmRecoveryServicesVaultBackupCredentials.cs index 56a4fcb7168d..8320bda96a50 100644 --- a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRmRecoveryServicesVaultBackupCredentials.cs +++ b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRmRecoveryServicesVaultBackupCredentials.cs @@ -25,7 +25,7 @@ using System.Text; using System.Xml; -namespace Microsoft.Azure.Commands.AzureBackup.Cmdlets +namespace Microsoft.Azure.Commands.RecoveryServices { /// /// Command to download an azure backup vault's credentials. From ace0fc388c920ed0e3a380c261953835948126d9 Mon Sep 17 00:00:00 2001 From: pikumarmsft Date: Mon, 11 Apr 2016 20:35:54 +0530 Subject: [PATCH 04/10] Merging ASR and Backup get-VaultCred cmdlet. --- ...zureRMRecoveryServicesVaultSettingsFile.cs | 55 +++++++-- ...mRecoveryServicesVaultBackupCredentials.cs | 106 +++++++----------- 2 files changed, 88 insertions(+), 73 deletions(-) diff --git a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRMRecoveryServicesVaultSettingsFile.cs b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRMRecoveryServicesVaultSettingsFile.cs index 2c952368f686..2bc6bdcc7954 100644 --- a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRMRecoveryServicesVaultSettingsFile.cs +++ b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRMRecoveryServicesVaultSettingsFile.cs @@ -25,21 +25,25 @@ namespace Microsoft.Azure.Commands.RecoveryServices /// Retrieves Azure Recovery Services Vault Settings File. /// [Cmdlet(VerbsCommon.Get, "AzureRmRecoveryServicesVaultSettingsFile")] - [OutputType(typeof(VaultSettingsFilePath))] - public class GetAzureRmRecoveryServicesVaultSettingsFile : RecoveryServicesCmdletBase + [OutputType(typeof(VaultSettingsFilePath), typeof(string))] + public partial class GetAzureRmRecoveryServicesVaultSettingsFile : RecoveryServicesCmdletBase { /// /// Expiry in hours for generated certificate. /// - private const int VaultCertificateExpiryInHoursForHRM = 120; + private const int VaultCertificateExpiryInHoursForHRM = 120; + + /// + /// Expiry in hours for generated certificate. + /// + private const int VaultCertificateExpiryInHoursForBackup = 48; #region Parameters /// /// Gets or sets vault Object. /// - [Parameter(ParameterSetName = ASRParameterSets.ByDefault, Mandatory = true, ValueFromPipeline = true)] - [Parameter(ParameterSetName = ASRParameterSets.ForSite, Mandatory = true, ValueFromPipeline = true)] + [Parameter(ValueFromPipeline = true, Position = 1)] [ValidateNotNullOrEmpty] public ARSVault Vault { get; set; } @@ -63,10 +67,38 @@ public class GetAzureRmRecoveryServicesVaultSettingsFile : RecoveryServicesCmdle /// /// Gets or sets vault Object. /// - [Parameter(ParameterSetName = ASRParameterSets.ByDefault)] - [Parameter(ParameterSetName = ASRParameterSets.ForSite)] + [Parameter(Mandatory = true, Position = 2)] public string Path { get; set; } + /// + /// Gets or sets the path where the credential file is to be generated + /// + /// + /// Gets or sets vault Object. + /// + [Parameter(ParameterSetName = ASRParameterSets.ByDefault, Mandatory = true, ValueFromPipeline = true)] + [Parameter(ParameterSetName = ASRParameterSets.ForSite, Mandatory = true, ValueFromPipeline = true)] + public SwitchParameter ASR + { + get { return asr; } + set { asr = value; } + } + private bool asr; + + /// + /// Gets or sets the path where the credential file is to be generated + /// + /// + /// Gets or sets vault Object. + /// + [Parameter(ParameterSetName = "ForBackup", Mandatory = true)] + public SwitchParameter Backup + { + get { return backup; } + set { backup = value; } + } + private bool backup; + #endregion Parameters /// @@ -76,7 +108,14 @@ public override void ExecuteCmdlet() { try { - this.GetVaultSettingsFile(); + if (asr) + { + this.GetVaultSettingsFile(); + } + if(backup) + { + this.GetAzureRMRecoveryServicesVaultBackupCredentials(Path, VaultCertificateExpiryInHoursForBackup); + } } catch (AggregateException aggregateEx) { diff --git a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRmRecoveryServicesVaultBackupCredentials.cs b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRmRecoveryServicesVaultBackupCredentials.cs index 8320bda96a50..58cb60f871b8 100644 --- a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRmRecoveryServicesVaultBackupCredentials.cs +++ b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRmRecoveryServicesVaultBackupCredentials.cs @@ -27,81 +27,57 @@ namespace Microsoft.Azure.Commands.RecoveryServices { - /// - /// Command to download an azure backup vault's credentials. - /// - [Cmdlet(VerbsCommon.Get, "AzureRmRecoveryServicesVaultBackupCredentials"), OutputType(typeof(string))] - public class GetAzureRMBackupVaultCredentials : RecoveryServicesCmdletBase + public partial class GetAzureRmRecoveryServicesVaultSettingsFile { - [Parameter(Position = 0, Mandatory = true, HelpMessage = "The Azure Recovery Service vault object which is the parent resource.", ValueFromPipeline = true)] - [ValidateNotNullOrEmpty] - public ARSVault Vault { get; set; } - - [Parameter(Position = 2, Mandatory = true, HelpMessage = "The directory where the vault credentials file will be saved. This must be specified as an absolute path.")] - [ValidateNotNullOrEmpty] - public string TargetLocation { get; set; } - - private const int VaultCertificateExpiryInHoursForBackup = 48; - - public override void ExecuteCmdlet() + public void GetAzureRMRecoveryServicesVaultBackupCredentials(string targetLocation, int vaultCertificateExpiryInHoursForBackup) { - if (!Directory.Exists(TargetLocation)) - { - throw new ArgumentException("The target location provided is not a directory. Please provide a directory."); - } - - string subscriptionId = DefaultContext.Subscription.Id.ToString(); - string displayName = Vault.Name; + if (!Directory.Exists(targetLocation)) + { + throw new ArgumentException("The target location provided is not a directory. Please provide a directory."); + } - WriteDebug(string.Format(CultureInfo.InvariantCulture, - "Executing cmdlet with SubscriptionId = {0}, ResourceGroupName = {1}, ResourceName = {2}, TargetLocation = {3}", - subscriptionId, Vault.ResouceGroupName, Vault.Name, TargetLocation)); + string subscriptionId = DefaultContext.Subscription.Id.ToString(); + string displayName = this.Vault.Name; - // Generate certificate - X509Certificate2 cert = CertUtils.CreateSelfSignedCertificate(VaultCertificateExpiryInHoursForBackup, subscriptionId.ToString(), this.Vault.Name); + WriteDebug(string.Format(CultureInfo.InvariantCulture, + "Executing cmdlet with SubscriptionId = {0}, ResourceGroupName = {1}, ResourceName = {2}, TargetLocation = {3}", + subscriptionId, this.Vault.ResouceGroupName, this.Vault.Name, targetLocation)); - AcsNamespace acsNamespace = null; - string channelIntegrityKey = string.Empty; - try - { - // Upload cert into ID Mgmt - WriteDebug(string.Format(CultureInfo.InvariantCulture, "RecoveryService - Going to upload the certificate")); - acsNamespace = UploadCert(cert, subscriptionId); - WriteDebug(string.Format(CultureInfo.InvariantCulture, "RecoveryService - Successfully uploaded the certificate")); - } - catch (Exception exception) - { - throw exception; - } + // Generate certificate + X509Certificate2 cert = CertUtils.CreateSelfSignedCertificate(vaultCertificateExpiryInHoursForBackup, subscriptionId.ToString(), this.Vault.Name); - // generate vault credentials - string vaultCredsFileContent = GenerateVaultCreds(cert, subscriptionId, acsNamespace); + AcsNamespace acsNamespace = null; + string channelIntegrityKey = string.Empty; + try + { + // Upload cert into ID Mgmt + WriteDebug(string.Format(CultureInfo.InvariantCulture, "RecoveryService - Going to upload the certificate")); + acsNamespace = UploadCert(cert, subscriptionId); + WriteDebug(string.Format(CultureInfo.InvariantCulture, "RecoveryService - Successfully uploaded the certificate")); + } + catch (Exception exception) + { + throw exception; + } - // NOTE: One of the scenarios for this cmdlet is to generate a file which will be an input to DPM servers. - // We found a bug in the DPM UI which is looking for a particular namespace in the input file. - // The below is a hack to circumvent this issue and this would be removed once the bug can be fixed. - vaultCredsFileContent = vaultCredsFileContent.Replace("Microsoft.Azure.Commands.AzureBackup.Models", - "Microsoft.Azure.Portal.RecoveryServices.Models.Common"); + // generate vault credentials + string vaultCredsFileContent = GenerateVaultCreds(cert, subscriptionId, acsNamespace); - // prepare for download - string fileName = string.Format("{0}_{1:ddd MMM dd yyyy}.VaultCredentials", displayName, DateTime.UtcNow); - string filePath = Path.Combine(TargetLocation, fileName); - WriteDebug(string.Format("Saving Vault Credentials to file : {0}", filePath)); + // NOTE: One of the scenarios for this cmdlet is to generate a file which will be an input to DPM servers. + // We found a bug in the DPM UI which is looking for a particular namespace in the input file. + // The below is a hack to circumvent this issue and this would be removed once the bug can be fixed. + vaultCredsFileContent = vaultCredsFileContent.Replace("Microsoft.Azure.Commands.AzureBackup.Models", + "Microsoft.Azure.Portal.RecoveryServices.Models.Common"); - File.WriteAllBytes(filePath, Encoding.UTF8.GetBytes(vaultCredsFileContent)); + // prepare for download + string fileName = string.Format("{0}_{1:ddd MMM dd yyyy}.VaultCredentials", displayName, DateTime.UtcNow); + string filePath = System.IO.Path.Combine(targetLocation, fileName); + WriteDebug(string.Format("Saving Vault Credentials to file : {0}", filePath)); - // Output filename back to user - WriteObject(fileName); - } + File.WriteAllBytes(filePath, Encoding.UTF8.GetBytes(vaultCredsFileContent)); - /// - /// Method to return the Certificate Expiry time in hours - /// - /// - /// - private int GetCertificateExpiryInHours(string resourceType = null) - { - return VaultCertificateExpiryInHoursForBackup; + // Output filename back to user + WriteObject(fileName); } /// @@ -157,7 +133,7 @@ private string GenerateVaultCredsForBackup(X509Certificate2 cert, string subscri using (var writer = XmlWriter.Create(output, GetXmlWriterSettings())) { BackupVaultCreds backupVaultCreds = new BackupVaultCreds(subscriptionId, - Vault.Name, + this.Vault.Name, CertUtils.SerializeCert(cert, X509ContentType.Pfx), acsNamespace, GetAgentLinks()); From 3b064df395854f5205a523906450d92e3189e050 Mon Sep 17 00:00:00 2001 From: pikumarmsft Date: Tue, 12 Apr 2016 17:12:01 +0530 Subject: [PATCH 05/10] merging files. --- .../Commands.RecoveryServices.csproj | 3 - ...RecoveryServicesVaultExtendedInfoClient.cs | 3 +- .../Models/PSContracts.cs | 2 +- ...mRecoveryServicesVaultBackupCredentials.cs | 172 ------------------ 4 files changed, 2 insertions(+), 178 deletions(-) delete mode 100644 src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRmRecoveryServicesVaultBackupCredentials.cs diff --git a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Commands.RecoveryServices.csproj b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Commands.RecoveryServices.csproj index d67ee0c491c7..561d8a5b2cca 100644 --- a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Commands.RecoveryServices.csproj +++ b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Commands.RecoveryServices.csproj @@ -129,9 +129,6 @@ - - Code - diff --git a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Common/PSRecoveryServicesVaultExtendedInfoClient.cs b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Common/PSRecoveryServicesVaultExtendedInfoClient.cs index ca2ba9b03c26..7761516bc5a2 100644 --- a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Common/PSRecoveryServicesVaultExtendedInfoClient.cs +++ b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Common/PSRecoveryServicesVaultExtendedInfoClient.cs @@ -135,13 +135,12 @@ public UploadCertificateResponse UploadCertificate(X509Certificate2 managementCe var certificateArgs = new CertificateArgs(); certificateArgs.Properties = new Dictionary(); certificateArgs.Properties.Add("certificate", Convert.ToBase64String(managementCert.GetRawCertData())); - // CertificateArgs.Properties.Add("ContractVersion", "V2012_12"); var response = this.recoveryServicesClient.VaultExtendedInfo.UploadCertificateAsync( vault.ResouceGroupName, vault.Name, certificateArgs, managementCert.FriendlyName, - this.GetRequestHeaders()); ; + this.GetRequestHeaders()); response.Wait(); return response.Result; } diff --git a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Models/PSContracts.cs b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Models/PSContracts.cs index c146dd04920a..32af77e8646a 100644 --- a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Models/PSContracts.cs +++ b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Models/PSContracts.cs @@ -358,6 +358,7 @@ public VaultCreds() /// resource name /// management cert /// authenticating service namespace + /// resource type backup vault or ASR vault public VaultCreds(string subscriptionId, string resourceName, string managementCert, AcsNamespace acsNamespace, string resourceType = null) { this.SubscriptionId = subscriptionId; @@ -507,7 +508,6 @@ public ASRVaultCreds( /// /// Class to define backup vault credentials /// - [SuppressMessage("Microsoft.StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleClass", Justification = "Grouping classes based on entity")] [DataContract] public class BackupVaultCreds : VaultCreds { diff --git a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRmRecoveryServicesVaultBackupCredentials.cs b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRmRecoveryServicesVaultBackupCredentials.cs deleted file mode 100644 index 58cb60f871b8..000000000000 --- a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRmRecoveryServicesVaultBackupCredentials.cs +++ /dev/null @@ -1,172 +0,0 @@ -// ---------------------------------------------------------------------------------- -// -// Copyright Microsoft Corporation -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// ---------------------------------------------------------------------------------- - -using Microsoft.Azure.Commands.RecoveryServices; -using Microsoft.Azure.Management.RecoveryServices.Models; -using Microsoft.Azure.Portal.RecoveryServices.Models.Common; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Management.Automation; -using System.Runtime.Serialization; -using System.Security.Cryptography.X509Certificates; -using System.Text; -using System.Xml; - -namespace Microsoft.Azure.Commands.RecoveryServices -{ - public partial class GetAzureRmRecoveryServicesVaultSettingsFile - { - public void GetAzureRMRecoveryServicesVaultBackupCredentials(string targetLocation, int vaultCertificateExpiryInHoursForBackup) - { - if (!Directory.Exists(targetLocation)) - { - throw new ArgumentException("The target location provided is not a directory. Please provide a directory."); - } - - string subscriptionId = DefaultContext.Subscription.Id.ToString(); - string displayName = this.Vault.Name; - - WriteDebug(string.Format(CultureInfo.InvariantCulture, - "Executing cmdlet with SubscriptionId = {0}, ResourceGroupName = {1}, ResourceName = {2}, TargetLocation = {3}", - subscriptionId, this.Vault.ResouceGroupName, this.Vault.Name, targetLocation)); - - // Generate certificate - X509Certificate2 cert = CertUtils.CreateSelfSignedCertificate(vaultCertificateExpiryInHoursForBackup, subscriptionId.ToString(), this.Vault.Name); - - AcsNamespace acsNamespace = null; - string channelIntegrityKey = string.Empty; - try - { - // Upload cert into ID Mgmt - WriteDebug(string.Format(CultureInfo.InvariantCulture, "RecoveryService - Going to upload the certificate")); - acsNamespace = UploadCert(cert, subscriptionId); - WriteDebug(string.Format(CultureInfo.InvariantCulture, "RecoveryService - Successfully uploaded the certificate")); - } - catch (Exception exception) - { - throw exception; - } - - // generate vault credentials - string vaultCredsFileContent = GenerateVaultCreds(cert, subscriptionId, acsNamespace); - - // NOTE: One of the scenarios for this cmdlet is to generate a file which will be an input to DPM servers. - // We found a bug in the DPM UI which is looking for a particular namespace in the input file. - // The below is a hack to circumvent this issue and this would be removed once the bug can be fixed. - vaultCredsFileContent = vaultCredsFileContent.Replace("Microsoft.Azure.Commands.AzureBackup.Models", - "Microsoft.Azure.Portal.RecoveryServices.Models.Common"); - - // prepare for download - string fileName = string.Format("{0}_{1:ddd MMM dd yyyy}.VaultCredentials", displayName, DateTime.UtcNow); - string filePath = System.IO.Path.Combine(targetLocation, fileName); - WriteDebug(string.Format("Saving Vault Credentials to file : {0}", filePath)); - - File.WriteAllBytes(filePath, Encoding.UTF8.GetBytes(vaultCredsFileContent)); - - // Output filename back to user - WriteObject(fileName); - } - - /// - /// Upload certificate - /// - /// management certificate - /// subscription Id - /// resource name - /// resource type - /// resource group name - /// acs namespace of the uploaded cert - private AcsNamespace UploadCert(X509Certificate2 cert, string subscriptionId) - { - UploadCertificateResponse response = RecoveryServicesClient.UploadCertificate(cert, this.Vault); - - return new AcsNamespace(response); - } - - /// - /// Generates vault creds file - /// - /// management certificate - /// subscription Id - /// resource type - /// display name - /// acs namespace - /// xml file in string format - private string GenerateVaultCreds(X509Certificate2 cert, string subscriptionId, AcsNamespace acsNamespace) - { - try - { - return GenerateVaultCredsForBackup(cert, subscriptionId, acsNamespace); - } - catch (Exception exception) - { - throw exception; - } - } - - /// - /// Generates vault creds file content for backup Vault - /// - /// management certificate - /// subscription Id - /// resource type - /// display name - /// acs namespace - /// xml file in string format - private string GenerateVaultCredsForBackup(X509Certificate2 cert, string subscriptionId, AcsNamespace acsNamespace) - { - using (var output = new MemoryStream()) - { - using (var writer = XmlWriter.Create(output, GetXmlWriterSettings())) - { - BackupVaultCreds backupVaultCreds = new BackupVaultCreds(subscriptionId, - this.Vault.Name, - CertUtils.SerializeCert(cert, X509ContentType.Pfx), - acsNamespace, - GetAgentLinks()); - DataContractSerializer serializer = new DataContractSerializer(typeof(BackupVaultCreds)); - serializer.WriteObject(writer, backupVaultCreds); - - WriteDebug(string.Format(CultureInfo.InvariantCulture, "RecoveryService - Backup Vault - Successfully serialized the file content")); - } - - return Encoding.UTF8.GetString(output.ToArray()); - } - } - - private static string GetAgentLinks() - { - return "WABUpdateKBLink,http://go.microsoft.com/fwlink/p/?LinkId=229525;" + - "StorageQuotaPurchaseLink,http://go.microsoft.com/fwlink/?LinkId=205490;" + - "WebPortalLink,http://go.microsoft.com/fwlink/?LinkId=252913;" + - "WABprivacyStatement,http://go.microsoft.com/fwlink/?LinkId=221308"; - } - - /// - /// A set of XmlWriterSettings to use for the publishing profile - /// - /// The XmlWriterSettings set - private XmlWriterSettings GetXmlWriterSettings() - { - return new XmlWriterSettings - { - Encoding = new UTF8Encoding(false), - Indent = true, - NewLineOnAttributes = true - }; - } - } -} From cea53bf41cd42ec9d5cec1e7330c04b5bf1f2883 Mon Sep 17 00:00:00 2001 From: pikumarmsft Date: Tue, 12 Apr 2016 17:14:04 +0530 Subject: [PATCH 06/10] Adding backup vault cred code to Get-AzureRmRecoveryVaultSettingFiles.cs --- ...zureRMRecoveryServicesVaultSettingsFile.cs | 158 +++++++++++++++++- 1 file changed, 153 insertions(+), 5 deletions(-) diff --git a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRMRecoveryServicesVaultSettingsFile.cs b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRMRecoveryServicesVaultSettingsFile.cs index 2bc6bdcc7954..181b62a15b1d 100644 --- a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRMRecoveryServicesVaultSettingsFile.cs +++ b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRMRecoveryServicesVaultSettingsFile.cs @@ -18,6 +18,12 @@ using System.Security.Cryptography.X509Certificates; using Microsoft.Azure.Common.Authentication.Models; using Microsoft.Azure.Portal.RecoveryServices.Models.Common; +using System.IO; +using System.Xml; +using System.Runtime.Serialization; +using System.Text; +using System.Globalization; +using Microsoft.Azure.Management.RecoveryServices.Models; namespace Microsoft.Azure.Commands.RecoveryServices { @@ -76,8 +82,8 @@ public partial class GetAzureRmRecoveryServicesVaultSettingsFile : RecoveryServi /// /// Gets or sets vault Object. /// - [Parameter(ParameterSetName = ASRParameterSets.ByDefault, Mandatory = true, ValueFromPipeline = true)] - [Parameter(ParameterSetName = ASRParameterSets.ForSite, Mandatory = true, ValueFromPipeline = true)] + [Parameter(ParameterSetName = ASRParameterSets.ByDefault, Mandatory = true)] + [Parameter(ParameterSetName = ASRParameterSets.ForSite, Mandatory = true)] public SwitchParameter ASR { get { return asr; } @@ -112,9 +118,9 @@ public override void ExecuteCmdlet() { this.GetVaultSettingsFile(); } - if(backup) + if (backup) { - this.GetAzureRMRecoveryServicesVaultBackupCredentials(Path, VaultCertificateExpiryInHoursForBackup); + this.GetAzureRMRecoveryServicesVaultBackupCredentials(); } } catch (AggregateException aggregateEx) @@ -140,7 +146,7 @@ private void GetVaultSettingsFile() if (!string.IsNullOrEmpty(this.SiteIdentifier) && !string.IsNullOrEmpty(this.SiteFriendlyName)) { - site.ID = this.SiteIdentifier; + site.ID = this.SiteIdentifier; site.Name = this.SiteFriendlyName; } @@ -183,5 +189,147 @@ private string GenerateFileName() return fileName; } + + #region Backup Vault Credentials + public void GetAzureRMRecoveryServicesVaultBackupCredentials() + { + string targetLocation = string.IsNullOrEmpty(this.Path) ? Utilities.GetDefaultPath() : this.Path; + if (!Directory.Exists(targetLocation)) + { + throw new ArgumentException("The target location provided is not a directory. Please provide a directory."); + } + + string subscriptionId = DefaultContext.Subscription.Id.ToString(); + string displayName = this.Vault.Name; + + WriteDebug(string.Format(CultureInfo.InvariantCulture, + "Executing cmdlet with SubscriptionId = {0}, ResourceGroupName = {1}, ResourceName = {2}, TargetLocation = {3}", + subscriptionId, this.Vault.ResouceGroupName, this.Vault.Name, targetLocation)); + + // Generate certificate + X509Certificate2 cert = CertUtils.CreateSelfSignedCertificate(VaultCertificateExpiryInHoursForBackup, subscriptionId.ToString(), this.Vault.Name); + + AcsNamespace acsNamespace = null; + string channelIntegrityKey = string.Empty; + try + { + // Upload cert into ID Mgmt + WriteDebug(string.Format(CultureInfo.InvariantCulture, "RecoveryService - Going to upload the certificate")); + acsNamespace = UploadCert(cert); + WriteDebug(string.Format(CultureInfo.InvariantCulture, "RecoveryService - Successfully uploaded the certificate")); + } + catch (Exception exception) + { + throw exception; + } + + // generate vault credentials + string vaultCredsFileContent = GenerateVaultCreds(cert, subscriptionId, acsNamespace); + + // NOTE: One of the scenarios for this cmdlet is to generate a file which will be an input to DPM servers. + // We found a bug in the DPM UI which is looking for a particular namespace in the input file. + // The below is a hack to circumvent this issue and this would be removed once the bug can be fixed. + vaultCredsFileContent = vaultCredsFileContent.Replace("Microsoft.Azure.Commands.AzureBackup.Models", + "Microsoft.Azure.Portal.RecoveryServices.Models.Common"); + + // prepare for download + string fileName = string.Format("{0}_{1:ddd MMM dd yyyy}.VaultCredentials", displayName, DateTime.UtcNow); + string filePath = System.IO.Path.Combine(targetLocation, fileName); + WriteDebug(string.Format("Saving Vault Credentials to file : {0}", filePath)); + + File.WriteAllBytes(filePath, Encoding.UTF8.GetBytes(vaultCredsFileContent)); + + VaultSettingsFilePath output = new VaultSettingsFilePath() + { + FilePath = filePath, + }; + + // Output filename back to user + WriteObject(output); + } + + /// + /// Upload certificate + /// + /// management certificate + /// subscription Id + /// acs namespace of the uploaded cert + private AcsNamespace UploadCert(X509Certificate2 cert) + { + UploadCertificateResponse response = RecoveryServicesClient.UploadCertificate(cert, this.Vault); + + return new AcsNamespace(response); + } + + /// + /// Generates vault creds file + /// + /// management certificate + /// subscription Id + /// acs namespace + /// xml file in string format + private string GenerateVaultCreds(X509Certificate2 cert, string subscriptionId, AcsNamespace acsNamespace) + { + try + { + return GenerateVaultCredsForBackup(cert, subscriptionId, acsNamespace); + } + catch (Exception exception) + { + throw exception; + } + } + + /// + /// Generates vault creds file content for backup Vault + /// + /// management certificate + /// subscription Id + /// acs namespace + /// xml file in string format + private string GenerateVaultCredsForBackup(X509Certificate2 cert, string subscriptionId, AcsNamespace acsNamespace) + { + using (var output = new MemoryStream()) + { + using (var writer = XmlWriter.Create(output, GetXmlWriterSettings())) + { + BackupVaultCreds backupVaultCreds = new BackupVaultCreds(subscriptionId, + this.Vault.Name, + CertUtils.SerializeCert(cert, X509ContentType.Pfx), + acsNamespace, + GetAgentLinks()); + DataContractSerializer serializer = new DataContractSerializer(typeof(BackupVaultCreds)); + serializer.WriteObject(writer, backupVaultCreds); + + WriteDebug(string.Format(CultureInfo.InvariantCulture, "RecoveryService - Backup Vault - Successfully serialized the file content")); + } + + return Encoding.UTF8.GetString(output.ToArray()); + } + } + + private static string GetAgentLinks() + { + return "WABUpdateKBLink,http://go.microsoft.com/fwlink/p/?LinkId=229525;" + + "StorageQuotaPurchaseLink,http://go.microsoft.com/fwlink/?LinkId=205490;" + + "WebPortalLink,http://go.microsoft.com/fwlink/?LinkId=252913;" + + "WABprivacyStatement,http://go.microsoft.com/fwlink/?LinkId=221308"; + } + + /// + /// A set of XmlWriterSettings to use for the publishing profile + /// + /// The XmlWriterSettings set + private XmlWriterSettings GetXmlWriterSettings() + { + return new XmlWriterSettings + { + Encoding = new UTF8Encoding(false), + Indent = true, + NewLineOnAttributes = true + }; + } + + #endregion } } From 1105812621a2d61b345a6a87c7626b6d8cc106e6 Mon Sep 17 00:00:00 2001 From: pikumarmsft Date: Tue, 12 Apr 2016 17:22:20 +0530 Subject: [PATCH 07/10] removing nuget changes from csproj --- .../Commands.RecoveryServices/Commands.RecoveryServices.csproj | 1 - .../Vault/GetAzureRMRecoveryServicesVaultSettingsFile.cs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Commands.RecoveryServices.csproj b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Commands.RecoveryServices.csproj index 63c7f2ee801d..bea93b771751 100644 --- a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Commands.RecoveryServices.csproj +++ b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Commands.RecoveryServices.csproj @@ -167,5 +167,4 @@ - \ No newline at end of file diff --git a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRMRecoveryServicesVaultSettingsFile.cs b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRMRecoveryServicesVaultSettingsFile.cs index 181b62a15b1d..f976d53c187b 100644 --- a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRMRecoveryServicesVaultSettingsFile.cs +++ b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRMRecoveryServicesVaultSettingsFile.cs @@ -73,7 +73,7 @@ public partial class GetAzureRmRecoveryServicesVaultSettingsFile : RecoveryServi /// /// Gets or sets vault Object. /// - [Parameter(Mandatory = true, Position = 2)] + [Parameter(Position = 2)] public string Path { get; set; } /// From 13edbe5c05310e852a465c36c336a8300622d0ce Mon Sep 17 00:00:00 2001 From: pikumarmsft Date: Tue, 12 Apr 2016 18:37:54 +0530 Subject: [PATCH 08/10] Adding strings to resex file --- .../Properties/Resources.Designer.cs | 54 +++++++++++++++++++ .../Properties/Resources.resx | 18 +++++++ ...zureRMRecoveryServicesVaultSettingsFile.cs | 13 ++--- 3 files changed, 79 insertions(+), 6 deletions(-) diff --git a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Properties/Resources.Designer.cs b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Properties/Resources.Designer.cs index 9e9061c1ad0b..31ae6ced6777 100644 --- a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Properties/Resources.Designer.cs +++ b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Properties/Resources.Designer.cs @@ -69,6 +69,15 @@ internal static string AzureVMNetworkIsNotAssociatedWithTheSubscription { } } + /// + /// Looks up a localized string similar to RecoveryService - Backup Vault - Successfully serialized the file content. + /// + internal static string BackupVaultSerialized { + get { + return ResourceManager.GetString("BackupVaultSerialized", resourceCulture); + } + } + /// /// Looks up a localized string similar to Operation Failed. ///. @@ -106,6 +115,15 @@ internal static string DisableProtectionWhatIfMessage { } } + /// + /// Looks up a localized string similar to Executing cmdlet with SubscriptionId = {0}, ResourceGroupName = {1}, ResourceName = {2}, TargetLocation = {3}. + /// + internal static string ExecutingGetVaultCredCmdlet { + get { + return ResourceManager.GetString("ExecutingGetVaultCredCmdlet", resourceCulture); + } + } + /// /// Looks up a localized string similar to Calls using ID based parameter {0} will not be supported from next release. Please use its corresponding full object parameter instead.. /// @@ -368,6 +386,15 @@ internal static string ResourceNameNullOrEmpty { } } + /// + /// Looks up a localized string similar to Saving Vault Credentials to file : {0}. + /// + internal static string SavingVaultCred { + get { + return ResourceManager.GetString("SavingVaultCred", resourceCulture); + } + } + /// /// Looks up a localized string similar to Server {0} is not associated with the Vault {1}. /// @@ -441,6 +468,24 @@ internal static string SubscriptionIsNotAssociatedWithTheAccount { } } + /// + /// Looks up a localized string similar to RecoveryService - Successfully uploaded the certificate. + /// + internal static string UploadedCertToIdmgmt { + get { + return ResourceManager.GetString("UploadedCertToIdmgmt", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to RecoveryService - Going to upload the certificate. + /// + internal static string UploadingCertToIdmgmt { + get { + return ResourceManager.GetString("UploadingCertToIdmgmt", resourceCulture); + } + } + /// /// Looks up a localized string similar to Could not validate the storage account and subscription given. ///Are you sure you want to continue {0}?. @@ -469,6 +514,15 @@ internal static string VaultCreationSuccessMessage { } } + /// + /// Looks up a localized string similar to The target location provided is not a directory. Please provide a directory.. + /// + internal static string VaultCredPathException { + get { + return ResourceManager.GetString("VaultCredPathException", resourceCulture); + } + } + /// /// Looks up a localized string similar to Vault has been deleted. /// diff --git a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Properties/Resources.resx b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Properties/Resources.resx index feef11f65291..783bbe796ff6 100644 --- a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Properties/Resources.resx +++ b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Properties/Resources.resx @@ -277,4 +277,22 @@ Please provide a storage account with the same location as that of the vault. Site {0} is not associated with the Vault {1} + + RecoveryService - Backup Vault - Successfully serialized the file content + + + Executing cmdlet with SubscriptionId = {0}, ResourceGroupName = {1}, ResourceName = {2}, TargetLocation = {3} + + + Saving Vault Credentials to file : {0} + + + RecoveryService - Successfully uploaded the certificate + + + RecoveryService - Going to upload the certificate + + + The target location provided is not a directory. Please provide a directory. + \ No newline at end of file diff --git a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRMRecoveryServicesVaultSettingsFile.cs b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRMRecoveryServicesVaultSettingsFile.cs index f976d53c187b..a48e7cf0962e 100644 --- a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRMRecoveryServicesVaultSettingsFile.cs +++ b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRMRecoveryServicesVaultSettingsFile.cs @@ -24,6 +24,7 @@ using System.Text; using System.Globalization; using Microsoft.Azure.Management.RecoveryServices.Models; +using Microsoft.Azure.Commands.RecoveryServices.Properties; namespace Microsoft.Azure.Commands.RecoveryServices { @@ -196,14 +197,14 @@ public void GetAzureRMRecoveryServicesVaultBackupCredentials() string targetLocation = string.IsNullOrEmpty(this.Path) ? Utilities.GetDefaultPath() : this.Path; if (!Directory.Exists(targetLocation)) { - throw new ArgumentException("The target location provided is not a directory. Please provide a directory."); + throw new ArgumentException(Resources.VaultCredPathException); } string subscriptionId = DefaultContext.Subscription.Id.ToString(); string displayName = this.Vault.Name; WriteDebug(string.Format(CultureInfo.InvariantCulture, - "Executing cmdlet with SubscriptionId = {0}, ResourceGroupName = {1}, ResourceName = {2}, TargetLocation = {3}", + Resources.ExecutingGetVaultCredCmdlet, subscriptionId, this.Vault.ResouceGroupName, this.Vault.Name, targetLocation)); // Generate certificate @@ -214,9 +215,9 @@ public void GetAzureRMRecoveryServicesVaultBackupCredentials() try { // Upload cert into ID Mgmt - WriteDebug(string.Format(CultureInfo.InvariantCulture, "RecoveryService - Going to upload the certificate")); + WriteDebug(string.Format(CultureInfo.InvariantCulture, Resources.UploadingCertToIdmgmt)); acsNamespace = UploadCert(cert); - WriteDebug(string.Format(CultureInfo.InvariantCulture, "RecoveryService - Successfully uploaded the certificate")); + WriteDebug(string.Format(CultureInfo.InvariantCulture, Resources.UploadedCertToIdmgmt)); } catch (Exception exception) { @@ -235,7 +236,7 @@ public void GetAzureRMRecoveryServicesVaultBackupCredentials() // prepare for download string fileName = string.Format("{0}_{1:ddd MMM dd yyyy}.VaultCredentials", displayName, DateTime.UtcNow); string filePath = System.IO.Path.Combine(targetLocation, fileName); - WriteDebug(string.Format("Saving Vault Credentials to file : {0}", filePath)); + WriteDebug(string.Format(Resources.SavingVaultCred, filePath)); File.WriteAllBytes(filePath, Encoding.UTF8.GetBytes(vaultCredsFileContent)); @@ -301,7 +302,7 @@ private string GenerateVaultCredsForBackup(X509Certificate2 cert, string subscri DataContractSerializer serializer = new DataContractSerializer(typeof(BackupVaultCreds)); serializer.WriteObject(writer, backupVaultCreds); - WriteDebug(string.Format(CultureInfo.InvariantCulture, "RecoveryService - Backup Vault - Successfully serialized the file content")); + WriteDebug(string.Format(CultureInfo.InvariantCulture, Resources.BackupVaultSerialized)); } return Encoding.UTF8.GetString(output.ToArray()); From 8b6c206c3f949d32ef6875e056b68b619a273ac9 Mon Sep 17 00:00:00 2001 From: pikumarmsft Date: Wed, 13 Apr 2016 10:59:15 +0530 Subject: [PATCH 09/10] minor fix as per PR comments --- .../PSRecoveryServicesVaultExtendedInfoClient.cs | 5 +++-- .../GetAzureRMRecoveryServicesVaultSettingsFile.cs | 12 +++++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Common/PSRecoveryServicesVaultExtendedInfoClient.cs b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Common/PSRecoveryServicesVaultExtendedInfoClient.cs index 7761516bc5a2..8eadcc529135 100644 --- a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Common/PSRecoveryServicesVaultExtendedInfoClient.cs +++ b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Common/PSRecoveryServicesVaultExtendedInfoClient.cs @@ -128,8 +128,9 @@ public ASRVaultCreds GenerateVaultCredential(X509Certificate2 managementCert, AR /// /// Upload cert to idmgmt /// - /// - /// + /// certificate to be uploaded + /// vault object + /// Upload Certificate Response public UploadCertificateResponse UploadCertificate(X509Certificate2 managementCert, ARSVault vault) { var certificateArgs = new CertificateArgs(); diff --git a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRMRecoveryServicesVaultSettingsFile.cs b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRMRecoveryServicesVaultSettingsFile.cs index a48e7cf0962e..ceb5820041c9 100644 --- a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRMRecoveryServicesVaultSettingsFile.cs +++ b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRMRecoveryServicesVaultSettingsFile.cs @@ -32,8 +32,8 @@ namespace Microsoft.Azure.Commands.RecoveryServices /// Retrieves Azure Recovery Services Vault Settings File. /// [Cmdlet(VerbsCommon.Get, "AzureRmRecoveryServicesVaultSettingsFile")] - [OutputType(typeof(VaultSettingsFilePath), typeof(string))] - public partial class GetAzureRmRecoveryServicesVaultSettingsFile : RecoveryServicesCmdletBase + [OutputType(typeof(VaultSettingsFilePath))] + public class GetAzureRmRecoveryServicesVaultSettingsFile : RecoveryServicesCmdletBase { /// /// Expiry in hours for generated certificate. @@ -192,6 +192,9 @@ private string GenerateFileName() } #region Backup Vault Credentials + /// + /// Get vault credentials for backup vault type. + /// public void GetAzureRMRecoveryServicesVaultBackupCredentials() { string targetLocation = string.IsNullOrEmpty(this.Path) ? Utilities.GetDefaultPath() : this.Path; @@ -253,7 +256,6 @@ public void GetAzureRMRecoveryServicesVaultBackupCredentials() /// Upload certificate /// /// management certificate - /// subscription Id /// acs namespace of the uploaded cert private AcsNamespace UploadCert(X509Certificate2 cert) { @@ -309,6 +311,10 @@ private string GenerateVaultCredsForBackup(X509Certificate2 cert, string subscri } } + /// + /// Get Agent Links + /// + /// Agent links in string format private static string GetAgentLinks() { return "WABUpdateKBLink,http://go.microsoft.com/fwlink/p/?LinkId=229525;" + From 196bfd36c31ffa9b5e7e6419c8371230850cb917 Mon Sep 17 00:00:00 2001 From: pikumarmsft Date: Wed, 13 Apr 2016 18:29:21 +0530 Subject: [PATCH 10/10] Making SiteRecovery as optional --- ...zureRMRecoveryServicesVaultSettingsFile.cs | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRMRecoveryServicesVaultSettingsFile.cs b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRMRecoveryServicesVaultSettingsFile.cs index ceb5820041c9..37b3b6e701a8 100644 --- a/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRMRecoveryServicesVaultSettingsFile.cs +++ b/src/ResourceManager/RecoveryServices/Commands.RecoveryServices/Vault/GetAzureRMRecoveryServicesVaultSettingsFile.cs @@ -50,7 +50,7 @@ public class GetAzureRmRecoveryServicesVaultSettingsFile : RecoveryServicesCmdle /// /// Gets or sets vault Object. /// - [Parameter(ValueFromPipeline = true, Position = 1)] + [Parameter(Mandatory = true, ValueFromPipeline = true, Position = 1)] [ValidateNotNullOrEmpty] public ARSVault Vault { get; set; } @@ -83,14 +83,14 @@ public class GetAzureRmRecoveryServicesVaultSettingsFile : RecoveryServicesCmdle /// /// Gets or sets vault Object. /// - [Parameter(ParameterSetName = ASRParameterSets.ByDefault, Mandatory = true)] - [Parameter(ParameterSetName = ASRParameterSets.ForSite, Mandatory = true)] - public SwitchParameter ASR + [Parameter(ParameterSetName = ASRParameterSets.ByDefault, Mandatory = false)] + [Parameter(ParameterSetName = ASRParameterSets.ForSite, Mandatory = false)] + public SwitchParameter SiteRecovery { - get { return asr; } - set { asr = value; } + get { return siteRecovery; } + set { siteRecovery = value; } } - private bool asr; + private bool siteRecovery; /// /// Gets or sets the path where the credential file is to be generated @@ -115,14 +115,15 @@ public override void ExecuteCmdlet() { try { - if (asr) - { - this.GetVaultSettingsFile(); - } if (backup) { this.GetAzureRMRecoveryServicesVaultBackupCredentials(); } + else + { + this.GetVaultSettingsFile(); + } + } catch (AggregateException aggregateEx) {