diff --git a/NuGet.config b/NuGet.config index 4b821f800992e3c37517c61bef0dc570f13f4abf..c302e3d4c2996fbba62f5560da56a3c2472f41b4 100644 --- a/NuGet.config +++ b/NuGet.config @@ -4,8 +4,10 @@ <clear /> <!--Begin: Package sources managed by Dependency Flow automation. Do not edit the sources below.--> <!-- Begin: Package sources from dotnet-runtime --> + <add key="darc-int-dotnet-runtime-5a400c2" value="https://pkgs.dev.azure.com/dnceng/internal/_packaging/darc-int-dotnet-runtime-5a400c21/nuget/v3/index.json" /> <!-- End: Package sources from dotnet-runtime --> <!-- Begin: Package sources from dotnet-efcore --> + <add key="darc-int-dotnet-efcore-f7333f1" value="https://pkgs.dev.azure.com/dnceng/internal/_packaging/darc-int-dotnet-efcore-f7333f1a/nuget/v3/index.json" /> <!-- End: Package sources from dotnet-efcore --> <!--End: Package sources managed by Dependency Flow automation. Do not edit the sources above.--> <add key="dotnet-eng" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json" /> @@ -25,8 +27,10 @@ <clear /> <!--Begin: Package sources managed by Dependency Flow automation. Do not edit the sources below.--> <!-- Begin: Package sources from dotnet-efcore --> + <add key="darc-int-dotnet-efcore-f7333f1" value="true" /> <!-- End: Package sources from dotnet-efcore --> <!-- Begin: Package sources from dotnet-runtime --> + <add key="darc-int-dotnet-runtime-5a400c2" value="true" /> <!-- End: Package sources from dotnet-runtime --> <!--End: Package sources managed by Dependency Flow automation. Do not edit the sources above.--> </disabledPackageSources> diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 391db802b3a07d9d179602e9d4de3277dd3a4467..c7f52d020c136cdfab59169c009c82602dd45980 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -9,37 +9,37 @@ --> <Dependencies> <ProductDependencies> - <Dependency Name="dotnet-ef" Version="6.0.9"> + <Dependency Name="dotnet-ef" Version="6.0.10"> <Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-efcore</Uri> - <Sha>33e3c950af2eb996c0b3c48e30eb4471138da675</Sha> + <Sha>f7333f1afa250ed33d3db52f0b531910b23a55b2</Sha> </Dependency> - <Dependency Name="Microsoft.EntityFrameworkCore.InMemory" Version="6.0.9"> + <Dependency Name="Microsoft.EntityFrameworkCore.InMemory" Version="6.0.10"> <Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-efcore</Uri> - <Sha>33e3c950af2eb996c0b3c48e30eb4471138da675</Sha> + <Sha>f7333f1afa250ed33d3db52f0b531910b23a55b2</Sha> </Dependency> - <Dependency Name="Microsoft.EntityFrameworkCore.Relational" Version="6.0.9"> + <Dependency Name="Microsoft.EntityFrameworkCore.Relational" Version="6.0.10"> <Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-efcore</Uri> - <Sha>33e3c950af2eb996c0b3c48e30eb4471138da675</Sha> + <Sha>f7333f1afa250ed33d3db52f0b531910b23a55b2</Sha> </Dependency> - <Dependency Name="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.9"> + <Dependency Name="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.10"> <Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-efcore</Uri> - <Sha>33e3c950af2eb996c0b3c48e30eb4471138da675</Sha> + <Sha>f7333f1afa250ed33d3db52f0b531910b23a55b2</Sha> </Dependency> - <Dependency Name="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.9"> + <Dependency Name="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.10"> <Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-efcore</Uri> - <Sha>33e3c950af2eb996c0b3c48e30eb4471138da675</Sha> + <Sha>f7333f1afa250ed33d3db52f0b531910b23a55b2</Sha> </Dependency> - <Dependency Name="Microsoft.EntityFrameworkCore.Tools" Version="6.0.9"> + <Dependency Name="Microsoft.EntityFrameworkCore.Tools" Version="6.0.10"> <Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-efcore</Uri> - <Sha>33e3c950af2eb996c0b3c48e30eb4471138da675</Sha> + <Sha>f7333f1afa250ed33d3db52f0b531910b23a55b2</Sha> </Dependency> - <Dependency Name="Microsoft.EntityFrameworkCore" Version="6.0.9"> + <Dependency Name="Microsoft.EntityFrameworkCore" Version="6.0.10"> <Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-efcore</Uri> - <Sha>33e3c950af2eb996c0b3c48e30eb4471138da675</Sha> + <Sha>f7333f1afa250ed33d3db52f0b531910b23a55b2</Sha> </Dependency> - <Dependency Name="Microsoft.EntityFrameworkCore.Design" Version="6.0.9"> + <Dependency Name="Microsoft.EntityFrameworkCore.Design" Version="6.0.10"> <Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-efcore</Uri> - <Sha>33e3c950af2eb996c0b3c48e30eb4471138da675</Sha> + <Sha>f7333f1afa250ed33d3db52f0b531910b23a55b2</Sha> </Dependency> <Dependency Name="Microsoft.Extensions.Caching.Abstractions" Version="6.0.0"> <Uri>https://github.com/dotnet/runtime</Uri> @@ -93,9 +93,9 @@ <Uri>https://github.com/dotnet/runtime</Uri> <Sha>4822e3c3aa77eb82b2fb33c9321f923cf11ddde6</Sha> </Dependency> - <Dependency Name="Microsoft.Extensions.DependencyInjection" Version="6.0.0"> - <Uri>https://github.com/dotnet/runtime</Uri> - <Sha>4822e3c3aa77eb82b2fb33c9321f923cf11ddde6</Sha> + <Dependency Name="Microsoft.Extensions.DependencyInjection" Version="6.0.1"> + <Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-runtime</Uri> + <Sha>5a400c212afdf8e675c9a1d38442e6d2f19f7b74</Sha> </Dependency> <Dependency Name="Microsoft.Extensions.FileProviders.Abstractions" Version="6.0.0"> <Uri>https://github.com/dotnet/runtime</Uri> @@ -177,9 +177,9 @@ <Uri>https://github.com/dotnet/runtime</Uri> <Sha>4822e3c3aa77eb82b2fb33c9321f923cf11ddde6</Sha> </Dependency> - <Dependency Name="Microsoft.Internal.Runtime.AspNetCore.Transport" Version="6.0.9-servicing.22419.5"> + <Dependency Name="Microsoft.Internal.Runtime.AspNetCore.Transport" Version="6.0.10-servicing.22476.5"> <Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-runtime</Uri> - <Sha>163a63591cf9e9b682063cf3995948c2b885a042</Sha> + <Sha>5a400c212afdf8e675c9a1d38442e6d2f19f7b74</Sha> </Dependency> <Dependency Name="System.Diagnostics.DiagnosticSource" Version="6.0.0"> <Uri>https://github.com/dotnet/runtime</Uri> @@ -245,40 +245,40 @@ <Uri>https://github.com/dotnet/runtime</Uri> <Sha>4822e3c3aa77eb82b2fb33c9321f923cf11ddde6</Sha> </Dependency> - <Dependency Name="Microsoft.NETCore.App.Ref" Version="6.0.9"> + <Dependency Name="Microsoft.NETCore.App.Ref" Version="6.0.10"> <Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-runtime</Uri> - <Sha>163a63591cf9e9b682063cf3995948c2b885a042</Sha> + <Sha>5a400c212afdf8e675c9a1d38442e6d2f19f7b74</Sha> </Dependency> - <Dependency Name="Microsoft.NET.Runtime.MonoAOTCompiler.Task" Version="6.0.9"> + <Dependency Name="Microsoft.NET.Runtime.MonoAOTCompiler.Task" Version="6.0.10"> <Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-runtime</Uri> - <Sha>163a63591cf9e9b682063cf3995948c2b885a042</Sha> + <Sha>5a400c212afdf8e675c9a1d38442e6d2f19f7b74</Sha> </Dependency> - <Dependency Name="Microsoft.NET.Runtime.WebAssembly.Sdk" Version="6.0.9"> + <Dependency Name="Microsoft.NET.Runtime.WebAssembly.Sdk" Version="6.0.10"> <Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-runtime</Uri> - <Sha>163a63591cf9e9b682063cf3995948c2b885a042</Sha> + <Sha>5a400c212afdf8e675c9a1d38442e6d2f19f7b74</Sha> </Dependency> <!-- Win-x64 is used here because we have picked an arbitrary runtime identifier to flow the version of the latest NETCore.App runtime. All Runtime.$rid packages should have the same version. --> - <Dependency Name="Microsoft.NETCore.App.Runtime.win-x64" Version="6.0.9"> + <Dependency Name="Microsoft.NETCore.App.Runtime.win-x64" Version="6.0.10"> <Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-runtime</Uri> - <Sha>163a63591cf9e9b682063cf3995948c2b885a042</Sha> + <Sha>5a400c212afdf8e675c9a1d38442e6d2f19f7b74</Sha> </Dependency> - <Dependency Name="Microsoft.NETCore.App.Runtime.AOT.win-x64.Cross.browser-wasm" Version="6.0.9"> + <Dependency Name="Microsoft.NETCore.App.Runtime.AOT.win-x64.Cross.browser-wasm" Version="6.0.10"> <Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-runtime</Uri> - <Sha>163a63591cf9e9b682063cf3995948c2b885a042</Sha> + <Sha>5a400c212afdf8e675c9a1d38442e6d2f19f7b74</Sha> </Dependency> - <Dependency Name="Microsoft.NETCore.BrowserDebugHost.Transport" Version="6.0.9-servicing.22419.5"> + <Dependency Name="Microsoft.NETCore.BrowserDebugHost.Transport" Version="6.0.10-servicing.22476.5"> <Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-runtime</Uri> - <Sha>163a63591cf9e9b682063cf3995948c2b885a042</Sha> + <Sha>5a400c212afdf8e675c9a1d38442e6d2f19f7b74</Sha> </Dependency> </ProductDependencies> <ToolsetDependencies> <!-- Listed explicitly to workaround https://github.com/dotnet/cli/issues/10528 --> - <Dependency Name="Microsoft.NETCore.Platforms" Version="6.0.5"> + <Dependency Name="Microsoft.NETCore.Platforms" Version="6.0.6"> <Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-runtime</Uri> - <Sha>f316191dbb5782d76ceb457018dcd80ff8ce8692</Sha> + <Sha>5a400c212afdf8e675c9a1d38442e6d2f19f7b74</Sha> </Dependency> <Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="6.0.0-beta.22463.7"> <Uri>https://github.com/dotnet/arcade</Uri> diff --git a/eng/Versions.props b/eng/Versions.props index 476775f07a678ee28a5ff26accd48cf44e0a38ac..21f391cb89f263d2dd7cb9375fe2b70ff3a7ccd5 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -63,12 +63,12 @@ <PropertyGroup Label="Automated"> <!-- Packages from dotnet/runtime --> <MicrosoftExtensionsDependencyModelVersion>6.0.0</MicrosoftExtensionsDependencyModelVersion> - <MicrosoftNETCoreAppRefVersion>6.0.9</MicrosoftNETCoreAppRefVersion> - <MicrosoftNETCoreAppRuntimewinx64Version>6.0.9</MicrosoftNETCoreAppRuntimewinx64Version> - <MicrosoftNETRuntimeMonoAOTCompilerTaskVersion>6.0.9</MicrosoftNETRuntimeMonoAOTCompilerTaskVersion> - <MicrosoftNETRuntimeWebAssemblySdkVersion>6.0.9</MicrosoftNETRuntimeWebAssemblySdkVersion> - <MicrosoftNETCoreAppRuntimeAOTwinx64CrossbrowserwasmVersion>6.0.9</MicrosoftNETCoreAppRuntimeAOTwinx64CrossbrowserwasmVersion> - <MicrosoftNETCoreBrowserDebugHostTransportVersion>6.0.9-servicing.22419.5</MicrosoftNETCoreBrowserDebugHostTransportVersion> + <MicrosoftNETCoreAppRefVersion>6.0.10</MicrosoftNETCoreAppRefVersion> + <MicrosoftNETCoreAppRuntimewinx64Version>6.0.10</MicrosoftNETCoreAppRuntimewinx64Version> + <MicrosoftNETRuntimeMonoAOTCompilerTaskVersion>6.0.10</MicrosoftNETRuntimeMonoAOTCompilerTaskVersion> + <MicrosoftNETRuntimeWebAssemblySdkVersion>6.0.10</MicrosoftNETRuntimeWebAssemblySdkVersion> + <MicrosoftNETCoreAppRuntimeAOTwinx64CrossbrowserwasmVersion>6.0.10</MicrosoftNETCoreAppRuntimeAOTwinx64CrossbrowserwasmVersion> + <MicrosoftNETCoreBrowserDebugHostTransportVersion>6.0.10-servicing.22476.5</MicrosoftNETCoreBrowserDebugHostTransportVersion> <MicrosoftExtensionsCachingAbstractionsVersion>6.0.0</MicrosoftExtensionsCachingAbstractionsVersion> <MicrosoftExtensionsCachingMemoryVersion>6.0.1</MicrosoftExtensionsCachingMemoryVersion> <MicrosoftExtensionsConfigurationAbstractionsVersion>6.0.0</MicrosoftExtensionsConfigurationAbstractionsVersion> @@ -82,7 +82,7 @@ <MicrosoftExtensionsConfigurationUserSecretsVersion>6.0.1</MicrosoftExtensionsConfigurationUserSecretsVersion> <MicrosoftExtensionsConfigurationXmlVersion>6.0.0</MicrosoftExtensionsConfigurationXmlVersion> <MicrosoftExtensionsDependencyInjectionAbstractionsVersion>6.0.0</MicrosoftExtensionsDependencyInjectionAbstractionsVersion> - <MicrosoftExtensionsDependencyInjectionVersion>6.0.0</MicrosoftExtensionsDependencyInjectionVersion> + <MicrosoftExtensionsDependencyInjectionVersion>6.0.1</MicrosoftExtensionsDependencyInjectionVersion> <MicrosoftExtensionsFileProvidersAbstractionsVersion>6.0.0</MicrosoftExtensionsFileProvidersAbstractionsVersion> <MicrosoftExtensionsFileProvidersCompositeVersion>6.0.0</MicrosoftExtensionsFileProvidersCompositeVersion> <MicrosoftExtensionsFileProvidersPhysicalVersion>6.0.0</MicrosoftExtensionsFileProvidersPhysicalVersion> @@ -103,7 +103,7 @@ <MicrosoftExtensionsOptionsDataAnnotationsVersion>6.0.0</MicrosoftExtensionsOptionsDataAnnotationsVersion> <MicrosoftExtensionsOptionsVersion>6.0.0</MicrosoftExtensionsOptionsVersion> <MicrosoftExtensionsPrimitivesVersion>6.0.0</MicrosoftExtensionsPrimitivesVersion> - <MicrosoftInternalRuntimeAspNetCoreTransportVersion>6.0.9-servicing.22419.5</MicrosoftInternalRuntimeAspNetCoreTransportVersion> + <MicrosoftInternalRuntimeAspNetCoreTransportVersion>6.0.10-servicing.22476.5</MicrosoftInternalRuntimeAspNetCoreTransportVersion> <SystemDiagnosticsDiagnosticSourceVersion>6.0.0</SystemDiagnosticsDiagnosticSourceVersion> <SystemDiagnosticsEventLogVersion>6.0.0</SystemDiagnosticsEventLogVersion> <SystemDirectoryServicesProtocolsVersion>6.0.1</SystemDirectoryServicesProtocolsVersion> @@ -120,16 +120,16 @@ <SystemTextJsonVersion>6.0.6</SystemTextJsonVersion> <SystemThreadingChannelsVersion>6.0.0</SystemThreadingChannelsVersion> <!-- Only listed explicitly to workaround https://github.com/dotnet/cli/issues/10528 --> - <MicrosoftNETCorePlatformsVersion>6.0.5</MicrosoftNETCorePlatformsVersion> + <MicrosoftNETCorePlatformsVersion>6.0.6</MicrosoftNETCorePlatformsVersion> <!-- Packages from dotnet/efcore --> - <dotnetefVersion>6.0.9</dotnetefVersion> - <MicrosoftEntityFrameworkCoreInMemoryVersion>6.0.9</MicrosoftEntityFrameworkCoreInMemoryVersion> - <MicrosoftEntityFrameworkCoreRelationalVersion>6.0.9</MicrosoftEntityFrameworkCoreRelationalVersion> - <MicrosoftEntityFrameworkCoreSqliteVersion>6.0.9</MicrosoftEntityFrameworkCoreSqliteVersion> - <MicrosoftEntityFrameworkCoreSqlServerVersion>6.0.9</MicrosoftEntityFrameworkCoreSqlServerVersion> - <MicrosoftEntityFrameworkCoreToolsVersion>6.0.9</MicrosoftEntityFrameworkCoreToolsVersion> - <MicrosoftEntityFrameworkCoreVersion>6.0.9</MicrosoftEntityFrameworkCoreVersion> - <MicrosoftEntityFrameworkCoreDesignVersion>6.0.9</MicrosoftEntityFrameworkCoreDesignVersion> + <dotnetefVersion>6.0.10</dotnetefVersion> + <MicrosoftEntityFrameworkCoreInMemoryVersion>6.0.10</MicrosoftEntityFrameworkCoreInMemoryVersion> + <MicrosoftEntityFrameworkCoreRelationalVersion>6.0.10</MicrosoftEntityFrameworkCoreRelationalVersion> + <MicrosoftEntityFrameworkCoreSqliteVersion>6.0.10</MicrosoftEntityFrameworkCoreSqliteVersion> + <MicrosoftEntityFrameworkCoreSqlServerVersion>6.0.10</MicrosoftEntityFrameworkCoreSqlServerVersion> + <MicrosoftEntityFrameworkCoreToolsVersion>6.0.10</MicrosoftEntityFrameworkCoreToolsVersion> + <MicrosoftEntityFrameworkCoreVersion>6.0.10</MicrosoftEntityFrameworkCoreVersion> + <MicrosoftEntityFrameworkCoreDesignVersion>6.0.10</MicrosoftEntityFrameworkCoreDesignVersion> <!-- Packages from dotnet/arcade --> <MicrosoftDotNetBuildTasksInstallersVersion>6.0.0-beta.22463.7</MicrosoftDotNetBuildTasksInstallersVersion> <MicrosoftDotNetBuildTasksTemplatingVersion>6.0.0-beta.22463.7</MicrosoftDotNetBuildTasksTemplatingVersion> diff --git a/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs b/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs index e495f45e472535233943f567840489b2de7695f6..dfbdf4a1e2263d711df74f39a7ef21faaed5df54 100644 --- a/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs +++ b/src/DataProtection/DataProtection/src/Repositories/FileSystemXmlRepository.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Runtime.InteropServices; using System.Xml.Linq; using Microsoft.AspNetCore.DataProtection.Internal; using Microsoft.Extensions.Logging; @@ -131,9 +132,17 @@ namespace Microsoft.AspNetCore.DataProtection.Repositories // crashes mid-write, we won't end up with a corrupt .xml file. Directory.Create(); // won't throw if the directory already exists + var tempFilename = Path.Combine(Directory.FullName, Guid.NewGuid().ToString() + ".tmp"); var finalFilename = Path.Combine(Directory.FullName, filename + ".xml"); + // Create a temp file with the correct Unix file mode before moving it to the expected finalFilename. + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + var tempTempFilename = Path.GetTempFileName(); + File.Move(tempTempFilename, tempFilename); + } + try { using (var tempFileStream = File.OpenWrite(tempFilename)) diff --git a/src/DataProtection/DataProtection/test/Repositories/FileSystemXmlRepositoryTests.cs b/src/DataProtection/DataProtection/test/Repositories/FileSystemXmlRepositoryTests.cs index 4a5fbd282bfd7b4d8efff9cf0142c28e86bd3e79..fce9cdf15f1a7da76642298db4987403c603898f 100644 --- a/src/DataProtection/DataProtection/test/Repositories/FileSystemXmlRepositoryTests.cs +++ b/src/DataProtection/DataProtection/test/Repositories/FileSystemXmlRepositoryTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.InteropServices; @@ -158,6 +159,39 @@ namespace Microsoft.AspNetCore.DataProtection.Repositories }); } + [ConditionalFact] + [OSSkipCondition(OperatingSystems.Windows, SkipReason = "UnixFileMode is not supported on Windows.")] + public void StoreElement_CreatesFileWithUserOnlyUnixFileMode() + { + WithUniqueTempDirectory(dirInfo => + { + // Arrange + var element = XElement.Parse("<element1 />"); + var repository = new FileSystemXmlRepository(dirInfo, NullLoggerFactory.Instance); + + // Act + repository.StoreElement(element, "friendly-name"); + + // Assert + var fileInfo = Assert.Single(dirInfo.GetFiles()); + + //Assert.Equal(UnixFileMode.UserRead | UnixFileMode.UserWrite, fileInfo.UnixFileMode); + var processStartInfo = new ProcessStartInfo + { + FileName = "ls", + Arguments = $"-l {fileInfo.FullName}", + RedirectStandardOutput = true, + UseShellExecute = false + }; + var process = Process.Start(processStartInfo); + + Assert.NotNull(process); + var output = process!.StandardOutput.ReadToEnd(); + process.WaitForExit(); + Assert.StartsWith("-rw-------", output); + }); + } + /// <summary> /// Runs a test and cleans up the temp directory afterward. /// </summary> diff --git a/src/Http/WebUtilities/src/FileBufferingReadStream.cs b/src/Http/WebUtilities/src/FileBufferingReadStream.cs index f66916c8ebff7b93e2e94f573fe1879cdd5652b2..f8873905c205bd7f56d6714efd1454f19be234a5 100644 --- a/src/Http/WebUtilities/src/FileBufferingReadStream.cs +++ b/src/Http/WebUtilities/src/FileBufferingReadStream.cs @@ -6,6 +6,7 @@ using System.Buffers; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; +using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Internal; @@ -258,6 +259,14 @@ namespace Microsoft.AspNetCore.WebUtilities } _tempFileName = Path.Combine(_tempFileDirectory, "ASPNETCORE_" + Guid.NewGuid().ToString() + ".tmp"); + + // Create a temp file with the correct Unix file mode before moving it to the assigned _tempFileName in the _tempFileDirectory. + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + var tempTempFileName = Path.GetTempFileName(); + File.Move(tempTempFileName, _tempFileName); + } + return new FileStream(_tempFileName, FileMode.Create, FileAccess.ReadWrite, FileShare.Delete, 1024 * 16, FileOptions.Asynchronous | FileOptions.DeleteOnClose | FileOptions.SequentialScan); } diff --git a/src/Http/WebUtilities/src/FileBufferingWriteStream.cs b/src/Http/WebUtilities/src/FileBufferingWriteStream.cs index 28c4c27ab7580f06bf7823fcee30634fba87113f..33ad86dc282a6dbda6ac094c7b14d3d1f63ce6e2 100644 --- a/src/Http/WebUtilities/src/FileBufferingWriteStream.cs +++ b/src/Http/WebUtilities/src/FileBufferingWriteStream.cs @@ -7,6 +7,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; using System.IO.Pipelines; +using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Internal; @@ -271,6 +272,14 @@ namespace Microsoft.AspNetCore.WebUtilities { var tempFileDirectory = _tempFileDirectoryAccessor(); var tempFileName = Path.Combine(tempFileDirectory, "ASPNETCORE_" + Guid.NewGuid() + ".tmp"); + + // Create a temp file with the correct Unix file mode before moving it to the assigned tempFileName in the _tempFileDirectory. + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + var tempTempFileName = Path.GetTempFileName(); + File.Move(tempTempFileName, tempFileName); + } + FileStream = new FileStream( tempFileName, FileMode.Create, diff --git a/src/Http/WebUtilities/test/FileBufferingReadStreamTests.cs b/src/Http/WebUtilities/test/FileBufferingReadStreamTests.cs index 640562b6c6a0b356158812fcc04f9e94f268f88b..29ea59fd5471f5eed9b523c700fa04435376527d 100644 --- a/src/Http/WebUtilities/test/FileBufferingReadStreamTests.cs +++ b/src/Http/WebUtilities/test/FileBufferingReadStreamTests.cs @@ -3,9 +3,11 @@ using System; using System.Buffers; +using System.Diagnostics; using System.IO; using System.Linq; using System.Threading.Tasks; +using Microsoft.AspNetCore.Testing; using Moq; using Xunit; @@ -598,6 +600,47 @@ namespace Microsoft.AspNetCore.WebUtilities Assert.Equal(data.AsMemory(0, read2).ToArray(), buffer2.AsMemory(0, read2).ToArray()); } + [ConditionalFact] + [OSSkipCondition(OperatingSystems.Windows, SkipReason = "UnixFileMode is not supported on Windows.")] + public void Read_BufferingContentToDisk_CreatesFileWithUserOnlyUnixFileMode() + { + var inner = MakeStream(1024 * 2); + string tempFileName; + using (var stream = new FileBufferingReadStream(inner, 1024, null, GetCurrentDirectory())) + { + var bytes = new byte[1024 * 2]; + var read0 = stream.Read(bytes, 0, bytes.Length); + Assert.Equal(bytes.Length, read0); + Assert.Equal(read0, stream.Length); + Assert.Equal(read0, stream.Position); + Assert.False(stream.InMemory); + Assert.NotNull(stream.TempFileName); + + var read1 = stream.Read(bytes, 0, bytes.Length); + Assert.Equal(0, read1); + + tempFileName = stream.TempFileName!; + Assert.True(File.Exists(tempFileName)); + + //Assert.Equal(UnixFileMode.UserRead | UnixFileMode.UserWrite, File.GetUnixFileMode(tempFileName)); + var processStartInfo = new ProcessStartInfo + { + FileName = "ls", + Arguments = $"-l {tempFileName}", + RedirectStandardOutput = true, + UseShellExecute = false + }; + var process = Process.Start(processStartInfo); + + Assert.NotNull(process); + var output = process!.StandardOutput.ReadToEnd(); + process.WaitForExit(); + Assert.StartsWith("-rw-------", output); + } + + Assert.False(File.Exists(tempFileName)); + } + private static string GetCurrentDirectory() { return AppContext.BaseDirectory; diff --git a/src/Http/WebUtilities/test/FileBufferingWriteStreamTests.cs b/src/Http/WebUtilities/test/FileBufferingWriteStreamTests.cs index 9459a192959d02c8d4ddd9bb26e3894ea309e4b6..3e326d267bc2bc4f9d53c39d4270a5f03c399fea 100644 --- a/src/Http/WebUtilities/test/FileBufferingWriteStreamTests.cs +++ b/src/Http/WebUtilities/test/FileBufferingWriteStreamTests.cs @@ -8,7 +8,9 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.Extensions.Configuration; +using Microsoft.AspNetCore.Testing; using Xunit; +using System.Diagnostics; namespace Microsoft.AspNetCore.WebUtilities { @@ -371,6 +373,37 @@ namespace Microsoft.AspNetCore.WebUtilities Assert.Equal(0, bufferingStream.Length); } + [ConditionalFact] + [OSSkipCondition(OperatingSystems.Windows, SkipReason = "UnixFileMode is not supported on Windows.")] + public void Write_BufferingContentToDisk_CreatesFileWithUserOnlyUnixFileMode() + { + // Arrange + var input = new byte[] { 1, 2, 3, }; + using var bufferingStream = new FileBufferingWriteStream(memoryThreshold: 2, tempFileDirectoryAccessor: () => TempDirectory); + bufferingStream.Write(input, 0, 2); + + // Act + bufferingStream.Write(input, 2, 1); + + // Assert + Assert.NotNull(bufferingStream.FileStream); + + //Assert.Equal(UnixFileMode.UserRead | UnixFileMode.UserWrite, File.GetUnixFileMode(bufferingStream.FileStream.SafeFileHandle)); + var processStartInfo = new ProcessStartInfo + { + FileName = "ls", + Arguments = $"-l {bufferingStream.FileStream!.Name}", + RedirectStandardOutput = true, + UseShellExecute = false + }; + var process = Process.Start(processStartInfo); + + Assert.NotNull(process); + var output = process!.StandardOutput.ReadToEnd(); + process.WaitForExit(); + Assert.StartsWith("-rw-------", output); + } + public void Dispose() { try diff --git a/src/Shared/CertificateGeneration/CertificateManager.cs b/src/Shared/CertificateGeneration/CertificateManager.cs index 987db2bba0315e8d20d1f9b24774b41e20590c1c..1e4295ca1dd25efa5fa981650bbb918b65b04920 100644 --- a/src/Shared/CertificateGeneration/CertificateManager.cs +++ b/src/Shared/CertificateGeneration/CertificateManager.cs @@ -7,6 +7,7 @@ using System.Diagnostics; using System.Diagnostics.Tracing; using System.IO; using System.Linq; +using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Text; @@ -539,6 +540,14 @@ namespace Microsoft.AspNetCore.Certificates.Generation try { Log.WriteCertificateToDisk(path); + + // Create a temp file with the correct Unix file mode before moving it to the expected path. + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + var tempFilename = Path.GetTempFileName(); + File.Move(tempFilename, path, overwrite: true); + } + File.WriteAllBytes(path, bytes); } catch (Exception ex) when (Log.IsEnabled()) @@ -559,6 +568,14 @@ namespace Microsoft.AspNetCore.Certificates.Generation { var keyPath = Path.ChangeExtension(path, ".key"); Log.WritePemKeyToDisk(keyPath); + + // Create a temp file with the correct Unix file mode before moving it to the expected path. + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + var tempFilename = Path.GetTempFileName(); + File.Move(tempFilename, keyPath, overwrite: true); + } + File.WriteAllBytes(keyPath, pemEnvelope); } catch (Exception ex) when (Log.IsEnabled()) diff --git a/src/Tools/FirstRunCertGenerator/test/CertificateManagerTests.cs b/src/Tools/FirstRunCertGenerator/test/CertificateManagerTests.cs index 297d7a13da9e8b0d9839fbfc74158ae7af7f95f2..d406d8bf940dfe1ea38be454cd2cc21913ee9dc9 100644 --- a/src/Tools/FirstRunCertGenerator/test/CertificateManagerTests.cs +++ b/src/Tools/FirstRunCertGenerator/test/CertificateManagerTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.InteropServices; @@ -419,6 +420,51 @@ namespace Microsoft.AspNetCore.Certificates.Generation.Tests e.Oid.Value == "1.3.6.1.4.1.311.84.1.1" && e.RawData[0] == 1); } + + [ConditionalFact] + [OSSkipCondition(OperatingSystems.Windows, SkipReason = "UnixFileMode is not supported on Windows.")] + [OSSkipCondition(OperatingSystems.MacOSX, SkipReason = "https://github.com/dotnet/aspnetcore/issues/6720")] + public void EnsureCreateHttpsCertificate_CreatesFilesWithUserOnlyUnixFileMode() + { + _fixture.CleanupCertificates(); + + const string CertificateName = nameof(EnsureCreateHttpsCertificate_CreatesFilesWithUserOnlyUnixFileMode) + ".pem"; + const string KeyName = nameof(EnsureCreateHttpsCertificate_CreatesFilesWithUserOnlyUnixFileMode) + ".key"; + + var certificatePassword = Guid.NewGuid().ToString(); + var now = DateTimeOffset.UtcNow; + now = new DateTimeOffset(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, 0, now.Offset); + + var result = _manager + .EnsureAspNetCoreHttpsDevelopmentCertificate(now, now.AddYears(1), CertificateName, trust: false, includePrivateKey: true, password: certificatePassword, keyExportFormat: CertificateKeyExportFormat.Pem, isInteractive: false); + + Assert.Equal(EnsureCertificateResult.Succeeded, result); + + Assert.True(File.Exists(CertificateName)); + //Assert.Equal(UnixFileMode.UserRead | UnixFileMode.UserWrite, File.GetUnixFileMode(CertificateName)); + AssertFileMode(CertificateName, "-rw-------"); + + Assert.True(File.Exists(KeyName)); + //Assert.Equal(UnixFileMode.UserRead | UnixFileMode.UserWrite, File.GetUnixFileMode(KeyName)); + AssertFileMode(KeyName, "-rw-------"); + } + + private static void AssertFileMode(string path, string fileMode) + { + var processStartInfo = new ProcessStartInfo + { + FileName = "ls", + Arguments = $"-l {path}", + RedirectStandardOutput = true, + UseShellExecute = false + }; + var process = Process.Start(processStartInfo); + + Assert.NotNull(process); + var output = process!.StandardOutput.ReadToEnd(); + process.WaitForExit(); + Assert.StartsWith(fileMode, output); + } } public class CertFixture : IDisposable diff --git a/src/Tools/dotnet-user-secrets/src/Internal/SecretsStore.cs b/src/Tools/dotnet-user-secrets/src/Internal/SecretsStore.cs index a2d3bb40b1668b1203d5a2fad90942264c2eb7e7..5648f643ce5a09bc11a37e00aa86fe131650ddeb 100644 --- a/src/Tools/dotnet-user-secrets/src/Internal/SecretsStore.cs +++ b/src/Tools/dotnet-user-secrets/src/Internal/SecretsStore.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Runtime.InteropServices; using System.Text; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration.UserSecrets; @@ -46,6 +47,9 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal public int Count => _secrets.Count; + // For testing. + internal string SecretsFilePath => _secretsFilePath; + public bool ContainsKey(string key) => _secrets.ContainsKey(key); public IEnumerable<KeyValuePair<string, string>> AsEnumerable() => _secrets; @@ -75,6 +79,13 @@ namespace Microsoft.Extensions.SecretManager.Tools.Internal } } + // Create a temp file with the correct Unix file mode before moving it to the expected _filePath. + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + var tempFilename = Path.GetTempFileName(); + File.Move(tempFilename, _secretsFilePath, overwrite: true); + } + File.WriteAllText(_secretsFilePath, contents.ToString(), Encoding.UTF8); } diff --git a/src/Tools/dotnet-user-secrets/src/Program.cs b/src/Tools/dotnet-user-secrets/src/Program.cs index b939a4798e7614838deedaed1ca1b1b56defb561..be8eb3185bd45a7b128adcc14055a950f4c67546 100644 --- a/src/Tools/dotnet-user-secrets/src/Program.cs +++ b/src/Tools/dotnet-user-secrets/src/Program.cs @@ -29,6 +29,9 @@ namespace Microsoft.Extensions.SecretManager.Tools _workingDirectory = workingDirectory; } + // For testing. + internal string SecretsFilePath { get; private set; } + public bool TryRun(string[] args, out int returnCode) { try @@ -91,6 +94,10 @@ namespace Microsoft.Extensions.SecretManager.Tools var store = new SecretsStore(userSecretsId, reporter); var context = new Internal.CommandContext(store, reporter, _console); options.Command.Execute(context); + + // For testing. + SecretsFilePath = store.SecretsFilePath; + return 0; } diff --git a/src/Tools/dotnet-user-secrets/test/SecretManagerTests.cs b/src/Tools/dotnet-user-secrets/test/SecretManagerTests.cs index 515cff54bd7aff6ddaaf591a6ce514f8d79158e5..e08f36ac278a0c13976c15f68b0914bbb26c7040 100644 --- a/src/Tools/dotnet-user-secrets/test/SecretManagerTests.cs +++ b/src/Tools/dotnet-user-secrets/test/SecretManagerTests.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Globalization; using System.IO; using System.Text; @@ -338,5 +339,32 @@ namespace Microsoft.Extensions.SecretManager.Tools.Tests Assert.DoesNotContain(Resources.FormatError_ProjectMissingId(project), _console.GetOutput()); Assert.DoesNotContain("--help", _console.GetOutput()); } + + [ConditionalFact] + [OSSkipCondition(OperatingSystems.Windows, SkipReason = "UnixFileMode is not supported on Windows.")] + public void SetSecrets_CreatesFileWithUserOnlyUnixFileMode() + { + var projectPath = _fixture.GetTempSecretProject(); + var secretManager = new Program(_console, projectPath); + + secretManager.RunInternal("set", "key1", Guid.NewGuid().ToString(), "--verbose"); + + Assert.NotNull(secretManager.SecretsFilePath); + + //Assert.Equal(UnixFileMode.UserRead | UnixFileMode.UserWrite, File.GetUnixFileMode(secretManager.SecretsFilePath)); + var processStartInfo = new ProcessStartInfo + { + FileName = "ls", + Arguments = $"-l {secretManager.SecretsFilePath}", + RedirectStandardOutput = true, + UseShellExecute = false + }; + var process = Process.Start(processStartInfo); + + Assert.NotNull(process); + var output = process!.StandardOutput.ReadToEnd(); + process.WaitForExit(); + Assert.StartsWith("-rw-------", output); + } } }