Add support for the gssapi-with-mic auth method
Context
The only way to clone a GitLab repositoty with Kerberos is to use SPNEGO with the HTTP protocol, which has a few drawbacks:
-
a known libcurl bug is forcing the user to specify an empty username which produces confusing URL (
https://:@host/path
) and requires the use of an obscure Git optionhttp.emptyAuth
. - libcurl is prioritizing SPNEGO over basic auth when credentials are provided via the URL, thus causing issues with GitLab CI.
Proposal
Fortunately, the SSH protocol has support for two authentication method related to Kerberos: gssapi-with-mic
and gssapi-keyex
. The later, less prevalent, has the advantage of not requiring the user to validate the host key fingerprint on the first connection but is not supported by the SSHd implementation used by gitlab-sshd which only supports gssapi-with-mic
.
gitlab-sshd does not actually implement GSS-API functions, it is the responsibility of the developer to choose an implementation:
-
gokrb5
unfortunately only implements the initiator (client) functions, we needs the acceptor (server) functions. -
go-gssapi
is promising but not production-ready according to its authors. -
OpenShift
gssapi
offer a comprehensive set of functions and seems mature enough, this is the one I chose.
This MR:
- adds a
gssapi
settings block in gitlab-sshd's configuration to controls whether GSSAPI should be enabled or not, which keytab file and service principal name to use. - adds support for the
gssapi-with-mic
authentication method in gitlab-sshd - adds a new
krb5principal
parameter to the internal API calls, support for this parameter in GitLab is provided in gitlab!97648 (merged).
How to test this MR
You will need a working Kerberos installation:
In order to compile this MR on MacOS, we need to install heimdal
:
brew install heimdal
And then modify this line in the Makefile
to:
CGO_CFLAGS="-I/opt/homebrew/opt/heimdal/include" GOBIN="$(CURDIR)/bin" go install $(GOBUILD_FLAGS) ./cmd/...
You need a keytab with credentials for the principal host/<hostname>@<REALM>
where <hostname>
is the hostname of your gitlab instance. It can be added using the same steps that are used in the Dockerfile:
addprinc -randkey host/gdk.test
ktadd -k /etc/host.keytab host/gdk.test
Then the keytab file can be copied from the container, for example as: docker cp $(docker-compose ps -qa krb5):/etc/host.keytab .
. We need this file to specify in the Gitlab Shell config (config.yml
):
gssapi:
enabled: true
keytab: "./host.keytab"
service_principal_name: "host/gdk.test"
You may add the following Kerberos options in your client host (/etc/krb5.config
) if you do not have PTR records for your Gitlab instance hostname:
[libdefaults]
rnds = false
dns_canonicalize_hostname = false
You will need a valid Kerberos TGT:
$ kinit <principal>
You will need the following SSH option enabled on your client host (~/.ssh/config
):
GSSAPIAuthentication yes
I use this snippet to disable public key authentication (not necessary in a non-testing setup since GSSAPI has priority):
$ cat ~/.ssh/config
Host gdk.test
Port 2222
User git
PubKeyAuthentication no
GSSAPIAuthentication yes
Try connecting to the SSH server with the verbose flag enabled, if you see the authenticated using "gssapi-with-mic"
, it works!
$ ssh -Tv gdk.test discover
[...]
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug1: Authentications that can continue: publickey,gssapi-with-mic
debug1: Next authentication method: gssapi-with-mic
Authenticated to gdk.test ([XXX.XXX.XXX.XXX]:2222) using "gssapi-with-mic".
[...]
Closes #196 (closed) and Configure SSH-based KRB5 authentication (gitlab#3447 - closed)