Safe and simple AWS credential management for your Symfony/PHP application

nikolastojilj12

Nikola Stojiljkovic

Posted on October 10, 2021

Safe and simple AWS credential management for your Symfony/PHP application

Introduction

If you have a Symfony/PHP application which needs to connect to AWS and use some of its services (S3, Secrets Manager,...) and you want to avoid pushing credentials to your Git repository or revealing them to any third party (ex. deployment, testing or code review tools), then follow this guide.

This guide will show you how to quickly and safely integrate AWS authentication both on your local development environment and on the server, both on bare metal and by using Docker.

Note that this is all available on the official AWS Documentation portal... scattered across multiple pages and documentation sections and buried in walls of text.

AWS SDK for PHP

AWS SDK for PHP (install in your project with composer require aws/aws-sdk-php) is a library which you'll use the most when working with AWS services in your PHP application. The SDK has several built-in method for connecting to AWS and authenticating your application - you only need to know how best to use it.


Local development environment - bare metal

Steps:

  • Install AWS CLI;
  • Configure AWS CLI;
  • AWS SDK for PHP will pick up credentials stored in ~/.aws directory and automatically use them.

Step 1. Install AWS CLI

Windows - default installation method

Windows - Scoop (my preferred method)

Scoop is a Windows package manager which provides many CLI tools, including those from Linux. If you don't know about it and would like to know more, check out my article on Scoop: Using Scoop and Cmder to make PHP development on Windows bearable

Install AWS CLI with:

scoop install aws
Enter fullscreen mode Exit fullscreen mode

Other operating systems

Follow the official guide for your operating system at: https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html

Step 2. Configure AWS CLI

Run:

aws configure
Enter fullscreen mode Exit fullscreen mode

and complete the questions from the prompt. This will store your AWS login credentials to your user's ~/.aws directory.

When your application tries to use AWS SDK, the SDK will automatically look whether credentials are stored in this directory and will try to use them.


Local development environment - Docker

Steps:

  • Add AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables to .env.local file;
  • AWS SDK for PHP will pick them up and use them to connect to AWS services from your Docker container.

Apart from reading credentials from the ~/.aws directory, AWS SDK for PHP supports reading credentials from the mentioned environment variables.

If you're running your application in Docker locally, open the .env.local file and add AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables to it (of course, fill the values with your AWS access key ID and AWS secret access key).

Symfony's .env.local file is excluded from Git by default, so these values will not leave your computer.


Server - AWS EC2

You don't need to configure anything. EC2 instances can connect to other AWS services by default by using AWS metadata service to retrieve credentials from an IAM role.


Server - non-AWS bare metal server

If you are running your Symfony application on a server which is not hosted on AWS:

  • Open terminal and open ssh connection to your server;
  • Download and install AWS CLI on your server. Guide: https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2-linux.html#cliv2-linux-install ;
  • Run aws configure and add your credentials. They will be stored on the server in your user's ~/.aws directory;
  • Make sure that a user on your server which has PHP execution rights (for example: apache) has access to the .aws directory;
  • AWS SDK for PHP will pick up credentials stored in ~/.aws directory and use them to connect to AWS services.

Server - Dockerized environment on AWS

Steps:

  • Use the AWS_CONTAINER_CREDENTIALS_RELATIVE_URI environment variable during docker build;
  • Add AWS_CONTAINER_CREDENTIALS_RELATIVE_URI argument to your Dockerfile;

Step 1. Add AWS_CONTAINER_CREDENTIALS_RELATIVE_URI in docker build

Open your project's buildspec.yml file and edit the docker build to include AWS_CONTAINER_CREDENTIALS_RELATIVE_URI environment variable. It should look something like this:

phases:
    build:
        commands:
            ...
            docker build --build-arg AWS_CONTAINER_CREDENTIALS_RELATIVE_URI=$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI -t myapp:latest .
Enter fullscreen mode Exit fullscreen mode

Step 2. Add an argument to your Dockerfile

Open your project's Dockerfile and add AWS_CONTAINER_CREDENTIALS_RELATIVE_URI argument before the first RUN command:

ARG AWS_CONTAINER_CREDENTIALS_RELATIVE_URI
Enter fullscreen mode Exit fullscreen mode

AWS SDK for PHP will handle the rest. The app in your Docker container can now connect to AWS services by using AWS metadata service to retrieve credentials from an IAM role.


Server - Dockerized environment outside of AWS

To be completely honest, I didn't have an opportunity to work on this setup directly. Having that in mind, let's proceed.

The method of integrating AWS credentials in this case really depends on your CI/CD pipeline and tools. By reading this article you probably already have an idea how to add credentials to a Dockerized server environment, but here's some of the options anyway:

Option 1. - AWS CLI + Docker volume

Just like a bare metal non-AWS server (described above), you can open an ssh session to your server and install/configure AWS CLI on the server. You can then add a Docker volume pointing to ~/.aws directory on the server which will transfer credentials into the container.

Option 2. - Use AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables

This option is based on the same method as the local Dockerized environment.

Depending on your CI/CD pipeline and tools, you might consider using AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables. Of course, you have to make sure that no third-party server has access to these values. If you are controlling your own CI/CD pipeline, for example by using a self-hosted GitLab instance, you can add these values in it.

Note: You can't use AWS_CONTAINER_CREDENTIALS_RELATIVE_URI

AWS_CONTAINER_CREDENTIALS_RELATIVE_URI is populated by AWS services (ECS and CodeBuild). Using this environment variable makes sense when you are deploying using AWS CodeBuild, but if you are building and deploying outside of AWS, then it's not available to you.


Conclusion

You should now have an idea on how to set up your environment(s) so that your project can use AWS services securely without exposing credentials.

Let me know in the comments if you have a more elegant solution.

💖 💪 🙅 🚩
nikolastojilj12
Nikola Stojiljkovic

Posted on October 10, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related