本章从单个节点和整个kubernetes集群角度考量容器的安全配置,并且在静态配置和动态行为两个方面给出了具体的考量标准和容器安全解决方案。
容器安全 | 静态配置 | 动态行为 |
---|---|---|
节点(docker) | CIS Docker Benchmark检测评分 | Docker镜像漏洞库、容器安全配置运行 |
集群(kubernetes) | Sonobuoy合规检测评分、kubernetes CIS 安全基线检测评分 | Falco容器动态行为安全检测审计 |
注:CIS Docker Benchmark是docker公司与互联网安全中心(CIS)合作,制作了一份基准文档。基准文档涵盖了运行 Docker 的宿主(系统)的配置、Docker 本身的配置,以及在 Docker 管理下运行的容器的配置。
注:Sonobuoy 是一个诊断工具,它通过一致性测试 (conformance testing) 来快速了解 Kubernetes 集群的状态。一致性测试用于检查一个集群是否被正确地配置了,并且它的行为是否符合 Kubernetes 官方规定的规范。Sonobuoy 已经被云原生计算基金会 CNCF 采纳为一致性认证 (Certified Kubernetes Conformance Program) 的基础性技术,这一认证是 Kubernetes 供应商一个重要的认证。
注:kubernetes CIS 安全基线是互联网安全中心(CIS)针对kubernetes制定的配置策略基准(即CIS基准),使组织可以改善其安全性和合规性计划及态势。容器安全厂商Aquq以CIS推出的K8s Benchmark作为基础,开源出了一套安全检测工具Kube-bench。
注:Docker镜像漏洞库:
CVE数据库上已知漏洞;
Debian、RedHat或Ubuntu安全团队编写的特定于发行版的漏洞列表;
目前常用开源的容器镜像分析扫描器有Anchore、Clair、Dagda、Trivy。
注:容器安全配置运行:AppArmor、selinux、seccomp/seccomp-bpf。这些都属于linux框架本身,它们可以在docker容器启动时通过选项--security-opt等指定配置,也可以配置在Kubernetes Pod安全策略(pod-security-policy)中。
AppArmor将安全配置文件附加到容器中运行的进程,定义文件系统特权、网络访问规则、库链接等。它是一个强制访问控制(或MAC)系统,这意味着它将阻止禁止的操作发生。
安全增强Linux(SELinux)是一个Linux内核安全模块,在某些方面类似,并且经常与AppArmor相比较。SELinux比AppArmor更强大、更细粒度、更灵活,这是以学习曲线陡峭和复杂性增加为代价的。
Seccomp和seccomp -bpf允许过滤系统调用,阻止执行可能对底层主机OS有危险的系统调用,这些调用对于用户域二进制文件的常规操作是不需要的。它与Falco有一些细微的相似之处,尽管seccomp不知道容器的存在。
注:Falco 是一个云原生运行时安全系统,可与容器和原始 Linux 主机一起使用。它由 Sysdig 开发,是 Cloud Native Computing Foundation(云原生计算基金会)的一个沙箱项目。Falco 的工作方式是查看文件更改、网络活动、进程表和其他数据是否存在可疑行为,然后通过可插拔后端发送警报。通过内核模块或扩展的 BPF 探测器在主机的系统调用级别检查事件。Falco 包含一组丰富的规则,可以编辑这些规则以标记特定的异常行为,并为正常的计算机操作创建允许列表。
开源容器镜像扫描器Anchore、Clair、Dagda、Trivy对比
名称 | Harbor集成扫描 | 快速部署方式 | 漏洞库来源 | 特色功能点 |
---|---|---|---|---|
Anchore | 能 | docker-compose部署,使用postgres数据库 | CVE数据库、Debian、RedHat、Ubuntu等os安全团队发布的漏洞库、github发布语言包java、python、npm等漏洞库 | 应用用户定义的策略来实现自定义安全检查,例如:Dockerfile检查、凭证泄漏、特定于语言的包(npm、maven等)、软件许可证等等 |
Clair | 能 | docker-compose部署,使用postgres数据库 | CVE数据库、Debian、RedHat或Ubuntu安全团队发布的漏洞源 | 主要关注漏洞扫描和CVE匹配部分,尽管它通过可插入驱动程序的实现为用户提供了一定的可扩展性。 |
Dagda | 不能,只能手动依次扫描镜像 | docker-compose部署,使用mongdb数据库 | CVE数据库 | 两个显著的特性使得Dagda不同于类似的容器安全工具:1)它与ClamAV集成在一起,不仅可以作为一个容器镜像扫描器,还可以作为杀毒软件)2) Dagda还提供了运行时保护功能,从Docker守护进程收集实时事件,并与CNCF的Falco集成来收集运行时容器安全事件。 |
Trivv | 能 | rpm/deb包,二进制 | CVE数据库 | 只使用一个二进制文件,不需要安装数据库或其他库,易于集成。 |
开源安全工具在保护基于容器的基础结构中起着重要作用。可以根据业务需求和优先级选择适宜的工具(组合)进行云架构下安全保障:比如使用Clair进行容器镜像合规性分析,使用Dagda结合Falco进行安全审计和对已知漏洞进行静态分析,用Anchore自定义策略进行组合安全保障。
容器存储限制:xfs
容器安全配置运行:AppArmor、selinux、seccomp/seccomp-bpf、pod-security-policy
harbor默认采用clair作为镜像扫描器,可以增添多个镜像扫描器。
镜像扫描
扫描后的镜像busybox
扫描后的镜像nginx
harbor添加镜像扫描器anchore
1、使用docker-compose部署anchore,anchore会从漏洞库取数据存入postgres数据库,因此,首次部署需要联网。安装anchore-cli或者登入anchore-api容器执行以下查看抓取数据进度
xww@xww-NUC8i5BEH:/media/xww/sda1/dockersecurity/anchore$ anchore-cli system feeds list
Feed Group LastSync RecordCount
github github:composer pending None
github github:gem pending None
github github:java pending None
github github:npm pending None
github github:nuget pending None
github github:python pending None
nvdv2 nvdv2:cves pending None
vulnerabilities alpine:3.10 2020-06-11T08:11:25.691831 1725
vulnerabilities alpine:3.11 2020-06-11T08:11:50.357710 1904
vulnerabilities alpine:3.3 2020-06-11T08:12:16.967769 457
vulnerabilities alpine:3.4 2020-06-11T08:12:23.352002 681
vulnerabilities alpine:3.5 2020-06-11T08:12:32.694881 875
vulnerabilities alpine:3.6 2020-06-11T08:12:44.503788 1051
vulnerabilities alpine:3.7 2020-06-11T08:13:01.670516 1395
vulnerabilities alpine:3.8 2020-06-11T08:13:21.401048 1486
vulnerabilities alpine:3.9 2020-06-11T08:13:43.141225 1558
vulnerabilities amzn:2 2020-06-11T08:14:09.621640 361
vulnerabilities centos:5 2020-06-11T08:14:26.977266 1347
vulnerabilities centos:6 2020-06-11T08:15:06.678641 1413
vulnerabilities centos:7 2020-06-11T08:15:53.491927 1077
vulnerabilities centos:8 2020-06-11T08:16:41.130828 292
vulnerabilities debian:10 2020-06-11T08:17:00.163989 22921
vulnerabilities debian:11 2020-06-11T08:22:16.645022 20066
vulnerabilities debian:7 pending 15000
...
2、部署harbor-adapter-anchore
到kubernetes集群中
创建anchore-creds的secret保存anchore用户名与密码
kubectl create secret generic anchore-creds --from-literal=username=admin --from-literal=password=foobar
harbor-adapter-anchore的yaml文件中,注意配置anchore endpoint,username,password。
...
spec:
containers:
- name: adapter
image: anchore/harbor-scanner-adapter:1.0.0
imagePullPolicy: IfNotPresent
env:
- name: SCANNER_ADAPTER_LISTEN_ADDR
value: ":8080"
- name: ANCHORE_ENDPOINT
value: "http://192.168.50.2:8228"
- name: ANCHORE_USERNAME
valueFrom:
secretKeyRef:
name: anchore-creds
key: username
- name: ANCHORE_PASSWORD
valueFrom:
secretKeyRef:
name: anchore-creds
key: password
...
anchore用户名密码默认为admin/foobar 可通过命令创建新的用户名与密码
anchore-cli account add harbor
anchore-cli account user add --account harbor harbor harboruserpass123
3、在harbor上配置新增scan,endpoint配置为harbor-adapter-anchore的service名称与端口
设置anchore为默认镜像扫描器,然后扫描镜像
nginx镜像在harbor自带clair镜像扫描器扫描没有问题,但是在anchore镜像扫描器发现漏洞。因为clair处于离线安装没有完整拉取其漏洞库。所以镜像漏洞库的维护与更新非常重要。
查看clair容器日志,发现其一直没有完全获取其漏洞库,保持以2分钟的幂次方等待尝试拉取数据。
root@focal-1:/home/test# kubectl logs harbor-harbor-clair-6cffc7d8c6-sjklz -c clair
ls: /harbor_cust_cert: No such file or directory
{"Event":"running database migrations","Level":"info","Location":"pgsql.go:216","Time":"2020-06-11 02:39:01.677047"}
{"Event":"database migration ran successfully","Level":"info","Location":"pgsql.go:223","Time":"2020-06-11 02:39:01.721602"}
{"Event":"starting health API","Level":"info","Location":"api.go:85","Time":"2020-06-11 02:39:01.722089","port":6061}
{"Event":"starting main API","Level":"info","Location":"api.go:52","Time":"2020-06-11 02:39:01.722018","port":6060}
{"Event":"notifier service is disabled","Level":"info","Location":"notifier.go:77","Time":"2020-06-11 02:39:01.722265"}
{"Event":"updater service started","Level":"info","Location":"updater.go:83","Time":"2020-06-11 02:39:01.722374","lock identifier":"e4b8db14-a191-4259-a935-ac396c11d38c"}
{"Event":"updating vulnerabilities","Level":"info","Location":"updater.go:192","Time":"2020-06-11 02:39:01.770736"}
{"Event":"fetching vulnerability updates","Level":"info","Location":"updater.go:239","Time":"2020-06-11 02:39:01.770775"}
{"Event":"Start fetching vulnerabilities","Level":"info","Location":"ubuntu.go:85","Time":"2020-06-11 02:39:01.770827","package":"Ubuntu"}
{"Event":"Start fetching vulnerabilities","Level":"info","Location":"alpine.go:52","Time":"2020-06-11 02:39:01.770889","package":"Alpine"}
{"Event":"Start fetching vulnerabilities","Level":"info","Location":"amzn.go:84","Time":"2020-06-11 02:39:01.770957","package":"Amazon Linux 2"}
{"Event":"Start fetching vulnerabilities","Level":"info","Location":"amzn.go:84","Time":"2020-06-11 02:39:01.771123","package":"Amazon Linux 2018.03"}
{"Event":"Start fetching vulnerabilities","Level":"info","Location":"oracle.go:119","Time":"2020-06-11 02:39:01.771138","package":"Oracle Linux"}
{"Event":"Start fetching vulnerabilities","Level":"info","Location":"rhel.go:92","Time":"2020-06-11 02:39:01.771201","package":"RHEL"}
{"Event":"Start fetching vulnerabilities","Level":"info","Location":"debian.go:63","Time":"2020-06-11 02:39:01.771307","package":"Debian"}
{"Event":"could not pull ubuntu-cve-tracker repository","Level":"error","Location":"ubuntu.go:174","Time":"2020-06-11 02:39:12.392148","error":"exit status 128","output":"Cloning into '.'...\nfatal: unable to access 'https://git.launchpad.net/ubuntu-cve-tracker/': Could not resolve host: git.launchpad.net\n"}
{"Event":"an error occured when fetching update","Level":"error","Location":"updater.go:246","Time":"2020-06-11 02:39:12.392203","error":"could not download requested resource","updater name":"ubuntu"}
{"Event":"could not download Debian's update","Level":"error","Location":"debian.go:68","Time":"2020-06-11 02:39:21.784230","error":"Get https://security-tracker.debian.org/tracker/data/json: dial tcp: lookup security-tracker.debian.org on 10.233.0.3:53: server misbehaving"}
{"Event":"an error occured when fetching update","Level":"error","Location":"updater.go:246","Time":"2020-06-11 02:39:21.784393","error":"could not download requested resource","updater name":"debian"}
{"Event":"could not download mirror list","Level":"error","Location":"amzn.go:180","Time":"2020-06-11 02:39:21.786702","error":"Get https://cdn.amazonlinux.com/2/core/latest/x86_64/mirror.list: dial tcp: lookup cdn.amazonlinux.com on 10.233.0.3:53: server misbehaving"}
{"Event":"an error occured when fetching update","Level":"error","Location":"updater.go:246","Time":"2020-06-11 02:39:21.786869","error":"could not download requested resource","updater name":"amzn2"}
{"Event":"could not download RHEL's update list","Level":"error","Location":"rhel.go:106","Time":"2020-06-11 02:39:21.816098","error":"Get https://www.redhat.com/security/data/oval/: dial tcp: lookup www.redhat.com on 10.233.0.3:53: server misbehaving"}
{"Event":"an error occured when fetching update","Level":"error","Location":"updater.go:246","Time":"2020-06-11 02:39:21.816222","error":"could not download requested resource","updater name":"rhel"}
{"Event":"could not download mirror list","Level":"error","Location":"amzn.go:180","Time":"2020-06-11 02:39:21.816506","error":"Get http://repo.us-west-2.amazonaws.com/2018.03/updates/x86_64/mirror.list: dial tcp: lookup repo.us-west-2.amazonaws.com on 10.233.0.3:53: server misbehaving"}
{"Event":"an error occured when fetching update","Level":"error","Location":"updater.go:246","Time":"2020-06-11 02:39:21.816929","error":"could not download requested resource","updater name":"amzn1"}
{"Event":"could not download Oracle's update list","Level":"error","Location":"oracle.go:134","Time":"2020-06-11 02:39:21.821327","error":"Get https://linux.oracle.com/oval/: dial tcp: lookup linux.oracle.com on 10.233.0.3:53: server misbehaving"}
{"Event":"an error occured when fetching update","Level":"error","Location":"updater.go:246","Time":"2020-06-11 02:39:21.821466","error":"could not download requested resource","updater name":"oracle"}
{"Event":"could not pull alpine-secdb repository","Level":"error","Location":"alpine.go:186","Time":"2020-06-11 02:39:22.411116","error":"exit status 128","output":"Cloning into '.'...\nfatal: unable to access 'https://github.com/alpinelinux/alpine-secdb/': Could not resolve host: github.com\n"}
{"Event":"an error occured when fetching update","Level":"error","Location":"updater.go:246","Time":"2020-06-11 02:39:22.411172","error":"could not download requested resource","updater name":"alpine"}
{"Event":"adding metadata to vulnerabilities","Level":"info","Location":"updater.go:279","Time":"2020-06-11 02:39:22.411192"}
{"Event":"could not get NVD data feed hash","Level":"warning","Location":"nvd.go:161","Time":"2020-06-11 02:39:22.416158","data feed name":"2002","error":"Get https://nvd.nist.gov/feeds/json/cve/1.0/nvdcve-1.0-2002.meta: dial tcp: lookup nvd.nist.gov on 10.233.0.3:53: server misbehaving"}
{"Event":"could not get NVD data feed hash","Level":"warning","Location":"nvd.go:161","Time":"2020-06-11 02:39:22.419184","data feed name":"2003","error":"Get https://nvd.nist.gov/feeds/json/cve/1.0/nvdcve-1.0-2003.meta: dial tcp: lookup nvd.nist.gov on 10.233.0.3:53: server misbehaving"}
{"Event":"could not get NVD data feed hash","Level":"warning","Location":"nvd.go:161","Time":"2020-06-11 02:39:22.420803","data feed name":"2004","error":"Get https://nvd.nist.gov/feeds/json/cve/1.0/nvdcve-1.0-2004.meta: dial tcp: lookup nvd.nist.gov on 10.233.0.3:53: server misbehaving"}
{"Event":"could not get NVD data feed hash","Level":"warning","Location":"nvd.go:161","Time":"2020-06-11 02:39:22.422519","data feed name":"2005","error":"Get https://nvd.nist.gov/feeds/json/cve/1.0/nvdcve-1.0-2005.meta: dial tcp: lookup nvd.nist.gov on 10.233.0.3:53: server misbehaving"}
{"Event":"could not get NVD data feed hash","Level":"warning","Location":"nvd.go:161","Time":"2020-06-11 02:39:22.424148","data feed name":"2006","error":"Get https://nvd.nist.gov/feeds/json/cve/1.0/nvdcve-1.0-2006.meta: dial tcp: lookup nvd.nist.gov on 10.233.0.3:53: server misbehaving"}
{"Event":"could not get NVD data feed hash","Level":"warning","Location":"nvd.go:161","Time":"2020-06-11 02:39:22.425739","data feed name":"2007","error":"Get https://nvd.nist.gov/feeds/json/cve/1.0/nvdcve-1.0-2007.meta: dial tcp: lookup nvd.nist.gov on 10.233.0.3:53: server misbehaving"}
{"Event":"could not get NVD data feed hash","Level":"warning","Location":"nvd.go:161","Time":"2020-06-11 02:39:22.427580","data feed name":"2008","error":"Get https://nvd.nist.gov/feeds/json/cve/1.0/nvdcve-1.0-2008.meta: dial tcp: lookup nvd.nist.gov on 10.233.0.3:53: server misbehaving"}
{"Event":"could not get NVD data feed hash","Level":"warning","Location":"nvd.go:161","Time":"2020-06-11 02:39:22.429501","data feed name":"2009","error":"Get https://nvd.nist.gov/feeds/json/cve/1.0/nvdcve-1.0-2009.meta: dial tcp: lookup nvd.nist.gov on 10.233.0.3:53: server misbehaving"}
{"Event":"could not get NVD data feed hash","Level":"warning","Location":"nvd.go:161","Time":"2020-06-11 02:39:22.431423","data feed name":"2010","error":"Get https://nvd.nist.gov/feeds/json/cve/1.0/nvdcve-1.0-2010.meta: dial tcp: lookup nvd.nist.gov on 10.233.0.3:53: server misbehaving"}
{"Event":"could not get NVD data feed hash","Level":"warning","Location":"nvd.go:161","Time":"2020-06-11 02:39:22.433901","data feed name":"2011","error":"Get https://nvd.nist.gov/feeds/json/cve/1.0/nvdcve-1.0-2011.meta: dial tcp: lookup nvd.nist.gov on 10.233.0.3:53: server misbehaving"}
{"Event":"could not get NVD data feed hash","Level":"warning","Location":"nvd.go:161","Time":"2020-06-11 02:39:27.440569","data feed name":"2012","error":"Get https://nvd.nist.gov/feeds/json/cve/1.0/nvdcve-1.0-2012.meta: dial tcp: lookup nvd.nist.gov on 10.233.0.3:53: server misbehaving"}
{"Event":"could not get NVD data feed hash","Level":"warning","Location":"nvd.go:161","Time":"2020-06-11 02:39:27.470485","data feed name":"2013","error":"Get https://nvd.nist.gov/feeds/json/cve/1.0/nvdcve-1.0-2013.meta: dial tcp: lookup nvd.nist.gov on 10.233.0.3:53: server misbehaving"}
{"Event":"could not get NVD data feed hash","Level":"warning","Location":"nvd.go:161","Time":"2020-06-11 02:39:27.475509","data feed name":"2014","error":"Get https://nvd.nist.gov/feeds/json/cve/1.0/nvdcve-1.0-2014.meta: dial tcp: lookup nvd.nist.gov on 10.233.0.3:53: server misbehaving"}
{"Event":"could not get NVD data feed hash","Level":"warning","Location":"nvd.go:161","Time":"2020-06-11 02:39:27.479245","data feed name":"2015","error":"Get https://nvd.nist.gov/feeds/json/cve/1.0/nvdcve-1.0-2015.meta: dial tcp: lookup nvd.nist.gov on 10.233.0.3:53: server misbehaving"}
{"Event":"could not get NVD data feed hash","Level":"warning","Location":"nvd.go:161","Time":"2020-06-11 02:39:27.484171","data feed name":"2016","error":"Get https://nvd.nist.gov/feeds/json/cve/1.0/nvdcve-1.0-2016.meta: dial tcp: lookup nvd.nist.gov on 10.233.0.3:53: server misbehaving"}
{"Event":"could not get NVD data feed hash","Level":"warning","Location":"nvd.go:161","Time":"2020-06-11 02:39:27.488133","data feed name":"2017","error":"Get https://nvd.nist.gov/feeds/json/cve/1.0/nvdcve-1.0-2017.meta: dial tcp: lookup nvd.nist.gov on 10.233.0.3:53: server misbehaving"}
{"Event":"could not get NVD data feed hash","Level":"warning","Location":"nvd.go:161","Time":"2020-06-11 02:39:27.490757","data feed name":"2018","error":"Get https://nvd.nist.gov/feeds/json/cve/1.0/nvdcve-1.0-2018.meta: dial tcp: lookup nvd.nist.gov on 10.233.0.3:53: server misbehaving"}
{"Event":"could not get NVD data feed hash","Level":"warning","Location":"nvd.go:161","Time":"2020-06-11 02:39:27.497702","data feed name":"2019","error":"Get https://nvd.nist.gov/feeds/json/cve/1.0/nvdcve-1.0-2019.meta: dial tcp: lookup nvd.nist.gov on 10.233.0.3:53: server misbehaving"}
{"Event":"could not get NVD data feed hash","Level":"warning","Location":"nvd.go:161","Time":"2020-06-11 02:39:27.502183","data feed name":"2020","error":"Get https://nvd.nist.gov/feeds/json/cve/1.0/nvdcve-1.0-2020.meta: dial tcp: lookup nvd.nist.gov on 10.233.0.3:53: server misbehaving"}
...
{"Event":"Not all updaters succeeded, sleep duration: 2m0s","Level":"warning","Location":"updater.go:136","Time":"2020-06-11 02:39:28.248869"}
...
{"Event":"Not all updaters succeeded, sleep duration: 4m0s","Level":"warning","Location":"updater.go:136","Time":"2020-06-11 02:41:29.639687"}
...
{"Event":"Not all updaters succeeded, sleep duration: 8m0s","Level":"warning","Location":"updater.go:136","Time":"2020-06-11 02:45:35.098772"}
...
{"Event":"Not all updaters succeeded, sleep duration: 16m0s","Level":"warning","Location":"updater.go:136","Time":"2020-06-11 02:53:36.323417"}
...
{"Event":"Not all updaters succeeded, sleep duration: 32m0s","Level":"warning","Location":"updater.go:136","Time":"2020-06-11 03:09:37.911076"}
...
{"Event":"Not all updaters succeeded, sleep duration: 1h4m0s","Level":"warning","Location":"updater.go:136","Time":"2020-06-11 03:41:38.427084"}
...
{"Event":"Not all updaters succeeded, sleep duration: 2h8m0s","Level":"warning","Location":"updater.go:136","Time":"2020-06-11 04:45:39.729896"}
...
harbor默认采用notary作为可信镜像签名与验证工具(前提是harbor必须配置HTTPS)
示例,采用harbor helm chart 部署了v1.10版本镜像仓库,配置中采用nodeport暴露服务,并且配置自动生成tls证书。修改的配置如下
expose:
type: nodePort
tls:
enabled: true
secretName: ""
commonName: "portus.teligen.com"
nodePort:
# The name of NodePort service
name: harbor
ports:
http:
# The service port Harbor listens on when serving with HTTP
port: 80
# The node port Harbor listens on when serving with HTTP
nodePort: 30002
https:
# The service port Harbor listens on when serving with HTTPS
port: 443
# The node port Harbor listens on when serving with HTTPS
nodePort: 30003
# Only needed when notary.enabled is set to true
notary:
# The service port Notary listens on
port: 4443
# The node port Notary listens on
nodePort: 30004
externalURL: https://portus.teligen.com:30003
harbor运行后,从组件core的pod目录/etc/core/ca/..data/
下存有自动生成tls证书。需要把它们拷到docker宿主机上,并且放置在目录1) /etc/docker/certs.d/portus.teligen.com:30003/
和2)/usr/local/share/ca-certificates/
,运行命令update-ca-certificates
导入可信证书。
可信镜像测试
1、配置环境变量export DOCKER_CONTENT_TRUST=1
和export DOCKER_CONTENT_TRUST_SERVER=https://portus.teligen.com:30004
开启可信配置。
2、执行以下命令上传镜像,上传完镜像内容,并且会上传镜像元数据,并且加密保存镜像元数据。
root@focal-1:/home/test/data# docker push portus.teligen.com:30003/library/nginx:1.17
The push refers to repository [portus.teligen.com:30003/library/nginx]
b3003aac411c: Layer already exists
216cf33c0a28: Layer already exists
c2adabaecedb: Layer already exists
1.17: digest: sha256:cccef6d6bdea671c394956e24b0d0c44cd82dbe83f543a47fdc790fadea48422 size: 948
Signing and pushing trust metadata
You are about to create a new root signing key passphrase. This passphrase
will be used to protect the most sensitive key in your signing system. Please
choose a long, complex passphrase and be careful to keep the password and the
key file itself secure and backed up. It is highly recommended that you use a
password manager to generate the passphrase and keep it safe. There will be no
way to recover this key. You can find the key in your config directory.
Enter passphrase for new root key with ID c8610da:
Passphrase is too short. Please use a password manager to generate and store a good random passphrase.
Enter passphrase for new root key with ID c8610da:
Repeat passphrase for new root key with ID c8610da:
Enter passphrase for new repository key with ID 0e177b1:
Repeat passphrase for new repository key with ID 0e177b1:
Finished initializing "portus.teligen.com:30003/library/nginx"
Successfully signed portus.teligen.com:30003/library/nginx:1.17
root@focal-1:/home/test/data#
3、检查可信镜像
root@focal-1:/home/test/data# docker trust inspect portus.teligen.com:30003/library/nginx:1.17
[
{
"Name": "portus.teligen.com:30003/library/nginx:1.17",
"SignedTags": [
{
"SignedTag": "1.17",
"Digest": "cccef6d6bdea671c394956e24b0d0c44cd82dbe83f543a47fdc790fadea48422",
"Signers": [
"Repo Admin"
]
}
],
"Signers": [],
"AdministrativeKeys": [
{
"Name": "Root",
"Keys": [
{
"ID": "69afff7f00b55c1c5cc5d8a0530e770f8673b54f720b28223fbf04fd03bf84af"
}
]
},
{
"Name": "Repository",
"Keys": [
{
"ID": "0e177b10c4097374d5145086010b4e8b574b9767cbf8152a74601148d250cff9"
}
]
}
]
}
]
root@focal-1:/home/test/data#
4、取消可信配置unset DOCKER_CONTENT_TRUST
,上传一个新镜像
root@focal-2:/home/test# docker push portus.teligen.com:30003/library/busybox:latest
The push refers to repository [portus.teligen.com:30003/library/busybox]
a6d503001157: Pushed
latest: digest: sha256:afe605d272837ce1732f390966166c2afff5391208ddd57de10942748694049d size: 527
root@focal-2:/home/test#
5、打开可信配置,拉取新镜像,会发现notary没有该镜像的可信信息,拒绝下载。
root@focal-1:/home/test# docker pull portus.teligen.com:30003/library/busybox:latest
Error: remote trust data does not exist for portus.teligen.com:30003/library/busybox: portus.teligen.com:30004 does not have trust data for portus.teligen.com:30003/library/busybox
root@focal-1:/home/test#
测试结果表明,使用notary可信可以只下载内容可信的镜像
6、测试篡改镜像内容,上传覆盖原始镜像
root@focal-2:/home/test# docker images | grep nginx
nginx 1.17 602e111c06b6 6 weeks ago 127MB
portus.teligen.com:30003/library/nginx 1.17 602e111c06b6 6 weeks ago 127MB
goharbor/nginx-photon v1.10.1 01276d086ad6 4 months ago 44MB
root@focal-2:/home/test#
root@focal-2:/home/test# docker tag goharbor/nginx-photon:v1.10.1 portus.teligen.com:30003/library/nginx:1.17
root@focal-2:/home/test# docker push portus.teligen.com:30003/library/nginx:1.17
The push refers to repository [portus.teligen.com:30003/library/nginx]
48cda078e98d: Pushed
47a4bb1cfbc7: Pushed
1.17: digest: sha256:8f900484be88c2f72699996ade92cbcbd84366f386396af0ac093430e6c2f7f2 size: 740
Signing and pushing trust metadata
ERRO[0010] couldn't add target to targets: could not find necessary signing keys, at least one of these keys must be available: 0e177b10c4097374d5145086010b4e8b574b9767cbf8152a74601148d250cff9
failed to sign portus.teligen.com:30003/library/nginx:1.17: could not find necessary signing keys, at least one of these keys must be available: 0e177b10c4097374d5145086010b4e8b574b9767cbf8152a74601148d250cff9
root@focal-2:/home/test# docker images | grep nginx
nginx 1.17 602e111c06b6 6 weeks ago 127MB
portus.teligen.com:30003/library/nginx <none> 602e111c06b6 6 weeks ago 127MB
goharbor/nginx-photon v1.10.1 01276d086ad6 4 months ago 44MB
portus.teligen.com:30003/library/nginx 1.17 01276d086ad6 4 months ago 44MB
root@focal-2:/home/test# docker rmi portus.teligen.com:30003/library/nginx:1.17
Untagged: portus.teligen.com:30003/library/nginx:1.17
Untagged: portus.teligen.com:30003/library/nginx@sha256:8f900484be88c2f72699996ade92cbcbd84366f386396af0ac093430e6c2f7f2
root@focal-2:/home/test# docker pull portus.teligen.com:30003/library/nginx:1.17
Pull (1 of 1): portus.teligen.com:30003/library/nginx:1.17@sha256:cccef6d6bdea671c394956e24b0d0c44cd82dbe83f543a47fdc790fadea48422
sha256:cccef6d6bdea671c394956e24b0d0c44cd82dbe83f543a47fdc790fadea48422: Pulling from library/nginx
Digest: sha256:cccef6d6bdea671c394956e24b0d0c44cd82dbe83f543a47fdc790fadea48422
Status: Image is up to date for portus.teligen.com:30003/library/nginx@sha256:cccef6d6bdea671c394956e24b0d0c44cd82dbe83f543a47fdc790fadea48422
Tagging portus.teligen.com:30003/library/nginx@sha256:cccef6d6bdea671c394956e24b0d0c44cd82dbe83f543a47fdc790fadea48422 as portus.teligen.com:30003/library/nginx:1.17
portus.teligen.com:30003/library/nginx:1.17
root@focal-2:/home/test#
root@focal-2:/home/test# docker images | grep nginx
nginx 1.17 602e111c06b6 6 weeks ago 127MB
portus.teligen.com:30003/library/nginx 1.17 602e111c06b6 6 weeks ago 127MB
goharbor/nginx-photon v1.10.1 01276d086ad6 4 months ago 44MB
root@focal-2:/home/test#
并且,在镜像仓库中可以看到镜像内容的异常,需要上传正确的镜像内容。
测试结果表明,使用notary可信可以防止下载被篡改的镜像。
falco包含以下安装方式
1)直接安装在主机上
2)falco用户空间程序运行在容器中,falco驱动安装在主机上
3)falco用户空间程序运行在容器中,falco驱动运行在特权模式容器中
测试环境使用第三种安装方式
falco驱动程序运行
docker run --rm -i -t \
--privileged \
-v /root/.falco:/root/.falco \
-v /proc:/host/proc:ro \
-v /boot:/host/boot:ro \
-v /lib/modules:/host/lib/modules:ro \
-v /usr:/host/usr:ro \
-v /etc:/host/etc:ro \
falcosecurity/falco-driver-loader:latest
falco用户空间程序运行
docker run --rm -i -t \
--cap-add SYS_PTRACE --pid=host $(ls /dev/falco* | xargs -I {} echo --device {}) \
-v /var/run/docker.sock:/var/run/docker.sock \
falcosecurity/falco-no-driver:latest
热更新命令(更新falco配置而无需重启falco)
kill -1 $(cat /var/run/falco.pid)