private PSRepositoryInfo RepoValidationHelper(Hashtable repo) { if (!repo.ContainsKey("Name") || String.IsNullOrEmpty(repo["Name"].ToString())) { WriteError(new ErrorRecord( new PSInvalidOperationException("Repository name cannot be null"), "NullNameForRepositoriesParameterSetRegistration", ErrorCategory.InvalidArgument, this)); return(null); } if (repo["Name"].ToString().Equals("PSGallery")) { WriteError(new ErrorRecord( new PSInvalidOperationException("Cannot register PSGallery with -Name parameter. Try: Register-PSResourceRepository -PSGallery"), "PSGalleryProvidedAsNameRepoPSet", ErrorCategory.InvalidArgument, this)); return(null); } if (!repo.ContainsKey("Uri") || String.IsNullOrEmpty(repo["Uri"].ToString())) { WriteError(new ErrorRecord( new PSInvalidOperationException("Repository Uri cannot be null"), "NullUriForRepositoriesParameterSetRegistration", ErrorCategory.InvalidArgument, this)); return(null); } if (!Utils.TryCreateValidUri(uriString: repo["Uri"].ToString(), cmdletPassedIn: this, uriResult: out Uri repoUri, errorRecord: out ErrorRecord errorRecord)) { WriteError(errorRecord); return(null); } PSCredentialInfo repoCredentialInfo = null; if (repo.ContainsKey("CredentialInfo") && !Utils.TryCreateValidPSCredentialInfo(credentialInfoCandidate: (PSObject)repo["CredentialInfo"], cmdletPassedIn: this, repoCredentialInfo: out repoCredentialInfo, errorRecord: out ErrorRecord errorRecord1)) { WriteError(errorRecord1); return(null); } try { WriteVerbose(String.Format("(RepositoriesParameterSet): on repo: {0}. Registers Name based repository", repo["Name"])); return(NameParameterSetHelper(repo["Name"].ToString(), repoUri, repo.ContainsKey("Priority") ? Convert.ToInt32(repo["Priority"].ToString()) : defaultPriority, repo.ContainsKey("Trusted") ? Convert.ToBoolean(repo["Trusted"].ToString()) : defaultTrusted, repoCredentialInfo)); } catch (Exception e) { if (!(e is ArgumentException || e is PSInvalidOperationException)) { ThrowTerminatingError(new ErrorRecord( new PSInvalidOperationException(e.Message), "TerminatingErrorParsingAddingIndividualRepo", ErrorCategory.InvalidArgument, this)); } WriteError(new ErrorRecord( new PSInvalidOperationException(e.Message), "ErrorParsingIndividualRepo", ErrorCategory.InvalidArgument, this)); return(null); } }
private List <PSResourceInfo> InstallPackage( IEnumerable <PSResourceInfo> pkgsToInstall, // those found to be required to be installed (includes Dependency packages as well) string repoName, string repoUri, PSCredentialInfo repoCredentialInfo, PSCredential credential, bool isLocalRepo) { List <PSResourceInfo> pkgsSuccessfullyInstalled = new List <PSResourceInfo>(); int totalPkgs = pkgsToInstall.Count(); // Counters for tracking current package out of total int totalInstalledPkgCount = 0; foreach (PSResourceInfo pkg in pkgsToInstall) { totalInstalledPkgCount++; var tempInstallPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); try { // Create a temp directory to install to var dir = Directory.CreateDirectory(tempInstallPath); // should check it gets created properly // To delete file attributes from the existing ones get the current file attributes first and use AND (&) operator // with a mask (bitwise complement of desired attributes combination). // TODO: check the attributes and if it's read only then set it // attribute may be inherited from the parent // TODO: are there Linux accommodations we need to consider here? dir.Attributes &= ~FileAttributes.ReadOnly; _cmdletPassedIn.WriteVerbose(string.Format("Begin installing package: '{0}'", pkg.Name)); if (!_quiet) { int activityId = 0; int percentComplete = ((totalInstalledPkgCount * 100) / totalPkgs); string activity = string.Format("Installing {0}...", pkg.Name); string statusDescription = string.Format("{0}% Complete", percentComplete); _cmdletPassedIn.WriteProgress( new ProgressRecord(activityId, activity, statusDescription)); } // Create PackageIdentity in order to download string createFullVersion = pkg.Version.ToString(); if (pkg.IsPrerelease) { createFullVersion = pkg.Version.ToString() + "-" + pkg.Prerelease; } if (!NuGetVersion.TryParse(createFullVersion, out NuGetVersion pkgVersion)) { var message = String.Format("{0} package could not be installed with error: could not parse package '{0}' version '{1} into a NuGetVersion", pkg.Name, pkg.Version.ToString()); var ex = new ArgumentException(message); var packageIdentityVersionParseError = new ErrorRecord(ex, "psdataFileNotExistError", ErrorCategory.ReadError, null); _cmdletPassedIn.WriteError(packageIdentityVersionParseError); _pkgNamesToInstall.RemoveAll(x => x.Equals(pkg.Name, StringComparison.InvariantCultureIgnoreCase)); continue; } var pkgIdentity = new PackageIdentity(pkg.Name, pkgVersion); var cacheContext = new SourceCacheContext(); if (isLocalRepo) { /* Download from a local repository -- this is slightly different process than from a server */ var localResource = new FindLocalPackagesResourceV2(repoUri); var resource = new LocalDownloadResource(repoUri, localResource); // Actually downloading the .nupkg from a local repo var result = resource.GetDownloadResourceResultAsync( identity: pkgIdentity, downloadContext: new PackageDownloadContext(cacheContext), globalPackagesFolder: tempInstallPath, logger: NullLogger.Instance, token: _cancellationToken).GetAwaiter().GetResult(); // Create the package extraction context PackageExtractionContext packageExtractionContext = new PackageExtractionContext( packageSaveMode: PackageSaveMode.Nupkg, xmlDocFileSaveMode: PackageExtractionBehavior.XmlDocFileSaveMode, clientPolicyContext: null, logger: NullLogger.Instance); // Extracting from .nupkg and placing files into tempInstallPath result.PackageReader.CopyFiles( destination: tempInstallPath, packageFiles: result.PackageReader.GetFiles(), extractFile: new PackageFileExtractor( result.PackageReader.GetFiles(), packageExtractionContext.XmlDocFileSaveMode).ExtractPackageFile, logger: NullLogger.Instance, token: _cancellationToken); result.Dispose(); } else { /* Download from a non-local repository */ // Set up NuGet API resource for download PackageSource source = new PackageSource(repoUri); // Explicitly passed in Credential takes precedence over repository CredentialInfo if (credential != null) { string password = new NetworkCredential(string.Empty, credential.Password).Password; source.Credentials = PackageSourceCredential.FromUserInput(repoUri, credential.UserName, password, true, null); } else if (repoCredentialInfo != null) { PSCredential repoCredential = Utils.GetRepositoryCredentialFromSecretManagement( repoName, repoCredentialInfo, _cmdletPassedIn); string password = new NetworkCredential(string.Empty, repoCredential.Password).Password; source.Credentials = PackageSourceCredential.FromUserInput(repoUri, repoCredential.UserName, password, true, null); } var provider = FactoryExtensionsV3.GetCoreV3(NuGet.Protocol.Core.Types.Repository.Provider); SourceRepository repository = new SourceRepository(source, provider); /* Download from a non-local repository -- ie server */ var downloadResource = repository.GetResourceAsync <DownloadResource>().GetAwaiter().GetResult(); DownloadResourceResult result = null; try { result = downloadResource.GetDownloadResourceResultAsync( identity: pkgIdentity, downloadContext: new PackageDownloadContext(cacheContext), globalPackagesFolder: tempInstallPath, logger: NullLogger.Instance, token: _cancellationToken).GetAwaiter().GetResult(); } catch (Exception e) { _cmdletPassedIn.WriteVerbose(string.Format("Error attempting download: '{0}'", e.Message)); } finally { // Need to close the .nupkg if (result != null) { result.Dispose(); } } } _cmdletPassedIn.WriteVerbose(string.Format("Successfully able to download package from source to: '{0}'", tempInstallPath)); // pkgIdentity.Version.Version gets the version without metadata or release labels. string newVersion = pkgIdentity.Version.ToNormalizedString(); string normalizedVersionNoPrerelease = newVersion; if (pkgIdentity.Version.IsPrerelease) { // eg: 2.0.2 normalizedVersionNoPrerelease = pkgIdentity.Version.ToNormalizedString().Substring(0, pkgIdentity.Version.ToNormalizedString().IndexOf('-')); } string tempDirNameVersion = isLocalRepo ? tempInstallPath : Path.Combine(tempInstallPath, pkgIdentity.Id.ToLower(), newVersion); var version4digitNoPrerelease = pkgIdentity.Version.Version.ToString(); string moduleManifestVersion = string.Empty; var scriptPath = Path.Combine(tempDirNameVersion, pkg.Name + PSScriptFileExt); var modulePath = Path.Combine(tempDirNameVersion, pkg.Name + PSDataFileExt); // Check if the package is a module or a script var isModule = File.Exists(modulePath); string installPath; if (_savePkg) { // For save the installation path is what is passed in via -Path installPath = _pathsToInstallPkg.FirstOrDefault(); // If saving as nupkg simply copy the nupkg and move onto next iteration of loop // asNupkg functionality only applies to Save-PSResource if (_asNupkg) { var nupkgFile = pkgIdentity.ToString().ToLower() + ".nupkg"; File.Copy(Path.Combine(tempDirNameVersion, nupkgFile), Path.Combine(installPath, nupkgFile)); _cmdletPassedIn.WriteVerbose(string.Format("'{0}' moved into file path '{1}'", nupkgFile, installPath)); pkgsSuccessfullyInstalled.Add(pkg); continue; } } else { // PSModules: /// ./Modules /// ./Scripts /// _pathsToInstallPkg is sorted by desirability, Find will pick the pick the first Script or Modules path found in the list installPath = isModule ? _pathsToInstallPkg.Find(path => path.EndsWith("Modules", StringComparison.InvariantCultureIgnoreCase)) : _pathsToInstallPkg.Find(path => path.EndsWith("Scripts", StringComparison.InvariantCultureIgnoreCase)); } if (isModule) { var moduleManifest = Path.Combine(tempDirNameVersion, pkgIdentity.Id + PSDataFileExt); if (!File.Exists(moduleManifest)) { var message = String.Format("{0} package could not be installed with error: Module manifest file: {1} does not exist. This is not a valid PowerShell module.", pkgIdentity.Id, moduleManifest); var ex = new ArgumentException(message); var psdataFileDoesNotExistError = new ErrorRecord(ex, "psdataFileNotExistError", ErrorCategory.ReadError, null); _cmdletPassedIn.WriteError(psdataFileDoesNotExistError); _pkgNamesToInstall.RemoveAll(x => x.Equals(pkg.Name, StringComparison.InvariantCultureIgnoreCase)); continue; } if (!Utils.TryParsePSDataFile(moduleManifest, _cmdletPassedIn, out Hashtable parsedMetadataHashtable)) { // Ran into errors parsing the module manifest file which was found in Utils.ParseModuleManifest() and written. continue; } moduleManifestVersion = parsedMetadataHashtable["ModuleVersion"] as string; // Accept License verification if (!_savePkg && !CallAcceptLicense(pkg, moduleManifest, tempInstallPath, newVersion)) { continue; } // If NoClobber is specified, ensure command clobbering does not happen if (_noClobber && !DetectClobber(pkg.Name, parsedMetadataHashtable)) { continue; } } // Delete the extra nupkg related files that are not needed and not part of the module/script DeleteExtraneousFiles(pkgIdentity, tempDirNameVersion); if (_includeXML) { CreateMetadataXMLFile(tempDirNameVersion, installPath, pkg, isModule); } MoveFilesIntoInstallPath( pkg, isModule, isLocalRepo, tempDirNameVersion, tempInstallPath, installPath, newVersion, moduleManifestVersion, scriptPath); _cmdletPassedIn.WriteVerbose(String.Format("Successfully installed package '{0}' to location '{1}'", pkg.Name, installPath)); pkgsSuccessfullyInstalled.Add(pkg); } catch (Exception e) { _cmdletPassedIn.WriteError( new ErrorRecord( new PSInvalidOperationException( message: $"Unable to successfully install package '{pkg.Name}': '{e.Message}'", innerException: e), "InstallPackageFailed", ErrorCategory.InvalidOperation, _cmdletPassedIn)); _pkgNamesToInstall.RemoveAll(x => x.Equals(pkg.Name, StringComparison.InvariantCultureIgnoreCase)); } finally { // Delete the temp directory and all its contents _cmdletPassedIn.WriteVerbose(string.Format("Attempting to delete '{0}'", tempInstallPath)); if (Directory.Exists(tempInstallPath)) { if (!TryDeleteDirectory(tempInstallPath, out ErrorRecord errorMsg)) { _cmdletPassedIn.WriteError(errorMsg); } else { _cmdletPassedIn.WriteVerbose(String.Format("Successfully deleted '{0}'", tempInstallPath)); } } } } return(pkgsSuccessfullyInstalled); }
private PSRepositoryInfo NameParameterSetHelper(string repoName, Uri repoUri, int repoPriority, bool repoTrusted, PSCredentialInfo repoCredentialInfo) { if (repoName.Equals("PSGallery", StringComparison.OrdinalIgnoreCase)) { WriteVerbose("Provided Name (NameParameterSet) but with invalid value of PSGallery"); throw new ArgumentException("Cannot register PSGallery with -Name parameter. Try: Register-PSResourceRepository -PSGallery"); } return(AddToRepositoryStoreHelper(repoName, repoUri, repoPriority, repoTrusted, repoCredentialInfo)); }
private PSRepositoryInfo AddToRepositoryStoreHelper(string repoName, Uri repoUri, int repoPriority, bool repoTrusted, PSCredentialInfo repoCredentialInfo) { // 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)) { throw new ArgumentException("Invalid Uri, must be one of the following Uri schemes: HTTPS, HTTP, FTP, File Based"); } if (repoCredentialInfo != null) { bool isSecretManagementModuleAvailable = Utils.IsSecretManagementModuleAvailable(repoName, this); if (repoCredentialInfo.Credential != null) { if (!isSecretManagementModuleAvailable) { ThrowTerminatingError(new ErrorRecord( new PSInvalidOperationException($"Microsoft.PowerShell.SecretManagement module is not found, but is required for saving PSResourceRepository {repoName}'s Credential in a vault."), "RepositoryCredentialSecretManagementUnavailableModule", ErrorCategory.ResourceUnavailable, this)); } else { Utils.SaveRepositoryCredentialToSecretManagementVault(repoName, repoCredentialInfo, this); } } if (!isSecretManagementModuleAvailable) { 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."); } } WriteVerbose("All required values to add to repository provided, calling internal Add() API now"); if (!ShouldProcess(repoName, "Register repository to repository store")) { return(null); } return(RepositorySettings.Add(repoName, repoUri, repoPriority, repoTrusted, repoCredentialInfo)); }
private PSRepositoryInfo RepoValidationHelper(Hashtable repo) { WriteVerbose(String.Format("Parsing through repository: {0}", repo["Name"])); Uri repoUri = null; if (repo.ContainsKey("Uri")) { if (String.IsNullOrEmpty(repo["Uri"].ToString())) { WriteError(new ErrorRecord( new PSInvalidOperationException("Repository Uri cannot be null if provided"), "NullUriForRepositoriesParameterSetUpdate", ErrorCategory.InvalidArgument, this)); return(null); } if (!Utils.TryCreateValidUri(uriString: repo["Uri"].ToString(), cmdletPassedIn: this, uriResult: out repoUri, errorRecord: out ErrorRecord errorRecord)) { WriteError(errorRecord); return(null); } } bool repoTrusted = false; isSet = false; if (repo.ContainsKey("Trusted")) { repoTrusted = (bool)repo["Trusted"]; isSet = true; } PSCredentialInfo repoCredentialInfo = null; if (repo.ContainsKey("CredentialInfo") && !Utils.TryCreateValidPSCredentialInfo(credentialInfoCandidate: (PSObject)repo["CredentialInfo"], cmdletPassedIn: this, repoCredentialInfo: out repoCredentialInfo, errorRecord: out ErrorRecord errorRecord1)) { WriteError(errorRecord1); return(null); } try { var updatedRepo = RepositorySettings.UpdateRepositoryStore(repo["Name"].ToString(), repoUri, repo.ContainsKey("Priority") ? Convert.ToInt32(repo["Priority"].ToString()) : DefaultPriority, repoTrusted, isSet, DefaultPriority, repoCredentialInfo, this, out string errorMsg); if (!string.IsNullOrEmpty(errorMsg)) { WriteError(new ErrorRecord( new PSInvalidOperationException(errorMsg), "ErrorSettingRepository", ErrorCategory.InvalidData, this)); } return(updatedRepo); } catch (Exception e) { WriteError(new ErrorRecord( new PSInvalidOperationException(e.Message), "ErrorSettingIndividualRepoFromRepositories", ErrorCategory.InvalidArgument, this)); return(null); } }
private IEnumerable <PSResourceInfo> SearchFromRepository( string repositoryName, Uri repositoryUri, PSCredentialInfo repositoryCredentialInfo) { PackageSearchResource resourceSearch; PackageMetadataResource resourceMetadata; SearchFilter filter; SourceCacheContext context; // File based Uri scheme. if (repositoryUri.Scheme == Uri.UriSchemeFile) { FindLocalPackagesResourceV2 localResource = new FindLocalPackagesResourceV2(repositoryUri.ToString()); resourceSearch = new LocalPackageSearchResource(localResource); resourceMetadata = new LocalPackageMetadataResource(localResource); filter = new SearchFilter(_prerelease); context = new SourceCacheContext(); foreach (PSResourceInfo pkg in SearchAcrossNamesInRepository( repositoryName: repositoryName, pkgSearchResource: resourceSearch, pkgMetadataResource: resourceMetadata, searchFilter: filter, sourceContext: context)) { yield return(pkg); } yield break; } // Check if ADOFeed- for which searching for Name with wildcard has a different logic flow. if (repositoryUri.ToString().Contains("pkgs.")) { _isADOFeedRepository = true; } // HTTP, HTTPS, FTP Uri schemes (only other Uri schemes allowed by RepositorySettings.Read() API). PackageSource source = new PackageSource(repositoryUri.ToString()); // Explicitly passed in Credential takes precedence over repository CredentialInfo. if (_credential != null) { string password = new NetworkCredential(string.Empty, _credential.Password).Password; source.Credentials = PackageSourceCredential.FromUserInput(repositoryUri.ToString(), _credential.UserName, password, true, null); _cmdletPassedIn.WriteVerbose("credential successfully set for repository: " + repositoryName); } else if (repositoryCredentialInfo != null) { PSCredential repoCredential = Utils.GetRepositoryCredentialFromSecretManagement( repositoryName, repositoryCredentialInfo, _cmdletPassedIn); string password = new NetworkCredential(string.Empty, repoCredential.Password).Password; source.Credentials = PackageSourceCredential.FromUserInput(repositoryUri.ToString(), repoCredential.UserName, password, true, null); _cmdletPassedIn.WriteVerbose("credential successfully read from vault and set for repository: " + repositoryName); } // GetCoreV3() API is able to handle V2 and V3 repository endpoints. var provider = FactoryExtensionsV3.GetCoreV3(NuGet.Protocol.Core.Types.Repository.Provider); SourceRepository repository = new SourceRepository(source, provider); resourceSearch = null; resourceMetadata = null; try { resourceSearch = repository.GetResourceAsync <PackageSearchResource>().GetAwaiter().GetResult(); resourceMetadata = repository.GetResourceAsync <PackageMetadataResource>().GetAwaiter().GetResult(); } catch (Exception e) { Utils.WriteVerboseOnCmdlet(_cmdletPassedIn, "Error retrieving resource from repository: " + e.Message); } if (resourceSearch == null || resourceMetadata == null) { yield break; } filter = new SearchFilter(_prerelease); context = new SourceCacheContext(); foreach (PSResourceInfo pkg in SearchAcrossNamesInRepository( repositoryName: String.Equals(repositoryUri.AbsoluteUri, _psGalleryUri, StringComparison.InvariantCultureIgnoreCase) ? _psGalleryRepoName : (String.Equals(repositoryUri.AbsoluteUri, _poshTestGalleryUri, StringComparison.InvariantCultureIgnoreCase) ? _poshTestGalleryRepoName : repositoryName), pkgSearchResource: resourceSearch, pkgMetadataResource: resourceMetadata, searchFilter: filter, sourceContext: context)) { yield return(pkg); } }
private PSRepositoryInfo UpdateRepositoryStoreHelper(string repoName, Uri repoUri, int repoPriority, bool repoTrusted, PSCredentialInfo repoCredentialInfo) { if (repoUri != null && !(repoUri.Scheme == System.Uri.UriSchemeHttp || repoUri.Scheme == System.Uri.UriSchemeHttps || repoUri.Scheme == System.Uri.UriSchemeFtp || repoUri.Scheme == System.Uri.UriSchemeFile)) { throw new ArgumentException("Invalid Uri, must be one of the following Uri schemes: HTTPS, HTTP, FTP, File Based"); } // 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("*")) { throw new ArgumentException("Name cannot be null/empty, contain asterisk or be just whitespace"); } // check PSGallery Uri is not trying to be set if (repoName.Equals("PSGallery", StringComparison.OrdinalIgnoreCase) && repoUri != null) { throw new ArgumentException("The PSGallery repository has a pre-defined Uri. Setting the -Uri parameter for this repository is not allowed, instead try running 'Register-PSResourceRepository -PSGallery'."); } // check PSGallery CredentialInfo is not trying to be set if (repoName.Equals("PSGallery", StringComparison.OrdinalIgnoreCase) && repoCredentialInfo != null) { throw new ArgumentException("The PSGallery repository does not require authentication. Setting the -CredentialInfo parameter for this repository is not allowed, instead try running 'Register-PSResourceRepository -PSGallery'."); } // 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, this); if (repoCredentialInfo.Credential != null) { if (!isSecretManagementModuleAvailable) { ThrowTerminatingError(new ErrorRecord( new PSInvalidOperationException($"Microsoft.PowerShell.SecretManagement module is not found, but is required for saving PSResourceRepository {repoName}'s Credential in a vault."), "RepositoryCredentialSecretManagementUnavailableModule", ErrorCategory.ResourceUnavailable, this)); } else { Utils.SaveRepositoryCredentialToSecretManagementVault(repoName, repoCredentialInfo, this); } } if (!isSecretManagementModuleAvailable) { 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) { throw new ArgumentException("Either Uri, Priority, Trusted or CredentialInfo parameters must be requested to be set"); } WriteVerbose("All required values to set repository provided, calling internal Update() API now"); if (!ShouldProcess(repoName, "Set repository's value(s) in repository store")) { return(null); } return(RepositorySettings.Update(repoName, repoUri, repoPriority, _trustedNullable, repoCredentialInfo)); }