DC/OS Confluent Kafka Security
The DC/OS Confluent Kafka service supports Kafka’s native transport encryption, authentication, and authorization mechanisms. The service provides automation and orchestration to simplify the usage of these important features.
A good overview of these features can be found here, and Kafka’s security documentation can be found here.
Transport Encryption
With transport encryption enabled, DC/OS Confluent Kafka will automatically deploy all nodes with the correct configuration to encrypt communication via SSL. The nodes will communicate securely between themselves using SSL.
The service uses the DC/OS CA to generate the SSL artifacts that it uses to secure the service. Any client that trusts the DC/OS CA will consider the service’s certificates valid.
Prerequisites
- A DC/OS Service Account with a secret stored in the DC/OS Secret Store.
- DC/OS Superuser permissions for modifying the permissions of the Service Account.
Configure Transport Encryption
Set up the service account
Grant the service account the correct permissions.
- In DC/OS 1.10, the required permission is
dcos:superuser full
. - In DC/OS 1.11 and later, the required permissions are:
dcos:secrets:default:/<service name>/* full
dcos:secrets:list:default:/<service name> read
dcos:adminrouter:ops:ca:rw full
dcos:adminrouter:ops:ca:ro full
where <service name>
is the name of the service to be installed.
Run the following DC/OS Enterprise CLI commands to set permissions for the service account on a strict cluster:
dcos security org users grant ${SERVICE_ACCOUNT} dcos:mesos:master:task:app_id:<service/name> create
dcos security org users grant ${SERVICE_ACCOUNT} dcos:mesos:master:reservation:principal:dev_hdfs create
dcos security org users grant ${SERVICE_ACCOUNT} dcos:mesos:master:volume:principal:dev_hdfs create
Install the service
Install the DC/OS Confluent Kafka service including the following options in addition to your own:
{
"service": {
"service_account": "<your service account name>",
"service_account_secret": "<full path of service secret>",
"security": {
"transport_encryption": {
"enabled": true, "allow_plaintext": <true|false default false>
}
}
}
}
Verify Transport Encryption Enabled
After service deployment completes, check the list of Kafka endpoints for the endpoint broker-tls
. If service.security.transport_encryption.allow_plaintext
is true
, then the broker
endpoint will also be available.
Transport Encryption for Clients
With Transport Encryption enabled, service clients will need to be configured to use the DC/OS CA bundle to verify the connections they make to the service. Consult your client’s documentation for trusting a CA and configure your client appropriately.
Authentication
DC/OS Confluent Kafka supports two authentication mechanisms, SSL and Kerberos. The two are supported independently and may not be combined. If both SSL and Kerberos authentication are enabled, the service will use Kerberos authentication.
Kerberos Authentication
Kerberos authentication relies on a central authority to verify that Kafka clients (be it broker, consumer, or producer) are who they say they are. DC/OS Confluent Kafka integrates with your existing Kerberos infrastructure to verify the identity of clients.
Prerequisites
- The hostname and port of a KDC reachable from your DC/OS cluster
- Sufficient access to the KDC to create Kerberos principals
- Sufficient access to the KDC to retrieve a keytab for the generated principals
- The DC/OS Enterprise CLI
- DC/OS Superuser permissions
Configure Kerberos Authentication
Create principals
The DC/OS Confluent Kafka service requires a Kerberos principal for each broker to be deployed. Each principal must be of the form
<service primary>/kafka-<broker index>-broker.<service subdomain>.autoip.dcos.thisdcos.directory@<service realm>
with:
service primary = service.security.kerberos.primary
broker index = 0 up to brokers.count - 1
service subdomain = service.name with all
/'s removed
service realm = service.security.kerberos.realm
For example, if installing with these options:
{
"service": {
"name": "a/good/example",
"security": {
"kerberos": {
"primary": "example",
"realm": "EXAMPLE"
}
}
},
"brokers": {
"count": 3
}
}
then the principals to create would be:
example/kafka-0-broker.agoodexample.autoip.dcos.thisdcos.directory@EXAMPLE
example/kafka-1-broker.agoodexample.autoip.dcos.thisdcos.directory@EXAMPLE
example/kafka-2-broker.agoodexample.autoip.dcos.thisdcos.directory@EXAMPLE
Active Directory
Microsoft Active Directory can be used as a Kerberos KDC. Doing so requires creating a mapping between Active Directory users and Kerberos principals.
The utility ktpass can be used to both create a keytab from Active Directory and generate the mapping at the same time.
The mapping can, however, be created manually. For a Kerberos principal like <primary>/<host>@<REALM>
, the Active Directory user should have its servicePrincipalName
and userPrincipalName
attributes set to,
servicePrincipalName = <primary>/<host>
userPrincipalName = <primary>/<host>@<REALM>
For example, with the Kerberos principal example/kafka-0-broker.agoodexample.autoip.dcos.thisdcos.directory@EXAMPLE
, then the correct mapping would be,
servicePrincipalName = example/kafka-0-broker.agoodexample.autoip.dcos.thisdcos.directory
userPrincipalName = example/kafka-0-broker.agoodexample.autoip.dcos.thisdcos.directory@EXAMPLE
If either mapping is incorrect or not present, the service will fail to authenticate that Principal. The symptom in the Kerberos debug logs will be an error of the form
KRBError:
sTime is Wed Feb 07 03:22:47 UTC 2018 1517973767000
suSec is 697984
error code is 6
error Message is Client not found in Kerberos database
sname is krbtgt/AD.MESOSPHERE.COM@AD.MESOSPHERE.COM
msgType is 30
when the userPrincipalName
is set incorrectly, and an error of the form
KRBError:
sTime is Wed Feb 07 03:44:57 UTC 2018 1517975097000
suSec is 128465
error code is 7
error Message is Server not found in Kerberos database
sname is kafka/kafka-1-broker.confluent-kafka.autoip.dcos.thisdcos.directory@AD.MESOSPHERE.COM
msgType is 30
when the servicePrincipalName
is set incorrectly.
Place Service Keytab in DC/OS Secret Store
The DC/OS Confluent Kafka service uses a keytab containing all node principals (service keytab). After creating the principals above, generate the service keytab making sure to include all the node principals. This will be stored as a secret in the DC/OS Secret Store.
The service keytab should be stored at service/path/name/service.keytab
. As noted above. for DC/OS 1.10, it would be __dcos_base64__service.keytab
), where service/path/name
matches the path and name of the service. For example, if installing with the options
{
"service": {
"name": "a/good/example"
}
}
then the service keytab should be stored at a/good/example/service.keytab
.
Documentation for adding a file to the secret store can be found here.
Install the Service
Install the DC/OS Confluent Kafka service with the following options in addition to your own:
{
"service": {
"security": {
"kerberos": {
"enabled": true,
"enabled_for_zookeeper": <true|false default false>,
"kdc": {
"hostname": "<kdc host>",
"port": <kdc port>
},
"primary": "<service primary default kafka>",
"realm": "<realm>",
"keytab_secret": "<path to keytab secret>",
"debug": <true|false default false>
}
}
}
}
{
"kafka": {
"kafka_zookeeper_uri": <list of zookeeper hosts>
}
}
The DC/OS Confluent Zookeeper service (confluent-zookeeper
package) is intended for this purpose and supports Kerberos.
It is possible to enable Kerberos after initial installation but the service may be unavailable during the transition. Additionally, your Kafka clients will need to be reconfigured.
SSL Authentication
SSL authentication requires that all clients be they brokers, producers, or consumers present a valid certificate from which their identity can be derived. DC/OS Confluent Kafka uses the CN
of the SSL certificate as the principal for a given client. For example, from the certificate CN=bob@example.com,OU=,O=Example,L=London,ST=London,C=GB
the principal bob@example.com
will be extracted.
Prerequisites
- Completion of the section Transport Encryption above
Install the Service
Install the DC/OS Confluent Kafka service with the following options in addition to your own:
{
"service": {
"service_account": "<service-account>",
"service_account_secret": "<secret path>",
"security": {
"transport_encryption": {
"enabled": true
},
"ssl_authentication": {
"enabled": true
}
}
}
}
It is possible to enable SSL authentication after initial installation, but the service may be unavailable during the transition. Additionally, your Kafka clients will need to be reconfigured.
Authenticating a Client
To authenticate a client against DC/OS Confluent Kafka, you will need to configure it to use a certificate signed by the DC/OS CA. After generating a certificate signing request, you can issue it to the DC/OS CA by calling the API <dcos-cluster>/ca/api/v2/sign
. Using curl
the request would look like:
$ curl -X POST \
-H "Authorization: token=$(dcos config show core.dcos_acs_token)" \
<dcos-cluster>/ca/api/v2/sign \
-d '{"certificate_request": "<json-encoded-value-of-request.csr>"}'
The response will contain a signed public certificate. Full details on the DC/OS CA API can be found here.
Authorization
The DC/OS Confluent Kafka service supports Kafka’s ACL-based authorization system. To use Kafka’s ACLs, either SSL or Kerberos authentication must be enabled as detailed above.
Enable Authorization
Prerequisites
Install the Service
Install the DC/OS Confluent Kafka service with the following options in addition to your own (remember, either SSL authentication or Kerberos must be enabled):
{
"service": {
"security": {
"authorization": {
"enabled": true,
"super_users": "<list of super users>",
"allow_everyone_if_no_acl_found": <true|false default false>
}
}
}
}
service.security.authorization.super_users
should be set to a semi-colon delimited list of principals to treat as super users (all permissions). The format of the list is User:<user1>;User:<user2>;...
. Using Kerberos authentication, the “user” value is the Kerberos primary, and for SSL authentication the “user” value is the CN
of the certificate. The Kafka brokers themselves are automatically designated as super users.
Securely Exposing DC/OS Confluent Kafka Outside the Cluster.
Both transport encryption and Kerberos are tightly coupled to the DNS hosts of the Kafka brokers. As such, exposing a secure Confluent Kafka service outside of the cluster requires additional setup.
Broker to Client Connection
To expose a secure Confluent Kafka service outside of the cluster, any client connecting to it must be able to access all brokers of the service via the IP address assigned to the broker. This IP address will be one of: an IP address on a virtual network or the IP address of the agent the broker is running on.
Forwarding DNS and Custom Domain
Every DC/OS cluster has a unique cryptographic ID which can be used to forward DNS queries to that Cluster. To securely expose the service outside the cluster, external clients must have an upstream resolver configured to forward DNS queries to the DC/OS cluster of the service as described here.
With only forwarding configured, DNS entries within the DC/OS cluster will be resolvable at <task-domain>.autoip.dcos.<cryptographic-id>.dcos.directory
. However, if you configure a DNS alias, you can use a custom domain. For example, <task-domain>.cluster-1.acmeco.net
. In either case, the DC/OS Confluent Kafka service will need to be installed with an additional security option:
{
"service": {
"security": {
"custom_domain": "<custom-domain>"
}
}
}
where <custom-domain>
is one of autoip.dcos.<cryptographic-id>.dcos.directory
or your organization specific domain (e.g., cluster-1.acmeco.net
).
As a concrete example, using the custom domain of cluster-1.acmeco.net
the broker 0 task would have a host of kafka-0-broker.<service-name>.cluster-1.acmeco.net
.
Kerberos Principal Changes
Transport encryption alone does not require any additional changes. Endpoint discovery will work as normal, and clients will be able to connect securely with the custom domain as long as they are configured as described here.
Kerberos, however, does require slightly different configuration. As noted in the section Create Principals, the principals of the service depend on the hostname of the service. When creating the Kerberos principals, be sure to use the correct domain.
For example, if installing with these settings:
{
"service": {
"name": "a/good/example",
"security": {
"custom_domain": "cluster-1.example.net",
"kerberos": {
"primary": "example",
"realm": "EXAMPLE"
}
}
},
"brokers": {
"count": 3
}
}
then the principals to create would be:
example/kafka-0-broker.agoodexample.cluster-1.example.net@EXAMPLE
example/kafka-1-broker.agoodexample.cluster-1.example.net@EXAMPLE
example/kafka-2-broker.agoodexample.cluster-1.example.net@EXAMPLE