locked
Why does hosting a website in ASP.NET Core require write access to RRS feed

  • Question

  • User1879745236 posted

    When trying to run my ASP.NET Core website it crashes while trying to create a directory in C:\WINDOWS\system32\config\systemprofile\.

    1. Why is that even necessary?

    2. What components/features might require this?
    I'm not using anything that might need it, from a feature like FileDataStore I can understand it.

    3. I've tried turning off all kinds of features activated in the startup.cs, the same error remains or hosting breaks entirely.

    4. I've tried granting IIS_USRS write access to the folder. However this is not a real solution as I cannot tell my customers that my hosted website requires access to the system32 folder. It also makes no sense for .NET Core. Which is supposed to be platform independent and all. Yet it requires access to a hardcoded file path?!

    5. I want to list all the features being used. The Startup.cs calls several other files. So in order to keep it readable I flattened the code and simplified some of the names. It could be that a compiler error sneaked in because of that. But the actual code compiles fine.:

    using System;
    using System.Diagnostics;
    using System.IO;
    using System.Net.Http;
    using System.Text.Json;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.DataProtection;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Identity;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.DependencyInjection.Extensions;
    using Microsoft.Extensions.Hosting;
    using Company.Features; namespace Company.WebSite {   public class Startup {     private IConfiguration m_Configuration;     public IConfiguration Configuration { get { return m_Configuration; } }     public Startup (IConfiguration configuration) {       m_Configuration = configuration;     } // Constructor Startup     public void ConfigureServices (IServiceCollection services) {       IConfigurationSection root = Configuration.GetSection(MyOptions.OptionsKey);       MyOptions options = root.Get<MyOptions>();       services.Configure<MyOptions>(root);       services.TryAddTransient<ForwardTokenHandler>();       IHttpClientBuilder blClientBuilder = services.AddHttpClient(MyWebApiClient.ClientName);       blClientBuilder.ConfigurePrimaryHttpMessageHandler(serviceProvider => {         return new HttpClientHandler() {           AllowAutoRedirect = false,           PreAuthenticate = true,           UseDefaultCredentials = true,         };       });       blClientBuilder.AddHttpMessageHandler<ForwardTokenHandler>();       services.Configure<DataProtectionTokenProviderOptions>(options => options.TokenLifespan = TimeSpan.FromDays(2));       IDataProtectionBuilder dataProtectionBuilder = services.AddDataProtection();       DataProtectionOptions dataProtectionOptions = root.GetSection(DataProtectionOptions.OptionsKey).Get<DataProtectionOptions>();       if (dataProtectionOptions != null) {         if (!String.IsNullOrWhiteSpace(dataProtectionOptions.KeyRingFolder) && Directory.Exists(dataProtectionOptions.KeyRingFolder)) {           // This would be a candidate for requiring file system access so I tried commenting out this line.           dataProtectionBuilder.PersistKeysToFileSystem(new DirectoryInfo(dataProtectionOptions.KeyRingFolder));           dataProtectionBuilder.ProtectKeysWithDpapi(true);         }         if (!String.IsNullOrWhiteSpace(dataProtectionOptions.ApplicationName)) {           dataProtectionBuilder.SetApplicationName(dataProtectionOptions.ApplicationName);         }       }       WebSessionStateOptions sessionStateOptions = root.GetSection(sessionStateOptions.OptionsKey).Get<sessionStateOptions>();       if (sessionStateOptions == null) {         sessionStateOptions = new WebSessionStateOptions();         sessionStateOptions.Cookie.Name = ".Company.WebSession";       }       services.AddSession(options => {         options.IdleTimeout = TimeSpan.FromMinutes(20);       });       IConfigurationSection securitySection = configuration.GetSection(SecurityClientOptions.OptionsKey);       SecurityClientOptions securityOptions = securitySection.Get<SecurityClientOptions>();       services.Configure<SecurityClientOptions>(securitySection);       services.AddHttpContextAccessor();       IConfigurationSection securitySection = configuration.GetSection(SecurityClientOptions.OptionsKey);       SecurityClientOptions securityOptions = securitySection.Get<SecurityClientOptions>();       if (securityOptions.AuthenticationType == AuthenticationType.Windows) {         // Potential cause of file system problems, tried commenting it out.         services.AddTransient<ITokenStorage, CookieTokenStorage>(serviceProvider => {           IHttpContextAccessor contextAccessor = serviceProvider.GetRequiredService<IHttpContextAccessor>();           return new CookieTokenStorage(contextAccessor);         });       } else if (securityOptions.AuthenticationType == AuthenticationType.Cookies) {         CookieAuthenticationOptions cookieOptions = securitySection.GetSection(CookieAuthenticationOptions.OptionsKey).Get<CookieAuthenticationOptions>();         if (cookieOptions != null) {           services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options => {             options.Cookie.Name = cookieOptions.Cookie.Name;           });         }         // Potential cause of file system problems, tried commenting it out.         services.AddTransient<ITokenStorage, ClaimsTokenStorage>();       }       services.AddTransient<MyWebApiClient>();       services.AddTransient<ConfigController>();       IMvcBuilder mvcBuilder = services.AddControllersWithViews();       services.AddAntiforgery();       if (services == null) { throw new ArgumentNullException(nameof(services)); }       services.TryAddTransient<SessionIdHandler>();       services.TryAddTransient<ForwardTokenHandler>();       IHttpClientBuilder builder = services.AddHttpClient("SecurityApiClient");       builder.ConfigurePrimaryHttpMessageHandler(serviceProvider => {         return new HttpClientHandler() {         };       });       builder.AddHttpMessageHandler<SessionIdHandler>();       builder.AddHttpMessageHandler<ForwardTokenHandler>();       services.TryAddTransient<JwtTokenService>();       CookieEncryption.Initialize(securityOptions.CookieEncryptionKey);       return services;     } // ConfigureClientSecurity     public void Configure (IApplicationBuilder appIWebHostEnvironment env) {       if (env.IsDevelopment()) {         app.UseDeveloperExceptionPage();       } else {         app.UseExceptionHandler("/Home/Error");         app.UseHsts();       }       app.UseStaticFiles(); // Tried commenting this out.       app.UseRouting();       app.UseAuthentication();       app.UseAuthorization();       app.UseSession();       app.UseEndpoints(endpoints => {         endpoints.MapControllerRoute(           name"Default",           pattern"{controller=Home}/{action=Index}");       });     }   } }

    Edit 1:
    6. The full error from browser:

    HTTP Error 500.31 - ANCM Failed to Find Native Dependencies

    Common solutions to this issue:

    The specified version of Microsoft.NetCore.App or Microsoft.AspNetCore.App was not found.

    Specific error detected by ANCM:

    System.UnauthorizedAccessException: Access to the path 'C:\WINDOWS\system32\config\systemprofile\.dotnet' is denied. at System.IO.FileSystem.CreateDirectory(String fullPath, Byte[] securityDescriptor) at System.IO.Directory.CreateDirectory(String path) at Microsoft.Extensions.EnvironmentAbstractions.DirectoryWrapper.CreateDirectory(String path) at Microsoft.DotNet.Configurer.FileSystemExtensions.<>c__DisplayClass0_0.b__0() at Microsoft.DotNet.Cli.Utils.FileAccessRetrier.RetryOnIOException(Action action) at Microsoft.DotNet.Configurer.FileSystemExtensions.CreateIfNotExists(IFileSystem fileSystem, String filePath) at Microsoft.DotNet.Configurer.FileSentinel.Create() at Microsoft.DotNet.Configurer.DotnetFirstTimeUseConfigurer.Configure() at Microsoft.DotNet.Cli.Program.ConfigureDotNetForFirstTimeUse(IFirstTimeUseNoticeSentinel firstTimeUseNoticeSentinel, IAspNetCertificateSentinel aspNetCertificateSentinel, IFileSentinel toolPathSentinel, Boolean isDotnetBeingInvokedFromNativeInstaller, DotnetFirstRunConfiguration dotnetFirstRunConfiguration, IEnvironmentProvider environmentProvider) at Microsoft.DotNet.Cli.Program.ProcessArgs(String[] args, ITelemetry telemetryClient) at Microsoft.DotNet.Cli.Program.Main(String[] args)

    7. Event viewer error (there are three, but this is the only one with relevant information):

    Could not find 'aspnetcorev2_inprocess.dll'. Exception message:
    System.UnauthorizedAccessException: Access to the path 'C:\WINDOWS\system32\config\systemprofile\.dotnet' is denied.
       at System.IO.FileSystem.CreateDirectory(String fullPath, Byte[] securityDescriptor)
       at System.IO.Directory.CreateDirectory(String path)
       at Microsoft.Extensions.EnvironmentAbstractions.DirectoryWrapper.CreateDirectory(String path)
       at Microsoft.DotNet.Configurer.FileSystemExtensions.<>c__DisplayClass0_0.<CreateIfNotExists>b__0()
       at Microsoft.DotNet.Cli.Utils.FileAccessRetrier.RetryOnIOException(Action action)
       at Microsoft.DotNet.Configurer.FileSystemExtensions.CreateIfNotExists(IFileSystem fileSystem, String filePath)
       at Microsoft.DotNet.Configurer.FileSentinel.Create()
       at Microsoft.DotNet.Configurer.DotnetFirstTimeUseConfigurer.Configure()
       at Microsoft.DotNet.Cli.Program.ConfigureDotNetForFirstTimeUse(IFirstTimeUseNoticeSentinel firstTimeUseNoticeSentinel, IAspNetCertificateSentinel aspNetCertificateSentinel, IFileSentinel toolPathSentinel, Boolean isDotnetBeingInvokedFromNativeInstaller, DotnetFirstRunConfiguration dotnetFirstRunConfiguration, IEnvironmentProvider environmentProvider)
       at Microsoft.DotNet.Cli.Program.ProcessArgs(String[] args, ITelemetry telemetryClient)
       at Microsoft.DotNet.Cli.Program.Main(String[] args)

    Edit 2:

    It turns out the arguments reference in my Web.Config to the compiled project file had the wrong name. I renamed it but the site still doesn't work. It's annoying that we get these random errors unrelated to the actual problem. I don't get an error message any more, only a warning in the Event Viewer:

    Error unprotecting the session cookie.
     
    Exception: 
    System.Security.Cryptography.CryptographicException: The key {GUID} was not found in the key ring.
    This is very strange as the cookie protection shouldn't be used because the settings aren't there. So the real error is probably something completely different. As with the other error.
    Thursday, December 10, 2020 8:40 PM

Answers

  • User475983607 posted

    There are many reasons for the error; HTTP Error 500.31 - ANCM Failed to Find Native Dependencies.  If you've installed the correct run-time then the issue is usually something in the startup.  

    The easiest way to find the problem is to start the application using the dotnet command line utility.  This requires SDK installation on your server.  you can also enable logging and set the application to development mode.

    For dotnet just remote to the server.  Open the application folder.  Type CMD in the windows explorer address bar to open the command prompt. Start the app.

    dotnet YouApplication.dll

    Startup error messages will show in the console.  Otherwise copy the application URL into the browser and open the application.  Any errors will show in the console.

    The other method is setting configuration in the server to development mode.  I use server variables and have how you configure the app but the docs explain environments.

    https://docs.microsoft.com/en-us/aspnet/core/fundamentals/environments?view=aspnetcore-5.0

    Open the web.config and enable logging.

    stdoutLogEnabled="true" stdoutLogFile=".\logs\stdout"

    Then access the app as normal.  Check the logs folder for errors.  I use first method when I get the ANCM error. It's usually an oversight in my startup logic.   I use the last method when there's a problem with a page that I can't figure out on my dev box.

    Anyway, these troubleshooting approaches are covered in the standard troubleshooting documentation.

    https://docs.microsoft.com/en-us/aspnet/core/test/troubleshoot-azure-iis?view=aspnetcore-5.0

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, December 11, 2020 1:00 PM

All replies

  • User753101303 posted

    Hi,

    Which details do you have about this error? Don't you have the folder name or even a call stack? Possibly use http://docs.lacunasoftware.com/en-us/articles/amplia/on-premises/windows/enable-stdout-log.html to see if you get something from the log.

    You usually don't read code to guess which error happens but to understand  why the error you already know happens.

    Thursday, December 10, 2020 10:44 PM
  • User-821857111 posted

    According to this issue: https://github.com/dotnet/sdk/issues/9717, it happens when dotnet.exe is first run. Someone found a solution by changing the web config. Perhaps try that?

    Friday, December 11, 2020 7:05 AM
  • User585649674 posted

    Could not find 'aspnetcorev2_inprocess.dll'. Exception message:
    System.UnauthorizedAccessException: Access to the path 'C:\WINDOWS\system32\config\systemprofile\.dotnet' is denied.

    It is looking at the dotnet restore folder because it could not find the "aspnetcorev2......dll"

    Please double check if netcore module for IIS is installed in the server.

    Go to IIS. Click on server name on left side.

    double click on modules.

    There should be "AspNetCoreModuleV2"

    If present, restart the IIS for good measure. Also verify the app pool settings, it must be .Net CLR version must be "No Managed Code" and Managed Pipeline must be "Integrated"

    If not present, download and install "dotnet-hosting-<version>-win.exe"

    Friday, December 11, 2020 7:25 AM
  • User753101303 posted

    As poiinted by nideeshm make sure you don't skip the https://docs.microsoft.com/en-us/aspnet/core/tutorials/publish-to-iis?view=aspnetcore-5.0&tabs=visual-studio#install-the-net-core-hosting-bundle step on this server (seems dotnet ends up in trying this folder to find the missing DLL).

    As you see it"s much easier to start from the actual error rather than trying to guess which error you have by reading code.

    Edit: while at it and to be on the safe side you could also run dotnet --list-runtimes and check you have the expected runtimes.

    Friday, December 11, 2020 8:06 AM
  • User1879745236 posted

    Thanks for the quick response. I've installed the hosting package and the module is available in IIS. Hosting web api's and another website converted by a colleague works fine. So it's not a system problem but a problem with this specific website. I've added additional information to the original post.

    Friday, December 11, 2020 12:22 PM
  • User475983607 posted

    There are many reasons for the error; HTTP Error 500.31 - ANCM Failed to Find Native Dependencies.  If you've installed the correct run-time then the issue is usually something in the startup.  

    The easiest way to find the problem is to start the application using the dotnet command line utility.  This requires SDK installation on your server.  you can also enable logging and set the application to development mode.

    For dotnet just remote to the server.  Open the application folder.  Type CMD in the windows explorer address bar to open the command prompt. Start the app.

    dotnet YouApplication.dll

    Startup error messages will show in the console.  Otherwise copy the application URL into the browser and open the application.  Any errors will show in the console.

    The other method is setting configuration in the server to development mode.  I use server variables and have how you configure the app but the docs explain environments.

    https://docs.microsoft.com/en-us/aspnet/core/fundamentals/environments?view=aspnetcore-5.0

    Open the web.config and enable logging.

    stdoutLogEnabled="true" stdoutLogFile=".\logs\stdout"

    Then access the app as normal.  Check the logs folder for errors.  I use first method when I get the ANCM error. It's usually an oversight in my startup logic.   I use the last method when there's a problem with a page that I can't figure out on my dev box.

    Anyway, these troubleshooting approaches are covered in the standard troubleshooting documentation.

    https://docs.microsoft.com/en-us/aspnet/core/test/troubleshoot-azure-iis?view=aspnetcore-5.0

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, December 11, 2020 1:00 PM