internal void WriteProvisioningManifestXml(XmlWriter xmlWriter, ProvisionConfigExternalDirectorySync provisionConfig) { xmlWriter.WriteStartElement("SiteProvisioning"); WriteProvisioningManifestXml_SiteMembership(xmlWriter, provisionConfig); WriteProvisioningManifestXml_GroupsMembership(xmlWriter, provisionConfig); xmlWriter.WriteEndElement(); }
internal void GenerateProvisioningManifestFile(string provisioningManifest, ProvisionConfigExternalDirectorySync provisionConfig) { var xmlWriter = XmlWriter.Create(provisioningManifest); WriteProvisioningManifestXml(xmlWriter, provisionConfig); xmlWriter.Close(); }
/// <summary> /// Output the site membership block /// </summary> /// <param name="xmlWriter"></param> private void WriteProvisioningManifestXml_SiteMembership(XmlWriter xmlWriter, ProvisionConfigExternalDirectorySync provisionConfig) { xmlWriter.WriteStartElement("SiteMembership"); //-------------------------------------------------------------------------------- //Write the provisioning instructions into the XML //-------------------------------------------------------------------------------- //Modify existing users? //1. xmlWriter.WriteAttributeString( ProvisionUserInstructions.XmlAttribute_authDefaultExistingUsers, ProvisionUserInstructions.XmlAttributeText(provisionConfig.ActionForExistingDefaultAuthUsers)); //2. xmlWriter.WriteAttributeString( ProvisionUserInstructions.XmlAttribute_authSamlExistingUsers, ProvisionUserInstructions.XmlAttributeText(provisionConfig.ActionForExistingSamlUsers)); //3. xmlWriter.WriteAttributeString( ProvisionUserInstructions.XmlAttribute_authOpenIdExistingUsers, ProvisionUserInstructions.XmlAttributeText(provisionConfig.ActionForExistingOpenIdUsers)); //Modify missing users //1. xmlWriter.WriteAttributeString( ProvisionUserInstructions.XmlAttribute_authDefaultMissingUsers, ProvisionUserInstructions.XmlAttributeText(provisionConfig.ActionForMissingDefaultAuthUsers)); //2. xmlWriter.WriteAttributeString( ProvisionUserInstructions.XmlAttribute_authSamlMissingUsers, ProvisionUserInstructions.XmlAttributeText(provisionConfig.ActionForMissingSamlUsers)); //3. xmlWriter.WriteAttributeString( ProvisionUserInstructions.XmlAttribute_authOpenIdMissingUsers, ProvisionUserInstructions.XmlAttributeText(provisionConfig.ActionForMissingOpenIdUsers)); //Unlicese unexptected users //1. xmlWriter.WriteAttributeString( ProvisionUserInstructions.XmlAttribute_authDefaultUnexpectedUsers, ProvisionUserInstructions.XmlAttributeText(provisionConfig.ActionForUnexpectedDefaultAuthUsers)); //2. xmlWriter.WriteAttributeString( ProvisionUserInstructions.XmlAttribute_authSamlUnexpectedUsers, ProvisionUserInstructions.XmlAttributeText(provisionConfig.ActionForUnexpectedSamlUsers)); //3. xmlWriter.WriteAttributeString( ProvisionUserInstructions.XmlAttribute_authOpenIdUnexpectedUsers, ProvisionUserInstructions.XmlAttributeText(provisionConfig.ActionForUnexpectedOpenIdUsers)); //Write out all the users RolesManager.WriteUserRolesAsXml(xmlWriter); xmlWriter.WriteEndElement(); }
/// <summary> /// Take all the User->Role/Auth mappings, and all the Group memberships and create a provisioning manifest XML file /// </summary> /// <param name="provisioningManifest"></param> /// <param name="provisionConfig"></param> internal void GenerateProvisioningManifestFile(string provisioningManifest, ProvisionConfigExternalDirectorySync provisionConfig) { var xmlWriter = new XmlTextWriter(provisioningManifest, System.Text.Encoding.UTF8); using (xmlWriter) { xmlWriter.Formatting = Formatting.Indented; //Let's make it human readable WriteProvisioningManifestXml(xmlWriter, provisionConfig); xmlWriter.Close(); } }
/// <summary> /// Constructor: From XML /// </summary> /// <param name="xmlNode"></param> public SynchronizePatternMatchingGroupToGroup(XmlNode xmlNode) { this.SourceGroupName = xmlNode.Attributes[ProvisionConfigExternalDirectorySync.SynchronizeGroupToGroup.XmlAttribute_SoruceGroup].Value; this.NamePatternMatch = ProvisionConfigExternalDirectorySync.ParseNamePatternMatch( XmlHelper.SafeParseXmlAttribute(xmlNode, XmlAttribute_SourceGroupMatch, NamePatternMatch_Equals)); //An optional filter to apply this.FilterSourceGroupNameContains = XmlHelper.SafeParseXmlAttribute(xmlNode, XmlAttribute_FilterSourceGroupContains, ""); //Read in the grant license attributes ProvisioningGroup.ReadGrantLicenseXmlAttributes( xmlNode, this.SourceGroupName, out this.GrantLicenseInstructions, out this.GrantLicenseRole); }
/// <summary> /// Output the groups membership block /// </summary> /// <param name="xmlWriter"></param> private void WriteProvisioningManifestXml_GroupsMembership(XmlWriter xmlWriter, ProvisionConfigExternalDirectorySync provisionConfig) { xmlWriter.WriteStartElement("GroupsMemberships"); //-------------------------------------------------------------------------------- //Write the provisioning instructions into the XML //-------------------------------------------------------------------------------- //Missing group members? xmlWriter.WriteAttributeString( ProvisionUserInstructions.XmlAttribute_MissingGroupMembers, ProvisionUserInstructions.XmlAttributeText(provisionConfig.ActionForGroupMisingMembers)); //Unexpected group members? xmlWriter.WriteAttributeString( ProvisionUserInstructions.XmlAttribute_UnexpectedGroupMembers, ProvisionUserInstructions.XmlAttributeText(provisionConfig.ActionForGroupUnexpectedMembers)); //Write out all the groups GroupsMembershipManager.WriteUserGroupsAsXml(xmlWriter); xmlWriter.WriteEndElement(); }
/// <summary> /// Constructor /// </summary> /// <param name="config"></param> /// <param name="configSyncGroups"></param> /// <param name="showLogsHere"></param> /// <param name="statusLogs"></param> /// <param name="csvDataGenerator"></param> public AzureDownload( AzureAdConfig config, ProvisionConfigExternalDirectorySync configSyncGroups, IShowLogs showLogsHere, TaskStatusLogs statusLogs, CsvDataGenerator csvDataGenerator) { _showLogsHere = showLogsHere; _configAzure = config; _configSyncGroups = configSyncGroups; if (statusLogs == null) { statusLogs = new TaskStatusLogs(); } _statusLogs = statusLogs; //Either use one passed in, or create one if (csvDataGenerator == null) { csvDataGenerator = new CsvDataGenerator(); } _csvProvisionResults = csvDataGenerator; }
/// <summary> /// Generate a maniefest file based on the current Online site /// </summary> /// <param name="statusLogs"></param> /// <param name="pathSecrets"></param> /// <param name="pathOutputFile"></param> /// <param name="ignoreAllUsersGroup">(recommend TRUE) If false, the manifest file will contain the "all users" group</param> private void GenerateManifestFromOnlineSite( TaskStatusLogs statusLogs, string pathSecrets, string pathOutputFile, bool ignoreAllUsersGroup) { var pathOutputs = Path.GetDirectoryName(pathOutputFile); ProvisionConfigSiteAccess secretsConfig; //=========================================================================================== //Get the sign in information //=========================================================================================== try { //Load the config from the files secretsConfig = new ProvisionConfigSiteAccess(pathSecrets); } catch (Exception exSignInConfig) { statusLogs.AddError("Error loading sign in config file"); throw new Exception("1012-327: Error parsing sign in config, " + exSignInConfig.Message); } //=========================================================================================== //Create a place for out output files //=========================================================================================== FileIOHelper.CreatePathIfNeeded(pathOutputs); var provisionSettings = ProvisionConfigExternalDirectorySync.FromDefaults(); //=========================================================================================== //Download all the data we need from the Tableau Online site //=========================================================================================== statusLogs.AddStatusHeader("Retrieving information from Tableau"); UpdateStatusText(statusLogs); var tableauDownload = new TableauProvisionDownload( secretsConfig, this, statusLogs, ignoreAllUsersGroup); try { tableauDownload.Execute(); } catch (Exception exTableauDownload) { statusLogs.AddError("Error retrieving data from Tableau"); throw new Exception("813-0148: Error in Tableau Download, " + exTableauDownload.Message); } //=========================================================================================== //Write the provisioning manifest out to a file //=========================================================================================== statusLogs.AddStatusHeader("Writing out manifest file for Tableau provisioning"); UpdateStatusText(statusLogs); var outputProvisioningRoles = tableauDownload.ProvisioningManifestResults; try { outputProvisioningRoles.GenerateProvisioningManifestFile(pathOutputFile, provisionSettings); } catch (Exception exWriteProvisioningManifest) { statusLogs.AddError("Error creating provisioning manifest"); throw new Exception("1012-252: Error writing provisioning manifest, " + exWriteProvisioningManifest.Message); } }
/// <summary> /// Run the provisioning pulling from AzureAD /// </summary> /// <param name="pathSecrets"></param> /// <param name="pathProvisionPlan"></param> private void ProvisionFromAzureAd( TaskStatusLogs statusLogs, string pathSecrets, string pathProvisionPlan, bool deployToTableauTarget, string pathOutputs) { //=========================================================================================== //Create a place for out output files //=========================================================================================== FileIOHelper.CreatePathIfNeeded(pathOutputs); AzureAdConfig configSignInAzure; ProvisionConfigExternalDirectorySync configGroupsMapping; //=========================================================================================== //Get the sign in information //=========================================================================================== try { //Load the config from the files configSignInAzure = new AzureAdConfig(pathSecrets); } catch (Exception exSignInConfig) { statusLogs.AddError("Error loading sign in config file. Error: " + exSignInConfig.Message); throw new Exception("813-1212: Error parsing sign in config, " + exSignInConfig.Message); } //=========================================================================================== //Get the Groups/Roles mapping information //=========================================================================================== try { configGroupsMapping = new ProvisionConfigExternalDirectorySync(pathProvisionPlan); } catch (Exception exGroupsMapping) { statusLogs.AddError("Error loading sync groups provisioning file. Error: " + exGroupsMapping.Message); throw new Exception("813-1214: Error parsing sync groups, " + exGroupsMapping.Message); } //=========================================================================================== //Download all the data we need from Azure //=========================================================================================== statusLogs.AddStatusHeader("Retrieving information from Azure AD"); UpdateStatusText(statusLogs); var azureDownload = new AzureDownload(configSignInAzure, configGroupsMapping, this, statusLogs, null); try { azureDownload.Execute(); //Sanity test IwsDiagnostics.Assert(azureDownload.IsExecuteComplete.Value, "813-834: Internal error. Async work still running"); } catch (Exception exAzureDownload) { statusLogs.AddError("Error retrieving data from Azure AD. Error: " + exAzureDownload.Message); throw new Exception("813-0148: Error in Azure Download, " + exAzureDownload.Message); } //=========================================================================================== //Write the provisioning manifest out to an intermediary file //=========================================================================================== statusLogs.AddStatusHeader("Writing out manifest file for Tableau provisioning"); UpdateStatusText(statusLogs); var outputProvisioningRoles = azureDownload.ProvisioningManifestResults; string provisioningManifest = Path.Combine(pathOutputs, "ProvisioningManifest.xml"); try { outputProvisioningRoles.GenerateProvisioningManifestFile(provisioningManifest, configGroupsMapping); } catch (Exception exWriteProvisioningManifest) { statusLogs.AddError("Error creating provisioning manifest. Error: " + exWriteProvisioningManifest.Message); throw new Exception("813-739: Error writing provisioning manifest, " + exWriteProvisioningManifest.Message); } //================================================================================================= //See if this is a test run, or whether we want to actually deploy the provisioning //================================================================================================= if (deployToTableauTarget) { //=========================================================================================== //Provision the Tableau site using the manifest file we just created //=========================================================================================== statusLogs.AddStatusHeader("Provision Tableau site using generated manifest file"); UpdateStatusText(statusLogs); try { ProvisionFromFileManifest(statusLogs, pathSecrets, provisioningManifest, pathOutputs); } catch (Exception exProvisionSite) { statusLogs.AddError("Error provisioning Tableau Online site. Error: " + exProvisionSite.Message); throw new Exception("814-353: Error provisioning Tableau Online site, " + exProvisionSite.Message); } } else { statusLogs.AddStatusHeader("Skipping Tableau site provisioning step (generate manifest only)"); } }