Skip to content

Container lint command fails if referencing secrets not present in the environment  #35972

Closed
@spideyfusion

Description

@spideyfusion

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.

  1. Create a new Symfony project (e.g. symfony new reproducer).

  2. Generate a new public/private key pair for the secrets vault with bin/console secrets:generate-keys.

  3. Add a secret to the vault with bin/console secrets:set TEST.

  4. Reference the secret in your service configuration:

App\Controller\TestController:
    arguments:
        - '%env(TEST)%'
  1. 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: ~

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions