Helm 插件之 helm-secrets:利用 PGP 加密你的 Values 文件

在使用 Helm 部署應(yīng)用程序時,我們經(jīng)常會遇到需要為所要部署的應(yīng)用程序設(shè)定敏感信息值的情況,如:
為應(yīng)用程序自身設(shè)定登陸名和密碼信息,或設(shè)定應(yīng)用程序連接數(shù)據(jù)庫時所需的信息等等。

若將這些包含了敏感信息的值直接以明文的方式存儲在自定義的 Values 文件中,尤其是當(dāng)使用如 Git 等代碼版本控制工具追蹤 Values 文件時,將會帶來非常大的安全隱患。

因此,我們通常不會將這些包含有敏感信息的值保存在 Values 文件中,而是在部署的過程中,通過 HELM 命令的 --set 參數(shù),以命令行的形式為這些變量設(shè)定值。

但使用這種方式同樣也有它自身的局限性:首先,如果要設(shè)定的敏感字段過多,則在命令行中需要指定的參數(shù)就越多,這將使得命令行過于冗長且容易出錯,同時部署人員需要記住的部署參數(shù)也變得復(fù)雜起來;其次,通過查看系統(tǒng)執(zhí)行過的命令歷史記錄,同樣能夠獲取到在執(zhí)行 HELM 命令時所有指定的敏感信息參數(shù),這在一定程度上同樣存在安全隱患。

而本文將介紹另一種相對來說比較完美的解決方案:利用 Helm 的 secrets 插件,將這些包含了敏感信息的值通過某種加密手段加密之后,在保存到 Values 文件中去。

HELM SECRETS 插件簡介

helm-secrets 插件可以幫助我們將定義在 values.yaml 文件中的值進行加密之后重新存儲到 Values 文件中,被加密后的 Values 文件可以被隨意分發(fā)、存儲到代碼版本管理工具中而不用擔(dān)心敏感信息被暴露。下面是一個加密后的 Values 文件示例:

#ENC[AES256_GCM,data:IHAqGPYHlUdD2+xSn5ZcYCo=,iv:1KKx8l1zl41LuNYcKw3biXm0vx+vjAeA7wdnNHYjQ6Y=,tag:MmWG4SIeXPt0o0HOHGtJeQ==,type:comment]
registry:
    url: ENC[AES256_GCM,data:sYON9+wBDq9jcmhy8iUaITpIjApLbys=,iv:z/ITKkJp2rS/jMyvxghweA+7W0QlZ98PR+4gDGhX+WI=,tag:TLbCkMcIfW30/80FpaozoA==,type:str]
    username: ENC[AES256_GCM,data:5Ju2bxk=,iv:hxRUoi0lViW7chOQTiyZyt4nGMS5V5YZyFNf19LmvpA=,tag:lb830A5pnZ4bI0HUosyc7Q==,type:str]
    password: ENC[AES256_GCM,data:1WmPZCSlzGbSn2LqMc7DmHjQKTjsaPUdn9nMKvbl+KIJ451EPkV0s3dqF+NVZ5E+T6reYN/lY7Ok3VmGvboVAbFs1IYzn7KenbGLMGgCT+JhUFaYz16TeGGsyWDk6YcIIw/XzR6lTjilpHF+DuZuepOyiAnCO0Q5k4aux2lICQh6P8mOezt8flP9/blnFGVZhaaE5r5vT6hsaQbsy7Rnk2lP926xT8NWcaXR85AleRvevQ/zwFIFjjk=,iv:ivA6U20LCHOoR9WGSmuvlJdhnYx/ZC8Pw9czMjNrrlI=,tag:wX3SiiBv8OjSZkpbCznDZw==,type:str]

jenkins:
    master:
        JCasC:
            configScripts:
                credentials-config: ENC[AES256_GCM,data:3dN7KBW...Ov/rsUA=,tag:qlfV/0x0vr45JxMYM1UdMQ==,type:str]
sops:
    kms: []
    gcp_kms: []
    lastmodified: '2019-07-10T06:21:36Z'
    mac: ENC[AES256_GCM,data:sKsL25V5yci+oD1PpfA5fU6zE7YCc6Sxg7myE4eqoDcA+guG8gUg4Hcj5yAB4APBq3+KtPIXoF0hNHVYZOOYqZXQrMpO0jASjWHmLAFTUb6FE6xOtb4mP3FBk8W6Km7TfNz3Te8WW4nsb/+c0WmFSQnIolaeXgbbZhZ23x+V9g=1,iv:Oha7rwD2y3xCc+UnI+xXwrnFByMhNJkF84TiYq4/LsWI=,tag:W3e9ox2G9QL5jQEV0VwGA==,type:str]
    pgp:
    -   created_at: '2019-07-10T06:21:34Z'
        enc: |
            -----BEGIN PGP MESSAGE-----

            hQEMA9Q2nDmrg55qAQf/aXiC7EXZlP5OZDrH3clCb0I9uqP8eNhVgAzqyfSaajGB
            ...
            =h7fE
            -----END PGP MESSAGE-----
        fp: AD331C18082B4669992805DDCB8EA0C7BC44A464
    unencrypted_suffix: _unencrypted
    version: 3.0.3

可以看到,加密操作僅僅是針對 YAML 文件中所有 Key 對應(yīng)的值進行的,而保留了 Key 本真。相對于那種針對整個 YAML 文件進行整體加密的方式來說,通過這種加密方式加密后的文件,仍然保留了很強的可讀性,這使得我們對加密后的 YAML 文件進行維護變的可能。

而當(dāng)我們部署應(yīng)用程序時,直接將加密后的 Values 文件傳遞給 HELM 命令,helm-secrets 插件則會自動負(fù)責(zé)為我們對加密的值進行解密操作,整個過程無需任何人為干預(yù)。

安裝 helm-secrets 插件

在使用 helm-secrets 插件之前,首先確保該插件被安裝到了本地 HELM 中,安裝 HELM 插件非常簡單,使用下面命令直接進行安裝即可:

$ helm plugin install https://github.com/futuresimple/helm-secrets

安裝完成后,可通過 HELM 的 list 命令查看插件是否安裝成功:

$ helm plugin list
NAME    VERSION DESCRIPTION
secrets 2.0.2   This plugin provides secrets values encryption for Helm charts secure storing

SOPS 命令簡介

事實上,helm-secrets 插件本身并沒有任何加密與解密的能力,也沒有提供任何只針對于 YAML 文件的 Key 值進行加密和解密的工作方式,而它所有的工作,都是通過調(diào)用 SOPS 命令來幫助它完成的。

SOPS 是由 Mozilla 開發(fā)的一款開源的文本編輯工具,它支持對 YAML, JSON, ENV, INI 和 BINARY 文本格式的文件進行編輯,并利用 AWS KMS, GCP KMS, Azure Key Vault 或 PGP 等加密方式對編輯的文件進行加密和解密。

我們會在后面的小節(jié)中對 SOPS 做進一步的介紹。此時,你只需知道 SOPS 命令是確保 helm-secrets 插件可以正常工作的必不可少的依賴,因此,我們必須要確保系統(tǒng)中正確安裝了 SOPS 命令。

幸運的是,helm-secrets 插件會自動檢測并安裝 sops 命令到我們的系統(tǒng)中,因此在插件安裝完成后,你還應(yīng)該可以運行 sops 相關(guān)命令,如獲取 sops 的版本信息:

$ sops -v

當(dāng)然,你也可以通過手動方式選擇自行安裝 sops 工具,如使用 brew install sops 命令為 Mac 系統(tǒng)安裝 SOPS,或直接下載 SOPS 的可執(zhí)行文件,更多信息請查看 SOPS 文檔。

如果以上命令全部執(zhí)行成功,那么恭喜你,你已經(jīng)成功安裝了 helm-secrets 插件及其相關(guān)依賴。但在真正介紹如何使用該插件之前,我們還需要了解一些加密解密相關(guān)的基礎(chǔ)知識和命令。

PGP 簡介

正如前面所講,helm-secrets 插件是通過調(diào)用 SOPS 命令來對我們的 Values 文件進行加密和解密的,而 SOPS 本身又支持多種加密方式,如 AWS 云的 KMS,Google 云的 MKS,微軟 Azure 云的 Key Vault,以及 PGP 等加密方式。本文將著重介紹如何利用 PGP 對我們的 Values 文件進行加密和解密。

PGP 與 GPG

在了解 PGP 加密之前,我們首先要區(qū)分好兩個名詞概念:PGP 與 GPG。

Pretty Good Privacy,也就是我們平時所說的 PGP,實際上通常指的是 OpenPGP。OpenPGP 只是一系列協(xié)議或標(biāo)準(zhǔn),而并非某個特定的工具或命令,它規(guī)定了如何使用特定的方式和算法對文件或內(nèi)容進行加密和解密,任何實現(xiàn)了 OpenPGP 協(xié)議的工具都擁有加密和解密的能力。而本文接下來所要使用的 gpg 命令,正是這樣一個實現(xiàn)了 OpenPGP 協(xié)議的工具,或者說命令,利用 gpg 命令,我們可以實現(xiàn) PGP 加密方式。為了避免混淆,后文將一律使用 GPG 代替。

安裝 GPG

GPG,全名 GNU Privacy Guard,是隸屬于 GNU 項目下的一款開源免費的加密工具。目前絕大部分 Linux 發(fā)行版本都默認(rèn)安裝了 GPG,直接運行下面命令查看你當(dāng)前所在系統(tǒng)中是否已經(jīng)正確安裝了 GPG:

$ gpg --version

你也可以嘗試使用下面命令手動安裝 GPG 到你的系統(tǒng)中:

# Ubuntu,Debian 用戶
$ sudo apt install gnupg

# CentOS,F(xiàn)edora,RHEL 用戶
$ sudo yum install gnupg

# MacOS 用戶
$ brew install gnupg

生成 GPG 密鑰對

如果你使用過 SSH,那么你一定熟悉公鑰和私鑰的概念,GPG 同樣也使用了公鑰和私鑰的概念實現(xiàn)了非對稱加密算法。簡單來說:公鑰用于加密,擁有公鑰的人可以且僅僅可以進行加密操作,它可以分發(fā)給任何組織或個人;而私鑰則用于解密,且僅能用于解密那些由該私鑰與之配對的公鑰加密的信息,任何擁有私鑰的人都可以進行解密操作,因此,確保私鑰不被泄漏對安全性起著至關(guān)重要的作用。

在使用 gpg 命令進行加密解密之前,首先需要生成 GPG 公鑰和私鑰。你可以使用命令 gpg --gen-key 來交互式地生成密鑰對,之所以說交互式,是因為在生成密鑰對時會要求用戶交互式的輸入一些相關(guān)信息,如如用戶名、郵箱等等。你也可以使用下面命令直接生成出密鑰對,注意,在執(zhí)行命令之前,請注意修改下方 name、email 等字段信息為你自己相應(yīng)的信息:

$ gpg --batch --generate-key <<EOF
%echo Generating a basic OpenPGP key for HELM Secret
Key-Type: RSA
Key-Length: 4096
Subkey-Type: RSA
Subkey-Length: 4096
Name-Real: HELM Secret
Name-Comment: Used for HELM Secret Plugin
Name-Email: helm-secret@email.com
Expire-Date: 0
%no-ask-passphrase
%no-protection
%commit
%echo done
EOF

該命令將會為我們生成一對長度為 4096 且永不過期的 RSA 密鑰對,gpg 命令支持使用更多的參數(shù)來控制生成密鑰對,如為生成的密鑰對設(shè)定使用密碼等等,更多關(guān)于 GPG 命令的使用參數(shù),請參考官方文檔。

當(dāng)生成 GPG 密鑰對以后,我們就可通過 gpg--list-keys--list-secret-keys 命令分別列出當(dāng)前系統(tǒng)中的公鑰和私鑰信息了:

$ gpg --list-key

pub   rsa4096 2020-04-24 [SCEA]
      13D525EEF0A5FA38F4E78F7900E0160999E3C663
uid           [ultimate] HELM Secret (Used for HELM Secret Plugin) <helm-secret@email.com>
sub   rsa4096 2020-04-24 [SEA]

上面命令列出了當(dāng)前系統(tǒng)中的公鑰信息,其中 13D525EEF0A5FA38F4E78F7900E0160999E3C663 或者后十六位 00E0160999E3C663 為公鑰的 ID。

我們也可以通過傳遞密鑰的用戶名、郵箱或 ID 來查看某個特定的密鑰信息:

$ gpg --list-key "HELM Secret"
# 或
$ gpg --list-key "helm-secret@email.com"
# 或
$ gpg --list-key 00E0160999E3C663

在生成了密鑰對之后,就可以利用它們來為我們的文件進行加密和解密操作了。

使用 GPG 加密和解密文件

為了更好地理解 help-secrets(或 SOPS 命令)的優(yōu)勢,我們首先嘗試直接使用 gpg 命令來加密我們的文件:

  1. 首先創(chuàng)建一個名為 secrets.values.yaml 的文件,并寫入以下內(nèi)容:
App:
 username: login-user
 password: login-pwd
  1. 使用 gpg 命令對該文件進行加密:
$ gpg -e -r 00E0160999E3C663 secrets.values.yaml
  • -e 參數(shù)指定本次為加密操作
  • -r 參數(shù)指定了加密時所要使用的公鑰信息,這里直接通過公鑰 ID 來指定,我們也可以使用密鑰的用戶名和郵箱等信息,如 HELM Secrethelm-secret@email.com。

當(dāng)加密完成后,GPG 命令會在 secrets.values.yaml 文件所在的目錄下創(chuàng)建一個與它同名,且以 .gpg 結(jié)尾的新文件 secrets.values.yaml.gpg。該文件包含了加密后的內(nèi)容,如果你嘗試查看該文件內(nèi)容,會發(fā)現(xiàn)整個文件內(nèi)容將會以亂碼的形式展現(xiàn)出來,而這正式 GPG 的工作方式。

當(dāng)然,我們也可以使用 gpg 命令對某個加密過的文件進行解密操作:

$ gpg -d secrets.values.yaml.gpg
gpg: encrypted with 4096-bit RSA key, ID C79B2F32F9EE1A8E, created 2020-04-24
      "HELM Secret (Used for HELM Secret Plugin) <helm-secret@email.com>"
App:
  username: login-user
  password: login-pwd

-d參數(shù)用指定 GPG 命令執(zhí)行的是解密操作。與加密操作不同,我們并沒有指定解密時要使用的私鑰 ID,這是因為 GPG 在加密的同時,將解密時所需的私鑰信息一并寫入到了加密后的文件中去。當(dāng)然,你仍然可以使用 -r C8EABE3FAE86D256 參數(shù)明確指定解密時使用的私鑰 ID。你可能已經(jīng)注意到了,其實私鑰 ID 與公鑰 ID 完全相同。

當(dāng)解密操作成功后,GPG 命令會將解密后的內(nèi)容直接打印到屏幕上。

至此,我們成功地使用了 GPG 命令對文件進行了加密和解密操作,但不難看出,GPG 的加密操作是針對整個文件進行的,而加密后的文件內(nèi)容也將變得完全無法維護。

接下來,就讓我們簡單看一下,如何使用 SOPS 命令對這種 Key-Value 類型的文件進行加密和解密,并同時保證加密后的文件的可讀性和可維護性的。

SOPS 的簡單使用

為了更好地理解 helm-secrets 插件,先讓我們簡單看一下如何通過 SOPS 命令使用我們剛剛生成的 GPG 密鑰對來對 YAML 文件進行加密和解密操作:

  • 依然使用我們前面創(chuàng)建好的 secrets.values.yaml 文件,并確保寫入了以下內(nèi)容:
App:
  username: login-user
  password: login-pwd
  • 使用 sops 命令對 secrets.values.yaml 文件進行加密:
$ sops --encrypt --in-place --pgp 00E0160999E3C663 secrets.values.yaml
  1. --encrypt, -e 參數(shù)告訴 sops 進行加密操作;
  2. --in-place, -i 參數(shù)指定將加密后的內(nèi)容直接替換掉原文件內(nèi)容,若不指定該參數(shù),則加密后的內(nèi)容將會被輸出到屏幕上;
  3. --pgp, -p 參數(shù)指定我們加密時所要使用的 PGP 公鑰 ID。
  • 查看加密后的 secrets.values.yaml 文件內(nèi)容:
$ cat secrets.values.yaml

App:
    username: ENC[AES256_GCM,data:VwLJ94VxsEBMZg==,iv:Qeb6aNT1oryPplmtUx1ufIeiqwJ9APllLnorqvkdjRU=,tag:CuWtAlLEZeOuQFoW34FiEQ==,type:str]
    password: ENC[AES256_GCM,data:jo8lGGOFZuDY,iv:5Wwt/T0SskFxgWXNRjpoIPq+PIuTGILGIeN/dYOJ/Fg=,tag:ncC3t67xArsXvwwEjAGyLg==,type:str]
sops:
    kms: []
    gcp_kms: []
    azure_kv: []
    lastmodified: '2020-04-24T03:48:37Z'
    mac: ENC[AES256_GCM,data:uFdXa2qWDSYqaeVsOLZiQos5K611uZYW91ZhLT00MJRb32TxE190RlJjhvl8+/GUOClZcIaU8DejebDP1TVqVFl6wpFqjVM3TLwW0JDm+b+zpCzMje9e17dNjLp7W2awBTPmrF3AXUopLi8oHOuopW89q2gKgFIUW215zjmQET0=,iv:A85xzE6gEXpcwUE6rIvHwHNhqmaCmFOHoYX3Y4qjaGI=,tag:VSB9b9vKLRJg4/klwliJbQ==,type:str]
    pgp:
    -   created_at: '2020-04-24T03:48:35Z'
        enc: |
            -----BEGIN PGP MESSAGE-----

            hQIMA8ebLzL57hqOAQ//fOzjkY5tW1/fGd/HWrxsgC02YxAjmHggI2ek5VacdhYP
            A9RUYhpipJpBt1LnwHq/B1rV1E4dkOu1lpyAmI9P0qIc+6o0+6jEhqEyjsDQSGn5
            kh31oBNYfLq8XpHQg33jOIHpv6/BU7tqzsVMum3HjvnsSrhc3gRtBq5LZoLP/smA
            3y36tRLHIGFGqOEwy3CdSiPmsyCKQBEYRK0+7mhXX+ulEMudYXKgXk4qCL1UAB0y
            X03K0UATNYp8fRkHqzcpf5nLDNzpCGI0BNbxBQYZdbcP3KFNyKGDFtDaNCcJq9jv
            d6yMnioNWYBCtDlrZXlQGzipheWKwZ7JnNa1nmYpCJ3uh6I3mbtkHjljD88QUm6Y
            czGAsTDYESJPl5y2wdKdMxHOyE++Ii5LvNr2UD3D+ePYvAIpK1TWjfokCe18ZvvD
            v4kHbqbJfffpLCmy0CRVFu/yLnGdZGqniPY/UPPRk28cnKF+fxpX7EmLvzCUgadC
            4emIrR6nBUgGvU+fInZrNOccRhYU2S4So45CW2EXW5E4uNj8ayfUgtaUeRwW8pRE
            ZMGe1yna7a8UC0syiubC1rr8KHKs8nITfRrelV/BtEkfFDI9sm77AMcaWaAaaBz8
            C1L3A1iPhnclDnt3USqOTioLnZs9CjysyNSeiTvehsTC1E3GqgmVbUGob+0Im2fS
            XgHaA9fXLtulXkRQGFYpaNEt6r0mkgdq0DXCCfba6EflHg9BvPfrK0dtXrchlCY/
            K154U0LkPNHtLBXB0rNwz0Z9aA1CwBdRZ6r8V67SJS1nbsiIvyHfc4dq8n3qhVM=
            =HOrp
            -----END PGP MESSAGE-----
        fp: 00E0160999E3C663
    unencrypted_suffix: _unencrypted
    version: 3.5.0

不難看出,SOPS 僅僅是對 YAML 文件中的值進行了加密,而保留了所有 Key 信息,這使得即使是加密后的文件仍然保留了很強的可讀性。

此外,SOPS 還在文件中追加了一個新的 Key 值 sops,用于保存加密該文件時所使用的一些加密信息。

當(dāng)然,我們還可以通過 sops 命令對加密后的文件進行解密操作:

$ sops --decrypt secrets.values.yaml

App:
    username: login-user
    password: login-pwd

--decrypt, -d 參數(shù)指定我們要對文件進行解密操作。當(dāng)然,你也可以通過 -p 參數(shù)將解密時的私鑰 ID 傳遞給 SOPS 命令,但這通常是不必要但,因為與 GPG 一樣,SOPS 在加密文件時會自動解密時需要的私鑰 ID 記錄在內(nèi)。

通過上面的操作,我們成功地使用 SOPS 命令對 YAML 文件進行了加密和解密操作,而這也正是 helm-secrets 插件背后的工作流程。在了解了 SOPS 工作模式之后,接下來,讓我們開始正式步入 helm-secrets 插件的學(xué)習(xí)中去。

開始使用 helm-secrets 插件

在掌握了 GPG 和 SOPS 的一些基本原理和操作后,學(xué)習(xí)使用 helm-secrets 插件就將變得特別簡單起來。

helm-secrets 插件會為 HELM 命令創(chuàng)建一個新的子命令: secrets,所有關(guān)于該插件的子命令,都是通過 helm secrets 格式所調(diào)用的。首先讓我們通過 -h 參數(shù)打印出 helm-secrets 插件的幫助文檔信息:

$ helm secrets -h

GnuPG secrets encryption in Helm Charts

This plugin provides ability to encrypt/decrypt secrets files
to store in less secure places, before they are installed using
Helm.

To decrypt/encrypt/edit you need to initialize/first encrypt secrets with
sops - https://github.com/mozilla/sops

Available Commands:
  enc           Encrypt secrets file
  dec           Decrypt secrets file
  view          Print secrets decrypted
  edit          Edit secrets file and encrypt afterwards
  clean         Remove all decrypted files in specified directory (recursively)
  install       wrapper that decrypts secrets[.*].yaml files before running helm install
  template      wrapper that decrypts secrets[.*].yaml files before running helm template
  upgrade       wrapper that decrypts secrets[.*].yaml files before running helm upgrade
  lint          wrapper that decrypts secrets[.*].yaml files before running helm lint
  diff          wrapper that decrypts secrets[.*].yaml files before running helm diff
                  (diff is a helm plugin)

幫助文檔信息列出了 helm-secrets 插件支持的所有子命令,而這些子命令又可以被劃分為兩類:

  • 一類是由該插件提供的子命令,如 enc、decview、edit 以及 clean 等,這些子命令由該插件所創(chuàng)建,而在 HEML 中并不存在;

  • 另一類則是在 HELM 中已經(jīng)存在的子命令,如 enc、dec、view、edit 以及 clean 等。對于這些本就存在于 HELM 中的子命令來說,helm-secrets 插件僅僅是對這些子命令做了一層封裝操作,而背后真正調(diào)用的仍然是 HELM 自身的這些子命令,因此通過 helm-secrets 插件調(diào)用這些子命令時的用法與直接通過 HELM 調(diào)用的用法完全一致。

提示:你還可以為某個特定的子命令使用 -h 參數(shù),來獲取該子命令的幫助文檔信息,如 helm secrets dec -h。

下面讓我們通過部署一個實際的例子,來演示 helm-secrets 插件是如何工作的。

PostgreSQL

PostgreSQL 是由伯克利大學(xué)開發(fā)的一款有著 30 多年歷史的開源關(guān)系型數(shù)據(jù)庫,如今仍被大量的公司和企業(yè)所使用。HELM 官方 Chart 倉庫也提供了穩(wěn)定版的 PostgreSQL Chart,來幫助我們在 Kubernetes 平臺上快速部署 PostgreSQL 集群。接下來,就讓我們嘗試使用 helm-secret 插件部署一個 PostgreSQL 數(shù)據(jù)庫集群到我們的 Kubernetes 平臺上,來看看它是如何幫助我們保護我們的敏感信息不被泄漏的。

默認(rèn)情況下,PostgreSQL Chart 會為部署的 PostgreSQL 實例創(chuàng)建一個名為 postgres 的管理員賬號,并生成一個包含 10 位字符的隨機字符串作為它的密碼。我們可以通過為 Chart 設(shè)定 postgresqlUsernamepostgresqlPassword 的值,來手動指定管理員的用戶名和密碼信息。

  • 首先創(chuàng)建一個包含如下內(nèi)容的 secrets.yaml 文件:
postgresqlDatabase: my-database
postgresqlUsername: admin
postgresqlPassword: admin

該文件指定了為部署的 PostgreSQL 實例創(chuàng)建一個名為 admin 的管理員賬號,同時設(shè)定它的密碼為 admin

  • 嘗試直接使用 HELM 命令通過該 Values 文件做一次測試部署:
$ helm install postgresql stable/postgresql -f secrets.yaml --dry-run --debug

上面的命令中由于我們使用了 --dry-run 參數(shù),因此它只會將所有將要部署到 Kubernetes 平臺上到資源全部以 YAML 的格式輸出到屏幕上,而不會做真正的部署。

如果你仔細(xì)查看輸出的 YAML 信息,會發(fā)現(xiàn)該 Chart 會創(chuàng)建一個包含了一個名為 postgresql-password Key 的 Kubernetes Secret 資源,其值為 “YWRtaW4=”,使用命令 echo "YWRtaW4=" | base64 -d - 將該值進行 base64 轉(zhuǎn)譯之后輸出到屏幕上,我們會得到 “admin”,這說明我們在 secrets.yaml 文件中的配置已經(jīng)生效。

加密 secrets.yaml 文件

正如你所看到的那樣,PostgreSQL 的管理員用戶名和密碼都以明文的方式存儲在了 secrets.yaml 文件中。接下來,就讓我們使用 helm-secrets 插件的 enc 子命令對該文件進行加密:

$ helm secrets enc secrets.yaml

如果你直接執(zhí)行上面命令,有可能會和我一樣得到下面的錯誤信息:

Encrypting secrets.yaml
config file not found and no keys provided through command line options
Error: plugin "secrets" exited with error

該錯誤信息是由 SOPS 命令報錯的,它提示我們說,當(dāng)它嘗試加密文件時,即沒有在配置文件中找到加密時要使用的公鑰信息,也沒有在命令行中指定公鑰信息。換言之,就是 SOPS 不知道使用哪個 GPG 公鑰對文件進行加密操作。通過前面的學(xué)習(xí)我們知道,可通過 --pgp, -p 參數(shù)將密鑰對信息傳遞給 SOPS 命令,但由于這里是通過 helm-secrets 插件調(diào)用的 SOPS 命令,我們無法像使用 SOPS 命令本身那樣通過參數(shù)的方式傳遞信息。

其實 SOPS 命令還提供另外兩種設(shè)定 GPG 密鑰對信息的方式:通過設(shè)定環(huán)境變量和配置文件的方式來指定 GPG 密鑰對。

設(shè)定環(huán)境變量:

如果我們沒有在命令行通過 --pgp, -p 參數(shù)為 SOPS 指定密鑰信息,那么它則會嘗試從 SOPS_PGP_FP 系統(tǒng)環(huán)境變量中獲取該信息,因此我們可以將密鑰對 ID 指定給該環(huán)境變量:

$ export SOPS_PGP_FP=00E0160999E3C663

SOPS 配置文件:

SOPS 還支持另一種更加靈活的方式來指定密鑰信息 —— 配置文件。每當(dāng)執(zhí)行 SOPS 命令時,它都會在當(dāng)前目錄下查找名為 .sops.yaml 的文件作為它的配置文件,下面是一個最基本的 SOPS 配置文件:

creation_rules:
    - pgp: "13D525EEF0A5FA38F4E78F7900E0160999E3C663"

事實上,SOPS 的配置文件能做到的遠(yuǎn)遠(yuǎn)不止這些,我們可以在配置文件中設(shè)定多條規(guī)則,并為每條規(guī)則設(shè)定不同的密鑰信息,以達到不同的文件使用不同的密鑰進行加密和解密,更多關(guān)于 SOPS 配置信息,請參考 SOPS 文檔。

當(dāng)為 SOPS 配置好密鑰信息后,再次執(zhí)行 helm secrets enc secrets.yaml 命令重新為 secrets 文件加密。加密操作會講加密后的內(nèi)容將直接覆蓋掉原 secrets.yaml 文件中的內(nèi)容,查看加密后的 secrets.yaml 文件:

$ cat secrets.yaml

postgresqlDatabase: ENC[AES256_GCM,data:aZNFdHVIgJkWDiI=,iv:zsban/onWOllCou/lpgIUzZoIGlZAjTHcVmG+Xu+asI=,tag:lCbMEVCsR7Nhc+jBZTc1Ng==,type:str]
postgresqlUsername: ENC[AES256_GCM,data:/9ciQtc=,iv:+csoC+vx7wfT8WHrzECktG1UU/sVq+Q44zdJZHMPDaU=,tag:DHiCF1x7hyHnYi7gMFm3Lg==,type:str]
postgresqlPassword: ENC[AES256_GCM,data:9xAlAbg=,iv:EH+DmDZU9g/u6eCMkaNBDhxpPkDpX7HQrhcAFVPVqOw=,tag:snEhGpmkRAwjuVrxYHCOiA==,type:str]
sops:
    kms: []
    gcp_kms: []
    azure_kv: []
    lastmodified: '2020-04-24T04:56:24Z'
    mac: ENC[AES256_GCM,data:KQ5P2C55mdaUt1EFqV9411rXY7pi/dQlRQ/FcW6BqQe45u/ZqhCNR1VD8H2tZ4BRl1mQ4xOGzOYdzddKRc/D0vNHVyoEI4IRd2Jd+QnICINDwQ/Xq9kXysOSnV308DSV+EAabxreIDKdvV7RF3b5GGoEifXS8YDVhQmQjfGyhwU=,iv:sR2TI9W+1YAzfY5k82tnkrN4Q+vH3kxITGi9kzLOMq4=,tag:auUx5q6imy2nVfJLsBoGrg==,type:str]
    pgp:
    -   created_at: '2020-04-24T04:56:22Z'
        enc: |
            -----BEGIN PGP MESSAGE-----

            hQIMA8ebLzL57hqOAQ/+Oq3bVKIx8T9EqI1EyvBeuW2lN95MDAjZD/+77ntTixW/
            zNintG5dEPT9Uqi1mlwTCqZF9D1ptuQMgLgvddV/PPLG7afO60yy1kQW2+jGWons
            N0HuinVvESs7GCj+xMBd0cyKZ0iYqbafg4Mub60T0qX4/w9IuDV1o/vswceajmaC
            YkKF/ATMnLEV0UVVeXwzyVWFGrmworPWStyx9WgB3Vj0VEYGQPub6JzSRUyGdHVr
            2JljSKlTzAzlAUbcEvKCxjWWBypkvNTMua9AhMtYtagbRlcJuSFdOIAgbIVHW6Qd
            C06b/HL5+B8umeweN36g5BSjUiD8HmtpFEKBT92WKuYfRFijkCSME3VhVGvHm4Zo
            fPPLQRswf5dRu8IXBFW52/W36/ZgzzA1kqf1cGCTETMMQghxeRSuQU9caZ4L0UFm
            ZbXdB+w92XZjiNVR5EpA1hDLbBQVKqUjZ92dpmNql5bzKoBObT+p/7hb8ixNLc66
            EBgPbefbAdQBkwuelSdNIi2vfkSFVxMLDvsL5Zn8YLrEbjaresQ0rvugxIUj4190
            moZ/I08HmsfyC02xGReK0ZCmbWR/+NcSJJOqofNAFrK0ritcT8hUPN86VuhVS6xp
            NaT1FTLBCae8vqsn1FIK09f+u64hxfQiOBmtMQ7JrTG2xDo5BiHn+sydAdD6/I3S
            XgGLdaDg1ZPsT4peB56Qy1G8H2DlwGSmM+Drazfgvus+zyW8FaVNfIUbrydu1u2X
            79U4BXQhjhDDIXwf+ipttksfEEhpMN1JxzrLO7l9pYYe13/VRR1NmkI7p3eN+GM=
            =n0UG
            -----END PGP MESSAGE-----
        fp: 00E0160999E3C663
    unencrypted_suffix: _unencrypted
    version: 3.5.0

不難發(fā)現(xiàn),加密后的文件內(nèi)容與我們之前使用 sops 命令加密的文件內(nèi)容在格式上完全一致,這也正說明了 SOPS 是 helm-secret 插件背后真正的 “幕后使者”。

加密后的 secrets.yaml 文件將被用于部署我們的 Chart,且該文件也可以被自由分發(fā)、存儲到 Git 中去,因為我們只要確保 PGP 私鑰不被泄漏,就無需擔(dān)心該文件會被他人解密,從而導(dǎo)致敏感信息被泄漏的問題。

同樣,helm-secrets 插件也提供了用于解密的 dec 子命令:

$ helm secrets dec secrets.yaml

且與 SOPS 一樣,解密后的內(nèi)容將被存儲到新創(chuàng)建的 secrets.yaml.dec 文件中去。

你還可以使用 helm-secrets 插件提供的 view 子命令直接查看解密后的文件內(nèi)容:

$ helm secrets view secrets.yaml

postgresqlDatabase: my-database
postgresqlUsername: admin
postgresqlPassword: admin

當(dāng)生成好加密后的 secrets.yaml 文件后,就可以通過 helm-secrets 插件使用該文件進行部署工作了。

部署 PostgreSQL

helm-secrets 插件提供的 install 子命令用于部署 HELM Chart,而正如我們前面所講那樣,它僅僅是對 helm install 命令進行了一層封裝操作,因此用法與 helm install 命令完全一致:

$ helm secrets install postgresql stable/postgresql -f secrets.yaml

當(dāng)執(zhí)行以上命令時, helm-secrets 插件首先會對 secrets.yaml 文件中所有 Key 值進行解密操作,再將解密后的 YAML 文件傳遞給 helm install 命令進行部署。

你可以通過執(zhí)行命令 kubectl get secret --namespace default postgresql -o jsonpath="{.data.postgresql-password}" | base64 --decode 來查看剛剛部署的 PostgreSQL 實例的管理員密碼信息,來驗證密碼是否我們之前設(shè)定的 admin。

Values 文件名

不知你是否已經(jīng)注意到,在部署 PostgreSQL Chart 時,我們將所有自定義變量值全部保存到了一個名為 secrets.yaml 的文件中,而在通常情況下,我們都習(xí)慣于將這些自定義變量值保存到名為 values.yaml 的文件中去。

事實上,這是有意而為之的,因為 helm-secrets 插件僅僅會對 secrets.yaml 文件,以及任何以 secrets. 為前綴名的 YAML 進行解密,例如:

$ helm secrets install XXXX -f values.yaml -f secrets.yaml -f secrets.env.yaml

當(dāng)使用上面命令部署時,helm-secrets 插件僅僅會對 secrets.yamlsecrets.env.yaml 文件中的所有 Key 值進行解密操作,而保留 values.yaml 中的 Key 值不變。

另外需要切記的一點是,雖然 .yaml.yml 都可作為 YAML 類型文件的后綴來使用,但 helm-secret 只支持 .yaml 后綴,使用 .yml 作為后綴的文件將無法被解密。

在其它節(jié)點執(zhí)行部署操作

到目前為止,從創(chuàng)建 PGP 密鑰對,到對 secrets.yaml 文件的加密,在到部署 PostgreSQL 等等所有這一系列操作全部都在同一臺機器上完成。但當(dāng)團隊內(nèi)有其它成員需要與你一起開發(fā)和部署 Helm Chart,或者你希望可以在其它機器上做開發(fā)部署時,則你還需要了解如何導(dǎo)入與導(dǎo)出 PGP 密鑰對。

公鑰的導(dǎo)入與導(dǎo)出

通過前面對 PGP 的講解我們了解到,公鑰用于加密,私鑰用于解密。因此,你若希望其他人或在其它工作機器上也有能夠加密 Values 文件的能力,那么,你只需將你的 PGP 公鑰導(dǎo)入到他的工作電腦上即可。

導(dǎo)入 PGP 公鑰有兩種方式:一種是手動導(dǎo)出導(dǎo)入公鑰;另一種是上傳你的公鑰到公鑰服務(wù)器中,其他人則可以直接從公鑰服務(wù)器中導(dǎo)入你的公鑰。下面就讓我們分別看一下如何通過這兩種方式導(dǎo)入與導(dǎo)出你的公鑰。

手動導(dǎo)入導(dǎo)出公鑰

  1. 首先將公鑰導(dǎo)入到文件中:
$ gpg --export --armor "helm-secret@email.com" > helm.pub

該命令將公鑰導(dǎo)出到了名為 helm.pub 的文件中,將導(dǎo)出的公鑰傳遞給他人。

  1. 通過 import 命令導(dǎo)入到自己機器中即可:
$ gpg --import helm.pub

通過公鑰服務(wù)器導(dǎo)入與導(dǎo)出公鑰

為了便于導(dǎo)入他人公鑰,世界上存在許多公鑰服務(wù)器,專門用于存儲公鑰信息。任何人都可以上傳自己的公鑰到這些服務(wù)器上,以便他人下載使用。

  1. 上傳公鑰非常簡單,僅需指定要使用的服務(wù)器,以及要上傳的公鑰 ID 即可:
$ gpg --keyserver keyserver.ubuntu.com --send-key 00E0160999E3C663

該命令會將我們的公鑰 00E0160999E3C663 上傳到 keyserver.ubuntu.com 服務(wù)器上。

  1. 一旦將公鑰上傳到某個服務(wù)器之后,就可以從該服務(wù)器導(dǎo)入公鑰到本地電腦中:
$ gpg --keyserver keyserver.ubuntu.com --recv 00E0160999E3C663

gpg --keyserver keyserver.ubuntu.com --recv 00E0160999E3C663
gpg: key 00E0160999E3C663: public key "HELM Secret (Used for HELM Secret Plugin) <helm-secret@email.com>" imported
gpg: Total number processed: 1
gpg:               imported: 1

無論使用哪種導(dǎo)入方式,在導(dǎo)入完成后,你都應(yīng)該可以通過 gpg --list-keys 命令查看到剛剛導(dǎo)入都公鑰信息。

提示:導(dǎo)入公鑰僅僅使你擁有了加密的能力,因此你無法在只導(dǎo)入了公鑰的機器上使用 helm-secrets 進行解密或部署操作。

私鑰的導(dǎo)入與導(dǎo)出

與加密流程類似,若你希望其他人或在其它工作機器上能夠解密你的 Values 文件,那么你則需要將你的私鑰導(dǎo)入到其它的工作機器上。私鑰的導(dǎo)入與導(dǎo)出只能通過手動方式完成:

$ gpg --export-secret-key -a "helm-secret@email.com" > helm

我們首先使用 --export-secret-key 命令將私鑰導(dǎo)入到了 helm 文件中,將該文件通過安全的方式傳遞給需要的人之后,使用下面命令再次導(dǎo)入即可:

$ gpg --import helm

gpg: key 00E0160999E3C663: "HELM Secret (Used for HELM Secret Plugin) <helm-secret@email.com>" not changed
gpg: key 00E0160999E3C663: secret key imported
gpg: Total number processed: 1
gpg:              unchanged: 1
gpg:       secret keys read: 1
gpg:   secret keys imported: 1

當(dāng)私鑰導(dǎo)入成功后,即可通過 gpg --list-secret-keys 命令查看當(dāng)前系統(tǒng)中的私鑰信息。

導(dǎo)入私鑰,就意味著當(dāng)前所在機器擁有了解密的能力,同樣也就意味著擁有了部署的能力。

提示:私鑰用于解密操作,因此你可以在導(dǎo)入了私鑰的機器上使用 helm-secrets 進行部署。但是,你若想修改 Values 文件并加密,同樣需要確保你正確地導(dǎo)入了公鑰。

再次提醒,擁有私鑰就等于擁有了解密的能力,因此,一定要確保私鑰的安全而不被泄密。

結(jié)束語

源碼中泄漏用戶名密碼等敏感信息的事件頻頻發(fā)送,工具只是手段,最重要的是時刻保持警惕的頭腦。

最后的最后,你可以通過依次執(zhí)行以下命令進行清理操作:

# 刪除 PostgreSQL 部署
$ helm delete postgresql

# 刪除 PGP 密鑰對
$ gpg --delete-secret-key 00E0160999E3C663
$ gpg --delete-key 00E0160999E3C663

# 刪除所有 Values 文件
$ rm -rf secrets*.yaml*
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容