I have spring boot application which connect to my kafka cluster.
Application(as kafka client) uses SASL authentication and I specified JAAS configuration through System.setProperty() before initializing kafka producer and consumer.
It is working fine with single kafka cluster setup.
kafka_client_jaas.conf
KafkaClient {
org.apache.kafka.common.security.plain.PlainLoginModule required
username="myClusterUser"
password="user-secret";
};
MyKafkaProducer.java
…
private void init()
{
System.setProperty("java.security.auth.login.config", "kafka_client_jaas.conf");
…
}
Now I have a third party(someone else’s) kafka cluster which is completely disconnected from my kafka cluster. Third party kafka cluster also uses SASL authentication.
How java application can connect to two different kafka clusters and both clusters required SASL authentication?
Username and password are different for both the clusters and I can set only one JAAS config file in java.security.auth.login.config.
Since Kafka 0.10.2, you can use the sasl.jaas.config setting to configure SASL authentication per Kafka client. This enables running multiple Kafka clients with different (or the same) SASL configurations in a single JVM.
To do so:
Unset java.security.auth.login.config
In each Kafka client properties add sasl.jaas.config. For example:
sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required \
username="myClusterUser" \
password="user-secret";
see http://kafka.apache.org/documentation.html#security_sasl_plain_clientconfig for the full details
MyKafkaClient.java
import org.apache.kafka.common.config.SaslConfigs;
private void init() {
properties.put(SaslConfigs.SASL_JAAS_CONFIG,
"org.apache.kafka.common.security.plain.PlainLoginModule required username=\"myClusterUser\" password=\"user-secret\"");
}
delete your JAAS file
Related
I am trying to connect to a aws msk cluster from spring boot kafka app.
i have aws msk arn ,boot strap server config available.
How to integrate in the application?
Any examples
Can i run it from local,i mean connect to AWS MSK from local app instance
msk cluster
Connection to AWS MSK is like connecting to any Kafka cluster.
It depends on how you had setup your MSK ? (VPC - Subnet)
Check whether you can access from your local or need to be on VPN.
Also see how your brokers endpoints are configured and exposed -
Ex:
Plaintext (broker:9092)
TLS (broker:9094)
If its plaintext, its as simple as setting bootstrap.servers.
Otherwise, you need to add below mentioned properties to access your MSK cluster.
security.protocol: SSL
ssl.truststore.location: jks
ssl.truststore.password: pwd
Please let me know if you still have questions.
If you can connect from kafka-console-* commands (or simpler, kafkacat) then you should be able to connect from any other application.
I suggest you debug using those tools before running anything else.
I have written a number of services that communicate via REST API calls. The services can be configured to use HTTP or HTTPS. Any given client has security configuration that defines the connection to a server. "Default" configuration properties are set by values in application.yml and this has worked well up to this point.
I've come to realize, however, that this does not work for a more realistic situation. The problem is that I'm attempting to set specific arguments, like a server host/port when a client is launched, and the values I'm setting are being ignored.
An example:
Service A (client) will communicate with Service B (server) for some purpose.
Service A has security configuration set up like the following:
#Configuration
#EnableConfigurationProperties({ClientConnectionProperties.class,
SecurityCertificateProperties.class})
public class ClientSecurityConfiguration {
...
}
#ConfigurationProperties("client.connection")
public class ClientConnectionProperties {
...
}
#ConfigurationProperties("server.ssl")
public class SecurityCertificateProperties {
...
}
application.yml has defnitions for the various properties that are assigned to values in the configuration objects.
client:
connection:
scheme: https
host: localhost
port: 8443
server:
port: 7081
ssl:
enabled: true
protocol: TLS
trust-store-type: JKS
trust-store: classpath:server.truststore
trust-store-password: <password>
key-store-type: JKS
key-store: classpath:server.keystore
key-store-password: <password>
This is all well and good when both client and server are running on localhost. However, I'm testing running them where they reside on different hosts, so I need to override client.connection.host from localhost to the actual host. I do this by specifying -Dclient.connection.host=<host> as a VM argument when launching the client. Unfortunately, this does not work. The client ends up trying to connect to localhost and fails (for obvious reasons).
How can I get my override values set into these configuration items? Is there a way to defer or delay the "default" loading so that my values take effect? Is there some other technique to use to get them in there?
You can override Spring Boot properties by using Spring arguments instead of JVM arguments.
Example:
java -jar your-app.jar --client.connection.host=<host>
Related question: https://stackoverflow.com/a/37053004/12355118
I am attempting to setup a Spring Cloud Config Server backed by Spring Cloud Vault secret management. I'm relatively new to Spring but I have tried following instructions and examples here:-
http://cloud.spring.io/spring-cloud-vault-config/
Everything works fine provided you follow the default settings like http, localhost and 8200 for the vault endpoint and tls_disable = 1 to switch off SSL. However these are not practical settings for any real environment and there are few examples anywhere that help with this. Can anyone help with a working example?
I have Successfully set up vault with TLS enable. I have successfully set up a config server that connects using a self signed cert. I can even inject a secret value into the config server and expose it via #Value and #PostConstruct.
All of this is working. However when I try to leverage Spring Conig endpoints to access vault, I get the following:-
{
"timestamp": 1486413850574,
"status": 500,
"error": "Internal Server Error",
"exception": "org.springframework.web.client.ResourceAccessException",
"message": "I/O error on GET request for \"http://127.0.0.1:8200/v1/secret/myapp\": Connection refused: connect; nested exception is java.net.ConnectException: Connection refused: connect",
"path": "/myapp/default"
}
Config server is using default values even though I have set overrides in the bootstrap.yml.:-
server:
port: 8888
spring:
profiles:
active: vault
spring.cloud.vault:
host: myhost.mydomain.com
port: 8200
scheme: https
authentication: TOKEN
token: 0f1887c3-d8a8-befd-a5a2-01e4e066c50
ssl:
trust-store: configTrustStore.jks
trust-store-password: changeit
As you can see it should be pointing to myhost.mydomain.com not
127.0.0.1 and it should be using https, not http as the protocol scheme.
I'm not sure why it uses these defaults for config server endpoints but uses correct settings during spring cloud vault startup. I'm using all the latest stable builds of Spring Dalsten.M1 and Spring Cloud Vault 1.0.0.M1. I realize these are milestone releases. I've also tried Camden and Brixton combos with no luck. I can supply code if required.
Any help greatly appreciated.
As I mention in my response to spensergibb, I have had some success in resolving this myself. Based on his comments I will clarify my intent as it will help with a common understanding of the issue. I am attempting to do two things:-
Stand up a configuration server that uses Vault as a backend, (as opposed to the default GIT backend) and expose the Vault API to client applications (over TLS) so that they can retrieve their own secrets. I do not want all my client applications to connect to Vault directly. I want them to get their configuration from a config server by having the config server connect to Vault. Until last night I was unable to achieve this goal, unless I set everything up as default with TLS disabled and using loopback address, port 8200 for the Vault software etc. Obviously defaults are not practical for any of our deployed environments. I will mention that the link posted by spencergibb does help me understand why this was not working but the subtlety of the reason is why I missed it before. Read on for my explanation.
I want the config server to configure itself from Vault directly. That is, connect to Vault via Spring Cloud Vault Config. This worked right away for me as described in the documentation. However this goal is somewhat trivial as I do not have a real use case at this time. But I wanted to understand if it could be done since I saw no real reason why not and it seemed like good first steps in integrating Vault.
The distinction between these two capabilities helped me understand that the problem derives from the fact that Spring Cloud Config Server and Spring Cloud Vault appear to be using two different beans to inject the Vault configuration properties. Spring Cloud Config Server uses VaultEnvironmentRepository annotated with #ConfigurationProperties("spring.cloud.config.server.vault") and Spring Cloud Vault uses VaultProperties annotated with #ConfigurationProperties("spring.cloud.vault").
This caused me to add two different configs to my bootstrap yml.
server:
port: 8888
spring:
profiles:
active: local, vault
application:
name: quoting-domain-configuration-server
cloud:
vault:
host: VDDP03P-49A26EF.lm.lmig.com
port: 8200
scheme: https
authentication: TOKEN
token: 0f1997c3-d8a8-befd-a5a2-01e4e066c50a
ssl:
trust-store: configTrustStore.jks
trust-store-password: changeit
config:
server:
vault:
host: VDDP03P-49A26EF.lm.lmig.com
port: 8200
scheme: https
authentication: TOKEN
token: 0f1997c3-d8a8-befd-a5a2-01e4e066c50a
Note the same config details. Just different yml paths. This is the subtle point I missed given that I started by getting goal number 1 to work first and assuming the same config would work for both goals. (Note: Token and password are contrived).
This almost worked except for an SSL handshake error. As you can see there are no SSL attributes set on the spring.cloud.config.server.vault path. The VaultProperties bean does not support them. I was not sure how to deal with this (perhaps another non-vault specific bean that I could not find). My solution was to simply force the cert configuration myself like this:-
#SpringBootApplication
#EnableConfigServer
public class Application
{
public static void main(String[] args)
{
System.setProperty("javax.net.ssl.trustStore",
Application.class.getResource("/configTrustStore.jks").getFile());
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
SpringApplication.run(Application.class, args);
}
}
This SSL solution is pretty ugly. I'm sure there must be a better way to do this part. So I am open to other suggestions. However once I completed all above steps everything now works.
Thanks for your write up. I was struggling to get this working. I was able to get a client service to connect to a Spring Cloud Config server and a Vault server but I was not able to get a Spring Cloud Config server to connect to a Vault server.
I even struggled after copying your configuration into my Spring Cloud Config server. While I eventually got it working with your configuration I was able to pare it down quite a bit. The key was that the token does not belong in the Spring Cloud Config server. It belongs in the client.
I was trying http://localhost:8888/{application}/default in the browser but got the following:
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Thu May 11 14:21:31 EDT 2017
There was an unexpected error (type=Bad Request, status=400).
Missing required header: X-Config-Token
I used PostMan to send the request with a X-Config-Token header containing the Vault token and it worked.
Here is my final config.
server:
port: ${PORT:8888}
management:
context-path: /manage
security:
enabled: true
spring:
profiles:
active: git,vault
application:
name: config-server
cloud:
config:
server:
git:
order: 1
uri: file:///temp/config-server/config
vault:
order: 0
host: localhost
port: 8200
scheme: http
So it looks like you need to add the token to the client. Maybe using spring.cloud.config.token.
instead
#SpringBootApplication
#EnableConfigServer
public class Application
{
public static void main(String[] args)
{
System.setProperty("javax.net.ssl.trustStore",
Application.class.getResource("/configTrustStore.jks").getFile());
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
SpringApplication.run(Application.class, args);
}
}
write
bootstrap yml ->
javax.net.ssl.trustStore: /configTrustStore.jks
javax.net.ssl.trustStorePassword: changeit
Although I am answering late. But I was able to configure spring cloud config server to use Vault as backend with CERT authentication via certificates. And moreover you do not require to send X-Config-Token in GET request. So your config-server GET requests will work in the same way it works with GITHUB as backend.As my implementation will get the token on the fly and change the incoming request by appending header. I would recommend to check all the steps in my tutorial and github repo.
Here is my tutorial : https://medium.com/#java.developer.raman/enable-spring-config-server-to-use-cert-authentication-with-vault-as-back-end-ff84e1ef2de7?sk=45a26d7f1277437d91a5cff3d5997287
And GitHub repository: https://github.com/java-developer-raman/config-server-vault-backend
I have an Apache Storm topology hosted on Linux servers with Kerberos security installed.
I wish to submit tests onto this storm topology from my remote windows machine.
I am having difficulty configuring my client to connect with Kerberos Authentication
I am stuck with this exception
SIMPLE authentication is not enabled. Available:[TOKEN, KERBEROS]
I have managed to submit remote MapReduce jobs using this client code
final UserGroupInformation userGroupInformation = UserGroupInformation.createProxyUser(USER_NAME, UserGroupInformation.getCurrentUser());
final AuthenticationMethod authenticationMethod = AuthenticationMethod.KERBEROS;
userGroupInformation.setAuthenticationMethod(authenticationMethod);
userGroupInformation.doAs(new PrivilegedExceptionAction<UserGroupInformation>() {
What is the equivalent configuration for a Storm Topology?
I am trying to install a kafka & zookeeper instance on a remote server. I only need 1 node of each actually because i only want to provide remote kafka for test purposes.
Kafka and Zookeeper are running from the Apache Kafka tarball you can find there (v0.0.9), inside a Docker image.
Trying to consume / produce using the provided scripts. And trying to produce using own java application. Everythinf is working fine if Kafka & ZK are installed on the local server.
Here is the error I get while trying to produce :
BrokerPartitionInfo:83 - Error while fetching metadata [{TopicMetadata for topic RSS ->
No partition metadata for topic RSS due to kafka.common.LeaderNotAvailableException}] for topic [RSS]: class kafka.common.LeaderNotAvailableException
Kafka properties tested
First :
borker.id=0
port=9092
host.name=<external-ip>
zookeeper.connect=localhost:<PORT>
Second:
borker.id=0
port=9092
host.name=<external-ip>
zookeeper.connect=<external-ip>:<PORT>
Third:
borker.id=0
port=9092
host.name=<external-ip>
zookeeper.connect=<external-ip>:<PORT>
advertised.host.name=<external-ip>
advertised.host.port=<external-ip>
Last:
borker.id=0
port=9092
host.name=</etc/host name>
zookeeper.connect=<external-ip>:<PORT>
advertised.host.name=<external-ip>
advertised.host.port=<external-ip>
Here is my "/etc/hosts"
127.0.0.1 kafka kafka
127.0.0.1 localhost
I followed the Getting Started, which if I understood is a localhost / signle server configurations. I cannot understand what I have to do to get this work with remote calls...
Thanks for your help !
EDIT 1
host.name=localhost
advertised.host.name=politik.cm-cloud.fr
Seems to allow a local consumer (on the server) and producer. But if we want to do the same from a remote server we get
[2015-12-09 12:44:10,826] WARN Session 0x0 for server null, unexpected error, closing socket connection and attempting reconnect (org.apache.zookeeper.ClientCnxn)
java.net.NoRouteToHostException: No route to host
The error does not look like connectivity problem with Zookeeper / Kafka.
Just follow the instruction in "quickstart" from http://kafka.apache.org/
BrokerPartitionInfo:83 - Error while fetching metadata [{TopicMetadata for topic RSS ->
Additionally the error indicates there is no partition info i.e topic not yet created . Try creating topics first and then try to produce/consume because when producing to a non existent topic kafka will create the topic based on auto.create.topics.enable in server.properties but remotely it is better to create topics rathen than relying on auto create