diff --git a/.gitignore b/.gitignore index 6f5244b..a78008f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,61 +1,64 @@ -################# -## Eclipse -################# - -*.pydevproject -.project -.metadata -bin/ -tmp/ -*.tmp -*.bak -*.swp -*~.nib -local.properties -.classpath -.settings/ -.loadpath - -# External tool builders -.externalToolBuilders/ - -# Locally stored "Eclipse launch configurations" -*.launch - -# CDT-specific -.cproject - -# PDT-specific -.buildpath - - -################# -## Visual Studio -################# - ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. # User-specific files *.suo *.user +*.userosscache *.sln.docstates -# Build results +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs +# Build results [Dd]ebug/ +[Dd]ebugPublic/ [Rr]elease/ +[Rr]eleases/ x64/ -build/ +x86/ +bld/ [Bb]in/ [Oo]bj/ +[Ll]og/ + +# Files created and used by our build scripts +nuget.exe +build/ +tools/ +.nuget/CredentialProviderBundle.zip +.nuget/CredentialProvider.VSS.exe +.nuget/EULA_Microsoft Visual Studio Team Services Credential Provider.docx +.nuget/ThirdPartyNotices.txt +AssemblyInfo.g.cs +tests/Scripts/Config-*.json + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ # MSTest test Results [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +project.fragment.lock.json +artifacts/ + *_i.c *_p.c +*_i.h *.ilk *.meta *.obj @@ -75,22 +78,31 @@ build/ *.vssscc .builds *.pidb -*.log +*.svclog *.scc -.vs + +# Chutzpah Test files +_Chutzpah* # Visual C++ cache files ipch/ *.aps *.ncb +*.opendb *.opensdf *.sdf *.cachefile +*.VC.db +*.VC.VC.opendb # Visual Studio profiler *.psess *.vsp *.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ # Guidance Automation Toolkit *.gpState @@ -98,6 +110,10 @@ ipch/ # ReSharper is a .NET coding add-in _ReSharper*/ *.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode # TeamCity is a build add-in _TeamCity* @@ -106,8 +122,16 @@ _TeamCity* *.dotCover # NCrunch -*.ncrunch* +_NCrunch_* .*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ # Installshield output folder [Ee]xpress/ @@ -126,88 +150,127 @@ DocProject/Help/html publish/ # Publish Web Output -*.Publish.xml -*.pubxml +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +#*.pubxml *.publishproj -# NuGet Packages Directory -## TODO: If you have NuGet Package Restore enabled, uncomment the next line -packages/ - -# Windows Azure Build Output -csx +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ *.build.csdef -# Windows Store app package directory +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ # Others -sql/ -*.Cache ClientBin/ -[Ss]tyle[Cc]op.* ~$* *~ *.dbmdl -*.[Pp]ublish.xml +*.dbproj.schemaview +*.jfm *.pfx *.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ # RIA/Silverlight projects Generated_Code/ -# Backup & report files from converting an old project file to a newer -# Visual Studio version. Backup files are not needed, because we have git ;-) +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) _UpgradeReport_Files/ Backup*/ UpgradeLog*.XML UpgradeLog*.htm -############# -## Windows detritus -############# +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings -# Windows image file caches -Thumbs.db -ehthumbs.db +# Microsoft Fakes +FakesAssemblies/ -# Folder config file -Desktop.ini +# GhostDoc plugin setting file +*.GhostDoc.xml -# Recycle Bin used on file shares -$RECYCLE.BIN/ +# Node.js Tools for Visual Studio +.ntvs_analysis.dat -# Mac crap -.DS_Store +# Visual Studio 6 build log +*.plg +# Visual Studio 6 workspace options file +*.opt -############# -## Python -############# +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions -*.py[cod] +# Paket dependency manager +.paket/paket.exe +paket-files/ -# Packages -*.egg -*.egg-info -dist/ -build/ -eggs/ -parts/ -var/ -sdist/ -develop-eggs/ -.installed.cfg +# FAKE - F# Make +.fake/ -# Installer logs -pip-log.txt +# JetBrains Rider +.idea/ +*.sln.iml -# Unit test / coverage reports -.coverage -.tox +# CodeRush +.cr/ -#Translations -*.mo +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc -#Mr Developer -.mr.developer.cfg +# Ignore test results +*.trx +Results.?.xml \ No newline at end of file diff --git a/README.md b/README.md index 90a338a..f7ae695 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,14 @@ # NuGet.Status -This repo contains the website running NuGet's [public status page](https://status.nuget.org). The status page is in an early preview. +This repo contains the website running NuGet's [public status page](https://status.nuget.org). ## Contributing -Pull requests should be based on the `dev` branch. Once a release is planned, the `dev` branch or specific, cherry-picked changes can flow to `master`. +Set up your DEV environment: -To deploy, merge into the `release-{environment}` branch. +```scripts\Setup-DevEnvironment.ps1``` -* `release-dev` deploys to [http://nuget-dev-0-status.azurewebsites.net](http://nuget-dev-0-status.azurewebsites.net) -* `release-int` deploys to [http://nuget-int-0-status.azurewebsites.net](http://nuget-int-0-status.azurewebsites.net) -* `release-prod` deploys to [https://status.nuget.org](https://status.nuget.org) ([http://nuget-prod-status.trafficmanager.net](http://nuget-prod-status.trafficmanager.net)) +Pull requests should be based on the `dev` branch. Once a release is planned, the `dev` branch or specific, cherry-picked changes, can flow to `master`. ## Feedback @@ -18,4 +16,4 @@ If you're having trouble with the NuGet.org Website, file a bug on the [NuGet Ga If you're having trouble with the NuGet client tools (the Visual Studio extension, NuGet.exe command line tool, etc.), file a bug on [NuGet Home](https://github.com/nuget/home/issues). -Check out the [contributing](http://docs.nuget.org/contribute) page to see the best places to log issues and start discussions. The [NuGet Home](https://github.com/NuGet/Home) repo provides an overview of the different NuGet projects available. +Check out the [contributing](http://docs.nuget.org/contribute) page to see the best places to log issues and start discussions. The [NuGet Home](https://github.com/NuGet/Home) repo provides an overview of the different NuGet projects available. \ No newline at end of file diff --git a/build.cmd b/build.cmd new file mode 100644 index 0000000..3db1eab --- /dev/null +++ b/build.cmd @@ -0,0 +1 @@ +PowerShell.exe -NoProfile -ExecutionPolicy ByPass ".\build.ps1 -Configuration 'Release' -Verbose" \ No newline at end of file diff --git a/build.ps1 b/build.ps1 new file mode 100644 index 0000000..bd426c2 --- /dev/null +++ b/build.ps1 @@ -0,0 +1,119 @@ +[CmdletBinding(DefaultParameterSetName='RegularBuild')] +param ( + [ValidateSet("debug", "release")] + [string]$Configuration = 'debug', + [int]$BuildNumber, + [switch]$SkipRestore, + [switch]$SkipSubModules, + [switch]$CleanCache, + [string]$SimpleVersion = '1.0.0', + [string]$SemanticVersion = '1.0.0-zlocal', + [string]$PackageSuffix, + [string]$Branch, + [string]$CommitSHA, + [string]$BuildBranch = '81aeee183e8a171e4c0fd29fc78de509339808ee' +) + +Set-StrictMode -Version 1.0 + +# This script should fail the build if any issue occurs. +trap { + Write-Host "BUILD FAILED: $_" -ForegroundColor Red + Write-Host "ERROR DETAILS:" -ForegroundColor Red + Write-Host $_.Exception -ForegroundColor Red + Write-Host ("`r`n" * 3) + exit 1 +} + +if (-not (Test-Path "$PSScriptRoot/build")) { + New-Item -Path "$PSScriptRoot/build" -ItemType "directory" +} + +# Enable TLS 1.2 since GitHub requires it. +[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12 + +Invoke-WebRequest -UseBasicParsing -Uri "https://raw.githubusercontent.com/NuGet/ServerCommon/$BuildBranch/build/init.ps1" -OutFile "$PSScriptRoot/build/init.ps1" +. "$PSScriptRoot/build/init.ps1" -BuildBranch "$BuildBranch" + +Function Clean-Tests { + [CmdletBinding()] + param() + + Trace-Log 'Cleaning test results' + + Remove-Item (Join-Path $PSScriptRoot "Results.*.xml") +} + +Write-Host ("`r`n" * 3) +Trace-Log ('=' * 60) + +$startTime = [DateTime]::UtcNow +if (-not $BuildNumber) { + $BuildNumber = Get-BuildNumber +} +Trace-Log "Build #$BuildNumber started at $startTime" + +$BuildErrors = @() + +Invoke-BuildStep 'Reset all submodules' { Reset-Submodules } ` + -skip:($SkipSubModules) ` + -ev +BuildErrors + +Invoke-BuildStep "Update NuGetGallery submodule" { + Invoke-Git 'submodule', 'update', '--init', '--', 'src/NuGet.Status/NuGetGallery' + } ` + -skip:($SkipSubModules) ` + -ev +BuildErrors + +Invoke-BuildStep 'Getting private build tools' { Install-PrivateBuildTools } ` + -ev +BuildErrors + +Invoke-BuildStep 'Cleaning test results' { Clean-Tests } ` + -ev +BuildErrors + +Invoke-BuildStep 'Installing NuGet.exe' { Install-NuGet } ` + -ev +BuildErrors + +Invoke-BuildStep 'Clearing package cache' { Clear-PackageCache } ` + -skip:(-not $CleanCache) ` + -ev +BuildErrors + +Invoke-BuildStep 'Clearing artifacts' { Clear-Artifacts } ` + -ev +BuildErrors + +Invoke-BuildStep 'Restoring solution packages' { ` + Install-SolutionPackages -path (Join-Path $PSScriptRoot ".nuget\packages.config") -output (Join-Path $PSScriptRoot "packages") -excludeversion } ` + -skip:$SkipRestore ` + -ev +BuildErrors + +Invoke-BuildStep 'Set version metadata in AssemblyInfo.cs' { + $Paths = ` + (Join-Path $PSScriptRoot "src\NuGet.Status\Properties\AssemblyInfo.g.cs") + + Foreach ($Path in $Paths) { + Set-VersionInfo -Path $Path -Version $SimpleVersion -Branch $Branch -Commit $CommitSHA + } +} ` +-ev +BuildErrors + +Invoke-BuildStep 'Building solution' { + $SolutionPath = Join-Path $PSScriptRoot "src\NuGet.Status.sln" + Build-Solution $Configuration $BuildNumber -MSBuildVersion "15" $SolutionPath -SkipRestore:$SkipRestore ` +} ` +-ev +BuildErrors + +Trace-Log ('-' * 60) + +## Calculating Build time +$endTime = [DateTime]::UtcNow +Trace-Log "Build #$BuildNumber ended at $endTime" +Trace-Log "Time elapsed $(Format-ElapsedTime ($endTime - $startTime))" + +Trace-Log ('=' * 60) + +if ($BuildErrors) { + $ErrorLines = $BuildErrors | %{ ">>> $($_.Exception.Message)" } + Error-Log "Builds completed with $($BuildErrors.Count) error(s):`r`n$($ErrorLines -join "`r`n")" -Fatal +} + +Write-Host ("`r`n" * 3) \ No newline at end of file diff --git a/scripts/Setup-DevEnvironment.ps1 b/scripts/Setup-DevEnvironment.ps1 new file mode 100644 index 0000000..fc6aaa4 --- /dev/null +++ b/scripts/Setup-DevEnvironment.ps1 @@ -0,0 +1,2 @@ +. "$PSScriptRoot/Setup-Submodule.ps1" +. "$PSScriptRoot/Setup-SslCertificate" \ No newline at end of file diff --git a/scripts/Setup-SslCertificate.ps1 b/scripts/Setup-SslCertificate.ps1 new file mode 100644 index 0000000..0454f5f --- /dev/null +++ b/scripts/Setup-SslCertificate.ps1 @@ -0,0 +1,123 @@ +param( + [string]$SiteName = "NuGet Status", + [string]$SitePhysicalPath, + [string]$AppCmdPath +) + +function Get-SiteFQDN() {return "localhost"} +function Get-SiteHttpHost() {return "$(Get-SiteFQDN):80"} +function Get-SiteHttpsHost() {return "$(Get-SiteFQDN):443"} + +function Get-SiteCertificate() { + return @(dir -l "Cert:\LocalMachine\Root" ` + | where {$_.Subject -eq "CN=$(Get-SiteFQDN)"}) ` + | Select-Object -First 1 +} + +function Initialize-SiteCertificate() { + Write-Host "Generating a Self-Signed SSL Certificate for $(Get-SiteFQDN)" + + # Create a new self-signed certificate. New-SelfSignedCertificate can only create + # certificates into the My certificate store. + $myCert = New-SelfSignedCertificate -DnsName $(Get-SiteFQDN) -CertStoreLocation "Cert:\LocalMachine\My" + + # Move the newly created self-signed certificate to the Root store. + $rootStore = New-Object System.Security.Cryptography.X509Certificates.X509Store("Root", "LocalMachine") + $rootStore.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite) + $rootStore.Add($myCert) + $rootStore.Close() + + # Return the self-signed certificate from the Root store. + $cert = Get-SiteCertificate + + if($cert -eq $null) { + throw "Failed to create an SSL Certificate" + } + + return $cert +} + +function Invoke-Netsh() { + $argStr = $([String]::Join(" ", $args)) + $result = netsh @args + $parsed = [Regex]::Match($result, ".*Error: (\d+).*") + + if($parsed.Success) { + $err = $parsed.Groups[1].Value + if($err -ne "183") { + throw $result + } + } elseif ($result -eq "The parameter is incorrect.") { + throw "Parameters for netsh are incorrect:`r`n $argStr" + } else { + Write-Host $result + } +} + +if(!(([Security.Principal.WindowsPrincipal]([System.Security.Principal.WindowsIdentity]::GetCurrent())).IsInRole([Security.Principal.WindowsBuiltInRole]"Administrator"))) { + throw "This script must be run as an admin." +} + +Write-Host "[BEGIN] Setting up IIS Express" -ForegroundColor Cyan + +$ScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path +if(!$SitePhysicalPath) { + $SitePhysicalPath = Join-Path $ScriptRoot "..\src\NuGet.Status" +} +if(!(Test-Path $SitePhysicalPath)) { + throw "Could not find site at $SitePhysicalPath. Use -SitePhysicalPath argument to specify the path." +} +$SitePhysicalPath = Convert-Path $SitePhysicalPath + +# Find IIS Express +if(!$AppCmdPath) { + $IISXVersion = dir 'HKLM:\Software\Microsoft\IISExpress' | + foreach { New-Object System.Version ($_.PSChildName) } | + sort -desc | + select -first 1 + if(!$IISXVersion) { + throw "Could not find IIS Express. Please install IIS Express before running this script, or use -AppCmdPath to specify the path to appcmd.exe for your IIS environment" + } + $IISRegKey = (Get-ItemProperty "HKLM:\Software\Microsoft\IISExpress\$IISXVersion") + $IISExpressDir = $IISRegKey.InstallPath + if(!(Test-Path $IISExpressDir)) { + throw "Can't find IIS Express in $IISExpressDir. Please install IIS Express" + } + $AppCmdPath = "$IISExpressDir\appcmd.exe" +} + +if(!(Test-Path $AppCmdPath)) { + throw "Could not find appcmd.exe in $AppCmdPath!" +} + +# Enable access to the necessary URLs +# S-1-1-0 is the unlocalized version for: user=Everyone +Invoke-Netsh http add urlacl "url=http://$(Get-SiteHttpHost)/" "sddl=D:(A;;GX;;;S-1-1-0)" +Invoke-Netsh http add urlacl "url=https://$(Get-SiteHttpsHost)/" "sddl=D:(A;;GX;;;S-1-1-0)" + +$SiteFullName = "$SiteName ($(Get-SiteFQDN))" + +$sites = @(&$AppCmdPath list site $SiteFullName) +if($sites.Length -gt 0) { + Write-Warning "Site '$SiteFullName' already exists. Deleting and recreating." + &$AppCmdPath delete site "$SiteFullName" +} + +&$AppCmdPath add site /name:"$SiteFullName" /bindings:"http://$(Get-SiteHttpHost),https://$(Get-SiteHttpsHost)" /physicalPath:$SitePhysicalPath + +Write-Host "[DONE] Setting up IIS Express" -ForegroundColor Cyan +Write-Host "[BEGIN] Setting SSL Certificate" -ForegroundColor Cyan + +# Ensure a certificate is bound to localhost's port 443. Generate a new +# self-signed certificate if necessary. +$siteCert = Get-SiteCertificate + +if ($siteCert -eq $null) { + $siteCert = Initialize-SiteCertificate +} + +Write-Host "Using SSL Certificate: $($siteCert.Thumbprint)" + +Invoke-Netsh http add sslcert hostnameport="$(Get-SiteHttpsHost)" certhash="$($siteCert.Thumbprint)" certstorename=Root appid="{$([Guid]::NewGuid().ToString())}" + +Write-Host "[DONE] Setting SSL Certificate" -ForegroundColor Cyan \ No newline at end of file diff --git a/scripts/Setup-Submodule.ps1 b/scripts/Setup-Submodule.ps1 new file mode 100644 index 0000000..24cfc4a --- /dev/null +++ b/scripts/Setup-Submodule.ps1 @@ -0,0 +1,16 @@ +Function Invoke-Git { + [CmdletBinding()] + Param( + [string[]] $Arguments + ) + + # We are invoking git through cmd here because otherwise the redirection does not process until after git has completed, leaving errors in the stream. + Write-Host "git $Arguments" + & cmd /c "git $Arguments 2>&1" +} + +Write-Host 'Resetting submodules' +Invoke-Git -Arguments ('submodule', 'deinit', '--all', '-f') + +Write-Host "Updating submodules" +Invoke-Git -Arguments ('submodule', 'update', '--init', '--') \ No newline at end of file diff --git a/src/NuGet.Status/App_Start/FilterConfig.cs b/src/NuGet.Status/App_Start/FilterConfig.cs index 3f23eae..865a1f6 100644 --- a/src/NuGet.Status/App_Start/FilterConfig.cs +++ b/src/NuGet.Status/App_Start/FilterConfig.cs @@ -9,9 +9,7 @@ public class FilterConfig { public static void RegisterGlobalFilters(GlobalFilterCollection filters) { -#if !DEBUG filters.Add(new RequireHttpsAttribute()); -#endif } } } diff --git a/src/NuGet.Status/App_Start/Startup.cs b/src/NuGet.Status/App_Start/Startup.cs index c58c91a..fa13d7f 100644 --- a/src/NuGet.Status/App_Start/Startup.cs +++ b/src/NuGet.Status/App_Start/Startup.cs @@ -38,15 +38,10 @@ public void Configuration(IAppBuilder app) { app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType); - // Ignore secure cookie for local testing. - var cookieSecure = _redirectUri.StartsWith("http://localhost") - ? CookieSecureOption.Never - : CookieSecureOption.Always; - var options = new CookieAuthenticationOptions { CookieHttpOnly = true, - CookieSecure = cookieSecure, + CookieSecure = CookieSecureOption.Always, ExpireTimeSpan = TimeSpan.FromMinutes(10), SlidingExpiration = true }; @@ -84,21 +79,19 @@ private void Init() ServicePointManager.SecurityProtocol &= ~SecurityProtocolType.Ssl3; ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12; - var configurationProvider = MvcApplication.ConfigurationProvider; - -#pragma warning disable CS0618 // Type or member is obsolete - _postStatusEnabled = configurationProvider.GetOrDefaultSync("Ida:AdminEnabled"); -#pragma warning restore CS0618 // Type or member is obsolete + _postStatusEnabled = MvcApplication.StatusConfiguration.AdminEnabled; if (_postStatusEnabled) { - _clientId = configurationProvider.GetOrThrowSync("Ida:ClientId"); + var idaConfiguration = MvcApplication.IdaConfiguration; + + _clientId = idaConfiguration.ClientId; - _aadInstance = configurationProvider.GetOrThrowSync("Ida:AADInstance"); - _tenant = configurationProvider.GetOrThrowSync("Ida:Tenant"); + _aadInstance = idaConfiguration.AADInstance; + _tenant = idaConfiguration.Tenant; _authority = new Uri(new Uri(_aadInstance), _tenant).ToString(); - _rootUri = configurationProvider.GetOrThrowSync("Ida:RootUri"); + _rootUri = idaConfiguration.RootUri; _redirectUri = new Uri(new Uri(_rootUri), "admin").ToString(); } } diff --git a/src/NuGet.Status/Configuration/AppSettingsConfigurationProvider.cs b/src/NuGet.Status/Configuration/AppSettingsConfigurationProvider.cs new file mode 100644 index 0000000..36c2928 --- /dev/null +++ b/src/NuGet.Status/Configuration/AppSettingsConfigurationProvider.cs @@ -0,0 +1,27 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Configuration; +using System.Threading.Tasks; +using NuGet.Services.Configuration; +using NuGet.Services.KeyVault; + +namespace NuGet.Status.Configuration +{ + public class AppSettingsConfigurationProvider : ConfigurationProvider + { + private readonly ISecretInjector _secretInjector; + + public AppSettingsConfigurationProvider(ISecretInjector secretInjector) + { + _secretInjector = secretInjector ?? throw new ArgumentNullException(nameof(secretInjector)); + } + + protected override Task Get(string key) + { + var setting = ConfigurationManager.AppSettings[key]; + return _secretInjector.InjectAsync(setting); + } + } +} \ No newline at end of file diff --git a/src/NuGet.Status/Configuration/IdaConfiguration.cs b/src/NuGet.Status/Configuration/IdaConfiguration.cs new file mode 100644 index 0000000..23d5555 --- /dev/null +++ b/src/NuGet.Status/Configuration/IdaConfiguration.cs @@ -0,0 +1,29 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.ComponentModel.DataAnnotations; +using NuGet.Services.Configuration; + +namespace NuGet.Status.Configuration +{ + public class IdaConfiguration : Services.Configuration.Configuration + { + public const string IdaPrefix = "Ida:"; + + [ConfigurationKeyPrefix(IdaPrefix)] + [Required] + public string ClientId { get; set; } + + [ConfigurationKeyPrefix(IdaPrefix)] + [Required] + public string AADInstance { get; set; } + + [ConfigurationKeyPrefix(IdaPrefix)] + [Required] + public string Tenant { get; set; } + + [ConfigurationKeyPrefix(IdaPrefix)] + [Required] + public string RootUri { get; set; } + } +} \ No newline at end of file diff --git a/src/NuGet.Status/Configuration/SecretReaderFactory.cs b/src/NuGet.Status/Configuration/SecretReaderFactory.cs index 5ea88a0..520a5e8 100644 --- a/src/NuGet.Status/Configuration/SecretReaderFactory.cs +++ b/src/NuGet.Status/Configuration/SecretReaderFactory.cs @@ -42,10 +42,14 @@ public ISecretReader CreateSecretReader() var storeLocation = _configurationDictionary[StoreLocationKey]; var storeName = _configurationDictionary[StoreNameKey]; var validateCertificate = _configurationDictionary[ValidateCertificateKey]; + var certificate = CertificateUtility.FindCertificateByThumbprint( + (StoreName)Enum.Parse(typeof(StoreName), storeName), + (StoreLocation)Enum.Parse(typeof(StoreLocation), storeLocation), + certificateThumbprint, + bool.Parse(validateCertificate)); - int refreshIntervalSec; if (!_configurationDictionary.ContainsKey(CacheRefreshIntervalKey) || - !int.TryParse(_configurationDictionary[CacheRefreshIntervalKey], out refreshIntervalSec)) + !int.TryParse(_configurationDictionary[CacheRefreshIntervalKey], out int refreshIntervalSec)) { refreshIntervalSec = CachingSecretReader.DefaultRefreshIntervalSec; } @@ -54,10 +58,7 @@ public ISecretReader CreateSecretReader() new KeyVaultConfiguration( vaultName, clientId, - certificateThumbprint, - (StoreName)Enum.Parse(typeof(StoreName), storeName), - (StoreLocation)Enum.Parse(typeof(StoreLocation), storeLocation), - bool.Parse(validateCertificate))); + certificate)); secretReader = new CachingSecretReader(secretReader, refreshIntervalSec); } diff --git a/src/NuGet.Status/Configuration/StatusConfiguration.cs b/src/NuGet.Status/Configuration/StatusConfiguration.cs new file mode 100644 index 0000000..e375d51 --- /dev/null +++ b/src/NuGet.Status/Configuration/StatusConfiguration.cs @@ -0,0 +1,49 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.ComponentModel; +using System.ComponentModel.DataAnnotations; +using NuGet.Services.Configuration; + +namespace NuGet.Status.Configuration +{ + public class StatusConfiguration : Services.Configuration.Configuration + { + public const string StoragePrefix = "Storage:"; + + public string ApplicationInsightsKey { get; set; } + + [DefaultValue("https://www.nuget.org/")] + public string NuGetBaseUrl { get; set; } + + public string ExternalBrandingMessage { get; set; } + public string ExternalBrandingUrl { get; set; } + public string ExternalAboutUrl { get; set; } + public string ExternalPrivacyPolicyUrl { get; set; } + public string ExternalTermsOfUseUrl { get; set; } + public string TrademarksUrl { get; set; } + + [ConfigurationKeyPrefix(IdaConfiguration.IdaPrefix)] + public bool AdminEnabled { get; set; } + + [ConfigurationKeyPrefix(StoragePrefix)] + [Required] + public string ConnectionString { get; set; } + + [ConfigurationKeyPrefix(StoragePrefix)] + [Required] + public string SecondaryConnectionString { get; set; } + + [ConfigurationKeyPrefix(StoragePrefix)] + [Required] + public string BlobName { get; set; } + + [ConfigurationKeyPrefix(StoragePrefix)] + [Required] + public string ContainerName { get; set; } + + [ConfigurationKeyPrefix(StoragePrefix)] + [Required] + public string TableName { get; set; } + } +} \ No newline at end of file diff --git a/src/NuGet.Status/Controllers/AdminController.cs b/src/NuGet.Status/Controllers/AdminController.cs index 7ecede6..750f024 100644 --- a/src/NuGet.Status/Controllers/AdminController.cs +++ b/src/NuGet.Status/Controllers/AdminController.cs @@ -118,14 +118,14 @@ private async Task InsertEntityToStorage(StorageService storageService, Ma { try { - var table = await storageService.GetCloudTableAsync(); + var table = storageService.GetCloudTable(); var operation = TableOperation.Insert(entity); await table.ExecuteAsync(operation); return true; } catch (Exception e) { - QuietLog.Log($"{nameof(AdminController)}.{nameof(InsertEntityToStorage)}", $"Failed to insert entity to table with connection string key {storageService.ConnectionStringKey}!", e); + QuietLog.Log($"{nameof(AdminController)}.{nameof(InsertEntityToStorage)}", $"Failed to insert entity to table in {storageService.Name} storage!", e); } return false; diff --git a/src/NuGet.Status/Extensions/MessageExtensions.cs b/src/NuGet.Status/Extensions/MessageExtensions.cs index 43a33e8..44768f7 100644 --- a/src/NuGet.Status/Extensions/MessageExtensions.cs +++ b/src/NuGet.Status/Extensions/MessageExtensions.cs @@ -1,4 +1,4 @@ -using MarkdownDeep; +using Markdig; using NuGet.Services.Status; namespace NuGet.Status.Extensions @@ -8,16 +8,11 @@ public static class MessageExtensions /// /// Converts the of to HTML. /// - /// - /// The instance is NOT thread-safe. It must be created on every request. - /// public static string GetHtmlContents(this Message message) { - return new Markdown - { - SafeMode = true, - ExtraMode = false - }.Transform(message.Contents); + var pipelineBuilder = new MarkdownPipelineBuilder(); + pipelineBuilder.DisableHtml(); + return Markdown.ToHtml(message.Contents, pipelineBuilder.Build()); } } } \ No newline at end of file diff --git a/src/NuGet.Status/Global.asax.cs b/src/NuGet.Status/Global.asax.cs index 9cdc8d6..2ec2feb 100644 --- a/src/NuGet.Status/Global.asax.cs +++ b/src/NuGet.Status/Global.asax.cs @@ -3,15 +3,16 @@ using System; using System.Configuration; -using System.IO; using System.Linq; using System.Security.Claims; +using System.Threading; +using System.Threading.Tasks; using System.Web.Helpers; using System.Web.Hosting; using System.Web.Mvc; using System.Web.Optimization; using System.Web.Routing; -using Newtonsoft.Json.Linq; +using Microsoft.ApplicationInsights.Extensibility; using NuGet.Services.Configuration; using NuGet.Status.Configuration; using NuGet.Status.Helpers; @@ -21,26 +22,30 @@ namespace NuGet.Status { public class MvcApplication : System.Web.HttpApplication { - public static IConfigurationProvider ConfigurationProvider; + private static TimeSpan ConfigurationRefreshPeriod = new TimeSpan(days: 1, hours: 0, minutes: 0, seconds: 0); + private static readonly IConfigurationFactory _configurationFactory; + + public static StatusConfiguration StatusConfiguration { get; private set; } + + /// + /// The IDA configuration is only refreshed once. + /// It is only used on application startup in . + /// + private static Lazy _idaConfiguration = new Lazy( + () => _configurationFactory.Get().Result); + public static IdaConfiguration IdaConfiguration => _idaConfiguration.Value; static MvcApplication() { var configurationDictionary = ConfigurationManager.AppSettings.AllKeys.ToDictionary(key => key, key => ConfigurationManager.AppSettings[key]); - - var filename = configurationDictionary["Config:FileName"]; - var configPath = HostingEnvironment.MapPath($@"~/App_Data/{filename}.json"); - var configJson = File.ReadAllText(configPath); - var config = JObject.Parse(configJson); - foreach (var property in config.Properties()) - { - configurationDictionary[property.Name] = property.Value.ToString(); - } - var secretReaderFactory = new SecretReaderFactory(configurationDictionary); var secretReader = secretReaderFactory.CreateSecretReader(); var secretInjector = secretReaderFactory.CreateSecretInjector(secretReader); - ConfigurationProvider = new SecretConfigurationProvider(secretInjector, configurationDictionary); + var configurationProvider = new AppSettingsConfigurationProvider(secretInjector); + _configurationFactory = new ConfigurationFactory(configurationProvider); + + StatusConfiguration = _configurationFactory.Get().Result; } protected void Application_Start() @@ -55,16 +60,16 @@ protected void Application_Start() RouteConfig.RegisterRoutes(RouteTable.Routes); AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier; -#pragma warning disable CS0618 // Type or member is obsolete - UrlExtensions.BaseUrl = ConfigurationProvider - .GetOrDefaultSync("NuGetBaseUrl", "https://www.nuget.org/") - .TrimEnd('/'); -#pragma warning restore CS0618 // Type or member is obsolete + UrlExtensions.BaseUrl = StatusConfiguration.NuGetBaseUrl.TrimEnd('/'); - HostingEnvironment.QueueBackgroundWorkItem(token => + var instrumentationKey = StatusConfiguration.ApplicationInsightsKey; + if (!string.IsNullOrWhiteSpace(instrumentationKey)) { - return ServiceStatusHelper.ReloadServiceStatusForever(token); - }); + TelemetryConfiguration.Active.InstrumentationKey = instrumentationKey; + } + + HostingEnvironment.QueueBackgroundWorkItem(ServiceStatusHelper.ReloadServiceStatusForever); + HostingEnvironment.QueueBackgroundWorkItem(RefreshConfigurationForever); } protected void Application_Error(object sender, EventArgs e) @@ -75,11 +80,11 @@ protected void Application_Error(object sender, EventArgs e) Server.GetLastError()); } - private static JObject GetConfigFile(string filename) + private async Task RefreshConfigurationForever(CancellationToken token) { - var configPath = HostingEnvironment.MapPath($@"~/App_Data/{filename}.json"); - var configJson = File.ReadAllText(configPath); - return JObject.Parse(configJson); + await Task.Delay(ConfigurationRefreshPeriod); + StatusConfiguration = await _configurationFactory.Get(); + await RefreshConfigurationForever(token); } } } diff --git a/src/NuGet.Status/GlobalSuppressions.cs b/src/NuGet.Status/GlobalSuppressions.cs new file mode 100644 index 0000000..2f4b8a7 --- /dev/null +++ b/src/NuGet.Status/GlobalSuppressions.cs @@ -0,0 +1,8 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Diagnostics.CodeAnalysis; + +[module: SuppressMessage("Microsoft.Security.Web.Configuration", "CA3103:EnableFormsRequireSSL", Justification = "Forms authentication is not enabled.")] +[module: SuppressMessage("Microsoft.Security.Web.Configuration", "CA3119:EnableHttpCookiesRequireSsl", Justification = "Enabled in root web.config, which is inherited by other configurations.")] +[module: SuppressMessage("Microsoft.Security.Web.Configuration", "CA3135:EnableRoleManagerCookieRequireSsl", Justification = "Only used by a test project in the submodule that is not a part of this project.")] \ No newline at end of file diff --git a/src/NuGet.Status/Helpers/ServiceStatusHelper.cs b/src/NuGet.Status/Helpers/ServiceStatusHelper.cs index e4331d4..9529fb5 100644 --- a/src/NuGet.Status/Helpers/ServiceStatusHelper.cs +++ b/src/NuGet.Status/Helpers/ServiceStatusHelper.cs @@ -53,7 +53,7 @@ private static async Task ReloadServiceStatus(CancellationToken token) private static async Task GetServiceStatusAsync(CancellationToken token) { - var blob = await StorageHelper.PrimaryStorage.GetCloudBlockBlobAsync(); + var blob = StorageHelper.PrimaryStorage.GetCloudBlockBlob(); var json = await blob.DownloadTextAsync(token); return new CachedServiceStatus(json); } diff --git a/src/NuGet.Status/Helpers/StorageHelper.cs b/src/NuGet.Status/Helpers/StorageHelper.cs index 6b12ea8..0462108 100644 --- a/src/NuGet.Status/Helpers/StorageHelper.cs +++ b/src/NuGet.Status/Helpers/StorageHelper.cs @@ -5,10 +5,11 @@ namespace NuGet.Status.Helpers { public static class StorageHelper { - private const string PrimaryConnectionStringKey = "Storage:ConnectionString"; - private const string SecondaryConnectionStringKey = "Storage:SecondaryConnectionString"; - - public static StorageService PrimaryStorage => new StorageService(PrimaryConnectionStringKey); - public static StorageService SecondaryStorage => new StorageService(SecondaryConnectionStringKey); + public static StorageService PrimaryStorage => new StorageService( + "primary", + () => MvcApplication.StatusConfiguration.ConnectionString); + public static StorageService SecondaryStorage => new StorageService( + "secondary", + () => MvcApplication.StatusConfiguration.SecondaryConnectionString); } } \ No newline at end of file diff --git a/src/NuGet.Status/Helpers/StorageService.cs b/src/NuGet.Status/Helpers/StorageService.cs index cc1d565..d0b55c4 100644 --- a/src/NuGet.Status/Helpers/StorageService.cs +++ b/src/NuGet.Status/Helpers/StorageService.cs @@ -4,67 +4,49 @@ using Microsoft.WindowsAzure.Storage; using Microsoft.WindowsAzure.Storage.Blob; using Microsoft.WindowsAzure.Storage.Table; -using System.Threading.Tasks; +using System; namespace NuGet.Status.Helpers { public class StorageService { - private const string TableNameKey = "Storage:TableName"; - private const string ContainerNameKey = "Storage:ContainerName"; - private const string BlobNameKey = "Storage:BlobName"; + private readonly Func _getConnectionString; - public string ConnectionStringKey { get; } + public string Name { get; } - public StorageService(string connectionStringKey) + public StorageService(string name, Func getConnectionString) { - ConnectionStringKey = connectionStringKey; + Name = name; + _getConnectionString = getConnectionString; } - public async Task GetCloudBlockBlobAsync() + public CloudBlockBlob GetCloudBlockBlob() { - var blobName = await MvcApplication - .ConfigurationProvider - .GetOrThrow(BlobNameKey); - - var container = await GetCloudBlobContainerAsync(); - - return container.GetBlockBlobReference(blobName); + var container = GetCloudBlobContainer(); + return container.GetBlockBlobReference(MvcApplication.StatusConfiguration.BlobName); } - public async Task GetCloudBlobContainerAsync() + public CloudBlobContainer GetCloudBlobContainer() { - var containerName = await MvcApplication - .ConfigurationProvider - .GetOrThrow(ContainerNameKey); - - var storageAccount = await GetCloudStorageAccountAsync(); + var storageAccount = GetCloudStorageAccount(); return storageAccount .CreateCloudBlobClient() - .GetContainerReference(containerName); + .GetContainerReference(MvcApplication.StatusConfiguration.ContainerName); } - public async Task GetCloudTableAsync() + public CloudTable GetCloudTable() { - var tableName = await MvcApplication - .ConfigurationProvider - .GetOrThrow(TableNameKey); - - var storageAccount = await GetCloudStorageAccountAsync(); + var storageAccount = GetCloudStorageAccount(); return storageAccount .CreateCloudTableClient() - .GetTableReference(tableName); + .GetTableReference(MvcApplication.StatusConfiguration.TableName); } - public async Task GetCloudStorageAccountAsync() + public CloudStorageAccount GetCloudStorageAccount() { - var connectionString = await MvcApplication - .ConfigurationProvider - .GetOrThrow(ConnectionStringKey); - - return CloudStorageAccount.Parse(connectionString); + return CloudStorageAccount.Parse(_getConnectionString()); } } } \ No newline at end of file diff --git a/src/NuGet.Status/NuGet.Status.csproj b/src/NuGet.Status/NuGet.Status.csproj index b503633..697e30d 100644 --- a/src/NuGet.Status/NuGet.Status.csproj +++ b/src/NuGet.Status/NuGet.Status.csproj @@ -1,5 +1,6 @@  + Debug @@ -16,10 +17,10 @@ v4.6.2 false true - - - - + 443 + enabled + disabled + false @@ -54,9 +55,8 @@ ..\packages\Hyak.Common.1.0.2\lib\net45\Hyak.Common.dll True - - ..\packages\MarkdownDeep.NET.1.5\lib\.NetFramework 3.5\MarkdownDeep.dll - True + + ..\packages\Markdig.Signed.0.15.4\lib\net40\Markdig.dll ..\packages\Microsoft.ApplicationInsights.Agent.Intercept.2.0.6\lib\net45\Microsoft.AI.Agent.Intercept.dll @@ -105,54 +105,45 @@ ..\packages\Microsoft.Azure.KeyVault.Core.1.0.0\lib\net40\Microsoft.Azure.KeyVault.Core.dll - - ..\packages\Microsoft.Data.Edm.5.8.2\lib\net40\Microsoft.Data.Edm.dll - - - ..\packages\Microsoft.Data.OData.5.8.2\lib\net40\Microsoft.Data.OData.dll + + ..\packages\Microsoft.Extensions.Configuration.1.1.2\lib\netstandard1.1\Microsoft.Extensions.Configuration.dll - - ..\packages\Microsoft.Data.Services.Client.5.8.2\lib\net40\Microsoft.Data.Services.Client.dll + + ..\packages\Microsoft.Extensions.Configuration.Abstractions.1.1.2\lib\netstandard1.0\Microsoft.Extensions.Configuration.Abstractions.dll - - ..\packages\Microsoft.Extensions.Configuration.1.0.0\lib\netstandard1.1\Microsoft.Extensions.Configuration.dll - True - - - ..\packages\Microsoft.Extensions.Configuration.Abstractions.1.0.0\lib\netstandard1.0\Microsoft.Extensions.Configuration.Abstractions.dll - True + + ..\packages\Microsoft.Extensions.Configuration.EnvironmentVariables.1.0.0\lib\net451\Microsoft.Extensions.Configuration.EnvironmentVariables.dll - - ..\packages\Microsoft.Extensions.Configuration.FileExtensions.1.0.0\lib\net451\Microsoft.Extensions.Configuration.FileExtensions.dll - True + + ..\packages\Microsoft.Extensions.Configuration.FileExtensions.1.1.2\lib\net451\Microsoft.Extensions.Configuration.FileExtensions.dll ..\packages\Microsoft.Extensions.Configuration.Json.1.0.0\lib\net451\Microsoft.Extensions.Configuration.Json.dll True - - ..\packages\Microsoft.Extensions.FileProviders.Abstractions.1.0.0\lib\netstandard1.0\Microsoft.Extensions.FileProviders.Abstractions.dll - True + + ..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.1.1.1\lib\netstandard1.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll - - ..\packages\Microsoft.Extensions.FileProviders.Physical.1.0.0\lib\net451\Microsoft.Extensions.FileProviders.Physical.dll - True + + ..\packages\Microsoft.Extensions.FileProviders.Abstractions.1.1.1\lib\netstandard1.0\Microsoft.Extensions.FileProviders.Abstractions.dll - - ..\packages\Microsoft.Extensions.FileSystemGlobbing.1.0.0\lib\net451\Microsoft.Extensions.FileSystemGlobbing.dll - True + + ..\packages\Microsoft.Extensions.FileProviders.Physical.1.1.1\lib\net451\Microsoft.Extensions.FileProviders.Physical.dll - - ..\packages\Microsoft.Extensions.Primitives.1.0.0\lib\netstandard1.0\Microsoft.Extensions.Primitives.dll - True + + ..\packages\Microsoft.Extensions.FileSystemGlobbing.1.1.1\lib\net45\Microsoft.Extensions.FileSystemGlobbing.dll - - ..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.3.13.5\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll - True + + ..\packages\Microsoft.Extensions.Options.1.1.2\lib\netstandard1.0\Microsoft.Extensions.Options.dll - - ..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.3.13.5\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll - True + + ..\packages\Microsoft.Extensions.Primitives.1.1.1\lib\netstandard1.0\Microsoft.Extensions.Primitives.dll + + + ..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.3.19.4\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll + + + ..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.3.19.4\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll ..\packages\Microsoft.IdentityModel.Protocol.Extensions.1.0.0\lib\net45\Microsoft.IdentityModel.Protocol.Extensions.dll @@ -196,6 +187,9 @@ ..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll True + + ..\packages\Microsoft.Win32.Primitives.4.3.0\lib\net46\Microsoft.Win32.Primitives.dll + ..\packages\Microsoft.WindowsAzure.ConfigurationManager.3.1.0\lib\net40\Microsoft.WindowsAzure.Configuration.dll True @@ -206,13 +200,11 @@ ..\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll - - ..\packages\NuGet.Services.Configuration.1.0.75-r-develop\lib\net452\NuGet.Services.Configuration.dll - True + + ..\packages\NuGet.Services.Configuration.2.44.0\lib\net462\NuGet.Services.Configuration.dll - - ..\packages\NuGet.Services.KeyVault.1.0.75-r-develop\lib\net45\NuGet.Services.KeyVault.dll - True + + ..\packages\NuGet.Services.KeyVault.2.44.0\lib\net462\NuGet.Services.KeyVault.dll ..\packages\NuGet.Services.Status.2.38.0\lib\net462\NuGet.Services.Status.dll @@ -228,30 +220,85 @@ True + + ..\packages\System.AppContext.4.3.0\lib\net46\System.AppContext.dll + + + ..\packages\System.Console.4.3.0\lib\net46\System.Console.dll + + + ..\packages\System.Diagnostics.DiagnosticSource.4.3.0\lib\net46\System.Diagnostics.DiagnosticSource.dll + + + ..\packages\System.Diagnostics.Tracing.4.3.0\lib\net462\System.Diagnostics.Tracing.dll + + + ..\packages\System.Globalization.Calendars.4.3.0\lib\net46\System.Globalization.Calendars.dll + ..\packages\System.IdentityModel.Tokens.Jwt.4.0.0\lib\net45\System.IdentityModel.Tokens.Jwt.dll True - - ..\packages\System.IO.4.1.0\lib\net462\System.IO.dll + + ..\packages\System.IO.4.3.0\lib\net462\System.IO.dll + + + ..\packages\System.IO.Compression.4.3.0\lib\net46\System.IO.Compression.dll + + + + ..\packages\System.IO.Compression.ZipFile.4.3.0\lib\net46\System.IO.Compression.ZipFile.dll + + + ..\packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll + + + ..\packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll - + + ..\packages\System.Net.Http.4.3.4\lib\net46\System.Net.Http.dll + - - ..\packages\System.Runtime.4.1.0\lib\net462\System.Runtime.dll + + ..\packages\System.Net.Sockets.4.3.0\lib\net46\System.Net.Sockets.dll + + + + ..\packages\System.Reflection.4.3.0\lib\net462\System.Reflection.dll + + + ..\packages\System.Runtime.4.3.0\lib\net462\System.Runtime.dll + + + ..\packages\System.Runtime.CompilerServices.Unsafe.4.3.0\lib\netstandard1.0\System.Runtime.CompilerServices.Unsafe.dll - - ..\packages\System.Runtime.Extensions.4.1.0\lib\net462\System.Runtime.Extensions.dll + + ..\packages\System.Runtime.Extensions.4.3.0\lib\net462\System.Runtime.Extensions.dll - ..\packages\System.Runtime.InteropServices.4.1.0\lib\net462\System.Runtime.InteropServices.dll + ..\packages\System.Runtime.InteropServices.4.3.0\lib\net462\System.Runtime.InteropServices.dll + + + ..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll + + ..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net461\System.Security.Cryptography.Algorithms.dll + + + ..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll + + + ..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll + + + ..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll + ..\packages\System.Spatial.5.8.2\lib\net40\System.Spatial.dll @@ -301,6 +348,9 @@ ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll + + ..\packages\System.Xml.ReaderWriter.4.3.0\lib\net46\System.Xml.ReaderWriter.dll + ..\packages\WebGrease.1.5.2\lib\WebGrease.dll @@ -311,9 +361,12 @@ + + + @@ -322,6 +375,7 @@ + @@ -334,7 +388,7 @@ - + @@ -406,6 +460,19 @@ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + ..\..\build + $(BUILD_SOURCESDIRECTORY)\build + $(NuGetBuildPath) + none + + + + + + + + @@ -417,9 +484,9 @@ True True - 53485 + 443 / - http://localhost:19440/ + https://localhost:443/ False False @@ -435,6 +502,8 @@ This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -80,26 +101,63 @@ - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/NuGet.Status/packages.config b/src/NuGet.Status/packages.config index c8d6032..29abe31 100644 --- a/src/NuGet.Status/packages.config +++ b/src/NuGet.Status/packages.config @@ -2,7 +2,8 @@ - + + @@ -23,20 +24,21 @@ - - - - - - + + + + - - - - - + + + + + + + + @@ -45,29 +47,67 @@ + + - - + + - + + + + - + + + + + + + - - + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + - + + + + + + + + \ No newline at end of file