深圳幻海软件技术有限公司 欢迎您!

如何将Emissary Ingress与OPA集成

2023-03-20

​译者| 李睿审校| 孙淑娟API网关在公开微服务时,起着至关重要的作用。它们是网络中的一个附加跃点,传入请求必须通过该跃点才能与服务通信。API网关在收到来自客户端的请求之后会执行路由、组合、协议转换和用户策略实施,然后将其反向代理到适当的底层API。由于API网关能够执行上述

​译者 | 李睿

审校 | 孙淑娟

API网关在公开微服务时,起着至关重要的作用。它们是网络中的一个附加跃点,传入请求必须通过该跃点才能与服务通信。API网关在收到来自客户端的请求之后会执行路由、组合、协议转换和用户策略实施,然后将其反向代理到适当的底层API。由于API网关能够执行上述任务,它们还可以配置为将传入的客户端请求发送到外部第三方授权(authz)服务器。然后,传入请求的命运取决于这一外部身份验证服务器对网关的响应。这正是开放策略代理(OPA)发挥作用的地方。  

有许多开源的Kubernetes原生API网关,例如Contour、Kong Gateway、Traefik、Gloo等。以下深入了解一下Emissary Ingress。  

什么是Emissary Ingress?  

Emissary Ingress早期被称为Ambassar API网关;它是一个开源的Kubernetes原生API网关,目前是云原生应用计算基金会(CNCF)孵化项目。与许多其他Kubernetes网关一样,Emissary也被构建为与Envoy代理一起使用。它部署为完整的无状态架构,并支持多个插件,例如传统的SSO身份验证协议(例如OAuth、OpenIDConnect)、速率限制、日志记录和跟踪服务。Emissary在AuthService资源中利用其ExtAuth协议来配置传入请求的身份验证和授权。ExtAuth支持两种协议:gRPC和HTTP。对于gRPC接口,外部服务必须实现Envoy的external_auth.proto。  

OPA  

Open Policy Agent(OPA)是一个众所周知的通用策略引擎,并已成为跨堆栈的策略执行器,无论是API网关、服务网格、Kubernetes、微服务、CI/CD还是IAC。OPA将决策制定与策略执行分离,这样每当软件需要对传入请求做出决定时,它都会查询OPA。OPA-Envoy使用实现Envoy外部授权API的gRPC服务器扩展OPA,从而使其自身与Emissary的外部authz服务器兼容。

将Emissary Ingress与OPA集成  

上图展示了Emissary和OPA集成的高层架构。当来自客户端的传入请求到达Emissary时,它会向OPA发送授权请求,其中包含输入JSON。OPA根据提供给它的Rego策略评估这个JSON并响应Emissary;如果来自OPA的这个结果JSON允许为真,那么只有客户端请求被进一步路由到API,否则请求被Emissary拒绝并且永远不会到达API。将安装Emissary Ingress并将其与OPA集成以进行外部授权。  

(1)入门  

首先,需要启动一个Minikube集群。如果没有Minikube,可以从这里安装它。  

minikube start
  • 1.

通过Helm将Emissary Ingress安装到minikube。  

# Add the Repo:
helm repo add datawire https://app.getambassador.io
helm repo update
# Create Namespace and Install:
kubectl create namespace emissary && \
kubectl apply -f https://app.getambassador.io/yaml/emissary/2.2.2/emissary-crds.yaml
kubectl wait --timeout=90s --for=condition=available deployment emissary-apiext -n emissary-system
helm install emissary-ingress --namespace emissary datawire/emissary-ingress && \
kubectl -n emissary wait --for condition=available --timeout=90s deploy -lapp.kubernetes.io/instance=emissary-ingress
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

或者参考Emissary Ingress文档通过Kubernetes YAMLs安装它。

(2)为演示应用程序配置路由  

不同的网关有自己的一组用于公开服务的配置。在Emissary中,需要通过映射和侦听器配置路由。

映射资源只是告诉Emissary将传入请求重定向到哪个服务。它像Ingress一样高度可配置。将创建一个简单的映射资源,它将所有传入请求重定向到演示应用程序的服务,即demo-svc。  

cat <<EOF | kubectl apply -f -
apiVersion: getambassador.io/v3alpha1
kind: Mapping
metadata:
  name: demo-app-mapping  
spec:
  hostname: "*"
  prefix: /
  service: demo-svc
EOF
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

侦听器资源指示Emissary在网络上侦听传入请求。在这里,将创建一个侦听器来侦听端口8080和HTTP协议,并与所有命名空间中的主机关联。

cat <<EOF | kubectl apply -f -
apiVersion: getambassador.io/v3alpha1
kind: Listener
metadata:
  name: demo-app-listener-8080
  namespace: emissary
spec:
  port: 8080
  protocol: HTTP
  securityModel: XFP
  hostBinding:
    namespace:
      from: ALL
EOF
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.

(3)安装echo应用程序  

安装一个简单的echo服务器作为演示应用程序。  

cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: demo-app
  template:
    metadata:
      labels:
        app: demo-app
    spec:
      containers:
      - name: http-svc
        image: gcr.io/google_containers/echoserver:1.8
        ports:
        - containerPort: 8080
        env:
        - name: NODE_NAME
          valueFrom:
            fieldRef:
              fieldPath: spec.nodeName
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: POD_IP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP
---
apiVersion: v1
kind: Service
metadata:
  name: demo-svc
  labels:
    app: demo-app
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    app: demo-app
EOF
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.

通过不同的路径与演示应用程序通信。

minikube service emissary-ingress -n emissary
  • 1.

注意:上述公开方法可能不适用于macOS用户。他们可以使用一个忙框,并将其配置为命中Emissary本地端点。

使用目标端口80复制专用URL。URL必须为IP 192.168.49.2,后跟一个节点端口,如http://192.168.49.2:30329。将NodePort值导出为$NodePort环境变量,并将curl导出为路径处的值,如下所示:

curl http://192.168.49.2:$NODEPORT/public
curl http://192.168.49.2:$NODEPORT/secured
  • 1.
  • 2.

OPA尚未添加到设置中,并且上述curl请求直接发送到API,而无需任何策略强制。

(4)如何安装和配置OPA?

OPA将通过configmap读取提供给它的策略。创建以下configmap,其中包含一个策略,该策略只允许通过GET方法接收所有传入请求。

cat <<EOF | kubectl apply -n emissary -f  -
apiVersion: v1
kind: ConfigMap
metadata:
  name: demo-policy
data: 
  policy.rego: |-
    package envoy.authz
    default allow = false
    allow {
       input.attributes.request.http.method == "GET" 
    }
EOF
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

通过将OPA部署为独立部署或作为emissary-ingress的sidecar,可以将OPA配置为外部授权服务器。在这里,将其添加为sidecar。将以下YAML保存为opa-patch.yaml。  

spec:
  template:
    spec:
      containers:
      - name: opa
        image: openpolicyagent/opa:latest-envoy
        ports:
        - containerPort: 9191
        args:
          - "run"
          - "--server"
          - "--addr=0.0.0.0:8181"
          - "--set=plugins.envoy_ext_authz_grpc.addr=0.0.0.0:9191"
          - "--set=plugins.envoy_ext_authz_grpc.query=data.envoy.authz.allow"
          - "--set=decision_logs.console=true"
          - "--ignore=.*"
          - "/policy/policy.rego"
        volumeMounts:
          - mountPath: /policy
            name: demo-policy
            readOnly: true
      volumes:
      - name: demo-policy
        configMap:
          name: demo-policy
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.

修补 emissary-ingress 部署并等待所有 emissary-ingress pod 重新启动。

kubectl patch deployment emissary-ingress -n emissary --patch-file opa-patch.yaml
  • 1.

等到所有的emissary-ingresspod进入带有OPA sidecar的运行状态。  

创建以下AuthService。AuthService是一种资源,它配置Emissary与外部服务进行通信,以获取传入请求的Authn和Authz。将其配置为与localhost上的OPA通信,因为OPA被部署为sidecar。

cat <<EOF | kubectl apply -f -
apiVersion: getambassador.io/v3alpha1
kind: AuthService
metadata:
  name: opa-ext-authservice
  namespace: emissary
  labels:
    product: aes
    app: opa-ext-auth
spec:
  proto: grpc
  auth_service: localhost:9191
  timeout_ms: 5000
  tls: "false"
  allow_request_body: true
  protocol_version: v2
  include_body:
    max_bytes: 8192
    allow_partial: true
  status_on_error:
    code: 504
  failure_mode_allow: false
EOF
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.

现在尝试curl;由于该策略接受来自GET方法的请求并且对路径没有限制,因此两个请求都将获得200个OK响应。

curl -i http://192.168.49.2:$NODEPORT/public
curl -i http://192.168.49.2:$NODEPORT/private
  • 1.
  • 2.

现在编辑策略以仅接受来自路径 /public 的传入请求,而对任何其他路径的请求都将被拒绝。

cat <<EOF | kubectl apply -n emissary -f  -
apiVersion: v1
kind: ConfigMap
metadata:
  name: demo-policy
data: 
  policy.rego: |-
    package envoy.authz
    default allow = false
    allow {
       input.attributes.request.http.method == "GET"
       input.attributes.request.http.path == "/public" 
    }
EOF
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.

现在重新启动使者入口部署以使策略更改生效。

kubectl rollout restart deployment emissary-ingress -n emissary
  • 1.

等到所有的Emissary-Ingresspod在重启后进入Running状态。  

现在在路径/public处执行curl请求;它将被接受,但在路径/privat,e它将被OPA拒绝并返回403响应,因此请求不会到达演示API。  

curl-ihttp://192.168.49.2:$NODEPORT/public  
curl-ihttp://192.168.49.2:$NODEPORT/private
  • 1.
  • 2.

关于从客户端到公开API的传入请求的决策可以解耦到OPA作为Emissary Ingress设置中的外部授权服务器。OPA可以作为即插即用策略执行器添加到Emissary和任何其他支持Envoy外部授权API的网关。

原文标题:​​How Do You Integrate Emissary Ingress With OPA​​​,作者:Tayyab Jamadar