知识卡片

Profile+Tag机制:从"一对一互通"扩展到"一组对一"的访问控制简化

普通读书笔记卡

内容

Calico用Profile这个概念(类似AWS的Security Group)来实现访问控制的隔离——同一个Profile内的实例之间才能互相通信,每个Profile自带一套规则集,最基本的形态是”入连接只允许来自同名Profile的实例,出连接不限制,其余全部按默认策略drop”,天然实现了”没有明确声明允许的连接全部隔离”这个安全默认值。基于这个基础模型,可以为常见的三层Web架构(WEB→APP→DB)逐一声明规则:WEB暴露80/443端口对外,APP只允许来自WEB的连接,DB只允许来自APP的连接且限定在3306端口,除此之外禁止所有跨服务访问——用几条简单的JSON规则就能完整表达这套三层隔离关系。但简单的”Profile对Profile”规则在更复杂的现实场景下会遇到扩展性问题:如果有多组不同的APP都需要访问同一个DB,按最朴素的做法就要在DB的规则里为每一个APP的Profile单独加一条规则,规则数量会随着APP数量线性增长,维护起来繁琐又容易出错。Calico给出的解法是Tag这个高级特性:每个Profile默认拥有一个和自己同名的Tag,同时还可以额外挂上多个Tag(以列表形式保存),规则可以直接针对某个Tag来声明,而不是针对某个具体的Profile名字——把所有需要访问DB的APP的Profile都打上一个共同的Tag(比如db-users),DB的规则只需要写一条”允许来自db-users这个Tag的连接”,后续任何新增的APP只要在自己的Profile上加上db-users这个Tag,就自动获得了访问DB的权限,完全不需要去修改DB这一侧的规则。这个设计给出了一条访问控制规则设计的通用原则:当”谁能访问谁”这层关系可能是多对一、而且”谁”这一方还会持续增长时,不应该把规则直接绑定在具体的实体身上(否则规则数量会随实体数量线性膨胀),而应该引入一层可以灵活挂载、代表某种共同属性的标签,让规则针对标签声明,实体只需要声明自己拥有哪些标签,规则的可维护性就不会随实体数量增长而恶化。

参考来源

- 位置:《高可用架构(第1卷)》第4章《容器与云计算》"4.3 使用开源Calico构建Docker多租户网络"节,"4.3.3 利用Profile实现ACL"(源文件:_epub-src/OEBPS/Text/Chapter4_3_4.xhtml) - 结论依据:原文说明Profile基础规则集的隔离效果,并针对多组APP访问同一DB的场景引入Tag机制:"每个Profile可以有多个Tag……我们给所有需要访问DB的APP的Profile都加上db-users这个Tag……这样所有打了db-user这个Tag的实例就都能访问数据库了",直接支撑本卡片结论。 - 原始内容:在现实环境中,会有多组不同的APP都需要访问DB,如果每个APP都在DB中增加一条规则也很麻烦,同时还容易出错……我们给所有需要访问DB的APP的Profile都加上db-users这个Tag……这样所有打了db-user这个Tag的实例就都能访问数据库了。