Artifactory restore nuget packages with authentication from powershell - powershell

Our team started using Artifactory a few weeks ago and one of the challenges we are currently trying to work through is authentication. Currently we have every developer setup in Artifactory with an account login, we have a build.ps1 file that we use to restore our nuget packages but we're trying to automate this process.
Here is what our powershell script looks like. But it is not prompting the user to enter their username and password, unless they add it as parameters to the .\build.ps1 command line but the issue there is that the password is being entered in plain text.
"Updating NuGet Dependencies"
$nuget = "$rootDir\.nuget\NuGet.exe"
if ($nuser)
{
Invoke-Expression "$nuget Sources Update -Name 'Artifactory' -UserName $user -Password $pass"
}
Invoke-Expression "$nuget install -NonInteractive -DisableParallel"
if ($lastexitcode -ne 0) {
Write-Host -foreground red "Error occurred downloading dependencies."
exit 1
}
dir . | where { $_.psiscontainer } | where { (test-path (join-path $_.fullname "packages.config")) } | foreach {
Invoke-Expression "$nuget install '$($_.fullname)\packages.config' -NonInteractive -DisableParallel"
if ($lastexitcode -ne 0) {
Write-Host -foreground red "Error occurred downloading project dependencies."
exit 1
}
}

This article on handling passwords and credentials might prove useful to you:
Working with Passwords, Secure Strings and Credentials in Windows PowerShell

I had some problems with setting the credentials.
My solutions was to upgrade nuget.exe (v4.3.0 from v3.x.x) and using the Add Sources with the username/ password, with the ApiKey from the Artifactory as the password.

Related

How to run Powershell as an Admin yet execute functions as a Standard user?

I have a PowerShell script that has a function that deletes a certificate based on certain values in the Subject. This function works but only if I run the commands in a normal PowerShell window. If I run the PowerShell as an admin with separate admin credentials it fails.
The reason it fails is because when my script gets to the function where PowerShell parses the Personal Store of the Current User, it checks under the admin account running the script and not the current user itself. Is it possible to fix this within the Function itself?
Can I tell PowerShell to check the Currently Logged in Users Personal certificate Store and not the certificate store of the Admin user that is executing the script?
Unfortunately I need admin credentials to execute PowerShell scripts. I can't run them locally with my normal account.
function deleteCert(){
try {
Write-Host "Deleting Some Certificate..."
$cert = Get-ChildItem -Path Cert:\CurrentUser\My -Recurse | Where-Object {$_.Subject -Like "*Some Certificate*"}
if($cert -eq $null){
Write-Host "Unable to locate Certificate"
}else{
Remove-Item $cert
Write-Host "Deleting Some Certificate Successful..."
}
}catch {
Write-Error "Exception caught in removing certificate"
Exit
}
}

PowerShell script for software installation using chocolatey

enter code here
# Step 1) install Chocolatey when needed
if (-not (Test-Path -Path "$env:ProgramData\Chocolatey\choco.exe" -PathType Leaf)) {
# from https://chocolatey.org/install
Set-ExecutionPolicy Bypass -Scope Process -Force
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
}
# Step 2) define the array of packages you are offering
$Packages = 'googlechrome','firefox','codeblocks','windbg','nasm',
'explorersuite','pestudio','vscode','sysinternals','python'
# Step 3) define the Show-Menu function
function Show-Menu {
Clear-Host
Write-Host "**********************************************"
Write-Host "LIST OF SOFTWARES"
# write the options using the array of packages
for ($i = 0; $i -lt $Packages.Count; $i++) {
# {0,2} means right align with spaces to max 2 characters
Write-Host ('{0,2}. {1}' -f ($i + 1), $Packages[$i])
}
Write-Host " q. Exit the script"
Write-Host "*************************************************"
Write-Host
}
# Step 4) enter an endless loop you only exit if the user enters 'q'
while ($true) {
Show-Menu
$UserInput = Read-Host "Enter the software number to be installed"
# test if the user wants to quit and if so, break the loop
if ($UserInput -eq 'q') { break }
# test if the user entered a number between 1 and the total number of packages (inclusive)
if ([int]::TryParse($UserInput,[ref]$null) -and 1..$Packages.Count -contains [int]$UserInput) {
# here you install the chosen package using the array index number (= user input number minus 1)
$packageIndex = [int]$UserInput - 1
Write-Host "Installing $($Packages[$packageIndex])"
choco install $Packages[$packageIndex] -y
}
else {
$availableOptions = 1..$Packages.Count -join ','
Write-Host "Error in selection, choose $availableOptions or q" -ForegroundColor Red
}
$null = Read-Host "Press Enter to continue"
}
Problem Statement:
I am writing power shell script using chocolatey for software downloading and installing automatically. My script will display a menu with the list of software's whenever users enter the number the corresponding software will download and install.
When i run the script the executable files are not showing in control panel and desktop icon is also not creating but i am getting the message in power-shell terminal that the software is installed but i am not able to see that application.
I need to put some conditions in my script they are:
If the software is already installed then the software should not be downloaded
When the software is installed it has to shown in control panel and desktop icon should be created.
If any upgrade is their like for googlechrome and firefox generally up gradation takes place then the script has to upgrade.
Please help me and edit my script if anything is wrong
Thanks in advance
Referencing this answer, check to see if the relevant software is installed by checking the following registry keys:
$InstalledSoftware = Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*
$InstalledSoftware += Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*
If it's installed, you can either skip the installation altogether, or...
You can get the package managed under Chocolatey by "installing" the package anyways, but provide the -n (--skippowershell) parameter:
choco install -n packageName
This will download the package metadata but skip the actual PowerShell code (chocolateyInstall.ps1, which is embedded into all Chocolatey packages). This is the piece which runs MSIEXEC, an EXE installer, extracts zip archives for packages without a proper installer, etc. This has the benefit of allowing future updates to be manageable by Chocolatey without reinstalling the software which already exists.
Note: There may be some nuance surrounding specific packages you'll have to figure out, but for the majority of what is available as a Chocolatey package this approach will work.

In PowerShell script, how can I restore packages to resolve error: This project references NuGet package(s) that are missing on this computer

I am tasked with writing a PowerShell script to download the latest source code for a given branch, rebuild it and deploy it. The script I've written, is able to download projects, and in most cases has been able to rebuild them. But with one web project I get this error:
error : This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is ..\packages\Microsoft.Net.Compilers.2.0.1\build\Microsoft.Net.Compilers.props.
I've researched if PowerShell has a Update-Package command like the one available in the VS command prompt but have been unable to find the equivalent.
I know there's a cmdlet for Packages but from what I've seen they're used to update a specific package...what I need is to be able to have it download/update all packages referenced in the project.
Some points that might be of interest...
When I get latest on the solution to a new empty folder, the only thing in the packages folder is Modernizr.2.6.2. This is the same whether I'm getting latest in VS or in my PowerShell script.
If I open the solution within VS 2017, I am able to rebuild the solution with no problems. It downloads/installs over a dozen other packages...one of which is the Microsoft.Net.Compilers.props package referred to in the error message.
But if I delete everything and re-download the source code and then through my PowerShell script I call MSBuild to rebuild the solution I get the error mentioned above. It never seems to download/install the missing packages.
Anyone have any ideas how I can use MSBuild within my PowerShell script to rebuild the project and have it automatically update/install any packages it needs?
Thanks
I was able to find a solution to my problem on this page :Quickly Restore NuGet Packages With PowerShell
On that page is a script that uses Nuget.exe to download the packages based on the packages.config:
#This will be the root folder of all your solutions - we will search all children of
this folder
$SOLUTIONROOT = "C:\Projects\"
#This is where your NuGet.exe is located
$NUGETLOCATION = "C:\Projects\NuGet\NuGet.exe"
Function RestoreAllPackages ($BaseDirectory)
{
Write-Host "Starting Package Restore - This may take a few minutes ..."
$PACKAGECONFIGS = Get-ChildItem -Recurse -Force $BaseDirectory -ErrorAction SilentlyContinue | Where-Object { ($_.PSIsContainer -eq $false) -and ( $_.Name -eq "packages.config")}
ForEach($PACKAGECONFIG in $PACKAGECONFIGS)
{
Write-Host $PACKAGECONFIG.FullName
$NugetRestore = $NUGETLOCATION + " install " + " '" + $PACKAGECONFIG.FullName + "' -OutputDirectory '" + $PACKAGECONFIG.Directory.parent.FullName + "\packages'"
Write-Host $NugetRestore
Invoke-Expression $NugetRestore
}
}
RestoreAllPackages $SOLUTIONROOT
Write-Host "Press any key to continue ..."
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
I modified and added this function to my PS script and call it first to download all the packages and that does the job!
You need to call the restore target of MSBuild to download NuGet packages. You can do that by running something like:
git clone [your repo]
cd [your repo]
msbuild /target:Restore [Your Solution]
msbuild [Your Solution]
function buildVS
{
param
(
[parameter(Mandatory=$true)]
[String] $path,
[parameter(Mandatory=$false)]
[bool] $nuget = $true,
[parameter(Mandatory=$false)]
[bool] $clean = $true
)
process
{
$msBuildExe = 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\MSBuild\Current\Bin\MSBuild.exe'
if ($nuget) {
Write-Host "Restoring NuGet packages" -foregroundcolor green
& "$($msBuildExe)" "$($path)" /p:Configuration=Release /p:platform=x64 /t:restore
}
if ($clean) {
Write-Host "Cleaning $($path)" -foregroundcolor green
& "$($msBuildExe)" "$($path)" /t:Clean /m
}
Write-Host "Building $($path)" -foregroundcolor green
& "$($msBuildExe)" "$($path)" /t:Build /p:Configuration=Release /p:platform=x64
}
}

Cannot access Chocolatey package from Azure DevOps Artifact Feed

The flowing code has been pushed to an Azure DevOps Artifacts Feed:
schily-cdrtools
Pushing the nuget package and downloading work without issues using nuget.exe:
nuget.exe push -Source "cdrtools-artifacts" -ApiKey AzureDevOps schily-cdrtools.3.2.1.nupkg
nuget.exe install -Source "cdrtools-artifacts" schily-cdrtools
However, attempting to register this source with Chocolatey results in a 404 error using either a v2 or v3 nuget registration:
choco source add -n=schily-artifacts `
>> -s="https://flapjacks.pkgs.visualstudio.com/_packaging/schily-artifacts/nuget/v3/index.json" `
>> -u="xxxxxxxx" -p="xxxxxxxxxxx"
Error retrieving packages from source 'https://flapjacks.visualstudio.com/_packaging/schily-artifacts/nuget/v3/index.json':
The remote server returned an error: (404) Not Found.
schily-cdrtools not installed. The package was not found with the source(s) listed.
Source(s): 'https://flapjacks.visualstudio.com/_packaging/schily-artifacts/nuget/v3/index.json'
NOTE: When you specify explicit sources, it overrides default sources.
If the package version is a prerelease and you didn't specify `--pre`,
the package may not be found.
Please see https://chocolatey.org/docs/troubleshooting for more
assistance.
...and the same 404 error when using v2:
choco source add -n=schily-artifacts `
>> -s="https://flapjacks.pkgs.visualstudio.com/_packaging/schily-artifacts/nuget/v2" `
>> -u="xxxxxxxx" -p="xxxxxxx"
Trying to list with the v2 registration comes up with no packages found, however when running choco list with the v3 it comes back with a 404 error.
Finally, trying with Install-Package failes with a credentials issue:
Install-Package schily-cdrtools
WARNING: Cannot access 'https://flapjacks.pkgs.visualstudio.com/_packaging/schily-artifacts/nuget/v3/index.json'. Are you missing 'Credential' parameter in the cmdlet?
Install-Package : No match was found for the specified search criteria and package name 'schily-cdrtools'. Try Get-Packa
geSource to see all available registered package sources.
At line:1 char:1
+ Install-Package schily-cdrtools
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Microsoft.PowerShel\u2026lets.InstallPackage:InstallPackage) [Install-Package
], Exception
+ FullyQualifiedErrorId : NoMatchFoundForCriteria,Microsoft.PowerShell.PackageManagement.Cmdlets.InstallPackage
Any ideas no what I'm missing?
I've been using the following as a guide:
https://blog.pauby.com/post/chocolatey-repository-using-azure-devops-artifacts-feed/
Cannot access Chocolatey package from Azure DevOps Artifact Feed
I could not reproduce this issue after created a sample based on the steps in that guide. But I would like provide some troubleshooting to you:
Check your Chocolatey version, mine is Chocolatey v0.10.15.
Use PAT instead of password when you add Chocolatey Azure DevOps Feed named source.
Run the command line with Administrator.
The command line should be complete and does not require a branch, like:
choco source add -n=MyCustomFeed -s="https://pkgs.dev.azure.com/<MyOrgName>/_packaging/<FeedName>/nuget/v2" -u="MyAccount.com" -p="PAT"
My Test Result:
Hope this helps.
The PackageManagement cmdlets are broken currently so using Install-Package without the -Credential parameter will fail. You need to add the -Credential parameter to all of the PackageManagement cmdlets for them to work.
If I run (exactly):
choco source add -n=schily-artifacts -s="https://flapjacks.pkgs.visualstudio.com/_packaging/schily-artifacts/nuget/v2" -u="xxxxxxxx" -p="xxxxxxxxxxx"
Then I get:
Chocolatey v0.10.15
Added schily-artifacts - https://flapjacks.pkgs.visualstudio.com/_packaging/schily-artifacts/nuget/v2 (Priority 0)
Chocolatey doesn't validate the feed until you use it:
choco list --source=schily-artifacts
Chocolatey v0.10.15
Invalid credentials specified.
Invalid credentials specified.
Invalid credentials specified.
Invalid credentials specified.
Invalid credentials specified.
Invalid credentials specified.
Invalid credentials specified.
Invalid credentials specified.
[NuGet] Not able to contact source 'https://flapjacks.pkgs.visualstudio.com/_packaging/schily-artifacts/nuget/v2'. Error was The remote server returned an error: (401) Unauthorized.
Invalid credentials specified.
Invalid credentials specified.
Invalid credentials specified.
Invalid credentials specified.
Invalid credentials specified.
Invalid credentials specified.
Invalid credentials specified.
Invalid credentials specified.
[NuGet] Not able to contact source 'https://flapjacks.pkgs.visualstudio.com/_packaging/schily-artifacts/nuget/v2'. Error was The remote server returned an error: (401) Unauthorized.
0 packages found.
Which is what I'd expect (as the credentials are invalid). So I'm not sure where your errors are coming from when adding the source.
Another approach with Credential Provider, slightly modified version of the script that was publish in github.com/chocolatey/choco/issues/1721 (last lines were changed to use choco instead of nuget command).
The script runs a Credential Provider (which prompts you to login to Azure DevOps and automatically generate a PAT). The returned PAT is used with the same choco command as in Leo Liu's answer
param (
[Parameter(Mandatory=$true)]
[string]$feedName,
[Parameter(Mandatory=$true)]
[string]$url
)
$profilePath = [System.Environment]::GetFolderPath([System.Environment+SpecialFolder]::UserProfile)
$pluginLocation = [System.IO.Path]::Combine($profilePath, ".nuget", "plugins");
$localNetfxCredProviderPath = [System.IO.Path]::Combine("netfx", "CredentialProvider.Microsoft");
$fullNetfxCredProviderPath = [System.IO.Path]::Combine($pluginLocation, $localNetfxCredProviderPath)
$netfxExists = Test-Path -Path ($fullNetfxCredProviderPath)
if($netfxExists -eq $false)
{
Write-Host "Installing credential provider..."
iex "& { $(irm https://aka.ms/install-artifacts-credprovider.ps1) } -AddNetfx"
$netfxExists = Test-Path -Path ($fullNetfxCredProviderPath)
if($netfxExists -eq $false)
{
Write-Host "Credentials provider is required."
Write-Host "Maybe install manually from https://github.com/microsoft/artifacts-credprovider/releases"
return
}
}
$exe = [System.IO.Path]::Combine($fullNetfxCredProviderPath, 'CredentialProvider.Microsoft.exe')
# It's not possible to disable device based authentication, but we can set timeout to fail immidiately.
$ENV:NUGET_CREDENTIALPROVIDER_VSTS_DEVICEFLOWTIMEOUTSECONDS=0
# Validity period: 1 year. (Can have larger value)
$ENV:NUGET_CREDENTIALPROVIDER_VSTS_SESSIONTIMEMINUTES=365*24*60
# '-V Error' is required not to get extra messages
$msg = & $exe -V Error -U $url -C -F JSON 2>&1 | Out-String
if($lastexitcode -ne 0)
{
Write-Host
Write-Host "$msg"
Write-Host
Write-Host "Failed to run '$exe' ($lastexitcode)"
return
}
try
{
$info = ConvertFrom-Json $msg
}
catch
{
Write-Host
Write-Host "$msg"
Write-Host
return
}
choco source add -v -n="$feedName" -s="$url" -u "$($info.Username)" -p="$($info.Password)"

PowerShell script to deploy ASP.NET Core artifacts to Azure

I need a PowerShell script which will deploy an ASP.NET Core app's artifacts to Azure Web Service. Searching the Internet I managed to find this script:
param($websiteName, $packOutput)
$website = Get-AzureWebsite -Name $websiteName
Stop-AzureWebsite -Name $websiteName
# get the scm url to use with MSDeploy. By default this will be the second in the array
$msdeployurl = $website.EnabledHostNames[1]
$publishProperties = #{'WebPublishMethod'='MSDeploy';
'MSDeployServiceUrl'=$msdeployurl;
'DeployIisAppPath'=$website.Name;
'Username'=$website.PublishingUsername;
'Password'=$website.PublishingPassword
}
$publishScript = "${env:ProgramFiles(x86)}\Microsoft Visual Studio 14.0\Common7\IDE\Extensions\Microsoft\Web Tools\Publish\Scripts\1.2.0\default-publish.ps1"
. $publishScript -publishProperties $publishProperties -packOutput $packOutput
Start-AzureWebsite -Name $websiteName
I am using it the way it is shown on the screenshot:
But...nothing happens as the result of msdeploy command execution: no errors, no data deployed...
So, what is the correct way of deploying ASP.NET Core artifacts with PowerShell?
Visual Studio could generate Windows PowerShell publish script for deploying to a website. The publish script may look like this.
publish script
[cmdletbinding(SupportsShouldProcess=$true)]
param($publishProperties=#{}, $packOutput, $pubProfilePath)
# to learn more about this file visit https://go.microsoft.com/fwlink/?LinkId=524327
try{
if ($publishProperties['ProjectGuid'] -eq $null){
$publishProperties['ProjectGuid'] = 'xxxxxxxx-0260-4800-b864-e9afa92d7fc2'
}
$publishModulePath = Join-Path (Split-Path $MyInvocation.MyCommand.Path) 'publish-module.psm1'
Import-Module $publishModulePath -DisableNameChecking -Force
# call Publish-AspNet to perform the publish operation
Publish-AspNet -publishProperties $publishProperties -packOutput $packOutput -pubProfilePath $pubProfilePath
}
catch{
"An error occurred during publish.`n{0}" -f $_.Exception.Message | Write-Error
}
And a publish module that contains functions that will be used in the scripts. For more information about publishscripts for deploying to a website, please refer to this documentation.