利用 1Password 保护 kubectl 凭证

直接将凭证(token 或证书)写入 Kubectl 配置文件(`~/.kube/config`)有些不安全,本文将凭证存入 1Password 中,并利用 exec 功能动态从 1Password 读取凭证(读取的过程中,1Password 会弹出二次确认信息)来保证不会轻易泄漏配置文件

不使用 1Password?Mac 用户也可以将信息存入 Keychain 然后使用 security 命令行工具读取大体操作与本文类似

准备配置文件

首先准备一份可以直接使用的配置文件,包括 cluster user context 节,例如

apiVersion: v1 clusters: - cluster: certificate-authority-data: DATA+OMITTED server: https://127.0.0.1:6443 name: default contexts: - context: cluster: default user: default name: default current-context: default kind: Config preferences: {} users: - name: default user: client-certificate-data: DATA+OMITTED client-key-data: DATA+OMITTED

我们只需要对 user 进行修改 —— 将 client-certificate-dataclient-key-data 变为动态读取(如果不是证书认证,这里则是 token

生成凭证描述 JSON

将用户凭证的部分单独提取出来(类似如下的部分,在原始配置的 users[0].user 下)

client-certificate-data: DATA+OMITTED client-key-data: DATA+OMITTED

利用这一部分自行准备一份 JSON,类似于

{ "apiVersion": "client.authentication.k8s.io/v1beta1", "kind": "ExecCredential", "spec": { "interactive": false }, "status": { "clientCertificateData": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----\n", "clientKeyData": "-----BEGIN EC PRIVATE KEY-----\n...\n-----END EC PRIVATE KEY-----\n" } }

注意这里面的 status.clientCertificateDatastatus.clientKeyData 分别是由原来配置中的 yaml 的 client-certificate-dataclient-key-data 进行 base64 Decode 得来

(如果你不是使用证书认证而是使用 token,这里直接粘贴原始的 token 原文即可)

可以利用如下 JS 进行转换

import { parse } from 'yaml' import {z} from 'zod' const schema = z.object({ 'client-certificate-data': z.string(), 'client-key-data': z.string() }) export async function main(input: string) { const obj = schema.parse(parse(input)) const clientCertificateData = atob(obj['client-certificate-data']); const clientKeyData = atob(obj['client-key-data']); const result = { apiVersion: 'client.authentication.k8s.io/v1beta1', kind: "ExecCredential", spec: { interactive: false, }, status: { clientCertificateData, clientKeyData } } return JSON.stringify(result) }

存储到 1Password

创建一个 1Password 条目,新建一个密码类型的字段(假设明明为 k8s config)写入前一步准备的凭证 JSON,复制这个项目的 Private Share Link

image-20250104-122848.png

得到一行类似 https://start.1password.com/open/i?a=AAA&v=VVV&i=III 的链接,利用其中的 VVV(代表 Vault ID)和 III (代表 Item ID)的部分,构造一个 URL op://VVV/III/k8s config 备用(后面的 k8s config 和你的字段名称保持一致)

在命令行中输入 op read 'op://VVV/III/k8s config' 测试下能否正常读取到前面配置的 JSON

修改 kubeconfig

修改你的 kubeconfig 文件,将原来的

user: client-certificate-data: DATA+OMITTED client-key-data: DATA+OMITTED

替换成

user: exec: apiVersion: client.authentication.k8s.io/v1beta1 command: op args: - read - 'op://VVV/III/k8s config' interactiveMode: Always provideClusterInfo: false

即可