DEV Community

Nikola Stojiljkovic
Nikola Stojiljkovic

Posted on • Updated on

Configure Doctrine in Symfony to use AWS Secret values as MySQL connection parameters

If you are running Symfony 5, there are a couple of ways to keep your application's sensitive information (like database credentials) secret. One way is to use Symfony Secrets Vault. It's a great tool which offers a decent protection, but has a downside of having to manually manage private encryption keys.

However, if you are building and running your Symfony 5 application on AWS there's another option which doesn't include managing private keys: using AWS Secrets Manager to store sensitive data.

This post will guide you through the process of setting up your application to use secrets stored in AWS Secrets Manager as your database connection credentials. We'll use the constup/aws-secrets-bundle for this.

Step #1: Install AWS Secrets Bundle

First install the official AWS SDK for PHP:

composer require aws/aws-sdk-php
Enter fullscreen mode Exit fullscreen mode

Follow the guide of setting up AWS connection credentials, as described in bundle's documentation: AWS credentials and authentication

Update: I've recently published a full article about how to safely use AWS credentials. You can check it out here: Safe and simple AWS credential management for your Symfony/PHP application

Then install the bundle with:

composer require constup/aws-secrets-bundle
Enter fullscreen mode Exit fullscreen mode

Let's say that we have an AWS Secret named server_config in JSON format which contains our database connection credentials.

{
    "database_username": "some_username",
    "database_password": "some_password"
}
Enter fullscreen mode Exit fullscreen mode

Let's use the contents of this secret as database connection parameters in Symfony.

Step #2: Create environment variables

Create environment variables (in your Symfony .env file) called DATABASE_USERNAME and DATABASE_PASSWORD.
The values of these environment variables are made of the name of your AWS Secret, a delimiter and the name of the entry within the secret:

DATABASE_USERNAME='server_config','database_username'
DATABASE_PASSWORD='server_config','database_password'
Enter fullscreen mode Exit fullscreen mode

Step #3: Load secrets in service container parameters

Add the following to config/services.yaml:

parameters:
    database_username: '%env(aws:DATABASE_USERNAME)%'
    database_password: '%env(aws:DATABASE_PASSWORD)%'
Enter fullscreen mode Exit fullscreen mode

Now, when you call:

$this->getParameter('database_username');
Enter fullscreen mode Exit fullscreen mode

in a controller, the bundle will apply AWS processor to database_username parameter and use AWS SDK to fetch the value from the AWS Secret Manager.

Step #4: Configure Doctrine's MySQL connection

By default, Doctrine stores database connection parameters in the DATABASE_URL environment variable (in the .env file). It should look something like this:

DATABASE_URL="mysql://db_user:db_password@127.0.0.1:3306/db_name?serverVersion=8.0"
Enter fullscreen mode Exit fullscreen mode

To load database username and password which we fetched from the AWS Secrets Manager, just use the database_username and database_password service container parameters in the above line:

DATABASE_URL="mysql://%database_username%:%database_password%@127.0.0.1:3306/db_name?serverVersion=8.0"
Enter fullscreen mode Exit fullscreen mode

If you are using AWS RDS for database, also replace 127.0.0.1 with your RDS endpoint. (Hint: you can also store this
value in your server_config secret and fetch it just like username and password.)


Top comments (3)

Collapse
 
galiceau profile image
Galiceau

It is very interesting but there is a main issue concerning security aspect : the constup bundle requires AWS Credentials stored in the host. It is not a safe way to do. It would be better to use the instance profile permission to access to the secret in the secret manager. In this way, it is not necessary to know the AWS credentials. Clearly the instance profile should be granted to access to the AWS Secret manager.

Collapse
 
nikolastojilj12 profile image
Nikola Stojiljkovic

You may want to take a look at my other article: dev.to/nikolastojilj12/safe-and-si... That article covers pretty much all environments: from EC2 instances to bare metal local setups.

Collapse
 
jmertens profile image
Mertens Julien

Thanx for your post! I would suggest also if you have big trafic to cache credential to avoid latency and secret management calling limit exceeding.
my question is about auto rotation of password that can be activated on RDS : is there something in doctrine that could handle easily the changing "on the fly" like catching every "connection error due to wrong credential" and update secret in code before retrying the sql query ?