![img](https://img-
blog.csdnimg.cn/img_convert/1d314a152de2cfdc7cb17d2486454617.png)
目录
![image-20231125080337605](https://img-
blog.csdnimg.cn/img_convert/27470cf450b1a5959e13fd0231a0d98d.png)
文章目录
-
* 目录
- 本节实战
- 1、安全概述
- 2、证书签发流程
-
* 1.签发证书
- 2.身份认证
- 3、认证
-
* 1.对等认证
-
* a.默认的宽容模式
- b.全局严格 mTLS 模式
- c.命名空间级别策略
- d.为每个工作负载启用双向 TLS
- 2.请求认证
-
* a.JWK 与 JWKS 概述
- b.配置 JWT 终端用户认证
- c.设置强制认证规则
-
- 关于我
- 最后
本节实战
实战名称
🚩 实战:对等认证(默认的宽容模式)-2023.11.24(测速成功)
🚩 实战:对等认证(全局严格 mTLS 模式)-2023.11.24(测速成功)
🚩 实战:对等认证(命名空间级别策略)-2023.11.24(测速成功)
🚩 实战:对等认证(为每个工作负载启用双向 TLS)-2023.11.24(测速成功)
🚩 实战:对等认证(为每个端口配置不同的对等认证策略)-2023.11.24(测速成功)
🚩 实战:请求认证-2023.11.25(测试成功)
1、安全概述
安全是一个非常重要的话题,但也是平时容易被忽略的一个话题,我们在开发应用的时候,往往会忽略安全,但是当应用上线后,安全问题就会暴露出来,这时候就会造成很大的损失。Istio
通过在服务之间注入 Sidecar 代理,来实现对服务之间的流量进行控制和监控,从而实现服务之间的安全通信。
接下来我们将从** 证书管理、认证、授权 **等几个方面来学习 Istio 的安全机制。
将单一应用程序拆分为微服务可提供各种好处,包括更好的灵活性、可伸缩性以及服务复用的能力。但是,微服务也有特殊的安全需求:
- 为了抵御中间人攻击,需要流量加密。
- 为了提供灵活的服务访问控制,需要双向 TLS 和细粒度的访问策略。
- 要确定谁在什么时候做了什么,需要审计工具。
Istio 尝试提供全面的安全解决方案来解决所有这些问题,Istio 安全性可以减轻针对你的数据、端点、通信和平台的内外威胁。
![img](https://img-
blog.csdnimg.cn/img_convert/1d314a152de2cfdc7cb17d2486454617.png)
Istio 为微服务提供了无侵入,可插拔的安全框架。应用不需要修改代码, 就可以利用 Istio 提供的双向 TLS 认证实现服务身份认证
,并基于服务身份信息提供细粒度的访问控制。Istio 安全的高层架构如下图所示:
![img](https://img-
blog.csdnimg.cn/img_convert/c1c0a4dfbf16ad40e03949fa97140120.png)
上图展示了 Istio 中的 服务认证 和 授权 两部分。 服务认证 是通过控制面和数据面一起实现的:
- 控制面:Istiod 中实现了一个 CA (Certificate Authority,证书机构) 服务器。该 CA 服务器负责为网格中的各个服务签发证书,并将证书分发给数据面的各个服务的边车代理。
- 数据面:在网格中的服务相互之间发起 plain(原始的,未加密的) HTTP/TCP 通信时,和服务同一个 pod 中的边车代理会拦截服务请求,采用证书和对端服务的边车代理进行双向 TLS 认证并建立一个 TLS 连接,使用该 TLS 连接来在网络中传输数据。
Istio 的 授权 功能为网格中的工作负载提供网格、命名空间和工作负载级别的访问控制,这种控制层级提供了许多优点:
- 工作负载到工作负载以及最终用户到工作负载的授权。
- 一个简单的 API:它包括一个单独的并且很容易使用和维护的
AuthorizationPolicy
CRD。 - 灵活的语义:运维人员可以在 Istio 属性上定义自定义条件,并使用
DENY
和ALLOW
动作。 - 高性能:Istio 授权是在 Envoy 本地强制执行的。
- 高兼容性:原生支持 HTTP、HTTPS 和 HTTP2,以及任意普通 TCP 协议。
**授权策略对服务器端 Envoy 代理的入站流量实施访问控制。**每个 Envoy
代理都运行一个授权引擎,该引擎在运行时授权请求。当请求到达代理时,授权引擎根据当前授权策略评估请求上下文,并返回授权结果 ALLOW
或
DENY
。运维人员可以通过 YAML 资源清单文件来指定 Istio 授权策略。
2、证书签发流程
默认情况下,Istio CA 生成自签名根证书和密钥,并使用它们来签署工作负载证书。为了保护根 CA 密钥,我们应该使用在安全机器上 离线运行 的根
CA(比如使用 Hashicorp Vault 进行管理),并使用根
CA 向每个集群中运行的 Istio CA 颁发中间证书。Istio CA
可以使用管理员指定的证书和密钥对工作负载证书进行签名,并将管理员指定的根证书作为信任根分发给工作负载。
![img](https://img-
blog.csdnimg.cn/img_convert/ebf6c03567bf61bf5b2e0b77490b1878.png)
1.签发证书
当我们有了 Istio CA 根证书后就可以使用它来签发工作负载证书了,那么整个的证书签发流程又是怎样的呢?如下图所示:
![img](https://img-
blog.csdnimg.cn/img_convert/7ac74be79b97779b0bb5739af1977713.png)
- Envoy 向
pilot-agent
发起一个 SDS (Secret Discovery Service) 请求(启动的时候),要求获取自己的证书和私钥。 pilot-agent
生成私钥和 CSR 证书签名请求,向 Istiod 发送证书签发请求,请求中包含 CSR 和该 Pod 中服务的身份信息。- Istiod 提供 gRPC 服务以接受证书签名请求,根据请求中服务的身份信息(如果是 Kubernetes 则使用 Service Account)为其签发证书,将证书返回给
pilot-agent
。 pilot-agent
将证书和私钥通过 SDS 接口返回给 Envoy。pilot-agent
还会监控工作负载证书的过期时间,上述过程会定期重复进行证书和密钥轮换。
这个流程和我们自己用手动方式去进行证书签发是一样的,所以我们需要先了解下证书签发的流程。Istio CA
根证书就是一个证书颁发机构,平时如果要为我们自己的网站申请 HTTPS 证书我们也是去一些正规的 CA 机构进行申请, ** 而这个申请的信息就是生成的
CSR 证书签名请求** ,然后我们将这个 CSR 和身份信息提交给 CA 机构,CA
机构根据这些信息为我们签发证书,然后我们就可以使用这个证书了,只是我们这里在不同的组件上来执行这些操作,整体流程是一样的。
istio-ca-root-cert
[root@master1 ~]#kubectl get cm -nistio-system
NAME DATA AGE
……
istio-ca-root-cert 1 15d
……
[root@master1 ~]#
[root@master1 ~]#kubectl get po istiod-644f5d55fc-gs96f -nistio-system -oyaml
……
- mountPath: /var/run/secrets/istiod/ca
name: istio-csr-ca-configmap
readOnly: true
……
- configMap:
defaultMode: 420
name: istio-ca-root-cert
optional: true
name: istio-csr-ca-configmap
![image-20231123122545714](https://img-
blog.csdnimg.cn/img_convert/fd927f3d9dfec1045cb8d77571202540.png)
2.身份认证
另外要通过服务证书来实现网格中服务的身份认证,必须首先确保服务从控制面获取自身证书的流程是安全的。Istio 通过 Istiod 和 pilog- agent
之间的 gRPC 通道传递 CSR 和证书,因此在这两个组件进行通信时,双方需要先验证对方的身份,以避免恶意第三方伪造 CSR 请求或者假冒
Istiod CA 服务器。Istio 中主要包含下面两种认证方式:
-
Istiod 身份认证
-
Istiod 采用其内置的 CA 服务器为自身签发一个服务器证书,并采用该服务器证书对外提供基于 TLS 的 gPRC 服务。
-
Istiod 调用 Kubernetes APIServer 生成一个名为
istio-ca-root-cert
的 ConfigMap 对象, 在该 ConfigMap 中放入了 Istiod 的 CA 根证书。 -
该 ConfigMap 被 Mount 到
istio-proxy
容器中,被pilot-agent
用于验证 Istiod 的服务器证书。 -
在
pilot-agent
和 Istiod 建立 gRPC 连接时,pilot-agent
采用标准的 TLS 服务器认证流程对 Istiod 的服务器证书进行认证。 -
pilot-agent 身份认证
-
在 Kubernetes 中可以为每一个 Pod 关联一个 ServiceAccount,以表明该 Pod 中运行的服务的身份信息。
-
Kubernetes 会为该 ServiceAccount 生成一个 jwt token,并将该 token 通过 secret 加载到 pod 中的一个文件。
-
pilot-agent
在向 Istiod 发送 CSR 时,将其所在 Pod 的 service account token 也随请求发送给 Istiod。 -
Istiod 调用 Kube-apiserver 接口验证请求中附带的 service account token,以确认请求证书的服务身份是否合法。
这里需要注意的是不同版本的 Kubernetes 集群下面的 ServiceAccount Token 生成方式并不一样,但最终都是通过改 Token
来进行身份认证的。
- 1.20(含 1.20)之前的版本,在创建 sa 时会自动创建一个 secret,然后这个会把这个 secret 通过投射卷挂载到 pod
里,该 secret 里面包含的 token 是永久有效的。- 1.21~1.23 版本,在创建 sa 时也会自动创建 secret,但是在 pod 里并不会使用 secret 里的 token,而是由
kubelet 到 TokenRequest API 去申请一个 token,该 token 默认有效期为一年,但是 pod 每一个小时会更新一次
token。- 1.24 版本及以上,在创建 sa 时不再自动创建 secret 了,只保留由 kubelet 到 TokenRequest API 去申请
token。
3、认证
Istio 提供两种类型的认证用于管控网格服务间的双向 TLS 和终端用户的身份认证。:
-
对等认证 :用于服务到服务的认证,以验证建立连接的客户端。Istio 提供双向 TLS 作为传输认证的全栈解决方案,无需更改服务代码就可以启用它。这个解决方案:
-
为每个服务提供代表其角色的强大身份,以实现跨集群和云的互操作性。
-
确保服务间通信的安全。
-
提供密钥管理系统,以自动进行密钥和证书的生成、分发和轮换。
-
请求认证 :用于终端用户认证,以验证附加到请求的凭据。Istio 使用
JSON Web Token(JWT)
验证启用请求级认证,并使用自定义认证实现或任何OpenID Connect
的认证实现来简化的开发人员体验。
1.对等认证
a.默认的宽容模式
🚩 实战:对等认证(默认的宽容模式)-2023.11.24(测速成功)
实验环境:
k8s v1.27.6(containerd://1.6.20)(cni:flannel:v0.22.2)
istio v1.19.3(--set profile=demo)
实验软件:
链接:https://pan.baidu.com/s/1pMnJxgL63oTlGFlhrfnXsA?pwd=7yqb
提取码:7yqb
2023.11.5-实战:BookInfo 示例应用-2023.11.5(测试成功)
![image-20231105111842627](https://img-
blog.csdnimg.cn/img_convert/fa49597651264af20c4bb4175f427bc3.png)
- 下面我们来创建几个示例服务来对认证配置进行测试。
这里我们将在 foo
和 bar
命名空间下各自创建带有 Envoy 代理(Sidecar)的 httpbin 和 sleep 服务。还将在
legacy
命名空间下创建不带 Envoy 代理(Sidecar)的 httpbin 和 sleep 服务:
kubectl create ns foo
kubectl apply -f <(istioctl kube-inject -f samples/httpbin/httpbin.yaml) -n foo
kubectl apply -f <(istioctl kube-inject -f samples/sleep/sleep.yaml) -n foo
kubectl create ns bar
kubectl apply -f <(istioctl kube-inject -f samples/httpbin/httpbin.yaml) -n bar
kubectl apply -f <(istioctl kube-inject -f samples/sleep/sleep.yaml) -n bar
kubectl create ns legacy
kubectl apply -f samples/httpbin/httpbin.yaml -n legacy
kubectl apply -f samples/sleep/sleep.yaml -n legacy
查看:
[root@master1 istio-1.19.3]#kubectl get po -nfoo
NAME READY STATUS RESTARTS AGE
httpbin-5c44d89fd9-pmzkk 2/2 Running 0 3m43s
sleep-844db44b8c-49br9 2/2 Running 0 3m42s
[root@master1 istio-1.19.3]#kubectl get po -nbar
NAME READY STATUS RESTARTS AGE
httpbin-5c44d89fd9-zpdww 2/2 Running 0 3m43s
sleep-844db44b8c-q688w 2/2 Running 0 3m42s
[root@master1 istio-1.19.3]#kubectl get po -nlegacy
NAME READY STATUS RESTARTS AGE
httpbin-86869bccff-2cmj2 1/1 Running 0 3m47s
sleep-9454cc476-vvr4q 1/1 Running 0 3m44s
现在可以在 foo
、bar
或 legacy
三个命名空间下的任意 sleep Pod 中使用 curl 向
httpbin.foo
、httpbin.bar
或 httpbin.legacy
发送 HTTP 请求来验证部署结果,所有请求都应该成功并返回
HTTP 200。
-
例如验证
sleep.bar
到httpbin.foo
可达性如下:$ kubectl exec “$(kubectl get pod -l app=sleep -n bar -o jsonpath={.items…metadata.name})” -c sleep -n bar – curl http://httpbin.foo:8000/ip -s -o /dev/null -w “%{http_code}\n”
200 -
也可以使用一行指令检查所有可能的组合:
$ 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 f r o m − − c u r l − s " h t t p : / / h t t p b i n . {from} -- curl -s "http://httpbin. from−−curl−s"http://httpbin.{to}:8000/ip" -s -o /dev/null -w “sleep. f r o m t o h t t p b i n . {from} to httpbin. fromtohttpbin.{to}: %{http_code}\n”; done; done
sleep.foo to httpbin.foo: 200
sleep.foo to httpbin.bar: 200
sleep.foo to httpbin.legacy: 200
sleep.bar to httpbin.foo: 200
sleep.bar to httpbin.bar: 200
sleep.bar to httpbin.legacy: 200
sleep.legacy to httpbin.foo: 200
sleep.legacy to httpbin.bar: 200
sleep.legacy to httpbin.legacy: 200
这样保证了我们的服务之间是可以互相访问的。
接下来我们就来看下如何对服务进行认证。
-
默认情况下,在 Istio 网格内部的服务之间的所有流量都是通过双向 TLS 进行加密的,不需要做额外的操作,当使用双向 TLS 时,代理会将
X-Forwarded-Client-Cert
这个 Header 头注入到后端的上游请求,这个头信息的存在就是启用双向 TLS 的证据。例如:$ kubectl exec “$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items…metadata.name})” -c sleep -n foo – curl -s http://httpbin.foo:8000/headers -s
{
“headers”: {
“Accept”: “/”,
“Host”: “httpbin.foo:8000”,
“User-Agent”: “curl/7.81.0-DEV”,
“X-B3-Parentspanid”: “a59be7609a15c41f”,
“X-B3-Sampled”: “1”,
“X-B3-Spanid”: “034af52cfc2286b4”,
“X-B3-Traceid”: “eb07847c5c14c17fa59be7609a15c41f”,
“X-Envoy-Attempt-Count”: “1”,
“X-Forwarded-Client-Cert”: “By=spiffe://cluster.local/ns/foo/sa/httpbin;Hash=bb907e90c93bc3f1dd22763f952746e7d2b8c5ad7903ecbcc64324f3b5e55179;Subject=”“;URI=spiffe://cluster.local/ns/foo/sa/sleep”
}
}
可以看到上面我们的请求中包含了 X-Forwarded-Client-Cert
这个 Header 头,这就是启用双向 TLS
的证据,得到的这个值是一个 spiffe://
开头的字符串,这个字符串就是 SPIFFE ID, 这个 SPIFFE ID
就是用来表示服务的身份的 ,后面我们会详细介绍 SPIFFE。
** 零信任架构 **下,需要严格区分工作负载的识别和信任,而签发 X.509
证书是推荐的一种认证方式,在 Kubernetes
集群中,服务间是通过 DNS 名称互相访问的,而网络流量可能被 DNS 欺骗、BGP/路由劫持、ARP 欺骗等手段劫持,为了将服务名称(DNS
名称)与服务身份强关联起来,Istio 使用置于 X.509
证书中的安全命名(Secure naming)机制。
SPIFFE 是 Istio 所采用的安全命名的规范,它也是云原生定义的一种标准化的、可移植的工作负载身份规范。Secure Production
Identity Framework For Everyone (SPIFFE)
是一套服务之间相互进行身份识别的标准,主要包含以下内容:
- SPIFFE ID 标准,SPIFFE ID 是服务的唯一标识,具体实现使用 URI 资源标识符。
- SPIFFE Verifiable Identity Document (SVID) 标准,将 SPIFFE ID 编码到一个加密的可验证的数据格式中。
- 颁发与撤销 SVID 的 API 标准。
SPIFFE ID 规定了形如 spiffe://<trust domain>/<workload identifier>
的 URI
格式,作为工作负载(Workload)的唯一标识。Istio 使用形如
spiffe://<trust_domain>/ns/<namespace>/sa/<service_account>
格式的 SPIFFE ID
作为安全命名,注入到 X.509
证书的 subjectAltName
扩展中。其中的 trust domain
参数通过 Istiod
环境变量 TRUST_DOMAIN
注入,用于在多集群环境中交互,比如我们这里就是 cluster.local
,所以其实最终在 Envoy
的配置中可以看到匹配证书的 subjectAltName
值也是这个格式:
{
"combined_validation_context": {
"default_validation_context": {
"match_subject_alt_names": [
{
"exact": "spiffe://cluster.local/ns/istio-system/sa/istiod"
}
]
},
"validation_context_sds_secret_config": {
"name": "ROOTCA",
"sds_config": {
"api_config_source": {
"api_type": "GRPC",
"grpc_services": [
{
"envoy_grpc": {
"cluster_name": "sds-grpc"
}
}
],
"set_node_on_first_message_only": true,
"transport_api_version": "V3"
},
"initial_fetch_timeout": "0s",
"resource_api_version": "V3"
}
}
}
}
-
当服务器没有 Sidecar 时,
X-Forwarded-Client-Cert
这个 Header 头将不会存在,这意味着请求是明文的,比如我们请求httpbin.legacy
服务:[root@master1 istio-1.19.3]#kubectl exec “$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items…metadata.name})” -c sleep -n foo – curl http://httpbin.legacy:8000/headers -s
{
“headers”: {
“Accept”: “/”,
“Host”: “httpbin.legacy:8000”,
“User-Agent”: “curl/7.81.0-DEV”,
“X-B3-Sampled”: “1”,
“X-B3-Spanid”: “1385a68dd52bc759”,
“X-B3-Traceid”: “94d64875182fd6101385a68dd52bc759”,
“X-Envoy-Attempt-Count”: “1”,
“X-Envoy-Decorator-Operation”: “httpbin.legacy.svc.cluster.local:8000/*”,
“X-Envoy-Peer-Metadata”: “ChkKDkFQUF9DT05UQUlORVJTEgcaBXNsZWVwChoKCkNMVVNURVJfSUQSDBoKS3ViZXJuZXRlcwodCgxJTlNUQU5DRV9JUFMSDRoLMTAuMjQ0LjIuMjIKGQoNSVNUSU9fVkVSU0lPThIIGgYxLjE5LjMKoQEKBkxBQkVMUxKWASqTAQoOCgNhcHASBxoFc2xlZXAKJAoZc2VjdXJpdHkuaXN0aW8uaW8vdGxzTW9kZRIHGgVpc3RpbwoqCh9zZXJ2aWNlLmlzdGlvLmlvL2Nhbm9uaWNhbC1uYW1lEgcaBXNsZWVwCi8KI3NlcnZpY2UuaXN0aW8uaW8vY2Fub25pY2FsLXJldmlzaW9uEggaBmxhdGVzdAoaCgdNRVNIX0lEEg8aDWNsdXN0ZXIubG9jYWwKIAoETkFNRRIYGhZzbGVlcC04NDRkYjQ0YjhjLTQ5YnI5ChIKCU5BTUVTUEFDRRIFGgNmb28=”,
“X-Envoy-Peer-Metadata-Id”: “sidecar10.244.2.22sleep-844db44b8c-49br9.foo~foo.svc.cluster.local”
}
}[root@master1 istio-1.19.3]#kubectl exec “$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items…metadata.name})” -c sleep -n foo – curl http://httpbin.legacy:8000/headers -s | grep X-Forwarded-Client-Cert
b.全局严格 mTLS 模式
🚩 实战:对等认证(全局严格 mTLS 模式)-2023.11.24(测速成功)
实验环境:
k8s v1.27.6(containerd://1.6.20)(cni:flannel:v0.22.2)
istio v1.19.3(--set profile=demo)
实验软件:
链接:https://pan.baidu.com/s/1pMnJxgL63oTlGFlhrfnXsA?pwd=7yqb
提取码:7yqb
2023.11.5-实战:BookInfo 示例应用-2023.11.5(测试成功)
![image-20231105111842627](https://img-
blog.csdnimg.cn/img_convert/1a063188839deeef4eaca55e8f0ba944.png)
事实上当 Istio 自动将代理和工作负载之间的所有流量升级到双向 TLS 时, 工作负载仍然可以接收明文流量 ,如果想要禁用非 mTLS
的通信流量,我们可以使用一个 PeerAuthentication
资源对象来进行配置,只需要将整个网格的对等认证策略设置为 STRICT
模式,作用域为整个网格范围的对等认证策略不设置 selector
即可,这种认证策略必须应用于根命名空间(istiod 所在的命名空间),例如:
-
创建下资源
#peer-strict-global.yaml
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication # 对等认证策略
metadata:
name: default
namespace: istio-system
spec:
mtls:
mode: STRICT # STRICT 模式表示只允许 mTLS
对等认证策略指定 Istio 对目标工作负载实施的双向 TLS 模式。支持以下模式:
PERMISSIVE
:工作负载接受双向 TLS 和纯文本流量,也就是所谓的 宽容模式 。 此模式在迁移因为没有 Sidecar 而无法使用双向 TLS 的工作负载的过程中非常有用 。一旦工作负载完成 Sidecar 注入的迁移,应将模式切换为STRICT
。STRICT
:工作负载仅接收双向 TLS 流量。DISABLE
:禁用双向 TLS。从安全角度来看,除非提供自己的安全解决方案,否则请勿使用此模式。
这个对等认证策略将工作负载配置为仅接受 mTLS 加密的请求。 由于未对 selector 字段指定值,因此该策略适用于网格中的所有工作负载。
-
直接应用上面这个对等认证策略后,我们再次发送请求来进行测试:
[root@master1 istio-1.19.3]#kubectl apply -f peer-strict-global.yaml
peerauthentication.security.istio.io/default created
[root@master1 istio-1.19.3]#kubectl get PeerAuthentication -nistio-system
NAME MODE AGE
default STRICT 14s$ 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 f r o m − − c u r l − s " h t t p : / / h t t p b i n . {from} -- curl -s "http://httpbin. from−−curl−s"http://httpbin.{to}:8000/ip" -s -o /dev/null -w “sleep. f r o m t o h t t p b i n . {from} to httpbin. fromtohttpbin.{to}: %{http_code}\n”; done; done
sleep.foo to httpbin.foo: 200
sleep.foo to httpbin.bar: 200
sleep.foo to httpbin.legacy: 200
sleep.bar to httpbin.foo: 200
sleep.bar to httpbin.bar: 200
sleep.bar to httpbin.legacy: 200
sleep.legacy to httpbin.foo: 000
command terminated with exit code 56
sleep.legacy to httpbin.bar: 000
command terminated with exit code 56
sleep.legacy to httpbin.legacy: 200
我们可以发现从 sleep.legacy
到 httpbin.foo
和 httpbin.bar
的请求都失败了,其他依然是成功的,这是因为我们现在配置了 STRICT
严格要求使用 mTLS,由于 sleep.legacy
没有 Envoy
Sidecar,所以无法满足这一要求,所以要访问网格内部的工作负载是不被允许的。** 那为什么可以访问httpbin.legacy
呢?**这是因为我们在 legacy
命名空间下的 httpbin 服务没有 Envoy Sidecar,所以它不会被 Istio
管理,也就不会被强制要求使用 mTLS 了,所以我们可以直接访问它。
c.命名空间级别策略
🚩 实战:对等认证(命名空间级别策略)-2023.11.24(测速成功)
实验环境:
k8s v1.27.6(containerd://1.6.20)(cni:flannel:v0.22.2)
istio v1.19.3(--set profile=demo)
实验软件:
链接:https://pan.baidu.com/s/1pMnJxgL63oTlGFlhrfnXsA?pwd=7yqb
提取码:7yqb
2023.11.5-实战:BookInfo 示例应用-2023.11.5(测试成功)
![image-20231105111842627](https://img-
blog.csdnimg.cn/img_convert/1a063188839deeef4eaca55e8f0ba944.png)
-
上面我们是在根命名空间(istiod 所在的命名空间)下配置的对等认证策略,这样会影响到整个网格,如果我们只想对某个命名空间下的服务进行配置,那么我们可以使用命名空间级别的对等认证策略,该策略的规范与整个网格级别的规范相同,但是可以在
metadata
字段指定具体的命名空间的名称。比如我们要在foo
命名空间上启用严格的双向 TLS 对等策略,可以创建如下所示的资源对象:#peer-strict-ns.yaml
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: foo # 命名空间级别
spec:
mtls:
mode: STRICT -
直接应用上面的资源对象,然后再次发送请求来进行测试:
首先删除上面创建的全局对等认证策略
[root@master1 istio-1.19.3]#kubectl delete -f peer-strict-global.yaml
#部署:
[root@master1 istio-1.19.3]#kubectl apply -f peer-strict-ns.yaml$ 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 f r o m − − c u r l " h t t p : / / h t t p b i n . {from} -- curl "http://httpbin. from−−curl"http://httpbin.{to}:8000/ip" -s -o /dev/null -w “sleep. f r o m t o h t t p b i n . {from} to httpbin. fromtohttpbin.{to}: %{http_code}\n”; done; done
sleep.foo to httpbin.foo: 200
sleep.foo to httpbin.bar: 200
sleep.foo to httpbin.legacy: 200
sleep.bar to httpbin.foo: 200
sleep.bar to httpbin.bar: 200
sleep.bar to httpbin.legacy: 200
sleep.legacy to httpbin.foo: 000
command terminated with exit code 56
sleep.legacy to httpbin.bar: 200
sleep.legacy to httpbin.legacy: 200
由于这些策略只应用于命名空间 foo
中的服务,正常我们会看到只有从没有 Sidecar 的客户端(sleep.legacy
)到有 Sidecar
的客户端(httpbin.foo
)的请求会失败,其余都是成功的。
测试结束。😘
d.为每个工作负载启用双向 TLS
🚩 实战:对等认证(为每个工作负载启用双向 TLS)-2023.11.24(测速成功)
实验环境:
k8s v1.27.6(containerd://1.6.20)(cni:flannel:v0.22.2)
istio v1.19.3(--set profile=demo)
实验软件:
链接:https://pan.baidu.com/s/1pMnJxgL63oTlGFlhrfnXsA?pwd=7yqb
提取码:7yqb
2023.11.5-实战:BookInfo 示例应用-2023.11.5(测试成功)
![image-20231105111842627](https://img-
blog.csdnimg.cn/img_convert/bf946901e8bda7a017312cbf23cd7648.png)
-
要为特定工作负载设置对等认证策略,我们就必须配置
selector
字段指定与所需工作负载匹配的标签。比如我们只想要为httpbin.bar
服务启用严格模式的 mTLS,则可以创建如下所示的资源对象:#peer-strict-pod.yaml
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: “httpbin”
namespace: “bar”
spec:
selector:
matchLabels:
app: httpbin # 匹配 httpbin 应用的标签
mtls:
mode: STRICT -
上面的资源对象将为
bar
命名空间中的httpbin
应用启用严格模式的 mTLS,其他工作负载不受影响。直接应用上面的资源对象,然后再次发送请求来进行测试:#部署
[root@master1 istio-1.19.3]#kubectl apply -f peer-strict-pod.yaml$ 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 f r o m − − c u r l " h t t p : / / h t t p b i n . {from} -- curl "http://httpbin. from−−curl"http://httpbin.{to}:8000/ip" -s -o /dev/null -w “sleep. f r o m t o h t t p b i n . {from} to httpbin. fromtohttpbin.{to}: %{http_code}\n”; done; done
sleep.foo to httpbin.foo: 200
sleep.foo to httpbin.bar: 200
sleep.foo to httpbin.legacy: 200
sleep.bar to httpbin.foo: 200
sleep.bar to httpbin.bar: 200
sleep.bar to httpbin.legacy: 200
sleep.legacy to httpbin.foo: 000
command terminated with exit code 56
sleep.legacy to httpbin.bar: 000
command terminated with exit code 56
sleep.legacy to httpbin.legacy: 200
跟预期一样,从 sleep.legacy
到 httpbin.bar
的请求因为同样的原因失败。
测试结束。😘
为每个端口配置不同的对等认证策略
🚩 实战:对等认证(为每个端口配置不同的对等认证策略)-2023.11.24(测速成功)
实验环境:
k8s v1.27.6(containerd://1.6.20)(cni:flannel:v0.22.2)
istio v1.19.3(--set profile=demo)
实验软件:
链接:https://pan.baidu.com/s/1pMnJxgL63oTlGFlhrfnXsA?pwd=7yqb
提取码:7yqb
2023.11.5-实战:BookInfo 示例应用-2023.11.5(测试成功)
![image-20231105111842627](https://img-
blog.csdnimg.cn/img_convert/081525d8ce75b0a961a5c331c1ece2f4.png)
-
除此之外我们还可以为每个端口配置不同的对等认证策略,例如,以下对等认证策略要求在除 80 端口以外的所有端口上都使用双向 TLS:
#peer-strict-pod-port.yaml
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: “httpbin”
namespace: “bar”
spec:
selector:
matchLabels:
app: httpbin
mtls:
mode: STRICT
portLevelMtls:
80:
mode: DISABLE
上面的资源对象中我们配置了一个 portLevelMtls
字段,该字段用于配置端口级别的对等认证策略,这里我们配置了 80
端口的对等认证策略为
DISABLE
,即禁用双向 TLS,其他端口的对等认证策略为 STRICT
,即启用双向 TLS,也就是说我们只允许 httpbin
应用的
80
端口接收明文流量,其他端口都必须使用双向 TLS。
-
直接应用上面的资源对象,然后再次发送请求来进行测试:
#[root@master1 istio-1.19.3]#kubectl apply -f peer-strict-pod-port.yaml
$ 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 f r o m − − c u r l " h t t p : / / h t t p b i n . {from} -- curl "http://httpbin. from−−curl"http://httpbin.{to}:8000/ip" -s -o /dev/null -w “sleep. f r o m t o h t t p b i n . {from} to httpbin. fromtohttpbin.{to}: %{http_code}\n”; done; done
sleep.foo to httpbin.foo: 200
sleep.foo to httpbin.bar: 200
sleep.foo to httpbin.legacy: 200
sleep.bar to httpbin.foo: 200
sleep.bar to httpbin.bar: 200
sleep.bar to httpbin.legacy: 200
sleep.legacy to httpbin.foo: 000
command terminated with exit code 56
sleep.legacy to httpbin.bar: 200
sleep.legacy to httpbin.legacy: 200
可以看到现在我们从 sleep.legacy
到 httpbin.bar
的请求成功了,因为我们禁用了 80
端口的双向 TLS,所以
sleep.legacy
可以访问到 httpbin.bar
的服务了。
-
测试完成后记得删除上面创建的对等认证策略:
kubectl delete peerauthentication default -n foo
kubectl delete peerauthentication httpbin -n bar
测试结束。😘
2.请求认证
Istio 的请求认证用于终端用户认证,以验证附加到请求的凭据。Istio 使用 JWT
验证启用请求级认证,并使用自定义认证实现或任何 OpenID Connect
的认证实现来进行认证简化。
要在 Istio 中进行请求认证,可以通过一个 RequestAuthentication
资源对象来进行配置,如果请求包含无效的认证信息,它将根据配置的认证规则拒绝该请求。不包含任何认证凭证的请求将被接受,但不会有任何认证的身份。
🚩 实战:请求认证-2023.11.25(测试成功)
a.JWK 与 JWKS 概述
Istio 使用 JWT 对终端用户进行身份验证,Istio 要求提供 JWKS
格式的信息,用于 JWT 签名验证。因此这里得先介绍一下 JWK
和 JWKS
。
JWK
即 JSON Web Key
,是 JWT
的秘钥,它描述了一个加密密钥(公钥或私钥)的值及其各项属性。JWKS
描述一组 JWK
密钥,JWKS
的 JSON 文件格式如下:
{
"keys": [
<jwk-1>,
<jwk-2>,
...
]}
Istio 使用 JWK
描述验证 JWT
签名所需要的信息。在使用 RSA 签名算法时,JWK
描述的应该是用于验证的 RSA 公钥。一个
RSA 公钥的 JWK
描述如下:
{
"alg": "RS256", # 算法「可选参数」
"kty": "RSA", # 密钥类型
"use": "sig", # 被用于签名「可选参数」
"kid": "DHFxxxxx_-envvQ", # key 的唯一 id
"n": "xAExxxxMQ", 公钥的指数(exponent)
"e": "AQAB" # 公钥的模数(modulus)
}
那么需要如何生成 JWK
呢?我们可以使用 https://github.com/lestrrat-go/jwx 这个命令行工具,这是一个用 Go
语言开发的命令行工具,内置了对各种 JWx(JWT, JWK, JWA, JWS, JWE) 的支持。
-
我们可以使用下面的命令来安装
jwx
命令行工具:$ export GOPROXY=“https://goproxy.io” #“https://goproxy.io” 或者 "https://goproxy.cn"都行的。
$ git clone https://github.com/lestrrat-go/jwx.git
$ cd jwx
$ make jwx
go: downloading github.com/lestrrat-go/jwx/v2 v2.0.11
go: downloading github.com/urfave/cli/v2 v2.24.4…
go: downloading github.com/russross/blackfriday/v2 v2.1.0
go: downloading golang.org/x/sys v0.8.0
Installed jwx in /root/go/bin/jwx
注意:这里是要具有Go环境的:
![image-20231124074547767](https://img-
blog.csdnimg.cn/img_convert/b3bba9b54b722f13f1fd45f3697f09ca.png)
![image-20231124074724282](https://img-
blog.csdnimg.cn/img_convert/fbf47b8ec8739d10ed16b26a6a228c5a.png)
[root@master1 ~]#cp /opt/goDir/bin/jwx /usr/local/bin/
[root@master1 ~]#cd /tmp/
[root@master1 tmp]#jwx
NAME:
jwx - Tools for various JWE/JWK/JWS/JWT operations
USAGE:
jwx [global options] command [command options] [arguments...]
COMMANDS:
jwa List available algorithms and types
jwe Work with JWE messages
jwk Work with JWK and JWK sets
jws Work with JWS messages
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--help, -h show help
[root@master1 tmp]#
报错
/opt/goDir/pkg/mod/github.com/lestrrat-go/jwx/v2@v2.0.11/cert/cert.go:9:2: //go:build comment without // +build comment
/opt/goDir/pkg/mod/github.com/lestrrat-go/jwx/v2@v2.0.11/x25519/x25519.go:10:2: //go:build comment without // +build comment
make: *** [jwx] Error 1
![image-20231125065257703](https://img-
blog.csdnimg.cn/img_convert/47afe0de7694466406160a0c351c9ccc.png)
/opt/goDir/pkg/mod/github.com/lestrrat-go/jwx/v2@v2.0.11/cert/cert.go:9:2:
//go:build comment without // +build comment
/opt/goDir/pkg/mod/github.com/lestrrat-
go/jwx/v2@v2.0.11/x25519/x25519.go:10:2: //go:build comment without // +build
comment make: *** [jwx] Error 1
这个错误看起来是与 Go 的构建标记(build tags)相关的问题。错误信息指出在两个文件(cert.go
和 x25519.go
)的第 9
行和第 10 行有 //go:build
注释,但是缺少了 // +build
注释。
// +build
注释是用于控制构建的,指示在何种条件下构建或不构建文件。如果这些文件是条件性地构建的,你需要确保这些注释的格式是正确的。
在这两个文件中,你可能需要添加 // +build
注释,例如:
go// +build some_tag
或者,如果这些文件是通用的,不受构建标记的影响,你可以直接删除这些 //go:build
注释。
请注意,如果你在使用某些构建工具,比如 make
,确保你的构建脚本和构建过程正确处理了这些文件,并且使用了正确的构建标记。
🍀
排查过程:
![image-20231125065644901](https://img-
blog.csdnimg.cn/img_convert/3dfce270779590ac601f5eb7f236a421.png)
![image-20231125065554371](https://img-
blog.csdnimg.cn/img_convert/8b227bc1f5b611d7f5126886608eec6a.png)
![image-20231125065718822](https://img-
blog.csdnimg.cn/img_convert/0f15924d9183688d2441cf9db253375b.png)
🍀
感觉是自己的go版本问题……
重新换装了go版本后,果然好了;
[root@master1 ~]#go version
go version go1.17.13 linux/amd64
#原来自己go版本是:go1.16.2
![image-20231125070247577](https://img-
blog.csdnimg.cn/img_convert/6fddcda59ab0287b5720d55a691568af.png)
-
下面我们使用
jwx
命令行工具生成一个JWK
,通过模板指定kid
为youdianzhishi-key
:$ jwx jwk generate --keysize 4096 --type RSA --template ‘{“kid”:“youdianzhishi-key”}’ -o rsa.jwk
$ cat rsa.jwk
{
“d”: “AxxxwBw6Jok”,
“dp”: “j3xxxuvQ”,
“dq”: “zzxxxqQ”,
“e”: “AQAB”,
“kid”: “youdianzhishi-key”,
“kty”: “RSA”,
“n”: “5sxxxwV8”,
“p”: “-yxxxQ”,
“q”: “6zkC_xxxxKw”,
“qi”: “LExxxTw”
} -
然后从
rsa.jwk
中提取JWK
公钥:$ jwx jwk fmt --public-key -o rsa-public.jwk rsa.jwk
$ cat rsa-public.jwk
{
“e”: “AQAB”,
“kid”: “youdianzhishi-key”,
“kty”: “RSA”,
“n”: “5sxxxV8”
}
上面生成的 JWK
其实就是 RSA 公钥私钥换了一种存储格式而已。
-
我们可以使用下面的命令将它们转换成 PEM 格式的公钥和私钥:
$ jwx jwk fmt -I json -O pem rsa.jwk
-----BEGIN PRIVATE KEY-----
MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqAgEAAoICAQCym3O0Ik5QGZ8i
…
-----END PRIVATE KEY-----$ jwx jwk fmt -I json -O pem rsa-public.jwk
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsptztCJOUBmfIqSE8LR5
…
-----END PUBLIC KEY----- -
接下来我们就可以使用
jwx
命令行签发JWT Token
并验证其有效性了:jwx jws sign --key rsa.jwk --alg RS256 --header ‘{“typ”:“JWT”}’ -o token.txt - <<EOF
{
“iss”: “testing@secure.istio.io”,
“sub”: “cnych001”,
“iat”: 1700648397,
“exp”: 1700686042,
“name”: “Yang Ming”
}
EOFjwx jws sign --key rsa.jwk --alg RS256 --header ‘{“typ”:“JWT”}’ -o token.txt - <<EOF
{
“iss”: “testing@secure.istio.io”,
“sub”: “cnych001”,
“iat”: 1700858397,
“exp”: 1700886042,
“name”: “Yang Ming”
}
EOF
![image-20231125071635661](https://img-
blog.csdnimg.cn/img_convert/8aaaac1f5ef290980c9422e041b6cf40.png)
[root@master1 istio]#date +%s
1700867814
-
然后查看生成的 Token 文件内容:
$ cat token.txt
eyJhbGciOiJSUzI1NiIsImtpZCI6InlvdWRpYW56aGlzaGkta2V5In0… -
上面生成 JWT Token 实际上是由下面的算法生成的:
base64url_encode(Header) + ‘.’ + base64url_encode(Claims) + ‘.’ + base64url_encode(Signature)
-
我们可以将该 Token 粘贴到 jwt.io 网站上来解析:
![img](https://img-
blog.csdnimg.cn/img_convert/69dcc055dedb6fdbafad27629f0f30c5.png)
先看一下 Headers
部分,包含了一些元数据:
alg
: 所使用的签名算法,这里是RSA256
kid
:JWK
的kid
然后是 Payload(Claims)
部分,payload
包含了这个 token 的数据信息,JWT
标准规定了一些字段,另外还可以加入一些承载额外信息的字段。
iss
: issuer,token 是谁签发的sub
: token 的主体信息,一般设置为 token 代表用户身份的唯一 id 或唯一用户名exp
: token 过期时间,Unix 时间戳格式iat
: token 创建时间, Unix 时间戳格式
最后看一下签名 Signature 信息,签名是基于 JSON Web Signature (JWS) 标准来生成的,签名主要用于验证 token
是否有效,是否被篡改。签名支持很多种算法,这里使用的是 RSASHA256,具体的签名算法如下:
RSASHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
<rsa-public-key>,
<rsa-private-key>
-
最后可以使用 RSA Public Key 验证 JWT Token 的有效性:
$ jwx jws verify --alg RS256 --key rsa-public.jwk token.txt
{
“iss”: “testing@secure.istio.io”,
“sub”: “cnych001”,
“iat”: 1700648397,
“exp”: 1700656042,
“name”: “Yang Ming”
}
b.配置 JWT 终端用户认证
上面我们了解了 JWT、JWK、JWKS 这些概念,接下来我们来配置 Istio 的认证策略使用我们自己创建的 JWKS
。
-
为了方便访问,我们这里通过 Ingress 网关来暴露
httpbin.foo
服务,为其创建一个Gateway
对象:[root@master1 ~]#cd istio-1.19.3/
[root@master1 istio-1.19.3]#kubectl apply -f samples/httpbin/httpbin-gateway.yaml -n foo -
可以通过如下命令获取 HTTP 的访问端口:
export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath=‘{.spec.ports[?(@.name==“http2”)].nodePort}’)
-
然后获取集群中任意一个节点的 IP 地址:
export INGRESS_HOST=$(kubectl get po -l istio=ingressgateway -n istio-system -o jsonpath=‘{.items[0].status.hostIP}’)
-
然后可以通过下面的命令来测试
httpbin.foo
服务是否可以正常访问:[root@master1 istio-1.19.3]#curl “ I N G R E S S H O S T : INGRESS_HOST: INGRESSHOST:INGRESS_PORT/headers” -s -o /dev/null -w “%{http_code}\n”
200
如果上面命令返回 200
,则表示 httpbin.foo
服务可以正常访问。
-
接下来我们就可以添加一个请求认证策略对象,该策略要求 Ingress 网关指定终端用户的 JWT。
#jwt-examplt.yaml
apiVersion: “security.istio.io/v1”
kind: RequestAuthentication
metadata:
name: jwt-example
namespace: istio-system
spec:
selector:
matchLabels:
istio: ingressgateway #匹配我们的入口网关
jwtRules:
- issuer: “testing@secure.istio.io” # 签发者,需要和 JWT payload 中的 iss 属性完全一致。
# forwardOriginalToken: true
jwks: |
{
“keys”: [
{
“e”: “AQAB”,
“kid”: “youdianzhishi-key”,
“kty”: “RSA”,
“n”: “5sbkUCkQDuM3hiw9UTxmxO2wUYOT69IZje7M6O_R-ApJ3KkrhQS1C2SJelBTLgbaWhAsO4jBYOmFfWGLBA-XxrhoB9KxWCGA4EXf6fukp0ljGTYE6Th6r393jIJGDFUt8vQCjj5ivmBAQHLjwmnWiG6I93mrTQhoNHQWAde21O7yYNpg6fvjVJgRFqeAtpieA-5f2sQ8fBkefM0RFgQTqWPGfLHse5nqRWY4hG_gb23GzCo_Ti2h9wJZNuTfdK8hitahOq3eLlDVVvCu8hx-8BEs5APCj54gtqePswHeRXZi_03ccNii5CnW7Y1rHiL8LHKNHhY5tD2iZByh4YrnhkUWD-CXNqyUKx90de0R9H1ON6pqsmdEx4iAMx2xvnZ0S9NbKlk3glw_AvudjJUHa41xx7qy9OZ7QV6cB_ntwLtw513lk5Tfm-RDlVgyU-EO2jKXbOeiDpnb8kgRNBMKDqY9mgLfISW54N-LBjyVwVVHOvICWo0oPJypRgPRWD8f25wHqzjlsB8nIqJkj_e9p2c5WnAGiZWuZjm6t94IfFq9lWYUsSn-JtJvh3ATsv7ptDKFz2Ko82r1uD3446mr4I0J56C-7WOHGchlSOrDWKErwkIGxyrQ_3GEkUhkSxfArAv0bajmcMCu1_j8Eekqk7Fnm5QqytCFmFevzIJkwV8”
}
]
}
在上面的资源对象中我们通过 selector
匹配了 istio-ingressgateway
服务,因为我们要为 Ingress
网关添加请求认证,具体的请求认证规则通过 jwtRules
来进行配置,这里我们配置了一个 issuer
字段,该字段用于指定 JWT 的
Issuer
发行人,然后配置了一个 jwks
字段,该字段用于指定 JWT 的公钥集数据,我们也可以通过 jwksUri
来指向一个公钥集地址。对同一个 issuers
(jwt 签发者),可以设置多个公钥, 以实现 JWT 签名密钥的轮转 。JWT 的验证规则是:
- JWT 的
payload
中有issuer
属性,首先通过issuer
匹配到对应的 istio 中配置的jwks
。 - JWT 的
header
中有kid
属性,第二步在jwks
的公钥列表中,中找到kid
相同的公钥。 - 使用找到的公钥进行 JWT 签名验证。
配置中的 spec.selector
可以省略,这样会直接在整个命名空间中生效,比如在 istio-system
命名空间,该配置将在全集群的所有
sidecar/ingressgateway 上生效!
默认情况下,Istio 在完成了身份验证之后,会去掉 Authorization
请求头再进行转发。这将导致我们的后端服务获取不到对应的
Payload,无法判断终端用户的身份。因此我们需要启用 Istio 的 Authorization
请求头的转发功能,只需要在上面的资源对象中添加一个
forwardOriginalToken: true
字段即可。
-
直接应用上面的资源对象,然后再次发送请求来进行测试:
#kubectl apply -f jwt-example.yaml
[root@master1 istio]#curl “ I N G R E S S H O S T : INGRESS_HOST: INGRESSHOST:INGRESS_PORT/headers” -s -o /dev/null -w “%{http_code}\n”
200
可以看到现在依然可以正常访问,但是如果我们请求的时候带上一个无效的 JWT Token,则会返回 401
错误:
[root@master1 istio]#curl --header "Authorization: Bearer abcdef" "$INGRESS_HOST:$INGRESS_PORT/headers" -s -o /dev/null -w "%{http_code}\n"
401
-
要想正常访问,我们需要使用上面生成的 JWT Token 来进行访问:
[root@master1 istio]#TOKEN=$(cat token.txt)
[root@master1 istio]#curl --header “Authorization: Bearer T O K E N " " TOKEN" " TOKEN""INGRESS_HOST:$INGRESS_PORT/headers” -s -o /dev/null -w “%{http_code}\n”
200
可以看到就可以正常访问了。
c.设置强制认证规则
从上面的测试可以看出 Istio 的 JWT 验证规则,默认情况下会直接忽略不带 Authorization
请求头(即
JWT)的流量,因此这类流量能直接进入网格内部。通常这是没问题的,因为没有 Authorization
的流量即使进入到内部,也会因为无法通过
payload
判别身份而被拒绝操作。但是如果我们需要禁止不带 JWT
的流量,那么可以通过一个 AuthorizationPolicy
对象来进行配置了。
-
比如拒绝任何 JWT 无效的请求,则可以创建如下的资源对象:
#ap.yaml
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: deny-requests-without-authorization
namespace: istio-system
spec:
selector:
matchLabels:
istio: ingressgateway
action: DENY # 拒绝
rules:
- from:
- source:
notRequestPrincipals: [“*”] # 不存在任何请求身份(Principal)的 requests
上面的资源对象中我们配置的 action: DENY
表示拒绝,然后通过 rules
字段来配置拒绝的规则,这里我们配置了一个 from
字段,该字段用于指定请求的来源,这里我们配置了一个 notRequestPrincipals
字段,该字段用于指定请求的身份,这里我们配置为
*
,表示任何请求身份都不允许。
-
应用上面的资源对象后,重新发送没有令牌的请求,请求失败并返回错误码 403:
#kubectl apply -f ap.yaml
[root@master1 istio]#curl “ I N G R E S S H O S T : INGRESS_HOST: INGRESSHOST:INGRESS_PORT/headers” -s -o /dev/null -w “%{http_code}\n”
403 -
如果仅希望强制要求对部分 path 的请求必须带有 Authorization Header,可以这样设置:
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: deny-requests-without-authorization
namespace: istio-system
spec:
selector:
matchLabels:
istio: ingressgateway
action: DENY # 拒绝
rules:
- from:
- source:
notRequestPrincipals: [“*”] # 不存在任何请求身份的 requests
# 仅强制要求如下 host/path 相关的请求,必须带上 JWT token
to:
- operation:
hosts: [“another-host.com”]
paths: [“/headers”]
需要注意的是 RequestsAuthentication
和 AuthorizationPolicy
这两个对象返回的错误码是不同的:
RequestsAuthentication
验证失败的请求,Istio 会返回 401 状态码。AuthorizationPolicy
验证失败的请求,Istio 会返回 403 状态码。
最后,记得删除刚创建的资源
测试结束。😘
到这里我们就实现了对 JWT 的验证,当然除了验证之外,我们还需要授权,这个我们在下面的章节中来实现。
关于我
我的博客主旨:
- 排版美观,语言精炼;
- 文档即手册,步骤明细,拒绝埋坑,提供源码;
- 本人实战文档都是亲测成功的,各位小伙伴在实际操作过程中如有什么疑问,可随时联系本人帮您解决问题,让我们一起进步!
🍀 微信二维码
x2675263825 (舍得), qq:2675263825。
![image-20230107215114763](https://img-
blog.csdnimg.cn/img_convert/b454a106b2a2be626b8c13fa38bc8b99.png)
🍀 微信公众号
《云原生架构师实战》
![image-20230107215126971](https://img-
blog.csdnimg.cn/img_convert/2a9ee160a3a58b8700f27309faf1e7a6.png)
🍀 个人博客站点
http://onedayxyy.cn/
![image-20231113073017981](https://img-
blog.csdnimg.cn/img_convert/32f266d7b4cedecc15f131c1b709ccf9.png)
![image-20231113073039083](https://img-
blog.csdnimg.cn/img_convert/29e4da5592ea9784b08c7518cf71992e.png)
🍀 语雀
https://www.yuque.com/xyy-onlyone
![image-20231113073101271](https://img-
blog.csdnimg.cn/img_convert/15a005922b5cce119fa4fce601cd20fa.png)
🍀 csdn
https://blog.csdn.net/weixin_39246554?spm=1010.2135.3001.5421
![image-20230107215149885](https://img-
blog.csdnimg.cn/img_convert/8dd9483583d0157632dfc9f6526db609.png)
🍀 知乎
https://www.zhihu.com/people/foryouone
![image-20230107215203185](https://img-
blog.csdnimg.cn/img_convert/ef028f821b138490312a8bda5c41ab71.png)
最后
好了,关于本次就到这里了,感谢大家阅读,最后祝大家生活快乐,每天都过的有意义哦,我们下期见!
![image-20231125080418779](https://img-
blog.csdnimg.cn/img_convert/60908bf745d62bed5d39b22032ef4e98.png)
学习网络安全技术的方法无非三种:
第一种是报网络安全专业,现在叫网络空间安全专业,主要专业课程:程序设计、计算机组成原理原理、数据结构、操作系统原理、数据库系统、 计算机网络、人工智能、自然语言处理、社会计算、网络安全法律法规、网络安全、内容安全、数字取证、机器学习,多媒体技术,信息检索、舆情分析等。
第二种是自学,就是在网上找资源、找教程,或者是想办法认识一-些大佬,抱紧大腿,不过这种方法很耗时间,而且学习没有规划,可能很长一段时间感觉自己没有进步,容易劝退。
如果你对网络安全入门感兴趣,那么你需要的话可以点击这里👉网络安全重磅福利:入门&进阶全套282G学习资源包免费分享!
第三种就是去找培训。
接下来,我会教你零基础入门快速入门上手网络安全。
网络安全入门到底是先学编程还是先学计算机基础?这是一个争议比较大的问题,有的人会建议先学编程,而有的人会建议先学计算机基础,其实这都是要学的。而且这些对学习网络安全来说非常重要。但是对于完全零基础的人来说又或者急于转行的人来说,学习编程或者计算机基础对他们来说都有一定的难度,并且花费时间太长。
第一阶段:基础准备 4周~6周
这个阶段是所有准备进入安全行业必学的部分,俗话说:基础不劳,地动山摇
第二阶段:web渗透
学习基础 时间:1周 ~ 2周:
① 了解基本概念:(SQL注入、XSS、上传、CSRF、一句话木马、等)为之后的WEB渗透测试打下基础。
② 查看一些论坛的一些Web渗透,学一学案例的思路,每一个站点都不一样,所以思路是主要的。
③ 学会提问的艺术,如果遇到不懂得要善于提问。
配置渗透环境 时间:3周 ~ 4周:
① 了解渗透测试常用的工具,例如(AWVS、SQLMAP、NMAP、BURP、中国菜刀等)。
② 下载这些工具无后门版本并且安装到计算机上。
③ 了解这些工具的使用场景,懂得基本的使用,推荐在Google上查找。
渗透实战操作 时间:约6周:
① 在网上搜索渗透实战案例,深入了解SQL注入、文件上传、解析漏洞等在实战中的使用。
② 自己搭建漏洞环境测试,推荐DWVA,SQLi-labs,Upload-labs,bWAPP。
③ 懂得渗透测试的阶段,每一个阶段需要做那些动作:例如PTES渗透测试执行标准。
④ 深入研究手工SQL注入,寻找绕过waf的方法,制作自己的脚本。
⑤ 研究文件上传的原理,如何进行截断、双重后缀欺骗(IIS、PHP)、解析漏洞利用(IIS、Nignix、Apache)等,参照:上传攻击框架。
⑥ 了解XSS形成原理和种类,在DWVA中进行实践,使用一个含有XSS漏洞的cms,安装安全狗等进行测试。
⑦ 了解一句话木马,并尝试编写过狗一句话。
⑧ 研究在Windows和Linux下的提升权限,Google关键词:提权
以上就是入门阶段
第三阶段:进阶
已经入门并且找到工作之后又该怎么进阶?详情看下图
给新手小白的入门建议:
新手入门学习最好还是从视频入手进行学习,视频的浅显易懂相比起晦涩的文字而言更容易吸收,这里我给大家准备了一套网络安全从入门到精通的视频学习资料包免费领取哦!
如果你对网络安全入门感兴趣,那么你需要的话可以点击这里👉网络安全重磅福利:入门&进阶全套282G学习资源包免费分享!
![](https://i-blog.csdnimg.cn/blog_migrate/bb9deceea6e302b4974ef5d0ee98e694.jpeg)