×

重新创建加密密钥的加密机制基于存储在节点上的盲密钥和相关Tang服务器的私钥。为了防止攻击者获取Tang服务器私钥和节点加密磁盘的可能性,建议定期重新设置密钥。

您必须在从Tang服务器删除旧密钥之前,对每个节点执行重新设置密钥操作。以下部分提供了重新设置密钥和删除旧密钥的过程。

备份Tang服务器的密钥

Tang服务器使用/usr/libexec/tangd-keygen生成新密钥,并默认将其存储在/var/db/tang目录中。为了在发生故障时恢复Tang服务器,请备份此目录。密钥是敏感信息,因为它们能够执行已使用它们的全部主机的启动磁盘解密,因此必须相应地保护密钥。

步骤
  • 将备份密钥从/var/db/tang目录复制到临时目录,以便您可以从中恢复密钥。

恢复Tang服务器密钥

您可以通过访问备份中的密钥来恢复Tang服务器的密钥。

步骤
  • 将密钥从备份文件夹恢复到/var/db/tang/目录。

    Tang服务器启动时,会通告并使用这些恢复的密钥。

重新设置Tang服务器密钥

此过程以三台具有唯一密钥的Tang服务器为例。

使用冗余的Tang服务器可以降低节点无法自动启动的可能性。

重新设置Tang服务器及其所有关联的NBDE加密节点的密钥是一个三步过程。

先决条件
  • 在一个或多个节点上安装有效的网络绑定磁盘加密 (NBDE)。

步骤
  1. 生成新的Tang服务器密钥。

  2. 重新设置所有NBDE加密节点的密钥,使其使用新密钥。

  3. 删除旧的Tang服务器密钥。

    在所有NBDE加密节点完成密钥重新设置之前删除旧密钥会导致这些节点过度依赖任何其他已配置的Tang服务器。

Rekeying a Tang server
图1. 重新设置Tang服务器密钥的工作流程示例

生成新的Tang服务器密钥

先决条件
  • 运行Tang服务器的Linux机器上的root shell。

  • 为了方便验证Tang服务器密钥轮换,请使用旧密钥加密一个小测试文件。

    # echo plaintext | clevis encrypt tang '{"url":"https://127.0.0.1:7500”}' -y >/tmp/encrypted.oldkey
  • 验证加密是否成功以及文件是否可以解密以生成相同的字符串plaintext

    # clevis decrypt </tmp/encrypted.oldkey
步骤
  1. 找到并访问存储Tang服务器密钥的目录。这通常是/var/db/tang目录。检查当前通告的密钥指纹。

    # tang-show-keys 7500
    示例输出
    36AHjNH3NZDSnlONLz1-V4ie6t8
  2. 进入Tang服务器密钥目录

    # cd /var/db/tang/
  3. 列出当前的Tang服务器密钥

    # ls -A1
    示例输出
    36AHjNH3NZDSnlONLz1-V4ie6t8.jwk
    gJZiNPMLRBnyo_ZKfK4_5SrnHYo.jwk

    在正常的Tang服务器操作期间,此目录中有两个.jwk文件:一个用于签名和验证,另一个用于密钥派生。

  4. 禁用旧密钥的通告

    # for key in *.jwk; do \
      mv -- "$key" ".$key"; \
    done

    设置网络绑定磁盘加密 (NBDE) 或请求密钥的新客户端将不再看到旧密钥。现有客户端仍然可以访问和使用旧密钥,直到它们被删除。Tang服务器读取但不会通告存储在以.字符开头的UNIX隐藏文件中的密钥。

  5. 生成新密钥

    # /usr/libexec/tangd-keygen /var/db/tang
  6. 列出当前的Tang服务器密钥以验证旧密钥不再通告(因为它们现在是隐藏文件),并且存在新密钥。

    # ls -A1
    示例输出
    .36AHjNH3NZDSnlONLz1-V4ie6t8.jwk
    .gJZiNPMLRBnyo_ZKfK4_5SrnHYo.jwk
    Bp8XjITceWSN_7XFfW7WfJDTomE.jwk
    WOjQYkyK7DxY_T5pMncMO5w0f6E.jwk

    Tang会自动通告新密钥。

    较新的Tang服务器安装程序包含一个辅助/usr/libexec/tangd-rotate-keys目录,该目录可以同时处理禁用通告和生成新密钥。

  7. 如果您在共享相同密钥材料的负载均衡器后面运行多个Tang服务器,请确保在继续之前正确同步此处所做的更改。

验证
  1. 验证Tang服务器是否正在通告新密钥,以及是否未通告旧密钥。

    # tang-show-keys 7500
    示例输出
    WOjQYkyK7DxY_T5pMncMO5w0f6E
  2. 验证旧密钥虽然未通告,但仍可用于解密请求。

    # clevis decrypt </tmp/encrypted.oldkey

重新设置所有NBDE节点的密钥

您可以使用DaemonSet对象重新设置远程集群上的所有节点的密钥,而不会对远程集群造成任何停机时间。

如果节点在重新设置密钥期间断电,则它可能无法启动,必须通过Red Hat Advanced Cluster Management (RHACM)或GitOps管道重新部署。

先决条件
  • 对所有具有网络绑定磁盘加密 (NBDE) 节点的集群具有cluster-admin访问权限。

  • 所有Tang服务器都必须可访问正在重新设置密钥的每个NBDE节点,即使Tang服务器的密钥没有更改。

  • 获取每个Tang服务器的Tang服务器URL和密钥指纹。

步骤
  1. 根据以下模板创建DaemonSet对象。此模板设置了三个冗余的Tang服务器,但可以轻松适应其他情况。更改NEW_TANG_PIN环境中的Tang服务器URL和指纹以适合您的环境。

    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      name: tang-rekey
      namespace: openshift-machine-config-operator
    spec:
      selector:
        matchLabels:
          name: tang-rekey
      template:
        metadata:
          labels:
            name: tang-rekey
        spec:
          containers:
          - name: tang-rekey
            image: registry.access.redhat.com/ubi9/ubi-minimal:latest
            imagePullPolicy: IfNotPresent
            command:
            - "/sbin/chroot"
            - "/host"
            - "/bin/bash"
            - "-ec"
            args:
            - |
              rm -f /tmp/rekey-complete || true
              echo "Current tang pin:"
              clevis-luks-list -d $ROOT_DEV -s 1
              echo "Applying new tang pin: $NEW_TANG_PIN"
              clevis-luks-edit -f -d $ROOT_DEV -s 1 -c "$NEW_TANG_PIN"
              echo "Pin applied successfully"
              touch /tmp/rekey-complete
              sleep infinity
            readinessProbe:
              exec:
                command:
                - cat
                - /host/tmp/rekey-complete
              initialDelaySeconds: 30
              periodSeconds: 10
            env:
            - name: ROOT_DEV
              value: /dev/disk/by-partlabel/root
            - name: NEW_TANG_PIN
              value: >-
                {"t":1,"pins":{"tang":[
                  {"url":"http://tangserver01:7500","thp":"WOjQYkyK7DxY_T5pMncMO5w0f6E"},
                  {"url":"http://tangserver02:7500","thp":"I5Ynh2JefoAO3tNH9TgI4obIaXI"},
                  {"url":"http://tangserver03:7500","thp":"38qWZVeDKzCPG9pHLqKzs6k1ons"}
                ]}}
            volumeMounts:
            - name: hostroot
              mountPath: /host
            securityContext:
              privileged: true
          volumes:
          - name: hostroot
            hostPath:
              path: /
          nodeSelector:
            kubernetes.io/os: linux
          priorityClassName: system-node-critical
          restartPolicy: Always
          serviceAccount: machine-config-daemon
          serviceAccountName: machine-config-daemon

    在这种情况下,即使您正在重新设置tangserver01的密钥,也必须不仅指定tangserver01的新指纹,还必须指定所有其他Tang服务器的当前指纹。未能为重新设置密钥操作指定所有指纹会增加中间人攻击的机会。

  2. 要将守护程序集分发到必须重新设置密钥的每个集群,请运行以下命令。

    $ oc apply -f tang-rekey.yaml

    但是,为了大规模运行,请将守护程序集包装在ACM策略中。此ACM配置必须包含一个用于部署守护程序集的策略,一个用于检查所有守护程序集Pod是否为READY的策略,以及一个将其应用于适当集群集的放置规则。

验证守护程序集已成功重新设置所有服务器的密钥后,删除守护程序集。如果您不删除守护程序集,则必须在下次重新设置密钥操作之前删除它。

验证

分发守护程序集后,监控守护程序集以确保重新设置密钥已成功完成。示例守护程序集中的脚本如果重新设置密钥失败则以错误终止,如果成功则保持CURRENT状态。还有一个就绪探针,当重新设置密钥成功完成后,会将Pod标记为READY

  • 这是重新设置密钥完成之前守护程序集输出列表的示例。

    $ oc get -n openshift-machine-config-operator ds tang-rekey
    示例输出
    NAME         DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
    tang-rekey   1         1         0       1            0           kubernetes.io/os=linux   11s
  • 这是重新设置密钥成功完成之后守护程序集输出列表的示例。

    $ oc get -n openshift-machine-config-operator ds tang-rekey
    示例输出
    NAME         DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
    tang-rekey   1         1         1       1            1           kubernetes.io/os=linux   13h

重新设置密钥通常需要几分钟才能完成。

如果您使用ACM策略将守护程序集分发到多个集群,则必须包含一个合规性策略,该策略检查每个守护程序集的READY计数是否等于DESIRED计数。这样,对这种策略的合规性证明所有守护程序集Pod均为READY,并且重新设置密钥已成功完成。您还可以使用ACM搜索来查询所有守护程序集的状态。

对Tang服务器的临时重新设置密钥错误进行故障排除

要确定重新设置Tang服务器密钥的错误条件是否为临时性,请执行以下步骤。临时错误条件可能包括:

  • 临时网络中断

  • Tang服务器维护

通常,当发生这些类型的临时错误条件时,您可以等到守护程序集成功解决错误,或者您可以删除守护程序集,并在解决临时错误条件之前不要重试。

步骤
  1. 使用正常的Kubernetes Pod重启策略重启执行重新设置密钥操作的Pod。

  2. 如果任何关联的Tang服务器不可用,请尝试重新设置密钥,直到所有服务器重新上线。

对Tang服务器的永久重新设置密钥错误进行故障排除

如果在重新设置Tang服务器密钥后,经过较长时间READY计数仍不等于DESIRED计数,则可能表示永久性故障条件。在这种情况下,可能适用以下条件:

  • NEW_TANG_PIN定义中的Tang服务器URL或指纹存在错别字。

  • Tang服务器已停用或密钥永久丢失。

先决条件
  • 此过程中显示的命令可以在Tang服务器或任何可以访问Tang服务器的Linux系统上运行。

步骤
  1. 通过对每个Tang服务器的配置(如守护程序集中定义)执行简单的加密和解密操作来验证Tang服务器配置。

    这是一个使用错误指纹的加密和解密尝试示例。

    $ echo "okay" | clevis encrypt tang \
      '{"url":"http://tangserver02:7500","thp":"badthumbprint"}' | \
      clevis decrypt
    示例输出
    Unable to fetch advertisement: 'http://tangserver02:7500/adv/badthumbprint'!

    这是一个使用正确指纹的加密和解密尝试示例。

    $ echo "okay" | clevis encrypt tang \
      '{"url":"http://tangserver03:7500","thp":"goodthumbprint"}' | \
      clevis decrypt
    示例输出
    okay
  2. 确定根本原因后,请解决根本问题。

    1. 删除无效的守护程序集。

    2. 编辑守护程序集定义以修复根本问题。这可能包括以下任何操作:

      • 编辑Tang服务器条目以更正URL和指纹。

      • 移除不再服务的Tang服务器。

      • 添加一台新的Tang服务器,替换已停用的服务器。

  3. 再次分发更新后的守护进程集。

在配置中替换、移除或添加Tang服务器时,只要至少有一台原始服务器仍在运行(包括当前正在重新加密的服务器),重新加密操作就会成功。如果所有原始Tang服务器都无法运行或无法恢复,则系统无法恢复,您必须重新部署受影响的节点。

验证

检查守护进程集中的每个Pod的日志,以确定重新加密是否成功完成。如果重新加密不成功,日志可能会指示故障原因。

  1. 找到守护进程集创建的容器名称。

    $ oc get pods -A | grep tang-rekey
    示例输出
    openshift-machine-config-operator  tang-rekey-7ks6h  1/1  Running   20 (8m39s ago)  89m
  2. 打印容器的日志。以下日志来自已完成的成功重新加密操作。

    $ oc logs tang-rekey-7ks6h
    示例输出
    Current tang pin:
    1: sss '{"t":1,"pins":{"tang":[{"url":"http://10.46.55.192:7500"},{"url":"http://10.46.55.192:7501"},{"url":"http://10.46.55.192:7502"}]}}'
    Applying new tang pin: {"t":1,"pins":{"tang":[
      {"url":"http://tangserver01:7500","thp":"WOjQYkyK7DxY_T5pMncMO5w0f6E"},
      {"url":"http://tangserver02:7500","thp":"I5Ynh2JefoAO3tNH9TgI4obIaXI"},
      {"url":"http://tangserver03:7500","thp":"38qWZVeDKzCPG9pHLqKzs6k1ons"}
    ]}}
    Updating binding...
    Binding edited successfully
    Pin applied successfully

删除旧的Tang服务器密钥

先决条件
  • 运行Tang服务器的Linux机器上的root shell。

步骤
  1. 找到并访问存储Tang服务器密钥的目录。这通常是/var/db/tang目录。

    # cd /var/db/tang/
  2. 列出当前的Tang服务器密钥,显示已公布和未公布的密钥。

    # ls -A1
    示例输出
    .36AHjNH3NZDSnlONLz1-V4ie6t8.jwk
    .gJZiNPMLRBnyo_ZKfK4_5SrnHYo.jwk
    Bp8XjITceWSN_7XFfW7WfJDTomE.jwk
    WOjQYkyK7DxY_T5pMncMO5w0f6E.jwk
  3. 删除旧密钥。

    # rm .*.jwk
  4. 列出当前的Tang服务器密钥,以验证未公布的密钥不再存在。

    # ls -A1
    示例输出
    Bp8XjITceWSN_7XFfW7WfJDTomE.jwk
    WOjQYkyK7DxY_T5pMncMO5w0f6E.jwk
验证

此时,服务器仍然公布新的密钥,但尝试使用旧密钥解密将会失败。

  1. 查询Tang服务器以获取当前已公布的密钥指纹。

    # tang-show-keys 7500
    示例输出
    WOjQYkyK7DxY_T5pMncMO5w0f6E
  2. 解密之前创建的测试文件,以验证使用旧密钥解密是否失败。

    # clevis decrypt </tmp/encryptValidation
    示例输出
    Error communicating with the server!

如果您在负载均衡器后面运行多台共享相同密钥材料的Tang服务器,请确保在继续操作之前,所做的更改已正确同步到所有服务器。