Search code examples
goldapgoogle-workspace

How does Golang's LDAP client library work with certificates?


I'm trying to connect to G Suite's LDAPS server with Golang's LDAP library.

However, in the example, I don't really understand two things.

  1. It seems like it connects via non-encrypted LDAP first? Then it upgrades? Is that true, if so, can't I just start out by connecting encrypted?

  2. Google supplies a .cer & .key file to connect to their ldap server. I don't see where it use these files. I do see in their docs that a lot of LDAP clients require the files to be combined into a .p12. Is that necessary for Go?

If the person that answers this could supply an example, that would really help. Thank you.


Solution

  • StartTLS, as you've noted, allows one to upgrade a connection to use a TLS later on in the connections lifecycle.

    If you want to connect via TLS immediately, then use the well known ldaps port 636 (instead of 389) - and use DialTLS:

    // l, err := ldap.Dial("tcp", "ldap.example.com:389"))
    
    var tlsConf *tls.Config
    
    ldaps, err := ldap.DialTLS("tcp", "gsuite.google.com:636", tlsConf)
    

    You may also use DialURL which infers TLS or non-TLS by the schema e.g.

    conn, err := ldap.DialURL("ldap://ldap.example.com") // non-TLS on default port 389
    conn, err := ldap.DialURL("ldaps://ldap.example.com") // TLS on default port 636
    conn, err := ldap.DialURL("ldaps://myserver.com:1234") // TLS on custom port 1234
    
    // Note: there is no way to add a custom tls.Config with this method
    

    So if using, DialTLS: since you are using a Google service, it's trust cert should already be in your keychain, so a simple tls.Config should suffice:

    tlsConf = &tls.Config{ServerName:"gsuite.google.com"} // <- ensure this matches the hostname provided by the server
    

    If you want to get things up an running for testing:

    // DONT EVER USE THIS IN PRODUCTION...
    tlsConf = &tls.Config{InsecureSkipVerify: true} // DO NOT USE EVER
    

    To add a client cert for client-side authentication:

    // Load cer & key files into a pair of []byte 
    cert, err := tls.X509KeyPair(cer, key)
    if err != nil {
        log.Fatal(err)
    }
    tlsCong := &tls.Config{Certificates: []tls.Certificate{cert}}