aspnet / Configuration

[Archived] Interfaces and providers for accessing configuration files. Project moved to https://github.com/aspnet/Extensions

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Use of User Secrets Crashes in Environments without Appropriate Environment Variables

chrisoverzero opened this issue · comments

I am developing ASP.NET Core applications to run on AWS Lambda. When running the application locally, User Secrets works correctly, retrieving configuration from my %APPDATA%. After deploying the application to our development environment (I am aware of the intended use pattern of user secrets), however, it crashes with the included stack trace.

Looking at the source code, it appears that if neither %APPDATA% nor $HOME is set, a null is passed into Path.Combine. When running in AWS Lambda, for example, neither is set.

Stack trace details
An exception was thrown when the constructor for type 'NestingWorkflow.Http.LambdaFunction' was invoked. Check inner exception for more details.: LambdaException


at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor)
at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
at System.Activator.CreateInstance(Type type, Boolean nonPublic)
at System.Activator.CreateInstance(Type type)
Value cannot be null.
Parameter name: paths: ArgumentNullException
at System.IO.Path.Combine(String[] paths)
at Microsoft.Extensions.Configuration.UserSecrets.PathHelper.GetSecretsPathFromSecretsId(String userSecretsId)
at Microsoft.Extensions.Configuration.UserSecretsConfigurationExtensions.AddUserSecrets(IConfigurationBuilder configuration, String userSecretsId)
at Microsoft.Extensions.Configuration.UserSecretsConfigurationExtensions.AddUserSecrets(IConfigurationBuilder configuration, Assembly assembly, Boolean optional)
at Amazon.Lambda.AspNetCoreServer.APIGatewayProxyFunction.<>c.<CreateWebHostBuilder>b__12_0(WebHostBuilderContext hostingContext, IConfigurationBuilder config)
at Microsoft.AspNetCore.Hosting.WebHostBuilder.BuildCommonServices(AggregateException& hostingStartupErrors)
at Microsoft.AspNetCore.Hosting.WebHostBuilder.Build()
at Amazon.Lambda.AspNetCoreServer.APIGatewayProxyFunction..ctor()

Resolved with #873. I added more fallbacks. If nothing by default is found, you'll need to set an environment variable.

I don't think this solution solves my problem.

What's been implemented is a solution to "I want to read some user secrets from a place, but I have no HOME." However, I don't want to read any user secrets because there are none to read.

My current workaround is to set a HOME environment variable. It seems no better (and maybe worse?) to me to set DOTNET_USER_SECRETS_FALLBACK_DIR in order to read no secrets. It was my hope that lacking appropriate environment variables would cause this to no-op.

Have you given my fix a try yet? I also added calls to a few new locations via Environment.GetFolderPath. Are these also empty in AWS Lambda?

Are these also empty in AWS Lambda?

I'm afraid so. A function with this body:

context.Logger.LogLine($"ApplicationData: '{Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)}'");
context.Logger.LogLine($"UserProfile: '{Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)}'");

...produces this log output:

START RequestId: be8f3bbe-c029-11e8-9565-b1b4fea56a89 Version: $LATEST
ApplicationData: ''
UserProfile: ''
END RequestId: be8f3bbe-c029-11e8-9565-b1b4fea56a89
REPORT RequestId: be8f3bbe-c029-11e8-9565-b1b4fea56a89	Duration: 0.43 ms	Billed Duration: 100 ms 	Memory Size: 256 MB	Max Memory Used: 19 MB

Oh. What is a reasonable default for this environment then? No-op is not a great solution here because this may disguise or hide real issues.

That's a good question.

According to the docs, the only reasonable variable is LAMBDA_TASK_ROOT. Th-This isn't something you want to bake into the library, I'm sure.

Maybe a configuration setting that names the environment variable whose value to use? This is only very slightly better than my current solution of setting HOME to "/var/task". It does no more than remove the hard-coding. But maybe that's enough.

Ok. In the absence of a better default, I'd suggest setting DOTNET_USER_SECRETS_FALLBACK_DIR, or setting the ASPNETCORE_ENVIRONMENT to Production instead of Development.