Ambassador系列-09-AuthService認證服務

Authservice使用外部服務來實現身份驗證和授權。簡單來說,Client向Ambassador網關發送的請求,都會被Ambassador攔截,Ambassador會將攔截的請求報文體去除,只將報文頭轉發給外部認證服務,外部認證服務會進行身份驗證或者校驗token,如果合法將返回http狀態碼200,否則返回非200狀態碼。詳細流程如下:

Authentication Flow

  • AuthService是第一個調用的外部服務。Ambassador將http method和header都轉發給AuthService服務,只做兩個缺省變更:
    • Content-Length請求頭被置爲0.
    • 請求體body被移除。
  • 當返回HTTP狀態碼200時,表示認證或者校驗成功,允許繼續向上遊服務請求,其它所有的狀態碼都將阻止請求繼續進行,直接返回給客戶端。
  • bypass_auth:在Mapping中配置屬性bypass_auth爲true,禁用該mapping的身份驗證。
  • proto:外部認證服務支持的協議類型,包括http和grpc,缺省爲http。
  • include_body:是否包含報文體,缺省報文體會被去除。
    • max_bytes:傳遞給AuthService的報文體body的最大字節數。
    • allow_partial:如果爲true,第一個最大字節數會被髮送給AuthService,否則請求將被拒絕。
  • status_on_error:如果AuthService無法響應時返回的狀態碼,缺省爲403。
  • failure_node_allow:如果AuthService失敗時,請求是否允許轉到上游服務,缺省爲false。
  • 支持配置多個AuthService。

下面舉一例子。作者開發了一個簡單的SpringBoot應用,該應用在攔截器中接受username和password兩個參數,如果username=admin並且password=123時,返回http狀態碼200,否則返回狀態碼403。此服務作爲外部認證服務。該服務已經放到hub.docker.io中,存儲庫爲twingao/auth-server:1.0.0。

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    
    #接受兩個參數
    String username = (String)request.getParameter("username");
    String password = (String)request.getParameter("password");
	
    #如果username = admin並且password = 123時,返回SC_OK,即http狀態碼200.
    if (username != null && password != null) {
        if (username.equals("admin") && password.equals("123")) {
            response.reset();
            response.setStatus(HttpServletResponse.SC_OK);
	
            PrintWriter pw = response.getWriter();
            pw.flush();
            pw.close();
			
            return false;
        }
    }
	
    #否則,返回SC_FORBIDDEN,即http狀態碼403.
    response.reset();
    response.setStatus(HttpServletResponse.SC_FORBIDDEN);
    response.setCharacterEncoding("UTF-8");
    response.setContentType("applcation/json;chartset=UTF-8");

    PrintWriter pw = response.getWriter();
	
    pw.write(JSONObject.toJSONString(new JsonResult(ResultCode.NOT_LOGIN, "forbidden", "auth failure.")));
    pw.flush();
    pw.close();
	
    return false;
}

先將SpringBoot應用部署到Kubernetes。

vi auth-server-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: auth-service
  labels: 
    name: auth-service
spec:
  type: NodePort
  ports:
  - port: 80
    name: http
    protocol: TCP
    targetPort: 8080
    nodePort: 38080
  selector:
    name: auth-server
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: auth-server
spec:
  replicas: 1
  selector:
    matchLabels:
      name: auth-server
  template:
    metadata:
      labels: 
        name: auth-server
    spec:
      containers:
        - name: auth-server
          image: twingao/auth-server:1.0.0
          imagePullPolicy: IfNotPresent
          ports:
          - containerPort: 8080

kubectl apply -f auth-server-service.yaml

將auth-service設置爲外部認證服務AuthService。

vi auth-server-authservice.yaml
---
apiVersion: getambassador.io/v1
kind: AuthService
metadata:
  name: auth-server-authservice
spec:
  auth_service: auth-service:80

kubectl apply -f auth-server-authservice.yaml

假設echo服務已經被部署,否則請參考Ambassador系列-01-介紹、安裝和使用。現在繼續訪問echo服務。

#沒有攜帶username和password參數,禁止訪問
curl -i "http://192.168.1.50/foo"
HTTP/1.1 403 Forbidden
content-length: 69
content-type: text/plain
lua-scripts-enabled: Processed
date: Sat, 14 Dec 2019 04:17:28 GMT
server: envoy

{"code":"600","count":0,"data":"auth failure.","message":"forbidden"}

#攜帶正確的username和password參數,允許訪問
curl -i "http://192.168.1.50/foo/?username=admin&password=123"
HTTP/1.1 200 OK
date: Sat, 14 Dec 2019 04:22:32 GMT
content-type: text/plain
server: envoy
x-envoy-upstream-service-time: 12
lua-scripts-enabled: Processed
transfer-encoding: chunked


Hostname: echo-768f499dc8-f64b2

Pod Information:
        node name:      k8s-node2
        pod name:       echo-768f499dc8-f64b2
        pod namespace:  default
        pod IP: 10.244.2.41

Server values:
        server_version=nginx: 1.14.2 - lua: 10015

Request Information:
        client_address=10.244.1.35
        method=GET
        real path=//?username=admin&password=123
        query=username=admin&password=123
        request_version=1.1
        request_scheme=http
        request_uri=http://192.168.1.50:8080//?username=admin&password=123

Request Headers:
        accept=*/*
        content-length=0
        host=192.168.1.50
        user-agent=curl/7.29.0
        x-envoy-expected-rq-timeout-ms=3000
        x-envoy-internal=true
        x-envoy-original-path=/foo/?username=admin&password=123
        x-forwarded-for=10.244.0.0
        x-forwarded-proto=http
        x-request-id=5ee72824-4b25-4635-bba9-22cfa87f9d5c

Request Body:
        -no body in request-

#攜帶的username和password參數,但password值錯誤,禁止訪問
curl -i "http://192.168.1.50/foo?username=admin&password=1231"
HTTP/1.1 403 Forbidden
content-length: 69
content-type: text/plain
lua-scripts-enabled: Processed
date: Sat, 14 Dec 2019 04:24:03 GMT
server: envoy

{"code":"600","count":0,"data":"auth failure.","message":"forbidden"}

Ambassador系列文章

Ambassador系列-01-介紹、安裝和使用

Ambassador系列-02-Module模塊

Ambassador系列-03-服務配置和服務發現

Ambassador系列-04-服務配置Mapping

Ambassador系列-05-負載均衡

Ambassador系列-06-金絲雀發佈、斷路器、CORS和流量鏡像

Ambassador系列-07-TCP映射TCPMapping

Ambassador系列-08-TLS配置-HTTPS重定向和TLS終結

Ambassador系列-09-AuthService認證服務

Ambassador系列-10-RateLimitService限速服務

Ambassador系列-11-Helm安裝Ambassador Edge Stack 1.1.0

發佈了49 篇原創文章 · 獲贊 3 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章