Nikola Stojiljkovic
Posted on October 10, 2021
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
- Download the installer from https://awscli.amazonaws.com/AWSCLIV2.msi and run it.
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
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
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
andAWS_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 duringdocker build
; - Add
AWS_CONTAINER_CREDENTIALS_RELATIVE_URI
argument to yourDockerfile
;
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 .
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
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.
Posted on October 10, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.