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.pubto a namespace - A user tries authenticating using a certificate signed by the
CA - Gitlab Shell sends the fingerprint of the CA to
/authorized_certsand returns the namespace, which is remembered on Gitlab Shell during an SSH connection. TheCAis 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 -> 1relationship. - The namespace is sent every time
/allowedis 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 filesCAandCA.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-certificatebranch -
Use the UX from Gitlab Rails MR to add
CA.pubto a group -
Generate a certificate.
CAis the name of the CA file from 1st step,admin@example.comis the primary email of the user (username can be used as well),-V +1dis the expiration date, setting a small one like-V +5scan 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 (
makecommand can be run to be sure).gdk startto start the app,gdk tail sshdwill show the Gitlab Shell logs. -
Remove any loaded SSH keys:
ssh-add -D -
Explicitly set SSH key to
CAand test.gdk.testis the host here, can be127.0.0.1as 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.