Policy#
The Policy resource allows you to configure features such as access control and rate limiting; these can be added to your VirtualServer and VirtualServerRoute resources.
It is implemented as a custom resource.
This is the reference documentation for the Policy resource.
Prerequisites#
Policies work in conjunction with VirtualServer and VirtualServerRoute resources, which must be created separately.
Policy Specification#
Below is an example of a policy that allows access to clients from the subnet 10.0.0.0/8
and denies access to any others:
apiVersion: k8s.angie.software/v1
kind: Policy
metadata:
name: allow-localhost
spec:
accessControl:
allow:
- 10.0.0.0/8
Field |
Description |
Type |
Required |
---|---|---|---|
|
Access control policy based on the client's IP address. |
No |
|
|
Specifies which instance of ANIC should handle the Policy resource. |
|
No |
|
Rate limiting policy controls the rate of request processing based on a specified key. |
No |
|
|
Basic authentication policy configures Angie to authenticate client requests using HTTP basic authentication credentials. |
No |
|
|
IngressMTLS policy configures client certificate verification. |
No |
|
|
EgressMTLS policy configures authentication and certificate verification for upstream. |
No |
|
|
OIDC policy configures authentication via an OIDC provider. |
No |
|
|
JWT policy configures Angie to authenticate client requests using JSON Web Tokens. |
No |
Note
The policy must include exactly one value.
AccessControl#
The access control policy configures Angie to accept or reject requests from clients with specified IP addresses and subnets.
For example, the following policy allows access to clients from the subnet 10.0.0.0/8
and denies access to any others:
accessControl:
allow:
- 10.0.0.0/8
Conversely, the policy below does the opposite: it denies access to clients from 10.0.0.0/8
and allows access to any other clients:
accessControl:
deny:
- 10.0.0.0/8
Note
This feature is implemented using the Angie http_access module. The ANIC access control policy supports either allow or deny rules, but not both at the same time (unlike the module).
Field |
Description |
Type |
Required |
---|---|---|---|
|
Allows access for specified networks or addresses. For example, |
|
No |
|
Denies access for specified networks or addresses. For example, |
|
No |
AccessControl must include either allow
or deny
.
AccessControl Merge Behavior#
The VirtualServer or VirtualServerRoute resource can reference multiple access control policies. For example, here we reference two policies, each with a configured allow list:
policies:
- name: allow-policy-one
- name: allow-policy-two
When referencing multiple access control policies, ANIC will merge their contents into a single allow or deny list.
References to both allow and deny policies, as shown in the example below, are not supported. If both allow and deny lists are specified, ANIC will only use the allow list policies.
policies:
- name: deny-policy
- name: allow-policy-one
- name: allow-policy-two
RateLimit#
The rate limiting policy configures Angie to limit the rate of request processing.
For example, the following policy will limit all subsequent requests coming from a single IP address to a rate of 10 requests per second:
rateLimit:
rate: 10r/s
zoneSize: 10M
key: ${binary_remote_addr}
Note
This feature is implemented using the Angie http_limit_req_module.
Field |
Description |
Type |
Required |
---|---|---|---|
|
Allowed rate of requests. The rate is specified in requests per second (r/s) or requests per minute (r/m). |
|
Yes |
|
The key to which the rate limit applies. It can contain text, variables, or a combination of both. Variables must be enclosed in |
|
Yes |
|
Size of the shared memory zone. Only positive values are allowed. Allowed suffixes are |
|
Yes |
|
Specifies the threshold at which excess requests become delayed. If this parameter is not specified, all excess requests are delayed. |
|
No |
|
Disables the delay of excess requests when limiting the number of requests. It takes precedence over |
|
No |
|
Excess requests are delayed until their number exceeds the size of |
|
No |
|
Enables dry run mode. In this mode, rate limiting is not actually applied, but the number of excess requests is counted as usual in the shared memory zone. |
|
No |
|
Sets the desired log level for cases when the server refuses to process requests due to rate limits or delays request processing. Allowed values: |
|
No |
|
Specifies the status code returned in response to rejected requests. The value must fall within the range of |
|
No |
For each policy referenced by a VirtualServer or its VirtualServerRoute, ANIC will generate a single rate limiting zone defined by the http_limit_req directive. If two VirtualServer resources reference the same policy, ANIC will generate two separate rate limiting zones, one for each VirtualServer.
RateLimit Merge Behavior#
The VirtualServer or VirtualServerRoute resource can reference multiple rate limiting policies. For example, here we reference two policies:
policies:
- name: rate-limit-policy-one
- name: rate-limit-policy-two
When referencing multiple rate limiting policies, ANIC will configure Angie to use all specified rate limits. If multiple policies are defined, each additional policy inherits the parameters dryRun
, logLevel
, and rejectCode
from the first referenced policy (rate-limit-policy-one
in the example above).
BasicAuth#
Configures Angie to authenticate client requests using the basic HTTP authentication scheme.
For example, the following policy will reject all requests that do not contain a valid username and password combination in the HTTP Authentication
header:
basicAuth:
secret: htpasswd-secret
realm: "My API"
Note
This feature is implemented using the Angie http_auth_basic module.
Field |
Description |
Type |
Required |
---|---|---|---|
|
The name of the Kubernetes secret that contains the Htpasswd configuration. It must be in the same namespace as the Policy resource. The secret must be of type |
|
Yes |
|
The realm for basic authentication. |
|
No |
BasicAuth Merge Behavior#
The VirtualServer or VirtualServerRoute resource can reference multiple basic authentication policies. Only one of them will be applied. All subsequent references will be ignored. For example, here we reference two policies:
policies:
- name: basic-auth-policy-one
- name: basic-auth-policy-two
In this example, ANIC will use the configuration from the first reference to the policy "basic-auth-policy-one" and ignore "basic-auth-policy-two".
IngressMTLS#
The IngressMTLS policy configures client certificate verification.
For example, the following policy will verify the client certificate using the Certificate Authority certificate specified in ingress-mtls-secret
:
ingressMTLS:
clientCertSecret: ingress-mtls-secret
verifyClient: "on"
verifyDepth: 1
Below is an example of ingress-mtls-secret
of type angie.software/ca
:
kind: Secret
metadata:
name: ingress-mtls-secret
apiVersion: v1
type: angie.software/ca
data:
ca.crt: <base64encoded-certificate>
A VirtualServer resource that references the IngressMTLS policy must have the following settings:
TLS termination enabled.
A reference to the policy in the specification of the VirtualServer. It is not permitted to reference the IngressMTLS policy in a route or nested route of the VirtualServer.
If these conditions are violated, Angie will send a status code of 500
to clients.
You can pass client certificate information, including the certificate itself, to upstream servers. For example:
action:
proxy:
upstream: webapp
requestHeaders:
set:
- name: client-cert-subj-dn
value: ${ssl_client_s_dn} # subject DN
- name: client-cert
value: ${ssl_client_escaped_cert} # client certificate in PEM format (urlencoded)
We use the requestHeaders
parameter in Action.Proxy to set the values of two headers that Angie will pass to upstream servers. See the list of built-in variables supported by the http_ssl
module that you can use to pass client certificate information.
Note
This feature is implemented using the Angie http_ssl module.
Using a Certificate Revocation List#
The IngressMTLS policy supports configuring a CRL for the policy. This can be done in one of two ways.
Note
Only one of these configuration parameters can be used at a time.
-
Adding a
ca.crl
field to theangie.software/ca
secret type, which contains the certificate revocation list in base64 encoding. Example YAML:kind: Secret metadata: name: ingress-mtls-secret apiVersion: v1 type: angie.software/ca data: ca.crt: <base64encoded-certificate> ca.crl: <base64encoded-crl>
-
Adding a
crlFileName
field with the name of the CRL file in the IngressMTLS policy specification.Note
This configuration parameter should only be used when the CRL file is larger than 1 MB; otherwise, it is recommended to use the
angie.software/ca
secret type for managing the CRL.Example YAML:
apiVersion: k8s.angie.software/v1 kind: Policy metadata: name: ingress-mtls-policy spec: ingressMTLS: clientCertSecret: ingress-mtls-secret crlFileName: webapp.crl verifyClient: "on" verifyDepth: 1
Warning
When configuring the CRL using the ingressMTLS.crlFileName
field, additional context should be considered:
ANIC expects the CRL, in this case
webapp.crl
, to be located in the/etc/angie/secrets
directory. To deploy ANIC, a volume mount point will need to be added. Place your CRL in the/etc/angie/secrets
directory.When updating the contents of the CRL (for example, if a new certificate has been revoked), Angie needs to be reloaded to reflect the latest changes. Depending on your environment, this may require updating the name of the CRL file and applying this update to the
ingress-mtls.yaml
policy so that Angie receives the latest version of the CRL.
Refer to the Kubernetes documentation on volumes for the best implementation for your environment.
Field |
Description |
Type |
Required |
---|---|---|---|
|
The name of the Kubernetes secret that contains the certificate of the certificate authority. It must be in the same namespace as the Policy resource. The secret must be of type |
|
Yes |
|
Verification for the client. Allowed values: |
|
No |
|
Sets the depth of verification in the client certificate chain. The default value is |
|
No |
|
The name of the certificate revocation list file. ANIC will look for this file in the /etc/angie/secrets directory. |
|
No |
IngressMTLS Merge Behavior#
The VirtualServer resource can reference only one IngressMTLS policy. All subsequent references will be ignored. For example, here we reference two policies:
policies:
- name: ingress-mtls-policy-one
- name: ingress-mtls-policy-two
In this example, ANIC will use the configuration from the first reference to the policy ingress-mtls-policy-one
and ignore ingress-mtls-policy-two
.
EgressMTLS#
EgressMTLS configures authentication and certificate verification for upstreams.
For example, the following policy will use egress-mtls-secret
for authentication to the upstream application and egress-trusted-ca-secret
for verifying the application certificate:
egressMTLS:
tlsSecret: egress-mtls-secret
trustedCertSecret: egress-trusted-ca-secret
verifyServer: on
verifyDepth: 2
Note
This feature is implemented using the Angie http_proxy module.
Field |
Description |
Type |
Required |
---|---|---|---|
|
The name of the Kubernetes secret file that contains the TLS certificate and key. It must be in the same namespace as the Policy resource. The secret must be of type |
|
No |
|
The name of the Kubernetes secret that contains the certificate of the certificate authority. It must be in the same namespace as the Policy resource. The secret must be of type |
|
No |
|
Enables verification of the upstream HTTPS server certificate. |
|
No |
|
Sets the depth of verification in the certificate chain of the proxied HTTPS server. The default value is |
|
No |
|
Allows SSL sessions to be reused with upstreams. The default value is |
|
No |
|
Allows passing the server name via the |
|
No |
|
Allows overriding the server name used for verifying the upstream HTTPS server certificate. |
|
No |
|
Specifies the allowed ciphers for requests to the upstream HTTPS server. The default value is |
|
No |
|
Specifies the protocols for requests to the upstream HTTPS server. The default value is |
|
No |
EgressMTLS Merge Behavior#
The VirtualServer or VirtualServerRoute resource can reference multiple EgressMTLS policies. Only one of them will be applied. All subsequent references will be ignored. For example, here we reference two policies:
policies:
- name: egress-mtls-policy-one
- name: egress-mtls-policy-two
In this example, ANIC will use the configuration from the first reference to the policy egress-mtls-policy-one
and ignore egress-mtls-policy-two
.
OIDC#
OIDC (OpenID Connect) provides convenient user authentication through an external provider, using secure tokens to manage access in the system.
Note
This feature is disabled by default. To enable it, set the command-line argument enable-oidc=true
.
The OIDC policy configures ANIC as a client (relying party) for authentication via OpenID Connect:
policies:
- name: oidc-policy
For example, the following configuration uses clientID myclient
and clientSecret oidc-secret
to authenticate via the OpenID Connect provider https://idp.example.com
:
oidc:
clientID: myclient
clientSecret: oidc-secret
authEndpoint: https://idp.example.com/openid-connect/auth
jwksURI: https://idp.example.com/openid-connect/certs
tokenEndpoint: https://idp.example.com/openid-connect/token
scope: openid+profile+email
accessTokenEnable: true
Mandatory conditions:
In the VirtualServer specification, specify the mandatory variables
$jwt_claim_iat
,$jwt_claim_iss
,$jwt_claim_sub
,$jwt_claim_aud
in maps. These variables ensure token validation during OIDC authentication.-
Add a secret with the client key. The key must be Base64 encoded:
apiVersion: v1 kind: Secret metadata: name: oidc-secret type: angie.software/oidc data: client-secret: <client_secret>
Field |
Description |
Type |
Required |
---|---|---|---|
|
The client identifier provided by the OIDC provider. Identifies the application that is requesting authorization. |
|
Yes |
|
The name of the secret where the client key is stored. It must be in the same namespace as the Policy. |
|
Yes |
|
The URL of the authorization endpoint provided by the OIDC provider. This is the address to which requests for user authentication will be sent. |
|
Yes |
|
The URI where the OIDC provider provides certificates (JSON Web Key Set) for verifying the JWT tokens issued by the server (JSON Web Token). |
|
Yes |
|
The URL for obtaining authentication and refresh tokens from the OIDC provider. |
|
Yes |
|
A list of OIDC scopes to request from the provider. The default value is |
|
Yes |
|
Enables the use of Bearer tokens for authorizing access to protected resources on the proxied server. |
|
No |
Note
Only one OIDC policy can be referenced at a time in VirtualServer resources. However, one policy can be applied to different routes of VirtualServer resources.
OIDC Merge Behavior#
The VirtualServer resource can reference multiple OIDC policies. Only one of them will be applied. All subsequent references will be ignored. For example, here we reference two policies:
policies:
- name: oidc-policy-one
- name: oidc-policy-two
In this example, ANIC will use the configuration from the first reference to the policy oidc-policy-one
and ignore oidc-policy-two
.
JWT#
The JWT policy configures Angie to authenticate client requests using JSON Web Tokens.
policies:
- name: jwt-policy
Note
This feature is disabled by default. To enable it, set the command-line argument -enable-jwt=true
.
The following policy will reject all requests that do not contain a valid JWT in the HTTP token header:
jwt:
realm: MyProductAPI
secret: jwk-secret
token: $http_token
Mandatory conditions:
-
Add a secret with the client key. The key must be Base64 encoded:
apiVersion: v1 kind: Secret metadata: name: jwk-secret type: angie.software/jwk data: jwk: <client_secret>
Field |
Description |
Type |
Required |
---|---|---|---|
|
The realm that the client will see when requesting authentication, for example, a string describing the protected resource. |
|
Yes |
|
The name of the Kubernetes secret that stores the JSON Web Key (JWK) used to verify the signatures of JWT tokens. Angie will use the keys from this secret to validate the signatures of JWTs and verify their authenticity. The secret must be in the same namespace as the Policy. |
|
Yes |
|
Specifies where to extract the JWT from. For example, the variable |
|
No |
JWT Merge Behavior#
The VirtualServer resource can reference multiple JWT policies. Only one of them will be applied. All subsequent references will be ignored. For example, here we reference two policies:
policies:
- name: jwt-policy-one
- name: jwt-policy-two
In this example, ANIC will use the configuration from the first reference to the policy jwt-policy-one
and ignore jwt-policy-two
.
Applying Policies#
Policies can be applied to both VirtualServer and VirtualServerRoute resources. For example:
- VirtualServer:
apiVersion: k8s.angie.software/v1
kind: VirtualServer
metadata:
name: cafe
namespace: cafe
spec:
host: cafe.example.com
tls:
secret: cafe-secret
policies: # spec policies
- name: policy1
upstreams:
- name: coffee
service: coffee-svc
port: 80
routes:
- path: /tea
policies: # route policies
- name: policy2
namespace: cafe
route: tea/tea
- path: /coffee
policies: # route policies
- name: policy3
namespace: cafe
action:
pass: coffee
In the case of VirtualServer, a policy can be applied:
to all routes (spec policies)
-
to a specific route (route policies)
Route policies take precedence over specification policies of the same type. If in the example above the types of policies
policy-1
andpolicy-3
areAccessControl
, then for requests tocafe.example.com/coffee
, Angie will applypolicy-3
.Overriding is ensured by Angie: specification policies are implemented in the context of the
server
configuration, while route policies are implemented in the context oflocation
. As a result, route policies have priority within the same type. -
The VirtualServerRoute resource referenced by the above VirtualServer:
apiVersion: k8s.angie.software/v1 kind: VirtualServerRoute metadata: name: tea namespace: tea spec: host: cafe.example.com upstreams: - name: tea service: tea-svc port: 80 subroutes: # subroute policies - path: /tea policies: - name: policy4 namespace: tea action: pass: tea
In the VirtualServerRoute, a policy can be applied to a nested route (nested route policies).
Nested route policies take precedence over specification policies of the same type. In the example above, if the type of policies
policy-1
(in VirtualServer) andpolicy-4
isAccessControl
, then for requests tocafe.example.com/tea
, Angie will applypolicy-4
. As with VirtualServer, overriding is ensured by Angie.Nested route policies always take precedence over route policies regardless of type. For example, the policy
policy-2
in the VirtualServer route will be ignored on the nested route/tea
, as it has its own policies (in our case, onlypolicy4
). If the nested route had no policies, thenpolicy-2
would be applied. This overriding is performed by ANIC - the context of thelocation
for the nested route will contain either route policies or nested route policies, but not both together.
Invalid Policies#
Angie will consider a policy invalid if any of the following conditions are met:
The policy fails comprehensive validation.
The policy is not present in the cluster.
The policy does not meet the requirements for its specific type. For example, the
ingressMTLS policy
requires TLS termination to be enabled in the VirtualServer.
In the case of an invalid policy, Angie returns a status code of 500 for client requests with the following rules:
If a policy is referenced by a VirtualServer
route
or a VirtualServerRoutenested route
, Angie will return a status code of 500 for requests to the URI of that route.If a policy reference is specified in the VirtualServer
specification
, Angie will return a status code of 500 for requests to all URIs of that VirtualServer.
If a policy is invalid, the VirtualServer or VirtualServerRoute will have a status with a warning about the state and a message explaining why the policy was deemed invalid.
Validation#
There are two types of validation available for the Policy resource:
Structural validation using
kubectl
and the Kubernetes API server.Comprehensive validation using ANIC.
Structural Validation#
The custom resource definition for Policy includes a structural OpenAPI schema that describes the type of each field of the resource.
If you attempt to create (or update) a resource that violates the structural schema (for example, using a string value instead of an array of strings in the allow
field), then kubectl
and the Kubernetes API server will reject the resource.
-
Example of checking with
kubectl
:kubectl apply -f access-control-policy-allow.yaml error: error validating "access-control-policy-allow.yaml": error validating data: ValidationError(Policy.spec.accessControl.allow): invalid type for software.angie.k8s.v1.Policy.spec.accessControl.allow: got "string", expected "array"; if you choose to ignore these errors, turn validation off with --validate=false
-
Example of checking with the Kubernetes API server:
kubectl apply -f access-control-policy-allow.yaml --validate=false The Policy "webapp-policy" is invalid: spec.accessControl.allow: Invalid value: "string": spec.accessControl.allow in body must be of type array: "string"
If the resource passes structural validation, comprehensive validation by ANIC is performed.
Comprehensive Validation#
ANIC checks the fields of the Policy resource. If the resource is invalid, ANIC will reject it. The resource will remain in the cluster, but ANIC will ignore it.
You can use kubectl
to check whether ANIC successfully applied the Policy configuration. For the policy mypolicy
, we can run:
kubectl describe pol mypolicy
. . .
Events:
Type Reason Age From Message
-----
Normal AddedOrUpdated 11s angie-ingress-controller Policy default/mypolicy was added or updated
Note that the "Events" section includes a Normal event with the reason AddedOrUpdated, which informs us that the configuration was successfully applied.
If you create an invalid resource, ANIC will reject it and issue a Rejected event. For example, if you create a policy mypolicy
with an invalid IP address 10.0.0.
in the allow
field, you will get:
kubectl describe policy mypolicy
. . .
Events:
Type Reason Age From Message
-----
Warning Rejected 7s angie-ingress-controller Policy default/mypolicy is invalid and was rejected: spec.accessControl.allow[0]: Invalid value: "10.0.0.": must be a CIDR or IP
Note that the "Events" section includes a warning event indicating the reason for the rejection.
Additionally, this information is also available in the status
field of the Policy resource. Note the "Status" section of the policy:
kubectl describe pol mypolicy
. . .
Status:
Message: Policy default/mypolicy is invalid and was rejected: spec.accessControl.allow[0]: Invalid value: "10.0.0.": must be a CIDR or IP
Reason: Rejected
State: Invalid
Note
If you make an existing resource invalid, ANIC will reject it.