Description
Symfony version(s) affected: 4.4, 5.0
Description
If you reference a secret in your service configuration which is stored in a vault via the secrets:set
command and you don't dump the secrets to your local environment with the secrets:decrypt-to-local
command, running the container lint check with the lint:container
command will result in a following exception:
In SodiumVault.php line 122:
[SodiumException]
keypair size should be SODIUM_CRYPTO_BOX_KEYPAIRBYTES bytes
Exception trace:
at /bug/vendor/symfony/framework-bundle/Secrets/SodiumVault.php:122
sodium_crypto_box_seal_open() at /bug/vendor/symfony/framework-bundle/Secrets/SodiumVault.php:122
Symfony\Bundle\FrameworkBundle\Secrets\SodiumVault->reveal() at /bug/vendor/symfony/framework-bundle/Secrets/SodiumVault.php:166
Symfony\Bundle\FrameworkBundle\Secrets\SodiumVault->list() at /bug/vendor/symfony/framework-bundle/Secrets/SodiumVault.php:174
Symfony\Bundle\FrameworkBundle\Secrets\SodiumVault->loadEnvVars() at /bug/vendor/symfony/dependency-injection/EnvVarProcessor.php:153
Symfony\Component\DependencyInjection\EnvVarProcessor->getEnv() at /bug/vendor/symfony/dependency-injection/Container.php:409
Symfony\Component\DependencyInjection\Container->getEnv() at /bug/vendor/symfony/dependency-injection/ContainerBuilder.php:1522
Symfony\Component\DependencyInjection\ContainerBuilder->getEnv() at /bug/vendor/symfony/dependency-injection/ContainerBuilder.php:1381
Symfony\Component\DependencyInjection\ContainerBuilder->resolveEnvPlaceholders() at /bug/vendor/symfony/dependency-injection/Compiler/CheckTypeDeclarationsPass.php:204
Symfony\Component\DependencyInjection\Compiler\CheckTypeDeclarationsPass->checkType() at /bug/vendor/symfony/dependency-injection/Compiler/CheckTypeDeclarationsPass.php:142
Symfony\Component\DependencyInjection\Compiler\CheckTypeDeclarationsPass->checkTypeDeclarations() at /bug/vendor/symfony/dependency-injection/Compiler/CheckTypeDeclarationsPass.php:101
Symfony\Component\DependencyInjection\Compiler\CheckTypeDeclarationsPass->processValue() at /bug/vendor/symfony/dependency-injection/Compiler/AbstractRecursivePass.php:81
Symfony\Component\DependencyInjection\Compiler\AbstractRecursivePass->processValue() at /bug/vendor/symfony/dependency-injection/Compiler/CheckTypeDeclarationsPass.php:89
Symfony\Component\DependencyInjection\Compiler\CheckTypeDeclarationsPass->processValue() at /bug/vendor/symfony/dependency-injection/Compiler/AbstractRecursivePass.php:46
Symfony\Component\DependencyInjection\Compiler\AbstractRecursivePass->process() at /bug/vendor/symfony/dependency-injection/Compiler/Compiler.php:91
Symfony\Component\DependencyInjection\Compiler\Compiler->compile() at /bug/vendor/symfony/dependency-injection/ContainerBuilder.php:734
Symfony\Component\DependencyInjection\ContainerBuilder->compile() at /bug/vendor/symfony/framework-bundle/Command/ContainerLintCommand.php:67
Symfony\Bundle\FrameworkBundle\Command\ContainerLintCommand->execute() at /bug/vendor/symfony/console/Command/Command.php:255
Symfony\Component\Console\Command\Command->run() at /bug/vendor/symfony/console/Application.php:930
Symfony\Component\Console\Application->doRunCommand() at /bug/vendor/symfony/framework-bundle/Console/Application.php:97
Symfony\Bundle\FrameworkBundle\Console\Application->doRunCommand() at /bug/vendor/symfony/console/Application.php:264
Symfony\Component\Console\Application->doRun() at /bug/vendor/symfony/framework-bundle/Console/Application.php:83
Symfony\Bundle\FrameworkBundle\Console\Application->doRun() at /bug/vendor/symfony/console/Application.php:140
Symfony\Component\Console\Application->run() at /bug/bin/console:42
How to reproduce
NOTE: Native sodium PHP extension should be installed on your system.
-
Create a new Symfony project (e.g.
symfony new reproducer
). -
Generate a new public/private key pair for the secrets vault with
bin/console secrets:generate-keys
. -
Add a secret to the vault with
bin/console secrets:set TEST
. -
Reference the secret in your service configuration:
App\Controller\TestController:
arguments:
- '%env(TEST)%'
- Run
bin/console lint:container
.
Possible Solution
We could just catch \Exception
here instead, but I fear we would be potentially hiding a deeper issue.
Additional context
SodiumVault implements EnvVarLoaderInterface which gets triggered as a last fallback option when resolving environment variables (e.g. in CheckTypeDeclarationsPass, ResolveEnvPlaceholdersPass).
The problem is, SodiumVault
provides a list of additional variables to be injected into the existing environment, but has an environment parameter as its own dependency. Seems like a chicken and egg situation to me.
This can only be reproduced if the container is compiled, but not dumped, which is why the lint:container
command fails.
Workaround
You can disable the ability to pass the decryption key from an envirionment variable in your framework configuration:
framework:
secrets:
decryption_env_var: ~