-
Notifications
You must be signed in to change notification settings - Fork 11.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[9.x] New env:encrypt
and env:decrypt
commands
#44034
Conversation
env:encrypt
and env:decrypt
commands
This is something that should be a package used as part of app deployment flow, if people have any use for it. Few fundamental issues come to mind with this:
Overall this seems like a solution looking for a problem. The .env file itself is a simple paradigm used for years by many applications, meant to live outside your version control, already decrypted with sensitive information. |
Just adding here that a leaked key has the same problem. Even keys that are no longer used, and might not be realised to be sensitive anymore, still decrypts the version of the encrypted env file at the point in time it was used. The git history would have to be altered for this to be resolved. |
This is a nope for me. You're moving the secrets problematic from the deployment server back to the source code, where it has more surface of attack in case of leakage. |
This PR takes inspiration from Rail's own version of this feature, Secrets. @joedixon has simplified Laravel's implementation of this since keys are typically stored within a For comparison, the Rails implementation of this can be found at rails/rails#28038 |
Symfony also has its "vault" / secret security management system so that the sensitive environment variable values can be committed to version control -> https://symfony.com/doc/current/configuration/secrets.html It uses X25519 asymmetric cryptographic keys which are IMO safer than the symmetric encryption that this PR provides. The Sodium PHP extension is being used for that purpose and it does not allow you to use different (potentially weaker) algorithms/ciphers. Also it has a default convention as to where it stores the public key and the encrypted file (which takes into account the application environment so it knows when to create the encrypted file in for example TLDR; IMO the feature itself is totally valid (other frameworks like Rails and Symfony have this too), but I think that in its current state it needs a bit of polish. |
@X-Coder264 could you elaborate how using a different encryption scheme would be safer? What is unsafe about the approach proposed? |
I think he refers that is safer because is asym. To me, passing the public key is not far off of using a symmetric key, which in turn is not far off of using a list of secrets. Now that I put more thought into it, I think is not bad, you're just now adding all eggs into one basket. Asym has the same surface of attack that sym to decode the keys, and asym only adds more friction to the implementation. If approved, caution should be advised, because it will work as a keychain. |
I like the convenience this provides as it allows you to keep all your configuration in the same repo as your application code. I have my own custom solution to encrypt values in my .env files and it has been a great developer experience. I would suggest that rather than encrypting the entire .env file, only the secret values should be encrypted or else store the encrypted values in a separate file. It looks like Rails and Symfony store the encrypted values in a separate file from the main configuration. This is helpful because then non-sensitive values are easier to view and work with. I took inspiration from how
then run a command that will look for any lines starting with ENCRYPT then encrypt the value and replacing it with
I have a service provider that is responsible for decrypting the encrypted values and updating the config. It may be possible to use a vlucas/phpdotenv custom loader to handle decrypting the encrypted values. |
The benefits of asymmetric keys are that you can have the production server and senior DevOps people have possession of the private key, whereas everyone including the junior devs can have possession of the public key. |
I have a fresh PHP 8.2 Laravel 10 project Now my task is that I want to run the project without the .env file, if someone hacks my .env file or if someone has my .env data then all my confidential credentials are gone. My fresh project has only .env.example file and i copy it to .env then after i put all my secret credentials i run php artisan env:encrypt then it will generate .env.encrypted then i remove my .env file from laravel project because I don't want it. As I understand env.encryption is only used for version control i.e. if I want my .env file in git I can convert it into .env.encrypted and go ahead with git. Can you please explain how exactly to use .env.encrypted or how we can get around that concern |
Encrypting environment files is well documented and how to decrypt an encrypted environment file can be found here: https://laravel.com/docs/10.x/configuration#decryption Encrypting and decrypting environment files is as you said solely for the purpose of committing them in your VCS. So in a team you don't have to share for example credentials of services where every team member uses the same account/token/password. |
I need to use the encrypt version on the main server. Because if a hacker gets access to the .env file, he can see the encrypted version |
Technically it would be possible to leave the file encrypted on the server and let laravel decrypt the contents at runtime, whenever it needs to access an environment variable. But this wouldn't be more secure than having the file lying around there decrypted, as it is right now. For laravel to be able to get the decrypted content it must know the key to decrypt it. So the key needs to be there somewhere in plain text anyway. It's like having a safe in your house and you want it to be locked because you're worried that someone can access it when they break into your house. But the safe has a post-it with the combination on it. That isn't much of a difference to an unlocked safe in your house. |
This PR proposes two new Artisan commands;
env:encrypt
andenv:decrypt
which provide a mechanism for encrypting and decrypting .env files.Inspiration for this was taken from Rails who have had similar functionality since Rails 5.1 released in 2017.
The biggest benefit of this is that the encrypted environment files can be committed to version control which opens up a number of possibilities.
Real world examples where these commands can be used include ecosystem tools such as Forge, Vapor and Envoyer.
With Forge and Envoyer, it would be possible to decrypt the environment as part of the deployment script.
With Vapor, this would help solve an issue with the limit on the number of environment variables allowed by Lambda and the cost associated with decrypting secrets from KMS.
Decryption can be carried out either by passing a
--key
option to the command or by setting theLARAVEL_ENV_ENCRYPTION_KEY
environment variable. The affordance of the environment variable means it would be use in conjunction with secrets in a service like GitHub Actions.env:encrypt
Running
php artisan env:encrypt
will look for a.env
file at the root of the project, grab the contents of the file, encrypt it with a new key and save it as.env.encrypted
.The decryption key is displayed in the output of the command along with the cipher used and the path of the encrypted file.
You may utilise your own key by using the
--key
option.Similarly, you may specify any of the ciphers supported by Laravel’s [Encrypter](https://github.com/laravel/framework/blob/9.x/src/Illuminate/Encryption/Encrypter.php#L32-L37) class using the
--cipher
option. If no key is passed when using this option, the command will generate a key of the correct length for the cipher.You may also utilise the
--env
option to tell the command which environment you wish to encrypt.The above command will look for an environment file called
.env.production
. If the file exists, the contents will be encrypted and stored in a file called.env.production.encrypted
.If an encrypted file already exists at the location where the command is attempting to store it, it will not be overwritten by default. Of course, you may choose to do so using the
--force
option.env:decrypt
The
env:decrypt
command decrypts the contents of the encrypted environment file and writes the output to the.env
of the chosen environment.A decryption key is required to run this command which can be obtained from one of two places.
--key
optionsLARAVEL_ENV_ENCRYPTION_KEY
The
--key
option takes precedence over the environment variable. The purpose of the environment variable is to make the decryption process simple and secret during deployment/CI.Like the encrypt command, you may also pass the cipher used to encrypt the file.
In the decrypt command, passing the
--env
option will result in the command looking for a file called.env.[environment].encrypted
to decrypt which, if found and decrypted successfully, will be written to.env.[environment]
. This format is already supported by Laravel.If a file already exists where the command attempts to write the file to, it will not be overwritten. This behaviour can be forced with the
--force
option.Sometimes, for example if you were running the command as part of a forge deployment, you may wish to decrypt the contents of file to a different filename. You may do this with the
--filename
option.php artisan env:decrypt --key=h9kAPUmxdZ8ZbwT3 --env=production --filename=.env"
Running the command above would find the encrypted file
.env.production.encrypted
and write the decrypted contents to.env
.