Introduction
Environment variables play a crucial role in most modern applications by ensuring configurations are separate from application code. However, the sensitive nature of some of these variables, such as database credentials and API keys, demands a secure storage solution. This article will explore cloud-based options, primarily focusing on AWS, for storing and retrieving PHP environment variables securely, particularly for popular platforms like Magento, Drupal, Laravel and other PHP frameworks.
Why Securely Store Environment Variables?
Security: Plainly storing environment variables can be a vulnerability. Ensuring encryption and restricted access is vital to prevent data breaches.
Scalability: Cloud services can seamlessly cater to applications that scale, ensuring consistent access to environment variables across instances.
Maintainability: Centralised storage makes it easier to manage and rotate keys, credentials, or configurations without touching the application code.
AWS Secrets Manager
What is it?
AWS Secrets Manager is a service that helps you protect access to your applications, services, and IT resources without the upfront investment and on-premises maintenance.
How to use it with PHP applications:
Store environment variables like MySQL credentials, API keys as secrets in AWS Secrets Manager. When your PHP application (like Magento or Drupal) starts up, use the AWS SDK for PHP to retrieve and use these secrets.
Benefits:
- Automatic secret rotation.
- Tight integration with other AWS services.
- Audit secret use with AWS CloudTrail.
Steps to store environment variables/credentials into AWS Secrets Manager
1. Setup
Ensure that you have installed and configured AWS CLI and AWS SDK for PHP.
2. Define Your Credentials
First, you need to define the credentials you want to store as a secret. In this example, we will store MySQL credentials as secrets.
$mysql_username = 'your_mysql_username';
$mysql_password = 'your_mysql_password';
$mysql_db_name = 'your_db_name';
$mysql_host = 'your_host';
3. Prepare Your Secret as a JSON String
AWS Secrets Manager expects the secret’s value as a string. If you’re storing structured data (like the username and password), you should encode it as a JSON string.
$secretData = json_encode([
'mysql_username' => $mysql_username,
'mysql_password' => $mysql_password,
'mysql_db_name' => $mysql_db_name, // Optional
'mysql_host' => $mysql_host; // Optional
]);
4. Store MySQL Credentials into Secrets Manager:
Now, you can use the AWS SDK’s SecretsManagerClient
to store your credentials in the Secrets Manager. You'll be using the createSecret
method if it's a new secret, or updateSecret
if you're updating an existing one.
<?php
require 'vendor/autoload.php';
use Aws\SecretsManager\SecretsManagerClient;
use Aws\Exception\AwsException;
$secretName = 'YOUR_SECRET_NAME';
$region = 'YOUR_AWS_REGION'; // e.g., 'us-west-2'
$mysql_username = 'your_mysql_username';
$mysql_password = 'your_mysql_password';
$mysql_db_name = 'your_db_name';
$mysql_host = 'your_host';
$secretData = json_encode([
'mysql_username' => $mysql_username,
'mysql_password' => $mysql_password,
'mysql_db_name' => $mysql_db_name, // Optional
'mysql_host' => $mysql_host; // Optional
]);
// Initialize the Secrets Manager client
$client = new SecretsManagerClient([
'version' => 'latest',
'region' => $region
]);
try {
// Attempt to create or update the secret
$result = $client->createSecret([
'Name' => $secretName,
'SecretString' => $secretData,
]);
/* If the secret already exists, you might catch the exception
and use updateSecret instead */
} catch (AwsException $e) {
if ($e->getAwsErrorCode() === 'ResourceExistsException') {
// Secret already exists, update it
try {
$result = $client->updateSecret([
'SecretId' => $secretName,
'SecretString' => $secretData,
]);
} catch (AwsException $e) {
echo "Error updating secret: " . $e->getAwsErrorMessage();
}
} else {
// Handle other errors
echo "Error creating secret: " . $e->getAwsErrorMessage();
}
}
// Optionally, output the result or confirmation
echo "Secret stored successfully.";
?>
Note: You have the option to create and manage your secrets directly through the Secret Manager in the AWS console. For the purposes of this tutorial, we have provided the above example to demonstrate storing secrets from PHP.
Steps to retrieve environment variables/credentials from AWS Secrets Manager
1. Retrieve Credentials from Secrets Manager:
Using the AWS SDK for PHP, you can retrieve the MySQL credentials stored in the AWS Secrets Manager.
<?php
require 'vendor/autoload.php';
use Aws\SecretsManager\SecretsManagerClient;
use Aws\Exception\AwsException;
$secretName = 'YOUR_SECRET_NAME';
$region = 'YOUR_AWS_REGION'; // e.g., 'us-west-2'
$client = new SecretsManagerClient([
'version' => 'latest',
'region' => $region
]);
try {
$result = $client->getSecretValue(['SecretId' => $secretName]);
//Decode the secret JSON string
$secret = json_decode($result['SecretString'], true);
$mysql_username = $secret['mysql_username'];
$mysql_password = $secret['mysql_password'];
$mysql_db_name = $secret['mysql_db_name'];
$mysql_host = $secret['mysql_host'];
// Use the credentials to connect to your MySQL database or any further processing
$conn = new mysqli($mysql_host, $mysql_username, $mysql_password, $mysql_db_name);
} catch (AwsException $e) {
// Handle errors
echo "Error retrieving secret: " . $e->getAwsErrorMessage();
}
?>
With the above code, each time your PHP application needs to connect to MySQL, it fetches the latest credentials from AWS Secrets Manager. After a rotation event in Secrets Manager, the new credentials will automatically be retrieved by your application on its next connection attempt.
Make sure that the IAM role associated with your application has the necessary permissions to read the secret from Secrets Manager.
Conclusion
Securing environment variables is crucial in today’s digital era, where security breaches can lead to significant data and monetary losses. By leveraging services like AWS Secrets Manager, developers can ensure that sensitive data such as API keys and database credentials are stored securely and can be accessed safely when booting up applications like Magento, Drupal, Laravel and other PHP frameworks.