Skip to content

Commit

Permalink
Allow configuring credential-cache for kerberized hive connector
Browse files Browse the repository at this point in the history
  • Loading branch information
Praveen2112 committed Aug 29, 2022
1 parent 5b9d874 commit 5120f3f
Show file tree
Hide file tree
Showing 24 changed files with 609 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,10 @@ public void configure(Binder binder)
HadoopAuthentication createHadoopAuthentication(HdfsKerberosConfig config, HdfsConfigurationInitializer updater)
{
String principal = config.getHdfsTrinoPrincipal();
String keytabLocation = config.getHdfsTrinoKeytab();
KerberosConfiguration.Builder builder = new KerberosConfiguration.Builder()
.withKerberosPrincipal(principal)
.withKeytabLocation(keytabLocation);
.withKerberosPrincipal(principal);
config.getHdfsTrinoKeytab().ifPresent(builder::withKeytabLocation);
config.getHdfsTrinoCredentialCacheLocation().ifPresent(builder::withCredentialCacheLocation);
return createCachingKerberosHadoopAuthentication(builder.build(), updater);
}
};
Expand Down Expand Up @@ -103,10 +103,10 @@ public void configure(Binder binder)
HadoopAuthentication createHadoopAuthentication(HdfsKerberosConfig config, HdfsConfigurationInitializer updater)
{
String principal = config.getHdfsTrinoPrincipal();
String keytabLocation = config.getHdfsTrinoKeytab();
KerberosConfiguration.Builder builder = new KerberosConfiguration.Builder()
.withKerberosPrincipal(principal)
.withKeytabLocation(keytabLocation);
.withKerberosPrincipal(principal);
config.getHdfsTrinoKeytab().ifPresent(builder::withKeytabLocation);
config.getHdfsTrinoCredentialCacheLocation().ifPresent(builder::withCredentialCacheLocation);
return createCachingKerberosHadoopAuthentication(builder.build(), updater);
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,16 @@
import io.airlift.configuration.LegacyConfig;
import io.airlift.configuration.validation.FileExists;

import javax.validation.constraints.AssertTrue;
import javax.validation.constraints.NotNull;

import java.util.Optional;

public class HdfsKerberosConfig
{
private String hdfsTrinoPrincipal;
private String hdfsTrinoKeytab;
private String hdfsTrinoCredentialCacheLocation;

@NotNull
public String getHdfsTrinoPrincipal()
Expand All @@ -41,10 +45,9 @@ public HdfsKerberosConfig setHdfsTrinoPrincipal(String hdfsTrinoPrincipal)
}

@NotNull
@FileExists
public String getHdfsTrinoKeytab()
public Optional<@FileExists String> getHdfsTrinoKeytab()
{
return hdfsTrinoKeytab;
return Optional.ofNullable(hdfsTrinoKeytab);
}

@Config("hive.hdfs.trino.keytab")
Expand All @@ -55,4 +58,24 @@ public HdfsKerberosConfig setHdfsTrinoKeytab(String hdfsTrinoKeytab)
this.hdfsTrinoKeytab = hdfsTrinoKeytab;
return this;
}

@NotNull
public Optional<@FileExists String> getHdfsTrinoCredentialCacheLocation()
{
return Optional.ofNullable(hdfsTrinoCredentialCacheLocation);
}

@Config("hive.hdfs.trino.credential-cache.location")
@ConfigDescription("Trino credential-cache location used to access HDFS")
public HdfsKerberosConfig setHdfsTrinoCredentialCacheLocation(String hdfsTrinoCredentialCacheLocation)
{
this.hdfsTrinoCredentialCacheLocation = hdfsTrinoCredentialCacheLocation;
return this;
}

@AssertTrue(message = "Exactly one of `hive.hdfs.trino.keytab` or `hive.hdfs.trino.credential-cache.location` must be specified")
public boolean isConfigValid()
{
return getHdfsTrinoKeytab().isPresent() ^ getHdfsTrinoCredentialCacheLocation().isPresent();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,19 @@
package io.trino.hdfs.authentication;

import com.google.common.collect.ImmutableMap;
import io.airlift.configuration.ConfigurationFactory;
import org.testng.annotations.Test;

import java.io.IOException;
import javax.validation.constraints.AssertTrue;

import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Map;

import static io.airlift.configuration.testing.ConfigAssertions.assertFullMapping;
import static io.airlift.configuration.testing.ConfigAssertions.assertRecordedDefaults;
import static io.airlift.configuration.testing.ConfigAssertions.recordDefaults;
import static io.airlift.testing.ValidationAssertions.assertFailsValidation;
import static org.assertj.core.api.Assertions.assertThat;

public class TestHdfsKerberosConfig
{
Expand All @@ -32,12 +35,13 @@ public void testDefaults()
{
assertRecordedDefaults(recordDefaults(HdfsKerberosConfig.class)
.setHdfsTrinoPrincipal(null)
.setHdfsTrinoKeytab(null));
.setHdfsTrinoKeytab(null)
.setHdfsTrinoCredentialCacheLocation(null));
}

@Test
public void testExplicitPropertyMappings()
throws IOException
public void testExplicitPropertyMappingsForKeytab()
throws Exception
{
Path keytab = Files.createTempFile(null, null);

Expand All @@ -46,10 +50,64 @@ public void testExplicitPropertyMappings()
.put("hive.hdfs.trino.keytab", keytab.toString())
.buildOrThrow();

ConfigurationFactory configurationFactory = new ConfigurationFactory(properties);
HdfsKerberosConfig config = configurationFactory.build(HdfsKerberosConfig.class);

HdfsKerberosConfig expected = new HdfsKerberosConfig()
.setHdfsTrinoPrincipal("[email protected]")
.setHdfsTrinoKeytab(keytab.toString());

assertFullMapping(properties, expected);
assertThat(config.getHdfsTrinoPrincipal())
.isEqualTo(expected.getHdfsTrinoPrincipal());
assertThat(config.getHdfsTrinoKeytab())
.isEqualTo(expected.getHdfsTrinoKeytab());
}

@Test
public void testExplicitPropertyMappingsForCredentialCache()
throws Exception
{
Path credentialCacheLocation = Files.createTempFile("credentialCache", null);

Map<String, String> properties = ImmutableMap.<String, String>builder()
.put("hive.hdfs.trino.principal", "[email protected]")
.put("hive.hdfs.trino.credential-cache.location", credentialCacheLocation.toString())
.buildOrThrow();

ConfigurationFactory configurationFactory = new ConfigurationFactory(properties);
HdfsKerberosConfig config = configurationFactory.build(HdfsKerberosConfig.class);

HdfsKerberosConfig expected = new HdfsKerberosConfig()
.setHdfsTrinoPrincipal("[email protected]")
.setHdfsTrinoCredentialCacheLocation(credentialCacheLocation.toString());

assertThat(config.getHdfsTrinoPrincipal())
.isEqualTo(expected.getHdfsTrinoPrincipal());
assertThat(config.getHdfsTrinoCredentialCacheLocation())
.isEqualTo(expected.getHdfsTrinoCredentialCacheLocation());
}

@Test
public void testValidation()
throws Exception
{
assertFailsValidation(
new HdfsKerberosConfig()
.setHdfsTrinoPrincipal("[email protected]"),
"configValid",
"Exactly one of `hive.hdfs.trino.keytab` or `hive.hdfs.trino.credential-cache.location` must be specified",
AssertTrue.class);

Path keytab = Files.createTempFile(null, null);
Path credentialCacheLocation = Files.createTempFile("credentialCache", null);

assertFailsValidation(
new HdfsKerberosConfig()
.setHdfsTrinoPrincipal("[email protected]")
.setHdfsTrinoKeytab(keytab.toString())
.setHdfsTrinoCredentialCacheLocation(credentialCacheLocation.toString()),
"configValid",
"Exactly one of `hive.hdfs.trino.keytab` or `hive.hdfs.trino.credential-cache.location` must be specified",
AssertTrue.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ public static class Builder
{
private KerberosPrincipal kerberosPrincipal;
private Optional<String> keytabLocation = Optional.empty();
private Optional<String> credentialCacheLocation = Optional.empty();

public Builder withKerberosPrincipal(String kerberosPrincipal)
{
Expand All @@ -90,19 +91,34 @@ public Builder withKeytabLocation(String keytabLocation)
return this;
}

public Builder withCredentialCacheLocation(String credentialCacheLocation)
{
verifyFile(credentialCacheLocation);
this.credentialCacheLocation = Optional.of(credentialCacheLocation);
return this;
}

public KerberosConfiguration build()
{
ImmutableMap.Builder<String, String> optionsBuilder = ImmutableMap.<String, String>builder()
.put("doNotPrompt", "true")
.put("isInitiator", "true")
.put("principal", kerberosPrincipal.getName());

checkArgument(keytabLocation.isPresent() ^ credentialCacheLocation.isPresent(), "Either keytab or credential cache must be specified");

keytabLocation.ifPresent(
keytab -> optionsBuilder
.put("storeKey", "true")
.put("useKeyTab", "true")
.put("storeKey", "true")
.put("keyTab", keytab));

credentialCacheLocation.ifPresent(
credentialCache -> optionsBuilder
.put("useTicketCache", "true")
.put("renewTGT", "true")
.put("ticketCache", credentialCache));

return new KerberosConfiguration(kerberosPrincipal, optionsBuilder.buildOrThrow());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,17 @@
import io.airlift.configuration.ConfigDescription;
import io.airlift.configuration.validation.FileExists;

import javax.validation.constraints.AssertTrue;
import javax.validation.constraints.NotNull;

import java.util.Optional;

public class MetastoreKerberosConfig
{
private String hiveMetastoreServicePrincipal;
private String hiveMetastoreClientPrincipal;
private String hiveMetastoreClientKeytab;
private String hiveMetastoreCredentialCachePath;

@NotNull
public String getHiveMetastoreServicePrincipal()
Expand Down Expand Up @@ -54,10 +58,9 @@ public MetastoreKerberosConfig setHiveMetastoreClientPrincipal(String hiveMetast
}

@NotNull
@FileExists
public String getHiveMetastoreClientKeytab()
public Optional<@FileExists String> getHiveMetastoreClientKeytab()
{
return hiveMetastoreClientKeytab;
return Optional.ofNullable(hiveMetastoreClientKeytab);
}

@Config("hive.metastore.client.keytab")
Expand All @@ -67,4 +70,24 @@ public MetastoreKerberosConfig setHiveMetastoreClientKeytab(String hiveMetastore
this.hiveMetastoreClientKeytab = hiveMetastoreClientKeytab;
return this;
}

@NotNull
public Optional<@FileExists String> getHiveMetastoreClientCredentialCacheLocation()
{
return Optional.ofNullable(hiveMetastoreCredentialCachePath);
}

@Config("hive.metastore.client.credential-cache.location")
@ConfigDescription("Hive Metastore client credential cache location")
public MetastoreKerberosConfig setHiveMetastoreClientCredentialCacheLocation(String hiveMetastoreCredentialCachePath)
{
this.hiveMetastoreCredentialCachePath = hiveMetastoreCredentialCachePath;
return this;
}

@AssertTrue(message = "Exactly one of `hive.metastore.client.keytab` or `hive.metastore.client.credential-cache.location` must be specified")
public boolean isConfigValid()
{
return getHiveMetastoreClientKeytab().isPresent() ^ getHiveMetastoreClientCredentialCacheLocation().isPresent();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,10 @@ public void configure(Binder binder)
public HadoopAuthentication createHadoopAuthentication(MetastoreKerberosConfig config, HdfsConfigurationInitializer updater)
{
String principal = config.getHiveMetastoreClientPrincipal();
String keytabLocation = config.getHiveMetastoreClientKeytab();
KerberosConfiguration.Builder builder = new KerberosConfiguration.Builder()
.withKerberosPrincipal(principal)
.withKeytabLocation(keytabLocation);
.withKerberosPrincipal(principal);
config.getHiveMetastoreClientKeytab().ifPresent(builder::withKeytabLocation);
config.getHiveMetastoreClientCredentialCacheLocation().ifPresent(builder::withCredentialCacheLocation);
return createCachingKerberosHadoopAuthentication(builder.build(), updater);
}
}
Expand Down
Loading

0 comments on commit 5120f3f

Please sign in to comment.