diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..3bb178b
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,17 @@
+version: 2
+updates:
+ - package-ecosystem: gomod
+ directory: /
+ open-pull-requests-limit: 10
+ schedule:
+ interval: weekly
+ - package-ecosystem: github-actions
+ directory: /
+ open-pull-requests-limit: 5
+ schedule:
+ interval: weekly
+ - package-ecosystem: docker
+ directory: /
+ open-pull-requests-limit: 5
+ schedule:
+ interval: weekly
\ No newline at end of file
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
new file mode 100644
index 0000000..db3fb03
--- /dev/null
+++ b/.github/workflows/test.yml
@@ -0,0 +1,51 @@
+name: Test
+
+on:
+ push:
+ pull_request:
+
+jobs:
+ golangci:
+ name: lint
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+ - name: Set up Go
+ uses: actions/setup-go@v4
+ with:
+ go-version: 1.19
+ check-latest: true
+ cache: true
+ - name: golangci-lint
+ uses: golangci/golangci-lint-action@v3.2.0
+ with:
+ version: latest
+ skip-pkg-cache: true
+ args: --verbose
+ go-security-scan:
+ runs-on: ubuntu-latest
+ env:
+ GO111MODULE: on
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+
+ - name: Run Gosec Security Scanner
+ uses: securego/gosec@master
+ with:
+ args: '-no-fail -exclude-dir=pkg/apis -exclude-dir=ack-secret-manager-cli ./...'
+
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Set up Go
+ uses: actions/setup-go@v4
+ with:
+ go-version: 1.19
+ env:
+ GOPATH: ${{ env.HOME }}
+
+ - name: Build
+ run: make build
\ No newline at end of file
diff --git a/README-zh_CN.md b/README-zh_CN.md
index 94dbd6e..e190b95 100644
--- a/README-zh_CN.md
+++ b/README-zh_CN.md
@@ -2,58 +2,55 @@
# ACK Secret Manager
-[ack-secret-manager](https://github.com/AliyunContainerService/ack-secret-manager) 可以帮助您将存储在[阿里云KMS凭据管家](https://www.alibabacloud.com/help/zh/doc-detail/152001.html) 中的密钥凭据以K8s原生Secret对象的形式导入到集群中并实现密钥数据的自动同步,您可以在应用Pod中以挂载Secret等形式将存储在凭据管家中的密文引入到应用程序中使用,避免敏感数据在应用开发构建流程中的传播和泄露。
+[English](./README.md) | 简体中文
+[ack-secret-manager](https://github.com/AliyunContainerService/ack-secret-manager) 可以帮助您将存储在[阿里云KMS凭据管家](https://www.alibabacloud.com/help/zh/doc-detail/152001.html) 中的密钥凭据以K8s原生Secret对象的形式导入到集群中并实现密钥数据的自动同步,您可以在应用Pod中以挂载Secret等形式将存储在凭据管家中的密文引入到应用程序中使用,避免敏感数据在应用开发构建流程中的传播和泄露。
## 安装
-确保当前账号有足够的权限访问阿里云凭据管家服务,ack-secret-manager 支持共享网关和专属网关两种方式同步凭据管家的凭据。
-
-1. 设置共享网关访问权限,这里有两种方式:
-
- - 在集群对应的 WorkerRole 中添加权限
+1. 请确保组件使用的凭据有足够的权限访问阿里云凭据管家服务,可以使用如下两种配置方式,推荐使用RRSA方式,实现Pod维度的授权。
- - 登录容器服务控制台
+ - 在集群对应的 WorkerRole 中添加权限
- - 选择对应集群进入到集群详情页
+ - 登录容器服务控制台
- - 在集群信息中选择**集群资源**页,点击Worker RAM角色中对应的命名为**KubernetesWorkerRole-xxxxxxxxxxxxxxx** 的角色名称,会自动导航到RAM角色对应的控制台页面
+ - 选择对应集群进入到集群详情页
- - 点击添加权限按钮,创建自定义权限策略,策略内容如下:
+ - 在集群信息中选择**集群资源**页,点击Worker RAM角色中对应的命名为**KubernetesWorkerRole-xxxxxxxxxxxxxxx** 的角色名称,会自动导航到RAM角色对应的控制台页面
- ```json
- {
- "Action": [
- "kms:GetSecretValue",
- "kms:Decrypt"
- ],
- "Resource": [
- "*"
- ],
- "Effect": "Allow"
- }
- ```
+ - 点击添加权限按钮,创建自定义权限策略,策略内容如下:
- - 绑定上面创建的自定义策略给集群对应的WorkerRole
+ ```json
+ {
+ "Action": [
+ "kms:GetSecretValue",
+ "kms:Decrypt"
+ ],
+ "Resource": [
+ "*"
+ ],
+ "Effect": "Allow"
+ }
+ ```
- - 通过 [RRSA方式](https://help.aliyun.com/document_detail/356611.html) 实现Pod维度的授权
+ - 绑定上面创建的自定义策略给集群对应的WorkerRole
- * [启用RRSA功能](https://help.aliyun.com/document_detail/356611.html#section-ywl-59g-j8h)
+ - . 通过 [RRSA方式](https://help.aliyun.com/document_detail/356611.html) 实现Pod维度的授权
- * [使用RRSA功能](https://help.aliyun.com/document_detail/356611.html#section-rmr-eeh-878) :为指定的 serviceaccount 创建对应的 RAM 角色,为 RAM 角色设置信任策略,并为 RAM 角色授权
+ * [启用RRSA功能](https://help.aliyun.com/document_detail/356611.html#section-ywl-59g-j8h)
-2. 设置专属网关访问权限,详情见[通过应用接入点访问KMS实例](https://help.aliyun.com/document_detail/604467.html?spm=a2c4g.2252257.0.0.7f047495H2lmEh)
+ * [使用RRSA功能](https://help.aliyun.com/document_detail/356611.html#section-rmr-eeh-878) :为指定的 serviceaccount 创建对应的 RAM 角色,为 RAM 角色设置信任策略,并为 RAM 角色授权
-3. 登录到容器服务控制台
+2. 登录到容器服务控制台
- * 在左侧导航栏选择**市场** -> **应用市场**,在搜索栏中输入ack-secret-manager,选择进入到应用页面;
+ * 在左侧导航栏选择**市场** -> **应用市场**,在搜索栏中输入ack-secret-manager,选择进入到应用页面;
- * 选择需要安装的目标集群和命名空间、发布名称;
+ * 选择需要安装的目标集群和命名空间、发布名称;
- * 在参数配置页面进行自定义参数配置,包括 values.yaml 中的`rrsa.enable`以及配置 `envVarsFromSecret` 中的相关参数,参数说明参见下方的**配置说明**;
+ * 在参数配置页面进行自定义参数配置,包括 values.yaml 中的`rrsa.enable`以及配置 `envVarsFromSecret` 中的相关参数,参数说明参见下方的**配置说明**;
- * 点击**确定**按钮完成安装。
+ * 点击**确定**按钮完成安装。
## 升级
@@ -111,9 +108,7 @@
## 使用说明
-下文会在阿里云 KMS 凭据管家中添加一个测试凭据,并分别通过专属网关以及共享网关两种方式进行凭据同步,并展示部分扩展功能
-
-ack-secret-manager 涉及了两种 CRD,SecretStore 用于存放访问凭据(例如 RRSA ,ClientKey,AK 配置等),ExternalSecret 用于存放需要同步的凭据基础信息(如凭据名称,版本等)以及指定 SecretStore,保证了权限与数据分离,增强使用灵活性。具体介绍见下方 **CRD 配置介绍**
+ack-secret-manager 包含两种 CRD,其中SecretStore 用于存放访问凭据(例如 RRSA ,ClientKey,AK 配置等),ExternalSecret 用于存放需要同步的凭据基础信息(如凭据名称,版本等)以及指定 SecretStore,保证了权限与数据分离,增强使用灵活性。具体介绍 [CRD参数配置指导](doc/crd.md)
1. 创建凭据
@@ -125,365 +120,196 @@ ack-secret-manager 涉及了两种 CRD,SecretStore 用于存放访问凭据(
VersionId: v1
```
-2. 共享网关
+2. 创建SecretStore & ExternalSecret
前提:给集群开启 RRSA,并且正确配置相关 RAM Role 权限
- - 创建 SecretStore 的测试实例,测试模板如下,需对部分字段进行替换
+ 创建 SecretStore 的测试实例,测试模板如下,需对部分字段进行替换
```yaml
- apiVersion: 'alibabacloud.com/v1alpha1'
- kind: SecretStore
- metadata:
- name: scdemo
- spec:
- KMS:
- KMSAuth:
- oidcProviderARN: "acs:ram::{accountID}:oidc-provider/ack-rrsa-{clusterID}"
- ramRoleARN: "acs:ram::{accountID}:role/{roleName}"
+ apiVersion: 'alibabacloud.com/v1alpha1'
+ kind: SecretStore
+ metadata:
+ name: scdemo
+ spec:
+ KMS:
+ KMSAuth:
+ oidcProviderARN: "acs:ram::{accountID}:oidc-provider/ack-rrsa-{clusterID}"
+ ramRoleARN: "acs:ram::{accountID}:role/{roleName}"
```
- - 创建ExternalSecret的测试实例,测试模板如下:
+ 创建名称为`hello-service-external-secret.yml`的ExternalSecret的测试模版文件,测试模板如下:
```yaml
- apiVersion: 'alibabacloud.com/v1alpha1'
- kind: ExternalSecret
- metadata:
- name: esdemo
- spec:
- data: #无需特殊处理的数据源
- - key: test1 # kms 凭据名称
- name: test1 # 存入 secret 字段
- versionId: v1 #kms 凭据版本
- secretStoreRef:
- name: scdemo
- namespace: default
+ apiVersion: 'alibabacloud.com/v1alpha1'
+ kind: ExternalSecret
+ metadata:
+ name: esdemo
+ spec:
+ data: #无需特殊处理的数据源
+ - key: test1 # kms 凭据名称
+ name: test1 # 存入 secret 字段
+ versionId: v1 #kms 凭据版本
+ secretStoreRef:
+ name: scdemo
+ namespace: default
```
- - 执行命令创建externalsecret测试实例:
+ 执行命令创建externalsecret测试实例:
```sh
- kubectl apply -f hello-service-external-secret.yml
+ kubectl apply -f hello-service-external-secret.yml
```
- - 查看目标secret是否创建成功:
+ 查看目标secret是否创建成功:
```sh
- kubectl get secret esdemo -oyaml
+ kubectl get secret esdemo -oyaml
```
- - 如果创建成功,查看secret内容如下:
+ 如果创建成功,查看secret内容如下:
```yaml
- apiVersion: v1
- data:
- test1: eyJuYW1lIjoidG9tIiwiYWdlIjoiMTQiLCJmcmllbmRzIjpbeyJuYW1lIjoibGlsaSJ9LHsibmFtZSI6ImVkZiJ9XX0=
- kind: Secret
- metadata:
- creationTimestamp: "2023-10-09T13:03:09Z"
- labels:
- lastUpdatedAt: 2023-10-09T13.03.09Z
- name: esdemo
- namespace: default
- resourceVersion: "7311947"
- uid: 163c6a33-0bee-40b6-8ffe-6897277036cd
- type: Opaque
+ apiVersion: v1
+ data:
+ test1: eyJuYW1lIjoidG9tIiwiYWdlIjoiMTQiLCJmcmllbmRzIjpbeyJuYW1lIjoibGlsaSJ9LHsibmFtZSI6ImVkZiJ9XX0=
+ kind: Secret
+ metadata:
+ name: esdemo
+ namespace: default
+ type: Opaque
```
- - 在没有关闭自动同步配置的前提下,可以修改KMS凭据管家中的密钥内容,等待片刻后查看目标secret是否已经完成同步
+ 在没有关闭自动同步配置的前提下,可以修改KMS凭据管家中的密钥内容,等待片刻后查看目标secret是否已经完成同步
- - 如果您希望解析一个 JSON 格式的 secret 并将其中指定的 key-value 对同步到 k8s secret 中,可以使用`jmesPath`字段。以下是一个使用 `jmesPath` 字段的样例,我们将其部署在集群中
+ 另外ack-secret-manager支持跨账号同步凭据,在 `SecretStore.Spec.KMS.KMSAuth` 中配置 `remoteRamRoleArn`,`remoteRamRoleSessionName` 即可,以下为样例 SecretStore:
```yaml
- apiVersion: 'alibabacloud.com/v1alpha1'
- kind: ExternalSecret
- metadata:
- name: es-json-demo
- spec:
- data: #无需特殊处理的数据源
- - key: test1 # kms 凭据名称
- name: test1 # 存入 secret 字段
- versionId: v1 #kms 凭据版本
- secretStoreRef:
- name: scdemo
- namespace: default
- jmesPath: # 解析 json 串中的部分字段
- - path: "name"
- objectAlias: "name"
- - path: "friends[0].name"
- objectAlias: "friendname"
+ apiVersion: 'alibabacloud.com/v1alpha1'
+ kind: SecretStore
+ metadata:
+ name: scdemo
+ spec:
+ KMS:
+ KMSAuth:
+ oidcProviderARN: "acs:ram::{accountID}:oidc-provider/ack-rrsa-{clusterID}"
+ ramRoleARN: "acs:ram::{accountID}:role/{roleName}"
+ remoteRamRoleArn: "acs:ram::{accountID}:role/{roleName}"
+ remoteRamRoleSessionName: ""
```
- - 部署后检查 secret 是否创建成功
- ```sh
- kubectl get secret es-json-demo -oyaml
- ```
+3. JSON凭据解析
- - 同步成功即可看到如下结果
+ 如果您希望解析一个 JSON 格式的 secret 并将其中指定的 key-value 对同步到 k8s secret 中,可以使用`jmesPath`字段。以下是一个使用 `jmesPath` 字段的样例,我们将其部署在集群中
```yaml
- apiVersion: v1
- data:
- friendname: bGlsaQ==
- name: dG9t
- kind: Secret
- metadata:
- creationTimestamp: "2023-10-09T13:11:05Z"
- labels:
- lastUpdatedAt: 2023-10-09T13.11.05Z
- name: es-json-demo
- namespace: default
- resourceVersion: "7313940"
- uid: 18d84558-f526-4ff5-ab9a-720ec1861c30
- type: Opaque
- ```
-
- - 当您使用`jmesPath`字段时,必需指定下面两个子字段:
-
- - `path`: 必需项,基于 [JMES path](https://jmespath.org/specification.html) 规范解析 json 中的指定字段
-
- - `objectAlias`: 必需项,用于指定解析出的字段同步到 k8s secret 中的 key 名称
-
- - 共享网关当前支持跨账号同步凭据,在 `SecretStore.Spec.KMS.KMSAuth` 中配置 `remoteRamRoleArn`,`remoteRamRoleSessionName` 即可,以下为样例 SecretStore
-
- ```yaml
- apiVersion: 'alibabacloud.com/v1alpha1'
- kind: SecretStore
- metadata:
- name: scdemo
- spec:
- KMS:
- KMSAuth:
- oidcProviderARN: "acs:ram::{accountID}:oidc-provider/ack-rrsa-{clusterID}"
- ramRoleARN: "acs:ram::{accountID}:role/{roleName}"
- remoteRamRoleArn: "acs:ram::{accountID}:role/{roleName}"
- remoteRamRoleSessionName: ""
+ apiVersion: 'alibabacloud.com/v1alpha1'
+ kind: ExternalSecret
+ metadata:
+ name: es-json-demo
+ spec:
+ data: #无需特殊处理的数据源
+ - key: test1 # kms 凭据名称
+ name: test1 # 存入 secret 字段
+ versionId: v1 #kms 凭据版本
+ secretStoreRef:
+ name: scdemo
+ namespace: default
+ jmesPath: # 解析 json 串中的部分字段
+ - path: "name"
+ objectAlias: "name"
+ - path: "friends[0].name"
+ objectAlias: "friendname"
```
-
+ 当您使用`jmesPath`字段时,必需指定下面两个子字段:
-3. 专属网关
+ - `path`: 必需项,基于 [JMES path](https://jmespath.org/specification.html) 规范解析 json 中的指定字段
- 前提:已在 KMS 控制台创建应用接入点,并在应用接入点中创建 ClientKey,ClientKey 正确配置了关于凭据 test1 的权限
+ - `objectAlias`: 必需项,用于指定解析出的字段同步到 k8s secret 中的 key 名称
- - 在集群中创建 ClientKeyContent,Password 等相关字段的 secret
- ```yaml
- apiVersion: v1
- data:
- clientkey: {{ Client Key File Content }}
- password: {{ Password }}
- kind: Secret
- metadata:
- name: clientkey
- namespace: kube-system
- type: Opaque
- ```
-
- - 创建 SecretStore 实例
-
- ```yaml
- apiVersion: 'alibabacloud.com/v1alpha1'
- kind: SecretStore
- metadata:
- name: dkms-client
- spec:
- KMS:
- dedicatedKMSAuth:
- protocol: "https"
- endpoint: {{ kms Instance ID }}
- ignoreSSL: true
- clientKeyContent:
- name: clientkey
- namespace: kube-system
- key: clientkey
- password:
- name: clientkey
- namespace: kube-system
- key: password
- ```
+部署后检查 secret 是否创建成功
- - 创建 ExternalSecret 实例,SecretStoreRef 选择 default/dkms-client
-
- ```yaml
- apiVersion: 'alibabacloud.com/v1alpha1'
- kind: ExternalSecret
- metadata:
- name: es-dkms-demo
- spec:
- data: #无需特殊处理的数据源
- - key: test1 # kms 凭据名称
- name: dkms # 存入 secret 字段
- versionId: v1 #kms 凭据版本
- secretStoreRef:
- name: dkms-client
- namespace: default
- ```
-
- - 同步成功即可看到如下结果
-
- ```yaml
- apiVersion: v1
- data:
- dkms: eyJuYW1lIjoidG9tIiwiYWdlIjoiMTQiLCJmcmllbmRzIjpbeyJuYW1lIjoibGlsaSJ9LHsibmFtZSI6ImVkZiJ9XX0g
- kind: Secret
- metadata:
- creationTimestamp: "2023-10-09T13:59:24Z"
- labels:
- lastUpdatedAt: 2023-10-09T13.59.24Z
- name: es-dkms-demo
- namespace: default
- resourceVersion: "7326124"
- uid: 4773959c-d90a-44c6-bf88-094855802683
- type: Opaque
- ```
-
- - 如果您想将 JSON 凭据解析后再存放入 secret 中,但又不知道凭据的具体结构,可以采用自解析功能,即 dataProcess.Extract 字段。并且可以针对解析后的字段键进行规则替换,即 dataProcss.replaceRule 字段,防止不规则的 secret data key 导致无法创建 secret,以下为样例 ExternalSecret
-
- ```yaml
- apiVersion: 'alibabacloud.com/v1alpha1'
- kind: ExternalSecret
- metadata:
- name: extract-secret
- spec:
- dataProcess:
- - extract:
- key: test1
- name: extract
- versionId: v1
- secretStoreRef:
- name: dkms-client
- namespace: default
- replaceRule:
- - source: "^n.*e$" #替换 以n开头以e结尾 的 key 为 alibabacloud
- target: "alibabacloud"
- - source: "^f.*s$"
- target: "ack"
+ ```sh
+ kubectl get secret es-json-demo -oyaml
```
- - 同步成功即可看到如下结果,JSON 凭据被解析为三部分,且各自的键根据 replaceRule 规则进行了替换
+同步成功即可看到如下结果
```yaml
apiVersion: v1
data:
- ack: W3sibmFtZSI6ImxpbGkifSx7Im5hbWUiOiJlZGYifV0=
- age: IjE0Ig==
- alibabacloud: InRvbSI=
+ friendname: bGlsaQ==
+ name: dG9t
kind: Secret
metadata:
- creationTimestamp: "2023-10-09T14:07:35Z"
+ creationTimestamp: "2023-10-09T13:11:05Z"
labels:
- lastUpdatedAt: 2023-10-09T14.07.35Z
- name: extract-secret
+ lastUpdatedAt: 2023-10-09T13.11.05Z
+ name: es-json-demo
namespace: default
- resourceVersion: "7328187"
- uid: a3ab5278-02bd-4544-bae7-b502acccfe3c
+ resourceVersion: "7313940"
+ uid: 18d84558-f526-4ff5-ab9a-720ec1861c30
type: Opaque
```
-## CRD 配置介绍
-
-### ExternalSecret
-
-**spec**
-
-| crd 字段 | 描述 | 是否必选 |
-| ----------- | ------------------------------------------ | -------- |
-| provider | 获取 secret 的目标云产品(如 KMS 等) | 否 |
-| data | 数据源(目标数据的标识) | 否 |
-| dataProcess | 需要进行特殊加工的数据源(目标数据的标识) | 否 |
-| type | k8s secret 类型(Opaque等) | 否 |
-
-**data(无需经过特殊处理的数据源)**
-
-| crd 字段 | 描述 | 是否必选 |
-| -------------- | ------------------------------------------------------------ | -------- |
-| key | 目标 secret 的唯一标识(例如 KMS 凭据的 key) | 是 |
-| name | 在集群 secret data 中对应的 key | 否 |
-| versionStage | 目标 secret 版本状态 | 否 |
-| versionId | 目标 secret 版本号 | 否 |
-| jmesPath | 如果目标 secret 为 json 类型,可指定获取 json 中特定 key 对应的 value | 否 |
-| secretStoreRef | 引用的 SecretStore 信息 | 否 |
-
-**dataProcess(需要进行特殊处理的数据源)**
-
-| crd 字段 | 描述 | 是否必选 |
-| ----------- | ------------------------------------------------------------ | -------- |
-| extract | 针对目标 secret 进行 json 解析,不需要用户指定 json key | 否 |
-| replaceRule | 根据特定规则替换经过 json 解析的 secret 的 key,防止非法 key 不能存入 k8s secret | 否 |
-
-**replaceRule(用于进行 Secret Key 内容替换)**
-
-| crd 字段 | 描述 | 是否必选 |
-| -------- | ------------------------------------ | -------- |
-| target | 用于替换的字符串 | 是 |
-| source | 需要被替换的字符串,可以为正则表达式 | 是 |
-
-**jmesPath**
-
-| crd 字段 | 描述 | 是否必选 |
-| ----------- | ------------------------------- | -------- |
-| path | jmes 表达式,用户指定 json key | 是 |
-| objectAlias | 存入 k8s secret 对应的 data key | 是 |
-**secretStoreRef**
-
-| crd 字段 | 描述 | 是否必选 |
-| --------- | ---------------------------- | -------- |
-| name | 指定的 SecretStore name | 是 |
-| namespace | 指定的 SecretStore namespace | 是 |
-
-### SecretStore
-
-**spec**
-
-| crd 字段 | 描述 | 是否必选 |
-| -------- | ------------------- | -------- |
-| KMS | 代表目标云产品为KMS | 否 |
-
-**KMS**
-
-| crd 字段 | 描述 | 是否必选 |
-| ---------------- | --------------------------- | -------- |
-| KMSAuth | 共享网关下访问 KMS 所需凭证 | 否 |
-| dedicatedKMSAuth | 专属网关下访问 KMS 所需凭证 | 否 |
-
-**KMSAuth**
-
-| crd 字段 | 描述 | 是否必选 |
-| ------------------------ | ---------------------------- | -------- |
-| accessKey | 用户AK | 否 |
-| accessKeySecret | 用户SK | 否 |
-| ramRoleARN | ram 角色 arn | 否 |
-| ramRoleSessionName | 角色会话名 | 否 |
-| oidcProviderARN | oidc 提供商 arn | 否 |
-| oidcTokenFilePath | 暂时无用 | 否 |
-| remoteRamRoleArn | 跨账号 ram 角色 arn | 否 |
-| remoteRamRoleSessionName | 跨账号 ram 角色 session name | 否 |
-
-**dedicatedKMSAuth**
-
-| crd 字段 | 描述 | 是否必选 |
-| ---------------- | ----------------------------- | -------- |
-| protocol | 传输协议(https) | 是 |
-| endpoint | kms 实例 ID | 是 |
-| ca | 用户根CA,base64编码 | 否 |
-| ignoreSSL | 是否忽略 ssl 认证 | 否 |
-| clientKeyContent | 专属网关 client key file 内容 | 是 |
-| password | client key 加密口令 | 是 |
-
-**SecretRef(敏感访问凭据存放在 K8S secret 中)**
-
-| crd 字段 | 描述 | 是否必选 |
-| --------- | ------------------------ | -------- |
-| name | k8s secret 名称 | 是 |
-| namespace | k8s secret 所在namaspace | 是 |
-| key | k8s secret 数据对应的key | 是 |
+
+
+- dataProcess
+
+ 如果您想将 JSON 凭据解析后再存放入 secret 中,但又不知道凭据的具体结构,可以采用自解析功能,即 dataProcess.Extract 字段。并且可以针对解析后的字段键进行规则替换,即 dataProcss.replaceRule 字段,防止不规则的 secret data key 导致无法创建 secret,以下为样例 ExternalSecret
+
+ ```yaml
+ apiVersion: 'alibabacloud.com/v1alpha1'
+ kind: ExternalSecret
+ metadata:
+ name: extract-secret
+ spec:
+ dataProcess:
+ - extract:
+ key: test1
+ name: extract
+ versionId: v1
+ secretStoreRef:
+ name: dkms-client
+ namespace: default
+ replaceRule:
+ - source: "^n.*e$" #替换 以n开头以e结尾 的 key 为 alibabacloud
+ target: "alibabacloud"
+ - source: "^f.*s$"
+ target: "ack"
+ ```
+
+ 同步成功即可看到如下结果,JSON 凭据被解析为三部分,且各自的键根据 replaceRule 规则进行了替换
+
+ ```yaml
+ apiVersion: v1
+ data:
+ ack: W3sibmFtZSI6ImxpbGkifSx7Im5hbWUiOiJlZGYifV0=
+ age: IjE0Ig==
+ alibabacloud: InRvbSI=
+ kind: Secret
+ metadata:
+ creationTimestamp: "2023-10-09T14:07:35Z"
+ labels:
+ lastUpdatedAt: 2023-10-09T14.07.35Z
+ name: extract-secret
+ namespace: default
+ resourceVersion: "7328187"
+ uid: a3ab5278-02bd-4544-bae7-b502acccfe3c
+ type: Opaque
+ ```
+
+## 安全
+对于发现的安全漏洞,请发送邮件至**kubernetes-security@service.aliyun.com**,您可在[SECURITY.md](./SECURITY.md)文件中找到更多信息。
## Release Note
| 版本号 | 变更时间 | 变更内容 |
| ------- | -------------- | ------------------------------------------------------------ |
| `0.4.0` | 2022年12月22日 | 支持基于JMES解析提取JSON格式的密文字段 |
-| `0.5.0` | 2023年10月10日 | 1.支持专属版 KMS 凭据同步
2.多阿里云访问凭据管理
3.凭据自解析与键规则替换
4.共享版 KMS 跨账号凭据同步 |
\ No newline at end of file
+| `0.5.0` | 2023年10月10日 | 1.支持专属版 KMS 凭据同步
2.多阿里云访问凭据管理
3.凭据自解析与键规则替换
4.共享版 KMS 跨账号凭据同步 |
+
diff --git a/README.md b/README.md
index 7f972b5..2c690e4 100644
--- a/README.md
+++ b/README.md
@@ -2,56 +2,57 @@
English | [简体中文](./README-zh_CN.md)
-[ack-secret-manager](https://github.com/AliyunContainerService/ack-secret-manager) can help you import key credentials stored in [Alibaba Cloud KMS Secrets Manager](https://www.alibabacloud.com/help/en/key-management-service) into the cluster in the form of Kubernetes native Secret objects and achieve automatic synchronization of key data, you can introduce the ciphertext stored in the Secrets Manager into the application in the form of mounting Secret in the application Pod to avoid the spread of sensitive data in the application development and construction process and leaks.
+[ack-secret-manager](https://github.com/AliyunContainerService/ack-secret-manager) can help you import ciphertext stored in [Alibaba Cloud KMS Secrets Manager](https://www.alibabacloud.com/help/en/key-management-service) into the cluster in the form of Kubernetes native Secret objects and achieve automatic synchronization of key data, you can securely inject the ciphertext, which is stored in the Secrets Manager, into your application by mounting a Secret within the application's Pod. This practice helps to prevent the leakage and proliferation of sensitive data throughout the application supply chain.
## Install
-Make sure that the current account has sufficient permissions to access the Alibaba Cloud KMS Secrets Manager. ack-secret-manager supports two methods: shared KMS and dedicated KMS to synchronize the Secrets Manager's credentials.
+1. Please make sure that the credentials used by the ack-secret-manager have enough permissions to access the Alibaba Cloud KMS Secrets Manager. You can use the following two configuration methods, and we recommend you to use the second **RRSA** method to achieve authorization in the Pod level.
-1. There are two ways to set shared KMS access permissions:
+- Add permissions to the WorkerRole corresponding to the cluster
- - Add permissions to the WorkerRole corresponding to the cluster
+ - Log in to the Container Service console
- - Log in to the Container Service console
+ - Select the cluster to enter the cluster details page
- - Select the cluster to enter the cluster details page
+ - Navigate to the **Cluster Resources** page in the cluster information. Once there, click on the Worker RAM role with the corresponding name **KubernetesWorkerRole-xxxxxxxxxxxxxxx**. This will automatically take you to the console page associated with the RAM role.
- - Navigate to the **Cluster Resources** page in the cluster information. Once there, click on the Worker RAM role with the corresponding name **KubernetesWorkerRole-xxxxxxxxxxxxxxx**. This will automatically take you to the console page associated with the RAM role.
+ - Add kms RAM policy below into the policy bind to the worker role
- - Add kms RAM policy below into the policy bind to the worker role
+ ```json
+ {
+ "Action": [
+ "kms:GetSecretValue",
+ "kms:Decrypt"
+ ],
+ "Resource": [
+ "*"
+ ],
+ "Effect": "Allow"
+ }
+ ```
- ```json
- {
- "Action": [
- "kms:GetSecretValue",
- "kms:Decrypt"
- ],
- "Resource": [
- "*"
- ],
- "Effect": "Allow"
- }
- ```
- - Implement Pod dimension authorization through [RRSA method](https://www.alibabacloud.com/help/en/ack/ack-managed-and-ack-dedicated/user-guide/use-rrsa-to-authorize-pods-to-access-different-cloud-services)
+- Implement Pod dimension authorization through [RRSA method](https://www.alibabacloud.com/help/en/ack/ack-managed-and-ack-dedicated/user-guide/use-rrsa-to-authorize-pods-to-access-different-cloud-services)
- * [Enable RRSA functionality](https://www.alibabacloud.com/help/en/container-service-for-kubernetes/latest/use-rrsa-to-enforce-access-control#section-ywl-59g-j8h)
+ * [Enable RRSA functionality](https://www.alibabacloud.com/help/en/container-service-for-kubernetes/latest/use-rrsa-to-enforce-access-control#section-ywl-59g-j8h)
- * [Use RRSA function](https://www.alibabacloud.com/help/en/container-service-for-kubernetes/latest/use-rrsa-to-enforce-access-control#section-rmr-eeh-878): Create the corresponding RAM role for the specified serviceaccount, set the trust policy for the RAM role, and authorize the RAM role
+ * [Use RRSA function](https://www.alibabacloud.com/help/en/container-service-for-kubernetes/latest/use-rrsa-to-enforce-access-control#section-rmr-eeh-878): Create the corresponding RAM role for the specified serviceaccount, set the trust policy for the RAM role, and authorize the RAM role
-2. Set dedicated KMS access permissions. For details, see [Access a KMS instance by using an AAP](https://www.alibabacloud.com/help/en/key-management-service/latest/aap?spm=a2c63.l28256.0.0.2d881b76SOifvo)
+2. Log in to the Container Service console
-3. Log in to the Container Service console
+ * Select **Marketplace** -> **Marketplace** in the left navigation bar, enter **ack-secret-manager** in the search bar, and select to enter the application page;
- * Select **Marketplace** -> **Marketplace** in the left navigation bar, enter **ack-secret-manager** in the search bar, and select to enter the application page;
- * Select the target cluster, namespace, and release name to be installed;
+ * Select the target cluster, namespace, and release name to be installed;
- * Configure custom parameters on the parameter configuration page, including `rrsa.enable` in values.yaml and related parameters in `envVarsFromSecret`. For parameter descriptions, see the **configuration instructions** below;
- * Click the **OK** button to complete the installation.
+ * Configure custom parameters on the parameter configuration page, including `rrsa.enable` in values.yaml and related parameters in `envVarsFromSecret`. For parameter descriptions, see the **configuration instructions** below;
+
+
+ * Click the **OK** button to complete the installation.
+
## Upgrade
@@ -111,7 +112,7 @@ Make sure that the current account has sufficient permissions to access the Alib
The following will add a test credential in Alibaba Cloud KMS Secrets Manager, synchronize the credentials through dedicated KMS and shared KMS, and demonstrate some extended functions.
-ack-secret-manager involves two CRDs. SecretStore is used to store access credentials (such as RRSA configuration, ClientKey, AK configuration, etc.), and ExternalSecret is used to store basic credential information that needs to be synchronized (such as credential name, version, etc.) and specify the SecretStore. It ensures the separation of permissions and data and enhances the flexibility of use. See below for details **CRD configuration introduction**
+ack-secret-manager involves two CRDs. SecretStore is used to store access credentials (such as RRSA configuration, ClientKey, AK configuration, etc.), and ExternalSecret is used to store basic credential information that needs to be synchronized (such as credential name, version, etc.) and specify the SecretStore. It helps to enhance the isolation of credentials permission and the usability. Please check the [parameters guide](doc/crd.md)
1. Create credentials
@@ -123,11 +124,11 @@ ack-secret-manager involves two CRDs. SecretStore is used to store access creden
VersionId: v1
```
-2. Shared KMS
+2. Create SecretStore & ExternalSecret
Prerequisite: Enable RRSA for the cluster and correctly configure the relevant RAM Role permissions
- - Create a test instance of SecretStore. The test template is as follows. Some fields need to be replaced.
+ Create a test instance of SecretStore. The test template is as follows. Some fields need to be replaced.
```yaml
apiVersion: 'alibabacloud.com/v1alpha1'
@@ -141,7 +142,7 @@ ack-secret-manager involves two CRDs. SecretStore is used to store access creden
ramRoleARN: "acs:ram::{accountID}:role/{roleName}"
```
- - Create a test instance of ExternalSecret. The test template is as follows:
+ Create a test instance of ExternalSecret. The test template is as follows:
```yaml
apiVersion: 'alibabacloud.com/v1alpha1'
@@ -158,19 +159,19 @@ ack-secret-manager involves two CRDs. SecretStore is used to store access creden
namespace: default
```
- - Execute the command to create an externalsecret test instance:
+ Execute the command to create an externalsecret test instance:
```sh
kubectl apply -f hello-service-external-secret.yml
```
- - Check whether the target secret is created successfully:
+ Check whether the target secret is created successfully:
```sh
kubectl get secret esdemo -oyaml
```
- - If the creation is successful, view the secret content as follows:
+ If the creation is successful, view the secret content as follows:
```yaml
apiVersion: v1
@@ -188,9 +189,30 @@ ack-secret-manager involves two CRDs. SecretStore is used to store access creden
type: Opaque
```
- - Without turning off the automatic synchronization configuration, you can modify the key content in the KMS Secrets Manager and wait for a while to check whether the target secret has been synchronized.
+ Without turning off the automatic synchronization configuration, you can modify the key content in the KMS Secrets Manager and wait for a while to check whether the target secret has been synchronized.
+
+ We supports cross-account synchronization of credentials. Just configure `remoteRamRoleArn` and `remoteRamRoleSessionName` in `SecretStore.Spec.KMS.KMSAuth`. The following is a sample SecretStore
+
+ ```yaml
+ apiVersion: 'alibabacloud.com/v1alpha1'
+ kind: SecretStore
+ metadata:
+ name: scdemo
+ spec:
+ KMS:
+ KMSAuth:
+ oidcProviderARN: "acs:ram::{accountID}:oidc-provider/ack-rrsa-{clusterID}"
+ ramRoleARN: "acs:ram::{accountID}:role/{roleName}"
+ remoteRamRoleArn: "acs:ram::{accountID}:role/{roleName}"
+ remoteRamRoleSessionName: "
+ ```
+
+
+3. JSON-formatted support
- - If you want to parse a JSON-formatted secret and synchronize the key-value pairs specified in it to the k8s secret, you can use the `jmesPath` field. The following is an example using the `jmesPath` field, which we deploy in the cluster
+- jmesPath
+
+ If you want to parse a JSON-formatted secret and synchronize the key-value pairs specified in it to the k8s secret, you can use the `jmesPath` field. The following is an example using the `jmesPath` field, which we deploy in the cluster
```yaml
apiVersion: 'alibabacloud.com/v1alpha1'
@@ -212,13 +234,13 @@ ack-secret-manager involves two CRDs. SecretStore is used to store access creden
objectAlias: "friendname"
```
- - After deployment, check whether the secret is created successfully
+ After deployment, check whether the secret is created successfully
```sh
kubectl get secret es-json-demo -oyaml
```
- - If the synchronization is successful, you will see the following results:
+ If the synchronization is successful, you will see the following results:
```yaml
apiVersion: v1
@@ -237,105 +259,17 @@ ack-secret-manager involves two CRDs. SecretStore is used to store access creden
type: Opaque
```
- - When you use the `jmesPath` field, you must specify the following two subfields:
+ When you use the `jmesPath` field, you must specify the following two subfields:
- - `path`: Required, parses the specified field in json based on the [JMES path](https://jmespath.org/specification.html) specification
+ - `path`: Required, parses the specified field in json based on the [JMES path](https://jmespath.org/specification.html) specification
- - `objectAlias`: Required, used to specify the parsed field to be synchronized to the key name in the k8s secret
+ - `objectAlias`: Required, used to specify the parsed field to be synchronized to the key name in the k8s secret
- - The shared KMS currently supports cross-account synchronization of credentials. Just configure `remoteRamRoleArn` and `remoteRamRoleSessionName` in `SecretStore.Spec.KMS.KMSAuth`. The following is a sample SecretStore
- ```yaml
- apiVersion: 'alibabacloud.com/v1alpha1'
- kind: SecretStore
- metadata:
- name: scdemo
- spec:
- KMS:
- KMSAuth:
- oidcProviderARN: "acs:ram::{accountID}:oidc-provider/ack-rrsa-{clusterID}"
- ramRoleARN: "acs:ram::{accountID}:role/{roleName}"
- remoteRamRoleArn: "acs:ram::{accountID}:role/{roleName}"
- remoteRamRoleSessionName: "
- ```
-
-3. Dedicated KMS
- Prerequisite: An AAP (application access point) has been created in the KMS console, and a ClientKey has been created within the access point, correctly configured with permissions for the credential "test1".
+- dataProcess
- - Create a secret in the cluster containing the relevant fields such as ClientKeyContent, Password, etc.
-
- ```yaml
- apiVersion: v1
- data:
- clientkey: {{ Client Key File Content }}
- password: {{ Password }}
- kind: Secret
- metadata:
- name: clientkey
- namespace: kube-system
- type: Opaque
- ```
-
- - Create a SecretStore instance
-
- ```yaml
- apiVersion: 'alibabacloud.com/v1alpha1'
- kind: SecretStore
- metadata:
- name: dkms-client
- spec:
- KMS:
- dedicatedKMSAuth:
- protocol: "https"
- endpoint: {{ kms Instance ID }}
- ignoreSSL: true
- clientKeyContent:
- name: clientkey
- namespace: kube-system
- key: clientkey
- password:
- name: clientkey
- namespace: kube-system
- key: password
- ```
-
- - Create an ExternalSecret instance and select default/dkms-client as the SecretStoreRef.
-
- ```yaml
- apiVersion: 'alibabacloud.com/v1alpha1'
- kind: ExternalSecret
- metadata:
- name: es-dkms-demo
- spec:
- data:
- - key: test1
- name: dkms
- versionId: v1
- secretStoreRef:
- name: dkms-client
- namespace: default
- ```
-
- - Once the synchronization is successful, you will be able to see the following results.
-
- ```yaml
- apiVersion: v1
- data:
- dkms: eyJuYW1lIjoidG9tIiwiYWdlIjoiMTQiLCJmcmllbmRzIjpbeyJuYW1lIjoibGlsaSJ9LHsibmFtZSI6ImVkZiJ9XX0g
- kind: Secret
- metadata:
- creationTimestamp: "2023-10-09T13:59:24Z"
- labels:
- lastUpdatedAt: 2023-10-09T13.59.24Z
- name: es-dkms-demo
- namespace: default
- resourceVersion: "7326124"
- uid: 4773959c-d90a-44c6-bf88-094855802683
- type: Opaque
- ```
-
- - If you want to parse JSON credentials and store them in a secret but don't know the specific structure of the credentials, you can use the self-extraction feature, which is the `dataProcess.Extract` field. You can also perform rule-based replacements on the parsed field keys using the `dataProcess.replaceRule` field to prevent irregular secret data keys from causing issues when creating a secret. The following is an example of an ExternalSecret:
+ If you want to parse JSON credentials and store them in a secret but don't know the specific structure of the credentials, you can use the self-extraction feature, which is the `dataProcess.Extract` field. You can also perform rule-based replacements on the parsed field keys using the `dataProcess.replaceRule` field to prevent irregular secret data keys from causing issues when creating a secret. The following is an example of an ExternalSecret:
```yaml
apiVersion: 'alibabacloud.com/v1alpha1'
@@ -358,7 +292,7 @@ ack-secret-manager involves two CRDs. SecretStore is used to store access creden
target: "ack"
```
- - Once the synchronization is successful, you will be able to see the following results. The JSON credentials are parsed into three parts, and their respective keys are replaced according to the replaceRule rules.
+ Once the synchronization is successful, you will be able to see the following results. The JSON credentials are parsed into three parts, and their respective keys are replaced according to the replaceRule rules.
```yaml
apiVersion: v1
@@ -378,104 +312,8 @@ ack-secret-manager involves two CRDs. SecretStore is used to store access creden
type: Opaque
```
-## CRD configuration introduction
-
-### ExternalSecret
-
-**spec**
-
-| parameter | description | required |
-| ----------- | ------------------------------------------------------------ | -------- |
-| provider | The target cloud products for syncing credentials, such as KMS | no |
-| data | Data source (identifier for the target data) | no |
-| dataProcess | Data source requiring special processing (identifier for the target data) | no |
-| type | Kubernetes Secret types (Opaque, etc.) | no |
-
-**data**
-
-| parameter | description | required |
-| -------------- | ------------------------------------------------------------ | -------- |
-| key | The unique identifier for the target credential, such as the key for KMS credentials | yes |
-| name | The corresponding key for the credentials in the secret data of the cluster | no |
-| versionStage | The version stage of the target credential | no |
-| versionId | The version Id of the target credential | no |
-| jmesPath | If the target credential is in JSON format, you can specify to retrieve the value corresponding to a specific key in the JSON | no |
-| secretStoreRef | Information of the referenced SecretStore | no |
-
-**dataProcess(Data source requiring special processing.)**
-
-| parameter | description | required |
-| ----------- | ------------------------------------------------------------ | -------- |
-| extract | Parsing JSON for the target credential without requiring the user to specify the JSON key | no |
-| replaceRule | Replacing keys of the parsed secret based on specific rules to prevent illegal keys from being stored in the Kubernetes Secret | no |
-
-**replaceRule(The content replacement used for the Secret Key.)**
-
-| parameter | description | required |
-| --------- | ------------------------------------------------------------ | -------- |
-| target | The string used for replacement | yes |
-| source | The string that needs to be replaced, which can be a regular expression | yes |
-
-**jmesPath**
-
-| parameter | description | required |
-| ----------- | ------------------------------------------------------------ | -------- |
-| path | JMESPath expression that allows users to specify the JSON key | yes |
-| objectAlias | The data key corresponding to the Kubernetes Secret where the data will be stored | yes |
-
-**secretStoreRef**
-
-| parameter | description | required |
-| --------- | ----------------------------------- | -------- |
-| name | The specified SecretStore name | yes |
-| namespace | The specified SecretStore namespace | Yes |
-
-### SecretStore
-
-**spec**
-
-| parameter | description | required |
-| --------- | ------------------------------------------------------------ | -------- |
-| KMS | Representing the target cloud product as KMS (Key Management Service) | no |
-
-**KMS**
-
-| parameter | description | required |
-| ---------------- | ------------------------------------------------------------ | -------- |
-| KMSAuth | Credentials required to access KMS (Key Management Service) under a shared KMS | no |
-| dedicatedKMSAuth | Credentials required to access KMS (Key Management Service) under a dedicated KMS | no |
-
-**KMSAuth**
-
-| parameter | description | required |
-| ------------------------ | ----------------------------------- | -------- |
-| accessKey | AccessKey | no |
-| accessKeySecret | AccessKey Secret | no |
-| ramRoleARN | Ram role arn | no |
-| ramRoleSessionName | Role session name | no |
-| oidcProviderARN | OIDC provider arn | no |
-| oidcTokenFilePath | | no |
-| remoteRamRoleArn | Cross-account ram role are | no |
-| remoteRamRoleSessionName | Cross-account ram role session name | no |
-
-**dedicatedKMSAuth**
-
-| parameter | description | required |
-| ---------------- | ---------------------------------------- | -------- |
-| protocol | https | yes |
-| endpoint | Kms instance ID | yes |
-| ca | User root CA certificate, base64 encoded | no |
-| ignoreSSL | Whether to ignore ssl authentication | no |
-| clientKeyContent | dedicated KMS client key file content | yes |
-| password | client key password | yes |
-
-**SecretRef(sensitive access credentials are stored in K8S secret)**
-
-| parameter | description | required |
-| --------- | -------------------- | -------- |
-| name | k8s secret name | yes |
-| namespace | k8s secret namaspace | yes |
-| key | k8s secret key | Yes |
+## Security
+Please report vulnerabilities by email to **kubernetes-security@service.aliyun.com**. Also see our [SECURITY.md](./SECURITY.md) file for details.
## Release Note
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 0000000..7aba466
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,22 @@
+# Security Policy
+
+- [Security Policy](#security-policy)
+ - [Reporting security problems](#reporting-security-problems)
+ - [Vulnerability Management Plans](#vulnerability-management-plans)
+ - [Critical Updates And Security Notices](#critical-updates-and-security-notices)
+
+## Reporting security problems
+
+**DO NOT CREATE AN ISSUE** to report a security problem. Instead, please
+send an email to **kubernetes-security@service.aliyun.com**
+
+Please follow the [embargo policy](./embargo-policy.md) for all security-related problems.
+
+## Vulnerability Management Plans
+
+### Critical Updates And Security Notices
+
+We learn about critical software updates and security threats from these sources
+
+1. GitHub Security Alerts
+2. [Dependabot](https://dependabot.com/) Dependency Updates
diff --git a/cmd/manager/main.go b/cmd/manager/main.go
index 74af751..f784c2a 100644
--- a/cmd/manager/main.go
+++ b/cmd/manager/main.go
@@ -46,8 +46,8 @@ var (
)
func init() {
- corev1.AddToScheme(scheme)
- apis.AddToScheme(scheme)
+ _ = corev1.AddToScheme(scheme)
+ _ = apis.AddToScheme(scheme)
// +kubebuilder:scaffold:scheme
}
@@ -169,7 +169,11 @@ func main() {
}
//not start auto sync job if disable polling
if !disablePolling {
- esReconciler.InitSecretCache()
+ err := esReconciler.InitSecretCache()
+ if err != nil {
+ log.Error(err, "failed to init secret cache")
+ os.Exit(1)
+ }
go esReconciler.SecretRotationJob()
}
diff --git a/doc/crd.md b/doc/crd.md
new file mode 100644
index 0000000..d3ea605
--- /dev/null
+++ b/doc/crd.md
@@ -0,0 +1,98 @@
+## CRD Parameters Description
+
+### ExternalSecret
+
+**spec**
+
+| parameter | description | required |
+| ----------- | ------------------------------------------------------------ | -------- |
+| provider | The target cloud products for syncing credentials, such as KMS | no |
+| data | Data source (identifier for the target data) | no |
+| dataProcess | Data source requiring special processing (identifier for the target data) | no |
+| type | Kubernetes Secret types (Opaque, etc.) | no |
+
+**data**
+
+| parameter | description | required |
+| -------------- | ------------------------------------------------------------ | -------- |
+| key | The unique identifier for the target credential, such as the key for KMS credentials | yes |
+| name | The corresponding key for the credentials in the secret data of the cluster | no |
+| versionStage | The version stage of the target credential | no |
+| versionId | The version Id of the target credential | no |
+| jmesPath | If the target credential is in JSON format, you can specify to retrieve the value corresponding to a specific key in the JSON | no |
+| secretStoreRef | Information of the referenced SecretStore | no |
+
+**dataProcess(Data source requiring special processing.)**
+
+| parameter | description | required |
+| ----------- | ------------------------------------------------------------ | -------- |
+| extract | Parsing JSON for the target credential without requiring the user to specify the JSON key | no |
+| replaceRule | Replacing keys of the parsed secret based on specific rules to prevent illegal keys from being stored in the Kubernetes Secret | no |
+
+**replaceRule(The content replacement used for the Secret Key.)**
+
+| parameter | description | required |
+| --------- | ------------------------------------------------------------ | -------- |
+| target | The string used for replacement | yes |
+| source | The string that needs to be replaced, which can be a regular expression | yes |
+
+**jmesPath**
+
+| parameter | description | required |
+| ----------- | ------------------------------------------------------------ | -------- |
+| path | JMESPath expression that allows users to specify the JSON key | yes |
+| objectAlias | The data key corresponding to the Kubernetes Secret where the data will be stored | yes |
+
+**secretStoreRef**
+
+| parameter | description | required |
+| --------- | ----------------------------------- | -------- |
+| name | The specified SecretStore name | yes |
+| namespace | The specified SecretStore namespace | Yes |
+
+### SecretStore
+
+**spec**
+
+| parameter | description | required |
+| --------- | ------------------------------------------------------------ | -------- |
+| KMS | Representing the target cloud product as KMS (Key Management Service) | no |
+
+**KMS**
+
+| parameter | description | required |
+| ---------------- | ------------------------------------------------------------ | -------- |
+| KMSAuth | Credentials required to access KMS (Key Management Service) under a shared KMS | no |
+| dedicatedKMSAuth | Credentials required to access KMS (Key Management Service) under a dedicated KMS | no |
+
+**KMSAuth**
+
+| parameter | description | required |
+| ------------------------ | ----------------------------------- | -------- |
+| accessKey | AccessKey | no |
+| accessKeySecret | AccessKey Secret | no |
+| ramRoleARN | Ram role arn | no |
+| ramRoleSessionName | Role session name | no |
+| oidcProviderARN | OIDC provider arn | no |
+| oidcTokenFilePath | | no |
+| remoteRamRoleArn | Cross-account ram role are | no |
+| remoteRamRoleSessionName | Cross-account ram role session name | no |
+
+**dedicatedKMSAuth**
+
+| parameter | description | required |
+| ---------------- | ---------------------------------------- | -------- |
+| protocol | https | yes |
+| endpoint | Kms instance ID | yes |
+| ca | User root CA certificate, base64 encoded | no |
+| ignoreSSL | Whether to ignore ssl authentication | no |
+| clientKeyContent | dedicated KMS client key file content | yes |
+| password | client key password | yes |
+
+**SecretRef(sensitive access credentials are stored in K8S secret)**
+
+| parameter | description | required |
+| --------- | -------------------- | -------- |
+| name | k8s secret name | yes |
+| namespace | k8s secret namaspace | yes |
+| key | k8s secret key | Yes |
\ No newline at end of file
diff --git a/embargo-policy.md b/embargo-policy.md
new file mode 100644
index 0000000..12617af
--- /dev/null
+++ b/embargo-policy.md
@@ -0,0 +1,30 @@
+# Embargo Policy
+
+This policy forbids members of this project's security contacts any others
+defined below from sharing information outside of the security contacts and this
+listing without need-to-know and advance notice.
+
+The information members and others receive from the list defined below must:
+
+* not be made public,
+* not be shared,
+* not be hinted at
+* must be kept confidential and close held
+
+Except with the list's explicit approval. This holds true until the public
+disclosure date/time that was agreed upon by the list.
+
+If information is inadvertently shared beyond what is allowed by this policy,
+you are REQUIRED to inform the security contacts **kubernetes-security@service.aliyun.com** of exactly what
+information leaked and to whom. A retrospective will take place after the leak
+so we can assess how to not make this mistake in the future.
+
+Violation of this policy will result in the immediate removal and subsequent
+replacement of you from this list or the Security Contacts.
+
+## Disclosure Timeline
+
+This project sustains a **disclosure timeline** to ensure we provide a
+quality, tested release. On some occasions, we may need to extend this timeline
+due to complexity of the problem, lack of expertise available, or other reasons.
+Submitters will be notified if an extension occurs.
diff --git a/pkg/backend/kms/client_manager.go b/pkg/backend/kms/client_manager.go
index a9188dd..7aca0da 100644
--- a/pkg/backend/kms/client_manager.go
+++ b/pkg/backend/kms/client_manager.go
@@ -39,7 +39,6 @@ func (m *Manager) RegisterRamProvider(clientName string, stopper provider.Stoppe
}
m.ramProvider[clientName] = stopper
klog.Infof("register provider %v success", clientName)
- return
}
func (m *Manager) StopProvider(clientName string) {
diff --git a/pkg/backend/kms/kms_service.go b/pkg/backend/kms/kms_service.go
index 73a8207..b8684e0 100644
--- a/pkg/backend/kms/kms_service.go
+++ b/pkg/backend/kms/kms_service.go
@@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"fmt"
+ "github.com/jmespath/go-jmespath"
"math"
"regexp"
"time"
@@ -13,7 +14,6 @@ import (
sdkErr "github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors"
dkmsopenapiutil "github.com/aliyun/alibabacloud-dkms-gcs-go-sdk/openapi-util"
dkms "github.com/aliyun/alibabacloud-dkms-gcs-go-sdk/sdk"
- "github.com/jmespath/go-jmespath"
"k8s.io/klog"
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -25,8 +25,6 @@ const (
REJECTED_THROTTLING = "Rejected.Throttling"
SERVICE_UNAVAILABLE_TEMPORARY = "ServiceUnavailableTemporary"
INTERNAL_FAILURE = "InternalFailure"
- MAX_RETRY_TIMES = 5
- KMSVPCDomain = "%s.cryptoservice.kms.aliyuncs.com"
)
var (
@@ -181,21 +179,18 @@ func (c *KMSClient) getExternalDataFromKMS(data v1alpha1.DataSource) ([]byte, er
req.VersionId = tea.String(data.VersionId)
}
resp, err := c.kmsClient.GetSecretValue(req)
- for retryTimes := 1; retryTimes < MAX_RETRY_TIMES; retryTimes++ {
- if err != nil {
- if !judgeNeedRetry(err) {
- klog.Errorf("failed to get secret value from kms,key %v,error %v", data.Key, err)
+ if err != nil {
+ if !judgeNeedRetry(err) {
+ klog.Errorf("failed to get secret value from kms,key %v,error %v", data.Key, err)
+ return nil, err
+ } else {
+ time.Sleep(getWaitTimeExponential(1))
+ resp, err = c.kmsClient.GetSecretValue(req)
+ if err != nil {
+ klog.Errorf("retry to get secret value from kms failed,key %v,error %v", data.Key, err)
return nil, err
- } else {
- time.Sleep(getWaitTimeExponential(retryTimes))
- resp, err = c.kmsClient.GetSecretValue(req)
- if err != nil && retryTimes == MAX_RETRY_TIMES-1 {
- klog.Errorf("failed to get secret value from kms,key %v,error %v", data.Key, err)
- return nil, err
- }
}
}
- break
}
if *resp.Body.SecretDataType == utils.BinaryType {
klog.Errorf("not support binary type yet,key %v", data.Key)
@@ -221,21 +216,18 @@ func (c *KMSClient) getExternalDataFromDKMS(data v1alpha1.DataSource) ([]byte, e
runtimeOptions := &dkmsopenapiutil.RuntimeOptions{}
resp, err := c.dedicatedClient.GetSecretValueWithOptions(req, runtimeOptions)
- for retryTimes := 1; retryTimes < MAX_RETRY_TIMES; retryTimes++ {
- if err != nil {
- if !judgeNeedRetry(err) {
- klog.Errorf("failed to get secret value from kms,key %v,error %v", data.Key, err)
+ if err != nil {
+ if !judgeNeedRetry(err) {
+ klog.Errorf("failed to get secret value from kms,key %v,error %v", data.Key, err)
+ return nil, err
+ } else {
+ time.Sleep(getWaitTimeExponential(1))
+ resp, err = c.dedicatedClient.GetSecretValueWithOptions(req, runtimeOptions)
+ if err != nil {
+ klog.Errorf("retry to get secret value from kms failed,key %v,error %v", data.Key, err)
return nil, err
- } else {
- time.Sleep(getWaitTimeExponential(retryTimes))
- resp, err = c.dedicatedClient.GetSecretValueWithOptions(req, runtimeOptions)
- if err != nil && retryTimes == MAX_RETRY_TIMES-1 {
- klog.Errorf("failed to get secret value from kms,key %v,error %v", data.Key, err)
- return nil, err
- }
}
}
- break
}
if *resp.SecretDataType == utils.BinaryType {
klog.Errorf("not support binary type yet,key %v", data.Key)
diff --git a/pkg/backend/provider.go b/pkg/backend/provider.go
index 6c53490..2b03986 100644
--- a/pkg/backend/provider.go
+++ b/pkg/backend/provider.go
@@ -59,7 +59,7 @@ func NewProviderClientByENV(ctx context.Context, region string) error {
provider.Register(EnvClient, secretClient)
return true
})
- if errs != nil && len(errs) != 0 {
+ if len(errs) != 0 {
return fmt.Errorf("new provider client by env error %v", errs)
}
return nil
diff --git a/pkg/controller/externalsecret/secret_controller.go b/pkg/controller/externalsecret/secret_controller.go
index 3de192b..2e5916e 100644
--- a/pkg/controller/externalsecret/secret_controller.go
+++ b/pkg/controller/externalsecret/secret_controller.go
@@ -313,7 +313,7 @@ func (r *ExternalSecretReconciler) getExternalSecret(provider backend.Provider,
out[k] = v
}
}
- if errors != nil && len(errors) != 0 {
+ if len(errors) != 0 {
return out, fmt.Errorf("%v", errors)
}
return out, nil
@@ -352,7 +352,7 @@ func (r *ExternalSecretReconciler) getExternalSecretWithExtract(provider backend
out[k] = v
}
}
- if errors != nil && len(errors) != 0 {
+ if len(errors) != 0 {
return out, fmt.Errorf("%v", errors)
}
return out, nil
@@ -372,10 +372,8 @@ func (r *ExternalSecretReconciler) syncIfNeedUpdate(externalSec *api.ExternalSec
if err != nil {
klog.Errorf("get external secret error %v", err)
}
- if out != nil {
- for k, v := range out {
- secretMap[k] = v
- }
+ for k, v := range out {
+ secretMap[k] = v
}
}
if externalSec.Spec.DataProcess != nil && len(externalSec.Spec.DataProcess) != 0 {
@@ -383,10 +381,8 @@ func (r *ExternalSecretReconciler) syncIfNeedUpdate(externalSec *api.ExternalSec
if err != nil {
klog.Errorf("get external secret error %v", err)
}
- if out != nil {
- for k, v := range out {
- secretMap[k] = v
- }
+ for k, v := range out {
+ secretMap[k] = v
}
}
// Get the actual secret from Kubernetes
diff --git a/pkg/utils/util.go b/pkg/utils/util.go
index 450a5e8..f8746a0 100644
--- a/pkg/utils/util.go
+++ b/pkg/utils/util.go
@@ -18,7 +18,6 @@ package utils
import (
"context"
"encoding/json"
- "errors"
"fmt"
"io/ioutil"
"net/http"
@@ -73,7 +72,7 @@ func Retry(interval time.Duration, maxRetries int, f ConditionFunc) error {
}
<-tick.C
}
- return errors.New(fmt.Sprintf("still failing after %d retries", maxRetries))
+ return fmt.Errorf("still failing after %d retries", maxRetries)
}
func Contains(list []string, s string) bool {