/// <summary> /// Method to generate the credential file content /// </summary> /// <param name="managementCert">management cert</param> /// <param name="acsDetails">ACS details</param> /// <param name="channelIntegrityKey">Integrity key</param> /// <param name="vault">vault object</param> /// <param name="site">site object</param> /// <returns>vault credential object</returns> private ASRVaultCreds GenerateCredentialObject( X509Certificate2 managementCert, VaultCertificateResponse acsDetails, string channelIntegrityKey, ARSVault vault, ASRSite site) { string serializedCertificate = Convert.ToBase64String(managementCert.Export(X509ContentType.Pfx)); AcsNamespace acsNamespace = new AcsNamespace(acsDetails.Properties as ResourceCertificateAndAcsDetails); string resourceProviderNamespace = string.Empty; string resourceType = string.Empty; Utilities.GetResourceProviderNamespaceAndType(vault.ID, out resourceProviderNamespace, out resourceType); ASRVaultCreds vaultCreds = new ASRVaultCreds( vault.SubscriptionId, vault.Name, serializedCertificate, acsNamespace, channelIntegrityKey, vault.ResourceGroupName, site.ID, site.Name, resourceProviderNamespace, resourceType, vault.Location); return(vaultCreds); }
/// <summary> /// Gets the vault credential object /// </summary> /// <param name="managementCert">certificate to be uploaded</param> /// <param name="vault">vault object</param> /// <param name="site">site object</param> /// <param name="authType">authentication type</param> /// <returns>credential object</returns> public ASRVaultCreds GenerateVaultCredential( X509Certificate2 managementCert, ARSVault vault, ASRSite site, string authType) { ASRVaultCreds currentVaultContext = PSRecoveryServicesClient.arsVaultCreds; string resourceProviderNamespace = string.Empty; string resourceType = string.Empty; Utilities.GetResourceProviderNamespaceAndType(vault.ID, out resourceProviderNamespace, out resourceType); Logger.Instance.WriteDebug(string.Format( "GenerateVaultCredential resourceProviderNamespace = {0}, resourceType = {1}", resourceProviderNamespace, resourceType)); // Update vault settings with the working vault to generate file Utilities.UpdateCurrentVaultContext(new ASRVaultCreds() { ResourceGroupName = vault.ResourceGroupName, ResourceName = vault.Name, ResourceNamespace = resourceProviderNamespace, ARMResourceType = resourceType }); // Get Channel Integrity key string channelIntegrityKey; string getChannelIntegrityKey = this.GetCurrentVaultChannelIntegrityKey(); // Making sure we can generate the file, once the SDK and portal are inter-operable // upload certificate and fetch of ACIK can be made parallel to improvve the performace. // Upload certificate VaultCertificateResponse uploadCertificate = this.UpdateVaultCertificate( managementCert, authType); channelIntegrityKey = getChannelIntegrityKey; ASRVaultCreds arsVaultCreds = this.GenerateCredentialObject( managementCert, uploadCertificate, channelIntegrityKey, vault, site); // Update back the original vault settings Utilities.UpdateCurrentVaultContext(currentVaultContext); return(arsVaultCreds); }
/// <summary> /// Method to update vault certificate /// </summary> /// <param name="cert">certificate object </param> /// <returns>Upload Certificate Response</returns> private VaultCertificateResponse UpdateVaultCertificate(X509Certificate2 cert) { var certificateArgs = new CertificateRequest(); certificateArgs.Properties = new RawCertificateData(); certificateArgs.Properties.Certificate = cert.GetRawCertData(); certificateArgs.Properties.AuthType = AuthType.ACS; VaultCertificateResponse response = this.UpdateVaultCertificate(certificateArgs, cert.FriendlyName); return(response); }
/// <summary> /// Generates vault creds file content for backup Vault /// </summary> /// <param name="cert">management certificate</param> /// <param name="subscriptionId">subscription Id</param> /// <param name="acsNamespace">acs namespace</param> /// <returns>xml file in string format</returns> private string GenerateVaultCredsForBackup(X509Certificate2 cert, string subscriptionId, VaultCertificateResponse vaultCertificateResponse) { using (var output = new MemoryStream()) { using (var writer = XmlWriter.Create(output, GetXmlWriterSettings())) { ResourceCertificateAndAadDetails aadDetails = vaultCertificateResponse.Properties as ResourceCertificateAndAadDetails; RSBackupVaultAADCreds vaultCreds = new RSBackupVaultAADCreds() { SubscriptionId = subscriptionId, ResourceName = Vault.Name, ManagementCert = CertUtils.SerializeCert(cert, X509ContentType.Pfx), ResourceId = aadDetails.ResourceId.Value, AadAuthority = aadDetails.AadAuthority, AadTenantId = aadDetails.AadTenantId, ServicePrincipalClientId = aadDetails.ServicePrincipalClientId, IdMgmtRestEndpoint = aadDetails.AzureManagementEndpointAudience, ProviderNamespace = PSRecoveryServicesClient.ProductionRpNamespace, ResourceGroup = Vault.ResourceGroupName, Location = Vault.Location, Version = VaultCredentialVersionAad, ResourceType = RecoveryServicesVaultType, AgentLinks = GetAgentLinks() }; DataContractSerializer serializer = new DataContractSerializer(typeof(RSBackupVaultAADCreds)); serializer.WriteObject(writer, vaultCreds); WriteDebug(string.Format(CultureInfo.InvariantCulture, Resources.BackupVaultSerialized)); } return(Encoding.UTF8.GetString(output.ToArray())); } }
/// <summary> /// Generates vault creds file content for Site Recovery Vault /// </summary> /// <param name="cert">management certificate</param> /// <param name="subscriptionId">subscription Id</param> /// <param name="vaultCertificateResponse">vaultCertificate Response</param> /// <param name="asrSite">asrSite Info</param> /// <returns>xml file in string format</returns> private string GenerateVaultCredsForSiteRecovery(X509Certificate2 cert, string subscriptionId, VaultCertificateResponse vaultCertificateResponse, ASRSite asrSite) { using (var output = new MemoryStream()) { using (var writer = XmlWriter.Create(output, GetXmlWriterSettings())) { ResourceCertificateAndAadDetails aadDetails = vaultCertificateResponse.Properties as ResourceCertificateAndAadDetails; string resourceProviderNamespace = string.Empty; string resourceType = string.Empty; Utilities.GetResourceProviderNamespaceAndType(this.Vault.ID, out resourceProviderNamespace, out resourceType); Logger.Instance.WriteDebug(string.Format( "GenerateVaultCredential resourceProviderNamespace = {0}, resourceType = {1}", resourceProviderNamespace, resourceType)); // Update vault settings with the working vault to generate file Utilities.UpdateCurrentVaultContext(new ASRVaultCreds() { ResourceGroupName = this.Vault.ResourceGroupName, ResourceName = this.Vault.Name, ResourceNamespace = resourceProviderNamespace, ARMResourceType = resourceType }); //Code taken from Ibiza code string aadAudience = string.Format(CultureInfo.InvariantCulture, @"https://RecoveryServiceVault/{0}/{1}/{2}", Vault.Location, Vault.Name, aadDetails.ResourceId); RSVaultAsrCreds vaultCreds = new RSVaultAsrCreds() { VaultDetails = new ASRVaultDetails { SubscriptionId = subscriptionId, ResourceGroup = this.Vault.ResourceGroupName, ResourceName = this.Vault.Name, ResourceId = aadDetails.ResourceId.Value, Location = Vault.Location, ResourceType = RecoveryServicesVaultType, ProviderNamespace = PSRecoveryServicesClient.ProductionRpNamespace }, ManagementCert = CertUtils.SerializeCert(cert, X509ContentType.Pfx), Version = VaultCredentialVersionAad, AadDetails = new ASRVaultAadDetails { AadAuthority = aadDetails.AadAuthority, AadTenantId = aadDetails.AadTenantId, ServicePrincipalClientId = aadDetails.ServicePrincipalClientId, AadVaultAudience = aadAudience, ArmManagementEndpoint = aadDetails.AzureManagementEndpointAudience }, ChannelIntegrityKey = this.RecoveryServicesClient.GetCurrentVaultChannelIntegrityKey(), SiteId = asrSite.ID == null ? String.Empty : asrSite.ID, SiteName = asrSite.Name == null ? String.Empty : asrSite.Name }; DataContractSerializer serializer = new DataContractSerializer(typeof(RSVaultAsrCreds)); serializer.WriteObject(writer, vaultCreds); } return(Encoding.UTF8.GetString(output.ToArray())); } }
/// <summary> /// Generates vault creds file /// </summary> /// <param name="cert">management certificate</param> /// <param name="subscriptionId">subscription Id</param> /// <param name="acsNamespace">acs namespace</param> /// <returns>xml file in string format</returns> private string GenerateVaultCreds(X509Certificate2 cert, string subscriptionId, VaultCertificateResponse vaultCertificateResponse) { try { return(GenerateVaultCredsForBackup(cert, subscriptionId, vaultCertificateResponse)); } catch (Exception exception) { throw exception; } }
/// <summary> /// Get vault credentials for backup vault type. /// </summary> public void GetAzureRMRecoveryServicesVaultBackupCredentials() { string targetLocation = string.IsNullOrEmpty(this.Path) ? Utilities.GetDefaultPath() : this.Path; if (!Directory.Exists(targetLocation)) { throw new ArgumentException(Resources.VaultCredPathException); } string subscriptionId = DefaultContext.Subscription.Id.ToString(); string displayName = this.Vault.Name; WriteDebug(string.Format(CultureInfo.InvariantCulture, Resources.ExecutingGetVaultCredCmdlet, subscriptionId, this.Vault.ResourceGroupName, this.Vault.Name, targetLocation)); // Generate certificate X509Certificate2 cert = CertUtils.CreateSelfSignedCertificate( VaultCertificateExpiryInHoursForBackup, subscriptionId.ToString(), this.Vault.Name); VaultCertificateResponse vaultCertificateResponse = null; string channelIntegrityKey = string.Empty; try { // Upload cert into ID Mgmt WriteDebug(string.Format(CultureInfo.InvariantCulture, Resources.UploadingCertToIdmgmt)); vaultCertificateResponse = UploadCert(cert); WriteDebug(string.Format(CultureInfo.InvariantCulture, Resources.UploadedCertToIdmgmt)); } catch (Exception exception) { throw exception; } // generate vault credentials string vaultCredsFileContent = GenerateVaultCreds(cert, subscriptionId, vaultCertificateResponse); // 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(Resources.SavingVaultCred, filePath)); File.WriteAllBytes(filePath, Encoding.UTF8.GetBytes(vaultCredsFileContent)); VaultSettingsFilePath output = new VaultSettingsFilePath() { FilePath = filePath, }; // Output filename back to user WriteObject(output); }
/// <summary> /// Method to execute the command /// </summary> private void GetSiteRecoveryCredentials() { IAzureSubscription subscription = DefaultProfile.DefaultContext.Subscription; // Generate certificate X509Certificate2 cert = CertUtils.CreateSelfSignedCertificate( VaultCertificateExpiryInHoursForHRM, subscription.Id.ToString(), this.Vault.Name); ASRSite site = new ASRSite(); if (!string.IsNullOrEmpty(this.SiteIdentifier) && !string.IsNullOrEmpty(this.SiteFriendlyName)) { site.ID = this.SiteIdentifier; site.Name = this.SiteFriendlyName; } string fileName = this.GenerateFileName(); string filePath = string.IsNullOrEmpty(this.Path) ? Utilities.GetDefaultPath() : this.Path; // Generate file. if (RecoveryServicesClient.getVaultAuthType(this.Vault.ResourceGroupName, this.Vault.Name) == 0) { ASRVaultCreds vaultCreds = RecoveryServicesClient.GenerateVaultCredential( cert, this.Vault, site, AuthType.ACS); // write the content to a file. VaultSettingsFilePath output = new VaultSettingsFilePath() { FilePath = Utilities.WriteToFile <ASRVaultCreds>(vaultCreds, filePath, fileName) }; // print the path to the user. this.WriteObject(output, true); } else { string fullFilePath = System.IO.Path.Combine(filePath, fileName); WriteDebug( string.Format( CultureInfo.InvariantCulture, Resources.ExecutingGetVaultCredCmdlet, subscription.Id, this.Vault.ResourceGroupName, this.Vault.Name, fullFilePath)); VaultCertificateResponse vaultCertificateResponse = null; try { // Upload cert into ID Mgmt WriteDebug(string.Format(CultureInfo.InvariantCulture, Resources.UploadingCertToIdmgmt)); vaultCertificateResponse = UploadCert(cert); WriteDebug(string.Format(CultureInfo.InvariantCulture, Resources.UploadedCertToIdmgmt)); // generate vault credentials string vaultCredsFileContent = GenerateVaultCredsForSiteRecovery( cert, subscription.Id, vaultCertificateResponse, site); WriteDebug(string.Format(Resources.SavingVaultCred, fullFilePath)); File.WriteAllBytes(fullFilePath, Encoding.UTF8.GetBytes(vaultCredsFileContent)); VaultSettingsFilePath output = new VaultSettingsFilePath() { FilePath = fullFilePath, }; // Output filename back to user WriteObject(output, true); } catch (Exception exception) { throw exception; } } }
/// <summary> /// Generates vault creds file /// </summary> /// <param name="cert">management certificate</param> /// <param name="subscriptionId">subscription Id</param> /// <param name="acsNamespace">acs namespace</param> /// <returns>xml file in string format</returns> private string GenerateVaultCreds(X509Certificate2 cert, string subscriptionId, VaultCertificateResponse vaultCertificateResponse) { try { var certString = CertUtils.SerializeCert(cert, X509ContentType.Pfx); return(GenerateVaultCredsForBackup(certString, subscriptionId, vaultCertificateResponse)); } catch (Exception exception) { throw exception; } }
private void GetSiteRecoveryCredentialsWithCertificate(string certificate) { string subscriptionId = DefaultContext.Subscription.Id.ToString(); VaultCertificateResponse vaultCertificateResponse = null; ASRSite site = new ASRSite(); if (!string.IsNullOrEmpty(this.SiteIdentifier) && !string.IsNullOrEmpty(this.SiteFriendlyName)) { site.ID = this.SiteIdentifier; site.Name = this.SiteFriendlyName; } try { string fileName = this.GenerateFileName(); string filePath = string.IsNullOrEmpty(this.Path) ? Utilities.GetDefaultPath() : this.Path; string fullFilePath = System.IO.Path.Combine(filePath, fileName); // Upload cert into ID Mgmt WriteDebug(string.Format(CultureInfo.InvariantCulture, Resources.UploadingCertToIdmgmt)); byte[] bytes = Encoding.ASCII.GetBytes(certificate); var certificateArgs = new CertificateRequest(); certificateArgs.Properties = new RawCertificateData(); certificateArgs.Properties.Certificate = bytes; certificateArgs.Properties.AuthType = AuthType.AAD; string dateString = DateTime.Now.ToString("M-d-yyyy"); var friendlyName = string.Format("{0}{1}-{2}-vaultcredentials", this.Vault.Name, subscriptionId, dateString); vaultCertificateResponse = RecoveryServicesClient.GetRecoveryServicesClient.VaultCertificates.CreateWithHttpMessagesAsync( this.Vault.ResourceGroupName, this.Vault.Name, friendlyName, certificateArgs, RecoveryServicesClient.GetRequestHeaders()).Result.Body; WriteDebug(string.Format(CultureInfo.InvariantCulture, Resources.UploadedCertToIdmgmt)); string vaultCredsFileContent = GenerateVaultCredsForSiteRecovery( certificate, subscriptionId, vaultCertificateResponse, site); WriteDebug(string.Format(Resources.SavingVaultCred, fullFilePath)); AzureSession.Instance.DataStore.WriteFile(fullFilePath, Encoding.UTF8.GetBytes(vaultCredsFileContent)); VaultSettingsFilePath output = new VaultSettingsFilePath() { FilePath = fullFilePath, }; // Output filename back to user WriteObject(output, true); } catch (Exception exception) { throw exception; } }
/// <summary> /// Method to execute the command /// </summary> private void GetBackupCredentialsWithCertificate(string certificate) { // for .netStandard string targetLocation = string.IsNullOrEmpty(this.Path) ? Utilities.GetDefaultPath() : this.Path; if (!Directory.Exists(targetLocation)) { throw new ArgumentException(Resources.VaultCredPathException); } string subscriptionId = DefaultContext.Subscription.Id.ToString(); string displayName = this.Vault.Name; WriteDebug(string.Format(CultureInfo.InvariantCulture, Resources.ExecutingGetVaultCredCmdlet, subscriptionId, this.Vault.ResourceGroupName, this.Vault.Name, targetLocation)); VaultCertificateResponse vaultCertificateResponse = null; string channelIntegrityKey = string.Empty; try { // Upload cert into ID Mgmt WriteDebug(string.Format(CultureInfo.InvariantCulture, Resources.UploadingCertToIdmgmt)); byte[] bytes = Encoding.ASCII.GetBytes(certificate); var certificateArgs = new CertificateRequest(); certificateArgs.Properties = new RawCertificateData(); certificateArgs.Properties.Certificate = bytes; certificateArgs.Properties.AuthType = AuthType.AAD; string dateString = DateTime.Now.ToString("M-d-yyyy"); var friendlyName = string.Format("{0}{1}-{2}-vaultcredentials", this.Vault.Name, subscriptionId, dateString); vaultCertificateResponse = RecoveryServicesClient.GetRecoveryServicesClient.VaultCertificates.CreateWithHttpMessagesAsync( this.Vault.ResourceGroupName, this.Vault.Name, friendlyName, certificateArgs, RecoveryServicesClient.GetRequestHeaders()).Result.Body; WriteDebug(string.Format(CultureInfo.InvariantCulture, Resources.UploadedCertToIdmgmt)); } catch (Exception exception) { throw exception; } // generate vault credentials string vaultCredsFileContent = GenerateVaultCredsForBackup(certificate, subscriptionId, vaultCertificateResponse); // 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(Resources.SavingVaultCred, filePath)); AzureSession.Instance.DataStore.WriteFile(filePath, Encoding.UTF8.GetBytes(vaultCredsFileContent)); VaultSettingsFilePath output = new VaultSettingsFilePath() { FilePath = filePath, }; // Output filename back to user WriteObject(output); }
/// <summary> /// Upload certificate /// </summary> /// <param name="cert">management certificate</param> /// <returns>acs namespace of the uploaded cert</returns> private AcsNamespace UploadCert(X509Certificate2 cert) { VaultCertificateResponse response = RecoveryServicesClient.UploadCertificate(cert, this.Vault); return(new AcsNamespace(response.Properties as ResourceCertificateAndAcsDetails)); }