How to change values in appSettings.json file based on environment - asp.net-core

I am building API in .net core project and have to store some key value pairs in appSettings.json file for jwt token. For example i need to store valid issuer and valid audience. For development i have my appSettings.json file as below:
`{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"jwt": {
"JwtIssuer": "https://localhost:44332/",
"JwtAudience": "https://localhost:44332/",
"JwtSecretKey": "my super secure key"
}
"AllowedHosts": "*"
}`
For development environment this is fine but when i will have to deploy to say azure, do i need to change these URLs manually here in appSettings.json file or is there any other efficient way to manage these URLs that automatically gets updated based on environment.

The default of ConfigurationBuilder is looking for appsettings.<EnvironmentName>.json file, so based on the environment that you are working with
when you are in IIS Express you are in Development and when you deploy your application your environment is Production. This is why you need appsettings.Production.json

Related

Serilog & Elastic Search aspnetcore with docker not working

I have installed both elastic search and kibana 8.6.1
I am using Serilog.AspnetCore 6.1, Serilog.Enrichers.Environment 2.2, and Serilog.Sinks.ElasticSearch 9.0
I have configured my application with Serilog to log data to elastic search
configuration
.Enrich.FromLogContext()
.Enrich.WithMachineName()
.WriteTo.Debug()
.WriteTo.Console()
.WriteTo.Elasticsearch(new ElasticsearchSinkOptions(new Uri(elasticConfigurationSettings.Uri))
{
IndexFormat = $"applogs-{context.HostingEnvironment.ApplicationName?.ToLower().Replace(".", "-")}-{context.HostingEnvironment.EnvironmentName?.ToLower().Replace(".", "-")}-{DateTime.UtcNow:yyyy-MM}",
TypeName = null,
AutoRegisterTemplate = true
})
.Enrich.WithProperty("Environment", context.HostingEnvironment.EnvironmentName ?? "Environment Missing")
.Enrich.WithProperty("Application", context.HostingEnvironment.ApplicationName ?? "Application Unknown")
.ReadFrom.Configuration(context.Configuration);
SelfLog.Enable(Console.Error);
Below is my Serilog settings in the appsettings.json file
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Information",
"System": "Warning"
}
}
},
"ElasticConfiguration": {
"Uri": "http://localhost:9200"
}
I have an httphandler that has logging statements
logger.LogInformation("Sending request to {Url}", request.RequestUri);
logger.LogInformation("Received a success response from {Url}", response.RequestMessage.RequestUri);
but I never see any data in kibana. Any help would be appreciated.
you have to networking your containers with each other
you can using them by adding Container Orchestrator and making you're project multi-container app
see more information about it in this link
I was able to get things working.
I changed
"ElasticConfiguration": {
"Uri": "http://localhost:9200"
}
to
"ElasticConfiguration": {
"Uri": "http://elasticsearch:9200"
}
since this is the name of the container w/in docker.
I updated my docker-compose file to update a few settings within elasticsearch 8.6.1
- ES_JAVA_OPTS=-Xms512m -Xmx512m
- xpack.security.enabled=false
- discovery.type=single-node
- ELASTIC_CLIENT_APIVERSIONING=1
I updated my Kibana settings as well
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
In addition, I came across this SO post discussing Serilog and ES8, which helped me update my common logging library
I am now able to launch Kibana and see my logs.

ASP.NET Core (3.1) re-using IIS certificate in self-hosted (Kestrel) application

I have an ASP.NET Core (3.1) application which is self-hosted and running as a service. I would like to expose an HTTPS endpoint for it. On the same machine there is an IIS instaled with already configured https together with certificate:
The certificate seems to stored in local computer certificate store:
I can also list it via the powershell:
> get-childitem cert:\LocalMachine\My\ | format-table NotAfter, Subject
NotAfter Subject
-------- -------
27.10.2023 07:38:45 <irrelevant>
08.03.2022 09:52:44 CN=a7642e58-2cdf-4e9b-a277-60fad84d7c64, DC=3336d6b0-b132-47ee-a49b-3ab470a5336e
23.02.2022 21:51:53 CN=a7642e58-2cdf-4e9b-a277-60fad84d7c64, DC=3336d6b0-b132-47ee-a49b-3ab470a5336e
27.10.2031 06:48:06 CN=a7642e58-2cdf-4e9b-a277-60fad84d7c64
26.10.2024 10:41:03 E=****.com, CN=****, OU=IT, O=****, L=****, S=***, C=**
I changed the appsettings.json to use the certificate from the store:
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Warning"
}
},
"AllowedHosts": "*",
"Kestrel": {
"EndPoints": {
"Http": {
"Url": "http://*:5000"
},
"HttpsDefaultCert": {
"Url": "https://*:5001"
}
},
"Certificates": {
"Default": {
"Subject": "E=****.com, CN=****, OU=IT, O=****, L=****, S=***, C=**",
"Store": "My",
"Location": "LocalMachine",
"AllowInvalid": "true"
}
}
}
}
However this does not seem to work. I always get the following error:
System.InvalidOperationException: The requested certificate E=****.com, CN=****, OU=IT, O=****, L=****, S=***, C=** could not be found in LocalMachine/My with AllowInvalid setting: True
I do not know what could be the problem. The only thing that I think might be problematic is that the certificate subject actually contains newlines in the subject:
I do not know if this is the problem and I do not know how to enter it in the appsettings.json as multiline values can not be entered.
I've managed to track down the issue. Kestrel uses FindBySubjectName when searching for certificate.
FindBySubjectName does a sub-string search and will not match the full Subject of the certificate. If your certificate subject is something like 'CN=my-certificate' then searching for 'CN=my-certificate' will not find anything. Searching only for 'my-certificate' will work.
Additional note: In addition to specifying the correct search expression, make sure that the account under which you are running the application has sufficient permissions to read the certificate from certificate store. Certificates do have ACL so you do not have to run your app as an administrator.
I refer to the documentation for configuring the SSL certificates for Asp.NetCore app running on Kestrel.
I noticed some URL and ports settings also get stored in Properties/LaunchSettings.json file.
See Here: Configure endpoints for the ASP.NET Core Kestrel web server
Further, I noticed that you have put the Certificate under Defaults. I found other ways to configure the certificate. You could try to test them.
In the following appsettings.json example:
Set AllowInvalid to true to permit the use of invalid certificates (for example, self-signed certificates).
Any HTTPS endpoint that doesn't specify a certificate (HttpsDefaultCert in the example that follows) falls back to the cert defined under Certificates:Default or the development certificate.
{
"Kestrel": {
"Endpoints": {
"Http": {
"Url": "http://localhost:5000"
},
"HttpsInlineCertFile": {
"Url": "https://localhost:5001",
"Certificate": {
"Path": "<path to .pfx file>",
"Password": "$CREDENTIAL_PLACEHOLDER$"
}
},
"HttpsInlineCertAndKeyFile": {
"Url": "https://localhost:5002",
"Certificate": {
"Path": "<path to .pem/.crt file>",
"KeyPath": "<path to .key file>",
"Password": "$CREDENTIAL_PLACEHOLDER$"
}
},
"HttpsInlineCertStore": {
"Url": "https://localhost:5003",
"Certificate": {
"Subject": "<subject; required>",
"Store": "<certificate store; required>",
"Location": "<location; defaults to CurrentUser>",
"AllowInvalid": "<true or false; defaults to false>"
}
},
"HttpsDefaultCert": {
"Url": "https://localhost:5004"
}
},
"Certificates": {
"Default": {
"Path": "<path to .pfx file>",
"Password": "$CREDENTIAL_PLACEHOLDER$"
}
}
}
}
Schema notes:
Endpoints names are case-insensitive. For example, HTTPS and Https are equivalent.
The Url parameter is required for each endpoint. The format for this parameter is the same as the top-level Urls configuration parameter except that it's limited to a single value.
These endpoints replace those defined in the top-level Urls configuration rather than adding to them. Endpoints defined in code via Listen are cumulative with the endpoints defined in the configuration section.
The Certificate section is optional. If the Certificate section isn't specified, the defaults defined in Certificates:Default are used. If no defaults are available, the development certificate is used. If there are no defaults and the development certificate isn't present, the server throws an exception and fails to start.
The Certificate section supports multiple certificate sources.
Any number of endpoints may be defined in Configuration as long as they don't cause port conflicts.
Reference: Replace the default certificate from configuration

Asp.net core not using the correct certificate

I am trying to understand how certificates work with asp.net 5.0. I have created a self signed certificate using PKI Client and installed it to the certificate store trusted root.
I have updated my Kestrel config as below
"Kestrel": {
"EndPoints": {
"Http": {
"Url": "http://localhost:5000"
},
"HttpsInlineCertStore": {
"Url": "https://*:5001",
"Certificate": {
"Subject": "pal.com",
"Store": "My",
"Location": "LocalMachine",
"AllowInvalid": "false" // Set to true to allow invalid certificates (e.g. self-signed)
}
}
}
}
When I run my server and browse to path https://pal.com:5001/ it complains about the certificate. It looks like the browser is using the asp.net core development certificate
I am new to asp.net and ssl. Am I missing anything here?
ok, I got this working. That was me doing things incorrectly, I added Kestrel config in launchSettings file rather than appsettings. It worked after moving the config to appsettings.json file

How to make the MS Identity SPA example work for organization and personal accounts

I am following this link to make my own project.
My project has
Reactjs
Asp.Net Core Web Api
to access user's emails from Hotmail.The Reactjs app and WebApi live on different servers.
The example is almost what I need, but it only accepts accounts within same organization, not accepts Personal accounts.
I thought I only need to change the Tenant ID from a specific ID to "common" in related configurations and it will work.
I also registered the Supported account types on Azure for both Web Api and Reactjs to use the
AnyOrg + Personal Account
here is the config for Angular
{
"auth": {
"clientId": "28xxx12",
"authority": "https://login.microsoftonline.com/common",
"validateAuthority": true,
"redirectUri": "http://localhost:4200",
"postLogoutRedirectUri": "https://localhost:44321/signout-oidc",
"navigateToLoginRequestUrl": true
},
"cache": {
"cacheLocation": "localStorage"
},
"scopes": {
"loginRequest": [ "openid", "profile", "Mail.Read", "offline_access", "user.read"]
},
"resources": {
"todoListApi": {
"resourceUri": "https://localhost:44351/api/todolist/",
"resourceScope": "https://papayee008.onmicrosoft.com/papayee008/access_as_user"
}
}
}
here is the config for Web Api:
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"Domain": "papayee008.onmicrosoft.com",
"TenantId": "common",
"ClientId": "28xxx12"
},
"https_port": 44351,
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
But when I was trying to log in with my personal account, it throws me this error:
The simplest solution would be the use the same app/client id for both the SPA and the API. That is, instead of making separate app registrations for each component (as is suggested in the readme), simply make one app registration where you combine the steps for Register the service app (TodoListAPI) and Register the client app (TodoListSPA) in the readme of the sample repository.
EDIT: judging by the last screenshot, it might also be the case that your changes on "supported account types" on the AAD portal haven't taken effect yet. There's usually a few seconds delay, and if you tried to login with a personal account during that time, the issue in the screenshot would be expected.

ASP.NET Core publishing to Azure (Staging)

VS 2019
ASP.NET Core 3.1
I have developed a Web App locally and now I am ready to deploy to an Azure Staging environment.
My Web App was originally .Net (not Core) and I had not problems deploying it.
How to I tell the deployment process to use the "Staging" environment?
My launchSettings.json contains the following:
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:59000",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
I have a appSettings.Staging.json pointing to the Staging database...
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Warning"
}
},
"ConnectionStrings": {
"DbConnection": "Data Source=myapp.database.windows.net;Initial Catalog=MyAppCoreStaging;user id=myappstepadmin;password=mypassword;MultipleActiveResultSets=True"
}
}
But I am not sure how to tell it to use Staging when I deploy.
At the moment when I deploy, the browser starts up on the page and I get:
HTTP Error 500.30 - ANCM In-Process Start Failure
Common solutions to this issue:
The application failed to start
The application started but then stopped
The application started but threw an exception during startup
Troubleshooting steps:
Check the system event log for error messages
Enable logging the application process' stdout messages
Attach a debugger to the application process and inspect
For more information visit: https://go.microsoft.com/fwlink/?LinkID=2028265
Is there something I need to configure on Azure to use the Staging?
Since you are deploying to Azure and didn't specify that you are using a CI/CD Pipeline as your method of publishing, I assume that you are using the publishing profiles provided from Azure portal directly in Visual Studio.
In the Publish dialog, click on Edit -> settings -> Configuration and select Stage
In your Program.cs, your CreateWebHostBuilder (assuming you are using ASP.NET Core 3.0+; it's also possible for 2.2 but it's not IWebHostBuilder), you can specify that the appsettings file should be dependent on your solution configuration:
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseEnvironment(Environment);
where Environment can be a property with preprocessor directives:
public static string Environment
{
get
{
string environmentName;
#if DEBUG
environmentName = "development";
#elif STAGE
environmentName = "staging";
#elif RELEASE
environmentName = "production";
#endif
return environmentName;
}
}
If you use a build pipeline, you should look at this.
steps:
- task: DotNetCoreCLI#2
inputs:
command: 'publish'
publishWebProjects: true
arguments: '-o $(build.artifactstagingdirectory) /p:EnvironmentName=Staging'