diff --git a/contrib/upgrade-isn-isnd.sh b/contrib/upgrade-isn-isnd.sh index 457348b..8a93152 100755 --- a/contrib/upgrade-isn-isnd.sh +++ b/contrib/upgrade-isn-isnd.sh @@ -3,14 +3,11 @@ set -e # compiler tout dotnet build -c Release -dotnet publish -c Release src/isnd -dotnet publish -c Release src/isn +dotnet publish -c Release -f netcoreapp2.1 src/isnd # MAJ du serveur sudo systemctl stop isnd -sudo cp -a src/isnd/bin/Release/net10.0/publish/* /srv/www/isnd +sudo cp -a src/isnd/bin/Release/netcoreapp2.1/publish/* /srv/www/isnd sudo systemctl start isnd # MAJ du client -sudo cp -a src/isn/bin/Release/net10.0/* /usr/local/lib/isn -sudo chown -R root:root /usr/local/lib/isn - - +sudo cp -a src/isn/bin/Release/netcoreapp2.1/* /usr/local/lib/isn +sudo chown -R root.root /usr/local/lib/isn diff --git a/src/isn/Program.cs b/src/isn/Program.cs index 5abbbb3..6f1752d 100644 --- a/src/isn/Program.cs +++ b/src/isn/Program.cs @@ -12,7 +12,7 @@ namespace Isn public static void LoadConfig() { - FileInfo cfgSettingIf = new FileInfo(ConfigFileName); + FileInfo cfgSettingIf = new FileInfo(_configFileName); if (cfgSettingIf.Exists) { var json = File.ReadAllText(cfgSettingIf.FullName); @@ -29,13 +29,12 @@ namespace Isn { "h|help", "show this message and exit", h => shouldShowPushHelp = h != null }, }; - private static string ConfigDirectory => - Environment.GetEnvironmentVariable("ISN_CONFIG_DIR") - ?? Path.Combine( - Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), - ".isn"); - - private static string ConfigFileName => Path.Combine(ConfigDirectory, "config.json"); + private static readonly string _configFileName = + Path.Combine( + Path.Combine(Environment.GetFolderPath( + Environment.SpecialFolder.UserProfile), ".isn"), + "config.json") + ; public const string push = "push"; static readonly OptionSet options = new OptionSet { diff --git a/src/isn/commands/PushCommand.cs b/src/isn/commands/PushCommand.cs index 6820814..0f6f303 100644 --- a/src/isn/commands/PushCommand.cs +++ b/src/isn/commands/PushCommand.cs @@ -18,8 +18,6 @@ namespace Isn source = Program.Settings.Sources.First(s=>s.Value.Alias==source).Key; if (source==null) throw new InvalidOperationException("source is invalid"); - var resolvedApiKey = string.IsNullOrWhiteSpace(apikey) ? ResolveSourceApiKey(source) : apikey; - var resources = SourceHelpers.GetServerResources(source); if (resources.Resources == null) throw new InvalidOperationException("source gave no resource"); @@ -40,7 +38,7 @@ namespace Isn try { Console.WriteLine("Connecting to "+ pubRes.Id); - return client.UploadFilesToServer(new Uri(pubRes.Id), fi, resolvedApiKey); + return client.UploadFilesToServer(new Uri(pubRes.Id), fi, apikey); } catch (HttpRequestException hrex) { @@ -66,25 +64,5 @@ namespace Isn return report; } } - - private static string ResolveSourceApiKey(string source) - { - if (string.IsNullOrWhiteSpace(source)) - { - return null; - } - - if (Program.Settings.Sources.Values.Any(s => s.Alias == source)) - { - source = Program.Settings.Sources.First(s => s.Value.Alias == source).Key; - } - - if (Program.Settings.Sources.TryGetValue(source, out var sourceSettings)) - { - return sourceSettings.GetClearApiKey(); - } - - return null; - } } } \ No newline at end of file diff --git a/src/isn/commands/set-api-key.cs b/src/isn/commands/set-api-key.cs index 7da6021..0c4c2a5 100644 --- a/src/isn/commands/set-api-key.cs +++ b/src/isn/commands/set-api-key.cs @@ -61,7 +61,7 @@ namespace Isn } public static void SaveConfig() { - FileInfo cfgSettingIf = new FileInfo(ConfigFileName); + FileInfo cfgSettingIf = new FileInfo(_configFileName); if (!cfgSettingIf.Directory.Exists) cfgSettingIf.Directory.Create(); File.WriteAllText( cfgSettingIf.FullName, diff --git a/src/isnd/Controllers/Packages/PackagesController.Put.cs b/src/isnd/Controllers/Packages/PackagesController.Put.cs index 3084fa8..3f82924 100644 --- a/src/isnd/Controllers/Packages/PackagesController.Put.cs +++ b/src/isnd/Controllers/Packages/PackagesController.Put.cs @@ -31,12 +31,12 @@ namespace isnd.Controllers try { var clientVersionId = Request.Headers["X-NuGet-Client-Version"]; - string apiKey = Request.Headers["X-NuGet-ApiKey"].FirstOrDefault() ?? string.Empty; + string apiKey = Request.Headers["X-NuGet-ApiKey"][0]; ViewData["versionId"] = typeof(PackagesController).Assembly.FullName; var files = new List(); ViewData["files"] = files; - var clearkey = ApiKeyProtector.TryUnprotectKey(protector, apiKey); + var clearkey = protector.Unprotect(apiKey); var apikey = dbContext.ApiKeys.SingleOrDefault(k => k.Id == clearkey); if (apikey == null) { diff --git a/src/isnd/Helpers/ApiKeyProtector.cs b/src/isnd/Helpers/ApiKeyProtector.cs deleted file mode 100644 index 98f5e72..0000000 --- a/src/isnd/Helpers/ApiKeyProtector.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System; -using System.Security.Cryptography; -using System.Text; -using Microsoft.AspNetCore.DataProtection; - -namespace isnd.Helpers -{ - public static class ApiKeyProtector - { - private const byte LegacyDelta = 145; - - public static string TryUnprotectKey(IDataProtector protector, string protectedValue) - { - if (string.IsNullOrWhiteSpace(protectedValue)) - { - return protectedValue; - } - - if (TryUnprotect(protector, protectedValue, out var unprotected)) - { - return unprotected; - } - - if (TryUnprotectLegacy(protectedValue, out unprotected)) - { - return unprotected; - } - - return protectedValue; - } - - private static bool TryUnprotect(IDataProtector protector, string protectedValue, out string unprotected) - { - try - { - unprotected = protector.Unprotect(protectedValue); - return true; - } - catch (CryptographicException) - { - unprotected = null; - return false; - } - catch (FormatException) - { - unprotected = null; - return false; - } - } - - private static bool TryUnprotectLegacy(string protectedValue, out string unprotected) - { - try - { - unprotected = UnprotectLegacy(protectedValue); - return true; - } - catch (FormatException) - { - unprotected = null; - return false; - } - } - - public static string UnprotectLegacy(string protectedValue) - { - if (string.IsNullOrWhiteSpace(protectedValue)) - { - return protectedValue; - } - - var bytes = Convert.FromBase64String(protectedValue); - var unprotectedBytes = new byte[bytes.Length]; - for (var index = 0; index < bytes.Length; index++) - { - unprotectedBytes[index] = (byte)(bytes[index] ^ LegacyDelta); - } - - return Encoding.UTF8.GetString(unprotectedBytes); - } - } -} diff --git a/test/isn.tests/PushTest.cs b/test/isn.tests/PushTest.cs index 1871ebf..b4223fc 100644 --- a/test/isn.tests/PushTest.cs +++ b/test/isn.tests/PushTest.cs @@ -18,10 +18,6 @@ namespace Isn.tests { private readonly HttpListener listener; private readonly Task listenerTask; - private readonly string configDirectory; - private readonly string originalConfigDirectory; - - public string LastApiKeyHeader { get; private set; } public LocalSourceFixture() { @@ -49,11 +45,6 @@ namespace Isn.tests break; } - if (context.Request.HttpMethod == "PUT") - { - LastApiKeyHeader = context.Request.Headers["X-NuGet-ApiKey"]; - } - var indexJson = JsonConvert.SerializeObject(new ApiIndexViewModel(prefix + "index.json") { Version = "3.0.0", @@ -73,11 +64,6 @@ namespace Isn.tests } }); - configDirectory = Path.Combine(Path.GetTempPath(), $"isn-tests-{Guid.NewGuid():N}"); - Directory.CreateDirectory(configDirectory); - originalConfigDirectory = Environment.GetEnvironmentVariable("ISN_CONFIG_DIR"); - Environment.SetEnvironmentVariable("ISN_CONFIG_DIR", configDirectory); - SourceUrl = prefix + "index.json"; ConfigureIsnSettings(SourceUrl); Program.LoadConfig(); @@ -98,12 +84,6 @@ namespace Isn.tests { } } - - Environment.SetEnvironmentVariable("ISN_CONFIG_DIR", originalConfigDirectory); - if (Directory.Exists(configDirectory)) - { - Directory.Delete(configDirectory, recursive: true); - } } private static int GetFreePort() @@ -115,8 +95,12 @@ namespace Isn.tests return port; } - private void ConfigureIsnSettings(string sourceUrl) + private static void ConfigureIsnSettings(string sourceUrl) { + var home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); + var configDirectory = Path.Combine(home, ".isn"); + Directory.CreateDirectory(configDirectory); + var configPath = Path.Combine(configDirectory, "config.json"); var settings = new Settings { @@ -141,44 +125,6 @@ namespace Isn.tests this.fixture = fixture; } - [Fact] - public void SupportsIsolatedConfigDirectoryOverride() - { - var tempDir = Path.Combine(Path.GetTempPath(), $"isn-test-{Guid.NewGuid():N}"); - Directory.CreateDirectory(tempDir); - var originalConfigDir = Environment.GetEnvironmentVariable("ISN_CONFIG_DIR"); - var configFile = Path.Combine(tempDir, "config.json"); - var expectedSource = "https://example.test/index.json"; - var settings = new Settings - { - DataProtectionTitle = "isn", - Sources = new Dictionary - { - [expectedSource] = new SourceSettings { Alias = "override" } - }, - DefaultSourceKey = expectedSource - }; - - try - { - Environment.SetEnvironmentVariable("ISN_CONFIG_DIR", tempDir); - File.WriteAllText(configFile, JsonConvert.SerializeObject(settings, Formatting.Indented)); - - Program.LoadConfig(); - - Assert.Equal(expectedSource, Program.Settings.DefaultSourceKey); - Assert.True(Program.Settings.Sources.ContainsKey(expectedSource)); - } - finally - { - Environment.SetEnvironmentVariable("ISN_CONFIG_DIR", originalConfigDir); - if (Directory.Exists(tempDir)) - { - Directory.Delete(tempDir, recursive: true); - } - } - } - [Fact] public void HaveADefaultDataProtector() { @@ -213,22 +159,6 @@ namespace Isn.tests Assert.Single(report); } - [Fact] - public void PushUsesStoredApiKeyFromConfigWhenNoExplicitApiKeyIsProvided() - { - Program.LoadConfig(); - var clearApiKey = "stored-api-key"; - Program.Settings.Sources[fixture.SourceUrl].SetApiKey(clearApiKey); - Program.SaveConfig(); - Program.LoadConfig(); - - var report = Program.PushPkg(new[] { Path.Combine(AppContext.BaseDirectory, "dummy.nupkg") }); - - Assert.NotNull(report); - Assert.Single(report); - Assert.Equal(clearApiKey, fixture.LastApiKeyHeader); - } - [Fact] public void GetServerResourcesUsingHttpClientAsyncTest() { diff --git a/test/isnd.tests/UnitTestWebHost.cs b/test/isnd.tests/UnitTestWebHost.cs index b89caae..3ca896f 100644 --- a/test/isnd.tests/UnitTestWebHost.cs +++ b/test/isnd.tests/UnitTestWebHost.cs @@ -19,9 +19,6 @@ using System.Threading.Tasks; using NuGet.Protocol.Core.Types; using NuGet.Common; using Isn.Abstract; -using isnd.Helpers; -using Microsoft.AspNetCore.DataProtection; -using System.Security.Cryptography; namespace isnd.host.tests { @@ -52,27 +49,6 @@ namespace isnd.host.tests } } - [Fact] - public void LegacyApiKeyProtectorCanUnprotectValuesFromOlderClients() - { - const string clearValue = "legacy-api-key"; - var legacyProtectedValue = new Isn.DefaultDataProtector().Protect(clearValue); - - var unprotected = ApiKeyProtector.TryUnprotectKey(new ThrowingProtector(), legacyProtectedValue); - - Assert.Equal(clearValue, unprotected); - } - - [Fact] - public void ApiKeyProtectorReturnsRawValueWhenInputIsNotProtected() - { - const string rawApiKey = "CfDJ8AstXUEkxpJBrmoENwy__WNPxqcOwAuxyYgiU3Mebns5yxAT3VrC5vTuWTRSGZBFB7IGUyFkUYsp2nhRy64NqeUzLgOwEcU4FPOf-yaAtPeTMeStRd60bRh2ZYyQkQ3hrhW-lwpCLwYtNOnOyX2jayuzByF-4QfHIEhg6lbWenzf"; - - var result = ApiKeyProtector.TryUnprotectKey(new ThrowingProtector(), rawApiKey); - - Assert.Equal(rawApiKey, result); - } - [Fact] void TestDropUser() { @@ -141,14 +117,5 @@ namespace isnd.host.tests { throw new NotImplementedException(); } - - private sealed class ThrowingProtector : IDataProtector - { - public byte[] Protect(byte[] plaintext) => throw new CryptographicException("unexpected protect call"); - - public byte[] Unprotect(byte[] protectedData) => throw new CryptographicException("unexpected unprotect call"); - - public IDataProtector CreateProtector(string purpose) => this; - } } }