Neutron LBaaS TLS - Specification¶
BP https://blueprints.launchpad.net/neutron/+spec/lbaas-ssl-termination
Terminating TLS connections on the load balancer is a capability expected from modern load balancers and incorporated into many applications. This capability enables better certificate management and improved application based load balancing e.g. cookie-based persistency, L7 Policies appliance, etc.
Problem Description¶
No TLS offloading capability is available for Neutron LBaaS
Proposed Change¶
Note: This document is referencing to the new LBaaS objects model proposed at https://review.openstack.org/#/c/89903
Note: This document does not consider flavors framework proposed at https://review.openstack.org/#/c/90070 Before the flavors framework is in place, specific back-end driver which does not support TLS capabilities should throw an exception stating a lack of TLS support once it gets request for listener with TLS configuration. This document specifies a “core” feature set that every back-end implementing TLS capabilities must comply. TLS capabilities of various back-end implementations may differ in future releases, thus flavors aspect should definitely be part of TLS capabilities specification
Note: Horizon project aspect is not a part of this specification.
Tenant will manage his TLS certificates using Barbican. Certificates will be stored in Barbican secure containers.
Barbican is in charge of containers life cycle management, containers classification and validation. LBaaS TLS requires a specific container type (TLS). Only container of this type will be listed to the tenant for selection while configuring listener’s TLS containers to use. Any invalid container usage will raise an error.
Barbican will also manage list of interested consumers for each container. See spec at https://review.openstack.org/#/c/99516
Neutron LBaaS (a consumer, according to Barbican’s terminology) will not use a regular GET request for container resource in order to get the container. Instead, it will use a POST request to container’s consumers resource (http://admin-api/v1/containers/{container-uuid}/consumers) with following info:
- {
“type”: “LBaaS”, “URL”: “https://lbaas.myurl.net/loadbalancers/<lb_id>/”
}
Note: We might want to use specific Listener URL instead of Loadbalancer’s one, like “https://lbaas.myurl.net/lbaas/listeners/<listener_id>”
As a response, it will get containers data like container’s resource GET request was used. Barbican, in its turn will store consumer’s (LBaaS instance URL) data in its database so this info can be used for getting all consumers of a specific TLS container.
As a result, Neutron LBaaS TLS implementation is required to:
Use only POST request to container’s consumers resource in order to get the container’s data.
Perform DELETE request to container’s consumers resource when stop using a container.
Barbican TLS container will contain PEM encoded data. Specific back-end implementation might convert the certificates data to other format such as DER, if needed.
In addition to existing HTTP, HTTPS and TCP, new protocol, TERMINATED_HTTPS will be added for listener creation
For tenant, creating listener with TERMINATED_HTTPS as a protocol means desire to offload incoming encrypted traffic. New configuration options will be available for listener’s configuration including:
Default TLS container id for TLS termination
TLS containers list for SNI
In case when specific back-end is not able to support TLS capabilities, its driver should throw an exception. The exception message should state that this specific back-end (provider) does not support listeners with TLS offloading. The clear sign of listener’s requirement for TLS offloading capabilities is its TERMINATED_HTTPS protocol.
New module will be developed in Neutron LBaaS for Barbican TLS containers interactions. The module will be used by Neutron LBaaS front-end API code and providers’ driver code. The module will be used for validation and data extraction from default TLS container and SNI containers. This module represents the only legitimate API for Barbican TLS containers interactions. See ‘SNI certificates list management’ section for detailed module specification.
When creating listener with TERMINATED_HTTPS protocol:
Front-end TLS offloading is always enabled - hard coded as a default behaviour for listener with TERMINATED_HTTPS protocol
Tenant must supply default TLS container for front-end offloading. Not supplying a container is an invalid configuration.
TLS supported protocols and cipher suites for termination will be set to sane values by each back-end’s specific code
SNI certificates list is optional and not mandatory to specify
SNI certificates list specifying is described in “SNI certificates list management” section
Certificate intermediate chain will be stored as a part of Barbican’s TLS container
Back-end re-encryption will not be supported in first phase
Front-end client authentication and back-end server authentication will not be supported in first phase
When updating listener with TERMINATED_HTTPS protocol:
In TLS configuration domain, default TLS container ID for front-end offloading and SNI container IDs list are values that may be changed
In case when defaut TLS container ID is replaced for the listener, back-end implementation should ensure a lack of a downtime on LB appliance.
Same for changing SNI container IDs list, back-end should avoid LB downtime.
HA-Proxy LBaaS implementaion and other LBaaS implementations should be modified to support this specification.
With stated above, following is a description of a basic tenant use case - creating listener with TLS offloading:
Tenant cteates Barbican TLS container with a certificate.
Tenant creates listener with TERMINATED_HTTPS as a listener protocol and specifies the Barbican TLS container ID as a default TLS container for front-end offloading
As a result, listener created, offloading encrypted traffic on front-end with default tenant’s TLS certificate, not re-encrypting traffic to the back-end.
Requirements from Barbican¶
Tenant should be able to create and delete TLS containers using Barbican
Ability to store TLS certificates in Barbican containers that contain the TLS certificate itself, its private key and optionaly, intermediate chain
Creating TLS container with:
Certificate : PEM text field
Private_key: PEM text_field
(extracted) Private_key_pass_phrase : text field
Intermediates: PEM text field (optional) This field is a concatination of PEM encoded certificate blocks in specific order
Delete TLS certificate optional: Check if certificate is in use by any consumer and warn before deleting. Barbican’s BP discussing this feature: https://review.openstack.org/#/c/99516/
Get TLS container, including private key in PEM encoded PKCS1 or PKCS7 formats, by container id
Get TLS certificate in pem encoded x509 format, by container id
Restrictions¶
TLS settings are only available for listeners having TERMINATED_HTTPS as a protocol. In other cases TLS settings will be disabled and have None or empty values. There should be a meaningfull error message to a user explaining the exact reason of a failure in case of an invalid configuration.
Listener protocol is immutable. Changing the protocol will require radical re-configuration of provider’s back-end system, which seems to be not justified for this use case. Tenant should create new listener.
While updating existing TLS certificate, name and description are only values allowed to be modified. Creating new TLS container and using it instead of the old one will be easier option than re-configuring LBaaS back-end with modified container, at least in first phase.
SNI certificates list management¶
For SNI functionality, tenant will supply list of TLS containers in specific order. In case when specific back-end is not able to support SNI capabilities, its driver should throw an exception. The exception message should state that this specific back-end (provider) does not support SNI capability. The clear sign of listener’s requirement for SNI capability is a none empty SNI container ids list. However, reference implementation must support SNI capability.
New separate module will be developed in Neutron LBaaS for Barbican TLS containers interactions. The module will use service account for Barbican API interation. The module will have API for: * Ensuring Barbican TLS container existence (used by LBaaS front-end API)
Validating Barbican TLS container (used by LBaaS front-end API) This API will also “register” LBaaS as a container’s consumer in Barbican’s repository.
Extracting SubjectCommonName and SubjectAltName information from certificates’ X509 (used by LBaaS front-end API) As for now, only dNSName and directoryName types will be extracted from SubjectAltName sequence, while directoryName type usage is an issue for further discussion.
Extracting certificate’s data from Barbican TLS container (used by provider/driver code)
Unregistering LBaaS as a consumer of the container when container is not used by any listener any more (used by LBaaS front-end API)
The module will use pyOpenSSL and PyASN1 packages. Only this new common module should be used by Neutron LBaaS code for Barbican containers interactions.
Front-end LBaaS API (plugin) code will use a new developed module for validating Barbican TLS containers. Driver, in its turn, can extract SubjectCommonName and SubjectAltName information from certificates’ X509 via the common module API and use it for its specific SNI implementation.
Note:
Specific back-end driver does not have to use SubjectAltName information. Furthermore, specific driver may throw an exception saying SubjectAltName is not supported by its provider
Any specific driver implementation may extract host names info from certificates using the mentioned above common module API only, if needed.
SNI conflicts
Employing the order of certificates list is not a common requirement for all back-end implementations. The order of SNI containers list may be used by specific back-end code, like Radware’s, for specifying priorities among certificates. Order is meant to be a hint to resolve conflicts when 2 or more certificates match the DNS name requested in the SNI client hello. Specific backends might choose to ignore this order and might employ their own mechanisms to choose one among the clashing certificates. For ex. NetScaler employs the best match algorithm and does not require order for conflict resolution. It’s also possible that specific driver throws an exception saying there is a collision and this specific SNI setup will not be supported by the back-end.
Data Model Impact¶
Data model changes
lbaas_listeners table will be modified with new
default_tls_container_id (nullable string 36) - Barbican’s TLS container id
New lbaas_sni table will be created for storing ordered list of TLS containers associated to a listener for SNI capabilities. Association objects is composed of:
id (immutable string 36) - generated object id
listener_id (string 36) - associated listener id
tls_container_id (string 36) - associated Barbican TLS container id
position - (integer) index for preserving the order
Required database migration
add new columns to lbaas_isteners table
create new lbaas_sni table
New data initial set
New columns for lbaas_listeners table’s existing entries will be set to defaults
REST API Impact¶
Listener Attributes
Attribute Name |
Type |
Access |
Default Value |
Validation/ Conversion |
Description |
---|---|---|---|---|---|
default-tls- container-id |
UUID |
RW,tenant |
NULL |
UUID |
default TLS cert id to use for offloading |
sni_container _ids |
UUID list |
RW,tenant |
NULL |
UUID list |
ordered list of TLS containers to use for SNI . |
Functions
create_listener
Creates new listener
Request POST /v2.0/lbaas/listeners Accept: application/json { “listener”:{ <…usual listener parameters>, “protocol”: “TERMINATED_HTTPS” “default_tls_container_id”: “7804a0de-7f6b-409a-a47c-a1cc7bc77b4j”, “sni_container_ids”: None } }
Response { “listener”:{ “id”: “8604a0de-7f6b-409a-a47c-a1cc7bc77b2e” <…usual listener parameters>, “default_tls_container_id”: “7804a0de-7f6b-409a-a47c-a1cc7bc77b4c”, “sni_container_ids”: None “tenant_id”:”6b96ff0cb17a4b859e1e575d221683d3” } }
create_listener (with SNI list)
Creates new listener
Request POST /v2.0/lbaas/listeners Accept: application/json { “listener”:{ <…usual listener parameters>, “protocol”: “TERMINATED_HTTPS” “default_tls_container_id”: “7804a0de-7f6b-409a-a47c-a1cc7bc77b4j”, “sni_container_ids”: [5404a0de-7f6b-409a-a47c-a1ccgbc77b3j, 1206a0de-7f6b-409a-a47c-a1ccgbc7bgf3] } }
Response { “listener”:{ “id”: “8604a0de-7f6b-409a-a47c-a1cc7bc77b2e” <…usual listener parameters>, “default_tls_container_id”: “7804a0de-7f6b-409a-a47c-a1cc7bc77b4c”, “sni_container_ids”:[5404a0de-7f6b-409a-a47c-a1ccgbc77b3j, 1206a0de-7f6b-409a-a47c-a1ccgbc7bgf3] “tenant_id”:”6b96ff0cb17a4b859e1e575d221683d3” } }
update_listener
Updates VIP listener
Request PUT /v2.0/lbaas/listeners/<listener-id> Accept: application/json { “listener”:{ <…usual listener parameters>, “protocol”: “TERMINATED_HTTPS” “default_tls_container_id”: “7804a0de-7f6b-409a-a47c-a1cc7bc77b4c”, “sni_container_ids”: None } }
Response { “listener”:{ “id”: “8604a0de-7f6b-409a-a47c-a1cc7bc77b2e” <…usual listener parameters>, “default_tls_container_id”: “7804a0de-7f6b-409a-a47c-a1cc7bc77b4c”, “sni_container_ids”: None “tenant_id”:”6b96ff0cb17a4b859e1e575d221683d3” } }
Security Impact¶
Following are security requirements:
Retrieving TLS container from Barbican to LBaaS plugin/driver must be secured
Sending TLS container contents from driver to back-end system must be secured
Storing secrets on neutron server is prohibited
Back-end systems may need to ensure secured store for secrets to meet certain security compliance requirements
Notifications Impact¶
None
CLI Impact¶
Listener creation with TERMINATED_HTTPS protocol (default behavior) lb-listener-create –protocol TERMINATED_HTTPS –protocol-port 443 –default_tls_container_id 9a96ff0cb17a4b859e1e575d2216cd23 …<usual CLI options>
Listener creation with TERMINATED_HTTPS protocol and SNI certificates list lb-listener-create –protocol TERMINATED_HTTPS –protocol-port 443 –default_tls_container_id 9a96ff0cb17a4b859e1e575d2216cd23 –sni_container_ids list=true 6b96ff0cb17a4b859e1e575d221683d3 4596ff0cb17a4b859e1e575d22168ba1 …<usual CLI options>
Other End User Impact¶
None
Performance Impact¶
When updating listener without modifying TLS settings (default container id or SNI list) - Barbican API should not be used for retrieving container content which was not actually changed. This will prevent unnecessary resources consumption when, for example, members are added to the pool used by listener. It means that each Barbican TLS container will be validated only once for a listener while it’s still in use by this listener.
IPv6 Impact¶
None
Other Deployer Impact¶
Barbican is required to be deployed and functional in order this feature to work.
New dependencies are added for neutron, pyOpenSSL and PyASN1. These are required by new module for Barbican TLS containers interactions.
Developer Impact¶
None
Community Impact¶
This change has been in review since Juno. Much discussion has taken place over IRC and the mailing list.
Alternatives¶
None
Implementation¶
Assignee(s)¶
Primary assignee:
- Other contributors:
Barbican TLS containers interactions module - https://launchpad.net/~carlos-garza
Work Items¶
Develop new module for BArbican TLS containers interactions using pyOpenSSL and PyASN1 packages.
Implement changes in LBaaS DB schema v2
Implement changes in LBaaS extension v2
Implement all required CLI changes
Implement all required unit testing
Implement all required tempest testing
Make integration with Barbican certificates storage API Detailed specificatio of how Barbican’s API for containers should be used is at https://review.openstack.org/#/c/99516
Modifying LBaaS HA-Proxy driver to support TLS capability Detailed specification of this work item is at https://review.openstack.org/#/c/100931
Use HA-Proxy version 1.5
Implement horizon part of this spec, not as part of Juno release.
Dependencies¶
Barbican API requirements
Neutron LBaaS API v2 with new listener object implemented
New dependencies will be added for neutron, pyOpenSSL and PyASN1. These are required by new module for Barbican TLS containers interactions.
Testing¶
Tempest Tests¶
listener unit testing domains
REST API and attributes validation tests
DB mixin and schema tests
LBaaS Plugin with mocked driver end-to-end tests
Specific driver tests for each existing driver supporting TLS offloading
Tempest tests
CLI tests
New listener creation with TERMINATED_HTTPS as a protocol
No default TLS container for termination supplied. Check error generation
Default TLS container for termination supplied. Test expected default configuration took place.
Default TLS container supplied. SNI TLS containers list was supplied Test expected configuration took place
Update existing listener with TERMINATED_HTTPS as a protocole
Change default TLS container. Test expected configuration
Add/Modify SNI containers list. Test expected configuration
CLI tests should test inconsistency issues such as:
No default offloading TLS container specified when creating listener with TERMINATES_HTTPS protocole
Functional Tests¶
As above.
API Tests¶
As above.
Documentation Impact¶
User Documentation¶
Neutron CLI should be modified with updated listener commands with TLS options
Developer Documentation¶
Neutron API should be modified with new listener TLS attributes