示例#1
0
        public static PSCredential GetRepositoryCredentialFromSecretManagement(
            string repositoryName,
            PSCredentialInfo repositoryCredentialInfo,
            PSCmdlet cmdletPassedIn)
        {
            if (!IsSecretManagementVaultAccessible(repositoryName, repositoryCredentialInfo, cmdletPassedIn))
            {
                cmdletPassedIn.ThrowTerminatingError(
                    new ErrorRecord(
                        new PSInvalidOperationException($"Cannot access Microsoft.PowerShell.SecretManagement vault \"{repositoryCredentialInfo.VaultName}\" for PSResourceRepository ({repositoryName}) authentication."),
                        "RepositoryCredentialSecretManagementInaccessibleVault",
                        ErrorCategory.ResourceUnavailable,
                        cmdletPassedIn));
                return(null);
            }

            var results = PowerShellInvoker.InvokeScriptWithHost <object>(
                cmdlet: cmdletPassedIn,
                script: @"
                    param (
                        [string] $VaultName,
                        [string] $SecretName
                    )
                    $module = Microsoft.PowerShell.Core\Import-Module -Name Microsoft.PowerShell.SecretManagement -PassThru
                    if ($null -eq $module) {
                        return
                    }
                    & $module ""Get-Secret"" -Name $SecretName -Vault $VaultName
                ",
                args: new object[] { repositoryCredentialInfo.VaultName, repositoryCredentialInfo.SecretName },
                out Exception terminatingError);

            var secretValue = (results.Count == 1) ? results[0] : null;

            if (secretValue == null)
            {
                cmdletPassedIn.ThrowTerminatingError(
                    new ErrorRecord(
                        new PSInvalidOperationException(
                            message: $"Microsoft.PowerShell.SecretManagement\\Get-Secret encountered an error while reading secret \"{repositoryCredentialInfo.SecretName}\" from vault \"{repositoryCredentialInfo.VaultName}\" for PSResourceRepository ({repositoryName}) authentication.",
                            innerException: terminatingError),
                        "RepositoryCredentialCannotGetSecretFromVault",
                        ErrorCategory.InvalidOperation,
                        cmdletPassedIn));
            }

            if (secretValue is PSCredential secretCredential)
            {
                return(secretCredential);
            }

            cmdletPassedIn.ThrowTerminatingError(
                new ErrorRecord(
                    new PSNotSupportedException($"Secret \"{repositoryCredentialInfo.SecretName}\" from vault \"{repositoryCredentialInfo.VaultName}\" has an invalid type. The only supported type is PSCredential."),
                    "RepositoryCredentialInvalidSecretType",
                    ErrorCategory.InvalidType,
                    cmdletPassedIn));

            return(null);
        }
 public PSRepositoryInfo(string name, Uri uri, int priority, bool trusted, PSCredentialInfo credentialInfo)
 {
     Name           = name;
     Uri            = uri;
     Priority       = priority;
     Trusted        = trusted;
     CredentialInfo = credentialInfo;
 }
        /// <summary>
        /// Removes a repository from the XML
        /// Returns: void
        /// </summary>
        /// <param name="sectionName"></param>
        public static List <PSRepositoryInfo> Remove(string[] repoNames, out string[] errorList)
        {
            List <PSRepositoryInfo> removedRepos  = new List <PSRepositoryInfo>();
            List <string>           tempErrorList = new List <string>();
            XDocument doc;

            try
            {
                // Open file
                doc = LoadXDocument(FullRepositoryPath);
            }
            catch (Exception e)
            {
                throw new PSInvalidOperationException(String.Format("Loading repository store failed: {0}", e.Message));
            }

            // Get root of XDocument (XElement)
            var root = doc.Root;

            foreach (string repo in repoNames)
            {
                XElement node = FindRepositoryElement(doc, repo);
                if (node == null)
                {
                    tempErrorList.Add(String.Format("Unable to find repository '{0}'.  Use Get-PSResourceRepository to see all available repositories.", repo));
                    continue;
                }

                PSCredentialInfo repoCredentialInfo = null;
                if (node.Attribute("VaultName") != null & node.Attribute("SecretName") != null)
                {
                    repoCredentialInfo = new PSCredentialInfo(node.Attribute("VaultName").Value, node.Attribute("SecretName").Value);
                }
                removedRepos.Add(
                    new PSRepositoryInfo(repo,
                                         new Uri(node.Attribute("Uri").Value),
                                         Int32.Parse(node.Attribute("Priority").Value),
                                         Boolean.Parse(node.Attribute("Trusted").Value),
                                         repoCredentialInfo));
                // Remove item from file
                node.Remove();
            }

            // Close the file
            root.Save(FullRepositoryPath);
            errorList = tempErrorList.ToArray();

            return(removedRepos);
        }
示例#4
0
        public static void SaveRepositoryCredentialToSecretManagementVault(
            string repositoryName,
            PSCredentialInfo repositoryCredentialInfo,
            PSCmdlet cmdletPassedIn)
        {
            if (!IsSecretManagementVaultAccessible(repositoryName, repositoryCredentialInfo, cmdletPassedIn))
            {
                cmdletPassedIn.ThrowTerminatingError(
                    new ErrorRecord(
                        new PSInvalidOperationException($"Cannot access Microsoft.PowerShell.SecretManagement vault \"{repositoryCredentialInfo.VaultName}\" for PSResourceRepository ({repositoryName}) authentication."),
                        "RepositoryCredentialSecretManagementInaccessibleVault",
                        ErrorCategory.ResourceUnavailable,
                        cmdletPassedIn));
                return;
            }

            PowerShellInvoker.InvokeScriptWithHost(
                cmdlet: cmdletPassedIn,
                script: @"
                    param (
                        [string] $VaultName,
                        [string] $SecretName,
                        [object] $SecretValue
                    )
                    $module = Microsoft.PowerShell.Core\Import-Module -Name Microsoft.PowerShell.SecretManagement -PassThru
                    if ($null -eq $module) {
                        return
                    }
                    & $module ""Set-Secret"" -Name $SecretName -Vault $VaultName -Secret $SecretValue
                ",
                args: new object[] { repositoryCredentialInfo.VaultName, repositoryCredentialInfo.SecretName, repositoryCredentialInfo.Credential },
                out Exception terminatingError);

            if (terminatingError != null)
            {
                cmdletPassedIn.ThrowTerminatingError(
                    new ErrorRecord(
                        new PSInvalidOperationException(
                            message: $"Microsoft.PowerShell.SecretManagement\\Set-Secret encountered an error while adding secret \"{repositoryCredentialInfo.SecretName}\" to vault \"{repositoryCredentialInfo.VaultName}\" for PSResourceRepository ({repositoryName}) authentication.",
                            innerException: terminatingError),
                        "RepositoryCredentialCannotAddSecretToVault",
                        ErrorCategory.InvalidOperation,
                        cmdletPassedIn));
            }
        }
示例#5
0
        public static bool IsSecretManagementVaultAccessible(
            string repositoryName,
            PSCredentialInfo repositoryCredentialInfo,
            PSCmdlet cmdletPassedIn)
        {
            var results = PowerShellInvoker.InvokeScriptWithHost <bool>(
                cmdlet: cmdletPassedIn,
                script: @"
                    param (
                        [string] $VaultName
                    )
                    $module = Microsoft.PowerShell.Core\Import-Module -Name Microsoft.PowerShell.SecretManagement -PassThru
                    if ($null -eq $module) {
                        return
                    }
                    & $module ""Test-SecretVault"" -Name $VaultName
                ",
                args: new object[] { repositoryCredentialInfo.VaultName },
                out Exception terminatingError);

            if (terminatingError != null)
            {
                cmdletPassedIn.ThrowTerminatingError(
                    new ErrorRecord(
                        new PSInvalidOperationException(
                            message: $"Microsoft.PowerShell.SecretManagement\\Test-SecretVault encountered an error while validating the vault \"{repositoryCredentialInfo.VaultName}\" for PSResourceRepository ({repositoryName}) authentication.",
                            innerException: terminatingError),
                        "RepositoryCredentialSecretManagementInvalidVault",
                        ErrorCategory.InvalidOperation,
                        cmdletPassedIn));
            }

            bool result = (results.Count > 0) ? results[0] : false;

            return(result);
        }
        /// <summary>
        /// Add a repository to the store
        /// Returns: PSRepositoryInfo containing information about the repository just added to the repository store
        /// </summary>
        /// <param name="sectionName"></param>
        public static PSRepositoryInfo Add(string repoName, Uri repoUri, int repoPriority, bool repoTrusted, PSCredentialInfo repoCredentialInfo)
        {
            try
            {
                // Open file
                XDocument doc = LoadXDocument(FullRepositoryPath);
                if (FindRepositoryElement(doc, repoName) != null)
                {
                    throw new PSInvalidOperationException(String.Format("The PSResource Repository '{0}' already exists.", repoName));
                }

                // Else, keep going
                // Get root of XDocument (XElement)
                var root = doc.Root;

                // Create new element
                XElement newElement = new XElement(
                    "Repository",
                    new XAttribute("Name", repoName),
                    new XAttribute("Uri", repoUri),
                    new XAttribute("Priority", repoPriority),
                    new XAttribute("Trusted", repoTrusted)
                    );

                if (repoCredentialInfo != null)
                {
                    newElement.Add(new XAttribute(PSCredentialInfo.VaultNameAttribute, repoCredentialInfo.VaultName));
                    newElement.Add(new XAttribute(PSCredentialInfo.SecretNameAttribute, repoCredentialInfo.SecretName));
                }

                root.Add(newElement);

                // Close the file
                root.Save(FullRepositoryPath);
            }
            catch (Exception e)
            {
                throw new PSInvalidOperationException(String.Format("Adding to repository store failed: {0}", e.Message));
            }

            return(new PSRepositoryInfo(repoName, repoUri, repoPriority, repoTrusted, repoCredentialInfo));
        }
        public static List <PSRepositoryInfo> Read(string[] repoNames, out string[] errorList)
        {
            List <string> tempErrorList = new List <string>();
            var           foundRepos    = new List <PSRepositoryInfo>();

            XDocument doc;

            try
            {
                // Open file
                doc = LoadXDocument(FullRepositoryPath);
            }
            catch (Exception e)
            {
                throw new PSInvalidOperationException(String.Format("Loading repository store failed: {0}", e.Message));
            }

            if (repoNames == null || !repoNames.Any() || string.Equals(repoNames[0], "*") || repoNames[0] == null)
            {
                // Name array or single value is null so we will list all repositories registered
                // iterate through the doc
                foreach (XElement repo in doc.Descendants("Repository"))
                {
                    if (!Uri.TryCreate(repo.Attribute("Uri").Value, UriKind.Absolute, out Uri thisUri))
                    {
                        tempErrorList.Add(String.Format("Unable to read incorrectly formatted Uri for repo {0}", repo.Attribute("Name").Value));
                        continue;
                    }

                    PSCredentialInfo thisCredentialInfo;
                    string           credentialInfoErrorMessage = $"Repository {repo.Attribute("Name").Value} has invalid CredentialInfo. {PSCredentialInfo.VaultNameAttribute} and {PSCredentialInfo.SecretNameAttribute} should both be present and non-empty";
                    // both keys are present
                    if (repo.Attribute(PSCredentialInfo.VaultNameAttribute) != null && repo.Attribute(PSCredentialInfo.SecretNameAttribute) != null)
                    {
                        try
                        {
                            // both values are non-empty
                            // = valid credentialInfo
                            thisCredentialInfo = new PSCredentialInfo(repo.Attribute(PSCredentialInfo.VaultNameAttribute).Value, repo.Attribute(PSCredentialInfo.SecretNameAttribute).Value);
                        }
                        catch (Exception)
                        {
                            thisCredentialInfo = null;
                            tempErrorList.Add(credentialInfoErrorMessage);
                            continue;
                        }
                    }
                    // both keys are missing
                    else if (repo.Attribute(PSCredentialInfo.VaultNameAttribute) == null && repo.Attribute(PSCredentialInfo.SecretNameAttribute) == null)
                    {
                        // = valid credentialInfo
                        thisCredentialInfo = null;
                    }
                    // one of the keys is missing
                    else
                    {
                        thisCredentialInfo = null;
                        tempErrorList.Add(credentialInfoErrorMessage);
                        continue;
                    }

                    PSRepositoryInfo currentRepoItem = new PSRepositoryInfo(repo.Attribute("Name").Value,
                                                                            thisUri,
                                                                            Int32.Parse(repo.Attribute("Priority").Value),
                                                                            Boolean.Parse(repo.Attribute("Trusted").Value),
                                                                            thisCredentialInfo);

                    foundRepos.Add(currentRepoItem);
                }
            }
            else
            {
                foreach (string repo in repoNames)
                {
                    bool            repoMatch           = false;
                    WildcardPattern nameWildCardPattern = new WildcardPattern(repo, WildcardOptions.IgnoreCase);

                    foreach (var node in doc.Descendants("Repository").Where(e => nameWildCardPattern.IsMatch(e.Attribute("Name").Value)))
                    {
                        repoMatch = true;
                        if (!Uri.TryCreate(node.Attribute("Uri").Value, UriKind.Absolute, out Uri thisUri))
                        {
                            //debug statement
                            tempErrorList.Add(String.Format("Unable to read incorrectly formatted Uri for repo {0}", node.Attribute("Name").Value));
                            continue;
                        }

                        PSCredentialInfo thisCredentialInfo;
                        string           credentialInfoErrorMessage = $"Repository {node.Attribute("Name").Value} has invalid CredentialInfo. {PSCredentialInfo.VaultNameAttribute} and {PSCredentialInfo.SecretNameAttribute} should both be present and non-empty";
                        // both keys are present
                        if (node.Attribute(PSCredentialInfo.VaultNameAttribute) != null && node.Attribute(PSCredentialInfo.SecretNameAttribute) != null)
                        {
                            try
                            {
                                // both values are non-empty
                                // = valid credentialInfo
                                thisCredentialInfo = new PSCredentialInfo(node.Attribute(PSCredentialInfo.VaultNameAttribute).Value, node.Attribute(PSCredentialInfo.SecretNameAttribute).Value);
                            }
                            catch (Exception)
                            {
                                thisCredentialInfo = null;
                                tempErrorList.Add(credentialInfoErrorMessage);
                                continue;
                            }
                        }
                        // both keys are missing
                        else if (node.Attribute(PSCredentialInfo.VaultNameAttribute) == null && node.Attribute(PSCredentialInfo.SecretNameAttribute) == null)
                        {
                            // = valid credentialInfo
                            thisCredentialInfo = null;
                        }
                        // one of the keys is missing
                        else
                        {
                            thisCredentialInfo = null;
                            tempErrorList.Add(credentialInfoErrorMessage);
                            continue;
                        }

                        PSRepositoryInfo currentRepoItem = new PSRepositoryInfo(node.Attribute("Name").Value,
                                                                                thisUri,
                                                                                Int32.Parse(node.Attribute("Priority").Value),
                                                                                Boolean.Parse(node.Attribute("Trusted").Value),
                                                                                thisCredentialInfo);

                        foundRepos.Add(currentRepoItem);
                    }

                    if (!repo.Contains("*") && !repoMatch)
                    {
                        tempErrorList.Add(String.Format("Unable to find repository with Name '{0}'.  Use Get-PSResourceRepository to see all available repositories.", repo));
                    }
                }
            }

            errorList = tempErrorList.ToArray();
            // Sort by priority, then by repo name
            var reposToReturn = foundRepos.OrderBy(x => x.Priority).ThenBy(x => x.Name);

            return(reposToReturn.ToList());
        }
        /// <summary>
        /// Updates a repository name, Uri, priority, installation policy, or credential information
        /// Returns:  void
        /// </summary>
        public static PSRepositoryInfo Update(string repoName, Uri repoUri, int repoPriority, bool?repoTrusted, PSCredentialInfo repoCredentialInfo)
        {
            PSRepositoryInfo updatedRepo;

            try
            {
                // Open file
                XDocument doc  = LoadXDocument(FullRepositoryPath);
                XElement  node = FindRepositoryElement(doc, repoName);
                if (node == null)
                {
                    throw new ArgumentException("Cannot find the repository because it does not exist. Try registering the repository using 'Register-PSResourceRepository'");
                }

                // Else, keep going
                // Get root of XDocument (XElement)
                var root = doc.Root;

                // A null Uri value passed in signifies the Uri was not attempted to be set.
                // So only set Uri attribute if non-null value passed in for repoUri
                if (repoUri != null)
                {
                    node.Attribute("Uri").Value = repoUri.AbsoluteUri;
                }

                // A negative Priority value passed in signifies the Priority value was not attempted to be set.
                // So only set Priority attribute if non-null value passed in for repoPriority
                if (repoPriority >= 0)
                {
                    node.Attribute("Priority").Value = repoPriority.ToString();
                }

                // A null Trusted value passed in signifies the Trusted value was not attempted to be set.
                // So only set Trusted attribute if non-null value passed in for repoTrusted.
                if (repoTrusted != null)
                {
                    node.Attribute("Trusted").Value = repoTrusted.ToString();
                }

                // A null CredentialInfo value passed in signifies that CredentialInfo was not attempted to be set.
                // Set VaultName and SecretName attributes if non-null value passed in for repoCredentialInfo
                if (repoCredentialInfo != null)
                {
                    if (node.Attribute(PSCredentialInfo.VaultNameAttribute) == null)
                    {
                        node.Add(new XAttribute(PSCredentialInfo.VaultNameAttribute, repoCredentialInfo.VaultName));
                    }
                    else
                    {
                        node.Attribute(PSCredentialInfo.VaultNameAttribute).Value = repoCredentialInfo.VaultName;
                    }

                    if (node.Attribute(PSCredentialInfo.SecretNameAttribute) == null)
                    {
                        node.Add(new XAttribute(PSCredentialInfo.SecretNameAttribute, repoCredentialInfo.SecretName));
                    }
                    else
                    {
                        node.Attribute(PSCredentialInfo.SecretNameAttribute).Value = repoCredentialInfo.SecretName;
                    }
                }

                // Create Uri from node Uri attribute to create PSRepositoryInfo item to return.
                if (!Uri.TryCreate(node.Attribute("Uri").Value, UriKind.Absolute, out Uri thisUri))
                {
                    throw new PSInvalidOperationException(String.Format("Unable to read incorrectly formatted Uri for repo {0}", repoName));
                }

                // Create CredentialInfo based on new values or whether it was empty to begin with
                PSCredentialInfo thisCredentialInfo = null;
                if (node.Attribute(PSCredentialInfo.VaultNameAttribute)?.Value != null &&
                    node.Attribute(PSCredentialInfo.SecretNameAttribute)?.Value != null)
                {
                    thisCredentialInfo = new PSCredentialInfo(
                        node.Attribute(PSCredentialInfo.VaultNameAttribute).Value,
                        node.Attribute(PSCredentialInfo.SecretNameAttribute).Value);
                }

                updatedRepo = new PSRepositoryInfo(repoName,
                                                   thisUri,
                                                   Int32.Parse(node.Attribute("Priority").Value),
                                                   Boolean.Parse(node.Attribute("Trusted").Value),
                                                   thisCredentialInfo);

                // Close the file
                root.Save(FullRepositoryPath);
            }
            catch (Exception e)
            {
                throw new PSInvalidOperationException(String.Format("Updating to repository store failed: {0}", e.Message));
            }

            return(updatedRepo);
        }
示例#9
0
        public static PSRepositoryInfo AddToRepositoryStore(string repoName, Uri repoUri, int repoPriority, bool repoTrusted, PSCredentialInfo repoCredentialInfo, bool force, PSCmdlet cmdletPassedIn, out string errorMsg)
        {
            errorMsg = string.Empty;
            // remove trailing and leading whitespaces, and if Name is just whitespace Name should become null now and be caught by following condition
            repoName = repoName.Trim(' ');
            if (String.IsNullOrEmpty(repoName) || repoName.Contains("*"))
            {
                throw new ArgumentException("Name cannot be null/empty, contain asterisk or be just whitespace");
            }

            if (repoUri == null || !(repoUri.Scheme == System.Uri.UriSchemeHttp || repoUri.Scheme == System.Uri.UriSchemeHttps || repoUri.Scheme == System.Uri.UriSchemeFtp || repoUri.Scheme == System.Uri.UriSchemeFile))
            {
                errorMsg = "Invalid Uri, must be one of the following Uri schemes: HTTPS, HTTP, FTP, File Based";
                return(null);
            }

            if (repoCredentialInfo != null)
            {
                bool isSecretManagementModuleAvailable = Utils.IsSecretManagementModuleAvailable(repoName, cmdletPassedIn);

                if (repoCredentialInfo.Credential != null)
                {
                    if (!isSecretManagementModuleAvailable)
                    {
                        errorMsg = $"Microsoft.PowerShell.SecretManagement module is not found, but is required for saving PSResourceRepository {repoName}'s Credential in a vault.";
                        return(null);
                    }
                    else
                    {
                        Utils.SaveRepositoryCredentialToSecretManagementVault(repoName, repoCredentialInfo, cmdletPassedIn);
                    }
                }

                if (!isSecretManagementModuleAvailable)
                {
                    cmdletPassedIn.WriteWarning($"Microsoft.PowerShell.SecretManagement module cannot be found. Make sure it is installed before performing PSResource operations in order to successfully authenticate to PSResourceRepository \"{repoName}\" with its CredentialInfo.");
                }
            }

            if (!cmdletPassedIn.ShouldProcess(repoName, "Register repository to repository store"))
            {
                return(null);
            }

            if (!string.IsNullOrEmpty(errorMsg))
            {
                return(null);
            }

            var repo = RepositorySettings.Add(repoName, repoUri, repoPriority, repoTrusted, repoCredentialInfo, force);

            return(repo);
        }
示例#10
0
        public static PSRepositoryInfo AddRepository(string repoName, Uri repoUri, int repoPriority, bool repoTrusted, PSCredentialInfo repoCredentialInfo, bool force, PSCmdlet cmdletPassedIn, out string errorMsg)
        {
            errorMsg = String.Empty;
            if (repoName.Equals("PSGallery", StringComparison.OrdinalIgnoreCase))
            {
                errorMsg = "Cannot register PSGallery with -Name parameter. Try: Register-PSResourceRepository -PSGallery";
                return(null);
            }

            return(AddToRepositoryStore(repoName, repoUri, repoPriority, repoTrusted, repoCredentialInfo, force, cmdletPassedIn, out errorMsg));
        }
示例#11
0
        public static List <PSRepositoryInfo> Read(string[] repoNames, out string[] errorList)
        {
            List <string> tempErrorList = new List <string>();
            var           foundRepos    = new List <PSRepositoryInfo>();

            XDocument doc;

            try
            {
                // Open file
                doc = LoadXDocument(FullRepositoryPath);
            }
            catch (Exception e)
            {
                throw new PSInvalidOperationException(String.Format("Loading repository store failed: {0}", e.Message));
            }

            if (repoNames == null || repoNames.Length == 0 || string.Equals(repoNames[0], "*") || repoNames[0] == null)
            {
                // Name array or single value is null so we will list all repositories registered
                // iterate through the doc
                foreach (XElement repo in doc.Descendants("Repository"))
                {
                    if (repo.Attribute("Name") == null)
                    {
                        tempErrorList.Add(String.Format("Repository element does not contain neccessary 'Name' attribute, in file located at path: {0}. Fix this in your file and run again.", FullRepositoryPath));
                        continue;
                    }

                    if (repo.Attribute("Priority") == null)
                    {
                        tempErrorList.Add(String.Format("Repository element does not contain neccessary 'Priority' attribute, in file located at path: {0}. Fix this in your file and run again.", FullRepositoryPath));
                        continue;
                    }

                    if (repo.Attribute("Trusted") == null)
                    {
                        tempErrorList.Add(String.Format("Repository element does not contain neccessary 'Trusted' attribute, in file located at path: {0}. Fix this in your file and run again.", FullRepositoryPath));
                        continue;
                    }

                    bool urlAttributeExists = repo.Attribute("Url") != null;
                    bool uriAttributeExists = repo.Attribute("Uri") != null;
                    // case: neither Url nor Uri attributes exist
                    if (!urlAttributeExists && !uriAttributeExists)
                    {
                        tempErrorList.Add(String.Format("Repository element does not contain neccessary 'Url' or equivalent 'Uri' attribute (it must contain one), in file located at path: {0}. Fix this in your file and run again.", FullRepositoryPath));
                        continue;
                    }

                    Uri thisUrl = null;
                    // case: either attribute Uri or Url exists
                    // TODO: do we only allow both to exist, across repositories? (i.e if a file has Uri attribute for one repo and Url attribute for another --> is that invalid?)
                    if (urlAttributeExists)
                    {
                        if (!Uri.TryCreate(repo.Attribute("Url").Value, UriKind.Absolute, out thisUrl))
                        {
                            tempErrorList.Add(String.Format("Unable to read incorrectly formatted Url for repo {0}", repo.Attribute("Name").Value));
                            continue;
                        }
                    }
                    else if (uriAttributeExists)
                    {
                        if (!Uri.TryCreate(repo.Attribute("Uri").Value, UriKind.Absolute, out thisUrl))
                        {
                            tempErrorList.Add(String.Format("Unable to read incorrectly formatted Uri for repo {0}", repo.Attribute("Name").Value));
                            continue;
                        }
                    }

                    PSCredentialInfo thisCredentialInfo;
                    string           credentialInfoErrorMessage = $"Repository {repo.Attribute("Name").Value} has invalid CredentialInfo. {PSCredentialInfo.VaultNameAttribute} and {PSCredentialInfo.SecretNameAttribute} should both be present and non-empty";
                    // both keys are present
                    if (repo.Attribute(PSCredentialInfo.VaultNameAttribute) != null && repo.Attribute(PSCredentialInfo.SecretNameAttribute) != null)
                    {
                        try
                        {
                            // both values are non-empty
                            // = valid credentialInfo
                            thisCredentialInfo = new PSCredentialInfo(repo.Attribute(PSCredentialInfo.VaultNameAttribute).Value, repo.Attribute(PSCredentialInfo.SecretNameAttribute).Value);
                        }
                        catch (Exception)
                        {
                            thisCredentialInfo = null;
                            tempErrorList.Add(credentialInfoErrorMessage);
                            continue;
                        }
                    }
                    // both keys are missing
                    else if (repo.Attribute(PSCredentialInfo.VaultNameAttribute) == null && repo.Attribute(PSCredentialInfo.SecretNameAttribute) == null)
                    {
                        // = valid credentialInfo
                        thisCredentialInfo = null;
                    }
                    // one of the keys is missing
                    else
                    {
                        thisCredentialInfo = null;
                        tempErrorList.Add(credentialInfoErrorMessage);
                        continue;
                    }

                    PSRepositoryInfo currentRepoItem = new PSRepositoryInfo(repo.Attribute("Name").Value,
                                                                            thisUrl,
                                                                            Int32.Parse(repo.Attribute("Priority").Value),
                                                                            Boolean.Parse(repo.Attribute("Trusted").Value),
                                                                            thisCredentialInfo);

                    foundRepos.Add(currentRepoItem);
                }
            }
            else
            {
                foreach (string repo in repoNames)
                {
                    bool            repoMatch           = false;
                    WildcardPattern nameWildCardPattern = new WildcardPattern(repo, WildcardOptions.IgnoreCase);

                    foreach (var node in doc.Descendants("Repository").Where(e => e.Attribute("Name") != null && nameWildCardPattern.IsMatch(e.Attribute("Name").Value)))
                    {
                        if (node.Attribute("Priority") == null)
                        {
                            tempErrorList.Add(String.Format("Repository element does not contain neccessary 'Priority' attribute, in file located at path: {0}. Fix this in your file and run again.", FullRepositoryPath));
                            continue;
                        }

                        if (node.Attribute("Trusted") == null)
                        {
                            tempErrorList.Add(String.Format("Repository element does not contain neccessary 'Trusted' attribute, in file located at path: {0}. Fix this in your file and run again.", FullRepositoryPath));
                            continue;
                        }

                        repoMatch = true;
                        bool urlAttributeExists = node.Attribute("Url") != null;
                        bool uriAttributeExists = node.Attribute("Uri") != null;

                        // case: neither Url nor Uri attributes exist
                        if (!urlAttributeExists && !uriAttributeExists)
                        {
                            tempErrorList.Add(String.Format("Repository element does not contain neccessary 'Url' or equivalent 'Uri' attribute (it must contain one), in file located at path: {0}. Fix this in your file and run again.", FullRepositoryPath));
                            continue;
                        }

                        Uri thisUrl = null;
                        // case: either attribute Uri or Url exists
                        // TODO: do we only allow both to exist, across repositories? (i.e if a file has Uri attribute for one repo and Url attribute for another --> is that invalid?)
                        if (urlAttributeExists)
                        {
                            if (!Uri.TryCreate(node.Attribute("Url").Value, UriKind.Absolute, out thisUrl))
                            {
                                tempErrorList.Add(String.Format("Unable to read incorrectly formatted Url for repo {0}", node.Attribute("Name").Value));
                                continue;
                            }
                        }
                        else if (uriAttributeExists)
                        {
                            if (!Uri.TryCreate(node.Attribute("Uri").Value, UriKind.Absolute, out thisUrl))
                            {
                                tempErrorList.Add(String.Format("Unable to read incorrectly formatted Uri for repo {0}", node.Attribute("Name").Value));
                                continue;
                            }
                        }

                        PSCredentialInfo thisCredentialInfo;
                        string           credentialInfoErrorMessage = $"Repository {node.Attribute("Name").Value} has invalid CredentialInfo. {PSCredentialInfo.VaultNameAttribute} and {PSCredentialInfo.SecretNameAttribute} should both be present and non-empty";
                        // both keys are present
                        if (node.Attribute(PSCredentialInfo.VaultNameAttribute) != null && node.Attribute(PSCredentialInfo.SecretNameAttribute) != null)
                        {
                            try
                            {
                                // both values are non-empty
                                // = valid credentialInfo
                                thisCredentialInfo = new PSCredentialInfo(node.Attribute(PSCredentialInfo.VaultNameAttribute).Value, node.Attribute(PSCredentialInfo.SecretNameAttribute).Value);
                            }
                            catch (Exception)
                            {
                                thisCredentialInfo = null;
                                tempErrorList.Add(credentialInfoErrorMessage);
                                continue;
                            }
                        }
                        // both keys are missing
                        else if (node.Attribute(PSCredentialInfo.VaultNameAttribute) == null && node.Attribute(PSCredentialInfo.SecretNameAttribute) == null)
                        {
                            // = valid credentialInfo
                            thisCredentialInfo = null;
                        }
                        // one of the keys is missing
                        else
                        {
                            thisCredentialInfo = null;
                            tempErrorList.Add(credentialInfoErrorMessage);
                            continue;
                        }

                        PSRepositoryInfo currentRepoItem = new PSRepositoryInfo(node.Attribute("Name").Value,
                                                                                thisUrl,
                                                                                Int32.Parse(node.Attribute("Priority").Value),
                                                                                Boolean.Parse(node.Attribute("Trusted").Value),
                                                                                thisCredentialInfo);

                        foundRepos.Add(currentRepoItem);
                    }

                    if (!repo.Contains("*") && !repoMatch)
                    {
                        tempErrorList.Add(String.Format("Unable to find repository with Name '{0}'.  Use Get-PSResourceRepository to see all available repositories.", repo));
                    }
                }
            }

            errorList = tempErrorList.ToArray();
            // Sort by priority, then by repo name
            var reposToReturn = foundRepos.OrderBy(x => x.Priority).ThenBy(x => x.Name);

            return(reposToReturn.ToList());
        }
示例#12
0
        /// <summary>
        /// Removes a repository from the XML
        /// Returns: void
        /// </summary>
        /// <param name="sectionName"></param>
        public static List <PSRepositoryInfo> Remove(string[] repoNames, out string[] errorList)
        {
            List <PSRepositoryInfo> removedRepos  = new List <PSRepositoryInfo>();
            List <string>           tempErrorList = new List <string>();
            XDocument doc;

            try
            {
                // Open file
                doc = LoadXDocument(FullRepositoryPath);
            }
            catch (Exception e)
            {
                throw new PSInvalidOperationException(String.Format("Loading repository store failed: {0}", e.Message));
            }

            // Get root of XDocument (XElement)
            var root = doc.Root;

            foreach (string repo in repoNames)
            {
                XElement node = FindRepositoryElement(doc, repo);
                if (node == null)
                {
                    tempErrorList.Add(String.Format("Unable to find repository '{0}'.  Use Get-PSResourceRepository to see all available repositories.", repo));
                    continue;
                }

                PSCredentialInfo repoCredentialInfo = null;
                if (node.Attribute("VaultName") != null & node.Attribute("SecretName") != null)
                {
                    repoCredentialInfo = new PSCredentialInfo(node.Attribute("VaultName").Value, node.Attribute("SecretName").Value);
                }

                if (node.Attribute("Priority") == null)
                {
                    tempErrorList.Add(String.Format("Repository element does not contain neccessary 'Priority' attribute, in file located at path: {0}. Fix this in your file and run again.", FullRepositoryPath));
                    continue;
                }

                if (node.Attribute("Trusted") == null)
                {
                    tempErrorList.Add(String.Format("Repository element does not contain neccessary 'Trusted' attribute, in file located at path: {0}. Fix this in your file and run again.", FullRepositoryPath));
                    continue;
                }

                // determine if repo had Url or Uri (less likely) attribute
                bool urlAttributeExists = node.Attribute("Url") != null;
                bool uriAttributeExists = node.Attribute("Uri") != null;
                if (!urlAttributeExists && !uriAttributeExists)
                {
                    tempErrorList.Add(String.Format("Repository element does not contain neccessary 'Url' or equivalent 'Uri' attribute (it must contain one per Repository), in file located at path: {0}. Fix this in your file and run again.", FullRepositoryPath));
                    continue;
                }

                string attributeUrlUriName = urlAttributeExists ? "Url" : "Uri";
                removedRepos.Add(
                    new PSRepositoryInfo(repo,
                                         new Uri(node.Attribute(attributeUrlUriName).Value),
                                         Int32.Parse(node.Attribute("Priority").Value),
                                         Boolean.Parse(node.Attribute("Trusted").Value),
                                         repoCredentialInfo));
                // Remove item from file
                node.Remove();
            }

            // Close the file
            root.Save(FullRepositoryPath);
            errorList = tempErrorList.ToArray();

            return(removedRepos);
        }
示例#13
0
        /// <summary>
        /// Updates a repository name, Uri, priority, installation policy, or credential information
        /// Returns:  void
        /// </summary>
        public static PSRepositoryInfo Update(string repoName, Uri repoUri, int repoPriority, bool?repoTrusted, PSCredentialInfo repoCredentialInfo, PSCmdlet cmdletPassedIn, out string errorMsg)
        {
            errorMsg = string.Empty;
            PSRepositoryInfo updatedRepo;

            try
            {
                // Open file
                XDocument doc  = LoadXDocument(FullRepositoryPath);
                XElement  node = FindRepositoryElement(doc, repoName);
                if (node == null)
                {
                    bool repoIsTrusted = !(repoTrusted == null || repoTrusted == false);
                    repoPriority = repoPriority < 0 ? DefaultPriority : repoPriority;
                    return(AddToRepositoryStore(repoName, repoUri, repoPriority, repoIsTrusted, repoCredentialInfo, force: true, cmdletPassedIn, out errorMsg));
                }

                // Check that repository node we are attempting to update has all required attributes: Name, Url (or Uri), Priority, Trusted.
                // Name attribute is already checked for in FindRepositoryElement()

                if (node.Attribute("Priority") == null)
                {
                    errorMsg = $"Repository element does not contain neccessary 'Priority' attribute, in file located at path: {FullRepositoryPath}. Fix this in your file and run again.";
                    return(null);
                }

                if (node.Attribute("Trusted") == null)
                {
                    errorMsg = $"Repository element does not contain neccessary 'Trusted' attribute, in file located at path: {FullRepositoryPath}. Fix this in your file and run again.";
                    return(null);
                }

                bool urlAttributeExists = node.Attribute("Url") != null;
                bool uriAttributeExists = node.Attribute("Uri") != null;
                if (!urlAttributeExists && !uriAttributeExists)
                {
                    errorMsg = $"Repository element does not contain neccessary 'Url' attribute (or alternatively 'Uri' attribute), in file located at path: {FullRepositoryPath}. Fix this in your file and run again.";
                    return(null);
                }

                // Else, keep going
                // Get root of XDocument (XElement)
                var root = doc.Root;

                // A null Uri (or Url) value passed in signifies the Uri was not attempted to be set.
                // So only set Uri attribute if non-null value passed in for repoUri

                // determine if existing repository node (which we wish to update) had Url or Uri attribute
                Uri thisUrl = null;
                if (repoUri != null)
                {
                    if (!Uri.TryCreate(repoUri.AbsoluteUri, UriKind.Absolute, out thisUrl))
                    {
                        throw new PSInvalidOperationException(String.Format("Unable to read incorrectly formatted Url for repo {0}", repoName));
                    }

                    if (urlAttributeExists)
                    {
                        node.Attribute("Url").Value = thisUrl.AbsoluteUri;
                    }
                    else
                    {
                        node.Attribute("Uri").Value = thisUrl.AbsoluteUri;
                    }
                }
                else
                {
                    if (urlAttributeExists)
                    {
                        if (!Uri.TryCreate(node.Attribute("Url").Value, UriKind.Absolute, out thisUrl))
                        {
                            throw new PSInvalidOperationException(String.Format("The 'Url' for repository {0} is invalid and the repository cannot be used. Please update the Url field or remove the repository entry.", repoName));
                        }
                    }
                    else
                    {
                        if (!Uri.TryCreate(node.Attribute("Uri").Value, UriKind.Absolute, out thisUrl))
                        {
                            throw new PSInvalidOperationException(String.Format("The 'Url' for repository {0} is invalid and the repository cannot be used. Please update the Url field or remove the repository entry.", repoName));
                        }
                    }
                }

                // A negative Priority value passed in signifies the Priority value was not attempted to be set.
                // So only set Priority attribute if non-null value passed in for repoPriority
                if (repoPriority >= 0)
                {
                    node.Attribute("Priority").Value = repoPriority.ToString();
                }

                // A null Trusted value passed in signifies the Trusted value was not attempted to be set.
                // So only set Trusted attribute if non-null value passed in for repoTrusted.
                if (repoTrusted != null)
                {
                    node.Attribute("Trusted").Value = repoTrusted.ToString();
                }

                // A null CredentialInfo value passed in signifies that CredentialInfo was not attempted to be set.
                // Set VaultName and SecretName attributes if non-null value passed in for repoCredentialInfo
                if (repoCredentialInfo != null)
                {
                    if (node.Attribute(PSCredentialInfo.VaultNameAttribute) == null)
                    {
                        node.Add(new XAttribute(PSCredentialInfo.VaultNameAttribute, repoCredentialInfo.VaultName));
                    }
                    else
                    {
                        node.Attribute(PSCredentialInfo.VaultNameAttribute).Value = repoCredentialInfo.VaultName;
                    }

                    if (node.Attribute(PSCredentialInfo.SecretNameAttribute) == null)
                    {
                        node.Add(new XAttribute(PSCredentialInfo.SecretNameAttribute, repoCredentialInfo.SecretName));
                    }
                    else
                    {
                        node.Attribute(PSCredentialInfo.SecretNameAttribute).Value = repoCredentialInfo.SecretName;
                    }
                }

                // Create CredentialInfo based on new values or whether it was empty to begin with
                PSCredentialInfo thisCredentialInfo = null;
                if (node.Attribute(PSCredentialInfo.VaultNameAttribute)?.Value != null &&
                    node.Attribute(PSCredentialInfo.SecretNameAttribute)?.Value != null)
                {
                    thisCredentialInfo = new PSCredentialInfo(
                        node.Attribute(PSCredentialInfo.VaultNameAttribute).Value,
                        node.Attribute(PSCredentialInfo.SecretNameAttribute).Value);
                }

                updatedRepo = new PSRepositoryInfo(repoName,
                                                   thisUrl,
                                                   Int32.Parse(node.Attribute("Priority").Value),
                                                   Boolean.Parse(node.Attribute("Trusted").Value),
                                                   thisCredentialInfo);

                // Close the file
                root.Save(FullRepositoryPath);
            }
            catch (Exception e)
            {
                throw new PSInvalidOperationException(String.Format("Updating to repository store failed: {0}", e.Message));
            }

            return(updatedRepo);
        }
示例#14
0
        /// <summary>
        /// Add a repository to the store
        /// Returns: PSRepositoryInfo containing information about the repository just added to the repository store
        /// </summary>
        /// <param name="sectionName"></param>
        public static PSRepositoryInfo Add(string repoName, Uri repoUri, int repoPriority, bool repoTrusted, PSCredentialInfo repoCredentialInfo, bool force)
        {
            try
            {
                // Open file
                XDocument doc = LoadXDocument(FullRepositoryPath);
                if (FindRepositoryElement(doc, repoName) != null)
                {
                    if (!force)
                    {
                        throw new PSInvalidOperationException(String.Format("The PSResource Repository '{0}' already exists.", repoName));
                    }

                    // Delete the existing repository before overwriting it (otherwire multiple repos with the same name will be added)
                    List <PSRepositoryInfo> removedRepositories = RepositorySettings.Remove(new string[] { repoName }, out string[] errorList);

                    // Need to load the document again because of changes after removing
                    doc = LoadXDocument(FullRepositoryPath);

                    if (errorList.Count() > 0)
                    {
                        throw new PSInvalidOperationException($"The PSResource Repository '{repoName}' cannot be overwritten: ${errorList.FirstOrDefault()}");
                    }
                }

                // Else, keep going
                // Get root of XDocument (XElement)
                var root = doc.Root;

                // Create new element
                XElement newElement = new XElement(
                    "Repository",
                    new XAttribute("Name", repoName),
                    new XAttribute("Url", repoUri),
                    new XAttribute("Priority", repoPriority),
                    new XAttribute("Trusted", repoTrusted)
                    );

                if (repoCredentialInfo != null)
                {
                    newElement.Add(new XAttribute(PSCredentialInfo.VaultNameAttribute, repoCredentialInfo.VaultName));
                    newElement.Add(new XAttribute(PSCredentialInfo.SecretNameAttribute, repoCredentialInfo.SecretName));
                }

                root.Add(newElement);

                // Close the file
                root.Save(FullRepositoryPath);
            }
            catch (Exception e)
            {
                throw new PSInvalidOperationException(String.Format("Adding to repository store failed: {0}", e.Message));
            }

            return(new PSRepositoryInfo(repoName, repoUri, repoPriority, repoTrusted, repoCredentialInfo));
        }
示例#15
0
        public static PSRepositoryInfo UpdateRepositoryStore(string repoName, Uri repoUri, int repoPriority, bool repoTrusted, bool isSet, int defaultPriority, PSCredentialInfo repoCredentialInfo, PSCmdlet cmdletPassedIn, out string errorMsg)
        {
            errorMsg = string.Empty;
            if (repoUri != null && !(repoUri.Scheme == System.Uri.UriSchemeHttp || repoUri.Scheme == System.Uri.UriSchemeHttps || repoUri.Scheme == System.Uri.UriSchemeFtp || repoUri.Scheme == System.Uri.UriSchemeFile))
            {
                errorMsg = "Invalid Uri, Uri must be one of the following schemes: HTTPS, HTTP, FTP, File Based";
                return(null);
            }

            // check repoName can't contain * or just be whitespace
            // remove trailing and leading whitespaces, and if Name is just whitespace Name should become null now and be caught by following condition
            repoName = repoName.Trim();
            if (String.IsNullOrEmpty(repoName) || repoName.Contains("*"))
            {
                errorMsg = "Name cannot be null or empty, or contain wildcards";
                return(null);
            }

            // check PSGallery Uri is not trying to be set
            if (repoName.Equals("PSGallery", StringComparison.OrdinalIgnoreCase) && repoUri != null)
            {
                errorMsg = "The PSGallery repository has a predefined Uri. Setting the -Uri parameter for this repository is not allowed. Please run 'Register-PSResourceRepository -PSGallery' to register the PowerShell Gallery.";
                return(null);
            }

            // check PSGallery CredentialInfo is not trying to be set
            if (repoName.Equals("PSGallery", StringComparison.OrdinalIgnoreCase) && repoCredentialInfo != null)
            {
                errorMsg = "Setting the -CredentialInfo parameter for PSGallery is not allowed. Run 'Register-PSResourceRepository -PSGallery' to register the PowerShell Gallery.";
                return(null);
            }

            // determine trusted value to pass in (true/false if set, null otherwise, hence the nullable bool variable)
            bool?_trustedNullable = isSet ? new bool?(repoTrusted) : new bool?();

            if (repoCredentialInfo != null)
            {
                bool isSecretManagementModuleAvailable = Utils.IsSecretManagementModuleAvailable(repoName, cmdletPassedIn);

                if (repoCredentialInfo.Credential != null)
                {
                    if (!isSecretManagementModuleAvailable)
                    {
                        errorMsg = $"Microsoft.PowerShell.SecretManagement module is not found, but is required for saving PSResourceRepository {repoName}'s Credential in a vault.";
                        return(null);
                    }
                    else
                    {
                        Utils.SaveRepositoryCredentialToSecretManagementVault(repoName, repoCredentialInfo, cmdletPassedIn);
                    }
                }

                if (!isSecretManagementModuleAvailable)
                {
                    cmdletPassedIn.WriteWarning($"Microsoft.PowerShell.SecretManagement module cannot be found. Make sure it is installed before performing PSResource operations in order to successfully authenticate to PSResourceRepository \"{repoName}\" with its CredentialInfo.");
                }
            }

            // determine if either 1 of 4 values are attempting to be set: Uri, Priority, Trusted, CredentialInfo.
            // if none are (i.e only Name parameter was provided, write error)
            if (repoUri == null && repoPriority == defaultPriority && _trustedNullable == null && repoCredentialInfo == null)
            {
                errorMsg = "Must set Uri, Priority, Trusted or CredentialInfo parameter";
                return(null);
            }

            if (!cmdletPassedIn.ShouldProcess(repoName, "Set repository's value(s) in repository store"))
            {
                return(null);
            }

            if (!string.IsNullOrEmpty(errorMsg))
            {
                return(null);
            }

            return(Update(repoName, repoUri, repoPriority, _trustedNullable, repoCredentialInfo, cmdletPassedIn, out errorMsg));
        }
示例#16
0
        public static bool TryCreateValidPSCredentialInfo(
            PSObject credentialInfoCandidate,
            PSCmdlet cmdletPassedIn,
            out PSCredentialInfo repoCredentialInfo,
            out ErrorRecord errorRecord)
        {
            repoCredentialInfo = null;
            errorRecord        = null;

            try
            {
                if (!string.IsNullOrEmpty((string)credentialInfoCandidate.Properties[PSCredentialInfo.VaultNameAttribute]?.Value) &&
                    !string.IsNullOrEmpty((string)credentialInfoCandidate.Properties[PSCredentialInfo.SecretNameAttribute]?.Value))
                {
                    PSCredential credential = null;
                    if (credentialInfoCandidate.Properties[PSCredentialInfo.CredentialAttribute] != null)
                    {
                        try
                        {
                            credential = (PSCredential)credentialInfoCandidate.Properties[PSCredentialInfo.CredentialAttribute].Value;
                        }
                        catch (Exception e)
                        {
                            errorRecord = new ErrorRecord(
                                new PSArgumentException($"Invalid CredentialInfo {PSCredentialInfo.CredentialAttribute}", e),
                                "InvalidCredentialInfo",
                                ErrorCategory.InvalidArgument,
                                cmdletPassedIn);

                            return(false);
                        }
                    }

                    repoCredentialInfo = new PSCredentialInfo(
                        (string)credentialInfoCandidate.Properties[PSCredentialInfo.VaultNameAttribute].Value,
                        (string)credentialInfoCandidate.Properties[PSCredentialInfo.SecretNameAttribute].Value,
                        credential
                        );

                    return(true);
                }
                else
                {
                    errorRecord = new ErrorRecord(
                        new PSArgumentException($"Invalid CredentialInfo, must include non-empty {PSCredentialInfo.VaultNameAttribute} and {PSCredentialInfo.SecretNameAttribute}, and optionally a {PSCredentialInfo.CredentialAttribute}"),
                        "InvalidCredentialInfo",
                        ErrorCategory.InvalidArgument,
                        cmdletPassedIn);

                    return(false);
                }
            }
            catch (Exception e)
            {
                errorRecord = new ErrorRecord(
                    new PSArgumentException("Invalid CredentialInfo values", e),
                    "InvalidCredentialInfo",
                    ErrorCategory.InvalidArgument,
                    cmdletPassedIn);

                return(false);
            }
        }