-
Notifications
You must be signed in to change notification settings - Fork 605
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feat: Header Cert Auth plugin (#7775)
* framework for header cert auth plugin * add how-to page placeholder * add additional docs: getting started, and more * fix linting * add AWS/ALB details * remove screenshots and cleanup aws alb guide * minor editing and cleanup; fix konnect example * save * remove screenshots --------- Co-authored-by: Murillo <[email protected]> Co-authored-by: Angel <[email protected]>
- Loading branch information
1 parent
285dd6d
commit de65ee6
Showing
8 changed files
with
306 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
## Changelog | ||
|
||
### {{site.base_gateway}} 3.8.x | ||
* Introduced the Header Cert Authentication plugin. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
name: Header Cert Authentication | ||
search_aliases: | ||
- header cert auth | ||
- header-cert-auth | ||
- authentication | ||
dbless_compatible: | ||
dbless_explanation: | ||
free: false | ||
enterprise: true | ||
konnect: true | ||
network_config_opts: All | ||
notes: -- | ||
categories: | ||
- authentication | ||
publisher: Kong Inc. | ||
desc: Authenticate clients with mTLS certificates passed in headers by a WAF or load balancer | ||
|
47 changes: 47 additions & 0 deletions
47
app/_hub/kong-inc/header-cert-auth/how-to/_add-cert-authorities.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
--- | ||
nav_title: Add Certificate Authorities | ||
title: Add Certificate Authorities | ||
--- | ||
|
||
To use this plugin, you must add certificate authority (CA) certificates. These are | ||
stored in a separate `ca_certificates` store rather than the main certificates store because | ||
they do not require private keys. To add one, obtain a PEM-encoded copy of your CA certificate | ||
and pass it to the `/ca_certificates` endpoint in a `POST` request: | ||
|
||
{% navtabs %} | ||
{% navtab Kong Admin API %} | ||
```bash | ||
curl -X POST https://localhost:8001/ca_certificates -F [email protected] | ||
``` | ||
|
||
The response will contain an `id` value that can now be used for the Header Cert Auth plugin configurations or consumer mappings. | ||
|
||
{% endnavtab %} | ||
|
||
{% navtab Konnect %} | ||
|
||
Go through the Gateway Manager: | ||
1. From the {{site.konnect_short_name}} [{% konnect_icon runtimes %} **Gateway Manager**](https://cloud.konghq.com/us/gateway-manager/). | ||
1. Select a control plane and click **Certificates** | ||
1. Select the **CA Certificates** tab and **Add CA Certificate** | ||
1. Copy and paste your certificate information and click **Save**. | ||
|
||
You can view the certificate listed in the **Certificates** tab. | ||
|
||
To add a certificate via the {{site.konnect_short_name}} API, you need: | ||
* {{site.konnect_short_name}} control plane ID | ||
* [A personal access token](/konnect/api/) | ||
|
||
```bash | ||
curl -X POST https://konnect.konghq.com/api/control_planes/{controlPlaneID}/ca_certificates \ | ||
-F [email protected] \ | ||
--header "Authorization: Bearer TOKEN" | ||
``` | ||
{% endnavtab %} | ||
{% endnavtabs %} | ||
The `id` value returned can now be used for the Header Cert Auth plugin configurations or consumer mappings. | ||
|
||
{:.important} | ||
> **Important:** To ensure proper certificate validation, it is important to upload all required Certificate Authorities (CAs) and their intermediates into the Kong CA store. | ||
> <br><br> | ||
> Failure to do so may result in incomplete certificate validation, as some WAF and load balancer providers only send the end-leaf certificate in their header, rather than encoding the entire certificate chain sent by the client. This is especially crucial when using the `base64_encoded` format. |
78 changes: 78 additions & 0 deletions
78
app/_hub/kong-inc/header-cert-auth/how-to/_aws-alb-integration.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
--- | ||
nav_title: AWS ALB Integration | ||
title: AWS ALB Integration | ||
--- | ||
|
||
AWS has support for mutually authenticating clients that present X509 certificates to Application Load Balancer (ALB). | ||
You can learn more about mTLS with ALB in [AWS's blog post](https://aws.amazon.com/blogs/networking-and-content-delivery/introducing-mtls-for-application-load-balancer/). | ||
|
||
To make sure AWS/ALB works with the Header Cert Auth plugin with mTLS enabled, we first need to generate the required certificates. | ||
For development certificates, you can use OpenSSL to generate certificates or tools such as `mkcert`. | ||
|
||
## Add HTTPS listener to the ALB | ||
|
||
Configure the ALB by adding an HTTPS listener. | ||
|
||
1. In the Listener configuration, configure the following settings: | ||
* Protocol: HTTPS | ||
* Port: 443 | ||
* Routing actions: Forward to target groups | ||
|
||
2. In the Secure listener settings, configure the certificate from AWS Certificate Manager (ACM). | ||
Make sure to upload your certificates to ACM and use them in the ALB. | ||
* Certificate source: From ACM | ||
* Certificate (from ACM): Select the certificate that you want to use | ||
* Client certificate handling: Select Mutual authentication (mTLS) with Passthrough | ||
|
||
## Configure {{site.base_gateway}} with certificate and plugin | ||
|
||
Next, configure {{site.base_gateway}}. | ||
|
||
1. Add the root CA to the CA certificates: | ||
|
||
```bash | ||
curl -sX POST https://localhost:8001/ca_certificates -F [email protected] | ||
{ | ||
"tags": null, | ||
"created_at": 1566597621, | ||
"cert": "-----BEGIN CERTIFICATE-----\FullPEMOmittedForBrevity==\n-----END CERTIFICATE-----\n", | ||
"id": "322dce96-d434-4e0d-9038-311b3520f0a3" | ||
} | ||
``` | ||
|
||
2. Add the Header Cert Auth plugin to the service (or route). | ||
|
||
* We need to update the `certificate_header_name` to `X-Amzn-Mtls-Clientcert`. | ||
* The `certificate_header_format` should be `url_encoded` for AWS/ALB. | ||
|
||
```bash | ||
curl -X POST http://localhost:8001/services/{serviceName|Id}/plugins \ | ||
--header "accept: application/json" \ | ||
--header "Content-Type: application/json" \ | ||
--data ' | ||
{ | ||
"name": "header-cert-auth", | ||
"config": { | ||
"ca_certificates": [ | ||
"0D769DE8-7CC0-4541-989B-F9C23E20054C" | ||
], | ||
"certificate_header_name": "X-Amzn-Mtls-Clientcert", | ||
"certificate_header_format": "url_encoded", | ||
"secure_source": false | ||
} | ||
} | ||
``` | ||
## Validate | ||
Use the certificate and key to proxy the traffic: | ||
```bash | ||
curl -k --cert <client_certificate> --key <client_key> https://test-alb-<id>.us-east-2.elb.amazonaws.com/test | ||
``` | ||
You should then be able to see the certificate in the response headers: | ||
```bash | ||
"X-Amzn-Mtls-Clientcert": "-----BEGIN%20CERTIFICATE-----%0AMIIDbDCCAdSgAwIBAgIUa...-----END%20CERTIFICATE-----" | ||
``` |
94 changes: 94 additions & 0 deletions
94
app/_hub/kong-inc/header-cert-auth/how-to/_manual-mapping-cert-consumers.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
--- | ||
nav_title: Manual Mappings Between Certificate and Consumer Objects | ||
title: Manual Mappings Between Certificate and Consumer Objects | ||
--- | ||
Sometimes, you might not want to use automatic consumer lookup, or you have certificates | ||
that contain a field value not directly associated with consumer objects. In those | ||
situations, you may manually assign one or more subject names to the consumer object for | ||
identifying the correct consumer. | ||
|
||
{:.note} | ||
> **Note**: Subject names refer to the certificate's Subject Alternative Names (SAN) or | ||
Common Name (CN). CN is only used if the SAN extension does not exist. | ||
|
||
{% navtabs %} | ||
{% navtab Kong Admin API %} | ||
|
||
Create a mapping: | ||
|
||
```bash | ||
curl -X POST http://localhost:8001/consumers/{consumer}/header-cert-auth \ | ||
-d '[email protected]' | ||
``` | ||
|
||
Where `{consumer}` is the `id` or `username` property of the | ||
[consumer](/gateway/latest/admin-api/#consumer-object) entity to associate the | ||
credentials to. | ||
|
||
Once created, you'll see a `201` success message: | ||
|
||
```json | ||
HTTP/1.1 201 Created | ||
|
||
{ | ||
"consumer": { "id": "876bf719-8f18-4ce5-cc9f-5b5af6c36007" }, | ||
"created_at": 1443371053000, | ||
"subject_name": "[email protected]" | ||
} | ||
``` | ||
|
||
{% endnavtab %} | ||
{% navtab Declarative (YAML) %} | ||
|
||
To create a subject name mapping using declarative configuration, you must generate a UUID for each `header_cert_auth_credentials` mapping. You can use any | ||
UUID generator to do this. Here are some common ones, depending on your OS: | ||
* [Linux](https://man7.org/linux/man-pages/man1/uuidgen.1.html) | ||
* [MacOS](https://www.unix.com/man-page/mojave/1/uuidgen/) | ||
* [Windows](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/new-guid?view=powershell-7) | ||
|
||
After you have generated a UUID, add the following to your declarative | ||
configuration file: | ||
|
||
```yaml | ||
consumers: | ||
- custom_id: my-consumer | ||
username: {consumer} | ||
header_cert_auth_credentials: | ||
- id: bda09448-3b10-4da7-a83b-2a8ba6021f0c | ||
subject_name: [email protected] | ||
``` | ||
{% endnavtab %} | ||
{% endnavtabs %} | ||
#### Parameters for manual mapping | ||
Form Parameter | Default | Description | ||
--- | --- | --- | ||
`id`<br>*required for declarative config* | none | UUID of the consumer-mapping. Required if adding mapping using declarative configuration, otherwise generated automatically by Kong's Admin API. | ||
`subject_name`<br>*required* | none | The Subject Alternative Name (SAN) or Common Name (CN) that should be mapped to `consumer` (in order of lookup). | ||
`ca_certificate`<br>*optional* | none | **If using the Kong Admin API:** UUID of the Certificate Authority (CA). <br><br> **If using declarative configuration:** Full PEM-encoded CA certificate. <br><br>The provided CA UUID or full certificate has to be verifiable by the issuing certificate authority for the mapping to succeed. This is to help distinguish multiple certificates with the same subject name that are issued under different CAs. <br><br>If empty, the subject name matches certificates issued by any CA under the corresponding `config.ca_certificates`. | ||
|
||
### Matching behaviors | ||
|
||
After a client certificate has been verified as valid, the consumer object is determined in the following order, unless `skip_consumer_lookup` is set to `true`: | ||
|
||
1. Manual mappings with `subject_name` matching the certificate's SAN or CN (in that order) and `ca_certificate = <issuing authority of the client certificate>` | ||
2. Manual mappings with `subject_name` matching the certificate's SAN or CN (in that order) and `ca_certificate = NULL` | ||
3. If `config.consumer_by` is not null, consumer with `username` and/or `id` matching the certificate's SAN or CN (in that order) | ||
4. The `config.anonymous` consumer (if set) | ||
|
||
{:.note} | ||
> **Note**: Matching stops as soon as the first successful match is found. | ||
|
||
{% include_cached /md/plugins-hub/upstream-headers.md %} | ||
|
||
When `skip_consumer_lookup` is set to `true`, consumer lookup is skipped and instead of appending aforementioned headers, the plugin appends the following two headers | ||
|
||
* `X-Client-Cert-Dn`, distinguished name of the client certificate | ||
* `X-Client-Cert-San`, SAN of the client certificate | ||
|
||
Once `skip_consumer_lookup` is applied, any client with a valid certificate can access the Service/API. | ||
To restrict usage to only some of the authenticated users, also add the ACL plugin (not covered here) and create | ||
allowed or denied groups of users using the same | ||
certificate property being set in `authenticated_group_by`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
--- | ||
nav_title: Overview | ||
--- | ||
|
||
The Header Cert Authentication plugin authenticates API calls by using client certificates provided in HTTP headers, | ||
instead of relying on traditional TLS termination. | ||
This approach is particularly useful in scenarios where TLS traffic is terminated outside of {{site.base_gateway}} such as at an external CDN or load balancer and the client certificate is passed along in an HTTP header for subsequent validation. | ||
|
||
## How it works | ||
|
||
This plugin addresses the inability of the {{site.base_gateway}} to authenticate API calls using client certificates received in HTTP headers, rather than through traditional TLS termination. | ||
This occurs in scenarios where TLS traffic is not terminated at the {{site.base_gateway}}, but rather at an external CDN or load balancer, and the client certificate is preserved in an HTTP header for further validation. | ||
|
||
The Header Cert Authentication plugin is similar to the [mTLS Auth plugin](/hub/kong-inc/mtls-auth). | ||
However, the mTLS plugin is only designed for traditional TLS termination, while the Header Cert Auth plugin also provides support for client certificates in headers. | ||
|
||
The Header Cert Auth plugin extracts the client certificate from the HTTP header and validates it against the configured CA list. | ||
If the certificate is valid, the plugin maps the certificate to a consumer based on the common name field. | ||
|
||
The plugin validates the certificate provided against the configured CA list based on the | ||
requested route or service: | ||
* If the certificate is not trusted or has expired, the response is | ||
`HTTP 401 TLS certificate failed verification`. | ||
* If a valid certificate is not presented (including when requests are not sent to the HTTPS port), | ||
the response is HTTP 401 No required TLS certificate was sent. | ||
* However, if the config.anonymous option is configured on the plugin, | ||
an anonymous consumer is used, and the request is allowed to proceed. | ||
|
||
The plugin can be configured to only accept certificates from trusted IP addresses, as specified by the [`trusted_ips`](/gateway/{{page.release}}/reference/configuration/#trusted_ips) config option. This ensures that Kong can trust the header sent from the source and provides L4 level of security. | ||
|
||
{:.important} | ||
> **Important:** Incomplete or improper configuration of the Header Cert Authentication plugin can compromise the security of your API. | ||
<br><br> | ||
> For instance, enabling the option to bypass origin verification can allow malicious actors to inject fake certificates, as Kong will not be able to verify the authenticity of the header. This can downgrade the security level of the plugin, making your API vulnerable to attacks. Ensure you carefully evaluate and configure the plugin according to your specific use case and security requirements. | ||
Additionally, the plugin has a [static priority](/konnect/reference/plugins/) configured so that it runs after all authentication plugins, allowing other auth plugins (e.g. basic-auth) to secure the source first. This ensures that the source is secured by multiple layers of authentication by providing L7 level of security. | ||
|
||
### Client certificate request | ||
|
||
The `send_ca_dn` option is not supported in this plugin. This is used in mutual TLS authentication, where the server sends the list of trusted CAs to the client, and the client then uses this list to select the appropriate certificate to present. In this case since the plugin does not do TLS handshakes and only parses the client certificate from the header, it is not applicable. | ||
|
||
The same applies to SNI functionality. The plugin can verify the certificate without needing to know the specific hostname or domain being accessed. The plugin's authentication logic is decoupled from the TLS handshake and SNI, so it doesn't need to rely on SNI to function correctly (pretty much anything that deals with the actual TLS handshake is not needed for the plugin to work). | ||
|
||
## Troubleshooting | ||
|
||
When authentication fails, the client does not have access to any details that explain the failure. The security reason for this omission is to prevent malicious reconnaissance. Instead, the details are recorded inside Kong's error logs under the `[header-cert-auth]` filter. | ||
|
||
### FAQs | ||
|
||
**Q: Will the client need to encrypt the message with a private key and certificate when passing the certificate in the header?** | ||
|
||
**A:** No, the client only needs to send the target's certificate encoded in a header. Kong will validate the certificate, but it requires a high level of trust that the WAF/LB is the only entrypoint to the Kong proxy. The Header Cert Auth plugin will provide an option to secure the source, but additional layers of security are always preferable. Network level security (so that Kong only accepts requests from WAF - IP allow/deny mechanisms) and application-level security (Basic Auth or Key Auth plugins to authenticate the source first) are examples of multiple layers of security that can be applied. | ||
|
||
## Get started with the Header Cert Authentication plugin | ||
|
||
* [Add certificate authorities](/hub/kong-inc/header-cert-auth/how-to/add-cert-authorities/): | ||
To use this plugin, you must add certificate authority (CA) certificates. | ||
Set them up before configuring the plugin. | ||
* [Configuration reference](/hub/kong-inc/header-cert-auth/configuration/) | ||
* [Basic configuration example](/hub/kong-inc/header-cert-auth/how-to/basic-example/) | ||
* [Learn how to use the plugin](/hub/kong-inc/header-cert-auth/how-to/) | ||
* [Create manual mappings between certificate and consumer objects](/hub/kong-inc/header-cert-auth/how-to/manual-mapping-cert-consumers/) | ||
* [AWS ALB integration](/hub/kong-inc/header-cert-auth/how-to/aws-alb-integration/) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
strategy: gateway | ||
releases: | ||
minimum_version: '3.8.x' |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.