golang solance API for certificate based authentication

ulrich
ulrich Member Posts: 17
edited July 2023 in PubSub+ Event Broker #1

Hi,

I followed https://docs.solace.com/Cloud/ght_client_certs.htm 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 https://solace.community/discussion/1630/golang-example-to-read-from-queue-via-solace-golang-api

`package main

import (
   "flag"
   log "github.com/sirupsen/logrus"
   "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

Tagged:

Answers

  • amackenzie
    amackenzie Member, Employee Posts: 260 Solace Employee

    Do you have client certificate authentication set up on the broker?

    What is the error you are getting?

  • ulrich
    ulrich Member Posts: 17

    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...

  • ulrich
    ulrich Member Posts: 17
    edited July 2023 #4

    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()

    ?

  • Tamimi
    Tamimi Member, Administrator, Employee Posts: 491 admin

    Have you tried using the WithCertificateValidation function when creating the new transport security strategy? you can check more details here https://docs.solace.com/API-Developer-Online-Ref-Documentation/go/solace.dev/go/messaging/pkg/solace/config/index.html#TransportSecurityStrategy