跳到內容

如何保密敏感資訊

編輯此頁面

環境變數是儲存取決於應用程式運行位置的設定的最佳方式 - 例如,在本地開發時可能設定為一個值,而在生產環境中設定為另一個值的 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.phpconfig/secrets/prod/prod.decrypt.private.php

危險

prod.decrypt.private.php 檔案高度機密。您的開發團隊甚至持續整合服務都不需要該金鑰。如果解密金鑰已洩露(例如前員工離職),您應該考慮執行以下命令產生一個新的金鑰:secrets:generate-keys --rotate

建立或更新秘密

假設您想要將您的資料庫密碼儲存為秘密。透過使用 secrets:set 命令,您應該將此秘密新增到 devprod 金庫中

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 中引入。

移除秘密

Symfony 提供了一個方便的命令來移除秘密

1
$ php bin/console secrets:remove DATABASE_PASSWORD

本地秘密:在本機覆寫秘密

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 命令,該命令將所有本地秘密加密到金庫。

測試環境中的秘密

如果您在 devprod 環境中新增一個秘密,它將在 test 環境中遺失。您可以為 test 環境建立一個「金庫」並在那裡定義秘密。但更簡單的方法是透過 .env.test 檔案設定測試值

1
2
# .env.test
DATABASE_PASSWORD="testing"

將秘密部署到生產環境

由於解密金鑰絕不應該提交,因此您需要手動將此檔案儲存在某處並部署它。有 2 種方法可以做到這一點

  1. 上傳檔案

    第一個選項是將生產環境解密金鑰 - config/secrets/prod/prod.decrypt.private.php 複製到您的伺服器。

  2. 使用環境變數

    第二種方法是將 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'
本作品,包括程式碼範例,根據 Creative Commons BY-SA 3.0 授權條款授權。
目錄
    版本