0x00 前言
在 kubernetes 中,常用如下指令进入一个 Pod(在 Pod 运行命令),或者说 获取正在运行容器的 Shell:
kubectl exec ${pod_name} -- date
kubectl exec -it ${pod_name} -- /bin/bash
既然是 Shell 操作,基于零信任的理念,如何实现对这个过程的审计与管控呢,具体来说需要完成这么几个事情:
- 权限的托管,简单说就是哪个账号可以访问哪个 Pod(或其他 kubernetes 资源)
- 登录过程的可信任,链路是可信任的
- 对整个过程的审计(会话审计)
0x01 实现思路
首先了解下 kubernetes 的 exec 的工作原理,参见此文章 Kubectl exec 的工作原理解读。先看看 kubectl exec 的详细日志,如下:
# kubectl -v=7 exec -it nginx -- /bin/bash
I0125 10:51:55.434043 28053 loader.go:359] Config loaded from file: /home/isim/.kube/kind-config-linkerd
I0125 10:51:55.438595 28053 round_trippers.go:416] GET https://127.0.0.1:38545/api/v1/namespaces/default/pods/nginx
I0125 10:51:55.438607 28053 round_trippers.go:423] Request Headers:
I0125 10:51:55.438611 28053 round_trippers.go:426] Accept: application/json, */*
I0125 10:51:55.438615 28053 round_trippers.go:426] User-Agent: kubectl/v1.15.0 (linux/amd64) kubernetes/e8462b5
I0125 10:51:55.445942 28053 round_trippers.go:441] Response Status: 200 OK in 7 milliseconds
I0125 10:51:55.451050 28053 round_trippers.go:416] POST https://127.0.0.1:38545/api/v1/namespaces/default/pods/nginx/exec?command=%2Fbin%2Fbash&container=nginx&stdin=true&stdout=true&tty=true
I0125 10:51:55.451063 28053 round_trippers.go:423] Request Headers:
I0125 10:51:55.451067 28053 round_trippers.go:426] X-Stream-Protocol-Version: v4.channel.k8s.io
I0125 10:51:55.451090 28053 round_trippers.go:426] X-Stream-Protocol-Version: v3.channel.k8s.io
I0125 10:51:55.451096 28053 round_trippers.go:426] X-Stream-Protocol-Version: v2.channel.k8s.io
I0125 10:51:55.451100 28053 round_trippers.go:426] X-Stream-Protocol-Version: channel.k8s.ioI0125 10:51:55.451121 28053 round_trippers.go:426] User-Agent: kubectl/v1.15.0 (linux/amd64) kubernetes/e8462b5
I0125 10:51:55.465690 28053 round_trippers.go:441] Response Status: 101 Switching Protocols in 14 milliseconds
root@nginx:/#
总结下上面的过程:
1、两个连续 HTTP 请求
- GET 请求用来获取 Pod 信息:
https://127.0.0.1:38545/api/v1/namespaces/default/pods/nginx - POST 请求调用 Pod 的子资源 exec 在容器内执行命令(进入容器):
https://127.0.0.1:38545/api/v1/namespaces/default/pods/nginx/exec?command=%2Fbin%2Fbash&container=nginx&stdin=true&stdout=true&tty=true
子资源(subresource)隶属于某个 K8S 资源,表示为父资源下方的子路径,例如 /logs、/status、/scale、/exec 等。其中每个子资源支持的操作根据对象的不同而改变
2、APIServer 返回了 101 Ugrade 响应,向客户端表示已切换到 SPDY 协议
ps:SPDY 允许在单个 TCP 连接上复用独立的 Stdin/Stdout/Stderr/Spdy-error 流
从上面的过程来看,很容易联想到使用中间人(MITM)的方式来实现对此过程的劫持,如下图所示:

即需要实现一个 MITM,完成如下的功能:
- 构造一个 fake kubernetes API-Server,实现满足 exec 场景的 API 劫持及转发
- 内置一个与真正集群打通的 kubectl 客户端(或者实现相关的 kubectl 请求发起的接口)
- 实现对 User 的鉴权、认证
- 打通到真实 kubernetes 集群 Pod 访问的整个通道
- 整个流程中 CA 证书的签发及生效(推荐使用证书,这样 Kubernetes 所有的安全访问都是基于 CA 证书的)
0x02 业界实现
业界有两款开源的实现:
Teleport
Teleport 的整体架构如下:

关于 kubernetes 的详细实现架构如下:

This model allows Teleport proxy to work with any standard Kubernetes clusters supporting out of the box CSR API.
- User uses tsh login with proxy, nothing changes compared to usual SSH flow.
- Client receives short lived x509 certs and SSH certs issued by Telepoort CA. User’s kubernetes configuration is updated with x509 certs and credentials.
- Kubernetes API request goes to teleport proxy, as set up by kubeconfig
- Before processing the request, proxy needs a valid certificate recognized by Kubernetes cluster. Proxy delegates this task to the auth server and passes the list of kubernetes groups derived from user roles.
- Auth server uses Kubernetes native CSR API to send and approve request. Auth server acts both as a requester and approver.
- Proxy can now use the certificates issued by Kubernetes CA to terminate the request and proxy it to the auth server, capture the exec traffic
Pomerium
pomerium 的实现如下:


0x03 Teleport 的方案分析

参考
- Kubectl exec 的工作原理解读
- How It Works — kubectl exec
- 图解 kubernetes 命令执行核心实现
- Teleport - Kubernetes support
- Teleport Kubernetes Access Guide
- Teleport Kubernetes: how it works
- pomerium - Overview
- pomerium - kubernetes
- Achieving Cloud Native Security and Compliance with Teleport
- Architecture - pomerium
FEATURED TAGS
Latex
gRPC
负载均衡
OpenSSH
Authentication
Consul
Etcd
Kubernetes
性能优化
Python
分布式锁
WebConsole
后台开发
Golang
OpenSource
Nginx
Vault
网络安全
Perl
分布式理论
Raft
正则表达式
Redis
分布式
限流
go-redis
微服务
反向代理
ReverseProxy
Cache
缓存
连接池
OpenTracing
GOMAXPROCS
GoMicro
微服务框架
日志
zap
Pool
Kratos
Hystrix
熔断
并发
Pipeline
证书
Prometheus
Metrics
PromQL
Breaker
定时器
Timer
Timeout
Kafka
Xorm
MySQL
Fasthttp
bytebufferpool
任务队列
队列
异步队列
GOIM
Pprof
errgroup
consistent-hash
Zinx
网络框架
设计模式
HTTP
Gateway
Queue
Docker
网关
Statefulset
NFS
Machinery
Teleport
Zero Trust
Oxy
存储
Confd
热更新
OAuth
SAML
OpenID
Openssl
AES
微服务网关
IM
KMS
安全
数据结构
hashtable
Sort
Asynq
基数树
Radix
Crontab
热重启
系统编程
sarama
Go-Zero
RDP
VNC
协程池
UDP
hashmap
网络编程
自适应技术
环形队列
Ring Buffer
Circular Buffer
InnoDB
timewheel
GroupCache
Jaeger
GOSSIP
CAP
Bash
websocket
事务
GC
TLS
singleflight
闭包
Helm
network
iptables
MITM
HTTPS
Tap
Tun
路由
wireguard
gvisor
Git
NAT
协议栈
Envoy
FRP
DPI
gopacket
Cgroup
Namespace
DNS
eBPF
GoZero
Gost
Clash
Tracee
gopsutil
Linux
Kernel
HIDS
ELKEID
XDP
TC
Systemd
DDoS
DPDK
netlink
BCC
rootkit
bpftrace
AI
TCP
eino
Memory
Overlayfs
CVE