Using external SSL Trust/Key stores in Spring Boot - java

I have a Spring Boot app which I have deployed on a docker container on Google Compute Engine which uses a TrustStore and KeyStore for TLS. Currently, these p12 files are directly on the /src/main/resources/ path within the jar files. I'd like to externalize them and pull them from Google SecretManager on application load. The application utilizes Undertow.
I have the following settings:
server:
ssl:
enabled: true
trust-store-password: change-me
#trust-store: # to be set programmatically during launch
client-auth: need
#key-store: # to be set programmatically during launch
key-store-type: PKCS12
key-alias: my-alias
key-store-password: change-me
key-password: change-me
trust-store-type: PKCS12
And I'm attempting to do something along the lines of this in order to set the trust-store property.
#Configuration
class SSLStoreConfig {
private final String trustStore = "my-trust-store.p12"
#Autowired
SecretManagerTemplate secretManagerTemplate
#PostConstruct
private void configureSSL() {
byte[] secretBytes = secretManagerTemplate.getSecretBytes("sm://trust-store")
Path filePath = Paths.get(trustStore)
try {
Files.write(filePath, secretBytes)
} catch (IOException e) {
System.out.println("Failed to write bytes" + e.toString())
}
String value = filePath.toAbsolutePath().toString()
System.setProperty("server.ssl.trust-store", value)
}
#PreDestroy
private void removeStores() {
Path filePath = Paths.get(trustStore)
Files.delete(filePath)
}
}
Obviously, this is just for the trust-store. Once I'm able to set this successfully I can add the KeyStore as well.
How can I pull these files from GCP SecretManager and successfully reference them for the server.ssl configuration properties?

Related

Flink Job submission throws java.nio.file.NoSuchFileException while the file actually exists

I tried to submit a flink job that is already packaged in a JAR. Basically it consumes a kafka topic protected by SASL authentication, thus it requires a .jks file which I already include them in JAR and read in the code as:
try(InputStream resourceStream = loader.getResourceAsStream(configFile)){
properties.load(resourceStream);
properties.setProperty("ssl.truststore.location",
loader.getResource(properties.getProperty("ssl.truststore.location")).toURI().getPath());
}
catch(Exception e){
System.out.println("Failed to load config");
}
I tried to submit the job on two different (different VM specs) standalone server for the sake of testing. One server runs succesfully, but another throw a java.nio.file.NoSuchFileException, saying that my .jks file is not found. Can someone please point out the possible issue on it?
Here, the flink is deployed on a standalone cluster mode with the following version:
Flink version: 1.14.0
Java version: 11.0.13
I realize my question was really silly. This part actually returns null and trigger exception.
loader.getResource(properties.getProperty("ssl.truststore.location")).toURI().getPath()
The problem was that I submit the job through web UI thus I couldn't see the printed message. Thus, the filename resolves to the original one stored under the configFile, which is a relative path. Why one machine works and another one doesn't? Cause I previously somehow has the .jks on my homedir for another testing :).
For others to not jump into this mistake, here is the summary of what will .getResource() resolve if run from IDE (gradle run task) and jar, respectively.
// file:home/gradle-demo/build/resources/main/kafka-client.truststore.jks
// jar:file:home/gradle-demo/build/libs/gradle-demo-1.0-SNAPSHOT.jar!/kafka-client.truststore.jks
System.out.println(loader.getResource("kafka-client.trustore.jks").toString());
// home/gradle-demo/build/resources/main/kafka-client.truststore.jks
// file:home/gradle-demo/build/libs/gradle-demo-1.0-SNAPSHOT.jar!/kafka-client.truststore.jks
System.out.println(loader.getResource("kafka-client.trustore.jks").getPath());
// home/gradle-demo/build/resources/main/kafka-client.truststore.jks
// null
System.out.println(loader.getResource("kafka-client.trustore.jks").toURI().getPath());
// file:home/gradle-demo/build/resources/main/kafka-client.truststore.jks
// jar:file:home/gradle-demo/build/libs/gradle-demo-1.0-SNAPSHOT.jar!/kafka-client.truststore.jks
System.out.println(loader.getResource("kafka-client.trustore.jks").toURI());
kafka-client:2.4.1
org.apache.kafka.common.security.ssl.SslEngineBuilder#285
try (InputStream in = Files.newInputStream(Paths.get(path))) {
KeyStore ks = KeyStore.getInstance(type);
// If a password is not set access to the truststore is still available, but integrity checking is disabled.
char[] passwordChars = password != null ? password.value().toCharArray() : null;
ks.load(in, passwordChars);
return ks;
} catch (GeneralSecurityException | IOException e) {
throw new KafkaException("Failed to load SSL keystore " + path + " of type " + type, e);
}
It looks like we should put jks file in file system(nfs or hdfs) where task manager can access by absolute path.

Connect to AWS DocumentDB from Java Program via SSH Tunnel

Has anyone managed to connect a java program to AWS DocumentDB where the java program is running outside of AWS and DocumentDB has tls enabled? Any examples or guidance provided would be greatly appreciated.
This is what I've done so far =>
I've been following AWS's developer guide and I understand to be able to do this I need an SSH tunnel set up to a jump box (EC2 instance) and then to the DB Cluster. I have done this and connected from my laptop.
I have then created the required .jks file from AWS's rds-combined-ca-bundle.pem file and referenced it in a basic java main class. From the java main class I have referenced the cluster as localhost:27017 as this is where I've set up the SSH tunnel from.
My test code is following the AWS example for Java and I get the following error when I run the program =>
Caused by: javax.net.ssl.SSLHandshakeException: No subject alternative DNS name matching localhost found.
public class CertsTestMain {
public static void main(String[] args) {
String template = "mongodb://%s:%s#%s/test?ssl=true&replicaSet=rs0&readpreference=%s";
String username = "dummy";
String password = "dummy";
String clusterEndpoint = "localhost:27017";
String readPreference = "secondaryPreferred";
String connectionString = String.format(template, username, password, clusterEndpoint, readPreference);
String truststore = "C:/Users/eclipse-workspace/certs/certs/rds-truststore.jks";
String truststorePassword = "test!";
System.setProperty("javax.net.ssl.trustStore", truststore);
System.setProperty("javax.net.ssl.trustStorePassword", truststorePassword);
MongoClient mongoClient = MongoClients.create(connectionString);
MongoDatabase testDB = mongoClient.getDatabase("test");
MongoCollection<Document> bookingCollection = testDB.getCollection("booking");
MongoCursor<Document> cursor = bookingCollection.find().iterator();
try {
while (cursor.hasNext()) {
System.out.println(cursor.next().toJson());
}
} finally {
cursor.close();
}
}
}
So, for me, to make this work I only had to alter the template to:
String template = "mongodb://%s:%s#%s/test?sl=true&tlsAllowInvalidHostnames&readpreference=%s";
As long as you have created your .jks file correctly
(I did this simply it by using a linux env and running the script AWS provide for Java in the following link in Point 2 => https://docs.aws.amazon.com/documentdb/latest/developerguide/connect_programmatically.html)
and you have a fully working ssh tunnel as described in https://docs.aws.amazon.com/documentdb/latest/developerguide/connect-from-outside-a-vpc.html
then the above code will work.

The Application Default Credentials are not available with environment variable setup in mac Google Cloud Storage

The Application Default Credentials are not available.
They are available if running in Google Compute Engine.
Otherwise, the environment variable GOOGLE_APPLICATION_CREDENTIALS must be defined pointing to a file defining the credentials
Keep getting the above error instead I have set the environment variable on my local machine with the below command
export GOOGLE_APPLICATION_CREDENTIALS="/Users/macbook/Downloads/fetebird-2b6fa8261292.json"
If I check the path for the environment variable with the below command on terminal it does show the path of the variable
echo $GOOGLE_APPLICATION_CREDENTIALS
On Micronaut application I am trying to create a storage bucket during the startup
#Singleton
public class StartUp implements ApplicationEventListener<StartupEvent> {
private final GoogleCloudStorageService googleCloudStorageService;
public StartUp(GoogleCloudStorageService googleCloudStorageService) {
this.googleCloudStorageService = googleCloudStorageService;
}
#Override
public void onApplicationEvent(StartupEvent event) {
try {
this.googleCloudStorageService.createBucketWithStorageClassAndLocation().subscribe();
} catch (IOException e) {
e.printStackTrace();
}
}
}
On the service
#Singleton
public record GoogleCloudStorageService(GoogleCloudStorageConfiguration googleUploadObjectConfiguration, GoogleCredentialsConfiguration googleCredentialsConfiguration) {
private static final Logger LOG = LoggerFactory.getLogger(GoogleCloudStorageService.class);
public Observable<Void> createBucketWithStorageClassAndLocation() throws IOException {
GoogleCredentials credentials = GoogleCredentials.getApplicationDefault(); // fromStream(new FileInputStream(googleCredentialsConfiguration.getLocation()));
Storage storage = StorageOptions.newBuilder().setCredentials(credentials).setProjectId(googleUploadObjectConfiguration.projectId()).build().getService();
StorageClass storageClass = StorageClass.COLDLINE;
try {
Bucket bucket =
storage.create(
BucketInfo.newBuilder(googleUploadObjectConfiguration.bucketName())
.setStorageClass(storageClass)
.setLocation(googleUploadObjectConfiguration.locationName())
.build());
LOG.info(String.format("Created bucket %s in %s with storage class %s", bucket.getName(), bucket.getLocation(), bucket.getStorageClass()));
} catch (Exception ex) {
LOG.error(ex.getMessage());
}
return Observable.empty();
}
}
The environment variable is NULL while running the application
System.out.println(System.getenv("GOOGLE_APPLICATION_CREDENTIALS"))
The GoogleCredentials credentials = GoogleCredentials.getApplicationDefault(); causing an exception as
java.io.IOException: The Application Default Credentials are not available. They are available if running in Google Compute Engine. Otherwise, the environment variable GOOGLE_APPLICATION_CREDENTIALS must be defined pointing to a file defining the credentials. See https://developers.google.com/accounts/docs/application-default-credentials for more information.
at com.google.auth.oauth2.DefaultCredentialsProvider.getDefaultCredentials(DefaultCredentialsProvider.java:134)
at com.google.auth.oauth2.GoogleCredentials.getApplicationDefault(GoogleCredentials.java:120)
at com.google.auth.oauth2.GoogleCredentials.getApplicationDefault(GoogleCredentials.java:92)
at fete.bird.service.gcp.GoogleCloudStorageService.createBucketWithStorageClassAndLocation(GoogleCloudStorageService.java:24)
at fete.bird.core.StartUp.onApplicationEvent(StartUp.java:24)
at fete.bird.core.StartUp.onApplicationEvent(StartUp.java:11)
at io.micronaut.context.DefaultBeanContext.notifyEventListeners(DefaultBeanContext.java:1307)
at io.micronaut.context.DefaultBeanContext.publishEvent(DefaultBeanContext.java:1292)
at io.micronaut.context.DefaultBeanContext.start(DefaultBeanContext.java:248)
at io.micronaut.context.DefaultApplicationContext.start(DefaultApplicationContext.java:166)
at io.micronaut.runtime.Micronaut.start(Micronaut.java:71)
at io.micronaut.runtime.Micronaut.run(Micronaut.java:311)
at io.micronaut.runtime.Micronaut.run(Micronaut.java:297)
at fete.bird.ServiceApplication.main(ServiceApplication.java:8)
Is it on StartupEvent the micronaut doesn't access the environment variable?
Well I was missing the below instruction
Local development/testing
If running locally for development/testing, you can use the Google Cloud SDK. Create Application Default Credentials with gcloud auth application-default login, and then google-cloud will automatically detect such credentials.
https://github.com/googleapis/google-cloud-java
However, this solution is not perfect, since it is using the OAuth authentication and getting the warning as Your application has authenticated using end user credentials from Google Cloud SDK. We recommend that most server applications use service accounts instead. If your application continues to use end user credentials from Cloud SDK, you might receive a "quota exceeded" or "API not enabled" error. For more information about service accounts.

AmazonClientException: Unable To Load Credentials from any Provider in the Chain

My mule application writes json record to a kinesis stream. I use KPL producer library. When run locally, it picks AWS credentials from .aws/credentials and writes record to kinesis successfully.
However, when I deploy my application to Cloudhub, it throws AmazonClientException, obviously due to not having access to any of directories that DefaultAWSCredentialsProviderChain class supports. (http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/DefaultAWSCredentialsProviderChain.html)
This is how I attach credentials and it looks locally in .aws/credentials:
config.setCredentialsProvider( new
DefaultAWSCredentialsProviderChain());
I couldn't figure out a way to provide credentials explicitly using my-app.properies file.
Then I tried to create a separate configuration file with getters/setters. set access key and private key as private and then impement a getter:
public AWSCredentialsProvider getCredentials() {
if(accessKey == null || secretKey == null) {
return new DefaultAWSCredentialsProviderChain();
}
return new StaticCredentialsProvider(new BasicAWSCredentials(getAccessKey(), getSecretKey()));
}
}
This was intended to be used instead of DefaultAWSCredentialsProviderChain class this way---
config.setCredentialsProvider(new AWSConfig().getCredentials());
Still throws the same error when deployed.
The following repo states that it is possible to provide explicit credentials. I need help to figure out how because I can't find a proper documentation / example.
https://github.com/awslabs/amazon-kinesis-producer/blob/master/java/amazon-kinesis-producer-sample/src/com/amazonaws/services/kinesis/producer/sample/SampleProducer.java
I have Faced the same issue so, I got this solution I hope this will work for you also.
#Value("${s3_accessKey}")
private String s3_accessKey;
#Value("${s3_secretKey}")
private String s3_secretKey;
//this above value I am taking from Application.properties file
BasicAWSCredentials creds = new BasicAWSCredentials(s3_accessKey,
s3_secretKey);
AmazonS3 s3Client = AmazonS3ClientBuilder.standard().
withCredentials(new AWSStaticCredentialsProvider(creds))
.withRegion(Regions.US_EAST_2)
.build();

Subscribing to an Azure Service Bus Topic with Spring Boot and AMQP

I have an Azure Service bus topic set up called "state-changed" and it has a subscription called "reverb". I'm trying to set up a method with #JmsListener to subscribe to the topic but am getting an error:
2017-03-22 18:34:41.049 WARN 23356 --- [enerContainer-6] o.s.j.l.DefaultMessageListenerContainer : Setup of JMS message listener invoker failed for destination 'state-changed' - trying to recover. Cause: The messaging entity 'sb://[MySERVICEBUS].servicebus.windows.net/state-changed' could not be found. TrackingId:d2b442f79e0f44bdb449861ea57155ce_G44, SystemTracker:gateway6, Timestamp:3/22/2017 6:34:37 PM
javax.jms.JMSException: The messaging entity 'sb://[MySERVICEBUS].servicebus.windows.net/state-changed' could not be found. TrackingId:d2b442f79e0f44bdb449861ea57155ce_G44, SystemTracker:gateway6, Timestamp:3/22/2017 6:34:37 PM
at org.apache.qpid.amqp_1_0.jms.impl.TopicSubscriberImpl.createClientReceiver(TopicSubscriberImpl.java:111) ~[qpid-amqp-1-0-client-jms-0.32.jar:0.32]
at org.apache.qpid.amqp_1_0.jms.impl.MessageConsumerImpl.<init>(MessageConsumerImpl.java:129) ~[qpid-amqp-1-0-client-jms-0.32.jar:0.32]
at org.apache.qpid.amqp_1_0.jms.impl.TopicSubscriberImpl.<init>(TopicSubscriberImpl.java:46) ~[qpid-amqp-1-0-client-jms-0.32.jar:0.32]
at org.apache.qpid.amqp_1_0.jms.impl.SessionImpl.createDurableSubscriber(SessionImpl.java:544) ~[qpid-amqp-1-0-client-jms-0.32.jar:0.32]
at org.apache.qpid.amqp_1_0.jms.impl.SessionImpl.createDurableSubscriber(SessionImpl.java:59) ~[qpid-amqp-1-0-client-jms-0.32.jar:0.32]
at org.springframework.jms.listener.AbstractMessageListenerContainer.createConsumer(AbstractMessageListenerContainer.java:870) ~[spring-jms-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.createListenerConsumer(AbstractPollingMessageListenerContainer.java:215) ~[spring-jms-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.initResourcesIfNecessary(DefaultMessageListenerContainer.java:1189) ~[spring-jms-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1165) ~[spring-jms-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1158) ~[spring-jms-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:1055) ~[spring-jms-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at java.lang.Thread.run(Unknown Source) [na:1.8.0_77]
I have been using this blog post to try and get everything up and running: http://ramblingstechnical.blogspot.co.uk/p/using-azure-service-bus-with-spring-jms.html
I can add messages to the topic with JmsTemplate and read messages from it using the plain old Java JMS libraries outlined in the Azure docs: https://learn.microsoft.com/en-us/azure/service-bus-messaging/service-bus-java-how-to-use-jms-api-amqp so I know my topic does work and is accessable, it just seems to be when I configure it with Spring that I'm doing something wrong.
My configuration looks like:
#Configuration
public class JmsConfiguration
{
#Bean
public JmsListenerContainerFactory topicJmsListenerContainerFactory() throws NamingException
{
DefaultJmsListenerContainerFactory returnValue = new DefaultJmsListenerContainerFactory();
Context context = context();
ConnectionFactory cf = connectionFactory(context);
returnValue.setConnectionFactory(cf);
returnValue.setSubscriptionDurable(Boolean.TRUE);
return returnValue;
}
private Context context() throws NamingException
{
Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.qpid.amqp_1_0.jms.jndi.PropertiesFileInitialContextFactory");
env.put(Context.PROVIDER_URL, "src/main/resources/servicebus.properties");
Context context = new InitialContext(env);
return context;
}
/**
* #param context
* #return
* #throws NamingException
*/
private ConnectionFactory connectionFactory(Context context) throws NamingException
{
ConnectionFactory cf = (ConnectionFactory) context.lookup("SBCF");
return cf;
}
}
servicebus.properties (with username and password etc redacted):
# servicebus.properties - sample JNDI configuration
# Register a ConnectionFactory in JNDI using the form:
# connectionfactory.[jndi_name] = [ConnectionURL]
connectionfactory.SBCF=amqps://[USER]:[PASSWORD]#[MYSERVICEBUS]
# Register some queues in JNDI using the form
# queue.[jndi_name] = [physical_name]
# topic.[jndi_name] = [physical_name]
queue.workflow = workflow
topic.state-changed = stage-changed
And finally my listener class:
#Component
public class TestListener
{
Logger logger = LoggerFactory.getLogger(LoggingWorkflowEventHandler.class);
#JmsListener(destination = "state-changed", containerFactory = "topicJmsListenerContainerFactory", subscription = "reverb")
public void onMessage(String message)
{
logger.info("Received message from topic: {}", message);
}
}
If anyone has ever managed to get this working I'd be grateful for some pointers.
Your error message indicates the name of your destination is not found (message entity not found).
Note that you need to tell Azure your Subscription name in a specific way like this:
<TopicName>/Subscriptions/<SubscriptionName>
In your case:
state-changed/Subscriptions/reverb
Hope that helps
Cheers
Seb
If you use Spring Boot you can use prepared Azure ServiceBus JMS Spring Boot Starter where it works out of box.
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-servicebus-jms-spring-boot-starter</artifactId>
<version>2.3.5</version>
</dependency>
See a tutorial page https://learn.microsoft.com/en-us/azure/developer/java/spring-framework/configure-spring-boot-starter-java-app-with-azure-service-bus
Create or change a Trustrore:
As we want to establish a secured amqps connection to the Service Bus, we need to have all required SSL certificates stored in a truststore. As it seems that none of the existing ones contains the required certificates I - for transparency - created a new one like this:
Acquire the needed certificates by visiting https://<URL-Of-Your-Servicebus>, e.g. https://XXXXX.servicebus.cloudapi.de in a browser. Then click on the "lock" in the URL (or whatever your browser shows for a secure connection) and open the certificate from there.
Save the current certificate:
[]
When asked for the format to export, choose "DER binary" and save it as a ".cer" file, e.g. "1.cer"
Most likely you can see that your certificate is based on a certificate chain, which means it depends on other certificates. For each of those click "show certificate":
[]
And save that one in the same way as the one before. Repeat until you reach the root-certificate. In this example you will end up with three *.cer files. For further reference I will call them 1.cer, 2.cer and 3.cer
You should now create a new Truststore file for those certificates
/opt/webMethods9/jvm/jvm/bin/keytool -import -file
/opt/webMethods9/IntegrationServer/instances/default/packages/DEV_fse/resources/1.cer -keystore azureTruststore.jks -alias "D-TRUST Root Class 3 CA 2 2009"
/opt/webMethods9/jvm/jvm/bin/keytool -import -file
/opt/webMethods9/IntegrationServer/instances/default/packages/DEV_fse/resources/2.cer -keystore azureTruststore.jks -alias "D-TRUST SSL Class 3 CA 1 2009"
/opt/webMethods9/jvm/jvm/bin/keytool -import -file
/opt/webMethods9/IntegrationServer/instances/default/packages/DEV_fse/resources/3.cer -keystore azureTruststore.jks -alias "servicebus.cloudapi.de"
You will be asked to set the password for this newly created truststore the first time. Now move the truststore to /opt/webMethods9/IntegrationServer/config/certs/trusted (for later reference). You might add it to IS as a truststore (by using the admin-UI "Security > Keystore " and "Create Truststore Alias"), but there is no technical need to do it, as in our case the IS is not using the truststore - it's only used by QPID.
Create a properties file for JNDI You need to create a servicebus.properties file to act as the data source for a pseudo JNDI Server. You can technically place that file wherever you want, but I would recommend putting it in the "resources" folder of the "XXXXXXConnection" package. This should be the content of that file:
# servicebus.properties - sample JNDI configuration
# Register a ConnectionFactory in JNDI using the form:
# connectionfactory.[jndi_name] = [ConnectionURL]
connectionfactory.SBCF = amqps://XXXXXX.servicebus.cloudapi.de?jms.username=xxxxx&jms.password=xxxxxxx&amqp.idleTimeout=120000&jms.receiveLocalOnly=true&transport.trustStoreLocation=/opt/webMethods9/IntegrationServer/config/certs/trusted/azureTruststore.jks
# Register some queues in JNDI using the form
# queue.[jndi_name] = [physical_name]
# topic.[jndi_name] = [physical_name]
queue.QUEUE = myqueue
​
Some Explanations:​
SBCF will be the JNDI-Lookup name for the connection factory. This name is later needed in your JMS-Connection
xxxxxx.servicebus.cloudapi.de is the URL to your Service Bus
jms.username will be provided by your friendly Azure administrator
jms.password will be provided by your friendly Azure administrator. But be aware that you will need to URL-Encode what you will get from the admin before you can use it in this URL. This can for example be done by calling the IS Service pub.string:URLEncode manually in Designer.​​
amqp.idleTimeout needs to be set to 120000 (or higher) because of otherwise you cannot connect to SB
jms.receiveLocalOnly needs to be set to true because of otherwise you cannot connect to SB
transport.trustStoreLocation needs to point the truststore that contains all SSL Certificates that are required to create a secured (AMQPS) connection to SB
queue.QUEUE: QUEUE is the JNDI-Lookup name you will use later in your JMS-Client to send messages or in your JMS-Trigger to receive them. You should set to a something more meaningful probably. The value of this ("myqueue" in the example) is the name of the queue on the SB and has to be provided by your Azure Admin.
[]
The only two important values are:
"Initial Context Factory": org.apache.qpid.jms.jndi.JmsInitialContextFactory
"Provider URL": Must point to your created servicebus.properties, e.g. file:/opt/webMethods9/IntegrationServer/instances/default/packages/XXXXXXConnection/resources/servicebus.properties

Categories

Resources