|
|
**NOTE**: _This page is a discussion about an early attempt to provide TLS support in Kea. It is now obsolete and kept here for historic reasons only. The current (Feb. 2021) plan is to implement native TLS support in Kea. See [TLS design](https://gitlab.isc.org/isc-projects/kea/-/wikis/designs/rbac-tls-design#1-native-tls-implementation) page, section about Native TLS implementation._
|
|
|
|
|
|
-------
|
|
|
|
|
|
Kea 1.6.0 provides a control agent (CA) that is able to communicate over http. There's a documentation that explains how to deploy apache2 or nginx to serve as reverse proxy with adding TLS wrapper, so the service can be exposed over https. There are several problems with the approach:
|
|
|
|
|
|
1. DHCP admins are often not skilled in web server administration
|
|
|
2. additional software introduces additional maintenance overhead (need to track/update additional software)
|
|
|
3. the problems are exacerbated in larger deployments (many Kea servers)
|
|
|
4. CA doesn't provide any kind of access control.
|
|
|
|
|
|
One important aspect here is that while for the time being we consider simple RO/RW access, in the future it is likely that more complex access will be requested by customers. Our long term plan is to provide this flexibility in Stork that already has [role-based access control](https://stork.readthedocs.io/en/v0.6.0/usage.html#managing-users) and we could use that mechanism.
|
|
|
|
|
|
This discussion attempts to explore potential solutions to the aforementioned problems. See [requirements](https://gitlab.isc.org/isc-projects/kea/-/wikis/designs/rbac-tls-requirements) doc for more formal requirements and [design](https://gitlab.isc.org/isc-projects/kea/-/wikis/designs/https-wrapper-for-control-agent-solution) for the actual design.
|
|
|
|
|
|
## Problem 1: TLS support for CA
|
|
|
|
|
|
We need to provide TLS support somehow.
|
|
|
|
|
|
### Proposal 1.1: Bundle existing webserver (caddy)
|
|
|
|
|
|
One proposal considered was to bundle a whole complete web server. [Caddy](https://caddyserver.com/) was specifically mentioned.
|
|
|
|
|
|
Advantages:
|
|
|
+ ready to use, many features, including https (TLS) support, reverse proxy, and looks easy to use
|
|
|
|
|
|
Flaws:
|
|
|
- does not seem to have access control (users or anything similar). We could implement it in go (caddy is open source), but this would require maintaining patches, which would further complicate maintenance and development
|
|
|
- this doesn't solve the problem 2 (we would need to monitor caddy releases and update as needed, when security updates appear)
|
|
|
- it's a heavy dependency in several ways. First, it's a full web server with many bells and whistles that we're not going to use. Second, it brings a new language to kea: golang. While we as ISC have an experience with go now, it's not present in the Kea environment, so this would make Kea compilation even more complicated.
|
|
|
|
|
|
### Proposal 1.2: Implement TLS wrapper in python
|
|
|
|
|
|
Another proposal is to write tls wrapper in Python. After some experiments, this seems very easy to do. The minimalistic PoC looks like this:
|
|
|
|
|
|
```python
|
|
|
from http.server import HTTPServer, BaseHTTPRequestHandler
|
|
|
import ssl
|
|
|
|
|
|
class KeaCARequestHandler(BaseHTTPRequestHandler):
|
|
|
|
|
|
def do_GET(self):
|
|
|
self.send_response(200)
|
|
|
self.end_headers()
|
|
|
self.wfile.write(b'Hello, world!')
|
|
|
|
|
|
httpd = HTTPServer(('localhost', 4443), KeaCARequestHandler)
|
|
|
|
|
|
httpd.socket = ssl.wrap_socket (httpd.socket,
|
|
|
keyfile="./kea-ca.key",
|
|
|
certfile='./kea-ca.cert', server_side=True)
|
|
|
|
|
|
httpd.serve_forever()
|
|
|
```
|
|
|
|
|
|
The certificate and key can be easily generated using this command:
|
|
|
```
|
|
|
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365
|
|
|
```
|
|
|
|
|
|
Slightly more advanced version that handles GET and POST is available on [experiment-https-ca](https://gitlab.isc.org/isc-projects/kea/-/blob/experiment-https-ca/src/bin/agent/tls-ca.py) branch.
|
|
|
|
|
|
Advantages:
|
|
|
+ small
|
|
|
+ easy to develop (python development is fast, there are many examples and libraries to reuse)
|
|
|
+ fine tuned to our needs
|
|
|
+ uses language that we already use in Kea (kea-shell, a client for CA, is written in python)
|
|
|
+ while it doesn't have access control, it can be reasonably easy implemented in python.
|
|
|
|
|
|
Flaws:
|
|
|
- doesn't have access control (we would need to implement some form of access control on our own in python)
|
|
|
|
|
|
### Proposal 1.3: Use stunnel
|
|
|
|
|
|
[stunnel](https://www.stunnel.org/) is a proxy specifically designed to add TLS encryption functionality.
|
|
|
|
|
|
Advantages:
|
|
|
+ small
|
|
|
+ easy to use
|
|
|
|
|
|
Flaws:
|
|
|
- doesn't have access control
|
|
|
- it was frowned upon when used as a "solution" to DNS-over-TLS
|
|
|
|
|
|
### Proposal 1.4: Implement TLS support in CA using cryptolink
|
|
|
|
|
|
Kea already has support for two crypto libraries: OpenSSL and Botan, although we use very small part of their capabilities (only calculate digests for DNS Updates). We could expand our cryptolink code to provide TLS support.
|
|
|
|
|
|
Advantages:
|
|
|
+ fully integrated with existing code (no extra processes)
|
|
|
+ no extra dependencies
|
|
|
|
|
|
Flaws:
|
|
|
- may be very complicated to implement (TLS support in C++, maintaining http connection, keep-alives etc.)
|
|
|
- may be difficult to maintain (will we have to update cryptolink every time new openssl or botan comes out?)
|
|
|
|
|
|
### Proposed conclusion
|
|
|
|
|
|
Given the advantages and flaws, it seems that going with python implementation is the easiest way to go. It has small footprint, is easy to develop and provides a growth path, so we could extend its capabilities in the future. However, cryptolink is also an appealing solution, if it's determined not overly complicated.
|
|
|
|
|
|
### Francis' comment
|
|
|
|
|
|
Problem 1 is orthogonal to problem 3: it is about authentication when access control is authorization. Even if authorization makes sense only with authentication they are very different in particular in place to update in the code.
|
|
|
|
|
|
Note the python proposal can provide access control only if it can be fully done by filtering http(s) requests i.e. something like 3.1 or 3.2.
|
|
|
|
|
|
## Problem 2: Code Organization
|
|
|
|
|
|
Access control is useful for some, but not all users. It brings extra complexity that would be considered annoyance for users who doesn't need it. As such, it should be implemented as a hook for CA. There are 3 reasons for that:
|
|
|
|
|
|
- we had hook support in CA, but so far we didn't have good application for it
|
|
|
- access control is definitely a commercial type of feature
|
|
|
- not everyone will want this. We can contain the complexity in a hook, so people who are not interested will simply not use it.
|
|
|
|
|
|
## Problem 3: Provide basic access control
|
|
|
|
|
|
**DEFINING ACCESS ON COMMANDS LEVEL**. At the very least we need to make a distinction between read-only and write commands with some form of access control that would tell if the user is allowed to use RW, RO or no commands at all. The first aspect here is that we'll need to keep the information what kind of access is required to use a command.
|
|
|
|
|
|
### Proposal 3.1: Define regexps in the config file.
|
|
|
|
|
|
One way to define access control would be to use regexps in the config file. The regexp would allow to limit number of entries and make the config more compact:
|
|
|
|
|
|
```javascript
|
|
|
{
|
|
|
"Control-agent": {
|
|
|
"hooks-libraries": [
|
|
|
{
|
|
|
"library": "/opt/local/hookagent-access.so",
|
|
|
"parameters": {
|
|
|
"access-read-only": [
|
|
|
"*-get", "*-get-all", "*-list", ...
|
|
|
],
|
|
|
"access-read-write": [
|
|
|
"*-set", "*-add", "*-del", "*-wipe", "shutdown", ...
|
|
|
]
|
|
|
}
|
|
|
} ],
|
|
|
...
|
|
|
}
|
|
|
```
|
|
|
|
|
|
Advantages:
|
|
|
- compact notation
|
|
|
- extensible (users who develop their own commands can extend it)
|
|
|
- flexible (users could modify the access, e.g. flip a command to require rw access that normally is just ro)
|
|
|
|
|
|
Flaws:
|
|
|
- devs need to remember to review (and update if needed) the list every time a command is added
|
|
|
|
|
|
### Proposal 3.2: Extend JSON files
|
|
|
|
|
|
We could extend JSON files that are currently used to document commands. We would add extra parameter there, e.g. "access".
|
|
|
|
|
|
```javascript
|
|
|
{
|
|
|
"avail": "1.3.0",
|
|
|
"brief": [ "This command creates and adds a new subnet to the existing server configuration." ],
|
|
|
"access": "read-write",
|
|
|
"cmd-syntax": [ ... ],
|
|
|
"description": "See <xref linkend=\"idp69\"/>",
|
|
|
"hook": "subnet_cmds",
|
|
|
"name": "subnet4-add",
|
|
|
"resp-syntax": [ ... ],
|
|
|
"support": [ "kea-dhcp4" ]
|
|
|
}
|
|
|
```
|
|
|
|
|
|
Advantages:
|
|
|
- Trivial to maintain it for new commands
|
|
|
- Reusing already defined structures
|
|
|
- Easy to modify by users (just need to modify a JSON file)
|
|
|
- Easy to use by external devs (just define your own JSON file as you normally would for new commands)
|
|
|
|
|
|
Flaws:
|
|
|
- The data is not confined one place (config file), but two (config file + a directory with JSON files)
|
|
|
- We would need to package JSON commands
|
|
|
|
|
|
### Proposal 3.3: Extend CA and manager command code
|
|
|
|
|
|
The idea is:
|
|
|
- add a boolean parameter to registerCommand methods
|
|
|
- add a new entry in the command JSON map which already has "command" (mandatory), "arguments" (optional but common) and "service" (for extended commands)
|
|
|
- apply the access control in handleCommand method
|
|
|
- add a second port to listen in CA to split between service of read-only commands and service of all commands
|
|
|
|
|
|
Advantages:
|
|
|
- independent of the problem 1: it just assumes that the access to the unrestricted service port is not allowed to everybody who has access to the restricted service port
|
|
|
- fully integrated so easy to configure, package, etc
|
|
|
|
|
|
Flaws:
|
|
|
- require an update of all command hooks and in general all registerCommand callers
|
|
|
- not easy to integrate in a CA hook: at least the CA code must be adapted so there is no **technical** reason to move some part of the code in a hook DSO
|
|
|
- the RO/RW distinction is only the beginning. In the future this will likely evolve towards more complicated model: ACL (access control lists) or RBAC (role-based access control).
|
|
|
|
|
|
## Problem 4: Authentication: How to identify users
|
|
|
|
|
|
We also need to figure out how to identify users or tell who is sending the commands. One way is to do this based on client certificates. Would the be enough? Is it reasonably easy to do?
|
|
|
|
|
|
## Problem 5: Authorization: is user allowed to use command X?
|
|
|
|
|
|
For the time being, we want the authentication to be very simple - each user will belong to one of 3 classes: rw, ro or reject. This list of client certificates mapping to a role should be as simple as possible. We don't expect many users, so it may be a list in a config file.
|
|
|
|
|
|
Here's a proposal coming from a user (see #1263). This is more complex than what we initially assumed to be a simple read or write access.
|
|
|
|
|
|
The list of default roles would look like this:
|
|
|
|
|
|
1. admin role - all RW access, just like it is today.
|
|
|
1. superuser role - RW access to all DHCP API operations with exception of CB config, not even read-only access to things like mysql user/password or server.
|
|
|
1. operator - RW access to lease and HRs manipulative APIs and full read-only access (again, except for CB data).
|
|
|
1. viewer - RO access strictly to DHCP APIs, not CB data.
|
|
|
|
|
|
## Problem 6: REST methods
|
|
|
|
|
|
As of today, all commands are expected to be sent of POST in HTTP. Here's a proposal submitted by a user:
|
|
|
|
|
|
> If KEA control agent had used proper RESTful methods like GET, POST, DELETE, PATCH, PUT, etc., instead of using POST for all kind of operations, it would be possible to restrict access based on the method with something simple like this:
|
|
|
|
|
|
```
|
|
|
limit_except GET {
|
|
|
auth_basic "KEA DHCP";
|
|
|
auth_basic_user_file /etc/kea/.htpasswd;
|
|
|
}
|
|
|
```
|
|
|
|
|
|
> on nginx terminating SSL, for example.
|
|
|
|
|
|
|
|
|
# Proposed solution
|
|
|
|
|
|
Given the aspects discussed above, here's the proposed solution:
|
|
|
|
|
|
A TLS wrapper for CA will be implemented. When enabled, it will provide communication protection using TLS and will also provide access control (see proposal 1.2). Existing JSON files for all current commands will be extended with access-control level on per command basis (see proposal 3.2).
|
|
|
|
|
|
Reference [RBAC-TLS solution](https://gitlab.isc.org/isc-projects/kea/-/wikis/designs/https-wrapper-for-control-agent-solution) |