😽

【Istio】TLS / Authentication / Authorizationまとめ

2021/05/27に公開

TLS設定

TLS Secretを用いたHTTPS設定

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: my-gateway
  namespace: default
spec:
  selector:
    istio: ingressgateway  # default istio gateway proxy
  servers:
  - port:
      number: 80  # HTTP用
      name: http
      protocol: HTTP
    hosts:
    - uk.bookinfo.com  # DNSホスト(HTTP用)
  - port:
      number: 443  # HTTPS用
      name: https
      protocol: HTTPS
    hosts:
    - "bookinfo-namespace/*.bookinfo.com"  # HTTPS ポート443用DNS
    tls:
      mode: SIMPLE  # SIMPLE or MUTUAL
      credentialName: bookinfo-secret  # TLS証明書

SNI(複数ホストへのTLS)設定

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: my-gateway
  namespace: default
spec:
  selector:
    istio: ingressgateway  # default istio gateway proxy
  servers:
  - port:
      number: 80  # HTTP用
      name: http
      protocol: HTTP
    hosts:
    - uk.bookinfo.com  # DNSホスト(HTTP用)
  - port:
      number: 443  # HTTPS用
      name: https
      protocol: HTTPS
    hosts:
    - "bookinfo-namespace/*.bookinfo.com"  # HTTPS ポート443用DNS
    tls:
      mode: SIMPLE  # SIMPLE or MUTUAL
      credentialName: bookinfo-secret  # TLS証明書
  - port:
      number: 443  # SNI用HTTPSポート443
      name: https-sni
      protocol: HTTPS
    hosts:
    - "bookinfo-namespace/*.bookinfo-to-sni.com"  # DNS(SNI用)
    tls:
      mode: SIMPLE  # SIMPLE or MUTUAL
      credentialName: bookinfo-secret-to-sni # TLS証明書(SNI用)

SNI用ホストをVirtualServiceに追加

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: bookinfo-rule
  namespace: default
spec:
  hosts:
  - "bookinfo-namespace/*.bookinfo.com"  # HTTPS(メイン用)
  - "bookinfo-namespace/*.bookinfo-to-sni.com"  # HTTPS(SNI用)
  gateways:
  - default/my-gateway
  http:
  - match:
    - uri:
        prefix: /reviews/
    route:
    - destination:
        port:
          number: 80  # serviceポート
        host: reviews.prod.svc.cluster.local

PeerAuthentication(Namespace限定)

apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: default
  namespace: default  # 相互TLSトラフィックのみ許容 相互TLSのためdefaultはブロック
spec:
  mtls:
    mode: STRICT

PeerAuthentication(Workload限定)

apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: default
  namespace: default  # 相互TLSトラフィックのみ許容 
spec:
  selector:
    matchLabels:
      run: httpbin  # ラベル(httpbin)がついているpodに限定される
  mtls:
    mode: STRICT
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: httpbin
spec:
  host: httpbin.default  # ホスト
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL  # 相互TLSのみ許可する

HTTPからHTTPSへのリダイレクト

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: my-gateway
  namespace: some-config-namespace
spec:
  selector:
    app: my-gateway-controller
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - uk.bookinfo.com  # HTTPホスト
    tls:
      httpsRedirect: true  # HTTPからHTTPSへリダイレクト

curl pod作成

$ kubectl run curl \
      --restart Never \
      --image curlimages/curl \
      -n <namespace名> \
      --dry-run -o yaml \
      -- /bin/sh -c "sleep infinity" > curl_pod.yaml

httpbin pod作成

$ kubectl run httpbin \
      --restart Never \
      -n <namespace名> \
      --image docker.io/kennethreitz/httpbin

httpbin pod公開

kubectl expose pod httpbin --port 80 -n <namespace名>

curl実行

$ kubectl exec -it curl -n <curl podのnamespace名> sh
$ curl httpbin.<httpbinのnamespace名>/headers -v

JWT認証

apiVersion: security.istio.io/v1beta1
kind: RequestAuthentication
metadata:
  name: "jwt-example"
  namespace: istio-system  # Istioのroot namespaceに適用する
spec:
  selector:
    matchLabels:
      app: ingressgateway  # IngressGatewayに適用
  jwtRules:  # JWT必須化
  - issuer: "testing@secure.istio.io"
    jwksUri: "https://raw.githubusercontent.com/istio/istio/release-1.10/security/tools/jwt/samples/jwks.json"
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: require-jwt
  namespace: istio-system  # Istioのroot namespaceに適用する
spec:
  selector:
    matchLabels:
      app: ingressgateway  # IngressGatewayに適用
  action: ALLOW
  rules:
  - from:
    - source:  # principalsがある場合、JWT有効(valid)
       requestPrincipals: ["testing@secure.istio.io/testing@secure.istio.io"]

JWT認証(HTTP PATH限定)

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: jwt_path
  namespace: istio-system  # Istioのroot namespaceに適用する
spec:
  selector:
    matchLabels:
      app: ingressgateway  # IngressGatewayに適用
  action: ALLOW
  rules:
  - from:
    - source:  # principalsがある場合、JWT有効(valid)
       requestPrincipals: ["testing@secure.istio.io/testing@secure.istio.io"]
    to:
      - operation:
          paths: ["/headers"]  # headersへのアクセスは、JWT認証必須
      hosts: ["test.sni.com"]  # test.sni.com/headersへのアクセスはJWT認証必須

HTTP header Attributeを用いたJWT認証

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: jwt_path
  namespace: istio-system  # Istioのroot namespaceに適用する
spec:
  selector:
    matchLabels:
      app: ingressgateway  # IngressGatewayに適用
  action: ALLOW
  rules:
  - from:
    - source:  # principalsがある場合、JWT有効(valid)
       requestPrincipals: ["testing@secure.istio.io/testing@secure.istio.io"]
    to:
      - operation:
          paths: ["/headers"]  # headersへのアクセスは、JWT認証必須
      hosts: ["test.sni.com"]  # test.sni.com/headersへのアクセスはJWT認証必須
    when:
    - key: request.headers[x-token]
      values: ["admin"]  # headerのX-tokenがadminである必要あり

特定のIPアドレスに対して、JWT認証を有効化する

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: jwt_path
  namespace: istio-system  # Istioのroot namespaceに適用する
spec:
  selector:
    matchLabels:
      app: ingressgateway  # IngressGatewayに適用
  action: ALLOW
  rules:
  - from:
    - source:
       ipBlocks: ["XX.XXX.X.XX"]  # 指定したIPアドレスのみ、アクセス許可

ServiceEntry

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: external-svc-https
spec:
  hosts:
  - api.dropboxapi.com  # ServiceEntryに関連付けられているホスト
  location: MESH_EXTERNAL  # サービスを「メッシュの外部と見なす」か、「メッシュの一部と見なす」か
  ports:
  - number: 443
    name: https
    protocol: TLS
  resolution: DNS  # 必須項目

タイムアウト設定

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews-route
spec:
  hosts:
  - reviews.prod.svc.cluster.local # k8sのService名(virtualservice.ymlと同じ)
  - mesh  # Gatewayに限らず、それぞれのEnvoy Proxyにもルールを適用する
  http:
  - timeout: 1s  # 1秒以内にreturnしない場合、HTTPエラーコードが表示される
  - route:
    - destination:
        host: reviews.prod.svc.cluster.local # k8sのService名(virtualservice.ymlと同じ)
        subset: v1 # podにつけたlabel(負荷分散用)
      weight: 25
    - destination:
        host: reviews.prod.svc.cluster.local # k8sのService名(virtualservice.ymlと同じ)
        subset: v2 
      weight: 75

ServiceEntry HTTPS有効化

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: external-svc-https
spec:
  hosts:
  - www.google.com  # ServiceEntryに関連付けられているホスト
  location: MESH_EXTERNAL  # サービスを「メッシュの外部と見なす」か、「メッシュの一部と見なす」か
  ports:
  - number: 80
    name: http-port
    protocol: HTTP
  - number: 443
    name: https-port-for-tls-origination
    protocol: HTTPS
  resolution: DNS  # 必須項目
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: google-com
spec:
  host: www.google.com
  subsets:
  - name: tls-origination
    trafficPolicy:
      loadBalancer:  # round robin / random / least connectionの3択
        simple: ROUND_ROBIN
      portLevelSettings:
      - port:
          number: 443
        tls:
          mode: SIMPLE  # SIMPLE or MUTUAL
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: google.com
spec:
  hosts:
  - "*.google.com"
  http:
  - match:
    - port: 80
  - route:
    - destination:
        host: www.google.com  # ServiceEntryとDestinationRuleと関連付け
        subset: tls-origination  # DestinationRuleで定義
        port:
          number: 443

参考文献

Discussion