I'm wondering what techniques you use to store the database credentials for your application. I'm specifically concerned with java webapps, but I don't think there's any need to limit the questions to that.
things to consider:
Do you use property files,xml configs, other?
Is it bundled into your application(ie in a jar file) or stored seperately on the file system somewhere?
Is the password encrypted? If so, what encryption scheme do you use?
Since you're leaving the question open to platform, I'll add that database credentials for .NET apps are stored in the web.config file. From version 2.0 and above, there is a specific ConnectionStrings section that allows for easier programmatic access to the connection string.
In addition to having IIS automatically block direct requests to the web.config file by default, you can also use an IIS command to encrypt the ConnectionString section of the web.config file. This encryption is machine specific, adding to its strengths, and the .NET runtime will also decrypt the connection string on the fly when you access it, so there is no need for additional coding in your application to work with it.
With Java, database connection pools should be passed into webapps by the container. This is in the standard declarable in WEB-INF/web.xml as resources. The same applies to mail sessions and other external resources that may vary from installation to installation. Look up JNDI for more information on this)
The nice part with this is that the application doesn't care about how to actually connect to anything outside. It will not see any passwords, because the container itself will use them.
In tomcat this is configured either from context files (e.g.) in conf/Catalina/localhost/ , conf/server.xml or - preferably only for dev environments, from the webapps META-INF/context.xml. Other environments have their own configuration location or application.
The encryption of passwords actually depends on the container. Tomcat stores them in plaintext, but the application itself won't see it. I don't know about the mechanics in other environments.
On the Microsoft stack, things can be very nice.
You create a network user account in Active Directory with almost no permissions. You configure IIS to run your webapp as that user. You grant that user read access to the web folders and files on the disk. You configure SQL Server to grant that user read/write permissions on the tables you want. And in the connection string, you instruct the db client to connect as the user account which the webapp is currently being run as.
There is only one actual user account, although it is visible in multiple places. This user account has extremely limited permissions. There is no storing passwords anywhere, even if encrypted. There is no configuration that has to be done in code for this to work (it's all in setting up the permissions).
Depends on the app server.
I usually use JNDI lookups for the data source, so credentials are stored on the app server that handles the connection pool. No need to put anything other than the JNDI name in configuration that way.
Yes, the password is encrypted on WebLogic.
On Tomcat things can be dicey. Connection info is in META-INF/context.xml, which means plain text for the password. I only do that for development, never in production.
In Django, the credentials are in your settings.py configuration file. Since this is not generally kept in your /var/www/ directory tree, it's very safe.
Also, a single Django application may be used (and reused) for many web sites or web servers on the same host, each with it's own distinct settings. So the settings.py configuration is not bundled with the app, but is part of a single deployment of the app.
For asp.net:
I store global parameters such as the connection string and repository paths in the Registry and then a reference to the registry entry in the web.config.
The main reason being that I often find I have to write a stand alone executable to run background tasks and other automated features that require access to the same parameters. Therefore keeping everything that is truly global in one easily accessible place makes for an easier life.
As stated before, no platform specified, and using some ideas from earlier answers:
I am considering a containerised application. You could store the password for the database in a file in the container. The first step of your application would be to establish the database connection, even before listening on web requests. With a successful db connection the file with the credentials is deleted and the variables containing the these, are removed. So when you start serving requests, the only thing that remains, is an open database handle to use from this moment on. If for any reason the database connection is lost, you simply quit and wait to restart the container, the credentials file will be there again.
Which of these are good places to keep your web app’s database credentials?
In a separate file in your source code
In a separate file on your web server host
In your database
None. The database credentials should never be stored
Related
I have a local GeoServer running on tomcat which using a PostGIS store to get layers from the PostgreSQL database. There is a production server that runs the same version of my local GeoServer and PostgreSQL database. In order to apply changes in layers and layer groups of my local GeoServer, I copied and replaced the data directory to production GeoServer. After restarting the tomcat on the production server, Geoserver unable to load Layers and Layer Preview pages on the web interface. Trying to change the host address of the store or creating a new one, it gives me this error:
Error creating data store with the provided parameters: Failed to upgrade lock from read to write state, please re-try the configuration operation
You don't say which OS you are using or how you made the copy, but the most likely error is a permissions or ownership one.
Make sure that the user which is running GeoServer has permission to read, write and execute on the data dir. On linux machines I've seen issues with uid and gid differences between machines depending on how the copy id carried out. On Windows I've seen issues just because windows and the virus scanner feel like it.
When using the community function jdbcconfig, the same issues.
It seems that an error occurs because file locking of catalog is performed.
Since the data directory is not used by using JDBCconfig, the file lock has been improved by setting it to Lock Disable.
https://docs.geoserver.org/stable/en/user/configuration/globalsettings.html#file-locking
I am trying to configure CI using Visual Studio Online. I've configured GIT and made the build. It is automatically building with every push I make. I want to automatically publish my changes to my database (stored on my server). I've created publish config for that, made the connection string there and put the password in that config. It is working great however is there any way to store the password (other than plain text)?
It is a problem I have tried to fix myself (how do I have an open source project and still have builds with credentials in). The reality is that you can't store credentials in a public place and used by a public server without making them public.
You need to decide whether you trust VSO or not, if you do then you can give it your credentials and if you don't then you can't.
Normal things that you would do such as running the CI process under a service account or giving the account a certificate won't work for VSO because each build happens (seemingly from my testing) on a clean machine each time so you can't pre-configure security settings.
The best that you can really do is to only allow access to your database from known locations i.e. vso and whatever accesses the database rather than everywhere.
ed
I have a problem. My school's databases are only accessible locally. So when I work from home or without an internet connection, I need to switch out the connectionString in my web.config to reflect a local database.
Is there a way to have two seperate connectionstrings, where one is used if the other is unavailable? Also, can I automatically mirror the first one to my local DB if it's available?
I should mention; this is a Web Forms project using .NET 4.0
Common use case "to maintain separate db connections" is to have 1 web.config with multiple configuration folders in your service hosting project.
Basically, your web.config should have connectionStrings section to reference each configuration environment (Dev/Local/QA/Prod):
<connectionStrings configSource=".\Config\Dev\connectionStrings.config" />
I don't believe this is possible to do directly, options could include:
1) Have a flag set either in config or elsewhere to signify the environment you are working in
2) Have a custom method for retrieving the connection string, this could then potentially catch a failed db connection and try again with the other string (you could also save the appropriate string in session for connections after the first one)
I have SMO code which copies tables from one database to another. It runs fine in a desktop app. The same exact code put in a service, gives an error. The error is really obscure and doesn't hint about permissions.
I was wondering if the SMO objects need any kind of security to be used. Security context? Windows credentials.. etc? I am not talking about SQL Server security but security surrounding the use of the SMO methods.
You need full trust. You may have problems running this on certain hosted ASP.NET accounts, apps downloaded from the internet, or from shared drives, where CAS kicks in and gives the code something less than full trust and certain APIs won't be callable.
Are you using integrated security with your connection? If so, make sure the credentials that the service is running under have necessary access.
Make sure your service account (the account that your windows service is running as) has "Act as Part of Operating System" Policy.
So our web server apps need to connect to the database, and some other apps have startup scripts that execute at boot time.
What's the best way to store the name/password for these applications, in terms of
security, e.g. perhaps we don't want sysadmins to know the database password
maintainability, e.g. making the configuration easy to change when the password changes, etc.
both windows and linux solutions appreciated!
The best way to secure your password is to stop using one. Use a trusted connection:
How To: Connect to SQL Server Using Windows Authentication in ASP.NET 2.0.
Then you have nothing to hide - publish your web.config and source to the world, they still can't hit your database.
If that won't work for you, use the built in configuration encryption system in ASP.NET.
PostgreSQL offers a nice solution for this kind of situation in their documentation. Essentially, you use ssh to bridge a port on your machine to the PostgreSQL server port on the remote machine. This has three stages of authentication:
Restrict access to the local port, such as only letting a particular user connect to it.
Set up password-less connection to the PostgreSQL host with ssh as a particular user.
Allow the user ssh connects as to have local access to PostgreSQL without a password.
This reduces the security to whether your user accounts are secured and your ssh configuration is sound, and you have no need of a password stored anywhere.
Edit: I should add that this will work with any database that listens to a TCP/IP port. It just happens to be described in PostgreSQL. And you will want iptables (or the equivalent off Linux) to do the port restrictions. See this.
I agree with lomaxx: if somebody is already on the server or has wide ranging access to it (like a sysadmin), the game is pretty much over. So the idea would be to use a server you trust that it is secure to the degree you want it to be. Specifically:
You need to trust the sysadmins
You need to trust anybody else who is running code on the same server (this is why shared hosting is a big no-no for me)
Beyond that, environment variables seem to be a popular choice for storing these types of credentials, because this means that access to the source only (for example by compromising the dev box) doesn't reveal it directly and also it can be nicely localized for each server (dev, test, etc).
plain text? If they're on your server, I would hope the server is secure enough not to allow unauthorised access. If people can access your config files on the server, something has gone wrong much earlier.
clarification: in terms of security, maintainability (e.g. if the login needs to change, can I find it later, etc)
#lomax: perhaps I might not want everyone with access to the physical server (e.g. sysadmins) to see the password.
Thanks!
In most cases, I believe it is sufficient to obfuscate the password in a plain text file (eg. with base64). You cannot completely protect a stored password against a determined sysadmin with root access, so there's not really any need to try. Simple obfuscation, however, protects against accidentally revealing the password to a shoulder surfer.
A more complex alternative is to set up a dedicated secure password server that either:
provides a password decryption service
actually stores the passwords for use by other less secure servers
Depending on the network protocols used, this may not protect against a rogue sysadmin with tcpdump. And it probably won't protect against a determined sysadmin with a debugger, either. At that point, it might be time to look at something like Kerberos tickets.
You can bake a symmetric encryption key into your binary, and have that binary read an encrypted username/password from a file on disk when it starts up.
However, this is not really much more than obfuscation, since your code is likely to be stored in some source repository somewhere.
I would suggest that you would be better served to control access to your servers both physically and over the network using a firewall and a private network bubble, and store the passwords in the clear (or base-64 encoded) on disk with permissions locked down to the run user for your web app.
You can also lock down the database server to only accept connections from your web app machines by IP.
Ultimately, your problem is that the key (your DB username/password pair) needs to be available for programmatic, unattended use by your web apps.