6

I wanted to see if anyone else has set up a Google Cloud Directory Sync (GCDS aka GADS) with their Active Directory over secure LDAP (LDAPS). We've been syncing over port 389 and I'd like to encrypt that connection, but when I switch to port 636 the connection fails.

I am running the GCDS tool on a member server in my domain - is the connection that I'm trying to establish on port 636 going between Google's off-site servers and my DC, or is it between the GCDS tool and my DC? And even if it is between the GCDS tool and my DC, does it still require a 3rd party certificate or is a self-signed certificate sufficient because the software is being run on a domain-joined server? Should I run the program on a DC?

If this is an issue where I need a 3rd party certificate, some guidance would be appreciated as I'm not particularly knowledgeable in certificates. Thanks!

Mike
  • 379
  • 2
  • 3
  • 14

2 Answers2

5

Update Sept 23, 2020 Today I updated GCDS and the TLS stuff broke again. This time, the problem was with an inability to access our CRL file from an offline root CA. I found that Google has beefed up its help page for GCDS certificate problems here: https://support.google.com/a/answer/3075991 I found my solution there.

Update Jan 20, 2020: It is anticipated that with the March 2020 patches, Microsoft will disallow insecure binds. This answer is likely to gain some additional attention, as Google Cloud Directory Sync will likely then fail to connect to AD unless TLS is being used.

Original Answer

Google Cloud Directory Sync is a Java application. The GCDS installer installs a version of the Java run-time environment in a sub-folder. That installation has its own set of trusted root certificate authorities. It does not use the certs installed in Windows.

To get things working, you need to import the public certificate for the trusted Certificate Authority that issued the certificate being used by your domain controller. You could instead install the public certificate from your domain controller, but that certificate will likely expire much sooner than the issuing certificate authority's certificate.

Google provides instructions here: https://support.google.com/a/answer/3075991?hl=en However, their instructions use the DC's public certificate, not the CA's certificate.

Obtain the CA certificate. I'm going to call it the_cert.cer

If you're following Google's instructions, you're exporting the cert from the domain controller:

certutil -store My DomainController %TEMP%\the_cert.cer

But again, you're better off with the CA certificate.

Move the certificate to the GCDS host.

On the GCDS host

Change folders to the jre folder where GCDS is installed. For me it was:

cd "c:\Program Files\Google Cloud Directory Sync\jre"

Yours might be different depending on your environment.

Install the certificate into the Java keystore:

bin\keytool -keystore lib\security\cacerts -storepass changeit -import -file %TEMP%\the_cert.cer -alias pick_a_name_you_like

The keytool utility will prompt: Trust this certificate? [no]: Type yes and hit the Enter key.

Clean up:

del the_cert.cer

Now, going against my advice again and using the DC's cert, here's a complete script you could run via Task Scheduler to keep your certificate up-to-date on your domain controller, assuming you run GCDS on the same domain controller.

<#
  .SYNOPSIS
  Exports the bound AD LDAPS encryption certificate and imports it into
  Google Cloud Directory Sync's Java keystore, so that GCDS syncs will succeed.

  .DESCRIPTION
  Google Cloud Directory Sync runs on Java. Java maintains its own trusted keystore,
  separate from the host operating system. Often, this keystore grows stale when updates
  are neglected. Further, the keystore would never contain certificate information for
  self-signed or internally-distributed certificates.

  In order to make GCDS work with TLS using secure LDAPS binding, it is necessary to
  export your trusted certificate from the machine's certificate store and import it into
  the GCDS-bundled Java Runtime Environment's certificate store.

  This script assumes the DC being contacted resides on the same host as the GCDS installation.

  Given a ComputerName and Port, this script will connect to the named DC and determine the
  thumbprint of the certificate bound to the DC on the specific port.

  Using this thumbprint, the script then exports the certificate from the Local Computer's MY (Personal)
  certificate store. This does NOT include the private key, and therefore it's safe to do this.

  Next, the script deletes and re-imports the certificate into the JRE certificate store.

  .PARAMETER ComputerName
  Use the fully-qualified network name of the machine. We're assuming this is the same network name
  that will be used in GCDS to bind against the DC, and is also the CommonName represented in the certificate.

  .PARAMETER Port
  Usually this will be 636, but could be custom depending on your environment.

  .OUTPUTS
  Will list the thumbprint of the cert found and will show stderr and stdout of the keytool commands.
  Error handling could definitely be beefed up here.

  .EXAMPLE
  C:\PS> .\Update-JavaDomainControllerCertificate.ps1 -ComputerName my.domain.com -Port 636

#>

[CmdletBinding()]
param (
    [Parameter(Mandatory=$true)]
    [string]
    $ComputerName,

    [int]
    $Port = 636
)
$FilePath = "$($Env:TEMP)\adcert.crt"
$Certificate = $null
$TcpClient = New-Object -TypeName System.Net.Sockets.TcpClient
try {

    $TcpClient.Connect($ComputerName, $Port)
    $TcpStream = $TcpClient.GetStream()

    $Callback = { param($sender, $cert, $chain, $errors) return $true }

    $SslStream = New-Object -TypeName System.Net.Security.SslStream -ArgumentList @($TcpStream, $true, $Callback)
    try {

        $SslStream.AuthenticateAsClient('')
        $Certificate = $SslStream.RemoteCertificate

    } finally {
        $SslStream.Dispose()
    }

} finally {
    $TcpClient.Dispose()
}

if ($Certificate) {
    if ($Certificate -isnot [System.Security.Cryptography.X509Certificates.X509Certificate2]) {
        $Certificate = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList $Certificate
    }
    Write-Output "Found Certificate:"
    Write-Output $Certificate
}

Export-Certificate -Cert $Certificate -Force -FilePath $FilePath | Out-Null

Set-Location -Path "C:\Program Files\Google Cloud Directory Sync\jre"

# Delete existing entry
& .\bin\keytool -keystore lib\security\cacerts -storepass changeit -delete -noprompt -alias $ComputerName 2>&1 | %{ "$_" }

# Add entry
& .\bin\keytool -keystore lib\security\cacerts -storepass changeit -importcert -noprompt -file $FilePath -alias $ComputerName 2>&1 | %{ "$_" }

Remove-Item -Path $FilePath -Force
Larry Silverman
  • 567
  • 6
  • 13
  • Since you actually answered my question, I'm awarding this as the answer - I'm trusting it actually works ;) I appreciate the write-up! I don't know if I'll end up changing as it seems like adding SSL incurs more overhead, but it's definitely worth knowing how to do it should we need to in the future. – Mike Jul 12 '17 at 20:18
  • Leaving the insecure endpoint available is a security no-no which I'm trying to eliminate. The July 2017 patches contain something of a nudge. See https://portal.msrc.microsoft.com/en-us/security-guidance/releasenotedetail/f2b16606-4945-e711-80dc-000d3a32fc99 – Larry Silverman Jul 12 '17 at 20:39
  • GCDS lives on the machine it's authenticating against, so unless someone is sniffing that particular computer (highly unlikely), I don't see a need to use SSL. Now, if i had to authenticate over an unsecured network, then I'd definitely use SSL. – Mike Jul 14 '17 at 04:34
  • Sure, as long as you've firewalled 389 so external systems cannot get to it, you should be generally OK. – Larry Silverman Jul 14 '17 at 14:11
  • 1
    Do you really need to use the DC cert? Can't you install and trust the CA cert that generates the certs for your DCs? – Zoredache Jan 30 '20 at 18:52
  • You're right. What Java needs to trust is the Certificate Authority. – Larry Silverman Jan 30 '20 at 23:11
0

So, I just spoke with google support and it looks like I'm going to change direction on this. They confirmed that the client is communicating securely with the google servers. He also said that enabling SSL would increase the sync time significantly. Plus, if I run the client on a DC and use 127.0.0.1, then I don't even have to worry about exposing the traffic on our network, and even then it would still be confined to our private server network were I to run it on a member server.

So, I'll probably play around with it a little more to see if I can get 636 working just for kicks, but I probably won't spend too much time on it as I've got a good amount of other stuff to take care of. What's weird is that I tried using the MS LDP tool from that computer that's has the GADS client on it and it connects to my DC on port 636 without issue. I've been trying all sorts of domain\username combinations, all of which connect fine on 389, but once you change it to 636 and LDAP+SSL, it spits out:

Initializing... Error: Connection failed Exception: Failed to execute query because the object at Base DN: "DC=mydomain,DC=com" is missing or inaccessible.

So yeah, I'm not quite sure why it's not connecting on 636, but it looks like I don't even want it to anyways.

Mike
  • 379
  • 2
  • 3
  • 14
  • You most likely have to tell it that it should use SSL on that port. (Not sure how todo that for the sync tool) – eckes May 29 '17 at 07:29
  • There's a dropdown that allows you to select LDAP or LDAP+SSL – Mike May 29 '17 at 15:26
  • @Mike I've been facing this same type of issue. Running Google Cloud Directory Sync on the Domain Controller itself might be one option, but for setups that may require a separation between the Domain Controller and other services, there ought to be a way to resolve this issue in order to use the LDAP+SSL option. I'm currently looking for more documentation on this... – summea Jun 22 '17 at 22:47
  • 1
    After a conversation with Google, there really was no need to go the SSL route, especially because it would add significant slowdown to the sync and the tool and my DC are on the same secure network. Also, LDAPS has nothing to do with the issues we were having so it wasn't really worth the effort to figure it out. So yeah, you'll probably need to chat with Google to figure out how to get LDAPS working - sorry I don't have more info! – Mike Jun 23 '17 at 03:44