如何使用外部机密操作员 (ESO) 访问 Kubernetes 内部的保险库机密

_作者选择DISTICATION in Tech Fund]接受捐赠,作为WRITE FOR DONSITIONS计划)的一部分。

在Kubernetes中,您可以在Pod中使用secrets,以避免将连接字符串和其他敏感数据保留在源代码管理中,或者防止您的应用程序直接访问敏感数据。将机密存储在HashiCorp存储库是一种允许访问所需工具的安全方式)中。秘密存储通常提供诸如HTTPAPI之类的功能来安全地与它们交互。像vault这样的工具通常也提供了与Kubernetes集成的方法,例如通过使用sidecars.然而,这种方法和这些工具与Kubernetes集成的其他方式的一个缺点是,它们通常是特定于应用程序的,并创建了与工具的紧密耦合,您可能希望避免这种情况,以便在需要时可以轻松地切换机密提供程序。

External Secrets Operator(ESO)是一个Kubernetes操作符,它添加了几个自定义资源定义(CRD),并允许您使用原生Kubernetes secrets资源。它通过创建Kubernetes秘密并将其与位于秘密提供商中的指定秘密保持同步来实现这一点,无论是HashiCorp Vault,AWS Secrets Manager,GCP Secrets Manager还是任何其他受支持的提供商。该系统的主要好处是,通过引用本地Kubernetes秘密,任何使用Kubernetes中秘密的服务都与这些工具解耦。这种分离使您可以更轻松地更改支持提供程序,而无需更改任何其他内容。

在本教程中,您将在DigitalOcean管理的Kubernetes集群中安装Extra Secrets运算符,并设置一个SecretStore和一个ExternalSecres来从HashiCorp Vault实例取值。

最后,您将拥有一个可以工作的设置,在该设置中,您可以从外部Secrets操作符支持的任何提供者获取要在Kubernetes集群内部使用的秘密。

与任何管理敏感信息的服务一样,在类似生产的环境中使用之前,您应该考虑阅读有关Vault展开最佳做法的其他文档。例如,文件库的生产强化guide涵盖了策略、根令牌和审计等主题。

如果您正在寻找托管Kubernetes托管服务,查看我们为growth.构建的简单托管Kubernetes服务

前提条件

要完成本教程,您需要:

第一步-安装外部秘密操作器(ESO)

在本步骤中,您将通过Helm将外部Secrets操作符安装到您的Kubernetes集群中。由于您将使用Helm安装External Secrets操作符,因此需要确保正确设置了Kubernetes上下文。

要进行此设置,首先从您的Kubernetes集群的DigitalOcean Cloud控制面板下载您的Kubeconfig文件。在概述 选项卡中,找到** 配置** 部分,选择** 下载配置文件** 按钮。文件名为<clustername>-kubeconfig.yaml。您可以将该文件放在任何位置,但建议的位置是~/.kube文件夹。然后,使用以下命令之一将环境变量KUBECONFIG设置为等于文件的路径。

在Linux或Mac上,您可以运行以下命令:

1export KUBECONFIG=/home/sammy/.kube/clustername-kubeconfig.yaml

在Windows的PowerShell中,您可以使用以下命令:

1$env:KUBECONFIG = "C:\Users\sammy\.kube\clustername-kubeconfig.yaml"

接下来,通过运行以下命令确认您的当前上下文:

1kubectl config current-context

您的输出将如下所示:

1[label Output]
2my-k8s-cluster

设置好当前上下文后,您可以向Helm添加外部秘密存储库:

1helm repo add external-secrets https://charts.external-secrets.io

输出将如下所示:

1[label Output]
2"external-secrets" has been added to your repositories

接下来,确保你有最新的回购:

1helm repo update

您的输出将类似于以下内容:

1[label Output]
2...Successfully got an update from the "external-secrets" chart repository

添加完repo后,您可以使用Helm安装您添加的外部机密存储库

1helm install external-secrets \
2    external-secrets/external-secrets \
3    -n external-secrets \
4    --create-namespace \
5    --set installCRDs=true

通过-n外部秘密库选项,可以指定外部秘密库应该安装在外部秘密库命名空间中。如果使用--create-nampace,如果命名空间不存在,则会创建该命名空间。最后,将--set installCRDS设置为true,以确保外部秘密的自定义资源定义操作符与其一起安装。

您的输出将如下所示:

 1[label Output]
 2NAME: external-secrets
 3LAST DEPLOYED: {Date goes here}
 4NAMESPACE: external-secrets
 5STATUS: deployed
 6REVISION: 1
 7TEST SUITE: None
 8NOTES:
 9external-secrets has been deployed successfully!
10
11In order to begin using ExternalSecrets, you will need to set up a SecretStore
12or ClusterSecretStore resource (for example, by creating a 'vault' SecretStore).
13
14More information on the different types of SecretStores and how to configure them
15can be found in our Github: https://github.com/external-secrets/external-secrets

在本步骤中,您通过Helm将External Secrets运算符安装到您的Kubernetes集群中,这将允许您创建一个SecretStore和一个ExternalSecret。在下一步中,您将创建一个SecretStore

Step 2 -创建Secret Store

在本步骤中,您将创建一个SecretStore,它是外部Secrets运算符用来存储有关如何与给定的秘密提供者通信的信息。但在您使用外部秘密操作符之前,您需要在Kubernetes中添加您的保险库令牌,以便外部秘密操作员可以与秘密提供者通信。

作为先决条件的一部分,您可能已经学习了教程How to Secure Management Secrets with HashiCorp Vault on Ubuntu 20.04,》,该教程生成了一个用于身份验证的存储库令牌。在此步骤中,您可以使用通过解封Vault获得的根令牌(不建议用于生产),也可以使用本教程步骤5中的令牌,该步骤介绍如何在Vault中创建授权策略。

<$>[警告] 警告: 出于本教程的目的,您可以使用初始化Vault时提供的令牌,但不建议将其用于生产。最佳做法是设置更安全的外部机密操作符以供实际使用。您可以阅读存储库产品documentation.]中支持的不同身份验证方法 <$>

您将把这个令牌作为秘密放在Kubernetes中,以便外部Secrets操作员可以使用它与Vault进行通信。您可以通过运行以下命令来执行此操作,并将突出显示的部分替换为您的存储区令牌:

1kubectl create secret generic vault-token --from-literal=token=YOUR_VAULT_TOKEN

您的输出如下所示:

1[label Output]
2secret/vault-token created

您可以通过运行以下命令来验证这一点,该命令将获取default命名空间中的所有机密(除非您在前面的命令中添加了命名空间,否则您的命名空间将位于该命名空间中):

1kubectl get secrets

输出将如下所示:

1NAME TYPE DATA AGE
2vault-token Opaque 1 2m

创建了此秘密后,您可以开始使用外部秘密操作符。第一步是建立一个SecretStore,它保存联系秘密提供者的信息,并标识要使用哪个提供者。同一命名空间中的任何外部机密都可以访问机密存储,因此请确保根据需要对您的命名空间进行分段。在本教程中,您将把所有内容都放在default命名空间中,但对于生产集群,不建议这样做。

使用Nan或您喜欢的文本编辑器,创建一个ret-store.yaml文件,并在其中粘贴以下内容。请务必填写特定于您的设置的数据,例如server字段,这是可以访问您的Vault服务器的端点:

 1[label secret-store.yaml]
 2apiVersion: external-secrets.io/v1beta1
 3kind: SecretStore
 4metadata:
 5  name: vault-backend
 6spec:
 7  provider:
 8    vault:
 9      server: "https://your-domain:8200"
10      path: "kv"
11      version: "v1"
12      auth:
13        tokenSecretRef:
14          name: "vault-token"
15          key: "token"

Provider字段下,您可以使用server字段指定avult作为提供者,以及在哪里可以找到它。您还可以指定路径kv,这是您的密钥所在的根路径。如果您按照《存储库先决条件》教程操作,但将您的SecretStore命名为kv以外的其他名称,请确保相应地更改该字段。

KV引擎的v1默认开启。如果您在开启kv引擎时更改了其在文件库中的版本,您也可以指定版本为v2

最后一个字段是auth部分,您可以通过提供秘密的名称和令牌所在的秘密内部的密钥来指定您之前创建的秘密。要了解有关电子仓库的其他身份验证方法的详细信息,请查看产品documentation.

如果您有兴趣了解更多关于SecretStores提供的其他配置选项,您可以在外部秘密产品documentation,中找到CRD规范,它包含了所有可以提供的字段,以及Kubernetes添加的其他一些可以在添加后获取的字段。

保存并关闭该文件。

通过运行以下命令创建SecretStore

1kubectl apply -f ./secret-store.yaml

此命令将此CRD应用于您的集群并创建对象。您可以通过运行以下命令来查看该对象,该命令将显示Kubernetes内部有关该对象的所有信息:

1kubectl get SecretStore vault-backend -o yaml

您的输出将如下所示:

 1[label Output]
 2apiVersion: external-secrets.io/v1alpha1
 3kind: SecretStore
 4metadata:
 5  annotations:
 6    # Some kubernetes annotations
 7  creationTimestamp: # Timestamp of the creation time
 8  generation: 1
 9  name: vault-backend
10  namespace: default
11  resourceVersion: "12345"
12  uid: # a UID for the resource
13spec:
14  provider:
15    vault:
16      auth:
17        tokenSecretRef:
18          key: token
19          name: vault-token
20          namespace: default
21      path: kv
22      server: https://your-domain:8200
23      version: v1
24status:
25  conditions:
26    - type: Ready
27      status: "False"
28      reason: "ConfigError"
29      message: "SecretStore validation failed"
30      lastTransitionTime: "0000-00-00T00:00:00Z"

如果您成功创建了SecretStore,您将不会看到status字段,但如果您看到type:ReadyStatus:False``,则asonesMessage字段将提供有关错误的更多信息。一个非常常见的问题是无法创建客户端。这通常意味着您的客户端的身份验证方法失败了,因为SecretStore会尝试为您的提供商创建一个客户端来验证一切是否正常。对于本教程中的令牌身份验证方法,请务必检查您的SecretStore资源是否具有正确的密钥命名空间,以及名称和密钥是否与您创建的内容完全匹配。

疑难解答

根据文件库的设置方式,您在创建SecretStore时可能会遇到一些错误。其中最常见的是Message:Unable to Valify Store。这可能是几件事,但有几件事您可以检查,特别是如果您使用必备教程安装了Vault并安全地创建了一个秘密。

首先,您将告诉Vault侦听所有传入的请求,以便您可以通过更改Vault配置文件来远程访问它。如果您遵循了必备的库教程,那么您将更改/etc/vault.d/vault.hcl文件。

使用Nan或您喜欢的文本编辑器,打开/etc/vault.d/vault.hcl进行编辑。在listenertcp``部分下的配置文件中,检查地址。如果地址为127.0.0.1:8200,则改为0.0.0.0:8200,如图:

1[label /etc/vault.d/vault.hcl]
2...
3listener "tcp" {
4  address       = "0.0.0.0:8200"
5...
6}

此更改告诉Vault侦听外部连接,以便您可以从外部机密操作符访问它。重新启动Vault(确保再次解封),现在它应该接受外部连接。

第二个问题可能是防火墙阻止端口8200上的连接,该问题可以通过更新防火墙来修复:

1ufw allow 8200

<$>[警告] 警告: 这将在端口8200上向全世界开放文件库,如果没有安全防范措施,建议不要生产。请务必阅读文件库生产Hardening],以确保文件库实例已针对不良行为进行了加固。 <$>

在本节中,您在Kubernetes中创建了一个密钥,以保存有关如何向密钥提供者进行身份验证的信息。然后,您创建了一个SecretStore资源,告诉外部秘密操作员如何联系您的提供商。在下一步中,您将创建一个ExternalSecret

第三步-创建外部密钥

在本步骤中,您将创建一个ExternalSecret,它是External Secrets运算符中的主要资源。ExternalSecret资源告诉ESO从特定的SecretStore中获取特定的秘密,以及将信息放在哪里。此资源非常重要,因为它定义了您希望从外部密钥提供程序获取什么密钥、将其放置在何处、使用哪个密钥存储以及同步密钥的频率,以及其他几个选项。

要创建一个ExternalSecret,首先创建一个名为external-secret.yaml的文件,并添加以下代码:

 1[label external-secret.yaml]
 2apiVersion: external-secrets.io/v1alpha1
 3kind: ExternalSecret
 4metadata:
 5  name: my-cool-secret
 6spec:
 7  refreshInterval: "15s" # How often this secret is synchronized
 8  secretStoreRef:
 9    name: vault-backend
10    kind: SecretStore
11  target: # Our target Kubernetes Secret
12    name: my-cool-new-secret # If not present, then the secretKey field under data will be used
13    creationPolicy: Owner # This will create the secret if it doesn't exist
14  data:
15    - secretKey: my-cool-new-secret-key
16      remoteRef:
17        key: message # This is the remote key in the secret provider (might change in meaning based on your provider)
18        property: value # The property inside of the secret inside your secret provider

在这里,您创建了一个ExternalSecret,它引用了上一步中的SecretStore。在"target)中的位置,包含以下属性:

  • askKey:这是您要填充的Kubernetes密钥中的密钥。
  • emoteRef.key:这是密钥提供者内部的密钥。例如,在Vault中,您可以将机密放置在不同路径中。在这里,您可以使用类似于my文件夹/Coolsecrets/mysecu这样的值作为值。
  • emoteRef.Property:这是emoteRef.key中指定的路径所在秘密中的属性,您想要放在askKey中指定的key中。

data字段是YAML中的一个数组,因此您可以指定多个要放入单个Kubernetes密钥中的密钥。外部机密操作符还提供了一些高级模板逻辑,您可以使用它们来构建连接字符串之类的东西,您可以在Products documentation](https://external-secrets.io/v0.4.4/guides-templating/).的[高级模板]部分阅读更多关于这些内容的内容您也可以通过接口外部秘密引用docs.]来阅读ExternalSecres周围的所有字段和选项

完成后保存并关闭文件。

接下来,使用以下命令创建此资源:

1kubectl apply -f ./external-secret.yaml

在应用它之后,您可以通过运行以下命令来确保一切正常:

1kubectl get ExternalSecret my-cool-secret

您的输出将如下所示:

1[label Output]
2NAME STORE REFRESH INTERVAL STATUS
3my-cool-secret vault-backend 15s SecretSynced

输出确认ExternalSecret资源创建成功。

疑难解答

如果之前的输出在STATUS下有`Sync Error‘,请确保您的SecretStore设置正确。您可以通过运行以下命令来查看实际错误:

1kubectl get ExternalSecret my-cool-secret -o yaml

您的输出将类似于以下内容,它将提供有关错误的更多信息:

 1[label Output]
 2apiVersion: external-secrets.io/v1alpha1
 3kind: ExternalSecret
 4metadata:
 5  name: my-cool-secret
 6spec:
 7  refreshInterval: "15s"
 8  secretStoreRef:
 9    name: vault-backend
10    kind: SecretStore
11  target:
12    name: my-cool-new-secret
13    creationPolicy: Owner
14  data:
15    - secretKey: my-cool-new-secret-key
16      remoteRef:
17        key: test-secret
18        property: my-cool
19status:
20  # refreshTime is the time and date the external secret was fetched and
21  # the target secret updated
22  refreshTime: "2019-08-12T12:33:02Z"
23  # Standard condition schema
24  conditions:
25    # ExternalSecret ready condition indicates the secret is ready for use.
26    # This is defined as:
27    # - The target secret exists
28    # - The target secret has been refreshed within the last refreshInterval
29    # - The target secret content is up-to-date based on any target templates
30    - type: Ready
31      status: "True" # False if last refresh was not successful
32      reason: "SecretSynced"
33      message: "Secret was synced"
34      lastTransitionTime: "2019-08-12T12:33:02Z"

在此输出中,您将看到status字段,可能还会看到一些额外的注释(您可以忽略这些注释,因为它们通常是关于资源的元数据)。在status部分,您可以看到ExternalSecret是否已经正确同步,或者是否出了问题。

在本步骤中,您创建了一个ExternalSecret资源。ExternalSecret资源允许您在您的Secret提供程序中指定要获取的值,以及将它们放在Kubernetes中的位置。有关更多高级功能,您可以查看外部秘密产品documentation.

结论

现在您已经成功地在您的Kubernetes集群中设置了External Secrets运算符,并部署了SecretStoreExternalSecret,您可以部署任何其他您想要的秘密了。

外部秘密操作员还有许多其他功能和自定义资源,允许您以最适合您的需要的方式设置您的Kubernetes集群。此外,HashiCorp Vault不是唯一的提供商,其设置类似于本教程中介绍的内容。您可以从外部机密文档.)了解更多信息

Kubernetes中的这种秘密方法是强大的和可扩展的,因为operator是开源的,并且允许您为秘密使用各种提供者,而不必担心任何使用秘密的特定提供者。

最后,还有其他资源可以探索。其中一个是ExterExternalSecret,这是External Secrets Operator 0.5.0版本中新增的。此资源允许您定义一个ExternalSecret,然后让操作员在与您定义的选择器匹配的每个命名空间中创建此ExternalSecret。您可以阅读更多关于此功能的信息在产品文档中。另一个资源是SecretterSecretStore,它允许来自任何命名空间的ExternalSecret访问它(而普通的SecretStore只能在它所在的同一命名空间中访问)。

Published At
Categories with 技术
comments powered by Disqus