docs: add envoy docs (#3789)

Adds and adjusts documentation for Envoy.
pull/4113/head^2
James Elliott 2022-10-02 13:59:09 +11:00 committed by GitHub
parent c8fa19e6bd
commit 3822286c3b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 326 additions and 49 deletions

View File

@ -93,17 +93,11 @@ Docker or on top of [Kubernetes].
<img src="./docs/static/images/logos/nginx.png" height="50"/> <img src="./docs/static/images/logos/nginx.png" height="50"/>
<img src="./docs/static/images/logos/traefik.png" height="50"/> <img src="./docs/static/images/logos/traefik.png" height="50"/>
<img src="./docs/static/images/logos/caddy.png" height="50"/> <img src="./docs/static/images/logos/caddy.png" height="50"/>
<img src="./docs/static/images/logos/envoy.png" height="50"/>
<img src="./docs/static/images/logos/haproxy.png" height="50"/> <img src="./docs/static/images/logos/haproxy.png" height="50"/>
<img src="./docs/static/images/logos/kubernetes.png" height="50"/> <img src="./docs/static/images/logos/kubernetes.png" height="50"/>
</p> </p>
***Help Wanted:*** Assistance would be appreciated in getting Authelia working with
[Envoy](https://www.envoyproxy.io/).
<p align="center">
<img src="./docs/static/images/logos/envoy.png" height="50"/>
</p>
## Getting Started ## Getting Started
See the [Get Started Guide](https://www.authelia.com/integration/prologue/get-started/) or one of the curated examples See the [Get Started Guide](https://www.authelia.com/integration/prologue/get-started/) or one of the curated examples

View File

@ -0,0 +1,90 @@
---
title: "Istio"
description: "A guide to integrating Authelia with the Istio Kubernetes Ingress."
lead: "A guide to integrating Authelia with the Istio Kubernetes Ingress."
date: 2022-06-15T17:51:47+10:00
draft: false
images: []
menu:
integration:
parent: "kubernetes"
weight: 551
toc: true
---
Istio uses [Envoy](../proxies/envoy.md) as an Ingress. This means it has a relatively comprehensive integration option.
## Example
This example assumes that you have deployed an Authelia pod and you have configured it to be served on the URL
`https://auth.example.com` and there is a Kubernetes Service with the name `authelia` in the `default` namespace with
TCP port `80` configured to route to the Authelia pod's HTTP port and that your cluster is configured with the default
DNS domain name of `cluster.local`.
### Operator
This is an example IstioOperator manifest adjusted to authenticate with Authelia. This example only shows the necessary
portions of the resource that you add as well as context. You will need to adapt it to your needs.
```yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
meshConfig:
extensionProviders:
- name: 'authelia'
envoyExtAuthzHttp:
service: 'authelia.default.svc.cluster.local'
port: 80
pathPrefix: '/api/verify/'
includeRequestHeadersInCheck:
- accept
- cookie
- proxy-authorization
headersToUpstreamOnAllow:
- 'authorization'
- 'proxy-authorization'
- 'remote-*'
- 'authelia-*'
includeAdditionalHeadersInCheck:
X-Authelia-URL: 'https://auth.example.com/'
X-Forwarded-Method: '%REQ(:METHOD)%'
X-Forwarded-Proto: '%REQ(:SCHEME)%'
X-Forwarded-Host: '%REQ(:AUTHORITY)%'
X-Forwarded-URI: '%REQ(:PATH)%'
X-Forwarded-For: '%DOWNSTREAM_REMOTE_ADDRESS_WITHOUT_PORT%'
headersToDownstreamOnDeny:
- set-cookie
headersToDownstreamOnAllow:
- set-cookie
```
### Authorization Policy
The following [Authorization Policy] applies the above filter extension provider to the `nextcloud.example.com` domain:
```yaml
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: nextcloud
namespace: apps
spec:
action: CUSTOM
provider:
name: 'authelia'
rules:
- to:
- operation:
hosts:
- 'nextcloud.example.com'
```
## See Also
- Istio [External Authentication](https://istio.io/latest/docs/tasks/security/authorization/authz-custom/) Documentation
- Istio [Authorization Policy] Documentation
- Istio [IstioOperator Options](https://istio.io/latest/docs/reference/config/istio.operator.v1alpha1/) Documentation
- Istio [MeshConfig Extension Provider EnvoyExtAuthz HTTP Provider](https://istio.io/latest/docs/reference/config/istio.mesh.v1alpha1/#MeshConfig-ExtensionProvider-EnvoyExternalAuthorizationHttpProvider) Documentation
[Authorization Policy]: https://istio.io/latest/docs/reference/config/security/authorization-policy/

View File

@ -8,7 +8,7 @@ images: []
menu: menu:
integration: integration:
parent: "kubernetes" parent: "kubernetes"
weight: 551 weight: 552
toc: true toc: true
--- ---

View File

@ -151,6 +151,7 @@ example.com {
} }
``` ```
{{< /details >}} {{< /details >}}
### Advanced example ### Advanced example
The advanced example allows for more flexible customization, however the [basic example](#basic-examples) should be The advanced example allows for more flexible customization, however the [basic example](#basic-examples) should be

View File

@ -14,20 +14,13 @@ aliases:
- /i/envoy - /i/envoy
--- ---
[Envoy] is probably supported by __Authelia__. [Envoy] is supported by __Authelia__.
*__Important:__ When using these guides it's important to recognize that we cannot provide a guide for every possible *__Important:__ When using these guides it's important to recognize that we cannot provide a guide for every possible
method of deploying a proxy. These guides show a suggested setup only and you need to understand the proxy method of deploying a proxy. These guides show a suggested setup only and you need to understand the proxy
configuration and customize it to your needs. To-that-end we include links to the official proxy documentation configuration and customize it to your needs. To-that-end we include links to the official proxy documentation
throughout this documentation and in the [See Also](#see-also) section.* throughout this documentation and in the [See Also](#see-also) section.*
## UNDER CONSTRUCTION
It's currently not certain, but fairly likely that [Envoy] is supported by __Authelia__. We wish to add documentation
and thus if anyone has this working please let us know.
We will aim to perform documentation for this on our own but there is no current timeframe.
## Get Started ## Get Started
It's __*strongly recommended*__ that users setting up *Authelia* for the first time take a look at our It's __*strongly recommended*__ that users setting up *Authelia* for the first time take a look at our
@ -44,11 +37,210 @@ how you can configure multiple IP ranges. You should customize this example to f
You should only include the specific IP address ranges of the trusted proxies within your architecture and should not You should only include the specific IP address ranges of the trusted proxies within your architecture and should not
trust entire subnets unless that subnet only has trusted proxies and no other services.* trust entire subnets unless that subnet only has trusted proxies and no other services.*
## Potential ## Configuration
Below you will find commented examples of the following configuration:
* Authelia Portal
* Protected Endpoint (Nextcloud)
### Theoretical Example
Support for [Envoy] should be possible via [Envoy]'s Support for [Envoy] should be possible via [Envoy]'s
[external authorization](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authz/v3/ext_authz.proto.html#extensions-filters-http-ext-authz-v3-extauthz). [external authorization](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authz/v3/ext_authz.proto.html#extensions-filters-http-ext-authz-v3-extauthz).
{{< details "docker-compose.yaml" >}}
```yaml
---
version: "3.8"
networks:
net:
driver: bridge
services:
envoy:
container_name: envoy
image: envoyproxy/envoy:v1.23.0
restart: unless-stopped
networks:
net: {}
ports:
- '80:8080'
- '443:8443'
volumes:
- ${PWD}/data/envoy/envoy.yaml:/etc/envoy/envoy.yaml:ro
- ${PWD}/data/certificates:/certificates:ro
authelia:
container_name: authelia
image: authelia/authelia
restart: unless-stopped
networks:
net: {}
expose:
- 9091
volumes:
- ${PWD}/data/authelia/config:/config
environment:
TZ: "Australia/Melbourne"
nextcloud:
container_name: nextcloud
image: linuxserver/nextcloud
restart: unless-stopped
networks:
net: {}
expose:
- 443
volumes:
- ${PWD}/data/nextcloud/config:/config
- ${PWD}/data/nextcloud/data:/data
environment:
PUID: "1000"
PGID: "1000"
TZ: "Australia/Melbourne"
```
{{< /details >}}
{{< details "envoy.yaml" >}}
```yaml
static_resources:
listeners:
- name: listener_http
address:
socket_address:
address: 0.0.0.0
port_value: 8080
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
codec_type: auto
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: backend
domains: ["*"]
routes:
- match:
prefix: "/"
redirect:
https_redirect: true
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
- name: listener_https
address:
socket_address:
address: 0.0.0.0
port_value: 8443
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
use_remote_address: true
skip_xff_append: false
route_config:
name: local_route
virtual_hosts:
- name: whoami_service
domains: ["nextcloud.example.com"]
routes:
- match:
prefix: "/"
route:
cluster: nextcloud
- name: authelia_service
domains: ["auth.example.com"]
typed_per_filter_config:
envoy.filters.http.ext_authz:
"@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute
disabled: true
routes:
- match:
prefix: "/"
route:
cluster: authelia
http_filters:
- name: envoy.filters.http.ext_authz
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz
http_service:
path_prefix: '/api/verify/'
server_uri:
uri: authelia:9091
cluster: authelia
timeout: 0.25s
authorization_request:
allowed_headers:
patterns:
- exact: accept
- exact: cookie
- exact: proxy-authorization
headers_to_add:
- key: X-Authelia-URL
value: 'https://auth.example.com/'
- key: X-Forwarded-Method
value: '%REQ(:METHOD)%'
- key: X-Forwarded-Proto
value: '%REQ(:SCHEME)%'
- key: X-Forwarded-Host
value: '%REQ(:AUTHORITY)%'
- key: X-Forwarded-Uri
value: '%REQ(:PATH)%'
- key: X-Forwarded-For
value: '%DOWNSTREAM_REMOTE_ADDRESS_WITHOUT_PORT%'
authorization_response:
allowed_upstream_headers:
patterns:
- exact: authorization
- exact: proxy-authorization
- prefix: remote-
- prefix: authelia-
allowed_client_headers:
patterns:
- exact: set-cookie
allowed_client_headers_on_success:
patterns:
- exact: set-cookie
failure_mode_allow: false
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
clusters:
- name: nextcloud
connect_timeout: 0.25s
type: LOGICAL_DNS
dns_lookup_family: V4_ONLY
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: nextcloud
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: nextcloud
port_value: 80
- name: authelia
connect_timeout: 0.25s
type: LOGICAL_DNS
dns_lookup_family: V4_ONLY
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: authelia
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: authelia
port_value: 9091
```
{{< /details >}}
## See Also ## See Also
* [Envoy External Authorization Documentation](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authz/v3/ext_authz.proto.html#extensions-filters-http-ext-authz-v3-extauthz) * [Envoy External Authorization Documentation](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authz/v3/ext_authz.proto.html#extensions-filters-http-ext-authz-v3-extauthz)

View File

@ -15,19 +15,19 @@ aliases:
- /docs/home/supported-proxies.html - /docs/home/supported-proxies.html
--- ---
| Proxy | [Standard](#standard) | [Kubernetes](#kubernetes) | [XHR Redirect](#xhr-redirect) | [Request Method](#request-method) | | Proxy | [Standard](#standard) | [Kubernetes](#kubernetes) | [XHR Redirect](#xhr-redirect) | [Request Method](#request-method) |
|:---------------------:|:----------------------------------------------------------------:|:------------------------------------------------------------------------------------:|:------------------------------------:|:------------------------------------:| |:---------------------:|:----------------------------------------------------------------:|:------------------------------------------------------------------------------------:|:-----------------------------------------------------:|:-----------------------------------------------------:|
| [Traefik] | [<i class="icon-support-full"></i>](traefik.md) | [<i class="icon-support-full"></i>](../../integration/kubernetes/traefik-ingress.md) | <i class="icon-support-full"></i> | <i class="icon-support-full"></i> | | [Traefik] | [<i class="icon-support-full"></i>](traefik.md) | [<i class="icon-support-full"></i>](../../integration/kubernetes/traefik-ingress.md) | <i class="icon-support-full"></i> | <i class="icon-support-full"></i> |
| [NGINX] | [<i class="icon-support-full"></i>](nginx.md) | [<i class="icon-support-full"></i>](../../integration/kubernetes/nginx-ingress.md) | <i class="icon-support-none"></i> | <i class="icon-support-full"></i> | | [NGINX] | [<i class="icon-support-full"></i>](nginx.md) | [<i class="icon-support-full"></i>](../../integration/kubernetes/nginx-ingress.md) | <i class="icon-support-none" alt="Not Supported"></i> | <i class="icon-support-full"></i> |
| [NGINX Proxy Manager] | [<i class="icon-support-full"></i>](nginx-proxy-manager.md) | <i class="icon-support-unknown"></i> | <i class="icon-support-none"></i> | <i class="icon-support-full"></i> | | [NGINX Proxy Manager] | [<i class="icon-support-full"></i>](nginx-proxy-manager.md) | <i class="icon-support-unknown"></i> | <i class="icon-support-none" alt="Not Supported"></i> | <i class="icon-support-full"></i> |
| [SWAG] | [<i class="icon-support-full"></i>](swag.md) | <i class="icon-support-unknown"></i> | <i class="icon-support-none"></i> | <i class="icon-support-full"></i> | | [SWAG] | [<i class="icon-support-full"></i>](swag.md) | <i class="icon-support-unknown"></i> | <i class="icon-support-none" alt="Not Supported"></i> | <i class="icon-support-full"></i> |
| [HAProxy] | [<i class="icon-support-full"></i>](haproxy.md) | <i class="icon-support-unknown"></i> | <i class="icon-support-unknown"></i> | <i class="icon-support-full"></i> | | [HAProxy] | [<i class="icon-support-full"></i>](haproxy.md) | <i class="icon-support-unknown"></i> | <i class="icon-support-unknown"></i> | <i class="icon-support-full"></i> |
| [Caddy] | [<i class="icon-support-full"></i>](caddy.md) | <i class="icon-support-unknown"></i> | <i class="icon-support-full"></i> | <i class="icon-support-full"></i> | | [Caddy] | [<i class="icon-support-full"></i>](caddy.md) | <i class="icon-support-unknown"></i> | <i class="icon-support-full"></i> | <i class="icon-support-full"></i> |
| [Traefik] 1.x | [<i class="icon-support-full"></i>](traefikv1.md) | <i class="icon-support-unknown"></i> | <i class="icon-support-full"></i> | <i class="icon-support-full"></i> | | [Traefik] 1.x | [<i class="icon-support-full"></i>](traefikv1.md) | <i class="icon-support-unknown"></i> | <i class="icon-support-full"></i> | <i class="icon-support-full"></i> |
| [Envoy] | [<i class="icon-support-unknown"></i>](envoy.md) | <i class="icon-support-unknown"></i> | <i class="icon-support-unknown"></i> | <i class="icon-support-unknown"></i> | | [Envoy] | [<i class="icon-support-full"></i>](envoy.md) | [<i class="icon-support-full"></i>](../../integration/kubernetes/istio.md) | <i class="icon-support-unknown"></i> | <i class="icon-support-full"></i> |
| [Skipper] | [<i class="icon-support-full"></i>](skipper.md) | <i class="icon-support-unknown"></i> | <i class="icon-support-unknown"></i> | <i class="icon-support-unknown"></i> | | [Skipper] | [<i class="icon-support-full"></i>](skipper.md) | <i class="icon-support-unknown"></i> | <i class="icon-support-unknown"></i> | <i class="icon-support-unknown"></i> |
| [Apache] | [<i class="icon-support-none" alt="Not Supported"></i>](#apache) | <i class="icon-support-none"></i> | <i class="icon-support-none"></i> | <i class="icon-support-none"></i> | | [Apache] | [<i class="icon-support-none" alt="Not Supported"></i>](#apache) | <i class="icon-support-none" alt="Not Supported"></i> | <i class="icon-support-none" alt="Not Supported"></i> | <i class="icon-support-none" alt="Not Supported"></i> |
| [IIS] | [<i class="icon-support-none"></i>](#iis) | <i class="icon-support-none"></i> | <i class="icon-support-none"></i> | <i class="icon-support-none"></i> | | [IIS] | [<i class="icon-support-none" alt="Not Supported"></i>](#iis) | <i class="icon-support-none" alt="Not Supported"></i> | <i class="icon-support-none" alt="Not Supported"></i> | <i class="icon-support-none" alt="Not Supported"></i> |
Legend: Legend:
@ -87,8 +87,8 @@ available in [Kubernetes]. You would likely have to build your own [HAProxy] ima
### Envoy ### Envoy
[Envoy] is currently not documented, however a small pending feature will add complete support for [Envoy]. This is [Envoy] is currently only partially documented however it is technically supported via [Envoy]'s
possible via [Envoy]'s [external authorization](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authz/v3/ext_authz.proto.html#extensions-filters-http-ext-authz-v3-extauthz). [external authorization](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authz/v3/ext_authz.proto.html#extensions-filters-http-ext-authz-v3-extauthz).
### Caddy ### Caddy

View File

@ -14,28 +14,28 @@ toc: false
The following table is a support matrix for Authelia features and specific reverse proxies. The following table is a support matrix for Authelia features and specific reverse proxies.
| Proxy | Standard | Kubernetes | XHR Redirect | Request Method | | Proxy | [Standard](#standard) | [Kubernetes](#kubernetes) | [XHR Redirect](#xhr-redirect) | [Request Method](#request-method) |
|:---------------------:|:-------------------------------------------------------------------------------------:|:------------------------------------------------------------------------------------:|:------------------------------------:|:------------------------------------:| |:---------------------:|:-------------------------------------------------------------------------------------:|:------------------------------------------------------------------------------------:|:-----------------------------------------------------:|:-----------------------------------------------------:|
| [Traefik] | [<i class="icon-support-full"></i>](../../integration/proxies/traefik.md) | [<i class="icon-support-full"></i>](../../integration/kubernetes/traefik-ingress.md) | <i class="icon-support-full"></i> | <i class="icon-support-full"></i> | | [Traefik] | [<i class="icon-support-full"></i>](../../integration/proxies/traefik.md) | [<i class="icon-support-full"></i>](../../integration/kubernetes/traefik-ingress.md) | <i class="icon-support-full"></i> | <i class="icon-support-full"></i> |
| [NGINX] | [<i class="icon-support-full"></i>](../../integration/proxies/nginx.md) | [<i class="icon-support-full"></i>](../../integration/kubernetes/nginx-ingress.md) | <i class="icon-support-none"></i> | <i class="icon-support-full"></i> | | [NGINX] | [<i class="icon-support-full"></i>](../../integration/proxies/nginx.md) | [<i class="icon-support-full"></i>](../../integration/kubernetes/nginx-ingress.md) | <i class="icon-support-none" alt="Not Supported"></i> | <i class="icon-support-full"></i> |
| [NGINX Proxy Manager] | [<i class="icon-support-full"></i>](../../integration/proxies/nginx-proxy-manager.md) | <i class="icon-support-unknown"></i> | <i class="icon-support-none"></i> | <i class="icon-support-full"></i> | | [NGINX Proxy Manager] | [<i class="icon-support-full"></i>](../../integration/proxies/nginx-proxy-manager.md) | <i class="icon-support-unknown"></i> | <i class="icon-support-none" alt="Not Supported"></i> | <i class="icon-support-full"></i> |
| [SWAG] | [<i class="icon-support-full"></i>](../../integration/proxies/swag.md) | <i class="icon-support-unknown"></i> | <i class="icon-support-none"></i> | <i class="icon-support-full"></i> | | [SWAG] | [<i class="icon-support-full"></i>](../../integration/proxies/swag.md) | <i class="icon-support-unknown"></i> | <i class="icon-support-none" alt="Not Supported"></i> | <i class="icon-support-full"></i> |
| [HAProxy] | [<i class="icon-support-full"></i>](../../integration/proxies/haproxy.md) | <i class="icon-support-unknown"></i> | <i class="icon-support-unknown"></i> | <i class="icon-support-full"></i> | | [HAProxy] | [<i class="icon-support-full"></i>](../../integration/proxies/haproxy.md) | <i class="icon-support-unknown"></i> | <i class="icon-support-unknown"></i> | <i class="icon-support-full"></i> |
| [Caddy] | [<i class="icon-support-full"></i>](../../integration/proxies/caddy.md) | <i class="icon-support-unknown"></i> | <i class="icon-support-full"></i> | <i class="icon-support-full"></i> | | [Caddy] | [<i class="icon-support-full"></i>](../../integration/proxies/caddy.md) | <i class="icon-support-unknown"></i> | <i class="icon-support-full"></i> | <i class="icon-support-full"></i> |
| [Traefik] 1.x | [<i class="icon-support-full"></i>](../../integration/proxies/traefikv1.md) | <i class="icon-support-unknown"></i> | <i class="icon-support-full"></i> | <i class="icon-support-full"></i> | | [Traefik] 1.x | [<i class="icon-support-full"></i>](../../integration/proxies/traefikv1.md) | <i class="icon-support-unknown"></i> | <i class="icon-support-full"></i> | <i class="icon-support-full"></i> |
| [Envoy] | [<i class="icon-support-unknown"></i>](../../integration/proxies/envoy.md) | <i class="icon-support-unknown"></i> | <i class="icon-support-unknown"></i> | <i class="icon-support-unknown"></i> | | [Envoy] | [<i class="icon-support-full"></i>](../../integration/proxies/envoy.md) | [<i class="icon-support-full"></i>](../../integration/kubernetes/istio.md) | <i class="icon-support-unknown"></i> | <i class="icon-support-full"></i> |
| [Skipper] | [<i class="icon-support-full"></i>](../../integration/proxies/skipper.md) | <i class="icon-support-unknown"></i> | <i class="icon-support-unknown"></i> | <i class="icon-support-unknown"></i> | | [Skipper] | [<i class="icon-support-full"></i>](../../integration/proxies/skipper.md) | <i class="icon-support-unknown"></i> | <i class="icon-support-unknown"></i> | <i class="icon-support-unknown"></i> |
| [Apache] | <i class="icon-support-none" alt="Not Supported"></i> | <i class="icon-support-none"></i> | <i class="icon-support-none"></i> | <i class="icon-support-none"></i> | | [Apache] | <i class="icon-support-none" alt="Not Supported"></i> | <i class="icon-support-none" alt="Not Supported"></i> | <i class="icon-support-none" alt="Not Supported"></i> | <i class="icon-support-none" alt="Not Supported"></i> |
| [IIS] | <i class="icon-support-none"></i> | <i class="icon-support-none"></i> | <i class="icon-support-none"></i> | <i class="icon-support-none"></i> | | [IIS] | <i class="icon-support-none" alt="Not Supported"></i> | <i class="icon-support-none" alt="Not Supported"></i> | <i class="icon-support-none" alt="Not Supported"></i> | <i class="icon-support-none" alt="Not Supported"></i> |
Legend: Legend:
| Icon | Meaning | | Icon | Meaning |
|:------------------------------------:|:-------------------:| |-------------------------------------:|:-------------------:|
| <i class="icon-support-full"></i> | Supported | | <i class="icon-support-full"></i> | Supported |
| <i class="icon-support-unknown"></i> | Unknown | | <i class="icon-support-unknown"></i> | Unknown |
| <i class="icon-support-partial"></i> | Partially Supported | | <i class="icon-support-partial"></i> | Partially Supported |
| <i class="icon-support-none"></i> | Not Supported | | <i class="icon-support-none"></i> | Not Supported |
## More Information ## More Information