
如何保护对外暴露的 Kubernetes 服务?
作者 阳明
来源 | k8s技术圈(ID:kube100)
有时候我们需要在 Kubernetes 中暴露一些没有任何安全验证机制的服务,比如没有安装 xpack 的 Kibana,没有开启登录认证的 Jenkins 服务之类的,我们也想通过域名来进行访问,比较域名比较方便,更主要的是对于 Kubernetes 里面的服务,通过 Ingress 暴露一个服务太方便了,而且还可以通过 cert-manager 来自动的完成 HTTPS化。所以就非常有必要对这些服务进行一些安全验证了。
Basic Auth 认证
我们在前面升级 Dashboard 的文章中就给大家提到过两种方式来为我们的服务添加 Basic Auth 认证:haproxy/nginx 和 traefik/nginx-ingress。
使用 haproxy/nginx 的方式非常简单,就是直接添加 basic auth 认证,然后将请求转发到后面的服务;而 traefik/nginx-ingress 都直接提供了 basic auth 的支持,我们这里使用 nginx-ingress 来为 Jenkins 服务添加一个 basic auth 的认证服务。
首先,我们需要创建用于存储用户名和密码的 htpasswd文件:
然后,创建一个基于上面 htpasswd 文件的 Secret 对象:
最后,我们需要在 Ingress 对象中添加 auth-type:basic和 auth-jenkins-basic-auth两个 annotations:(ingress.yaml)
然后更新上面的资源对象:
更新完成后,现在我们去访问我们的 Jenkins 服务可以看到需要输入用户名和密码的提示信息了:
OAuth 认证
除了上面的 Basic Auth 认证方式以为,我们还可以通过 Github、Google 等提供的 OAuth 服务来进行身份验证。我们可以通过名为OAuth2 Proxy的工具来代理请求,它通过提供一个外部身份验证的反向代理来实现,使用起来也相对简单。
安装
首先我们需要为我们的应用添加自动的 HTTPS,可以参考我们前面的文章使用 Let's Encrypt 实现 Kubernetes Ingress 自动化 HTTPS。
然后登录 Github,在https://github.com/settings/applications/new添加一个新的 OAuth应用程序:
替换成你自己需要使用的域名,然后在回调 URL 上添加 /oauth2/callback,点击注册后,记录下应用详细页面 ClientID和 ClientSecret的值。然后还需要生成一个 cookie 密钥,当然如果我们系统中安装了 python 环境可以直接生成,没有的话用 Docker 容器运行当然也行:
然后部署 OAuth2Proxy应用,这里我们直接使用 Helm 来简化安装:
对于 GitHub,我们可以通过 github-org和 github-team来限制访问,一般设置 email-doamin="*",我们可以通过 OAuth2Proxy的示例文档来查看更改 GitHub Provider 的配置。
测试
同样我们这里还是使用一个 Jenkins 服务,大家也可以使用任意的一个服务来验证,当然最好是没有身份验证功能的,比如没有安装 x-pack 的 Kibana。
要实现外部服务来进行认证的关键点在于 nginx-ingress-controller 在 annotations 中为我们提供了 auth-url和 auth-signin两个注解来允许配置外部身份验证的入口。
上面这两个 annotation 需要 nginx-ingress-controller 在 v0.9.0 版本或以上。
我们在 Jenkins 的核心 Ingress 对象中配置服务认证的 url: https://$host/oauth2/auth,然后通过创建一个同域的 Ingress 对象将 oauth2路径代理到 OAuth2proxy应用去处理认证服务:
然后按照上面的思路重新创建 Jenkins 的两个 Ingress 对象:
我们这里通过 cert-manager来自动为服务添加 HTTPS ,添加了 kubernetes.io/tls-acme=true这个注解,然后我们在浏览器中打开我们的 Jenkins 服务,正常就会跳转到 GitHub 登录页面了:
然后认证通过后就可以跳转到我们的 Jenkins 服务了:
当然除了使用 GitHub 之外,还可以使用其他的 OAuth 认证服务,比如 Google,我们可以根据需要自行去添加即可。
