golang solance API for certificate based authentication

Hi,
I followed Configuring an Event Broker Service to use Client Certificate Authentication and set up the solace system to allow and accept certificate based authentication.
But so far I wasn’t able to get it running with golang.
Could someone indicate how to change the code from golang example to read from queue via solace golang API — Solace Community >
`package main

import (
“flag”
log “GitHub - sirupsen/logrus: Structured, pluggable logging for Go.
“os”
“os/signal”
“solace.dev/go/messaging”
“solace.dev/go/messaging/pkg/solace”
“solace.dev/go/messaging/pkg/solace/config”
“solace.dev/go/messaging/pkg/solace/message”
“solace.dev/go/messaging/pkg/solace/resource”
“time”
)
var (
logLevel = flag.Int(“logLevel”, 4, “log level (0-6)”)
logReportCaller = flag.Bool(“logReportCaller”, false, “add caller to log output”)
logFormatJson = flag.Bool(“logFormatJson”, true, “log in json format”)
)
func init() {
flag.Parse()
log.SetLevel(log.Level(*logLevel))
log.SetReportCaller(*logReportCaller)
log.SetFormatter(&log.TextFormatter{})
if *logFormatJson {
log.SetFormatter(&log.JSONFormatter{})
}
}
func getEnv(key string) string {
if val, ok := os.LookupEnv(key); ok {
return val
} else {
log.Info(“Missing environment variable “, key)
os.Exit(8)
}
return “”
}
// Message Handler
func MessageHandler(message message.InboundMessage) {
log.Debug(“Message Dump %s \n”, message)
payload, ok := message.GetPayloadAsBytes()
if ok {
log.Info(string(payload))
persistentReceiver.Ack(message)
}
log.Info(””)
}
var persistentReceiver solace.PersistentMessageReceiver
func main() {
// Configuration parameters
brokerConfig := config.ServicePropertyMap{
config.TransportLayerPropertyHost: getEnv(“SOLACE_HOST”),
config.ServicePropertyVPNName: getEnv(“SOLACE_VPN”),
config.AuthenticationPropertySchemeBasicUserName: getEnv(“SOLACE_USER”),
config.AuthenticationPropertySchemeBasicPassword: getEnv(“SOLACE_PASSWORD”),
}
messagingService, err := messaging.NewMessagingServiceBuilder().
FromConfigurationProvider(brokerConfig).
WithTransportSecurityStrategy(config.NewTransportSecurityStrategy().WithoutCertificateValidation()).
Build()
if err != nil {
panic(err)
}
// Connect to the messaging serice
if err := messagingService.Connect(); err != nil {
panic(err)
}
log.Info("Connected to the broker? ", messagingService.IsConnected())
queueName := getEnv(“AEM_QUEUE”)
durableNonExclusiveQueue := resource.QueueDurableNonExclusive(queueName)
//nonDurableExclusiveQueue := resource.QueueNonDurableExclusive(queueName)
// Build a Guaranteed message receiver and bind to the given queue
persistentReceiver, err = messagingService.CreatePersistentMessageReceiverBuilder().WithMessageClientAcknowledgement().Build(durableNonExclusiveQueue)
log.Info(“Bound to queue: %s”, queueName)
// Handling a panic from a non existing queue
defer func() {
if err := recover(); err != nil {
log.Printf(“Make sure queue name ‘%s’ exists on the broker.\nThe following error occurred when attempting to connect to create a Persistent Message Receiver:\n%s”, queueName, err)
}
}()
// Start Persistent Message Receiver
if err := persistentReceiver.Start(); err != nil {
panic(err)
}
log.Info("Persistent Receiver running? “, persistentReceiver.IsRunning())
if regErr := persistentReceiver.ReceiveAsync(MessageHandler); regErr != nil {
panic(regErr)
}
// Handle interrupts
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
// Block until a signal is received.
<-c
// TODO
// Find way to shutdown the go routine
// e.g use another channel, BOOl…etc
// TODO
// Terminate the Persistent Receiver
persistentReceiver.Terminate(2 * time.Second)
log.Info(”\nDirect Receiver Terminated? ", persistentReceiver.IsTerminated())
// Disconnect the Message Service
messagingService.Disconnect()
log.Info("Messaging Service Disconnected? ", !messagingService.IsConnected())
}
to connect to the system - assuming I have the correct
client1.key
clientCert1.pem
DigiCertGlobalRootCA.crt.pem
files

Do you have client certificate authentication set up on the broker?
What is the error you are getting?

Yes, I have the brocker set up as described in the solance documentation.
No error message so far as I don’t know how to change to code to use a client certificate for authorisation…

Got it partially working with
// Configuration parameters
brokerConfig := config.ServicePropertyMap{
config.TransportLayerPropertyHost: getEnv(“AEM_CONNECTION_STRING”),
config.ServicePropertyVPNName: getEnv(“AEM_VPN”),
}
authenticationStrategy := config.ClientCertificateAuthentication(getEnv(“AEM_CLIENT_CERT_FILE”), getEnv(“AEM_CLIENT_KEY_FILE”), “”)
messagingService, err := messaging.NewMessagingServiceBuilder().
FromConfigurationProvider(brokerConfig).
WithTransportSecurityStrategy(config.NewTransportSecurityStrategy().WithoutCertificateValidation()).
WithAuthenticationStrategy(authenticationStrategy).
Build()

open question remains how to do it with
WithCertificateValidation()
?

Have you tried using the WithCertificateValidation function when creating the new transport security strategy? you can check more details here config - PubSub+ Messaging API for Go v1.8.1

Hey Tamimi

Requesting you to please have a look at my code

import (

"fmt"

"sync"



"rs-web-bankfundtransfer/model"



"github.com/rs-commons/pkg/web"

"solace.dev/go/messaging"

"solace.dev/go/messaging/pkg/solace"

"solace.dev/go/messaging/pkg/solace/config"

"solace.dev/go/messaging/pkg/solace/message"

"solace.dev/go/messaging/pkg/solace/resource"

)

func CreateMessagingService(cfg *model.SolaceConsumerConfig, c *web.AppContext) (solace.MessagingService, error) {

logger := c.AppLogger

logger.Info("Entry in Consumer topic initialization")



serviceProps := config.ServicePropertyMap{

    config.TransportLayerPropertyHost:                             cfg.Host,

    config.ServicePropertyVPNName:                                 cfg.VPN,

    config.AuthenticationPropertySchemeBasicPassword:              cfg.Password,

    config.AuthenticationPropertySchemeBasicUserName:              cfg.Username,

    config.TransportLayerPropertyConnectionRetriesPerHost:         cfg.SolaceConnectRetriesPerHost,

    config.TransportLayerPropertyReconnectionAttempts:             cfg.SolaceReconnectRetries,

    config.TransportLayerPropertyReconnectionAttemptsWaitInterval: cfg.SolaceReconnectWaitMillis,

    config.TransportLayerPropertyConnectionAttemptsTimeout:        cfg.SolaceTimeoutMillis,

    config.TransportLayerPropertyConnectionRetries:                cfg.SolaceConnectRetries, 



}



if cfg.SSLAllow == 1 {

    serviceProps\[config.AuthenticationPropertyScheme\] = config.AuthenticationSchemeClientCertificate

    serviceProps\[config.TransportLayerSecurityPropertyTrustStorePath\] = cfg.SSLTrustStoreFile

    serviceProps\[config.TransportLayerSecurityPropertyMaximumProtocol\] = "TLSv1.3"

    serviceProps\[config.TransportLayerSecurityPropertyMinimumProtocol\] = "TLSv1.2"

    serviceProps\[config.AuthenticationPropertySchemeSSLClientCertFile\] = cfg.ClientCertfile

    serviceProps\[config.AuthenticationPropertySchemeSSLClientPrivateKeyFile\] = cfg.PrivateKeyFile

    serviceProps\[config.AuthenticationPropertySchemeClientCertPrivateKeyFilePassword\] = cfg.PrivateKeyPassword

    serviceProps\[config.AuthenticationPropertySchemeClientCertUserName\] = cfg.ClientCertUserName

    

}



messagingServiceBuilder := messaging.NewMessagingServiceBuilder().

    FromConfigurationProvider(serviceProps)



messagingService, err := messagingServiceBuilder.Build()

if err != nil {

    logger.Error("failed to build messaging service: %v", err.Error())

    return nil, fmt.Errorf("failed to build messaging service: %v", err)

}



// Connect to the broker

if err := messagingService.Connect(); err != nil {

    logger.Error("failed to connect: %v", err.Error())

    return nil, fmt.Errorf("failed to connect: %v", err)

}



logger.Info("Connected to Solace messaging service.")

return messagingService, nil

}

executing this always gives me an error

2025/08/29 16:49:47 log.go:41: ERROR solClientSSL.c:457 b-transactions-in-ti" 2025/08/28 16:49:47 log.go:45: WARNING solClientSSL.c:619 is not trusted, reason = “unable to get local issuer certificate” 2025/08/28 16:49:52 log.go:45: WARNING solClientSSL.c:1477 store ‘/home/rsapp/cert/Solace_JKS_NEW/new_sol_cert.pem’

what can be the possible cause for this issue,

I tried to convert a java code to go which looks like this

@Bean
public SolConnectionFactory solConnectionFactory() throws Exception {
logger.info(“Connected. Awaiting message…” + solaceHost);
SolConnectionFactory connectionFactory = SolJmsUtility.createConnectionFactory();
connectionFactory.setHost(solaceHost);
connectionFactory.setVPN(solacevpn);
connectionFactory.setUsername(solaceUserName);
connectionFactory.setPassword(solacePassword);
connectionFactory.setReconnectRetries(120);
connectionFactory.setReconnectRetryWaitInMillis(5000);
connectionFactory.setConnectRetriesPerHost(2);
connectionFactory.setConnectRetries(120);
connectionFactory.setConnectTimeoutInMillis(5000);
connectionFactory.setDirectTransport(false);
//connectionFactory.setDmqEligible(true);
if(solaceSSLAllow == 1) {

    System.out.println("DirectTransport: "+connectionFactory.getDirectTransport());
    connectionFactory.setAuthenticationScheme("AUTHENTICATION_SCHEME_CLIENT_CERTIFICATE");
    //connectionFactory.setSSLTrustStore("C:\\\\Users\\\\1659007\\\\solace\\\\Sathya_Key\\\\trustStore.jks");
    logger.info("SSLtrustStorefile >> " + SSLtrustStorefile);
    logger.info("SSLTrustStorePassword >>" + SSLTrustStorePassword);
    logger.info("SSLTrustStoreFormat >>" + SSLTrustStoreFormat);
    logger.info("SSLKeyStoreFormat >>" + SSLKeyStoreFormat);
    logger.info("SSLKeyStorePassword >>" + SSLKeyStorePassword);
    connectionFactory.setSSLTrustStore(SSLtrustStorefile);
    connectionFactory.setSSLTrustStorePassword(SSLTrustStorePassword);
    connectionFactory.setSSLTrustStoreFormat(SSLTrustStoreFormat);
    connectionFactory.setSSLKeyStoreFormat(SSLKeyStoreFormat);
    //connectionFactory.setSSLKeyStore("C:\\\\Users\\\\1659007\\\\solace\\\\Sathya_Key\\\\app-test-user.pfx");
    connectionFactory.setSSLKeyStore(SSLKeystorefile);
    logger.info("SSLKeystorefile ..." + SSLKeystorefile);
    connectionFactory.setSSLKeyStorePassword(SSLKeyStorePassword);
    //Use client certificate authentication scheme
}
return connectionFactory;

}

Please let me know where am i going wrong, I have converted every certificate and truststore to .pem as mentioned in go api reference docs, and just fyi my java code is actually working and I want to make it work in go