【51CTO.com快译】您将学习到如何使用Sidecar安全代理来提高应用程序的安全性能,并能防止诸如暴力破解等类型的攻击。
在Jaeger的产品部署中,我们限制访问Jaeger的查询服务,包括用户界面(UI),是非常有益的。例如,您可能有各种内部安全的要求,只允许某些群组能够访问跟踪数据,或者您可能将Jaeger部署到了公有云之上。在真正的微服务(microservices)方式里,一种可能的方法是给Jaeger查询服务添加一个Sidecar作为安全代理。各种入向请求都被传递到我们的Sidecar,而非直接到达Jaeger的查询服务上。而Sidecar将负责执行各种身份验证和授权的限制。
如上图所示:传入的HTTP请求到达路径(route)①,它使用内部服务②来进行解析,并与安全代理③进行通信。一旦请求通过验证,且所有安全的限制得到了满足,则该请求就到达Jaeger④。
出于演示的目的,我们将使用Keycloak(译者注:Keycloak是一个为浏览器和RESTful Web服务提供SSO的集成)作为自己的安全解决方案,当然其他任何安全代理也都适用于这个理念。当然如果您并不修改Red Hat的SSO(Single Sign-On),这个演示也能够运作。因此对于本次操作练习,我们需要如下:
- 一台Keycloak(或是Red Hat的SSO)服务器的运行实例。我们定义它的位置为$ { REDHAT_SSO_URL }
- 一个OpenShift的集群,我们将用来运行Jaeger的后端组件。它就像oc cluster up一样容易
- 一份Jaeger OpenShift产品模板的本地克隆
注意:我们并不会试图对组件之间(比如说从代理到收集器)的通信进行安全加固。而对于此类场景,我们完全可以使用其他技术来实现,例如相互间使用证书来进行认证,采用istio(译者注:istio是一个开源项目,提供统一的连接、安全、管理和监控微服务),或其他类似的工具。
准备Keycloak
对于该演示,我们将直接在主机上通过Docker来运行Keycloak。这是为了强调Keycloak并不需要像我们的Jaeger后端那样运行在同一个OpenShift集群之上。
下面的命令用来在主机上启动一个合适的Keycloak服务器。如果你已经有了自己的Keycloak或Red Hat的SSO服务器的话,则完全跳过这一步骤。
- docker run --rm --name keycloak-server -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=password -p 8080:8080 jboss/keycloak
一旦Keycloak服务器启动并运行,我们就可以创建一个Jaeger的域(realm)了:
1. 请使用用户名:admin和密码:password,登录到Keycloak(http://<YOUR_IP>:8080/auth/admin/master/console)。
2. 在左上角Select realm中用鼠标点击Add realm。将其命名为jaeger,然后点击Create。
3. 在Clients上,点击Create,将proxy-jaeger设置为名称并保存它。
4. 设置Access Type为confidential,并用*代表Valid Redirect URIs,并保存之。您可能需要在生产环境中进行微调,否则可能会暴露出已知的“未验证的重定向和转发”(Unvalidated Redirects and Forwards,译者注:源自OWASP TOP10 2010的A10)攻击。
5. 打开Installation选项卡并选择Keycloak OIDC JSON,然后复制其显示的JSON。如下所示,不过auth-server-url和secret的值会有所不同。
- {
- "realm": "jaeger",
- "auth-server-url": "http://192.168.2.111:8080/auth",
- "ssl-required": "external",
- "resource": "proxy-jaeger",
- "credentials": {
- "secret": "7f201319-1dfd-43cc-9838-057dac439046"
- }
- }
最后,让我们创建一个角色和用户,使得我们能够登录Jaeger的查询服务:
1. 在左下侧菜单-Configure的下面,请打开Roles页面,然后单击Add role。
2. 将角色的名称设置为user,并点击Save。
3. 在左下侧菜单-Manage的下面,请打开Users页面,然后单击Add user。
4. 按照您的设想去填写该表格,并将Email verified设置为ON,在并点击Save。
5. 为该用户打开Credentials选项卡,并设置一个(临时的或非临时的)密码。
6. 打开该用户的Role mappings选项卡,从Available Roles列表中选择角色为user,再点击Add。
准备OpenShift
对于该演示,我们假设您已经有一个OpenShift集群正在运行了。如果还没有的话,那么您可能需要参考minishift之类的工具了(译者注:minishift是一个通过虚拟机来模拟OpenShift集群的工具)。如果您正在运行最新版本的Fedora、CentOS或Red Hat Enterprise Linux,您可能需要安装包origin-clients,并运行oc cluster up --version=latest。这样您就能有一个基本的、运行在本地的OpenShift集群。
为了方便演示,我们将添加cluster-admin的权限给developer用户。同时我们创建如下的Jaeger命名空间:
- oc login -u system:admin
- oc new-project jaeger
- oc adm policy add-cluster-role-to-user cluster-admin developer -n jaeger
- oc login -u developer
准备Jaeger OpenShift模板
我们将使用Jaeger OpenShift产品模板(https://github.com/jaegertracing/jaeger-openshift/blob/master/production/jaeger-production-template.yml)作为开始:克隆整个存储库,或者得到本地版本的模板。
第一步是添加sidecar容器到query-deployment对象里。在containers列表下,我们指定了jaeger-query之后,就可以添加如下的sidecar代码:
- - image: jboss/keycloak-proxy
- name: ${JAEGER_SERVICE_NAME}-query-security-proxy
- volumeMounts:
- - mountPath: /opt/jboss/conf
- name: security-proxy-configuration-volume
- ports:
- - containerPort: 8080
- protocol: TCP
- readinessProbe:
- httpGet:
- path: "/"
- port: 8080
注意:该容器将volumeMount的名称指定为security-proxy-configuration-volume,我们将使用它来存储代理的配置文件。您可以在spec/template/spec节点下为query-deployment指定容量,并同样设定dnsPolicy的属性(它应该是在前续的代码片段中):
- volumes:
- - configMap:
- name: ${JAEGER_SERVICE_NAME}-configuration
- items:
- - key: proxy
- path: proxy.json
- name: security-proxy-configuration-volume
现在,我们需要来指定具有代理配置条目的ConfigMap。要做到这一点,我们应当给该模板添加一个新的顶层项目。在这里,我们建议您将其放置得越接近于其被使用之处越好。例如,就放在query-deployment的前面:
- - apiVersion: v1
- kind: ConfigMap
- metadata:
- name: ${JAEGER_SERVICE_NAME}-configuration
- labels:
- app: jaeger
- jaeger-infra: security-proxy-configuration
- data:
- proxy: |
- {
- "target-url": "http://localhost:16686",
- "bind-address": "0.0.0.0",
- "http-port": "8080",
- "applications": [
- {
- "base-path": "/",
- "adapter-config": {
- "realm": "jaeger",
- "auth-server-url": "${REDHAT_SSO_URL}",
- "ssl-required": "external",
- "resource": "proxy-jaeger",
- "credentials": {
- "secret": "THE-SECRET-FROM-INSTALLATION-FILE"
- }
- }
- ,
- "constraints": [
- {
- "pattern": "/*",
- "roles-allowed": [
- "user"
- ]
- }
- ]
- }
- ]
- }
请注意:我们只允许具有user角色的用户登录我们的Jaeger用户界面。在真实的场景中,您可能想要调整之,以适应您自己的设置。例如,您的用户数据可能来自LDAP,而您只想允许来自特定LDAP组的用户去访问Jaeger的用户界面。
各个credentials中的secret应当与我们从本练习最开始的Keycloak中所获得的secret相匹配。颇具好奇心的读者您也许会注意到,我们在auth-server-url属性下所提到了模板参数REDHAT_SSO_URL。改变您的Keycloak服务器,或是我们指定一个模板参数,都能允许我们在部署时对它进行设置。在该模板的parameters部分,我们可以添加以下属性:
- - description: The URL to the Red Hat SSO / Keycloak server
- displayName: Red Hat SSO URL
- name: REDHAT_SSO_URL
- required: true
- value: http://THE-URL-FROM-THE-INSTALLATION-FILE:8080/auth
可见这个值应该是一个您的浏览器和sidecar都能访问到的位置,就像您主机的局域网IP地址(192.x.10.x)一样。显然,使用Localhost/127.x是无法工作的。
作为最后一步,我们需要更改服务引导请求到端口8080(即为代理)上,而不是16686。你可以更改服务名为query-service的属性targetPort,将其设置到8080:
- - apiVersion: v1
- kind: Service
- metadata:
- name: ${JAEGER_SERVICE_NAME}-query
- labels:
- app: jaeger
- jaeger-infra: query-service
- spec:
- ports:
- - name: jaeger-query
- port: 80
- protocol: TCP
- targetPort: 8080
- selector:
- jaeger-infra: query-pod
- type: LoadBalancer
作为参考,您可以在博客链接--https://github.com/jaegertracing/jaeger-openshift/blob/KeycloakSecuringUI/production/jaeger-production-template.yml里看到完整的模板文件。
部署
现在我们已经一切准备就绪了,那么就开始部署Jaeger到我们的OpenShift集群上吧。请您在前续步骤里存储了YAML文件的相同目录中,运行以下的命令。我们在此引用到的名称是jaeger-production-template.yml:
- oc process -f jaeger-production-template.yml | oc create -n jaeger -f -
在开始运行的头几分钟内,如果pod的jaeger-query和jaeger-collector出现失败的话并无大碍,Cassandra(译者注:Cassandra是一套开源分布式数据库管理系统,用于储存特别大的数据)仍将会完成启动。最终,该服务也会启动并运行,如下图所示。
一旦准备好了接收服务,请点击路径(route)的URL(https://jaeger-query-jaeger.127.0.0.1.nip.io)。一个由Keycloak服务器所提供的登录界面就会呈现在您眼前。请使用您在前续步骤中设置好的凭证进行登录,之后您就可以顺利到达Jaeger的用户界面了。
结论
在这个练习中,我们了解到了如何为Jaeger的查询pod添加一个sidecar作为安全代理。它让所有的入向请求都传递到该sidecar,而Keycloak的所有特性,例如:双因素认证、服务帐户、单点登录、暴力攻击保护、LDAP支持、等都仍然是透明可用的。
原文标题:Protecting Jaeger UI With a Sidecar Security Proxy,作者:Juraci Paixao Kroehling
【51CTO译稿,合作站点转载请注明原文译者和出处为51CTO.com】