如何保密敏感資訊
環境變數是儲存取決於應用程式運行位置的設定的最佳方式 - 例如,在本地開發時可能設定為一個值,而在生產環境中設定為另一個值的 API 金鑰。
當這些值是敏感且需要保密時,您可以使用 Symfony 的秘密管理系統(有時稱為「金庫」)安全地儲存它們。
注意
秘密系統需要 Sodium PHP 擴充套件。
產生加密金鑰
為了加密和解密秘密,Symfony 需要加密金鑰。金鑰對可以透過執行以下命令產生
1
$ php bin/console secrets:generate-keys
這將產生一對非對稱加密金鑰。每個環境都有自己的金鑰組。假設您在 dev
環境中進行本地編碼,這將建立
config/secrets/dev/dev.encrypt.public.php
- 用於加密/新增秘密到金庫。可以安全提交。
config/secrets/dev/dev.decrypt.private.php
- 用於從金庫解密/讀取秘密。
dev
解密金鑰可以提交(假設沒有高度機密的秘密儲存在 dev 金庫中),但prod
解密金鑰絕不應該提交。
您可以透過執行以下命令,為 prod
環境產生一對加密金鑰
1
$ APP_RUNTIME_ENV=prod php bin/console secrets:generate-keys
這將產生 config/secrets/prod/prod.encrypt.public.php
和 config/secrets/prod/prod.decrypt.private.php
。
危險
prod.decrypt.private.php
檔案高度機密。您的開發團隊甚至持續整合服務都不需要該金鑰。如果解密金鑰已洩露(例如前員工離職),您應該考慮執行以下命令產生一個新的金鑰:secrets:generate-keys --rotate
。
建立或更新秘密
假設您想要將您的資料庫密碼儲存為秘密。透過使用 secrets:set
命令,您應該將此秘密新增到 dev
和 prod
金庫中
1 2 3 4 5 6 7
# the input is hidden as you type for security reasons
# set your default development value (can be overridden locally)
$ php bin/console secrets:set DATABASE_PASSWORD
# set your production value
$ APP_RUNTIME_ENV=prod php bin/console secrets:set DATABASE_PASSWORD
這將在 config/secrets/dev
中為秘密建立一個新檔案,並在 config/secrets/prod
中建立另一個檔案。您也可以透過其他幾種方式設定秘密
1 2 3 4 5 6 7 8
# provide a file where to read the secret from
$ php bin/console secrets:set DATABASE_PASSWORD ~/Download/password.json
# or contents passed to STDIN
$ echo -n "$DB_PASS" | php bin/console secrets:set DATABASE_PASSWORD -
# or let Symfony generate a random value for you
$ php bin/console secrets:set REMEMBER_ME --random
注意
沒有命令可以重新命名秘密,因此您需要建立一個新秘密並移除舊的。
在設定檔中參考秘密
秘密值可以與環境變數相同的方式參考。請小心不要意外地定義一個秘密和一個同名的環境變數:環境變數覆寫秘密。
如果您儲存了 DATABASE_PASSWORD
秘密,您可以透過以下方式參考它
1 2 3 4 5 6
# config/packages/doctrine.yaml
doctrine:
dbal:
password: '%env(DATABASE_PASSWORD)%'
# ...
# ...
實際值將在運行時解析:容器編譯和快取預熱不需要解密金鑰。
列出現有秘密
所有人都可以使用 secrets:list
命令列出秘密名稱。如果您有解密金鑰,您也可以透過傳遞 --reveal
選項來顯示秘密值
1 2 3 4 5 6 7
$ php bin/console secrets:list --reveal
------------------- ------------ -------------
Name Value Local Value
------------------- ------------ -------------
DATABASE_PASSWORD "my secret"
------------------- ------------ -------------
顯示現有秘密
如果您有解密金鑰,secrets:reveal
命令可讓您顯示單個秘密的值。
1 2 3
$ php bin/console secrets:reveal DATABASE_PASSWORD
my secret
7.1
secrets:reveal
命令在 Symfony 7.1 中引入。
本地秘密:在本機覆寫秘密
dev
環境秘密應包含適用於開發的良好預設值。但有時開發人員在開發時仍然需要在本地覆寫秘密值。
大多數的 secrets
命令(包括 secrets:set
)都有一個 --local
選項,該選項將「秘密」儲存在 .env.{env}.local
檔案中作為標準環境變數。若要在本地覆寫 DATABASE_PASSWORD
秘密,請執行
1
$ php bin/console secrets:set DATABASE_PASSWORD --local
如果您輸入 root
,您現在將在您的 .env.dev.local
檔案中看到這個
1
DATABASE_PASSWORD=root
這將覆寫 DATABASE_PASSWORD
秘密,因為環境變數始終優先於秘密。
現在列出秘密也會顯示本地變數
1 2 3 4 5 6
$ php bin/console secrets:list --reveal
------------------- ------------- -------------
Name Value Local Value
------------------- ------------- -------------
DATABASE_PASSWORD "dev value" "root"
------------------- ------------- -------------
Symfony 還提供了 secrets:decrypt-to-local
命令,該命令解密所有秘密並將其儲存在本地金庫中;以及 secrets:encrypt-from-local
命令,該命令將所有本地秘密加密到金庫。
測試環境中的秘密
如果您在 dev
和 prod
環境中新增一個秘密,它將在 test
環境中遺失。您可以為 test
環境建立一個「金庫」並在那裡定義秘密。但更簡單的方法是透過 .env.test
檔案設定測試值
1 2
# .env.test
DATABASE_PASSWORD="testing"
將秘密部署到生產環境
由於解密金鑰絕不應該提交,因此您需要手動將此檔案儲存在某處並部署它。有 2 種方法可以做到這一點
上傳檔案
第一個選項是將生產環境解密金鑰 -
config/secrets/prod/prod.decrypt.private.php
複製到您的伺服器。使用環境變數
第二種方法是將
SYMFONY_DECRYPTION_SECRET
環境變數設定為生產環境解密金鑰的 base64 編碼值。取得金鑰值的巧妙方法是1 2 3
# this command only gets the value of the key; you must also set an env var # in your system with this value (e.g. `export SYMFONY_DECRYPTION_SECRET=...`) $ php -r 'echo base64_encode(require "config/secrets/prod/prod.decrypt.private.php");'
為了提升效能(即避免在運行時解密秘密),您可以在部署期間將您的秘密解密到「本地」金庫
1
$ APP_RUNTIME_ENV=prod php bin/console secrets:decrypt-to-local --force
這會將所有解密的秘密寫入
.env.prod.local
檔案。完成此操作後,解密金鑰不需要保留在伺服器上。
秘密輪替
secrets:generate-keys
命令提供了一個 --rotate
選項來重新產生加密金鑰。Symfony 將使用舊金鑰解密現有秘密,產生新的加密金鑰,並使用新金鑰重新加密秘密。為了要解密先前的秘密,開發人員必須擁有解密金鑰。
設定
秘密系統預設為啟用,其某些行為可以設定
1 2 3 4 5 6
# config/packages/framework.yaml
framework:
secrets:
#vault_directory: '%kernel.project_dir%/config/secrets/%kernel.environment%'
#local_dotenv_file: '%kernel.project_dir%/.env.%kernel.environment%.local'
#decryption_env_var: 'base64:default::SYMFONY_DECRYPTION_SECRET'