当前位置:   article > 正文

安全保障基于软件全生命周期-Istio的认证机制_istio peerauthentication

istio peerauthentication

在介绍Istio的认证机制前,先了解一些安全领域的理论知识。传统网络安全架构是基于边界的安全架构,企业构建网络安全体系时,先寻找安全边界,把网络划分为外网、内网、DMZ(DeMilitarized Zone)等不同的区域,然后在边界上部署防火墙、入侵检测等产品。传统的认证是以网络为中心,采用内网信任、边界防护、静态访问控制的机制。


随着云计算、大数据、物联网等新技术与业务的融合,在安全方面提出了新的概念零信任架构(ZTA Zero Trust Architecture),零信任的核心原则是:从不信任、始终验证。安全架构的核心有如下几点

  • 以身份为中心
  • 以识别、持续认证、动态访问控制、授权、审计以及监测为链条
  • 以最小化实时授权为核心
  • 以多维信任算法为基础
  • 认证达末端

 零信任架构三大技术SIM包括
软件定义边界(SDP,Software Defined Perimeter)
SDP旨在使应用程序能在需要时部署安全边界,以便将服务于不安全的网络隔离开。
身份识别与访问管理(IAM,Identity and Access Management)
微隔离(MSG,Micro Segmentation)
微隔离本质上是一种网络安全隔离技术,相比较传统的网络安全隔离,微隔离的区别在于将网络边界分割到尽可能小,这样能缓解传统边界安全理念下的边界过度信任带来的安全风险。

Istio 中的安全性涉及多个组件:
用于密钥和证书管理的证书颁发机构(CA
配置 API 服务器分发给代理:认证策略/授权策略
安全命名信息
Sidecar和边缘代理作为Policy Enforcement Points(PEPs) 以保护客户端和服务器间的通信安全。
一组Envoy代理扩展,用于管理遥测和审计。Istio PKI 使用 X.509 证书为每个工作负载都提供强大的身份标识。伴随着每个 Envoy 代理的 istio-agent(istio-agent是指sidecar容器中的pilot-agent进程)和 istiod 一起协作来大规模进行自动化密钥和证书轮换。如下图所示完成完成身份的供应。

  • istiod 提供 gRPC 服务以接受证书签名请求(CSRs)。当工作负载启动时,Envoy通过秘密发现服务(SDS)API向同容器内的istio-agent发送证书和密钥请求。
  • 在收到SDS请求后,istio-agent 创建私钥和CSR,然后将CSR及其凭据发送到istiod CA签名
  • istiod CA 验证 CSR 中携带的凭据,成功验证后签署 CSR 以生成证书。
  • Istio-agent 通过 Envoy SDS API 将私钥和从 Istio CA 收到的证书发送给 Envoy。
  • Istio-agent会监工作负载证书的有效期。上述CSR过程会周期性地重复以处理证书和密钥轮换

Istio提供两种类型的认证:
Peer authentication:用于服务到服务的认证,以验证进行连接的客户端。Istio提供双向TLS 作为传输认证的全栈解决方案,无需更改服务代码就可以启用它。
Request authentication:用于最终用户认证,以验证附加到请求的凭据。 Istio使用JSON Web Token(JWT)验证启用请求级认证,并使用自定义认证实现或任何 OpenID Connect 的认证实现来简化的开发人员体验。

安全命名:服务器身份(Server identities)被编码在证书里,但服务名称(service names)通过服务发现或 DNS 被检索。安全命名信息将服务器身份映射到服务名称。身份 A 到服务名称 B 的映射表示“授权 A 运行服务 B“。控制平面监视 apiserver,生成安全命名映射,并将其安全地分发到 PEPs。

上面介绍了概念,接下来通过实际例子演示Istio如何完成认证的。创建三个namespace foo,bar,lagacy,其中foo,bar注入Istio sidecar,且三个namespace下都部署httpbin和sleep服务,这两个服务都来自Istio官网的sample目录下。创建对象完成后,查看bar下面的应用,可以看到是2/2,说明已经注入了Sidecar。接着尝试通过命令让bar namespace下的sleep应用通过curl命令访问httpbin应用,可以看到成功返回了200.

接着在三个namespace下让sleep服务访问httpbin服务。访问命令如下,也全部访问成功

for from in "foo" "bar" "legacy"; do for to in "foo" "bar" "legacy"; do kubectl exec "$(kubectl get pod -l app=sleep -n ${from} -o jsonpath={.items..metadata.name})" -c sleep -n ${from} -- curl -s "http://httpbin.${to}:8000/ip" -s -o /dev/null -w "sleep.${from} to httpbin.${to}: %{http_code}\n"; done; done

 接着查看是否存在peerauthentication对象和destinationRules,都不存在。查看httpbin/headers,可以看到header里面有Client-Cert信息。

接着直接在主机上通过httpbin pod的IP地址访问headers信息,可以看到无Cert信息。

 

通过上面的例子可以看到对于注入了Istio sidecard的应用来说,自动启动了mTLS的双向认证机制。接下来创建一个PeerAuthentication对象,模式是STRICT模式,PeerAuthentication的模式有三种,三种模式的区别如下所示:

PERMISSIVE:工作负载接受双向 TLS 和纯文本流量。此模式在迁移因为没有 sidecar 而无法使用双向 TLS 的工作负载的过程中非常有用。一旦工作负载完成 sidecar 注入的迁移,应将模式切换为 STRICT。
STRICT: 工作负载仅接收双向 TLS 流量。
DISABLE:禁用双向 TLS。 从安全角度来看,除非您提供自己的安全解决方案,否则请勿使用此模式。

  1. kubectl apply -f - <<EOF
  2. apiVersion: security.istio.io/v1beta1
  3. kind: PeerAuthentication
  4. metadata:
  5. name: "default"
  6. namespace: "istio-system"
  7. spec:
  8. mtls:
  9. mode: STRICT
  10. EOF

因为上述PeerAuthentication对象是创建在istio-system namespaces下面,即Istio的根namespace下,所以是全局生效。生效后再次用三个namespace下的sleep应用访问httpbin服务。可以看到legacy下的sleep服务访问foo,bar下的httpbin服务都失败了,因为legacy没有注入Istio sidecar,所以是纯文本流量,现在采用STRICT模式,所以会失败。Istio默认是采用PERMISSIVE。

接着在foo namespace下创建新的PeerAuthentication,对于访问httpbin的流量DISABLE,即禁用双向TLS。

  1. cat <<EOF | kubectl apply -n foo -f -
  2. apiVersion: security.istio.io/v1beta1
  3. kind: PeerAuthentication
  4. metadata:
  5. name: "overwrite-example"
  6. namespace: "foo"
  7. spec:
  8. selector:
  9. matchLabels:
  10. app: httpbin
  11. mtls:
  12. mode: DISABLE
  13. EOF

再次查看服务之间相互访问情况,可以看到Legacy下面的sleep应用访问foo下面的httpbin应用重新通了,只有bar下面的不同。因为上面的PA是创建在foo namespace。

通过上面的例子演示,可以看到可以通过配置PeerAuthentication来精细化控制服务间的隔离,即实现微隔离,也符合SDP原则,即应用自身来确定部署的安全边界。

上面介绍了PeerAuthentication(主要用户客户端和服务端都受Istio管理的场景),接着来看看Request Authentication(用户客户端不受Istio管理,无法使用mTLS的场景).。

Request 认证策略指定验证 JSON Web Token(JWT)所需的值。 这些值包括:
token 在请求中的位置
请求的 issuer
公共 JSON Web Key Set(JWKS)

Istio会根据request认证策略中的规则检查提供的令牌(如果已提供),并拒绝令牌无效的请求。当请求不带有令牌时,默认情况下将接受它们。接着通过实际例子来看看Request Authentication如何工作。首先通过gateway把httpbin的服务暴露出来。

  1. kubectl apply -f - <<EOF
  2. apiVersion: networking.istio.io/v1alpha3
  3. kind: Gateway
  4. metadata:
  5. name: httpbin-gateway
  6. namespace: foo
  7. spec:
  8. selector:
  9. istio: ingressgateway # use Istio default gateway implementation
  10. servers:
  11. - port:
  12. number: 80
  13. name: http
  14. protocol: HTTP
  15. hosts:
  16. - "*"
  17. EOF
  18. kubectl apply -f - <<EOF
  19. apiVersion: networking.istio.io/v1alpha3
  20. kind: VirtualService
  21. metadata:
  22. name: httpbin
  23. namespace: foo
  24. spec:
  25. hosts:
  26. - "*"
  27. gateways:
  28. - httpbin-gateway
  29. http:
  30. - route:
  31. - destination:
  32. port:
  33. number: 8000
  34. host: httpbin.foo.svc.cluster.local
  35. EOF

接着创建RequestAuthentication对象。

  1. kubectl apply -f - <<EOF
  2. apiVersion: "security.istio.io/v1beta1"
  3. kind: "RequestAuthentication"
  4. metadata:
  5. name: "jwt-example"
  6. namespace: istio-system
  7. spec:
  8. selector:
  9. matchLabels:
  10. istio: ingressgateway
  11. jwtRules:
  12. - issuer: "testing@secure.istio.io"
  13. jwksUri: "https://raw.githubusercontent.com/istio/istio/release-1.14/security/tools/jwt/samples/jwks.json"
  14. EOF

 在Istio的官网上提供了生成token的python代码,可以通过这个脚本生成有效的token。通过ingress svc的IP地址访问服务,如果不带token,默认是接收请求。

可以看到不带token的情况下,访问成功。

通过Istio官网提供的脚本生成有效的token,生成有效token官网提供了两种方式。

  1. 方式一
  2. TOKEN=$(curl https://raw.githubusercontent.com/istio/istio/master/security/tools/jwt/samples/demo.jwt -s)
  3. curl --header "Authorization: Bearer $TOKEN" $INGRESS_HOST/headers -s -o /dev/null -w "%{http_code}\n"
  4. 方式二
  5. pip install jwcrypto
  6. TOKEN=$(./gen-jwt.py key.pem --expire=300 --iss "new-issuer@secure.istio.io")

带着有效token访问ingress可以看到返回了200.如果把token替换成任意的字符串,返回了401,说明认证不通过。

 上面的例子中如果访问服务不带token则默认接受,这里通过生成AuthoriztionPolicy对象来控制如果不带token则拒绝请求。

  1. kubectl apply -f - <<EOF
  2. apiVersion: security.istio.io/v1beta1
  3. kind: AuthorizationPolicy
  4. metadata:
  5. name: "frontend-ingress"
  6. namespace: istio-system
  7. spec:
  8. selector:
  9. matchLabels:
  10. istio: ingressgateway
  11. action: DENY
  12. rules:
  13. - from:
  14. - source:
  15. notRequestPrincipals: ["*"]
  16. EOF

AuthorizationPolicy对象生效后,不带token访问则refused,带上有效token访问,仍然能成功访问成功。关于AuthorizationPolicy的使用会在下一篇博客中详细介绍。

通过上面的例子演示 AuthenticationRequest的工作过程。可以看到如果不受Istio管控的服务,通过AuthenticationRequest可以完成认证管控,保证应用安全。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/爱喝兽奶帝天荒/article/detail/763436
推荐阅读
相关标签
  

闽ICP备14008679号