Disabling development environment in .NET Core 2.0 app in AWS - amazon-web-services

I have a .NET Core MVC app that I deployed to AWS ElasticBeanstalk. But when i go to the app i get an error with message:
Development environment should not be enabled in deployed applications
In launchsettings.json file i have set ASPNETCORE_ENVIRONMENT's
value to Production.
When i deploy app using Visual Studio (AWS toolkit) i set Project
build configuration's value to Release.
I have also created environment variable with name
ASPNETCORE_ENVIRONMENT and value Production in EB Software Configuration.
But I am still getting the same error, any idea what would be the fix ?
My launchSettings.json file looks like this:
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://DUMMY.us-west-2.elasticbeanstalk.com/",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "http://DUMMY.us-west-2.elasticbeanstalk.com/",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"AlacsWeb": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://DUMMY.us-west-2.elasticbeanstalk.com/"
}
}
}
And startup.cs file:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
// Add application services.
services.AddTransient<IEmailSender, EmailSender>();
services.AddMvc();
// Add http context
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseBrowserLink();
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}

Thanks for posting your code. I'm answering here because there's more to say than the comment form will allow.
TLDR
Your environment variables are ignored in EBS because your startup isn't picking them up.
I don't know what influence launchSettings.json has in EBS but given that the environment variables in that file are ignored I suspect the answer is none whatsoever.
You can save environment variables in EBS.
launchSettings.json
I don't use these myself, so what follows is research and trivial testing.
This MS article claims that this file only kicks in for running in Visual Studio
When using Visual Studio, environment variables may be set in the launchSettings.json file.
However I know from a simple test that these are also picked up by dotnet run in the project directory. Also, I know that VS Code ignores it in favour of .vscode/launch.json.
What I do not know is whether IIS pays any attention to it. (IIS in an EBS instance I mean, as opposed to IIS Express on your dev box).
Environment variables
I think I can see why environment variables are being ignored.
Startup.cs has an alternative constructor which lets you build the configuration object from environment variables, configuration files, and so on. It accepts an IHostingEnvironment instance.
public class Startup
{
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.AddEnvironmentVariables(); // <--- This picks up env variables
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; }
// etc ....
}
EB environment variables
As I explained in a comment, EB + dotnet core 2 are in a right mess over environment variables. Our solution is not to parse the infernal file per my earlier answer but to Dockerise our dotnet apps.
That said, you can save environment variables in EB. As you say, Software Configuration is the correct place to enter them. Then, click on your environment (the green/grey/whatever card as it appears in EB), go to the Actions menu, and Save Configuration.

launchsettings.json is visual studio build specific. It doesn't impact deployment.
Following question has provided some insight on the issue
AWS Elastic Beanstalk environment variables in ASP.NET Core 1.0

a crazy solution:
replace:
if (env.IsDevelopment())
{
app.UseBrowserLink();
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
to
app.UseBrowserLink();
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();

Related

Specify multiple provisioning profile for expo local credentials

Expo EAS has a way to use local credentials
The problem is that I have 2 environments: production and development, and 2 provision profile accordingly. Unfortunatly I can't find a way how to define 2 different provision profiles in credentials.json.
{
"android": {
"keystore": {
"keystorePath": "android/keystores/release.keystore",
"keystorePassword": "paofohlooZ9e",
"keyAlias": "keyalias",
"keyPassword": "aew1Geuthoev"
}
},
"ios": {
"provisioningProfilePath": "ios/certs/profile.mobileprovision",
"distributionCertificate": {
"path": "ios/certs/dist-cert.p12",
"password": "iex3shi9Lohl"
}
}
}
The only field we have here is provisioningProfilePath.
When I'm trying to build internal distribution with a production profile, of course, I'm getting the error: You must use an adhoc provisioning profile (target 'TARGET NAME)' for internal distribution any solution?
Any suggestions?

How does .Net 6 determine it Enviroment

I've created a .Net 6.0 Console application. I need it to be able to migrate the database using the Entity Framework. Now when I run it, it says it's environment is 'Production'. Where is that configured?
Here's the startup code for the application.
static void Main(string[] args)
{
using IHost host = Host.CreateDefaultBuilder(args)
.UseSerilog((context, loggerConfiguration) => loggerConfiguration
.ReadFrom.Configuration(context.Configuration)
.WriteTo.Console())
.ConfigureServices((context, services) =>
{
services.RegisterCoreServices(context.Configuration);
})
.Build();
CallBatch(host.Services, args);
host.RunAsync();
}
Production is the default.
Check out Use multiple environments in ASP.NET Core
Environments
To determine the runtime environment, ASP.NET Core reads from the following environment variables:
DOTNET_ENVIRONMENT
ASPNETCORE_ENVIRONMENT when the WebApplication.CreateBuilder method is called. The default ASP.NET Core web app templates call WebApplication.CreateBuilder. The ASPNETCORE_ENVIRONMENT value overrides DOTNET_ENVIRONMENT.
IHostEnvironment.EnvironmentName can be set to any value, but the following values are provided by the framework:
Development: The launchSettings.json file sets ASPNETCORE_ENVIRONMENT to Development on the local machine.
Staging
Production: The default if DOTNET_ENVIRONMENT and ASPNETCORE_ENVIRONMENT have not been set.

Unity UWP build can't find AWSCredentials in the the shared credentials file in the default location

I'm making some tests (create a bucket, upload a file, list buckets etc) with Unity-UWP and Amazon AWS.
When I play it in the Editor, every thing works fine but when I try to find my AWS credentials in the UWP build it can't find them. This is my code:
void Start()
{
chain = new CredentialProfileStoreChain();
if (chain.TryGetAWSCredentials("default", out awsCredentials))
{
client = new AmazonS3Client(awsCredentials);
Debug.Log("Credential OK");
}
else
{
Debug.Log("Credential NO OK");
}
}
So, every time, I got "Credential NO OK" and can't continue with the tests.
Could it be because UWP is very sandboxed and the user is not giving explicit access to the "credentials" and "config" file in the defaul location?
If so, what could be the solution or workaround. I wouldn't like to use my credentials in the code.
Unity Version: 2020.3.3f1
AWS SDK: Version 3.7.38 of the netstandard2.0 DLLs
Build Environment: Visual Studio 2019
Build Type: Executable Only (for fast iteration and local test)
Build Configuration: Release
Target Architecture: x64
Test Environment: UWP running on Windows 10 Desktop, build 19041.985
Api Compatibility Level: .NET Standard 2.0
Also I added a "link.xml" file for preserving my AWS .dlls, and "internet client" anabled in both "player settings" and "appxmanifest"
thank you in advance.
As a workaround for this situation, I set my credentials in the Environment variables. As this post suggest From where and in what order does the AWS .NET SDK load credentials?, the Environment variables is one option to get the aws credentials without hard coding them.
You can lear How to configure the Environment Variables here from the Amazon docs.
This doesn't explain why "TryGetAWSCredentials" from the default location doesn't work on UWP but allow me to continue with my test.
Finally my code for, e.g. list my buckets with this aproach:
public async void RegionCredentials()
{
Amazon.RegionEndpoint region = Amazon.RegionEndpoint.GetBySystemName("us-east-1");
using (var client3 = new AmazonS3Client(region))
{
var response = await client3.ListBucketsAsync();
Debug.Log("Region OK");
Debug.Log("Region - Number of buckets: " + response.Buckets.Count);
foreach (S3Bucket bucket in response.Buckets)
{
Debug.Log("Region - You own Bucket with name: " + bucket.BucketName);
}
}
}

Get Azure WebJobs connection strings from KeyVault before host is built

I am following the directions at https://learn.microsoft.com/en-us/azure/app-service/app-service-key-vault-references
Essentially, I am attempting to protect the storage connection string used for AzureWebJobsDashboard and AzureWebJobsStorage behind an Azure Key vault secret. I cannot use my injected KeyVault service to fetch it because my service container has not been built yet. So I found (through the link above) I could express this intent using a "#Microsoft.KeyVault()" expression in configuration. Here is an example where I moved the configuration to inline code to keep it terse:
.ConfigureHostConfiguration(configurationBuilder =>
{
configurationBuilder
.AddConfiguration(configuration)
.AddInMemoryCollection(new Dictionary<string, string>
{
["ConnectionStrings:AzureWebJobsDashboard"] = "#Microsoft.KeyVault(SecretUri=https://host.vault.azure.net/secrets/secret-name/ec545689445a40b199c0e0a956f16fca)",
["ConnectionStrings:AzureWebJobsStorage"] = "#Microsoft.KeyVault(SecretUri=https://host.vault.azure.net/secrets/secret-name/ec545689445a40b199c0e0a956f16fca)",
});
})
If I run this, I get:
FormatException: No valid combination of account information found.
If I change the configuration values from the special annotation to the copied secret value from Key Vault (the blue copy button under the 'Show Secret Value' button), everything just works. This confirms to me the connection string I use is correct.
Also, I manually used KeyVaultClient w/AzureServiceTokenProvider to verify the process should work when running locally in Visual Studio, even before the host has been built. I am able to get the secret just fine. This tells me I have sufficient privileges to get the secret.
So now I am left wondering if this is even supported. There are pages which imply this is possible however, such as https://medium.com/statuscode/getting-key-vault-secrets-in-azure-functions-37620fd20a0b. At least for Azure Functions. I am using Azure Web Jobs which gets deployed as a console application with an ASP.NET Core service, and I cannot find an example with that configuration.
Can anybody clarify if what I am doing is supported? And if not, what is the advisable process for getting connection strings stored in Azure Key Vault before the Azure Web Jobs host has been built?
Thanks
I have gone through a lot of online resources and everything seems to indicate that the special decorated #Microsoft.KeyVault setting only works when the value lives in AppSettings on the Azure Portal, not in local configuration. Somebody please let me know if that is an incorrect assessment.
So to solve this problem, I came up with a solution which in all honesty, feels a little hacky because I am depending on the fact that the connection string is not read/cached from local configuration until the host is ran (not during build). Basically, the idea is to build a configuration provider for which I can set a value after the host has been built. For example:
public class DelayedConfigurationSource : IConfigurationSource
{
private IConfigurationProvider Provider { get; } = new DelayedConfigurationProvider();
public IConfigurationProvider Build(IConfigurationBuilder builder) => Provider;
public void Set(string key, string value) => Provider.Set(key, value);
private class DelayedConfigurationProvider : ConfigurationProvider
{
public override void Set(string key, string value)
{
base.Set(key, value);
OnReload();
}
}
}
A reference to this type gets added during host builder construction:
var delayedConfigurationSource = new DelayedConfigurationSource();
var hostBuilder = new HostBuilder()
.ConfigureHostConfiguration(configurationBuilder =>
{
configurationBuilder
.AddConfiguration(configuration)
.Add(delayedConfigurationSource);
})
...
And just make sure to set the configuration before running the host:
var host = hostBuilder.Build();
using (host)
{
var secretProvider = host.Services.GetRequiredService<ISecretProvider>();
var secret = await secretProvider.YourCodeToGetSecretAsync().ConfigureAwait(false);
delayedConfigurationSource.Set("ConnectionStrings:AzureWebJobsStorage", secret.Value);
await host.RunAsync().ConfigureAwait(false);
}
If there is a more intuitive way to accomplish this, please let me know. If not, the connection string design is plain silly.

Can't start a WCF Service installed as a Windows Service

I created a service that basically exposes some methods to update a sql server database.
I tested the service as a normal WCF Service (not a Windows Service) and it worked fine (which tells me that the ServiceModel definition in App.config is ok)
Then I turned it into a Windows Service, I installed it using InstallUtil, and it installed fine. But when trying to start it in the Services console, I get this message "The service WCFProductsWindowsService service on Local Computer started and then stopped. Some services stop automatically if they are not in use by other services or programs"
The solution that exposes the service is composed of two projects,
a class library that defines the service, the contract, and an ADO
NET Entity Data Model to the database,
and a console application that exposes the service
The class that exposes the serice is:
public class ProductsWindowsService : ServiceBase {
public ServiceHost serviceHost = null;
public ProductsWindowsService() {
ServiceName = "WCFProductsWindowsService";
}
public static void Main() {
ServiceBase.Run(new ProductsWindowsService());
}
protected override void OnStart(string[] args) {
if (serviceHost != null) {
serviceHost.Close();
}
serviceHost = new ServiceHost(typeof(ProductsServiceImpl));
serviceHost.Open();
}
protected override void OnStop() {
if (serviceHost != null) {
serviceHost.Close();
serviceHost = null;
}
}
}
I uploaded the simple project in SkyDrive
What could I be doing wrong?
Does not allow me to add a comment.
This error "The service WCFProductsWindowsService service on Local Computer started and then stopped. Some services stop automatically if they are not in use by other services or programs" indicates an exception is thrown.
I would check the event viewer to see the exception logged.
Does ProductsServiceImpl exists? I can't find it in your image or in your solution.