Service Mesh Istio 从入门到放弃 (五) istio 网络安全

文章目录

  • 配置基于HTTP的授权
  • 配置TLS安全网关
  • JWT鉴权

配置基于HTTP的授权

一般应用层面的业务服务都会基于http做各种请求get、post、put等方法的授权功能,这里做简单的演示

1.由于前面已经部署好bookinfo服务,如果做过对reviews服务的路由配置,这里可以把它删除掉,这样堆reviews服务的访问就会轮询它下面的三个实例,分别展示红星、黑星和无星

kubectl delete vs reviews

2.接下来在default的namespace下创建一个拒绝所有请求的策略,可以看到这个策略没有配置任何选择器selector,这个策略就会适用于default 命名空间下所有的服务实例,spec:的值也是空{},这代表着所有流量都被拒绝

kubectl apply -f - <

3.再去刷新页面就会返回RBAC: access denied的页面提示
4.创建一个允许get请求访问productpage服务的策略,这个策略没有设置from字段的值,这意味着任何来源的请求都允许访问

kubectl apply -f - <

这个时候再去刷新页面可以看到productpage页面但是,details服务和reivews服务的内容依然是看不到的,这是服务期望的,因为我们授权productpage可以访问details和reviews
5.接下来创建允许productpage可以访问details服务的策略,它允许cluster.local/ns/default/sa/bookinfo-productpage这个service account发出的get请求去访问details服务

kubectl apply -f - <

执行之后刷新页面就可以看到details服务显示内容了
6.创建允许productpage可以访问reviews服务的策略,它允许cluster.local/ns/default/sa/bookinfo-productpage这个service account发出的get请求去访问reviews服务

kubectl apply -f - <

刷新页面就可以看到右侧reviews服务的内容就可以看到了,但是ratings服务的内容依然是不可用的,无法看到,原因也是因为没有创建对应的授权策略
7.最后创建运训reviews服务访问ratings服务的策略,它允许cluster.local/ns/default/sa/bookinfo-reviews 这个service account发出的任何get请求访问ratings服务

kubectl apply -f - <

最后刷新页面,就可以像开头那样看到不同版本的reviews服务的内容了

配置TLS安全网关

  • 为了网络安全,需要为网关配置https的访问方式,保证请求在公网传输是安全的,同时系统内部不需要做任何改动

1.为服务创建根证书和私钥:

openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout example.com.key -out example.com.crt

2.为httpbin.example.com创建证书和私钥:

openssl req -out httpbin.example.com.csr -newkey rsa:2048 -nodes -keyout httpbin.example.com.key -subj "/CN=httpbin.example.com/O=httpbin organization"
openssl x509 -req -days 365 -CA example.com.crt -CAkey example.com.key -set_serial 0 -in httpbin.example.com.csr -out httpbin.example.com.crt
  1. 创建secret
kubectl create -n istio-system secret tls httpbin-credential --key=httpbin.example.com.key --cert=httpbin.example.com.crt

4.定义网关引用上一步的secret 指定https协议和443端口

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: mygateway
spec:
  selector:
    istio: ingressgateway 
  servers:
  - port:
      number: 443
      name: https
      protocol: HTTPS
    tls:
      mode: SIMPLE
      credentialName: httpbin-credential
    hosts:
    - httpbin.example.com

5.如果之前没有部署http-bin服务,需要部署一下

apiVersion: v1
kind: Service
metadata:
  name: httpbin
  labels:
    app: httpbin
spec:
  ports:
  - name: http
    port: 8000
  selector:
    app: httpbin
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpbin
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpbin
      version: v1
  template:
    metadata:
      labels:
        app: httpbin
        version: v1
    spec:
      containers:
      - image: docker.io/citizenstig/httpbin
        imagePullPolicy: IfNotPresent
        name: httpbin
        ports:
        - containerPort: 8000

6.定义验证需要的路由VirtualService

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: mygateway
spec:
  hosts:
  - "*"
  gateways:
  - mygateway
  http:
  - match:
    - uri:
        exact: /status
    - uri:
        prefix: /status
    route:
    - destination:
        host: httpbin
        port:
          number: 8000

7.获取https对外暴露的地址

//获取https 443 对外暴露的端口
kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}'
31967
//获取https 443 对外暴露的ip
kubectl get po -l istio=ingressgateway -n istio-system -o jsonpath='{.items[0].status.hostIP}'
192.168.188.130
  1. 请求验证,记得替换自己获取的ip和port,由于我的集群部署在虚拟机上,虚拟机192.168.188.130这个地址又被我映射到10.25.155.1这个宿主机上,所以下面验证的时候我是用的是10.25.155.1这个地址,最后获取茶壶的图案就代表配置https成功了
curl -i  -HHost:httpbin.example.com \                                                                 
--resolve httpbin.example.com:31967:10.25.155.1 \
--cacert example.com.crt "https://httpbin.example.com:31967/status/418"
HTTP/2 418
server: istio-envoy
date: Thu, 10 Sep 2020 10:09:26 GMT
access-control-allow-origin: *
access-control-allow-credentials: true
x-more-info: http://tools.ietf.org/html/rfc2324
content-length: 135
x-envoy-upstream-service-time: 48


    -=[ teapot ]=-

       _...._
     .'  _ _ `.
    | ."` ^ `". _,
    \_;`"---"`|//
      |       ;/
      \_     _/
        `"""`

JWT鉴权

1.首先创建模拟服务httpbin和sleep,为这俩服务注入envoy 代理实现鉴权

root@kube1:~# kubectl create ns foo
namespace/foo created
root@kube1:~/istio/istio-1.5.1# kubectl apply -f <(istioctl kube-inject -f samples/httpbin/httpbin.yaml) -n foo
serviceaccount/httpbin created
service/httpbin created
deployment.apps/httpbin created
root@kube1:~/istio/istio-1.5.1# kubectl apply -f <(istioctl kube-inject -f samples/sleep/sleep.yaml) -n foo
serviceaccount/sleep created
service/sleep created
deployment.apps/sleep created

2.验证这俩服务部署成功,并且可以互相通讯

root@kube1:~/istio/istio-1.5.1# kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- curl http://httpbin.foo:8000/ip -s -o /dev/null -w "%{http_code}\n"
200

3.在foo这个namespace下为httpbin这个服务创建jwt的认证策略,这个策略只接受[email protected] 颁发的jwt令牌

kubectl apply -f - <

4.等待一会策略才会生效,当通过一个无效的令牌访问这个服务的时候,会返回401

root@kube1:~/istio/istio-1.5.1# kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- curl "http://httpbin.foo:8000/headers" -s -o /dev/null -H "Authorization: Bearer invalidToken" -w "%{http_code}\n"
401

5.当你不通过jwt去访问这个服务,依然可以请求成功,因为它还没有配置授权策略

root@kube1:~/istio/istio-1.5.1# kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- curl "http://httpbin.foo:8000/headers" -s -o /dev/null -w "%{http_code}\n"
200

6.为httpbin这个服务创建一个授权策略,所有请求这个服务的流量必须携带有效的jwt信用凭证

kubectl apply -f - <

7.接着生成一个jwt的token也就是一个信用凭证

root@kube1:~/istio/istio-1.5.1# TOKEN=$(curl https://raw.githubusercontent.com/istio/istio/release-1.7/security/tools/jwt/samples/demo.jwt -s) && echo "$TOKEN" | cut -d '.' -f2 - | base64 --decode -

{"exp":4685989700,"foo":"bar","iat":1532389700,"iss":"[email protected]","sub":"[email protected]"}root@kube1:~/istio/istio-1.5.1

8.携带这个token去请求服务,可以得到200的成功响应

root@kube1:~/istio/istio-1.5.1# kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- curl "http://httpbin.foo:8000/headers" -s -o /dev/null -H "Authorization: Bearer $TOKEN" -w "%{http_code}\n"
200

9.现在不携带token去访问就会返回403拒绝服务了

root@kube1:~/istio/istio-1.5.1# kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- curl "http://httpbin.foo:8000/headers" -s -o /dev/null -w "%{http_code}\n"
403

你可能感兴趣的:(云原生,service,mesh,kubernetes,istio,云原生)