Today, I have a production environment hosted on IIS and using MsDeploy to be deployed. So the database connection string is set in appsetting.Production.json.
But i have to make a second production environment. So i will create a new publish profile for this environment but how can i set the connection string for this new environment ?
Thanks in advance,
Are they being deployed to separate machines? You can override the settings in appsettings.json by using Environment settings. You don't need to change your code to do this as ASP.NET Core does all the work for you.
In short, settings are read in the following order, with the later ones overriding values from the earlier ones:
Files (appsettings.json, appsettings.{Environment}.json, where
{Environment} is the app's current hosting environment)
Azure Key Vault
User secrets (Secret Manager) (in the Development environment only)
Environment variables
Command-line arguments
So, on your second production machine you can add an Environment variable to override the setting in appsettings.Production.json.
If you are using SQL Server then you can set the SQLCONNSTR_ environment variable to override your setting, add your connection name at the end e.g. SQLCONNSTR_DefaultConnection.
If you are going to use environment variables to override the settings on one machine I suggest you do it for all production machines for consistency.
Take a look at this section in the Configuration in ASP.NET Core for the full configuration sequence.
Information regarding the specific ConnectionString settings are on the same page as above.
Related
I'm playing around with a small ASP.NET Core 1.1 app which I have published. Now I'm following the documentation with regards to using appsettings*.json and environment variables. So I have the following:
appsettings.json
appsettings.Development.json
Each appsettings*.json file has an appropriate "ConnectionStrings:" section:
"ConnectionStrings": {
"IdeasDatabase": "Server=tcp:adb.database.windows.net,1433;Initial Catalog=db;Persist Security Info=False;User ID=a_user;Password=apwd;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"
}
So, when I published to begin with to Azure, I used a default connection string in the Publish settings (which was wrong I know), now this is showing in Azure remote settings for the my app:
The above connection string was populated on my first publish in this screen (Publish Wizard):
Now my Production app seems to be using this setting in the above image and not taking the setting from my appsettings.json connection string section.
My appsetting.json file is present on Azure App Service:
I know I can override that Database connection string in the Publish wizard tot the correct string, but shouldn't Azure take the Connection String first from my appsettings.json file which is different from wherever it is storing it on Azure.
now this is showing in Azure remote settings for the my app:
Azure remote settings stored as environment variables. It has a higher priority than configuration in appsettings.json. If you want to use the settings which configured in appsettings.json at runtime on Azure, you could delete the Azure remote settings from Azure portal or Visual Studio. After that, Azure Web App will use the setting in appsettings.json.
Use the environment variables or another secure mechanism. Storing the production connection string in a file is insecure.
I am running tomcat 8 on Windows Server 2012.
I have a web app that needs an user environment variable to be set in order to run.
I can start tomcat and retrieve the variable successfully like this:
set JAVA_HOME=C:\Program Files\Java\jdk1.8.0_65
set CATALINA_HOME=C:\TOOLS\apache-tomcat-8.0.30
set CATALINA_BASE=C:\Users\ULUser\tomcat\myapp
set MY_VAR=%CATALINA_BASE%
set PATH=%CATALINA_ROOT%\bin;%PATH%
set CATALINA_OPTS="-Djava.security.properties=%CATALINA_BASE%\conf\java.security.properties"
%CATALINA_HOME%\bin\catalina.bat run
But when I run as a windows service I cannot retrieve the MY_VAR variable using System.getenv("MY_VAR");
Googling has not helped because all the pages show how to set the Java and Tomcat variables, but not how to set user variables.
I cannot set it for the entire machine because I have several instances of tomcat and each one needs a different environment variable.
I would prefer a method that involves setting the variable in the tomcat configuration rather that with windows configuration.
My alternative is to use context.xml file in tomcat and retrieve the value with logic that retrieves context settings.
From an admin command prompt do the following command:
tomcat8 //US//YourServiceName ++Environment varname=value
You can set more than one variable by separating them with a semicolon (;) or a hash (#). The documentation is quite clear, but it's just difficult to believe anything's happened, because there's no visual indication anywhere, meaning if you run:
tomcat8w //ES//YourServiceName
to get the GUI config tool you will not see the environment variable anywhere, but if you run the service it will pick it up. It's like hidden magic. Don't know why they haven't included it somewhere in the config panel.
BLUF
Our application is attempting to write a file to a UNC folder using an ASP.NET web service running under .NET 4.5, IIS 7.5, and Windows Server 2008 R2. However, any attempt to write the file to the desired location results in an access denied exception.
The task seems simple however me and my team have been troubleshooting this for a while now and we are stumped as to what may be causing the error. Below are the details of our setup and what we have tried and found so far. Names have been changed to protect the innocent.
Environment Setup
The web server, mywebserver, has a website named My.Site.Com with a corresponding application pool named My.Site.Com. The application pool is configured as shown below.
.NET Framework Version : v4.0
Enable 32-bit Applications : False
Managed Pipeline Mode : Integrated
Name : My.Site.Com
Identity : ApplicationPoolIdentity
Load User Profile : False
The UNC path we are attempting to write to is \myotherserver\mydirectories\output where mydirectories is the actual share. On this share a domain group named mygroup-www has been granted full permissions to the share and all subfolders. The machine account (i.e., mywebserver) is a member of this mygroup-www group.
NOTE: For the moment, this UNC path actually lives on the same
machine, mywebserver. However, this will eventually be moved to a machine other
than mywebserver in our test environment and in the production environment
when that it is ready. Currently, I only have the one test environment to troubleshoot with.
The error can be replicated by executing the following code.
[WebMethod]
[ScriptMethod(UseHttpGet = false, ResponseFormat = ResponseFormat.Json)]
public string ExportReport(int reportId)
{
try
{
string output = ConfigHelper.OutputPath + "test.html"; // UNC path
string url = ConfigHelper.VirtualPath + "test.html";
string[] lines = { "Hello", "World!" };
File.WriteAllLines(output, lines); // Access Denied!
return url;
}
catch (System.Exception ex)
{
Logger.ErrorException("Error exporting report", ex);
throw;
}
}
Troubleshooting
Failed Attempts
We tried various combinations of group/user permissions on the folders (listed below). When running these tests we also ran Process Monitor. For each configuration we saw the same result. The w3wp.exe process attempted to create the file in the desired location but reported a result of ACCESS DENIED. The user of each configuration was IIS APPPOOL\My.Site.Com as expected.
Granting mydomain\mymachine$ full permissions to \myotherserver\mydirectories
Granting mydomain\mymachine$ full permissions to \myotherserver\mydirectories\output
NOTE: I have also tried modifying the code so that it would read a
simple file from \myotherserver\mydirectories\output. When
attempting to read the file, the process fails with an ACCESS DENIED
message as it did when writing the file.
Successful Attempts
We also tried several configurations that worked.
Grant the local IIS APPPOOL\My.Site.Com permissions
The first configuration to work was to grant the IIS APPPOOL\My.Site.Com full permissions to \myotherserver\mydirectories The file was successfully written however the process's user was quite unexpectedly a domain account that was set up for a web application on the same machine in another website. This remains very confusing but worked as the 'other' account also has write permissions to the share.
This won't work in production as we cannot use local accounts to grant access to networked resources but is an interesting data point nonetheless.
Change the App Pool Identity to Domain User
The second configuration that worked was to change the My.Site.Com application pool's identify to domain account that had full permissions to \myotherserver\mydirectories. This was a 'vanilla' domain account that was manually created by us. We did not capture what the user of the process was but that may be another useful data point.
This option may be possible, however it breaks away from best practices with IIS 7.5 and may not be allowed in our production environment due to fairly stringent IT policies.
Run the Site On My Development Machine
The third test was to run the site locally on my development machine, mydevmachine. My local IIS configuration is identical to mywebserver with the exception that I am running Windows 7 instead of Windows Server 2008. I granted full permissions for mydomain\mydevmachine to the \myotherserver\mydirectories and ran the application. The file was successfully written. According to Process Monitor the user for the process was correctly set to IIS APPPOOL\My.Site.Com.
Conclusion
We would like to enable write access as designed using the machine account of mywebserver. We have read ApplicationPoolIdentity user cannot modify files in shared folder in Windows Server 2008 and Permissions for Shared Folder for IIS 7 Application Pool Identity Across Domain and Application Pool Identities.
According to this information we should be able use the machine account to grant read and write access to networked resources such as the UNC path. In fact, I can do this in the desired manner when running the web site from my development machine.
There are a couple thoughts that come to mind. Perhaps there is something wrong with the machine account of the test web server. Or perhaps that 'other' software is interfering with the process somehow.
Any thoughts as to what may be causing this issue? What else should we do to troubleshoot?
Reboot your 'mywebserver'.
Marvel at the now mysteriously functional ApplicationPoolIdentity.
Install MS HotFix KB2545850 and learn the details about this bug in KB2672809 which also shows the steps to reproduce and demonstrate this apparently random problem. Direct download link here.
Speculate why Microsoft has not managed to release a normal windows update for this in the 3 years since that hotfix was published. While people still continue running into it and pulling their hair out because of this obscure problem.
Learn about the other folks who have shared and enjoyed this gift from MS that still continues to keep on giving:
IIS application using application pool identity loses primary token?
DirectoryServicesCOMException 80072020 From IIS 7.5 Site Running Under ApplicationPoolIdentity
ApplicationPoolIdentity cannot access network resources
ApplicationPoolIdentity IIS 7.5 to SQL Server 2008 R2 not working
Windows Authentication Failed when using application pool identity
IIS 7.5 stops using machine account to connect to network resource when using AppPoolIdentity
Your Windows 7 dev machine probably worked fine because it reboots more often than the server. Congrats on your very well written and thorough bug report. I rarely see that here.
I had similar problem accessing a network share using AppPoolIdentity in an ASP.NET application (access denied).
Using NetworkService account or other domain account worked but these were not the best solution.
I performed almost all the tests you did but finally found something that worked.
I figured out that the Network Service account was not used when accessing the shares, just like you did (i expected domain\machine$ account)
This worked for us:
On your IIS web site, go to Authentication and change the Anonymous Authentication item to "Application Pool Identity". It's by default set to "IUSR". This solved our problem.
Also maybe activating ASP.NET impersonation (still in Authentication menu) may help.
Thibault
I have faced same issue, I resolved by creating one domain account for each environemt (QA, STAGE, PRODUCTION). In Application pool identity I have set custom account and I used domain user for respective account. Now It gives me the ability to write and read the files from UNC Path.
We are in the process of completing SSIS packages. However as we move towards the deployment phase surprisingly we realized that deployment of SSIS package is not really straight forward as terms of security.
we need to run a SSIS package using either batch file or .NET program in production server. The caller (batch or .NET) should call the SSIS package by supplying parameters (such as source file, destination database, userid, password etc) and also read return code (Success/Error) from SSIS. The user id and password should not be in clear text format visible to anyone. We did some research and found that deployment can be done using many options such as XML config, SQL server Configuration, environment variables, Registry etc but did not mentioned any about password encryption. How can we achieve security and ensure flexibility deploying same package in multiple environment (DEV,UAT,PROD) and simple changing the environment specific variables at the time of deployment.
I am looking for somthing where MVC/Entity framework the connection strings are automatically encypted when the application is run first time using following code.
Configuration config = WebConfigurationManager.OpenWebConfiguration("~");
ConfigurationSection section = config.GetSection("connectionStrings");
if (!section.SectionInformation.IsProtected)
{
section.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
config.Save();
}
Your question confuses things.
By default, SSIS is going to encrypt anything that could be of a sensitive nature by using the author's Active Directory, AD, account. SSIS Packages Using Package Protection Level This Package Protection Level is EncryptSensitiveWithUserKey If you're using a SQL Server user and password in your connection string, the at-rest value in your SSIS package is going to be encrypted. Don't believe, me, open the file and find the Connection Manager's ConnectionString property.
Deployment is not done through XML, SQL Server, Registry etc. Those refer to methods of creating and storing configuration values that an SSIS package may access during run-time. Configuration has no concept of decrypting values. That isn't to say you can't encrypt values and have them decrypted for the caller, just that there is not built in mechanism for signifying "decrypt using this key."
An approach we are using is to use SQL Server for the holding of encrypted data. We create roles authorized to use the keys and then have computed columns that automatically decrypt the data based on role membership. A person not in that role querying the column will only ever get NULL back as the decrypted value. It's working well for use. EncryptionPOC
Deployment is done through
file copy
dtutil.exe
dtsinstall.exe
.NET api
I have been scouring the internet for a clear answer to this question and I haven't been able to find one.
We currently have a SQL configuration enabled across packages which stores everything in a database, (dev or prod). It is a tricky process to execute packages, figuring out which configuration the packages are mapped to, and having to change them during testing. My hope is that we can use an environment variable to always use a specific connection string to the specific sql server configuration we want to use based on the machine.
I have seen ways to set up variables with the connection string hard coded as an environment variable with an additional SQL server configuration after to manage this. I have also seen ways to manipulate the connection string using XML and calling that from a variable, or from the package itself.
Both of these solutions work and very well may be viable solutions.
My question that I'm really trying to answer is; Is it possible to develop the entire SQL Server configuration connection through the environment variable? As in combining the connection string with the configuration string so that the one environment variable connects straight to the package configuration? Has anyone tried this? Does it make sense as a solution to the problem?
Yes, we have done this and it works fine. Each package has two configurations: the first is an environment variable and the second is a SQL Server table. The environment variable is the connection string for a database containing a table with all the configurations and it is applied to a connection manager. The SQL Server configuration uses that connection manager to connect to the configuration database and retrieve the individual settings.
Because configurations are applied in order, the connection string for the connection manager is set before the SQL Server configuration tries to use it. In summary:
Create your package
Add a connection manager called "Configuration Database" or whatever
Add a SQL Server configuration to the package, use the "Configuration Database" as the Connection, and choose the settings to be stored in the table
Create an environment variable such as SSIS_PKG_CONF with the connection string to be used for the "Configuration Database" connection manager
Add an environment variable configuration to the package, use the SSIS_PKG_CONF variable, and assign it to the connection string for the "Configuration Database" connection manager
Now when you run the package, the configuration proceeds as follows:
The package processes the environment variable configuration
It assigns the value of the environment variable to the "Configuration Database" connection manager's connection string
The package processes the SQL Server configuration
It uses the "Configuration Database" connection manager to retrieve individual settings from a database table
This has worked well for us because we can change the connection string to point at a different source database for the configuration, without changing anything inside the package or the launcher (i.e. the SQL Agent job or script that runs the packages). There are other ways to do it and some people feel strongly that .dtsConfig files are the better option, but we found it easier to manage environment variables than config files
But in the end managing package configurations is a preference and a lot depends on what is easier in your environment with the tools and practices you already have.