github.com/nginxinc/kubernetes-ingress@v1.12.5/docs-web/configuration/policy-resource.md (about)

     1  # Policy Resource
     2  
     3  The Policy resource allows you to configure features like access control and rate-limiting, which you can add to your [VirtualServer and VirtualServerRoute resources](/nginx-ingress-controller/configuration/virtualserver-and-virtualserverroute-resources/).
     4  
     5  The resource is implemented as a [Custom Resource](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/).
     6  
     7  This document is the reference documentation for the Policy resource. An example of a Policy for access control is available in our [GitHub repo](https://github.com/nginxinc/kubernetes-ingress/blob/v1.12.5/examples-of-custom-resources/access-control).
     8  
     9  ## Contents
    10  
    11  - [Policy Resource](#policy-resource)
    12    - [Contents](#contents)
    13    - [Prerequisites](#prerequisites)
    14    - [Policy Specification](#policy-specification)
    15      - [AccessControl](#accesscontrol)
    16        - [AccessControl Merging Behavior](#accesscontrol-merging-behavior)
    17      - [RateLimit](#ratelimit)
    18        - [RateLimit Merging Behavior](#ratelimit-merging-behavior)
    19      - [JWT](#jwt)
    20        - [JWT Merging Behavior](#jwt-merging-behavior)
    21      - [IngressMTLS](#ingressmtls)
    22        - [IngressMTLS Merging Behavior](#ingressmtls-merging-behavior)
    23      - [EgressMTLS](#egressmtls)
    24        - [EgressMTLS Merging Behavior](#egressmtls-merging-behavior)
    25      - [OIDC](#oidc)
    26        - [Prerequisites](#prerequisites-1)
    27        - [Limitations](#limitations)
    28        - [OIDC Merging Behavior](#oidc-merging-behavior)
    29    - [Using Policy](#using-policy)
    30      - [WAF](#waf)
    31        - [WAF Merging Behavior](#waf-merging-behavior)
    32      - [Applying Policies](#applying-policies)
    33      - [Invalid Policies](#invalid-policies)
    34      - [Validation](#validation)
    35        - [Structural Validation](#structural-validation)
    36        - [Comprehensive Validation](#comprehensive-validation)
    37  
    38  ## Prerequisites
    39  
    40  Policies work together with [VirtualServer and VirtualServerRoute resources](/nginx-ingress-controller/configuration/virtualserver-and-virtualserverroute-resources/), which you need to create separately.
    41  
    42  ## Policy Specification
    43  
    44  Below is an example of a policy that allows access for clients from the subnet `10.0.0.0/8` and denies access for any other clients:
    45  ```yaml
    46  apiVersion: k8s.nginx.org/v1
    47  kind: Policy
    48  metadata:
    49    name: allow-localhost
    50  spec:
    51    accessControl:
    52      allow:
    53      - 10.0.0.0/8
    54  ```
    55  
    56  ```eval_rst
    57  .. list-table::
    58     :header-rows: 1
    59  
    60     * - Field
    61       - Description
    62       - Type
    63       - Required
    64     * - ``accessControl``
    65       - The access control policy based on the client IP address.
    66       - `accessControl <#accesscontrol>`_
    67       - No*
    68     * - ``rateLimit``
    69       - The rate limit policy controls the rate of processing requests per a defined key.
    70       - `rateLimit <#ratelimit>`_
    71       - No*
    72     * - ``jwt``
    73       - The JWT policy configures NGINX Plus to authenticate client requests using JSON Web Tokens.
    74       - `jwt <#jwt>`_
    75       - No*
    76     * - ``ingressMTLS``
    77       - The IngressMTLS policy configures client certificate verification.
    78       - `ingressMTLS <#ingressmtls>`_
    79       - No*
    80     * - ``egressMTLS``
    81       - The EgressMTLS policy configures upstreams authentication and certificate verification.
    82       - `egressMTLS <#egressmtls>`_
    83       - No*
    84     * - ``waf``
    85       - The WAF policy configures WAF and log configuration policies for `NGINX AppProtect </nginx-ingress-controller/app-protect/installation/>`_
    86       - `WAF <#waf>`_
    87       - No*
    88  ```
    89  
    90  \* A policy must include exactly one policy.
    91  
    92  ### AccessControl
    93  
    94  The access control policy configures NGINX to deny or allow requests from clients with the specified IP addresses/subnets.
    95  
    96  For example, the following policy allows access for clients from the subnet `10.0.0.0/8` and denies access for any other clients:
    97  ```yaml
    98  accessControl:
    99    allow:
   100    - 10.0.0.0/8
   101  ```
   102  
   103  In contrast, the policy below does the opposite: denies access for clients from `10.0.0.0/8` and allows access for any other clients:
   104  ```yaml
   105  accessControl:
   106    deny:
   107    - 10.0.0.0/8
   108  ```
   109  
   110  > Note: The feature is implemented using the NGINX [ngx_http_access_module](http://nginx.org/en/docs/http/ngx_http_access_module.html). The Ingress Controller access control policy supports either allow or deny rules, but not both (as the module does).
   111  
   112  ```eval_rst
   113  .. list-table::
   114     :header-rows: 1
   115  
   116     * - Field
   117       - Description
   118       - Type
   119       - Required
   120     * - ``allow``
   121       - Allows access for the specified networks or addresses. For example, ``192.168.1.1`` or ``10.1.1.0/16``.
   122       - ``[]string``
   123       - No*
   124     * - ``deny``
   125       - Denies access for the specified networks or addresses. For example, ``192.168.1.1`` or ``10.1.1.0/16``.
   126       - ``[]string``
   127       - No*
   128  ```
   129  \* an accessControl must include either `allow` or `deny`.
   130  
   131  #### AccessControl Merging Behavior
   132  
   133  A VirtualServer/VirtualServerRoute can reference multiple access control policies. For example, here we reference two policies, each with configured allow lists:
   134  ```yaml
   135  policies:
   136  - name: allow-policy-one
   137  - name: allow-policy-two
   138  ```
   139  When you reference more than one access control policy, the Ingress Controller will merge the contents into a single allow list or a single deny list.
   140  
   141  Referencing both allow and deny policies, as shown in the example below, is not supported. If both allow and deny lists are referenced, the Ingress Controller uses just the allow list policies.
   142  ```yaml
   143  policies:
   144  - name: deny-policy
   145  - name: allow-policy-one
   146  - name: allow-policy-two
   147  ```
   148  
   149  ### RateLimit
   150  
   151  > **Feature Status**: Rate-Limiting is available as a preview feature: it is suitable for experimenting and testing; however, it must be used with caution in production environments. Additionally, while the feature is in preview status, we might introduce some backward-incompatible changes to the resource specification in the next releases. The feature is disabled by default. To enable it, set the [enable-preview-policies](/nginx-ingress-controller/configuration/global-configuration/command-line-arguments/#cmdoption-enable-preview-policies) command-line argument of the Ingress Controller.
   152  
   153  The rate limit policy configures NGINX to limit the processing rate of requests.
   154  
   155  For example, the following policy will limit all subsequent requests coming from a single IP address once a rate of 10 requests per second is exceeded:
   156  ```yaml
   157  rateLimit:
   158    rate: 10r/s
   159    zoneSize: 10M
   160    key: ${binary_remote_addr}
   161  ```
   162  
   163  > Note: The feature is implemented using the NGINX [ngx_http_limit_req_module](https://nginx.org/en/docs/http/ngx_http_limit_req_module.html).
   164  
   165  ```eval_rst
   166  .. list-table::
   167     :header-rows: 1
   168  
   169     * - Field
   170       - Description
   171       - Type
   172       - Required
   173     * - ``rate``
   174       - The rate of requests permitted. The rate is specified in requests per second (r/s) or requests per minute (r/m).
   175       - ``string``
   176       - Yes
   177     * - ``key``
   178       - The key to which the rate limit is applied. Can contain text, variables, or a combination of them. Variables must be surrounded by ``${}``. For example: ``${binary_remote_addr}``. Accepted variables are ``$binary_remote_addr``, ``$request_uri``, ``$url``, ``$http_``, ``$args``, ``$arg_``, ``$cookie_``.
   179       - ``string``
   180       - Yes
   181     * - ``zoneSize``
   182       - Size of the shared memory zone. Only positive values are allowed. Allowed suffixes are ``k`` or ``m``, if none are present ``k`` is assumed.
   183       - ``string``
   184       - Yes
   185     * - ``delay``
   186       - The delay parameter specifies a limit at which excessive requests become delayed. If not set all excessive requests are delayed.
   187       - ``int``
   188       - No*
   189     * - ``noDelay``
   190       - Disables the delaying of excessive requests while requests are being limited. Overrides ``delay`` if both are set.
   191       - ``bool``
   192       - No*
   193     * - ``burst``
   194       - Excessive requests are delayed until their number exceeds the ``burst`` size, in which case the request is terminated with an error.
   195       - ``int``
   196       - No*
   197     * - ``dryRun``
   198       - Enables the dry run mode. In this mode, the rate limit is not actually applied, but the the number of excessive requests is accounted as usual in the shared memory zone.
   199       - ``bool``
   200       - No*
   201     * - ``logLevel``
   202       - Sets the desired logging level for cases when the server refuses to process requests due to rate exceeding, or delays request processing. Allowed values are ``info``, ``notice``, ``warn`` or ``error``. Default is ``error``.
   203       - ``string``
   204       - No*
   205     * - ``rejectCode``
   206       - Sets the status code to return in response to rejected requests. Must fall into the range ``400..599``. Default is ``503``.
   207       - ``string``
   208       - No*
   209  ```
   210  
   211  > For each policy referenced in a VirtualServer and/or its VirtualServerRoutes, the Ingress Controller will generate a single rate limiting zone defined by the [`limit_req_zone`](http://nginx.org/en/docs/http/ngx_http_limit_req_module.html#limit_req_zone) directive. If two VirtualServer resources reference the same policy, the Ingress Controller will generate two different rate limiting zones, one zone per VirtualServer.
   212  
   213  #### RateLimit Merging Behavior
   214  A VirtualServer/VirtualServerRoute can reference multiple rate limit policies. For example, here we reference two policies:
   215  ```yaml
   216  policies:
   217  - name: rate-limit-policy-one
   218  - name: rate-limit-policy-two
   219  ```
   220  
   221  When you reference more than one rate limit policy, the Ingress Controller will configure NGINX to use all referenced rate limits. When you define multiple policies, each additional policy inherits the `dryRun`, `logLevel`, and `rejectCode` parameters from the first policy referenced (`rate-limit-policy-one`, in the example above).
   222  
   223  ### JWT
   224  
   225  > **Feature Status**: JWT is available as a preview feature: it is suitable for experimenting and testing; however, it must be used with caution in production environments. Additionally, while the feature is in preview status, we might introduce some backward-incompatible changes to the resource specification in the next releases. The feature is disabled by default. To enable it, set the [enable-preview-policies](/nginx-ingress-controller/configuration/global-configuration/command-line-arguments/#cmdoption-enable-preview-policies) command-line argument of the Ingress Controller.
   226  
   227  > Note: This feature is only available in NGINX Plus.
   228  
   229  The JWT policy configures NGINX Plus to authenticate client requests using JSON Web Tokens.
   230  
   231  For example, the following policy will reject all requests that do not include a valid JWT in the HTTP header `token`:
   232  ```yaml
   233  jwt:
   234    secret: jwk-secret
   235    realm: "My API"
   236    token: $http_token
   237  ```
   238  
   239  You can pass the JWT claims and JOSE headers to the upstream servers. For example:
   240  ```yaml
   241  action:
   242    proxy:
   243      upstream: webapp
   244      requestHeaders:
   245        set:
   246        - name: user
   247          value: ${jwt_claim_user}
   248        - name: alg
   249          value: ${jwt_header_alg}
   250  ```
   251  We use the `requestHeaders` of the [Action.Proxy](/nginx-ingress-controller/configuration/virtualserver-and-virtualserverroute-resources/#action-proxy) to set the values of two headers that NGINX will pass to the upstream servers.
   252  
   253  The value of the `${jwt_claim_user}` variable is the `user` claim of a JWT. For other claims, use `${jwt_claim_name}`, where `name` is the name of the claim. Note that nested claims and claims that include a period (`.`) are not supported. Similarly, use `${jwt_header_name}` where `name` is the name of a header. In our example, we use the `alg` header.
   254  
   255  
   256  > Note: The feature is implemented using the NGINX Plus [ngx_http_auth_jwt_module](https://nginx.org/en/docs/http/ngx_http_auth_jwt_module.html).
   257  
   258  ```eval_rst
   259  .. list-table::
   260     :header-rows: 1
   261  
   262     * - Field
   263       - Description
   264       - Type
   265       - Required
   266     * - ``secret``
   267       - The name of the Kubernetes secret that stores the JWK. It must be in the same namespace as the Policy resource. The secret must be of the type ``nginx.org/jwk``, and the JWK must be stored in the secret under the key ``jwk``, otherwise the secret will be rejected as invalid.
   268       - ``string``
   269       - Yes
   270     * - ``realm``
   271       - The realm of the JWT.
   272       - ``string``
   273       - Yes
   274     * - ``token``
   275       - The token specifies a variable that contains the JSON Web Token. By default the JWT is passed in the ``Authorization`` header as a Bearer Token. JWT may be also passed as a cookie or a part of a query string, for example: ``$cookie_auth_token``. Accepted variables are ``$http_``, ``$arg_``, ``$cookie_``.
   276       - ``string``
   277       - No
   278  ```
   279  
   280  #### JWT Merging Behavior
   281  
   282  A VirtualServer/VirtualServerRoute can reference multiple JWT policies. However, only one can be applied. Every subsequent reference will be ignored. For example, here we reference two policies:
   283  ```yaml
   284  policies:
   285  - name: jwt-policy-one
   286  - name: jwt-policy-two
   287  ```
   288  In this example the Ingress Controller will use the configuration from the first policy reference `jwt-policy-one`, and ignores `jwt-policy-two`.
   289  
   290  ### IngressMTLS
   291  
   292  > **Feature Status**: IngressMTLS is available as a preview feature: it is suitable for experimenting and testing; however, it must be used with caution in production environments. Additionally, while the feature is in preview status, we might introduce some backward-incompatible changes to the resource specification in the next releases. The feature is disabled by default. To enable it, set the [enable-preview-policies](/nginx-ingress-controller/configuration/global-configuration/command-line-arguments/#cmdoption-enable-preview-policies) command-line argument of the Ingress Controller.
   293  
   294  The IngressMTLS policy configures client certificate verification.
   295  
   296  For example, the following policy will verify a client certificate using the CA certificate specified in the `ingress-mtls-secret`:
   297  ```yaml
   298  ingressMTLS:
   299    clientCertSecret: ingress-mtls-secret
   300    verifyClient: "on"
   301    verifyDepth: 1
   302  ```
   303  
   304  A VirtualServer that references an IngressMTLS policy must:
   305  * Enable [TLS termination](/nginx-ingress-controller/configuration/virtualserver-and-virtualserverroute-resources/#virtualserver-tls).
   306  * Reference the policy in the VirtualServer [`spec`](/nginx-ingress-controller/configuration/virtualserver-and-virtualserverroute-resources/#virtualserver-specification). It is not allowed to reference an IngressMTLS policy in a [`route `](/nginx-ingress-controller/configuration/virtualserver-and-virtualserverroute-resources/#virtualserver-route) or in a VirtualServerRoute [`subroute`](/nginx-ingress-controller/configuration/virtualserver-and-virtualserverroute-resources/#virtualserverroute-subroute).
   307  
   308  If the conditions above are not met, NGINX will send the `500` status code to clients.
   309  
   310  You can pass the client certificate details, including the certificate, to the upstream servers. For example:
   311  ```yaml
   312  action:
   313    proxy:
   314      upstream: webapp
   315      requestHeaders:
   316        set:
   317        - name: client-cert-subj-dn
   318          value: ${ssl_client_s_dn} # subject DN
   319        - name: client-cert
   320          value: ${ssl_client_escaped_cert} # client certificate in the PEM format (urlencoded)
   321  ```
   322  We use the `requestHeaders` of the [Action.Proxy](/nginx-ingress-controller/configuration/virtualserver-and-virtualserverroute-resources/#action-proxy) to set the values of the two headers that NGINX will pass to the upstream servers. See the [list of embedded variables](https://nginx.org/en/docs/http/ngx_http_ssl_module.html#variables) that are supported by the `ngx_http_ssl_module`, which you can use to pass the client certificate details.
   323  
   324  > Note: The feature is implemented using the NGINX [ngx_http_ssl_module](https://nginx.org/en/docs/http/ngx_http_ssl_module.html).
   325  
   326  ```eval_rst
   327  .. list-table::
   328     :header-rows: 1
   329  
   330     * - Field
   331       - Description
   332       - Type
   333       - Required
   334     * - ``clientCertSecret``
   335       - The name of the Kubernetes secret that stores the CA certificate. It must be in the same namespace as the Policy resource. The secret must be of the type ``nginx.org/ca``, and the certificate must be stored in the secret under the key ``ca.crt``, otherwise the secret will be rejected as invalid.
   336       - ``string``
   337       - Yes
   338     * - ``verifyClient``
   339       - Verification for the client. Possible values are ``"on"``, ``"off"``, ``"optional"``, ``"optional_no_ca"``. The default is ``"on"``.
   340       - ``string``
   341       - No
   342     * - ``verifyDepth``
   343       - Sets the verification depth in the client certificates chain. The default is ``1``.
   344       - ``int``
   345       - No
   346  ```
   347  
   348  #### IngressMTLS Merging Behavior
   349  
   350  A VirtualServer can reference only a single IngressMTLS policy. Every subsequent reference will be ignored. For example, here we reference two policies:
   351  ```yaml
   352  policies:
   353  - name: ingress-mtls-policy-one
   354  - name: ingress-mtls-policy-two
   355  ```
   356  In this example the Ingress Controller will use the configuration from the first policy reference `ingress-mtls-policy-one`, and ignores `ingress-mtls-policy-two`.
   357  
   358  ### EgressMTLS
   359  
   360  > **Feature Status**: EgressMTLS is available as a preview feature: it is suitable for experimenting and testing; however, it must be used with caution in production environments. Additionally, while the feature is in preview status, we might introduce some backward-incompatible changes to the resource specification in the next releases. The feature is disabled by default. To enable it, set the [enable-preview-policies](/nginx-ingress-controller/configuration/global-configuration/command-line-arguments/#cmdoption-enable-preview-policies) command-line argument of the Ingress Controller.
   361  
   362  The EgressMTLS policy configures upstreams authentication and certificate verification.
   363  
   364  For example, the following policy will use `egress-mtls-secret` to authenticate with the upstream application and `egress-trusted-ca-secret` to verify the certificate of the application:
   365  ```yaml
   366  egressMTLS:
   367    tlsSecret: egress-mtls-secret
   368    trustedCertSecret: egress-trusted-ca-secret
   369    verifyServer: on
   370    verifyDepth: 2
   371  ```
   372  
   373  > Note: The feature is implemented using the NGINX [ngx_http_proxy_module](https://nginx.org/en/docs/http/ngx_http_proxy_module.html).
   374  
   375  ```eval_rst
   376  .. list-table::
   377     :header-rows: 1
   378  
   379     * - Field
   380       - Description
   381       - Type
   382       - Required
   383     * - ``tlsSecret``
   384       - The name of the Kubernetes secret that stores the TLS certificate and key. It must be in the same namespace as the Policy resource. The secret must be of the type ``kubernetes.io/tls``, the certificate must be stored in the secret under the key ``tls.crt``, and the key must be stored under the key ``tls.key``, otherwise the secret will be rejected as invalid.
   385       - ``string``
   386       - No
   387     * - ``trustedCertSecret``
   388       - The name of the Kubernetes secret that stores the CA certificate. It must be in the same namespace as the Policy resource. The secret must be of the type ``nginx.org/ca``, and the certificate must be stored in the secret under the key ``ca.crt``, otherwise the secret will be rejected as invalid.
   389       - ``string``
   390       - No
   391     * - ``verifyServer``
   392       - Enables verification of the upstream HTTPS server certificate.
   393       - ``bool``
   394       - No
   395     * - ``verifyDepth``
   396       - Sets the verification depth in the proxied HTTPS server certificates chain. The default is ``1``.
   397       - ``int``
   398       - No
   399     * - ``sessionReuse``
   400       - Enables reuse of SSL sessions to the upstreams. The default is ``true``.
   401       - ``bool``
   402       - No
   403     * - ``serverName``
   404       - Enables passing of the server name through ``Server Name Indication`` extension.
   405       - ``bool``
   406       - No
   407     * - ``sslName``
   408       - Allows overriding the server name used to verify the certificate of the upstream HTTPS server.
   409       - ``string``
   410       - No
   411     * - ``ciphers``
   412       - Specifies the enabled ciphers for requests to an upstream HTTPS server. The default is ``DEFAULT``.
   413       - ``string``
   414       - No
   415     * - ``protocols``
   416       - Specifies the protocols for requests to an upstream HTTPS server. The default is ``TLSv1 TLSv1.1 TLSv1.2``.
   417       - ``string``
   418       - No
   419  ```
   420  > Note: the value of ``ciphers`` and ``protocols`` is not validated by the Ingress Controller. As a result, NGINX can fail to reload the configuration. To ensure that the configuration for a VirtualServer/VirtualServerRoute that references the policy was successfully applied, check its [status](/nginx-ingress-controller/configuration/global-configuration/reporting-resources-status/#virtualserver-and-virtualserverroute-resources). The validation will be added in the future releases.
   421  
   422  #### EgressMTLS Merging Behavior
   423  
   424  A VirtualServer/VirtualServerRoute can reference multiple EgressMTLS policies. However, only one can be applied. Every subsequent reference will be ignored. For example, here we reference two policies:
   425  ```yaml
   426  policies:
   427  - name: egress-mtls-policy-one
   428  - name: egress-mtls-policy-two
   429  ```
   430  In this example the Ingress Controller will use the configuration from the first policy reference `egress-mtls-policy-one`, and ignores `egress-mtls-policy-two`.
   431  
   432  ### OIDC
   433  
   434  > **Feature Status**: OIDC is available as a preview feature: it is suitable for experimenting and testing; however, it must be used with caution in production environments. Additionally, while the feature is in preview status, we might introduce some backward-incompatible changes to the resource specification in the next releases. The feature is disabled by default. To enable it, set the [enable-preview-policies](/nginx-ingress-controller/configuration/global-configuration/command-line-arguments/#cmdoption-enable-preview-policies) command-line argument of the Ingress Controller.
   435  
   436  The OIDC policy configures NGINX Plus as a relying party for OpenID Connect authentication.
   437  
   438  For example, the following policy will use the client ID `nginx-plus` and the client secret `oidc-secret` to authenticate with the OpenID Connect provider `https://idp.example.com`:
   439  ```yaml
   440  spec:
   441    oidc:
   442      clientID: nginx-plus
   443      clientSecret: oidc-secret
   444      authEndpoint: https://idp.example.com/openid-connect/auth
   445      tokenEndpoint: https://idp.example.com/openid-connect/token
   446      jwksURI: https://idp.example.com/openid-connect/certs
   447  ```
   448  
   449  NGINX Plus will pass the ID of an authenticated user to the backend in the HTTP header `username`.
   450  
   451  > Note: The feature is implemented using the [reference implementation](https://github.com/nginxinc/nginx-openid-connect/) of NGINX Plus as a relying party for OpenID Connect authentication.
   452  
   453  #### Prerequisites
   454  
   455  For the OIDC feature to work, it is necessary to enable [zone synchronization](https://docs.nginx.com/nginx/admin-guide/high-availability/zone_sync/), otherwise NGINX Plus will fail to reload. Additionally, it is necessary to configure a resolver, so that NGINX Plus can resolve the IDP authorization endpoint. For an example of the necessary configuration see the documentation [here](https://github.com/nginxinc/kubernetes-ingress/blob/v1.12.5/examples-of-custom-resources/oidc#step-7---configure-nginx-plus-zone-synchronization-and-resolver).
   456  
   457  > **Note**: The configuration in the example doesn't enable TLS and the synchronization between the replica happens in clear text. This could lead to the exposure of tokens.
   458  
   459  #### Limitations
   460  
   461  The OIDC policy defines a few internal locations that can't be customized: `/_jwks_uri`, `/_token`, `/_refresh`, `/_id_token_validation`, `/logout`, `/_logout`. In addition, as explained below `/_codexch` is the default value for redirect URI, but can be customized. Specifying one of these locations as a route in the VirtualServer or  VirtualServerRoute will result in a collision and NGINX Plus will fail to reload.
   462  
   463  ```eval_rst
   464  .. list-table::
   465     :header-rows: 1
   466  
   467     * - Field
   468       - Description
   469       - Type
   470       - Required
   471     * - ``clientID``
   472       - The client ID provided by your OpenID Connect provider.
   473       - ``string``
   474       - Yes
   475     * - ``clientSecret``
   476       - The name of the Kubernetes secret that stores the client secret provided by your OpenID Connect provider. It must be in the same namespace as the Policy resource. The secret must be of the type ``nginx.org/oidc``, and the secret under the key ``client-secret``, otherwise the secret will be rejected as invalid.
   477       - ``string``
   478       - Yes
   479     * - ``authEndpoint``
   480       - URL for the authorization endpoint provided by your OpenID Connect provider.
   481       - ``string``
   482       - Yes
   483     * - ``tokenEndpoint``
   484       - URL for the token endpoint provided by your OpenID Connect provider.
   485       - ``string``
   486       - Yes
   487     * - ``jwksURI``
   488       - URL for the JSON Web Key Set (JWK) document provided by your OpenID Connect provider.
   489       - ``string``
   490       - Yes
   491     * - ``scope``
   492       - List of OpenID Connect scopes. Possible values are ``openid``, ``profile``, ``email``, ``address` and ``phone``. The scope ``openid`` always needs to be present and others can be added concatenating them with a ``+`` sign, for example ``openid+profile+email``. The default is ``openid``.
   493       - ``string``
   494       - No
   495     * - ``redirectURI``
   496       - Allows overriding the default redirect URI. The default is ``/_codexch``.
   497       - ``string``
   498       - No
   499  ```
   500  
   501  > **Note**: Only one OIDC policy can be referenced in a VirtualServer and its VirtualServerRoutes. However, the same policy can still be applied to different routes in the VirtualServer and VirtualServerRoutes.
   502  
   503  #### OIDC Merging Behavior
   504  
   505  A VirtualServer/VirtualServerRoute can reference only a single OIDC policy. Every subsequent reference will be ignored. For example, here we reference two policies:
   506  ```yaml
   507  policies:
   508  - name: oidc-policy-one
   509  - name: oidc-policy-two
   510  ```
   511  In this example the Ingress Controller will use the configuration from the first policy reference `oidc-policy-one`, and ignores `oidc-policy-two`.
   512  
   513  ## Using Policy
   514  
   515  You can use the usual `kubectl` commands to work with Policy resources, just as with built-in Kubernetes resources.
   516  
   517  For example, the following command creates a Policy resource defined in `access-control-policy-allow.yaml` with the name `webapp-policy`:
   518  ```
   519  $ kubectl apply -f access-control-policy-allow.yaml
   520  policy.k8s.nginx.org/webapp-policy configured
   521  ```
   522  
   523  You can get the resource by running:
   524  ```
   525  $ kubectl get policy webapp-policy
   526  NAME            AGE
   527  webapp-policy   27m
   528  ```
   529  
   530  For `kubectl get` and similar commands, you can also use the short name `pol` instead of `policy`.
   531  
   532  ### WAF
   533  
   534  > **Feature Status**: WAF is available as a preview feature: it is suitable for experimenting and testing; however, it must be used with caution in production environments. Additionally, while the feature is in preview status, we might introduce some backward-incompatible changes to the resource specification in the next releases. The feature is disabled by default. To enable it, set the [enable-preview-policies](/nginx-ingress-controller/configuration/global-configuration/command-line-arguments/#cmdoption-enable-preview-policies) command-line argument of the Ingress Controller.
   535  
   536  > Note: This feature is only available in NGINX Plus with AppProtect.
   537  
   538  The WAF policy configures NGINX Plus to secure client requests using App Protect policies.
   539  
   540  For example, the following policy will enable the referenced APPolicy and APLogConf with the configured log destination:
   541  ```yaml
   542  waf:
   543    enable: true
   544    apPolicy: "default/dataguard-alarm"
   545    securityLog:
   546      enable: true
   547      apLogConf: "default/logconf"
   548      logDest: "syslog:server=127.0.0.1:514"
   549  ```
   550  
   551  > Note: The feature is implemented using the NGINX Plus [NGINX App Protect Module](https://docs.nginx.com/nginx-app-protect/configuration/).
   552  
   553  ```eval_rst
   554  .. list-table::
   555     :header-rows: 1
   556  
   557     * - Field
   558       - Description
   559       - Type
   560       - Required
   561     * - ``enable``
   562       - Enables NGINX App Protect.
   563       - ``bool``
   564       - Yes
   565     * - ``apPolicy``
   566       - The `App Protect policy </nginx-ingress-controller/app-protect/configuration/#app-protect-policies/>`_ of the WAF. Accepts an optional namespace.
   567       - ``string``
   568       - No
   569     * - ``securityLog.enable``
   570       -  Enables security log.
   571       - ``bool``
   572       - No
   573     * - ``securityLog.apLogConf``
   574       -  The `App Protect log conf </nginx-ingress-controller/app-protect/configuration/#app-protect-logs>`_ resource. Accepts an optional namespace.
   575       - ``string``
   576       - No
   577     * - ``securityLog.logDest``
   578       -  The log destination for the security log. Accepted variables are ``syslog:server=<ip-address | localhost>:<port>``, ``stderr``, ``<absolute path to file>``. Default is ``"syslog:server=127.0.0.1:514"``.
   579       - ``string``
   580       - No
   581  ```
   582  
   583  #### WAF Merging Behavior
   584  
   585  A VirtualServer/VirtualServerRoute can reference multiple WAF policies. However, only one can be applied. Every subsequent reference will be ignored. For example, here we reference two policies:
   586  ```yaml
   587  policies:
   588  - name: waf-policy-one
   589  - name: waf-policy-two
   590  ```
   591  In this example the Ingress Controller will use the configuration from the first policy reference `waf-policy-one`, and ignores `waf-policy-two`.
   592  
   593  ### Applying Policies
   594  
   595  You can apply policies to both VirtualServer and VirtualServerRoute resources. For example:
   596    * VirtualServer:
   597      ```yaml
   598      apiVersion: k8s.nginx.org/v1
   599      kind: VirtualServer
   600      metadata:
   601        name: cafe
   602        namespace: cafe
   603      spec:
   604        host: cafe.example.com
   605        tls:
   606          secret: cafe-secret
   607        policies: # spec policies
   608        - policy1
   609        upstreams:
   610        - name: coffee
   611          service: coffee-svc
   612          port: 80
   613        routes:
   614        - path: /tea
   615          policies: # route policies
   616          - name: policy2
   617            namespace: cafe
   618          route: tea/tea
   619        - path: /coffee
   620          policies: # route policies
   621          - name: policy3
   622            namespace: cafe
   623          action:
   624            pass: coffee
   625        ```
   626  
   627        For VirtualServer, you can apply a policy:
   628        - to all routes (spec policies)
   629        - to a specific route (route policies)
   630  
   631        Route policies of the *same type* override spec policies. In the example above, if the type of the policies `policy-1` and `policy-3` is `accessControl`, then for requests to `cafe.example.com/coffee`, NGINX will apply `policy-3`.
   632  
   633        The overriding is enforced by NGINX: the spec policies are implemented in the `server` context of the config, and the route policies are implemented in the `location` context. As a result, the route policies of the same type win.
   634    * VirtualServerRoute, which is referenced by the VirtualServer above:
   635      ```yaml
   636      apiVersion: k8s.nginx.org/v1
   637      kind: VirtualServerRoute
   638      metadata:
   639        name: tea
   640        namespace: tea
   641      spec:
   642        host: cafe.example.com
   643        upstreams:
   644        - name: tea
   645          service: tea-svc
   646          port: 80
   647        subroutes: # subroute policies
   648        - path: /tea
   649          policies:
   650          - name: policy4
   651            namespace: tea
   652          action:
   653            pass: tea
   654      ```
   655  
   656      For VirtualServerRoute, you can apply a policy to a subroute (subroute policies).
   657  
   658      Subroute policies of the same type override spec policies. In the example above, if the type of the policies `policy-1` (in the VirtualServer) and `policy-4` is `accessControl`, then for requests to `cafe.example.com/tea`, NGINX will apply `policy-4`. As with the VirtualServer, the overriding is enforced by NGINX.
   659  
   660      Subroute policies always override route policies no matter the types. For example, the policy `policy-2` in the VirtualServer route will be ignored for the subroute `/tea`, because the subroute has its own policies (in our case, only one policy `policy4`). If the subroute didn't have any policies, then the `policy-2` would be applied. This overriding is enforced by the Ingress Controller -- the `location` context for the subroute will either have route policies or subroute policies, but not both.
   661  
   662  ### Invalid Policies
   663  
   664  NGINX will treat a policy as invalid if one of the following conditions is met:
   665  * The policy doesn't pass the [comprehensive validation](#comprehensive-validation).
   666  * The policy isn't present in the cluster.
   667  * The policy doesn't meet its type-specific requirements. For example, an `ingressMTLS` policy requires TLS termination enabled in the VirtualServer.
   668  
   669  
   670  For an invalid policy, NGINX returns the 500 status code for client requests with the following rules:
   671  * If a policy is referenced in a VirtualServer `route` or a VirtualServerRoute `subroute`, then NGINX will return the 500 status code for requests for the URIs of that route/subroute.
   672  * If a policy is referenced in the VirtualServer `spec`, then NGINX will return the 500 status code for requests for all URIs of that VirtualServer.
   673  
   674  If a policy is invalid, the VirtualServer or VirtualServerRoute will have the [status](/nginx-ingress-controller/configuration/global-configuration/reporting-resources-status#virtualserver-and-virtualserverroute-resources) with the state `Warning` and the message explaining why the policy wasn't considered invalid.
   675  
   676  ### Validation
   677  
   678  Two types of validation are available for the Policy resource:
   679  * *Structural validation*, done by `kubectl` and the Kubernetes API server.
   680  * *Comprehensive validation*, done by the Ingress Controller.
   681  
   682  #### Structural Validation
   683  
   684  The custom resource definition for the Policy includes a structural OpenAPI schema, which describes the type of every field of the resource.
   685  
   686  If you try to create (or update) a resource that violates the structural schema -- for example, the resource uses a string value instead of an array of strings in the `allow` field -- `kubectl` and the Kubernetes API server will reject the resource.
   687  * Example of `kubectl` validation:
   688      ```
   689      $ kubectl apply -f access-control-policy-allow.yaml
   690      error: error validating "access-control-policy-allow.yaml": error validating data: ValidationError(Policy.spec.accessControl.allow): invalid type for org.nginx.k8s.v1.Policy.spec.accessControl.allow: got "string", expected "array"; if you choose to ignore these errors, turn validation off with --validate=false
   691      ```
   692  * Example of Kubernetes API server validation:
   693      ```
   694      $ kubectl apply -f access-control-policy-allow.yaml --validate=false
   695      The Policy "webapp-policy" is invalid: spec.accessControl.allow: Invalid value: "string": spec.accessControl.allow in body must be of type array: "string"
   696      ```
   697  
   698  If a resource passes structural validation, then the Ingress Controller's comprehensive validation runs.
   699  
   700  #### Comprehensive Validation
   701  
   702  The Ingress Controller validates the fields of a Policy resource. If a resource is invalid, the Ingress Controller will reject it. The resource will continue to exist in the cluster, but the Ingress Controller will ignore it.
   703  
   704  You can use `kubectl` to check whether or not the Ingress Controller successfully applied a Policy configuration. For our example `webapp-policy` Policy, we can run:
   705  ```
   706  $ kubectl describe pol webapp-policy
   707  . . .
   708  Events:
   709    Type    Reason          Age   From                      Message
   710    ----    ------          ----  ----                      -------
   711    Normal  AddedOrUpdated  11s   nginx-ingress-controller  Policy default/webapp-policy was added or updated
   712  ```
   713  Note how the events section includes a Normal event with the AddedOrUpdated reason that informs us that the configuration was successfully applied.
   714  
   715  If you create an invalid resource, the Ingress Controller will reject it and emit a Rejected event. For example, if you create a Policy `webapp-policy` with an invalid IP `10.0.0.` in the `allow` field, you will get:
   716  ```
   717  $ kubectl describe policy webapp-policy
   718  . . .
   719  Events:
   720    Type     Reason    Age   From                      Message
   721    ----     ------    ----  ----                      -------
   722    Warning  Rejected  7s    nginx-ingress-controller  Policy default/webapp-policy is invalid and was rejected: spec.accessControl.allow[0]: Invalid value: "10.0.0.": must be a CIDR or IP
   723  ```
   724  Note how the events section includes a Warning event with the Rejected reason.
   725  
   726  Additionally, this information is also available in the `status` field of the Policy resource. Note the Status section of the Policy:
   727  
   728  ```
   729  $ kubectl describe pol webapp-policy
   730  . . .
   731  Status:
   732    Message:  Policy default/webapp-policy is invalid and was rejected: spec.accessControl.allow[0]: Invalid value: "10.0.0.": must be a CIDR or IP
   733    Reason:   Rejected
   734    State:    Invalid
   735  ```
   736  
   737  **Note**: If you make an existing resource invalid, the Ingress Controller will reject it.