# 3.安全机制
## 3.1 SA
```sh
# 创建测试SA,我们发现一个SA有相对应的secrets
[19:25:06 root@master1 security]#kubectl create -f - <<EOF
> apiVersion: v1
> kind: ServiceAccount
> metadata:
> name: build-robot
> EOF
serviceaccount/build-robot created
[20:12:17 root@master1 security]#kubectl get sa,secrets
NAME SECRETS AGE
serviceaccount/build-robot 1 7m39s
serviceaccount/default 1 21d
NAME TYPE DATA AGE
secret/build-robot-token-rwfsb kubernetes.io/service-account-token 3 7m39s
secret/default-token-zjxfd kubernetes.io/service-account-token 3 21d
# 结合pod测试
[20:20:52 root@master1 security]#cat robot.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- image: 10.0.0.55:80/mykubernetes/nginx:1.21.3
name: nginx
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: build-robot-token-rwfsb
serviceAccountName: build-robot
volumes:
- name: build-robot-token-rwfsb
projected:
sources:
- serviceAccountToken:
path: build-robot-token-rwfsb
expirationSeconds: 7200
[20:20:44 root@master1 security]#kubectl describe pod nginx
Name: nginx
Namespace: default
Priority: 0
Node: node2.noisedu.cn/10.0.0.54
Start Time: Sun, 02 Jan 2022 20:20:44 +0800
Labels: <none>
Annotations: cni.projectcalico.org/containerID: 87d85747bcce0bce508455b4697e8ed2e6b387c3ef2511a7bd735fd288f5af13
cni.projectcalico.org/podIP: 10.244.4.4/32
cni.projectcalico.org/podIPs: 10.244.4.4/32
Status: Running
IP: 10.244.4.4
IPs:
IP: 10.244.4.4
Containers:
nginx:
Container ID: docker://66696744862f0e95efaf6eda484df98deb96967ccb2d7ef79c284c47fc09b09f
Image: 10.0.0.55:80/mykubernetes/nginx:1.21.3
Image ID: docker-pullable://10.0.0.55:80/mykubernetes/nginx@sha256:4424e31f2c366108433ecca7890ad527b243361577180dfd9a5bb36e828abf47
Port: <none>
Host Port: <none>
State: Running
Started: Sun, 02 Jan 2022 20:20:46 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from build-robot-token-rwfsb (rw)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
build-robot-token-rwfsb:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 7200
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 8s default-scheduler Successfully assigned default/nginx to node2.noisedu.cn
Normal Pulled 7s kubelet Container image "10.0.0.55:80/mykubernetes/nginx:1.21.3" already present on machine
Normal Created 6s kubelet Created container nginx
Normal Started 6s kubelet Started container nginx
```
## 3.2 UA
### user account 至少分为三个部分:
#### 用户条目 - credentials设定具体的user account名称
#### 集群 - cluster 设定该user account所工作的区域
#### 上下文环境 - context 设定用户和集群的关系
```sh
[16:34:11 root@master1 ~]#kubectl config view
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://10.0.0.70:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubernetes-admin
name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
```
创建UA的流程主要是分为7个步骤,最后的结果和上面类似.
1. 创建私钥
```sh
[17:02:17 root@master1 security]#cd /etc/kubernetes/pki/
[17:03:35 root@master1 pki]#umask 077; openssl genrsa -out noiselys.key 2048
Generating RSA private key, 2048 bit long modulus (2 primes)
..................................................................................+++++
..+++++
e is 65537 (0x010001)
[17:04:14 root@master1 pki]#ll
total 72
drwxr-xr-x 3 root root 4096 Jan 3 17:04 ./
drwxr-xr-x 5 root root 4096 Dec 12 00:18 ../
-rw-r--r-- 1 root root 1294 Dec 12 00:18 apiserver.crt
-rw-r--r-- 1 root root 1155 Dec 12 00:18 apiserver-etcd-client.crt
-rw------- 1 root root 1675 Dec 12 00:18 apiserver-etcd-client.key
-rw------- 1 root root 1675 Dec 12 00:18 apiserver.key
-rw-r--r-- 1 root root 1164 Dec 12 00:18 apiserver-kubelet-client.crt
-rw------- 1 root root 1679 Dec 12 00:18 apiserver-kubelet-client.key
-rw-r--r-- 1 root root 1066 Dec 11 23:29 ca.crt
-rw------- 1 root root 1675 Dec 11 23:29 ca.key
drwxr-xr-x 2 root root 4096 Dec 11 23:29 etcd/
-rw-r--r-- 1 root root 1078 Dec 11 23:29 front-proxy-ca.crt
-rw------- 1 root root 1679 Dec 11 23:29 front-proxy-ca.key
-rw-r--r-- 1 root root 1119 Dec 12 00:18 front-proxy-client.crt
-rw------- 1 root root 1679 Dec 12 00:18 front-proxy-client.key
-rw------- 1 root root 1679 Jan 3 17:04 noiselys.key
-rw------- 1 root root 1675 Dec 11 23:29 sa.key
-rw------- 1 root root 451 Dec 11 23:29 sa.pub
```
2. 基于私钥文件创建证书签名请求
```sh
[17:04:17 root@master1 pki]#openssl req -new -key noiselys.key -out noiselys.csr -subj "/CN=noiselys/O=noiselys"
Can't load /root/.rnd into RNG
140623717016000:error:2406F079:random number generator:RAND_load_file:Cannot open file:../crypto/rand/randfile.c:88:Filename=/root/.rnd
# 若是报这个error,可执行下面
[17:07:23 root@master1 pki]#cd /root
[17:08:00 root@master1 ~]#openssl rand -writerand .rnd
# 再次生成证书签名文件
[17:08:29 root@master1 pki]#rm -f noiselys.csr
[17:08:35 root@master1 pki]#openssl req -new -key noiselys.key -out noiselys.csr -subj "/CN=noiselys/O=noiselys"
[17:08:41 root@master1 pki]#ll
total 76
drwxr-xr-x 3 root root 4096 Jan 3 17:08 ./
drwxr-xr-x 5 root root 4096 Dec 12 00:18 ../
-rw-r--r-- 1 root root 1294 Dec 12 00:18 apiserver.crt
-rw-r--r-- 1 root root 1155 Dec 12 00:18 apiserver-etcd-client.crt
-rw------- 1 root root 1675 Dec 12 00:18 apiserver-etcd-client.key
-rw------- 1 root root 1675 Dec 12 00:18 apiserver.key
-rw-r--r-- 1 root root 1164 Dec 12 00:18 apiserver-kubelet-client.crt
-rw------- 1 root root 1679 Dec 12 00:18 apiserver-kubelet-client.key
-rw-r--r-- 1 root root 1066 Dec 11 23:29 ca.crt
-rw------- 1 root root 1675 Dec 11 23:29 ca.key
drwxr-xr-x 2 root root 4096 Dec 11 23:29 etcd/
-rw-r--r-- 1 root root 1078 Dec 11 23:29 front-proxy-ca.crt
-rw------- 1 root root 1679 Dec 11 23:29 front-proxy-ca.key
-rw-r--r-- 1 root root 1119 Dec 12 00:18 front-proxy-client.crt
-rw------- 1 root root 1679 Dec 12 00:18 front-proxy-client.key
-rw------- 1 root root 915 Jan 3 17:08 noiselys.csr
-rw------- 1 root root 1679 Jan 3 17:04 noiselys.key
-rw------- 1 root root 1675 Dec 11 23:29 sa.key
-rw------- 1 root root 451 Dec 11 23:29 sa.pub
```
3. 基于私钥和签名请求生产证书文件
```sh
[17:09:32 root@master1 pki]#openssl x509 -req -in noiselys.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out noiselys.crt -days 365
Signature ok
subject=CN = noiselys, O = noiselys
Getting CA Private Key
[17:11:44 root@master1 pki]#ll noise*
-rw------- 1 root root 1017 Jan 3 17:11 noiselys.crt
-rw------- 1 root root 915 Jan 3 17:08 noiselys.csr
-rw------- 1 root root 1679 Jan 3 17:04 noiselys.key
[17:11:49 root@master1 pki]#openssl x509 -in noiselys.crt -text -noout
Certificate:
Data:
Version: 1 (0x0)
Serial Number:
45:60:a7:2a:61:6f:67:25:67:ed:2a:8f:6f:77:0b:f9:55:4c:b7:6c
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN = kubernetes
Validity
Not Before: Jan 3 09:11:44 2022 GMT
Not After : Jan 3 09:11:44 2023 GMT
Subject: CN = noiselys, O = noiselys
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (2048 bit)
Modulus:
00:e4:d1:fd:14:84:5f:f4:e6:5c:87:c3:c0:8e:f0:
8c:dc:16:c7:b3:76:42:46:a6:5d:ab:a2:3f:7a:25:
3d:92:64:af:49:27:ab:49:97:c4:ae:89:79:f5:a8:
60:40:b6:b2:44:bc:87:fd:79:75:0f:7e:99:6f:e0:
bd:fe:59:e4:6d:52:82:64:bd:a5:f5:b2:27:39:72:
fb:57:25:8c:54:f1:ce:93:d4:59:18:02:ae:d0:31:
33:07:1e:70:ee:e2:db:0b:31:26:c6:a7:64:a0:99:
5f:a7:57:17:09:98:d9:e4:12:a4:89:e6:fe:33:61:
f7:14:7c:b6:be:9d:5c:0d:57:32:b4:c1:2b:48:db:
97:ec:7a:64:f0:17:63:b3:35:16:4d:b5:ff:0d:69:
09:55:3b:7f:ea:2b:a2:62:54:37:1c:43:94:e8:c6:
f2:cb:63:85:76:61:71:1d:5b:98:ab:46:c9:4a:b1:
68:7e:ea:a0:fb:bc:b1:ba:16:f1:65:82:43:bc:56:
27:51:03:f3:9b:bd:c3:7d:f6:6a:eb:65:41:88:51:
08:21:36:c7:c3:ec:91:fc:8a:5c:5e:ea:fe:c0:46:
7a:18:69:8a:9e:cb:5a:cf:de:cc:e6:16:22:dd:96:
ca:bb:4d:fb:ed:44:e8:59:14:b8:ab:59:a3:c6:8d:
52:57
Exponent: 65537 (0x10001)
Signature Algorithm: sha256WithRSAEncryption
bb:61:ef:ad:91:da:b7:ac:45:c2:f0:6e:f8:a0:f4:66:06:aa:
cd:e1:db:4c:a3:43:24:20:88:45:86:3e:1c:5f:88:9b:85:d1:
70:52:47:13:fa:ba:e1:87:2a:08:b1:a8:fe:5a:5f:7a:01:46:
b4:6d:9a:fd:2c:14:6b:eb:23:b1:a6:31:2f:7b:2d:da:9f:04:
fa:f5:19:f1:d9:41:5b:0a:7b:3e:b7:b9:3b:32:b2:12:cc:04:
38:4c:1f:63:df:c9:c5:d5:82:38:a2:7c:5f:27:9f:94:46:3c:
cb:c1:32:6c:ed:c5:02:b4:2f:bf:9f:b7:66:24:18:f0:a7:80:
71:68:5a:4f:30:02:f3:ef:fb:0b:9f:2b:ce:b1:59:8d:f7:d3:
8a:92:88:2e:9c:16:91:17:ec:b7:4c:2a:87:81:c5:f9:30:ed:
94:dd:b2:b2:29:fb:86:f1:db:7f:11:d3:ea:ac:46:a3:bb:65:
ac:84:cc:04:77:7b:3d:70:bf:34:f5:59:b0:4b:b4:fa:af:8d:
2b:d0:83:aa:cc:7f:0a:68:d0:a8:40:3a:5c:fe:e7:cc:45:5e:
0f:dd:01:42:69:3b:9d:40:d0:a0:95:ff:42:42:cf:6b:4e:8a:
00:d3:4c:bb:37:57:65:51:2a:10:0a:15:33:2d:58:2f:a9:d4:
50:d7:c3:b4
```
4. 基于tls文件在k8s上创建用户
```sh
[17:12:30 root@master1 pki]#kubectl config set-credentials noiselys --client-certificate=noiselys.crt --client-key=noiselys.key --embed-certs=true --kubeconfig=/data/noiselys.conf
User "noiselys" set.
[17:15:11 root@master1 pki]#kubectl config view --kubeconfig=/data/noiselys.conf
apiVersion: v1
clusters: null
contexts: null
current-context: ""
kind: Config
preferences: {}
users:
- name: noiselys
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
```
5. 创建工作区域 - cluster
```shell
[17:16:54 root@master1 pki]#kubectl config set-cluster mycluster --server="https://10.0.0.70:6443" --certificate-authority=/etc/kubernetes/pki/ca.crt --embed-certs=true --kubeconfig=/data/noiselys.conf
Cluster "mycluster" set.
[17:20:23 root@master1 pki]#kubectl config view --kubeconfig=/data/noiselys.conf
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://10.0.0.70:6443
name: mycluster
contexts: null
current-context: ""
kind: Config
preferences: {}
users:
- name: noiselys
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
```
6. 将cluster和user关联起来 - context
```shell
[17:20:39 root@master1 pki]#kubectl config set-context noiselys@mycluster --cluster=mycluster --user=noiselys --kubeconfig=/data/noiselys.conf
Context "noiselys@mycluster" created.
[17:22:37 root@master1 pki]#kubectl config view --kubeconfig=/data/noiselys.conf
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://10.0.0.70:6443
name: mycluster
contexts:
- context:
cluster: mycluster
user: noiselys
name: noiselys@mycluster
current-context: ""
kind: Config
preferences: {}
users:
- name: noiselys
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
```
7. 验证结果
```sh
# 上面的current-context是空,我们需要切换一下用户
[17:24:53 root@master1 pki]#kubectl config use-context noiselys@mycluster --kubeconfig=/data/noiselys.conf
Switched to context "noiselys@mycluster".
[17:25:01 root@master1 pki]#kubectl config view --kubeconfig=/data/noiselys.conf
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://10.0.0.70:6443
name: mycluster
contexts:
- context:
cluster: mycluster
user: noiselys
name: noiselys@mycluster
current-context: noiselys@mycluster
kind: Config
preferences: {}
users:
- name: noiselys
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
# 但是关于权限我们还未设置,所以无法得到资源信息
[17:25:09 root@master1 pki]#kubectl get pod --kubeconfig=/data/noiselys.conf
Error from server (Forbidden): pods is forbidden: User "noiselys" cannot list resource "pods" in API group "" in the namespace "default"
# 关于查看conf,我们有三种方法,从下面可以看出,推荐第一种
# 如果想多个配置文件并行,可以加入到环境变量KUBECONFIG,用:隔开
[17:26:05 root@master1 pki]#kubectl config --help
Modify kubeconfig files using subcommands like "kubectl config set current-context my-context"
The loading order follows these rules:
1. If the --kubeconfig flag is set, then only that file is loaded. The flag may only be set once and no merging takes
place.
2. If $KUBECONFIG environment variable is set, then it is used as a list of paths (normal path delimiting rules for
your system). These paths are merged. When a value is modified, it is modified in the file that defines the stanza. When
a value is created, it is created in the first file that exists. If no files in the chain exist, then it creates the
last file in the list.
3. Otherwise, ${HOME}/.kube/config is used and no merging takes place.
```
##