Beispiel #1
0
    /// <summary>
    /// Inner wrapper for async operations
    /// </summary>
    /// <returns></returns>
    private async Task Execute_Async()
    {
        var azureGraphSession = AzureGetGraphSession();

        //===================================================================================
        //Get Groups that map to Tableau Site User Roles from Azure
        //===================================================================================
        _statusLogs.AddStatus("Azure: Getting user roles groups");
        await GenerateUsersRolesList_FromAzureGroupsSyncList(azureGraphSession, _configSyncGroups.GroupsToRolesSyncList);

        //===================================================================================
        //Get Groups that map to Tableau Site Groups from Azure
        //===================================================================================
        _statusLogs.AddStatus("Azure: Getting user roles groups");
        await GenerateGroupsMembersList_FromAzureGroupsSyncList(azureGraphSession, _configSyncGroups.GroupsToGroupsSyncList);

        //===================================================================================
        //Now perform any replace/override operations we need to based on explicit users
        //===================================================================================
        _statusLogs.AddStatus("Replacing any explicit user/role overrides");
        foreach (var thisOverrideUser in _configSyncGroups.UserRolesOverrideList)
        {
            SetManagerForRoles.AddAndForceReplaceUser(thisOverrideUser);
        }

        //Mark the work status as complete
        IsExecuteComplete.Trigger();
    }
Beispiel #2
0
        private void btnProvisionFromAzureAd_Click(object sender, EventArgs e)
        {
            var statusLogs = new TaskStatusLogs();

            statusLogs.AddStatus("Starting...");
            UpdateStatusText(statusLogs, true);

            string pathSecrets = txtPathToSecrets.Text;

            if (!File.Exists(pathSecrets))
            {
                MessageBox.Show("Secrets file does not exist at specified path (" + pathSecrets + ")");
                return;
            }


            string pathProvisionPlan = txtPathToAzureAdProvisioningConfig.Text;

            if (!File.Exists(pathProvisionPlan))
            {
                MessageBox.Show("Config file does not exist at specified path (" + pathProvisionPlan + ")");
                return;
            }

            string pathOutput =
                Path.Combine(
                    Path.GetDirectoryName(pathProvisionPlan),
                    "out");

            FileIOHelper.CreatePathIfNeeded(pathOutput);

            //Show the user a command line that they can use to run this same work
            GenerateProvisioningCommandLine(
                CommandLineParser.Command_ProvisionFromAzure,
                pathSecrets,
                pathProvisionPlan,
                pathOutput);

            //Run the work
            try
            {
                ProvisionFromAzureAd(
                    statusLogs,
                    pathSecrets,
                    txtPathToAzureAdProvisioningConfig.Text,
                    pathOutput);
            }
            catch (Exception exError)
            {
                MessageBox.Show("Error: " + exError.Message);
            }

            UpdateStatusText(statusLogs, true);

            //Open the file explorer to the output directory
            if (Directory.Exists(pathOutput))
            {
                System.Diagnostics.Process.Start(pathOutput);
            }
        }
Beispiel #3
0
    /// <summary>
    /// Queries a site for all its users, and for recent content.
    /// Genterates and sends email to all the users
    /// </summary>
    /// <param name="showLogsHere"></param>
    /// <param name="statusLogs"></param>
    public void Execute()
    {
        //==================================================================================
        //Get the data we need to run
        //==================================================================================
        //Generate the URLs we will need
        var siteUrlManager = TableauServerUrls.FromContentUrl(_configTableauSecrets.SiteUrl, TaskMasterOptions.RestApiReponsePageSizeDefault);

        //=================================================================================
        //Sign in to the site
        //=================================================================================
        var siteSignIn = new TableauServerSignIn(
            siteUrlManager,
            _configTableauSecrets.SiteClientId,
            _configTableauSecrets.Secret,
            _statusLogs,
            _configTableauSecrets.SiteSignInMode);

        var signInSuccess = siteSignIn.Execute();

        ShowLogs();

        //=================================================================================
        //Get the basic site info
        //=================================================================================
        var downloadSiteInfo = new DownloadSiteInfo(siteSignIn);

        downloadSiteInfo.ExecuteRequest();
        var siteInfo = downloadSiteInfo.Site;

        //===================================================================================
        //Get Groups that map to Tableau Site User Roles from Tableau
        //===================================================================================
        _statusLogs.AddStatus("Tableau: Getting user roles groups");
        GenerateUsersRolesList_FromTableauSite(siteSignIn);

        //===================================================================================
        //Get Groups that map to Tableau Site Groups from Tableau
        //===================================================================================
        _statusLogs.AddStatus("Tableau: Getting user roles groups");
        GenerateGroupsMembersList_FromTableauSite(siteSignIn);
    }
Beispiel #4
0
        /// <summary>
        /// Called to generate a provisioning manifest file from a Tableau site
        /// This is useful for creating a "backup" of the sites existing users/groups
        /// provisioning
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnCreateBackupManifestFile_Click(object sender, EventArgs e)
        {
            var statusLogs = new TaskStatusLogs();

            statusLogs.AddStatus("Starting...");
            UpdateStatusText(statusLogs, true);
            bool ignoreAllUsersGroup = chkIgoreAllUsersGroup.Checked;


            string pathSecrets = txtPathToSecrets.Text;

            if (!File.Exists(pathSecrets))
            {
                MessageBox.Show("Secrets file does not exist at specified path (" + pathSecrets + ")");
                return;
            }


            string pathOutputManifestFile = txtPathToGenerateManifestFile.Text;

            //If they gave us a directory, not a file-name, then add filename to it
            if (Directory.Exists(pathOutputManifestFile))
            {
                pathOutputManifestFile = Path.Combine(
                    pathOutputManifestFile,
                    FileIOHelper.FilenameWithDateTimeUnique("SiteProvisionManifest.xml"));
                //Show it in the UI
                txtPathToGenerateManifestFile.Text = pathOutputManifestFile;
            }


            var pathOutput = Path.GetDirectoryName(pathOutputManifestFile);

            FileIOHelper.CreatePathIfNeeded(pathOutput);


            //Show the user a command line that they can use to run this same work
            GenerateProvisioningCommandLine(
                CommandLineParser.Command_GenerateManifestFromOnlineSite,
                pathSecrets,
                pathOutputManifestFile,
                pathOutput,
                ignoreAllUsersGroup);

            //Run the work
            try
            {
                GenerateManifestFromOnlineSite(
                    statusLogs,
                    pathSecrets,
                    pathOutputManifestFile,
                    ignoreAllUsersGroup);
            }
            catch (Exception exError)
            {
                MessageBox.Show("Error: " + exError.Message);
            }

            UpdateStatusText(statusLogs, true);

            //Open the file explorer to the output directory
            if (Directory.Exists(pathOutput))
            {
                System.Diagnostics.Process.Start(pathOutput);
            }
        }
Beispiel #5
0
        private void ProvisionFromAzureAd_FromUISetup(bool deployProvisioningToTableau)
        {
            var statusLogs = new TaskStatusLogs();

            statusLogs.AddStatus("Starting...");
            UpdateStatusText(statusLogs, true);

            string pathSecrets = txtPathToSecrets.Text;

            if (!File.Exists(pathSecrets))
            {
                MessageBox.Show("Secrets file does not exist at specified path (" + pathSecrets + ")");
                return;
            }


            string pathProvisionPlan = txtPathToAzureAdProvisioningConfig.Text;

            if (!File.Exists(pathProvisionPlan))
            {
                MessageBox.Show("Config file does not exist at specified path (" + pathProvisionPlan + ")");
                return;
            }

            string pathOutput =
                Path.Combine(
                    Path.GetDirectoryName(pathProvisionPlan),
                    "out");

            FileIOHelper.CreatePathIfNeeded(pathOutput);


            //=======================================================================================
            //Is this a test run, or a "deploy changes to Tableau run"
            //=======================================================================================
            string primaryCommand;

            if (deployProvisioningToTableau)
            {
                primaryCommand = CommandLineParser.Command_ProvisionFromAzure;
            }
            else
            {
                primaryCommand = CommandLineParser.Command_GenerateManifestFromAzure;
            }

            //Show the user a command line that they can use to run this same work
            GenerateProvisioningCommandLine(
                primaryCommand,
                pathSecrets,
                pathProvisionPlan,
                pathOutput);

            //Run the work
            try
            {
                ProvisionFromAzureAd(
                    statusLogs,
                    pathSecrets,
                    txtPathToAzureAdProvisioningConfig.Text,
                    deployProvisioningToTableau,
                    pathOutput);
            }
            catch (Exception exError)
            {
                MessageBox.Show("Error: " + exError.Message);
            }

            UpdateStatusText(statusLogs, true);

            //Open the file explorer to the output directory
            if (Directory.Exists(pathOutput))
            {
                System.Diagnostics.Process.Start(pathOutput);
            }
        }
Beispiel #6
0
    /// <summary>
    /// Called to attempt to execute a custom command (to be run after the user logs in)
    /// </summary>
    /// <param name="onlineLogin"></param>
    /// <param name="customCommand"></param>
    private void AttemptExecutionOfCustomHttpGet(TableauServerSignIn onlineLogin, string customCommand)
    {
        _statusLog.AddStatusHeader("GET request: " + customCommand);
        var customGetRequest = new SendPostLogInCommand(_onlineUrls, onlineLogin, customCommand);

        try
        {
            var customResult = customGetRequest.ExecuteRequest();
            _statusLog.AddStatus("GET result: " + customResult);
        }
        catch (Exception exCustomCommand)
        {
            _statusLog.AddError("Error during custom GET, " + exCustomCommand.ToString());
        }
    }
        /// <summary>
        /// Executes the authentication request against the Tableau server
        /// </summary>
        public bool ExecuteRequest()
        {
            var    webRequest = WebRequest.Create(_onlineUrls.UrlLogin);
            string bodyText   = xmlLogIn;

            bodyText = bodyText.Replace("{{iwsUserName}}", _userName);
            bodyText = bodyText.Replace("{{iwsPassword}}", _password);
            bodyText = bodyText.Replace("{{iwsSiteUrl}}", _siteUrlSegment);
            AssertTemplateFullyReplaced(bodyText);

            //===============================================================================================
            //Make the sign in request, trap and note, and rethrow any errors
            //===============================================================================================
            try
            {
                SendRequestContents(webRequest, bodyText);
            }
            catch (Exception exSendRequest)
            {
                StatusLog.AddError("Error sending sign in request: " + exSendRequest);
                throw;
            }


            //===============================================================================================
            //Get the web response, trap and note, and rethrow any errors
            //===============================================================================================
            WebResponse response;

            try
            {
                response = webRequest.GetResponse();
            }
            catch (Exception exResponse)
            {
                StatusLog.AddError("Error returned from sign in response: " + exResponse);
                throw;
            }

            var allHeaders = response.Headers;
            var cookies    = allHeaders["Set-Cookie"];

            _logInCookies = cookies; //Keep any cookies

            //===============================================================================================
            //Get the web response's XML payload, trap and note, and rethrow any errors
            //===============================================================================================
            XmlDocument xmlDoc;

            try
            {
                xmlDoc = GetWebResponseAsXml(response);
            }
            catch (Exception exSignInResponse)
            {
                StatusLog.AddError("Error returned from sign in xml response: " + exSignInResponse);
                throw;
            }

            var nsManager      = XmlHelper.CreateTableauXmlNamespaceManager("iwsOnline");
            var credentialNode = xmlDoc.SelectSingleNode("//iwsOnline:credentials", nsManager);
            var siteNode       = xmlDoc.SelectSingleNode("//iwsOnline:site", nsManager);

            _logInSiteId = siteNode.Attributes["id"].Value;
            _logInToken  = credentialNode.Attributes["token"].Value;

            //Adding the UserId to the log-in return was a feature that was added late in the product cycle.
            //For this reason this code is going to defensively look to see if hte attribute is there
            var    userNode = xmlDoc.SelectSingleNode("//iwsOnline:user", nsManager);
            string userId   = null;

            if (userNode != null)
            {
                var userIdAttribute = userNode.Attributes?["id"];
                if (userIdAttribute != null)
                {
                    userId = userIdAttribute.Value;
                }
                _logInUserId = userId;
            }

            //Output some status text...
            if (!string.IsNullOrWhiteSpace(userId))
            {
                StatusLog.AddStatus("Log-in returned user id: '" + userId + "'", -10);
            }
            else
            {
                StatusLog.AddStatus("No User Id returned from log-in request");
                return(false);  //Failed sign in
            }

            return(true); //Success
        }
Beispiel #8
0
        /// <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,
            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");
                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");
                throw new Exception("813-1214: Error parsing sync groups, " + exGroupsMapping.Message);
            }

            //===========================================================================================
            //Download all the data we need from Azure
            //===========================================================================================
            statusLogs.AddStatus("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");
                throw new Exception("813-0148: Error in Azure Download, " + exAzureDownload.Message);
            }

            //===========================================================================================
            //Write the provisioning manifest out to an intermediary file
            //===========================================================================================
            statusLogs.AddStatus("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");
                throw new Exception("813-739: Error writing provisioning manifest, " + exWriteProvisioningManifest.Message);
            }

            //===========================================================================================
            //Provision the Tableau site using the manifest file we just created
            //===========================================================================================
            statusLogs.AddStatus("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");
                throw new Exception("814-353: Error provisioning Tableau Online site, " + exProvisionSite.Message);
            }
        }