- A
- R
- Docker daemon attack surface
- T
- Set a deployment’s nginx container image to ‘nginx:1.9.1’, and its busybox container image to ‘busybox’.
- Update all deployments’ and rc’s nginx container’s image to ‘nginx:1.9.1’
- Update image of all containers of daemonset abc to ‘nginx:1.9.1’
- Print result (in yaml format) of updating nginx container image from local file, without hitting the server
- S
A
这周终于A上拖了后腿,确实以我个人的尿性,其他三个确实只要找到了素材,都不太成问题
为啥说拖了后腿么,还是为了完成作业,只做了个简单题

而且我觉得我在内存消耗上,已经彻底没脸见江东父老了
最主要还是,任何A方面的加戏目前看起来都很难完成,上周说的总结,估计又要流产…
这周这个罗马数字转10进制数字的,还有一个还是得记录一下,我觉得,他有可能用来检验提交的代码就是不完整的,因为我设想了有些异常输入,主要是针对不符合罗马数字规则的(也许因为是符合?)输入我觉得我没处理呢还,它竟然算我过了…
R
这周计划主要看这个,其实没啥内容,https://www.baeldung.com/rest-api-spring-oauth2-angular,扫了一遍其实oauth2这东西确实主要是前端得理解
但是感觉不接地气,因为在整jenkins,试图弥补一下原有的jenkins部署的一些问题,缺省jenkins的rpm安装后,jenkins用户操作不了docker,需要那个算是臭名昭著的 sudo usermod -aG docker $USER,自然又走到docker 文档里面那个章节
Docker daemon attack surface
标题是,docker daemon进程的攻击面,也就是整体都是围绕docker daemon这个进程相关来讨论的
总共八个段落,连复述带强译吧
第一段
主要说背景,运行容器暗含着就是运行了 docker daemon进程,而这个进程需要root特权,这里还提到了另一个东西,就是Rootless mode,19.03版时候出来(现在的stable还是19.03…19.03.11,在6.1)的一个新玩意儿,但是还是实验性的阶段
第二段
上来就是算是重要结论吧,only trusted users should e allowed to control your Docker daemon,也就是只让可以被信任的用户控制Docker daemon进程…好吧,跟没说一样,甩锅到管理员了岂不是。
但是也不是没理由,这是基于some powerful docker features的一个direct consequence。那么这些powerful features是什么呢?
接下来举了个例子:Specifically,Docker这货允许在host和guest container之间share一个目录…这个可能确实是最容易被注意到和理解的吧
再接下来这是在黑自己么docker,那些说docker文档在这方面陈述不够的,是不是真的看过docker的文档:and it allows you to do so 还是 without limiting the access rights of the container…其实我也不知道我这个断句对不对
然后docker还怕你不懂,告诉你说,前面说的这意思具体来说就是您老可以让你容器里面的/host跟host上的/ 成为一个东西,然后呢,容器就可以对host上的filesystem在without any restriction的情况下,去alter了,这个算比较中性吧,反正意思就是,可以搞事情了
接着算是做了个…类比?说这类似于virtualization systems allow filesystem resource sharing。这个其实我就没太看懂,它说的是虚拟机?虚拟机不是都是一个(组)文件么,我咋觉得没啥可比性,接着它继续解释,没啥玩意儿可以阻止你和virtual machine(这个确实说的很清楚了)共享你的root filesystem(甚至是你的root block device),最后这个倒是在理,虽然也不太懂吧,但是意思很明显:要是自己门户大开,我也管不了的意思,所以其实呼应了一开始那句很像甩锅得话
第三段
这就会导致了一个安全隐患,具体“这”是docker daemon ,sharing root filesystem这种机制能力,还是前面几乎花了一整段来绕的,甩给管理员的锅,总之吧,开始说技术细节了吧算是
for example,这个例子一下子拔得不低,如果你是通过一个web server的api来操控docker 启动一个容器,那么就得好好的仔细地做一下参数的检查了,这样才能确保那些有着险恶用心的(malicious)同学不能通过传入精心调配的(crafted)参数来操控docker创建可以肆意妄为(arbitrary)的容器
这段辞藻可真华丽,我不查字典都不知道有这么些nb的词语,但是其实只有malicious是六级词汇,那俩都是四级的,所以我…英语真是矬啊,不扯别得了,这段其实也没说出个啥来仔细一想,它其实说的应该是围绕docker打造PaaS平台的那些人吧,就好像做应用的也要防着sql注入一样
第四段
基于这个理由,the REST API endpoint(用来做Docker CLI和Docker daemon之前通信的)在Docker 0.5.2 版本中发生了变化,并且现在使用一个UNIX socket代替绑定到127.0.0.1 的 TCP 的socket,这开始给自己贴金了,看那么早就付出了努力,主要是括号里给更没看懂,他说后者(应该指的是127那个tcp socket)易于(be prone to)被跨站请求伪造攻击???后面应该就是发生着CSRF的条件从句:如果同志你恰巧直接在你本地的机器上运行docker,在VM之外,说的啥玩意儿…嗷,估计说的是裸机上,比如我有台用着ubuntu的pc,直接就跑docker了,而没有在虚拟机里玩儿docker,总之其实还是不太明白,反正是容易被攻击吧;然后就最后一句了,是接着前面 unix socket instead of tcp socket的。you can then use 传统的UNIX 权限检查?来限制对该socket的访问了。还是每个字都懂,放一起说的是啥不太明白
第五段
如果您清楚的知道(为什么)决定一定要通过HTTP来暴露REST API,你也可以这么搞…好吧,到底行不行?然后他就给支招了。然而,如果你真确定这么搞了,要注意上述的安全隐患。得留意的是,即便有防火墙限制网络上其他主机对REST API endpoint的访问,这个endpoint仍然能够从容器访问的到,这很容易导致特权提升。因此应当强制的在API endpoints上加上HTTPS和certificates来保证安全。他这里还给出一个链接,内容详细的说明了,这应该是一个双向的https校验,也就是要求客户端证书,客户端必须是一个可信的实体。最后一句,网络本身也得是受信的,或者VPN,也就是说,别往公网上去暴露吧…这么看起来这段还有点意思
第六段
就一句话,如果您,更倾向于SSH而不是TLS,那么也可以有这么两个姿势:
- 配置一个环境变量,DOCKER_HOST=ssh://USER@HOST
- ssh -L /path/do/docker.sock:/var/run/docker.sock
老实说,没看懂,一个TCP,一个UNIX socket?后面这个像是配了一个本地转发…
第七段
开始说点别的了,它说daemon也容易受到其他来源的攻击,例如从磁盘上 docker load加载镜像,或者从网络上 docker pull 拉取镜像,这么看起来,所谓的other inputs ,应该是指有别于之前的socket?
后面就更不懂了,主要是记述了docker 自1.3.2 和自1.10.0 之后两个重大的改变吧,但是真没看懂,强行中英混排复述一下
自1.3.2以来,作为一个更广泛的effort toward 特权分离的第一步,镜像现在在linux/unix 平台上,是在一个chrooted的子进程上被extracted的
自1.10.0以来,所有的镜像都会通过一个与其内容相关的加密校验和去存储和访问,以此来限制攻击者同已经存在的镜像去进行的碰撞攻击
以上纯粹瞎翻,带点儿自己的节奏吧
第八段
最后一段了
最后,如果运行了docker 在一个server上,那么就推荐只在这个server上跑个docker完事儿,这时候把所有的服务都移入到docker控制的容器当中。当然了,保有你最顺手的那些管理工具,也包括一些监控/监视进程,例如NRPE和collected…
最后这俩东西我就算是第一次知道,反正是监控的玩意儿,最后这波感觉就是安利,让docker变成一级的守护进程,包管理器,服务管理器,比如替代centos里面的systemd,从这个角度来看,似乎jenkins还是要跑在容器里
我自己的总结
简单总结下,可能不一定对
- docker daemon需要host主机的特权能力来实现docker的feature,所以
- docker 认为这玩意儿主要是一个管理配置责任,附带应用安全检查责任
- docker自己搞了Rootless mode,从另一个角度来帮用户缓解这个安全压力,不过还是实验性质的,这个有链接可进去细看
- 注意通过各种手段来监控检查不能乱挂载主机目录
- 注意docker的客户端/服务端架构,当客户端和服务端不在一起的时候,注意链路安全
- docker官方还是建议docker在一台主机上独占,我估计一方面是安利,希望docker占据更加有利的生态位,另一方面也是为了减少更复杂的基础环境带来的安全的复杂性
T
按说不应该提前(今天是20200610)完成作业
但是这个真的忍不住梳理一下,而且与其叫tip,倒不如叫一个教训
在试用kubectl set image得细节得时候,发现命令里面提到实可以一下子更新all … container’s image 得
Update existing container image(s) of resources. Possible resources include (case insensitive): pod (po), replicationcontroller (rc), deployment (deploy), daemonset (ds), replicaset (rs) Examples:
Set a deployment’s nginx container image to ‘nginx:1.9.1’, and its busybox container image to ‘busybox’.
kubectl set image deployment/nginx busybox=busybox nginx=nginx:1.9.1
Update all deployments’ and rc’s nginx container’s image to ‘nginx:1.9.1’
kubectl set image deployments,rc nginx=nginx:1.9.1 —all
Update image of all containers of daemonset abc to ‘nginx:1.9.1’
kubectl set image daemonset abc *=nginx:1.9.1
Print result (in yaml format) of updating nginx container image from local file, without hitting the server
kubectl set image -f path/to/file.yaml nginx=nginx:1.9.1 —local -o yaml
kubectl set image 是我很喜欢的命令,虽然正统的k8s同学估计就是一个apply -f 走天下,按我的思路,我其实觉的命令行这东西,不能有一个大一统得入口,否则跟没有一样,apply -f 一个yaml,也得是假设真的是有一个超好的编辑器,更需要一套好用到爆的SCM到环境得基础配置,我觉得这些能搞懂的同学就已经不一般了,倒不如多记几个命令,或者干脆如我这样脑子还不好记不住东西的,直接snippet一些地方,留着备用得好(shell里面跑过一次之后,还可以history得翻查,就是换了环境之后麻烦点)
废话不多说,主要是今天刚刚无心插柳的发现,其实,set image这货后面那个什么 = 什么,毫无疑问的类似一个selector,这意味着可以同时更新多个deployment,例如,我们的多租户环境,每个租户自己是单独的一套部署实例,如果要更新服务版本,貌似可以通过 kubectl set image deployments xxx=yyy --all 一下子把所有得pod都更新了
但是实际测试、试用得时候也发现现实冰冷而残酷:
- 我们用得rancher,同一个名称空间下面,通常习惯性得把两个不同得deployment起个不同的名字,缺省的下来,对应的deployment种得container得name,也就不一样了,所以一开始没试成功,后面直接编辑了yaml形式的配置(rancher里面这个操作,应该是相当于kubectl edit得效果),将不同的deployment里面container得名字改成一样的了
- 不同的名称空间,我们的现状也是…不同的名字,例如带着租户的标识,按编辑得习惯(原来小凯应该是没多想,直接多个租户区分,container用外面deployment得名字了)还是不同的,那就需要调整了,但还有一个巨大的障碍已经存在了,就是它是不同的名称空间
- 命令文档里里面的 *= 这个写法,感觉是适配daemonset独有的写法
- —all 得option,并非是all-namespace搜索,所以只能通过—namespace来指定特定的名称空间,这下就产生了较大的限制,通过试用发现目前这个命令是没有 —all-namespaces 得option得,想起之前看哪个issue,似乎kubectl的maintainer就不倾向于多个namespace一起做设置的操作,如果用户想做,他只是有好的提示可以自己去写脚本来做…
所以至此可以断言,实际上没法通过kubectl set image来对多个名称空间的服务中的容器做替换了
这也许是坏事,也许是好事,毕竟奢望在全局范围内或多个范围内做大量的更新(但其实它有dry-run查看是否有预期得结果)也不是个靠谱的事情,从目前我设计的执行流程来看,执行kubectl set image之后,是立即通过kubectl rollout status 来针对特定得deployment来进行部署成功与否得检查的,所以…确实一下子替换多个服务得容器,未必是一个好主意吧…
second tip
看这个

这个ctrl+shift+A,是之前的一个tip么,那时候是给文本sort的,还记得这个快捷键是特么钉钉的截图快捷键
所以有兴趣再试用一下,试用时发现,想调出这个settings来,还是需要先选定一些文字,否则出不来,出来之后确实能点进去设置,最主要是到最后也不知道caret是啥意思,还是查了字典,看了半天感觉应该值得还是选中的那个光标处的字符吧
从具体看到的情况来推测,除非真的视觉障碍或者强迫症,所以还是别乱改了吧
third tip
这个比较有用
校验你的正则表达式
其實吧,看了這麽多,大概率總結出的IDEA tip其實就是快捷鍵在一些特定場合的使用,比如這裏用的是alt-enter,这个组合键应该也是常用的之一,属于就是提示性的,幾乎你想對一個東西幹點兒什麽,但是又不知道具體如何操作時候,alt+enter就沒錯
具體要幹什麽,就看你自己記得多少了
之前好幾次,ctrl+shift+a 这个属于search类的,主要是search action的
對應可能比較有用過的還有ctrl+shift-n(这个是搜索文件名匹配的)還有ctrl+shift+f(这个厉害,是全文检索文件内容是否有匹配的,还能按mask来匹配,但是這個也和釘釘有衝突)
所有这些快捷键,还都得注意…输入法
才发现怎么刚一堆的繁体中文…
S
本来这个是想写到tip里的,但是tip都淤出来了,所以这里顺便做个笔记的同时,抨击一下(一般来说都抨击了,必然带有观点)阿里云一些细节设计,考虑到这么大一个花架子搞不好哪天就自我演化了,无论是有意识还是无意识的,所以这里记上一个不太精确的时间戳:202006161440 GMT+8
阿里云账号之间可以互相授信,参考这里,他的原始设计场景还是在于,资源的所有权和使用权,分属于不同的商业实体里面,我们这里这个其实我也不知道为啥搞成这样,据说初衷是为了省钱
阿里那篇ref其实写的挺全的了,但是行文的原因,感觉描述的有点不像是给人看的,我根据我尝试性的操作配置过程来描述一下,同时记录我认为的要点:
- 要有两个阿里云账号
- 这两个阿里云账号,用来做下面授权管理操作的,主账号(阿里云好像叫云账号)或者RAM子账号应该都可以
- 我是用的RAM子账号,但是我这两个子账号都是AdministratorAccess的权限
- 我推测(但是没有试过),应该只有RAM的管理权限就可以了
- 下面这么记录一些指代称谓,两个主账号(云账号),分别是A和B,各自有个全能的RAM子账号,分别是a和b,我们还要在B里面再创建两个账号,x和y,其中x在B里面是受限的,A里面却是nb的,y在A和B里面都是受限的
- 接下来是要配置让B能操作A里面的资源,实际上是让B里面的x,y来操作A里面的资源,方法是通过配置指定的匹配上A里面的角色
- A里面需要两类角色,一类是nb的,什么都能干的,索性叫j;一类是受限的,指定干什么才能干什么,索性叫k
- A里面直接创建RAM角色就可以





- 上面最后一张图里面,就是区分他是个god,还是受限的
- 这时候A侧的 j 和 k 的前半截,就算弄好了,但是这样还不一定能给B的x和y去用,但是B里面的b实际上已经可以用了,从这里访问


- 但是B侧的x和y还是不能用的,只是这里要强调的是B侧的b已经越权了
- 如果为了避免b的越权,则需要对A侧的RAM角色j和k做以下配置

- 就是要把那个root改了,对应我们是要B账号里面的x在A这里是全能的,那么上面root要改为user/x,左边的红色马赛克就是B的accountId,这个前面已经UI创建时候会要求你填上,或者当时如果选了同一个账号,这里也可以改
- 同时我们看到Principal.RAM是个数组,要是多个B侧的账号,就配多行,中间逗号分隔就行
这时候A的配置,就基本上完事儿了,但,对于x和y来说,可能还没完:
- 我们要到B的一侧,确保x和y都有 AliyunSTSAssumeRoleAccess,具体配置就不截图了
- B侧的b因为本身就是个全能得(具备AdministratorAccess权限),所以自带AliyunSTSAssumeRoleAccess,在A侧的j和k还是root时候就能访问
这是我本周作业部分的share,所以对于我来说,关键的是要输出一个观点
就是上面这个root,阿里云这个json的策略,对于用户来说并不十分友好(这个友好性如果要加强,一方面它好像有一个策略生成器,但是入口非常不好找,我现在就找不到;另一个是把它这个web 编辑器改成带智能提示的,这个反正非常不好用,就是知道的是知道,不知道的怎么也不知道),所以一般来说大家倾向于看见json也不去改,如果喜欢蒙着来而不是先读一遍文档的,结果就使用缺省设置root,导致不当的放权给那些已经授予了 AliyunSTSAssumeRoleAccess 的账号和角色,注意这个权限往往还不是直接对人的,所以危害可能更隐蔽
另外,它引导性的配置流程也有问题,如果想规避这个漏洞,操作上实际上应该先引导去修改信任策略,然后再授予权限,否则
就会导致,不走心的同学很容易设置一个放大了的权限给不恰当的人,
安全无小事,往往链条上任何一个点出了问题,就是满盘皆输,大多数人的认知能力其实一般来说都不太成问题(也不排除某一类人在特定问题上就是傻缺,好比我就是不会摆盘儿…),但是侥幸心理,往往会配合人的惰性仅仅在行政力面前才显得低眉顺目,这明显是另一个viewpoint,此处不便展开了
