Skip to main content

Using AWS Secrets Manager with Yii2

AWS Secrets Manager is used manage, retrieve, and rotate database credentials, API keys, and other secrets throughout their lifecycles.

Prerequisites

  1. PHP >= 7.4
  2. PHP apcu module should be installed (this can be checked using php -m | grep "apcu").
  3. AWS crededtial with Secrets manager access or server with secrets manager IAM role attached.

Usage

For this tutorial we'll assume that the following key-value secrets are already stored in the secrets manager:

{
"DB_USER_UIMS": "",
"DB_PASS_UIMS": "",
"DB_HOST_UIMS": "",
"DB_NAME_UIMS": "",
"DB_HOST_RO_UIMS": ""
}

There could be more key-value secrets based on the requirement.

Creating config file

Create a _conf.php file in the config folder

<?php
use Aws\Exception\AwsException;
use Aws\SecretsManager\SecretsManagerClient;

$secretName ='<secret name>';

// Checking apcu cache for stored secret
$secret = apcu_fetch($secretName);

// if secret is not cached, get the secret by calling the secrets manager SDK
if (!$secret) {
try {
$client = new SecretsManagerClient([
'version' => 'latest',
'region' => '<aws region>'
]);

$result = $client->getSecretValue([
'SecretId' => $secretName,
]);
} catch (AwsException $e) {
$error = $e->getAwsErrorCode();
if ($error == 'DecryptionFailureException') {
// Secrets Manager can't decrypt the protected secret text using the provided AWS KMS key.
// Handle the exception here, and/or rethrow as needed.
throw $e;
}
if ($error == 'InternalServiceErrorException') {
// An error occurred on the server side.
// Handle the exception here, and/or rethrow as needed.
throw $e;
}
if ($error == 'InvalidParameterException') {
// You provided an invalid value for a parameter.
// Handle the exception here, and/or rethrow as needed.
throw $e;
}
if ($error == 'InvalidRequestException') {
// You provided a parameter value that is not valid for the current state of the resource.
// Handle the exception here, and/or rethrow as needed.
throw $e;
}
if ($error == 'ResourceNotFoundException') {
// We can't find the resource that you asked for.
// Handle the exception here, and/or rethrow as needed.
throw $e;
}
}
// Decrypts secret using the associated KMS CMK.
// Depending on whether the secret is a string or binary, one of these fields will be populated.
if (isset($result['SecretString'])) {
$secret = $result['SecretString'];
} else {
$secret = base64_decode($result['SecretBinary']);
}
$secret = json_decode($secret, true);

// store the secret in cache for 1 week
apcu_store($secretName, $secret, 604800);

}

return $secret;
tip

This _conf.php file can be imported wherever the secrets are required.

Updating the existing DB file

Update the existing db.php and rest of the DB files according to the following snippet:

<?php
$conf = require (__DIR__."/_conf.php");

return [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host='.$conf["DB_HOST_UIMS"].';dbname='.$conf["DB_NAME_UIMS"],
'username' => $conf["DB_USER_UIMS"],
'password' => $conf["DB_PASS_UIMS"],
'charset' => 'utf8mb4',
'enableSchemaCache' => true,
'schemaCacheDuration' => 3600,
'schemaCache' => 'cache',

'slaveConfig' => [
'username' => $conf["DB_USER_UIMS"],
'password' => $conf["DB_PASS_UIMS"],
'charset' => 'utf8mb4',
'attributes' => [
PDO::ATTR_TIMEOUT => 10,
],
],

// list of slave configurations
'slaves' => [
[
'dsn' => 'mysql:host='.$conf["DB_HOST_RO_UIMS"].';dbname='.$conf["DB_NAME_UIMS"],
]
]
];

Resources

  1. AWS Secrets manager
  2. PHP APCu