NGINX Ingress Controller Documentation

구성

이 문서는 NGINX App Protect WAF 모듈을 구성하는 방법을 설명합니다.

VirtualServer 리소스Ingress 리소스에 대한 GitHub의 App Protect WAF 예제 리소스가 포함된 전체 NGINX Ingress Controller를 확인하세요.

목차

1. 글로벌 구성
2. App Protect 활성화
3. App Protect WAF 정책
4. App Protect WAF Log
5. App Protect WAF 사용자 정의 서명
6. NGINX Ingress Controller의 OpenAPI 사양
6-1. OpenAPI 참조 유형
6-1-1. URL Reference

7. NGINX Ingress Controller의 구성
8. Virtual Server Resource를 사용하여 NGINX Plus Ingress Controller 구성
9. 전제 조건

9-1. 1단계 웹 애플리케이션 배포
9-2. 2단계 AP 정책 배포
9-3. 3단계 WAF 정책 배포

9-4. 4단계 Load Balancning 구성
9-5. 5단계 애플리케이션 테스트
9-6. Virtual Server의 구성 예

1. 글로벌 구성

NGINX Ingress Controller에는 NGINX App Protect WAF 모듈에서 사용할 수 있는 것과 일치하는 글로벌 구성 매개변수가 있습니다. 전체 목록은 ConfigMap Key를 참조하세요. App Protect 매개변수는 app-protect* 접두사를 사용합니다.

2. App Protect 활성화

사용자 정의 리소스(VirtualServer, VirtualServerRoute) 또는 Ingress 리소스 기반으로 NGINX App Protect WAF를 활성화하고 구성할 수 있습니다.

VirtualServer 리소스에서 NGINX App Protect WAF를 구성하려면 APPolicy 사용자 정의 리소스를 참조하는 Policy 사용자 정의 리소스를 만들고 이를 VirtualServer 정의에 추가합니다. App Protect WAF 정책에 대한 문서를 참조하세요.

Ingress 리소스에서 NGINX App Protect WAF를 구성하려면 원하는 각 리소스에 App Protect Annotations을 적용합니다.

3. App Protect WAF 정책

APPolicy Custom Resource를 생성하여 VirtualServer, VirtualServerRoute 또는 Ingress 리소스에 대한 App Protect WAF 정책을 정의할 수 있습니다.

Notepolicy.signature-requirements[].minRevisionDatetimepolicy.signature-requirements[].maxRevisionDatetime 필드는 현재 지원되지 않습니다.

Note: 단항 트래픽에 대한 고급 gRPC 보호는 idl 파일 Inline 제공만 지원합니다. policy.idl-files[].link, policy.idl-files[].$refpolicy.idl-files[].file 필드는 지원되지 않습니다. IDL 파일은 policy.idl-files[].contents 필드에 제공되어야 합니다. 이 필드의 값은 base64로 인코딩될 수 있습니다. 이 경우 policy.idl-files[].isBase64 필드를 true로 설정해야 합니다.

Note: Ingress Controller의 외부 참조는 더 이상 사용되지 않으며 향후 릴리스에서 지원되지 않습니다.

Ingress 리소스에 App Protect WAF 정책을 추가하려면:

1. APPolicy Custom 리소스 Manifest를 생성합니다.

2. APPolicy 리소스의 spec 필드에 원하는 정책을 추가합니다.

Note: 정책 JSON과 리소스 사양 간의 관계는 1:1입니다. 예제에서와 같이 YAML에서 리소스를 정의하는 경우 정책을 YAML로 나타내야 합니다. 필드는 이름과 Level에서 Source JSON의 필드와 정확히 일치해야 합니다.

예를 들어 아래와 같은 DataGuard 정책을 사용한다고 가정해 보겠습니다.

{
    "policy": {
        "name": "dataguard_blocking",
        "template": { "name": "POLICY_TEMPLATE_NGINX_BASE" },
        "applicationLanguage": "utf-8",
        "enforcementMode": "blocking",
        "blocking-settings": {
            "violations": [
                {
                    "name": "VIOL_DATA_GUARD",
                    "alarm": true,
                    "block": true
                }
            ]
        },
        "data-guard": {
            "enabled": true,
            "maskData": true,
            "creditCardNumbers": true,
            "usSocialSecurityNumbers": true,
            "enforcementMode": "ignore-urls-in-list",
            "enforcementUrls": []
        }
    }
}

아래와 같이 spec에 정의된 정책을 사용하여 APPolicy 리소스를 생성합니다.

apiVersion: appprotect.f5.com/v1beta1
kind: APPolicy
metadata:
  name: dataguard-blocking
spec:
  policy:
    name: dataguard_blocking
    template:
      name: POLICY_TEMPLATE_NGINX_BASE
    applicationLanguage: utf-8
    enforcementMode: blocking
    blocking-settings:
      violations:
      - name: VIOL_DATA_GUARD
        alarm: true
        block: true
    data-guard:
      enabled: true
      maskData: true
      creditCardNumbers: true
      usSocialSecurityNumbers: true
      enforcementMode: ignore-urls-in-list
      enforcementUrls: []

필드가 이름과 Level에서 정확히 어떻게 일치하는지 확인하십시오. Ingress Controller가 YAML을 유효한 JSON App Protect WAF 정책 구성으로 변환합니다.

4. App Protect WAF Log

APLogConf Custom Resource를 생성하여 App Protect WAF Log 구성을 설정할 수 있습니다.

App Protect WAF Log 구성을 VirtualServer 또는 Ingress 리소스에 추가하려면:

1. APLogConf 사용자 정의 리소스 Manifest를 만듭니다.

2. APLogConf 리소스의 spec 필드에 원하는 Log 구성을 추가합니다.

3. 설명서에 따라 VirtualServer 정책 리소스 또는 Ingress 리소스에 대한 APLogConf 참조를 추가합니다.

예를 들어 App Protect WAF를 사용하여 VirtualServer 또는 Ingress 리소스에 대한 상태 변경 요청을 기록한다고 가정합니다. App Protect WAF Log 구성은 다음과 같습니다.

{
    "filter": {
        "request_type": "all"
    },
    "content": {
        "format": "default",
        "max_request_size": "any",
        "max_message_size": "5k"
    }
}

다음과 같이 APLogConf 리소스의 spec 에서 해당 구성을 정의합니다.

apiVersion: appprotect.f5.com/v1beta1
kind: APLogConf
metadata:
  name: logconf
spec:
  filter:
    request_type: all
  content:
    format: default
    max_request_size: any
    max_message_size: 5k

5. App Protect WAF 사용자 정의 서명

APUserSig Custom Resource를 생성하여 VirtualServer 또는 Ingress 리소스에 대한 App Protect WAF 사용자 정의 서명을 정의할 수 있습니다.

NoterevvisionDatetime 필드는 현재 지원되지 않습니다.

NoteAPUserSig 리소스는 APPolicyAPLogConf 리소스에 비해 NGINX Plus의 Reload 시간을 늘립니다. 자세한 내용은 NGINX Start 또는 Reload 실패를 참조하십시오.

VirtualServer 또는 Ingress 리소스에 사용자 정의 서명을 추가하려면:

1. APUserSig 사용자 정의 리소스 Manifest를 만듭니다.

2. 원하는 사용자 정의 서명을 APUserSig 리소스의 spec 필드에 추가합니다.

Note: JSON의 필드는 YAML에서 이름과 Level이 정확히 동일하게 표시되어야 합니다. Ingress Controller는 YAML을 유효한 JSON App Protect WAF 사용자 정의 서명으로 변환합니다. 정책 또는 Ingress 리소스에서 사용자 정의 서명 리소스를 참조할 필요가 없습니다.

예를 들어 다음과 같은 사용자 정의 서명을 만들고 싶다고 가정해 보겠습니다.

{  "softwareVersion": "15.1.0",
    "tag": "Fruits",
    "signatures": [
      {
      "name": "Apple_medium_acc",
      "rule": "content:\"apple\"; nocase;",
      "signatureType": "request",
      "attackType": {
         "name": "Brute Force Attack"
      },
      "systems": [
         {"name": "Microsoft Windows"},
         {"name": "Unix/Linux"}
                     ],
      "risk": "medium",
      "accuracy": "medium",
      "description": "Medium accuracy user defined signature with tag (Fruits)"
      }
   ]
}

다음과 같이 APUserSig 리소스 spec 에 해당 구성을 추가할 수 있습니다:

apiVersion: appprotect.f5.com/v1beta1
kind: APUserSig
metadata:
  name: apple
spec:
  signatures:
  - accuracy: medium
    attackType:
      name: Brute Force Attack
    description: Medium accuracy user defined signature with tag (Fruits)
    name: Apple_medium_acc
    risk: medium
    rule: content:"apple"; nocase;
    signatureType: request
    systems:
    - name: Microsoft Windows
    - name: Unix/Linux
  softwareVersion: 15.1.0
  tag: Fruits

6. NGINX Ingress Controller의 OpenAPI 사양

OpenAPI 사양은 RESTful API를 설명하는 데 필요한 사양 파일 형식을 정의합니다. 사양 파일은 JSON 또는 YAML로 작성할 수 있습니다. 사양 파일을 사용하면 API 보호 구현 작업이 간소화됩니다. 자세한 내용은 OpenAPI 사양(이전의 Swagger)을 참조하세요.

NGINX Ingress Controller는 OpenAPI 사양 버전 2.0 및 3.0을 지원합니다.

API 보호 정책을 생성하는 가장 간단한 방법은 OpenAPI 사양 파일을 사용하여 API 세부 정보를 가져오는 것입니다. OpenAPI 사양 파일을 사용하는 경우 NGINX App Protect WAF는 사양 파일에 포함된 내용에 따라 다음 속성에 대한 정책을 자동으로 생성합니다.

  • Methods
  • URLs
  • Parameters
  • JSON profiles

OpenAPI 지원 정책 템플릿은 NGINX App Protect WAF 패키지와 함께 제공되며 다음 위치에 있습니다. /etc/app_protect/conf/NginxApiSecurityPolicy.json

blocking(enforced)으로 설정된 OpenAPI와 관련된 위반 사항이 포함되어 있습니다.

6-1. OpenAPI 참조 유형

OpenAPI Specification 파일을 참조하는 방법에는 여러 가지가 있습니다. 구성은 외부 참조와 유사합니다.

Note: 정책에서 참조되는 OpenAPI 사양 파일의 모든 업데이트는 정책 컴파일을 트리거(Trigger)하지 않습니다. 이 작업은 NGINX 구성을 Reload하여 활성화해야 합니다.

6-1-1. URL Reference

URL Reference는 전체 URL을 제공하여 External Source를 참조하는 방법입니다.

HTTPS 프로토콜을 사용하기 전에 인증서를 구성해야 합니다. 자세한 내용은 외부 참조를 참조하십시오.

7. NGINX Ingress Controller의 구성

다음은 NGINX Ingress Controller에서 OpenAPI 보호 정책을 배포하는 일반적인 단계입니다.

1. API 보안 정책 /etc/app_protect/conf/NginxApiSecurityPolicy.json을 편집할 수 있도록 다른 파일에 복사합니다.

2. 원하는 OpenAPI 파일에 대한 참조를 추가합니다.

3. 필요한 경우 다른 사용자 정의 변경을 수행합니다(예: Data Guard Protection 활성화).

4. 도구를 사용하여 결과를 YAML로 변환합니다. 예를 들어 yq utility가 많이 있습니다.

5. YAML 속성을 추가하여 정책 자체(4단계에서와 같이)를 사용자 정의 리소스의 spec 속성 내에 배치하는 APPolicy 사용자 정의 리소스를 생성합니다. 위의 App Protect Policies 섹션을 참조하세요.

6. 이 예와 같이 APPolicy 사용자 정의 리소스를 참조하는 Policy 개체를 만듭니다.

7. 마지막으로, 이 예와 같이 Policy 개체를 VirtualServer 리소스에 연결합니다.

Note: 정책을 컴파일할 때 리소스 파일이 있는 서버를 항상 사용할 수 있는지 확인해야 합니다.

구성 예제

이 예제에서는 링크를 사용하여 OpenAPI Specification 파일 참조를 /etc/app_protect/conf/NginxApiSecurityPolicy.yaml에 추가합니다. 이는 query_intquery_str 매개변수 값에 대해 허용되는 데이터 유형을 구성합니다.

정책 구성:

---
apiVersion: appprotect.f5.com/v1beta1
  kind: APPolicy
  metadata:
    name: petstore_api_security_policy
  spec:
    policy:
      name: petstore_api_security_policy
      description: NGINX App Protect WAF API Security Policy for the Petstore API
      template:
        name: POLICY_TEMPLATE_NGINX_BASE
      open-api-files:
      - link: https://raw.githubusercontent.com/aws-samples/api-gateway-secure-pet-store/master/src/main/resources/swagger.yaml
      blocking-settings:
        violations:
        - block: true
          description: Disallowed file upload content detected in body
          name: VIOL_FILE_UPLOAD_IN_BODY
        - block: true
          description: Mandatory request body is missing
          name: VIOL_MANDATORY_REQUEST_BODY
        - block: true
          description: Illegal parameter location
          name: VIOL_PARAMETER_LOCATION
        - block: true
          description: Mandatory parameter is missing
          name: VIOL_MANDATORY_PARAMETER
        - block: true
          description: JSON data does not comply with JSON schema
          name: VIOL_JSON_SCHEMA
        - block: true
          description: Illegal parameter array value
          name: VIOL_PARAMETER_ARRAY_VALUE
        - block: true
          description: Illegal Base64 value
          name: VIOL_PARAMETER_VALUE_BASE64
        - block: true
          description: Disallowed file upload content detected
          name: VIOL_FILE_UPLOAD
        - block: true
          description: Illegal request content type
          name: VIOL_URL_CONTENT_TYPE
        - block: true
          description: Illegal static parameter value
          name: VIOL_PARAMETER_STATIC_VALUE
        - block: true
          description: Illegal parameter value length
          name: VIOL_PARAMETER_VALUE_LENGTH
        - block: true
          description: Illegal parameter data type
          name: VIOL_PARAMETER_DATA_TYPE
        - block: true
          description: Illegal parameter numeric value
          name: VIOL_PARAMETER_NUMERIC_VALUE
        - block: true
          description: Parameter value does not comply with regular expression
          name: VIOL_PARAMETER_VALUE_REGEXP
        - block: true
          description: Illegal URL
          name: VIOL_URL
        - block: true
          description: Illegal parameter
          name: VIOL_PARAMETER
        - block: true
          description: Illegal empty parameter value
          name: VIOL_PARAMETER_EMPTY_VALUE
        - block: true
          description: Illegal repeated parameter name
          name: VIOL_PARAMETER_REPEATED

참조 파일 myapi.yaml의 내용:

openapi: 3.0.1
info:
  title: 'Primitive data types'
  description: 'Primitive data types.'
  version: '2.5.0'
servers:
  - url: http://localhost
paths:
  /query:
    get:
      tags:
        - query_int_str
      description: query_int_str
      operationId: query_int_str
      parameters:
        - name: query_int
          in: query
          required: false
          allowEmptyValue: false
          schema:
            type: integer
        - name: query_str
          in: query
          required: false
          allowEmptyValue: true
          schema:
            type: string           
      responses:
        200:
          description: OK
        404:
          description: NotFound

이 경우 다음 요청은 query_int 매개변수에 정수 값이 있을 것으로 예상하므로 Illegal parameter data type 위반을 트리거합니다.

http://localhost/query?query_int=abc

요청이 차단됩니다.

link 옵션은 openApiFileReference 속성에서도 사용할 수 있으며 위의 App Protect WAF 정책 예제에서 볼 수 있는 open-api-files 속성과 동의어입니다.

NoteopenApiFileReference는 배열이 아닙니다.

8. Virtual Server Resource를 사용하여 NGINX Plus Ingress Controller 구성

이 예에서는 간단한 웹 애플리케이션인 NGINX App Protect WAF가 포함된 NGINX Plus Ingress Controller를 배포한 다음 VirtualServer 리소스를 사용하여 해당 애플리케이션에 대한 Load Balancing 및 WAF Protection를 구성합니다.

Note: GitHub에서 예제와 참조된 파일을 찾을 수 있습니다.

9. 전제 조건

1. 설치 지침에 따라 NGINX App Protect WAF가 포함된 Ingress Controller를 배포합니다.

2. Ingress Controller의 Public IP 주소를 Shell 변수에 저장합니다.

 $ IC_IP=XXX.YYY.ZZZ.III

3. Ingress Controller의 HTTP 포트를 Shell 변수에 저장합니다.

 $ IC_HTTP_PORT=<port number>

9-1. 1단계 웹 애플리케이션 배포

애플리케이션 배포 및 서비스를 생성합니다.

$ kubectl apply -f https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/v2.4.2/examples/custom-resources/waf/webapp.yaml

9-2. 2단계 AP 정책 배포

1. App Protect 보안 Log에 대한 syslog 서비스 및 Pod을 작성하십시오.

$ kubectl apply -f https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/v2.4.2/examples/custom-resources/waf/syslog.yaml

2. 사용자 정의 서명, App Protect WAF 정책 및 Log 구성을 생성합니다.

  $ kubectl apply -f https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/v2.4.2/examples/custom-resources/waf/ap-apple-uds.yaml
  $ kubectl apply -f https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/v2.4.2/examples/custom-resources/waf/ap-dataguard-alarm-policy.yaml
  $ kubectl apply -f https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/v2.4.2/examples/custom-resources/waf/ap-logconf.yaml

9-3. 3단계 WAF 정책 배포

WAF 정책 생성

 $ kubectl apply -f https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/v2.4.2/examples/custom-resources/waf/waf.yaml

정책 리소스의 App Protect 구성 설정을 확인합니다. 이전 단계에서 만든 정책 및 Log 구성으로 App Protect를 구성하여 WAF Protection를 활성화합니다.

9-4. 4단계 Load Balancning 구성

1. VirtualServer 리소스를 생성합니다.

$ kubectl apply -f https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/v2.4.2/examples/custom-resources/waf/virtual-server.yaml

VirtualServer는 3단계에서 만든 정책 waf-policy를 참조합니다.

9-5. 5단계 애플리케이션 테스트

애플리케이션에 액세스하려면 coffee tea 서비스를 curl하십시오. –resolve 옵션을 사용하여 webapp.example.com 요청의 호스트 헤더를 설정합니다.

1. 애플리케이션에 요청을 보냅니다.

$ curl --resolve webapp.example.com:$IC_HTTP_PORT:$IC_IP http://webapp.example.com:$IC_HTTP_PORT/
Server address: 10.12.0.18:80
Server name: webapp-7586895968-r26zn

2. 이제 의심스러운 URL이 포함된 요청을 전송해 보겠습니다.

$ curl --resolve webapp.example.com:$IC_HTTP_PORT:$IC_IP "http://webapp.example.com:$IC_HTTP_PORT/<script>"
<html><head><title>Request Rejected</title></head><body>

3. 마지막으로 사용자 정의 서명과 일치하는 의심스러운 데이터를 전송해 보겠습니다.

$ curl --resolve webapp.example.com:$IC_HTTP_PORT:$IC_IP -X POST -d "apple" http://webapp.example.com:$IC_HTTP_PORT/
<html><head><title>Request Rejected</title></head><body>

보시다시피 의심스러운 요청은 App Protect에 의해 차단되었습니다.

4. syslog Pod에서 보안 Log를 확인하려면 다음을 수행하십시오.

$ kubectl exec -it <SYSLOG_POD> -- cat /var/log/messages

9-6. Virtual Server의 구성 예

Virtual Server 예제는 Github Repo를 참조하십시오.

apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
  name: webapp
spec:
  host: webapp.example.com
  policies:
  - name: waf-policy
  upstreams:
  - name: webapp
    service: webapp-svc
    port: 80
  routes:
  - path: /
    action:
      pass: webapp