Support authentication using SSH Certificates
Related issue: gitlab#408474 (closed)
Gitlab Rails: Draft: Support uploading CA files to a group (gitlab!126741 - closed)
Functional flow:
The functional workflow is the following:
- An admin adds
CA.pub
to a namespace - A user tries authenticating using a certificate signed by the
CA
- Gitlab Shell sends the fingerprint of the CA to
/authorized_certs
and returns the namespace, which is remembered on Gitlab Shell during an SSH connection. TheCA
is unique for an instance (unique index for the fingerprint). It means that it's not necessary to integrate a namespace into the certificate, a certificate and a namespace have1 -> 1
relationship. - The namespace is sent every time
/allowed
is called. It means that we send project fullpath and the namespace in which a user is authenticated. If the project doesn't have the namespace in the list of its ancestors, the action is not allowed.
sequenceDiagram
User->>+Gitlab Shell: Auth using SSH Certificate
Gitlab Shell->>+Gitlab Rails: /authorized_certs?key=signing-key-of-certificate&user_identity=username-or-primary-email
Gitlab Rails-->>-Gitlab Shell: responds with the namespace that configures the CA and username of the user
Gitlab Shell-->>User: Authenticated successfully
User->>+Gitlab Shell: Git command to a specific project
Gitlab Shell->>+Gitlab Rails: /allowed [namespace=namespace]
Gitlab Rails-->>-Gitlab Shell: responds that the project belongs to this namespace or its ancestor
Gitlab Shell-->>User: success
Steps to verify
-
Ensure your current working directory is your
<GDK_ROOT>
-
Generate
CA
(Certificate Authority). Creates 2 filesCA
andCA.pub
:ssh-keygen -C CA -f CA
-
Create a new SSH ECDSA based key:
ssh-keygen -t ecdsa -f ~/.ssh/gitlab-shell-812-ecdsa
-
Gitlab Rails switched to
id-group-ssh-certificate
branch -
Use the UX from Gitlab Rails MR to add
CA.pub
to a group -
Generate a certificate.
CA
is the name of the CA file from 1st step,admin@example.com
is the primary email of the user (username can be used as well),-V +1d
is the expiration date, setting a small one like-V +5s
can be used to test that expired certificates are not accepted:ssh-keygen -s CA -I admin@example.com -V +1d ~/.ssh/gitlab-shell-812-ecdsa.pub
-
Gitlab Shell switched to this current branch (
make
command can be run to be sure).gdk start
to start the app,gdk tail sshd
will show the Gitlab Shell logs. -
Remove any loaded SSH keys:
ssh-add -D
-
Explicitly set SSH key to
CA
and test.gdk.test
is the host here, can be127.0.0.1
as well, the other options are to ensure no other config / key is used:ssh -v -F /dev/null -o "IdentitiesOnly=yes" -i ~/.ssh/gitlab-shell-812-ecdsa git@gdk.test -p 2222
The SSH certificate is accepted. The output similar to the following is generated:
debug1: Will attempt key: GitLab ED25519 SHA256:nAbfYGWTQguxdZFPfo6a9anzCVQ/oO6lRUAxotkxEtQ agent
debug1: Will attempt key: /Users/igordrozdov/.ssh/id_ed25519 ED25519 SHA256:VwKSgBdqjbYZEzaK2DsXcKwa4AG5Rh/ABrNATjXpIVM explicit
debug1: Will attempt key: /Users/igordrozdov/.ssh/id_ed25519 ED25519-CERT SHA256:nAbfYGWTQguxdZFPfo6a9anzCVQ/oO6lRUAxotkxEtQ explicit
debug1: SSH2_MSG_EXT_INFO received
debug1: kex_input_ext_info: server-sig-algs=<ssh-ed25519,sk-ssh-ed25519@openssh.com,sk-ecdsa-sha2-nistp256@openssh.com,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,rsa-sha2-256,rsa-sha2-512,ssh-rsa,ssh-dss>
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug1: Authentications that can continue: publickey
debug1: Next authentication method: publickey
debug1: Offering public key: GitLab ED25519 SHA256:nAbfYGWTQguxdZFPfo6a9anzCVQ/oO6lRUAxotkxEtQ agent
debug1: Authentications that can continue: publickey
debug1: Offering public key: /Users/igordrozdov/.ssh/id_ed25519 ED25519 SHA256:VwKSgBdqjbYZEzaK2DsXcKwa4AG5Rh/ABrNATjXpIVM explicit
debug1: Authentications that can continue: publickey
debug1: Offering public key: /Users/igordrozdov/.ssh/id_ed25519 ED25519-CERT SHA256:nAbfYGWTQguxdZFPfo6a9anzCVQ/oO6lRUAxotkxEtQ explicit
debug1: Server accepts key: /Users/igordrozdov/.ssh/id_ed25519 ED25519-CERT SHA256:nAbfYGWTQguxdZFPfo6a9anzCVQ/oO6lRUAxotkxEtQ explicit
Authenticated to gdk.test ([127.0.0.1]:2222) using "publickey".
I have multiple SSH keys in ~/.ssh
folder, but none of them are accepted (may require removing them from the user profile of your local instance). The certificate is accepted.