laravel-credentials icon indicating copy to clipboard operation
laravel-credentials copied to clipboard

Encrypting the APP_KEY itself

Open rohitgupta27 opened this issue 5 years ago • 1 comments

Thank you for the excellent package!! Our application is a medical application, so to be compliant with some security requirements, we have to encrypt all the secrets on the server and no secret should be in plaintext in the environment files. We are planning to use this package to encrypt DB credentials and other secrets, but that is not enough. Our APP_KEY has to be encrypted as well. Any suggestions how to achieve this?

We are hosted on AWS, so wondering if it would be possible to integrate this package with AWS KMS or AWS Secrets Manager to fetch the APP_KEY itself? Any help is greatly appreciated!!

rohitgupta27 avatar Oct 15 '20 14:10 rohitgupta27

Hi @rohitgupta27, I am a little bit late to the party. For our Kubernetes environment we are using the following helper method to load secrets from mounted files:

function credential($environmentKey, $fallback = NULL, $failOnMissing = true)
{
	$fromEnvironment = env($environmentKey);
	$useCredential = null;

	if (FALSE !== ($loadFromUrl = parse_url($fromEnvironment))) {
		$scheme = (isset($loadFromUrl['scheme'])) ? strtolower($loadFromUrl['scheme']) : null;

		// don't strtolower to keep path name intact (Linux filesystems)
		$path = isset($loadFromUrl['path']) ? $loadFromUrl['path'] : null;

		if (isset($loadFromUrl['query'])) {
			$params = [];

			parse_str($loadFromUrl['query'], $params);
			if (isset($params['relative_to'])) {
				switch ($params['relative_to']) {
					case 'storage':
						$path = storage_path($path);
						break;
					case 'application':
						$path = base_path($path);
						break;
					default:
						throw new \Exception("Unsupported relative_to argument: " . $params['relative_to']);
				}
			}
		}

		if ($scheme == 'file') {
			if (file_exists($path)) {
				$useCredential = file_get_contents($path);
			}
			else {
				if ($failOnMissing) {
					throw new \Exception("Secrets file $path has not been mounted");
				}
			}
		}
	} else {
		// this is not a URI, so fallback to environment variable
		$useCredential = $fromEnvironment;
	}
	
	if (empty($useCredential)) {
		$useCredential = $fallback;
	}

	if (empty($useCredential) && $failOnMissing) {
		throw new \Exception("Unable to locate secret for " . $environmentKey);
	}

	return $useCredential;
}
  1. During startup of your application, export the secret into the EC2/Docker container:
aws secretsmanager get-secret-value --secret-id YOUR_NAMESPACE/YOUR_SECRET--version-stage AWSCURRENT | jq --raw-output '.SecretString' > /secret.txt
  1. In your .env file change the APP_KEY value to file:///secret.txt.
  2. In your config/app.php change the key reference from key => env('APP_KEY') to key => credential('APP_KEY')

@mpociot Is this something you would have to be added to laravel-credentials natively? I would open a more polished PR for this feature.

schakko avatar Sep 15 '21 07:09 schakko