Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,10 @@ script:
presto-product-tests/bin/run_on_docker.sh \
singlenode-cassandra -g cassandra
fi
if [[ -v PRODUCT_TESTS_SPECIFIC_ENVIRONMENT ]]; then
presto-product-tests/bin/run_on_docker.sh \
multinode-tls-kerberos -g cli,group-by,join,tls
fi
- |
if [[ -v PRODUCT_TESTS_SPECIFIC_ENVIRONMENT_2 ]]; then
presto-product-tests/bin/run_on_docker.sh \
Expand Down
20 changes: 20 additions & 0 deletions presto-docs/src/main/sphinx/security/internal-communication.rst
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,26 @@ To enable SSL/TLS for Presto internal communication, do the following:
internal-communication.https.keystore.key=<keystore password>


Internal SSL/TLS communication with Kerberos
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

If :doc:`Kerberos</security/server>` authentication is enabled, specify valid Kerberos
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this document _HOST?

credentials for the internal communication, in addition to the SSL/TLS properties.

.. code-block:: none

internal-communication.kerberos.enabled=true

.. note::

The service name and keytab file used for internal Kerberos authentication is
taken from server Kerberos authentication properties, documented in :doc:`Kerberos</security/server>`,
``http.server.authentication.krb5.service-name`` and ``http.server.authentication.krb5.keytab``
respectively. Make sure you have the Kerberos setup done on the worker nodes as well.
The Kerberos principal for internal communication is built from
``http.server.authentication.krb5.service-name`` after appending it with the hostname of
the node where Presto is running on and default realm from Kerberos configuration.

Performance with SSL/TLS enabled
--------------------------------

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,13 @@

public class InternalCommunicationConfig
{
public static final String INTERNAL_COMMUNICATION_KERBEROS_ENABLED = "internal-communication.kerberos.enabled";

private boolean httpsRequired;
private String keyStorePath;
private String keyStorePassword;
private boolean kerberosEnabled;
private boolean kerberosUseCanonicalHostname = true;

public boolean isHttpsRequired()
{
Expand Down Expand Up @@ -58,4 +62,28 @@ public InternalCommunicationConfig setKeyStorePassword(String keyStorePassword)
this.keyStorePassword = keyStorePassword;
return this;
}

public boolean isKerberosEnabled()
{
return kerberosEnabled;
}

@Config(INTERNAL_COMMUNICATION_KERBEROS_ENABLED)
public InternalCommunicationConfig setKerberosEnabled(boolean kerberosEnabled)
{
this.kerberosEnabled = kerberosEnabled;
return this;
}

public boolean isKerberosUseCanonicalHostname()
{
return kerberosUseCanonicalHostname;
}

@Config("internal-communication.kerberos.use-canonical-hostname")
public InternalCommunicationConfig setKerberosUseCanonicalHostname(boolean kerberosUseCanonicalHostname)
{
this.kerberosUseCanonicalHostname = kerberosUseCanonicalHostname;
return this;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.facebook.presto.server;

import com.google.inject.Binder;
import com.google.inject.Module;
import io.airlift.configuration.AbstractConfigurationAwareModule;
import io.airlift.http.client.HttpClientConfig;
import io.airlift.http.client.spnego.KerberosConfig;

import java.io.UncheckedIOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Locale;

import static com.facebook.presto.server.InternalCommunicationConfig.INTERNAL_COMMUNICATION_KERBEROS_ENABLED;
import static com.facebook.presto.server.security.KerberosConfig.HTTP_SERVER_AUTHENTICATION_KRB5_KEYTAB;
import static com.google.common.base.Verify.verify;
import static io.airlift.configuration.ConditionalModule.installModuleIf;
import static io.airlift.configuration.ConfigBinder.configBinder;

public class InternalCommunicationModule
extends AbstractConfigurationAwareModule
{
@Override
protected void setup(Binder binder)
{
InternalCommunicationConfig internalCommunicationConfig = buildConfigObject(InternalCommunicationConfig.class);
configBinder(binder).bindConfigGlobalDefaults(HttpClientConfig.class, config -> {
config.setKeyStorePath(internalCommunicationConfig.getKeyStorePath());
config.setKeyStorePassword(internalCommunicationConfig.getKeyStorePassword());
});

install(installModuleIf(InternalCommunicationConfig.class, InternalCommunicationConfig::isKerberosEnabled, kerberosInternalCommunicationModule()));
}

private Module kerberosInternalCommunicationModule()
{
return binder -> {
InternalCommunicationConfig clientKerberosConfig = buildConfigObject(InternalCommunicationConfig.class);
com.facebook.presto.server.security.KerberosConfig serverKerberosConfig = buildConfigObject(com.facebook.presto.server.security.KerberosConfig.class);
verify(serverKerberosConfig.getKeytab() != null, "%s must be set when %s is true", HTTP_SERVER_AUTHENTICATION_KRB5_KEYTAB, INTERNAL_COMMUNICATION_KERBEROS_ENABLED);

configBinder(binder).bindConfigGlobalDefaults(KerberosConfig.class, kerberosConfig -> {
kerberosConfig.setConfig(serverKerberosConfig.getKerberosConfig());
kerberosConfig.setKeytab(serverKerberosConfig.getKeytab());
kerberosConfig.setUseCanonicalHostname(clientKerberosConfig.isKerberosUseCanonicalHostname());
});

String kerberosPrincipal = serverKerberosConfig.getServiceName() + "/" + getLocalCanonicalHostName();
configBinder(binder).bindConfigGlobalDefaults(HttpClientConfig.class, httpClientConfig -> {
httpClientConfig.setAuthenticationEnabled(true);
httpClientConfig.setKerberosPrincipal(kerberosPrincipal);
httpClientConfig.setKerberosRemoteServiceName(serverKerberosConfig.getServiceName());
});
};
}

private static String getLocalCanonicalHostName()
{
try {
return InetAddress.getLocalHost().getCanonicalHostName().toLowerCase(Locale.US);
}
catch (UnknownHostException e) {
throw new UncheckedIOException(e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,6 @@
import io.airlift.configuration.AbstractConfigurationAwareModule;
import io.airlift.discovery.client.ServiceDescriptor;
import io.airlift.discovery.server.EmbeddedDiscoveryModule;
import io.airlift.http.client.HttpClientConfig;
import io.airlift.slice.Slice;
import io.airlift.stats.GcMonitor;
import io.airlift.stats.JmxGcMonitor;
Expand Down Expand Up @@ -244,11 +243,7 @@ protected void setup(Binder binder)
// TODO: move to CoordinatorModule
install(installModuleIf(EmbeddedDiscoveryConfig.class, EmbeddedDiscoveryConfig::isEnabled, new EmbeddedDiscoveryModule()));

InternalCommunicationConfig internalCommunicationConfig = buildConfigObject(InternalCommunicationConfig.class);
configBinder(binder).bindConfigGlobalDefaults(HttpClientConfig.class, config -> {
config.setKeyStorePath(internalCommunicationConfig.getKeyStorePath());
config.setKeyStorePassword(internalCommunicationConfig.getKeyStorePassword());
});
install(new InternalCommunicationModule());

configBinder(binder).bindConfig(FeaturesConfig.class);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@

public class KerberosConfig
{
public static final String HTTP_SERVER_AUTHENTICATION_KRB5_KEYTAB = "http.server.authentication.krb5.keytab";

private File kerberosConfig;
private String serviceName;
private File keytab;
Expand Down Expand Up @@ -56,7 +58,7 @@ public File getKeytab()
return keytab;
}

@Config("http.server.authentication.krb5.keytab")
@Config(HTTP_SERVER_AUTHENTICATION_KRB5_KEYTAB)
public KerberosConfig setKeytab(File keytab)
{
this.keytab = keytab;
Expand Down
6 changes: 6 additions & 0 deletions presto-product-tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,12 @@ where profile is one of either:
multiple Docker containers. Presto is configured to only accept connections
on the HTTPS port (7878), and both coordinator and worker traffic is encrypted.
For multinode-tls, the default configuration is 1 coordinator and 2 workers.
- **multinode-tls-kerberos** - psuedo-distributed Hadoop installation running on a
single Docker container and a distributed installation of kerberized Presto
running on multiple Docker containers. Presto is configured to only accept
connections on the HTTPS port (7778), and both coordinator and worker traffic
is encrypted and kerberized. For multinode-tls-kerberos, the default configuration
is 1 coordinator and 2 workers.
- **singlenode** - pseudo-distributed Hadoop installation running on a
single Docker container and a single node installation of Presto also running
on a single Docker container.
Expand Down
2 changes: 2 additions & 0 deletions presto-product-tests/bin/run_on_docker.sh
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ if [[ "$ENVIRONMENT" == "multinode" ]]; then
PRESTO_SERVICES="${PRESTO_SERVICES} presto-worker"
elif [[ "$ENVIRONMENT" == "multinode-tls" ]]; then
PRESTO_SERVICES="${PRESTO_SERVICES} presto-worker-1 presto-worker-2"
elif [[ "$ENVIRONMENT" == "multinode-tls-kerberos" ]]; then
PRESTO_SERVICES="${PRESTO_SERVICES} presto-worker-1 presto-worker-2"
fi

# check docker and docker compose installation
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/usr/bin/env bash

SCRIPT_DIRECTORY=${BASH_SOURCE%/*}

source ${SCRIPT_DIRECTORY}/../common/compose-commons.sh

docker-compose \
-f ${SCRIPT_DIRECTORY}/../common/standard.yml \
-f ${SCRIPT_DIRECTORY}/../common/kerberos.yml \
-f ${SCRIPT_DIRECTORY}/docker-compose.yml \
"$@"
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
version: '2'
services:

presto-master:
domainname: docker.cluster
hostname: presto-master
image: '${HADOOP_BASE_IMAGE}-kerberized:${DOCKER_IMAGES_VERSION}'
command: /docker/volumes/conf/docker/files/presto-launcher-wrapper.sh multinode-tls-kerberos-master run
ports:
- '7778:7778'
networks:
default:
aliases:
- presto-master.docker.cluster
volumes:
- ../../../conf/presto/etc/environment-specific-catalogs/singlenode-kerberos-hdfs-no-impersonation/hive.properties:/docker/volumes/conf/presto/etc/catalog/hive.properties
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why no impersonation?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont think there is any specific reason. just chose one of the simple kerberos configs.


presto-worker-1:
domainname: docker.cluster
hostname: presto-worker-1
image: '${HADOOP_BASE_IMAGE}-kerberized:${DOCKER_IMAGES_VERSION}'
extends:
file: ../common/standard.yml
service: java-8-base
command: /docker/volumes/conf/docker/files/presto-launcher-wrapper.sh multinode-tls-kerberos-worker run
networks:
default:
aliases:
- presto-worker-1.docker.cluster
depends_on:
- presto-master
volumes_from:
- presto-master

presto-worker-2:
domainname: docker.cluster
hostname: presto-worker-2
image: '${HADOOP_BASE_IMAGE}-kerberized:${DOCKER_IMAGES_VERSION}'
extends:
file: ../common/standard.yml
service: java-8-base
command: /docker/volumes/conf/docker/files/presto-launcher-wrapper.sh multinode-tls-kerberos-worker run
networks:
default:
aliases:
- presto-worker-2.docker.cluster
depends_on:
- presto-master
volumes_from:
- presto-master

application-runner:
environment:
- TEMPTO_PROFILE_CONFIG_FILE=/docker/volumes/conf/tempto/tempto-configuration-for-docker-kerberos.yaml
- CLI_ARGUMENTS=--server https://presto-master.docker.cluster:7778 --keystore-path /docker/volumes/conf/presto/etc/docker.cluster.jks --keystore-password 123456 --krb5-config-path /etc/krb5.conf --krb5-principal presto-client/presto-master.docker.cluster@LABS.TERADATA.COM --krb5-keytab-path /etc/presto/conf/presto-client.keytab --krb5-remote-service-name presto-server --krb5-disable-remote-service-hostname-canonicalization
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

#
# WARNING
# ^^^^^^^
# This configuration file is for development only and should NOT be used be
# used in production. For example configuration, see the Presto documentation.
#

node.id=will-be-overwritten
node.environment=test
node.internal-address-source=FQDN

coordinator=true
node-scheduler.include-coordinator=true
discovery-server.enabled=true
discovery.uri=https://presto-master.docker.cluster:7778

query.max-memory=1GB
query.max-memory-per-node=512MB

http-server.http.enabled=false
http-server.https.enabled=true
http-server.https.port=7778
http-server.https.keystore.path=/docker/volumes/conf/presto/etc/docker.cluster.jks
http-server.https.keystore.key=123456

http.authentication.krb5.config=/etc/krb5.conf
http-server.authentication.type=KERBEROS
http.server.authentication.krb5.service-name=presto-server
http.server.authentication.krb5.keytab=/etc/presto/conf/presto-server.keytab

internal-communication.https.required=true
internal-communication.https.keystore.path=/docker/volumes/conf/presto/etc/docker.cluster.jks
internal-communication.https.keystore.key=123456

internal-communication.kerberos.enabled=true
internal-communication.kerberos.use-canonical-hostname=false
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

double licence

#

#
# WARNING
# ^^^^^^^
# This configuration file is for development only and should NOT be used be
# used in production. For example configuration, see the Presto documentation.
#

node.id=will-be-overwritten
node.environment=test
node.internal-address-source=FQDN

coordinator=false
discovery-server.enabled=false
discovery.uri=https://presto-master.docker.cluster:7778

query.max-memory=1GB
query.max-memory-per-node=512MB

http-server.http.enabled=false
http-server.https.enabled=true
http-server.https.port=7778
http-server.https.keystore.path=/docker/volumes/conf/presto/etc/docker.cluster.jks
http-server.https.keystore.key=123456

http.authentication.krb5.config=/etc/krb5.conf
http-server.authentication.type=KERBEROS
http.server.authentication.krb5.service-name=presto-server
http.server.authentication.krb5.keytab=/etc/presto/conf/presto-server.keytab

internal-communication.https.required=true
internal-communication.https.keystore.path=/docker/volumes/conf/presto/etc/docker.cluster.jks
internal-communication.https.keystore.key=123456

internal-communication.kerberos.enabled=true
internal-communication.kerberos.use-canonical-hostname=false
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ databases:
presto:
host: presto-master.docker.cluster
port: 7778
http_port: 8080
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it needed? http is disabled

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ya. but we run TLS test group (TlsTests) now in this profile. This property is used there to test if http_port is not actually being used.

https_port: ${databases.presto.port}
server_address: https://${databases.presto.host}:${databases.presto.port}

# jdbc_user in here should satisfy two requirements in order to pass SQL standard access control checks in Presto:
Expand Down