技术标签: 云原生 kubernetes 容器
默认 Secrets 对象的值是 base64 编码的内容,这个可以反编码得到原文的,不能起到加密重要密文的作用。
解决方法是使用开源的 Sealed Secrets
github 地址: https://github.com/bitnami-labs/sealed-secrets
有两部分总成:
kubeseal 程序使用非对称加密来加密,只有控制器才能解密。
这些加密的秘密被编码在SealedSecret资源中,您可以将其视为创建秘密的配方。
它的 YAML 资源文件大概是这样的:
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
name: mysecret
namespace: mynamespace
spec:
encryptedData:
foo: AgBy3i4OJSWK+PiTySYZZA9rO43cGDEq.....
经过 kubernetes 已安装的 controller 解密后相当于下面的内容:
apiVersion: v1
kind: Secret
metadata:
name: mysecret
namespace: mynamespace
data:
foo: YmFy # <- base64 编码的 "bar"
当这个 SealedSecret 的 secret 被创建的几秒钟之后,它会出现在 kubernetes 中;随后你可以像使用 kubernetes 原生的 secret 一样使用它。例如,从 Pod 引用它。
获取最新的版本 https://github.com/bitnami-labs/sealed-secrets/releases
选择自己喜欢的部署方式即可。
这里选择手动非工具部署
需要下载
---
apiVersion: v1
kind: ServiceAccount
metadata:
annotations: {
}
labels:
name: sealed-secrets-controller
name: sealed-secrets-controller
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
annotations: {
}
labels:
name: secrets-unsealer
name: secrets-unsealer
rules:
- apiGroups:
- bitnami.com
resources:
- sealedsecrets
verbs:
- get
- list
- watch
- apiGroups:
- bitnami.com
resources:
- sealedsecrets/status
verbs:
- update
- apiGroups:
- ""
resources:
- secrets
verbs:
- get
- list
- create
- update
- delete
- watch
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
- apiGroups:
- ""
resources:
- namespaces
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
annotations: {
}
labels:
name: sealed-secrets-controller
name: sealed-secrets-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: secrets-unsealer
subjects:
- kind: ServiceAccount
name: sealed-secrets-controller
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
annotations: {
}
labels:
name: sealed-secrets-service-proxier
name: sealed-secrets-service-proxier
namespace: kube-system
rules:
- apiGroups:
- ""
resourceNames:
- sealed-secrets-controller
resources:
- services
verbs:
- get
- apiGroups:
- ""
resourceNames:
- 'http:sealed-secrets-controller:'
- http:sealed-secrets-controller:http
- sealed-secrets-controller
resources:
- services/proxy
verbs:
- create
- get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
annotations: {
}
labels:
name: sealed-secrets-service-proxier
name: sealed-secrets-service-proxier
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: sealed-secrets-service-proxier
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: system:authenticated
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
annotations: {
}
labels:
name: sealed-secrets-key-admin
name: sealed-secrets-key-admin
namespace: kube-system
rules:
- apiGroups:
- ""
resources:
- secrets
verbs:
- create
- list
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
annotations: {
}
labels:
name: sealed-secrets-controller
name: sealed-secrets-controller
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: sealed-secrets-key-admin
subjects:
- kind: ServiceAccount
name: sealed-secrets-controller
namespace: kube-system
---
apiVersion: v1
kind: Service
metadata:
annotations: {
}
labels:
name: sealed-secrets-controller
name: sealed-secrets-controller
namespace: kube-system
spec:
ports:
- port: 8080
targetPort: 8080
selector:
name: sealed-secrets-controller
type: ClusterIP
---
apiVersion: v1
kind: Service
metadata:
annotations: {
}
labels:
name: sealed-secrets-controller-metrics
name: sealed-secrets-controller-metrics
namespace: kube-system
spec:
ports:
- port: 8081
targetPort: 8081
selector:
name: sealed-secrets-controller
type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
annotations: {
}
labels:
name: sealed-secrets-controller
name: sealed-secrets-controller
namespace: kube-system
spec:
minReadySeconds: 30
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
name: sealed-secrets-controller
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
annotations: {
}
labels:
name: sealed-secrets-controller
spec:
containers:
- args: []
command:
- controller
env: []
image: docker.io/bitnami/sealed-secrets-controller:0.26.1
imagePullPolicy: IfNotPresent
livenessProbe:
httpGet:
path: /healthz
port: http
name: sealed-secrets-controller
ports:
- containerPort: 8080
name: http
- containerPort: 8081
name: metrics
readinessProbe:
httpGet:
path: /healthz
port: http
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
stdin: false
tty: false
volumeMounts:
- mountPath: /tmp
name: tmp
imagePullSecrets: []
securityContext:
fsGroup: 65534
runAsNonRoot: true
runAsUser: 1001
seccompProfile:
type: RuntimeDefault
serviceAccountName: sealed-secrets-controller
terminationGracePeriodSeconds: 30
volumes:
- emptyDir: {
}
name: tmp
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: sealedsecrets.bitnami.com
spec:
group: bitnami.com
names:
kind: SealedSecret
listKind: SealedSecretList
plural: sealedsecrets
singular: sealedsecret
scope: Namespaced
versions:
- name: v1alpha1
schema:
openAPIV3Schema:
description: SealedSecret is the K8s representation of a "sealed Secret" -
a regular k8s Secret that has been sealed (encrypted) using the controller's
key.
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: SealedSecretSpec is the specification of a SealedSecret
properties:
data:
description: Data is deprecated and will be removed eventually. Use
per-value EncryptedData instead.
format: byte
type: string
encryptedData:
additionalProperties:
type: string
type: object
x-kubernetes-preserve-unknown-fields: true
template:
description: Template defines the structure of the Secret that will
be created from this sealed secret.
properties:
data:
additionalProperties:
type: string
description: Keys that should be templated using decrypted data
nullable: true
type: object
immutable:
description: Immutable, if set to true, ensures that data stored
in the Secret cannot be updated (only object metadata can be
modified). If not set to true, the field can be modified at
any time. Defaulted to nil.
type: boolean
metadata:
description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata'
nullable: true
properties:
annotations:
additionalProperties:
type: string
type: object
finalizers:
items:
type: string
type: array
labels:
additionalProperties:
type: string
type: object
name:
type: string
namespace:
type: string
type: object
x-kubernetes-preserve-unknown-fields: true
type:
description: Used to facilitate programmatic handling of secret
data.
type: string
type: object
required:
- encryptedData
type: object
status:
description: SealedSecretStatus is the most recently observed status of
the SealedSecret.
properties:
conditions:
description: Represents the latest available observations of a sealed
secret's current state.
items:
description: SealedSecretCondition describes the state of a sealed
secret at a certain point.
properties:
lastTransitionTime:
description: Last time the condition transitioned from one status
to another.
format: date-time
type: string
lastUpdateTime:
description: The last time this condition was updated.
format: date-time
type: string
message:
description: A human readable message indicating details about
the transition.
type: string
reason:
description: The reason for the condition's last transition.
type: string
status:
description: 'Status of the condition for a sealed secret. Valid
values for "Synced": "True", "False", or "Unknown".'
type: string
type:
description: 'Type of condition for a sealed secret. Valid value:
"Synced"'
type: string
required:
- status
- type
type: object
type: array
observedGeneration:
description: ObservedGeneration reflects the generation most recently
observed by the sealed-secrets controller.
format: int64
type: integer
type: object
required:
- spec
type: object
served: true
storage: true
subresources:
status: {
}
以某种方式创建一个json/yaml编码的Secret:
echo -n bar | kubectl create secret generic mysecret --dry-run=client --from-file=foo=/dev/stdin -o yaml >mysecret.yml
内容如下:
apiVersion: v1
data:
foo: YmFy
kind: Secret
metadata:
creationTimestamp: null
name: mysecret
生成加密的 secret 资源文件
kubeseal -f mysecret.yml -w mysealedsecret.yml
数据被加密后的资源文件如下:
---
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
creationTimestamp: null
name: mysecret
namespace: default
spec:
encryptedData:
foo: AgA4KaUIHoNRNv8ZN1H1+dZfRyHFahVcTMMgRjoTkbL8dYmImstmw9oxrahaL8OOji5inMZ+AYP2UGJjUzflWN5SNOWpFGLN5LGHG2tinp1TWt14wCI20XqbVkGsbEwiQeh8Nudb32EgCJ0/Z4dYsa3zBR1jAbklyNv3s8sUnvDN/yvijMJYqxU3kbnHqQhiwt9SohTw445GCv1YlOe7ZqmB1MR2uK+3tRx7WUWpGe8A84uxZEJYMps/S5gxbGUMp5uvIm55S3fEYsWxqus6ssVMUoBAyCaVKCkftfRQBBd2bpBTiiQ8cnAw2BRVaGtDCHKqbZ/FY/uhllUOHxfQxzWwtDh1k3hQgXLnvG8krJytZ4OqZmkWYsOYPgakwZcZeLpBryEJv5CuwG/5RCOM5Cxjlwqph2Kfah0kULNdoAe4GbwvW1bK0PI/9SKZbrhiQ/o6GfR30W9aos3ucNbZihRA9P6er8sWbguzN3qYvdqbrSdrJ+VAyjty7lEBR/BTlUo5NdjbLuYTOhGbhcvCi7TYXThklRjisNzbS1pd/CMIm8difwEudnXmx44+hsqoK8MLgYXXEdSriJuHMeql881pxP2HQjXabr4MJkTKO7hznc4/vNnP+QtNbvjL01f1XDxIUrzsv1D3T45pBYYIfvJGb9rcskyunjJvhyJ2LUAlWY6f3uKUTwBwSIcoEX4V6WuuKYc=
template:
metadata:
creationTimestamp: null
name: mysecret
namespace: default
创建资源对象到集群中
kubectl apply -f mysealedsecret.yml
查看资源对象
kubectl get secret mysecret
输出如下内容:
NAME TYPE DATA AGE
mysecret Opaque 1 17m
查看对象详情
kubectl describe secret mysecret
输出如下内容:
Name: mysecret
Namespace: default
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
foo: 3 bytes
请注意,SealedSecret 和 Secret 必须具有相同的命名空间和名称。这是一个防止同一集群上的其他用户重新使用您的密封机密的功能。
在 Pod 中使用
busybox.yml
文件内容:
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mypod
image: busybox
command:
- cat
- "/etc/mysecret/foo"
volumeMounts:
- name: foo
mountPath: "/etc/mysecret"
readOnly: true
volumes:
- name: foo
secret:
secretName: mysecret
创建这个 Pod:
kubectl apply -f busybox.yml
这个 SealedSecret对象的创建不验证用户。换句话说,任何人都可以创建一个Sealed Secret 对象。
这个和原生的 Secret 对象是一样的设计,都是通过集群的 RBAC 机制控制使用的权限。
如果希望 Sealed Secrets 控制器管理现有的 Secret,您可以使用 Sealed Secret 对您的 Secret 添加 sealedsecrets.bitnami.com/managed: "true"
annotations(注解)。
当解封具有相同名称和命名空间的 Sealed Secret 时,现有的 Secret 将被覆盖,并且 Sealed Secrets 将拥有该 Secret 的所有权(因此,当删除 Sealed Secret 时,该 Secret 也将被删除)。
例如有一个现有的 Secret 对象 test-secret
, 他的 YAML 文件内容如下:
apiVersion: v1
kind: Secret
metadata:
name: testsecret
data:
foo: MTIz
给原有的 Secret 添加注释
apiVersion: v1
kind: Secret
metadata:
name: testsecret
annotations:
sealedsecrets.bitnami.com/managed: "true"
data:
foo: MTIz
应用一下
kubectl apply -f test-seal.yml
查看运行中的 testsecret 对象的信息
查看运行中的 testsecret 对象 YAML 内容
接着,我创建同名的 Sealed Secrets 对象
这里我偷懒了,没通过创建新的密码创建 Sealed Secrets 对象,而是沿用原来的 Secrets 对象中的密码。
正确的做法是使用新的密码创建 Sealed Secrets 对象去覆盖原来的 Secrets 对象。
kubeseal -f test-secret.yml -w test-seal.yml
kubectl apply -f test-seal.yml
后面就可以使用这个含有加密秘密内容的 YAML 文件 test-seal.yml ,给到 开发使用了,即使可以查看文件中的内容,但因为里面的敏感数据已经被加密,真正的密码也可以得到有效的保护。
并且,此时再查看 Secret 实力对象 testsecret
,会发现对象已经被覆盖。
如果此时,删除 Sealed Secret 对象, 对应的这个 Secret 实例对象 testsecret
也会被删除。
加入你得到一个有加密密文的 YAML 文件
---
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
creationTimestamp: null
name: testsecret
namespace: default
spec:
encryptedData:
foo: AgAK7TTRNORyvO6nQFq9w0Unj6e+/NHPyipdtbuwdfhyvnZavLpmUIcbHnj/wj/QFvbFiAtc2NoTG2g/sZIZJ8/ZgJi4a7lrNJbCFKcSdxDSyPcAdP0K9SjiSqcpFxw1zVw0NJOtV2q8khcY+aDkk7QWdxio8+0qdSpb5KvbB+eCAByxVdixHJXd8Ul2s/6CqRCkm3DGwwvvvV/1ogoUWMidaZXK/Ju4RopAaKYrnJ0fSpDrR8vRZEC6wJD6HRXc5cXeVXJ8g3SXgAQ1tjRuJkBxF+5S8jODihioBVLbq++6FxXJ/4bepy7NFcY/K7ldnp/B6xngqFiawYuUlPnI+iscE6YkSlSFFGohrgj6xByGVf7jCNBbbOY9itgu8AY/zrAUCedgr8c+xtPfX7cwGlGicD5sw/M1mpRXE0T6uH3H3MTazHk2KZvXTk290pOF6bYrzoV5AsG6I37+fAhDDJs1WFtj47kk0eaiwKJuSPeSVxlQyKqP50oemhK3aXJCOz6ryZUppSD8ufRRqGJls+lN8oFLZakfR6sjYY5zQFLaHIw5vo9egn7dSdUdKch3lP5D4pSohSdHrSYJnEplA4XImRu68X5phJyih6IWPRrOtDv4wZ9+B3qSVMTD5YdyEPirt4azb6pY7Xk4NvCDQctgWP4FRzdjVzu2FNru6t8cC+Gz7fwIJXMr1dkH4W/e8I4UldU=
template:
metadata:
creationTimestamp: null
name: testsecret
namespace: default
如果你想验证文件内的加密密文是否有效,或者是否得到破坏。可以使用如下命令验证
cat test-seal.yml | kubeseal --validate
如果正常,则没有任何返回。如果有问题,则会返回如下内容:
error: unable to decrypt sealed secret: testsecret
文章浏览阅读331次。第一部分:准备工作1 安装虚拟机2 安装centos73 安装JDK以上三步是准备工作,至此已经完成一台已安装JDK的主机第二部分:准备3台虚拟机以下所有工作最好都在root权限下操作1 克隆上面已经有一台虚拟机了,现在对master进行克隆,克隆出另外2台子机;1.1 进行克隆21.2 下一步1.3 下一步1.4 下一步1.5 根据子机需要,命名和安装路径1.6 ..._创建一个hadoop项目
文章浏览阅读1.7k次。心脏滴血漏洞HeartBleed CVE-2014-0160 是由heartbeat功能引入的,本文从深入码层面的分析该漏洞产生的原因_heartbleed代码分析
文章浏览阅读1.4k次。前言ofd是国家文档标准,其对标的文档格式是pdf。ofd文档是容器格式文件,ofd其实就是压缩包。将ofd文件后缀改为.zip,解压后可看到文件包含的内容。ofd文件分析工具下载:点我下载。ofd文件解压后,可以看到如下内容: 对于xml文件,可以用文本工具查看。但是对于印章文件(Seal.esl)、签名文件(SignedValue.dat)就无法查看其内容了。本人开发一款ofd内容查看器,..._signedvalue.dat
文章浏览阅读1.8w次,点赞29次,收藏313次。整体系统设计本设计主要是对ADC和DAC的使用,主要实现功能流程为:首先通过串口向FPGA发送控制信号,控制DAC芯片tlv5618进行DA装换,转换的数据存在ROM中,转换开始时读取ROM中数据进行读取转换。其次用按键控制adc128s052进行模数转换100次,模数转换数据存储到FIFO中,再从FIFO中读取数据通过串口输出显示在pc上。其整体系统框图如下:图1:FPGA数据采集系统框图从图中可以看出,该系统主要包括9个模块:串口接收模块、按键消抖模块、按键控制模块、ROM模块、D.._基于fpga的信息采集
文章浏览阅读2.5w次。1.背景错误信息:-- [http-nio-9904-exec-5] o.s.c.n.z.filters.post.SendErrorFilter : Error during filteringcom.netflix.zuul.exception.ZuulException: Forwarding error at org.springframework.cloud..._com.netflix.zuul.exception.zuulexception
文章浏览阅读358次。1.介绍图的相关概念 图是由顶点的有穷非空集和一个描述顶点之间关系-边(或者弧)的集合组成。通常,图中的数据元素被称为顶点,顶点间的关系用边表示,图通常用字母G表示,图的顶点通常用字母V表示,所以图可以定义为: G=(V,E)其中,V(G)是图中顶点的有穷非空集合,E(G)是V(G)中顶点的边的有穷集合1.1 无向图:图中任意两个顶点构成的边是没有方向的1.2 有向图:图中..._给定一个邻接矩阵未必能够造出一个图
文章浏览阅读321次。(十二)、WDS服务器安装通过前面的测试我们会发现,每次安装的时候需要加域光盘映像,这是一个比较麻烦的事情,试想一个上万个的公司,你天天带着一个光盘与光驱去给别人装系统,这将是一个多么痛苦的事情啊,有什么方法可以解决这个问题了?答案是肯定的,下面我们就来简单说一下。WDS服务器,它是Windows自带的一个免费的基于系统本身角色的一个功能,它主要提供一种简单、安全的通过网络快速、远程将Window..._doc server2012上通过wds+mdt无人值守部署win11系统.doc
文章浏览阅读219次。python–xlrd/xlwt/xlutilsxlrd只能读取,不能改,支持 xlsx和xls 格式xlwt只能改,不能读xlwt只能保存为.xls格式xlutils能将xlrd.Book转为xlwt.Workbook,从而得以在现有xls的基础上修改数据,并创建一个新的xls,实现修改xlrd打开文件import xlrdexcel=xlrd.open_workbook('E:/test.xlsx') 返回值为xlrd.book.Book对象,不能修改获取sheett_xlutils模块可以读xlsx吗
文章浏览阅读8.2w次,点赞267次,收藏656次。运行Selenium出现'WebDriver' object has no attribute 'find_element_by_id'或AttributeError: 'WebDriver' object has no attribute 'find_element_by_xpath'等定位元素代码错误,是因为selenium更新到了新的版本,以前的一些语法经过改动。..............._unresolved attribute reference 'find_element_by_id' for class 'webdriver
文章浏览阅读198次。一:模态窗口//父页面JSwindow.showModalDialog(ifrmehref, window, 'dialogWidth:550px;dialogHeight:150px;help:no;resizable:no;status:no');//子页面获取父页面DOM对象//window.showModalDialog的DOM对象var v=parentWin..._jquery获取父window下的dom对象
文章浏览阅读1.7w次,点赞15次,收藏129次。算法(algorithm)是解决一系列问题的清晰指令,也就是,能对一定规范的输入,在有限的时间内获得所要求的输出。 简单来说,算法就是解决一个问题的具体方法和步骤。算法是程序的灵 魂。二、算法的特征1.可行性 算法中执行的任何计算步骤都可以分解为基本可执行的操作步,即每个计算步都可以在有限时间里完成(也称之为有效性) 算法的每一步都要有确切的意义,不能有二义性。例如“增加x的值”,并没有说增加多少,计算机就无法执行明确的运算。 _算法
文章浏览阅读1.5k次,点赞18次,收藏26次。网络安全的标准和规范是网络安全领域的重要组成部分。它们为网络安全提供了技术依据,规定了网络安全的技术要求和操作方式,帮助我们构建安全的网络环境。下面,我们将详细介绍一些主要的网络安全标准和规范,以及它们在实际操作中的应用。_网络安全标准规范