I did manage to get some scripts/steps in place that allow for multiple trusted certificates to the same server. Its works just fine, except for it throws out a TON of logs for the certificate that no longer (or does not yet) match what the server provides. These logs appear on the tentacle and the server, so the server would get overloaded awfully quick with a lot of tentacles.
As far as why this matters, is mostly in that we have Octopus servers for government applications. The requirement for them is that the government CA’s must be used to create the certificates, which limits how long the certificates last. Which means as often as every year we may need to re-issue a certificate for the octopus server… without a way to automatically rotate the certificates we would need to manually update every machine connected to those government servers. This could number easily reaches thousands of tentacles.
As far as how I got this to work, I have a script that does the following :
Calls tentacle.exe configure --trust <>
for the new thumbprint which was required to call the server-comms command
Calls tentacle.exe server-comms --thumbprint <> --style <> --host <> --port <>
to ensure that the octopus server information is appropriate connected/duplicated for the new thumbprint
Regex replaces the new poll://<>
information with the old poll://<>
information. So that both new certificate and old certificate thumbprints connect on the same polling channel.
This works 100%, either certificate that is presented is accepted by the tentacle. It does however create about half a gig of logs over a weeks time on the tentacle, which I believe all (or most) is duplicated on the server (and for every tentacle) because there is an error when matching the wrong cert.
I will paste the service startup of a tentacle configured for both servers at the bottom. In it you will notice it has the same poll:// for both certificates (it has 2 new cert entries due to needing to trust the thumbprint before being able to server-comms it… leaving a trusted row in the tentacle.config with no information other than the cert thumbprint). It will try to connect to the server with the first/old certificate and throw an INFO level error for this connection every 5 seconds. However the last line shows a successful connection to the same server with the correct/updated certificate. I haven’t looked at the tentacle code for handling any of this, but since this does already work it makes me hopeful that the solution would be to have the tentacle aggregate its information in a way to accept either certificate on the same server & poll://<> connection.
If you’d like some more information, logs, details, ideas, etc please reach out I would be happy to assist.
2019-07-11 10:15:28.3171 4952 7 INFO ==== RunAgentCommand ====
2019-07-11 10:15:28.3171 4952 7 INFO CommandLine: C:\Program Files\Octopus Deploy\Tentacle\Tentacle.exe run --instance=Tentacle
2019-07-11 10:15:29.2952 4952 7 INFO Agent will trust Octopus Servers with the thumbprint: <OLDCERTIFICATE>
2019-07-11 10:15:29.3372 4952 7 INFO Agent will trust Octopus Servers with the thumbprint: <NEWCERTIFICATE>
2019-07-11 10:15:29.3372 4952 7 INFO Agent will trust Octopus Servers with the thumbprint: <NEWCERTIFICATE>
2019-07-11 10:15:29.3372 4952 7 INFO Agent will poll Octopus Server at <OCTOPUSSERVERURL> for subscription poll://k8n9nsk7ctjmkmvedm5k/ expecting thumbprint <OLDCERTIFICATE>
2019-07-11 10:15:29.6512 4952 7 INFO Agent configured to use the system proxy, but no system proxy is configured for <OCTOPUSSERVERURL>
2019-07-11 10:15:29.7382 4952 7 INFO Agent will poll Octopus Server at <OCTOPUSSERVERURL> for subscription poll://k8n9nsk7ctjmkmvedm5k/ expecting thumbprint <NEWCERTIFICATE>
2019-07-11 10:15:30.0153 4952 8 INFO <OCTOPUSSERVERURL> 8 Opening a new connection
2019-07-11 10:15:30.1083 4952 7 INFO Agent configured to use the system proxy, but no system proxy is configured for <OCTOPUSSERVERURL>
2019-07-11 10:15:30.1113 4952 9 INFO <OCTOPUSSERVERURL> 9 Opening a new connection
2019-07-11 10:15:30.1113 4952 7 INFO Agent will not listen on any TCP ports
2019-07-11 10:15:30.1113 4952 7 INFO The Windows Service has started
2019-07-11 10:15:32.9746 4952 8 INFO <OCTOPUSSERVERURL> 8 Authentication failed while setting up connection to <OCTOPUSSERVERURL>
The server at <OCTOPUSSERVERURL> presented an unexpected security certificate. We expected the server to present a certificate with the thumbprint '<OLDCERTIFICATE>'. Instead, it presented a certificate with a thumbprint of '<NEWCERTIFICATE>' and subject '<CERTDATA>'. This usually happens when the client has been configured to expect the server to have the wrong certificate, or when the certificate on the server has been regenerated and the client has not been updated. It may also happen if someone is performing a man-in-the-middle attack on the remote machine, or if a proxy server is intercepting requests. Please check the certificate used on the server, and verify that the client has been configured correctly.
2019-07-11 10:15:32.9826 4952 8 INFO <OCTOPUSSERVERURL> 8 Exception in the polling loop, sleeping for 5 seconds. This may be cause by a network error and usually rectifies itself. Disregard this message unless you are having communication problems.
Halibut.HalibutClientException: An error occurred when sending a request to '<OCTOPUSSERVERURL>', after the request began: The server at <OCTOPUSSERVERURL> presented an unexpected security certificate. We expected the server to present a certificate with the thumbprint '<OLDCERTIFICATE>'. Instead, it presented a certificate with a thumbprint of '<NEWCERTIFICATE>' and subject '<CERTDATA>'. This usually happens when the client has been configured to expect the server to have the wrong certificate, or when the certificate on the server has been regenerated and the client has not been updated. It may also happen if someone is performing a man-in-the-middle attack on the remote machine, or if a proxy server is intercepting requests. Please check the certificate used on the server, and verify that the client has been configured correctly. ---> Halibut.Transport.UnexpectedCertificateException: The server at <OCTOPUSSERVERURL> presented an unexpected security certificate. We expected the server to present a certificate with the thumbprint '<OLDCERTIFICATE>'. Instead, it presented a certificate with a thumbprint of '<NEWCERTIFICATE>' and subject '<CERTDATA>'. This usually happens when the client has been configured to expect the server to have the wrong certificate, or when the certificate on the server has been regenerated and the client has not been updated. It may also happen if someone is performing a man-in-the-middle attack on the remote machine, or if a proxy server is intercepting requests. Please check the certificate used on the server, and verify that the client has been configured correctly.
at Halibut.Transport.ClientCertificateValidator.Validate(Object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslpolicyerrors) in Z:\buildAgent\workDir\fe2b45bbd4978f75\source\Halibut\Transport\ClientCertificateValidator.cs:line 26
at System.Net.Security.SecureChannel.VerifyRemoteCertificate(RemoteCertValidationCallback remoteCertValidationCallback, ProtocolToken& alertToken)
at System.Net.Security.SslState.CompleteHandshake(ProtocolToken& alertToken)
at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult)
at Halibut.Transport.SecureClient.EstablishNewConnection() in Z:\buildAgent\workDir\fe2b45bbd4978f75\source\Halibut\Transport\SecureClient.cs:line 152
at Halibut.Transport.SecureClient.ExecuteTransaction(Action`1 protocolHandler) in Z:\buildAgent\workDir\fe2b45bbd4978f75\source\Halibut\Transport\SecureClient.cs:line 65
--- End of inner exception stack trace ---
at Halibut.Transport.SecureClient.HandleError(Exception lastError, Boolean retryAllowed) in Z:\buildAgent\workDir\fe2b45bbd4978f75\source\Halibut\Transport\SecureClient.cs:line 207
at Halibut.Transport.PollingClient.ExecutePollingLoop(Object ignored) in Z:\buildAgent\workDir\fe2b45bbd4978f75\source\Halibut\Transport\PollingClient.cs:line 47
2019-07-11 10:15:33.0476 4952 9 INFO <OCTOPUSSERVERURL> 9 Secure connection established. Server at [::ffff:172.16.11.54]:443 identified by thumbprint: <NEWCERTIFICATE>, using protocol Tls12