7

Running into issues when trying to use kerberos auth with connecting to Kafka. Using scala and my jaas.config looks something like this.

 KafkaClient { 
        com.sun.security.auth.module.Krb5LoginModule required
        useKeyTab=true
        keyTab="/etc/security/keytabs/storm.service.keytab"
        storeKey=true
        useTicketCache=false
        serviceName="kafka"
        principal="storm@EXAMPLE.COM";
        debug=true
        client=true; };

Exception in thread "main" org.apache.kafka.common.KafkaException: Failed to construct kafka consumer  
    at org.apache.kafka.clients.consumer.KafkaConsumer.<init>(KafkaConsumer.java:799)  
    at org.apache.kafka.clients.consumer.KafkaConsumer.<init>(KafkaConsumer.java:615)  
    at org.apache.kafka.clients.consumer.KafkaConsumer.<init>(KafkaConsumer.java:596)  
    at org.apache.spark.sql.kafka010.SubscribeStrategy.createConsumer(ConsumerStrategy.scala:62)  
    at org.apache.spark.sql.kafka010.KafkaOffsetReader.createConsumer(KafkaOffsetReader.scala:314)  
    at org.apache.spark.sql.kafka010.KafkaOffsetReader.<init>(KafkaOffsetReader.scala:78)  
    at
 org.apache.spark.sql.kafka010.KafkaSourceProvider.createContinuousReader(KafkaSourceProvider.scala:130)
at org.apache.spark.sql.kafka010.KafkaSourceProvider.createContinuousReader(KafkaSourceProvider.scala:43)  
    at org.apache.spark.sql.streaming.DataStreamReader.load(DataStreamReader.scala:185)
    at com.gm.SparkDataIngest.Main$.main(Main.scala:119)
    at com.gm.SparkDataIngest.Main.main(Main.scala)  

Caused by: java.lang.IllegalArgumentException: Login module control flag is not available in the JAAS config  
    at org.apache.kafka.common.security.JaasConfig.loginModuleControlFlag(JaasConfig.java:85)
    at org.apache.kafka.common.security.JaasConfig.parseAppConfigurationEntry(JaasConfig.java:111)
    at org.apache.kafka.common.security.JaasConfig.<init>(JaasConfig.java:63)
    at org.apache.kafka.common.security.JaasContext.load(JaasContext.java:148)
    at org.apache.kafka.common.security.JaasContext.loadClientContext(JaasContext.java:142)
    at org.apache.kafka.common.network.ChannelBuilders.create(ChannelBuilders.java:119)
    at org.apache.kafka.common.network.ChannelBuilders.clientChannelBuilder(ChannelBuilders.java:65)
    at org.apache.kafka.clients.ClientUtils.createChannelBuilder(ClientUtils.java:88)
    at org.apache.kafka.clients.consumer.KafkaConsumer.<init>(KafkaConsumer.java:713)
Prakash K
  • 11,669
  • 6
  • 51
  • 109
Jordan Cheeks
  • 103
  • 1
  • 1
  • 9

3 Answers3

3

If your JAAS config is indeed what you have shown, then you have a syntax error -- specifically, an extra semicolon ; that makes the parser fail because it finds a 2nd config entry that does not make sense.

The JAAS config should be either simple (and note where the semicolons are)...

Blurb {
  some.login.module.class status
  option1=value1
  option2="value2"
  ;
};

...or complex (and now you understand what the semicolons imply...

Blurb {
  some.login.module.class status
  option1=value1
  option2="value2"
  ;
  other.login.module.class status
  option3=value3
  ;
};
DahDah {
  some.login.module.class status
  option1=value99
  option2="value88"
  ;
};


By the way, you can switch the JAAS configuration parser in debug mode by setting -Djava.security.debug=configparser

Personally I always use the combo -Dsun.security.krb5.debug=true -Djava.security.debug=gssloginconfig,configfile,configparser,logincontext when troubleshooting Kerberos issues.

Samson Scharfrichter
  • 8,884
  • 1
  • 17
  • 36
1

You should take care of how to construct client properties. Exactly in "sasl.jaas.config". So jaasCfg, this variable must have correct string interpolation. here an example where it works.

val jaasTemplate = "org.apache.kafka.common.security.scram.ScramLoginModule required username=\"%s\" password=\"%s\";"
val jaasCfg = String.format(jaasTemplate, username, password)


val producerProperties: Properties = {
  val props = new Properties()      
  props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "pkc-cloud:9092")
  props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, classOf[StringSerializer].getName)
  props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, classOf[KafkaAvroSerializer].getName)
  props.put(SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG, "")
  props.put("schema.registry.url", "https://domain.cloud")
  props.put("auto.register.schemas", false: java.lang.Boolean)
  props.put("use.latest.version", true: java.lang.Boolean)
  props.put("schemas.enable", false: java.lang.Boolean)
  props.put("security.protocol", "SASL_SSL")
  props.put("sasl.mechanism", "PLAIN")
  props.put("sasl.jaas.config", jaasCfg)
  props.put("client.dns.lookup", "use_all_dns_ips")
  props.put("basic.auth.credentials.source", "USER_INFO")
  props.put("basic.auth.user.info", "RJRRQegE/oOb/R87vq5ySNLm8GPSaaRYBe")
  props
}

However, it does not work in spite of showing the same string result when you print it in the console.

val ssalconfig = """org.apache.kafka.common.security.plain.PlainLoginModule REQUIRED username="3C" password="HM2XF8mCx8bohymoN7O7mRTA";"""
-1

I think the issue might be caused because of not supplying JAAS conf as it is mentioned in the stack trace. The ways to provide JAAS configurations are:

  • Via the client property: sasl.jaas.config
  • Via the Java property: java.security.auth.login.config

For further reference refer to cloudera blog or confulent blog or question.

Let me know if it helps!!

Anand Sai
  • 1,566
  • 7
  • 11