Norwegian version of this page

Github for IT staff

This page is intended as a best practice guide for setting up accounts and tools to be used in combination with version control through github.uio.no. Initially, it describes the use of 2-factor authentication and SSH/GPG signing of commits for repositories that require it. In addition, a best practice for using multiple SSH keys with the same user is included, as system users cannot be used with github.uio.no and deploy keys must be used, which in github must be unique per repository.

Bildet kan inneholde: hode, virveldyr, pattedyr, tegnefilm, katt.

1   Setup of 2-factor authentication

All IT staff at USIT who will be using github.uio.no must set up 2-factor authentication for their account. For this, you can use the applications Microsoft Authenticator, Authy (without cloud backup), Google Authenticator, and EnPass on iOS and Android, or FreeOTP on Android.

After downloading the app to your mobile device, you can navigate to the link below to set up 2-factor authentication: Github two factor authentication intro

Please note that 2-factor authentication in this service is not dependent/compatible with other 2-factor authentication services at UiO, so the 2-factor authentication set up in Github is only applicable within the Github service.

Note that SSH authentication should be used for operations against the Git service, meaning that you use an SSH key that is password protected, as HTTP authentication essentially becomes 1-factor authentication.

2   Signing commits with SSH

After version 2.34.0 of git, it is possible to sign commits with SSH keys, and this is also supported by Github. This is a slightly less extensive process than setting up GPG, as you usually already have SSH keys ready for use. The SSH key must be added to Github specifically as a signing key, and then Git must be set up to use the key for signing.

In the ~/.gitconfig file, the following fields should have values (change to your own use):

[user]
        email = sjurher@usit.uio.no
        name = Sjur Hernes
        signingKey = /home/sjurher/.ssh/id_ed25519

[gpg]
        format = ssh
[commit]
        gpgsign = true

3   Importing SSH keys to Github Actions runners

Create the file /opt/gh-runner-gpg/ssh_signers owned by root:actions-runner with 750 permissions, and add the public key contents in the following format:

<github email> <public key content>
eksempel@usit.uio.no ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJTULL/jlR82204TULLA11bA1dfCwbqyYr039x8LlmdM eksempel@usit.uio.no
eksempel@usit.uio.no ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJTULL/jlR82204TULLA11bA1dfCwbqyYr039x8LlmdM eksempel@usit.uio.no

Then, specify in the Git configuration file at /home/actions-runner/.gitconfig (owned by actions-runner) that Git should verify SSH-signed commits using the file:

[gpg "ssh"]
        allowedSignersFile = /opt/gh-runner-gpg/ssh_signers

You also need to open selinux to give ssh_keygen access to the files created by initrc in /tmp when importing the repository during a job run. This can be done by creating the file /tmp/sshsign.te (note that the filename must match the module name in the file):

module sshsign 1.0;

require {
        type initrc_tmp_t;
        type ssh_keygen_t;
        class file open;
}
allow ssh_keygen_t initrc_tmp_t:file open;

Then run the following commands:

sudo checkmodule -M -m -o /tmp/sshsign.mod /tmp/sshsign.te
sudo semodule_package -o /tmp/sshsign.pp -m /tmp/sshsign.mod
sudo semodule -i /tmp/sshsign.pp

You should now be ready to use SSH keys with your github-actions-runner.

4   Setting up GPG on Windows

For Windows, gpg4win is the recommended software for using GPG signing. This guide assumes that you have installed Git from the official website https://git-scm.com/download/win, with the default options selected during installation, including git-bash, which will be used with gpg4win for GPG key configuration and Git in this guide. Gpg4win can be downloaded from https://gpg4win.org/download.html. During the installation of gpg4win, you will be asked which components to install, and it is sufficient to install GnuPG. The other components like Kleopatra can be deselected.

Note: It is important that the email address you set in your GPG key matches the primary address set in your Github account and your client's git-config.

Once gpg4win is installed, open Git Bash and run gpg --full-generate-key to start creating your GPG key.:

safet@DESKTOP-KJO66O8 MINGW64 ~
$ gpg --full-generate-key
gpg (GnuPG) 2.2.25-unknown; Copyright (C) 2020 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

gpg: directory '/c/Users/safet/.gnupg' created
gpg: keybox '/c/Users/safet/.gnupg/pubring.kbx' created
Please select what kind of key you want:
(1) RSA and RSA (default)
(2) DSA and Elgamal
(3) DSA (sign only)
(4) RSA (sign only)
(14) Existing key from card
Your selection? 1
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072) 4096
Requested keysize is 4096 bits
Please specify how long the key should be valid.
        0 = key does not expire
<n>  = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Key is valid for? 5y
Is this correct? (y/N) y

GnuPG needs to construct a user ID to identify your key.

Real name: Safet Amedov
Email address: amedov@usit.uio.no
Comment:
You selected this USER-ID:
"Safet Amedov <amedov@usit.uio.no>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: /c/Users/safet/.gnupg/trustdb.gpg: trustdb created
gpg: key F157AAAED0F88FEC marked as ultimately trusted
gpg: directory '/c/Users/safet/.gnupg/openpgp-revocs.d' created
gpg: revocation certificate stored as '/c/Users/safet/.gnupg/openpgp-revocs.d/2816B7AC83F167D94DBCB4B5F157AAAED0F88FEC.rev'
public and secret key created and signed.

pub   rsa4096 2021-01-12 [SC]
2816B7AC83F167D94DBCB4B5F157AAAED0F88FEC
uid                      Safet Amedov <amedov@usit.uio.no>
sub   rsa4096 2021-01-12 [E]

Now that you have generated a key, you need to extract the public part of the GPG key, which will be added to Github. To do this, you need to retrieve the keyID using the following command:

  $ gpg --list-secret-keys --keyid-format LONG
  /c/Users/safet/.gnupg/pubring.kbx
  ---------------------------------
  sec   rsa4096/F157AAAED0F88FEC 2021-01-12 [SC]
2816B7AC83F167D94DBCB4B5F157AAAED0F88FEC
  uid                 [ultimate] Safet Amedov <amedov@usit.uio.no>
  ssb   rsa4096/F7AECB2A4DD9EA08 2021-01-12 [E]

The KeyID you want to retrieve here is F157AAAED0F88FEC:

safet@DESKTOP-KJO66O8 MINGW64 ~/test4 (master)
$ gpg --armor --export F157AAAED0F88FEC
-----BEGIN PGP PUBLIC KEY BLOCK-----

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
=B5Qc
-----END PGP PUBLIC KEY BLOCK-----

Copy the entire PGP key block and navigate to https://github.uio.no/settings/gpg/new. Paste the key block into the Key field.

The same KeyID should be used when configuring your local Git client to use the GPG key.

Set the following parameters for your Git client. Note that the name and email must match what you have set for your GPG key:

git config --global gpg.program "C:\Program Files (x86)\GnuPG\bin\gpg.exe"
git config --global user.signingkey F157AAAED0F88FEC
git config --global user.name "Safet Amedov"
git config --global user.email "amedov@usit.uio.no"
git config --global commit.gpgsign true

NOTE: Sometimes you may need to use the long KeyID (git config --global user.signingkey 2816B7AC83F167D94DBCB4B5F157AAAED0F88FEC) if the short KeyID doesn't work.

If you are using Visual Studio Code, you can enable signing in the settings like this:

/english/services/it/store-collaborate/version-control/help/images/vscode-gpg.png

You can now sign your commits with your GPG key, and the workflow is almost the same as a regular git commit. To enable signing for a specific repository, use the following command after navigating to the repository:

git config commit.gpgsign true

Then, you can add files and commit to the repository as usual:

safet@DESKTOP-KJO66O8 MINGW64 ~/test4 (master)
$ touch foobar.txt

safet@DESKTOP-KJO66O8 MINGW64 ~/test4 (master)
$ git add foobar.txt
safet@DESKTOP-KJO66O8 MINGW64 ~/test4 (master)
$ git commit -m "ny fil"

After running the last command, you will get a dialog from Pinentry where you enter the password for your GPG key, which is then used to sign the file you just committed.

The file is now signed, and you can push it to the repository as usual:

safet@DESKTOP-KJO66O8 MINGW64 ~/test4 (master)
$ git commit -m "ny fil"
[master ccf80da] ny fil
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 foobar.txt
safet@DESKTOP-KJO66O8 MINGW64 ~/test4 (master)
$ git push
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Delta compression using up to 2 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 891 bytes | 891.00 KiB/s, done.
Total 2 (delta 1), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To github.uio.no:amedov/test4.git
  09d77c5..ccf80da  master -> master

5   Setting up GPG on Mac and Linux

For Linux, you can install gpg using yum or apt, depending on the distribution you are using.

IMPORTANT: The email address you set in your GPG key must match the primary email address set in your Github account and in your client's git config.

5.1   Mac-specific

For Mac clients, you can use GPG Suite, which can be downloaded from https://gpgtools.org/. Alternatively, you can also install gpg using Homebrew, but then you should refer to the section below on how to work around potential issues with getting git and gpg to work together.

5.2   Problem with getting Git to use GPG to sign on Linux/Mac

If you encounter the following error, it means that you don't get a password prompt from GPG when trying to sign a commit with git:

error: gpg failed to sign the data
fatal: failed to write commit object

A workaround for this is to add the following to your .bash_profile:

export GPG_TTY=$(tty)

if [ -f ~/.gnupg/.gpg-agent-info ] && [ -n "$(pgrep gpg-agent)" ]; then
  source ~/.gnupg/.gpg-agent-info
export GPG_AGENT_INFO
else
   eval $(gpg-agent --daemon --write-env-file ~/.gnupg/.gpg-agent-info)
fi

When installing GPG Suite, it will prompt you to set up a GPG key during the initial setup, but this guide assumes that you set up the key via the command line.

5.3   Setup for Linux and Mac

To start creating a GPG key, open the terminal and enter gpg --full-generate-key:

safetvm$  gpg --full-generate-key

gpg (GnuPG) 2.2.23; Copyright (C) 2020 Free Software Foundation, Inc.

This is free software: you are free to change and redistribute it.

There is NO WARRANTY, to the extent permitted by law.

Please select what kind of key you want:

(1) RSA and RSA (default)

(2) DSA and Elgamal

(3) DSA (sign only)

(4) RSA (sign only)

  (14) Existing key from card

Your selection? 1

RSA keys may be between 1024 and 4096 bits long.

What keysize do you want? (3072) 4096

Requested keysize is 4096 bits

Please specify how long the key should be valid.

         0 = key does not expire

  &lt;n&gt;  = key expires in n days

    &lt;n&gt;w = key expires in n weeks

    &lt;n&gt;m = key expires in n months

    &lt;n&gt;y = key expires in n years

Key is valid for? 5y

Is this correct? (y/N) y

GnuPG needs to construct a user ID to identify your key.

Real name: Safet Amedov

Email address: amedov@usit.uio.no

Comment: GPG-key for github.uio.no

You selected this USER-ID:

"Safet Amedov (GPG-key for github.uio.no) &lt;amedov@usit.uio.no&gt;"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O

We need to generate a lot of random bytes. It is a good idea to perform

some other action (type on the keyboard, move the mouse, utilize the

disks) during the prime generation; this gives the random number

generator a better chance to gain enough entropy.

We need to generate a lot of random bytes. It is a good idea to perform

some other action (type on the keyboard, move the mouse, utilize the

disks) during the prime generation; this gives the random number

generator a better chance to gain enough entropy.

gpg: key DBCE06BAA3D86117 marked as ultimately trusted

gpg: revocation certificate stored as '/Users/safet/.gnupg/openpgp-revocs.d/EFEA54DF5D118480843CBFE0DBCE06BAA3D86117.rev'

public and secret key created and signed.

pub   rsa4096 2021-01-11 \[SC\]

    EFEA54DF5D118480843CBFE0DBCE06BAA3D86117

uid                      Safet Amedov (GPG-key for github.uio.no) &lt;amedov@usit.uio.no&gt;

sub   rsa4096 2021-01-11 \[E\]

Now that you have a key generated, you need to retrieve the public part of the GPG key, which will be added to GitHub. To do that, you need to fetch the keyID using the following command:

$ gpg --list-secret-keys --keyid-format LONG
/Users/safetvm/.gnupg/pubring.kbx
---------------------------------
sec   rsa4096/DBCE06BAA3D86117 2021-01-11 [SC]
    EFEA54DF5D118480843CBFE0DBCE06BAA3D86117
uid                 [ultimate] safet amedov <amedov@usit.uio.no>
ssb   rsa4096/8826246EB27700CC 2021-01-11 [E]

The keyID you want to retrieve here is DBCE06BAA3D86117:

$ gpg --armor --export DBCE06BAA3D86117
-----BEGIN PGP PUBLIC KEY BLOCK-----

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
=B5Qc
-----END PGP PUBLIC KEY BLOCK-----

Copy the entire PGP keyblock and navigate to https://github.com/settings/gpg/new and paste it into the Key field.

The same keyID should be used when configuring your local git client to use the GPG key.

Set the following parameters for your git client. Note that the name and email must match what you have set for your GPG key:

git config --global user.signingkey DBCE06BAA3D86117
git config --global user.name "Safet Amedov"
git config --global user.email "amedov@usit.uio.no"
git config --global commit.gpgsign true

You can now sign your commits with your GPG key, and the workflow is almost the same as a regular git commit. Signing is set per repository with the following command:

git config commit.gpgsign true

and it is set after navigating to the repository.

Then, you can add files and commit to the repository as usual:

touch foobar.file
git add foobar.file
git commit -m "ny fil"

After running the last command, you will get a dialog from Pinentry where you enter the password for your GPG key, which is then used to sign the file you just committed.

The file is now signed, and you can push it to the repository as usual:

safetvm@safetvms-Mac test4 % git commit -m "ny fil"
[master 09d77c5] ny fil
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 foobar.file
safetvm@safetvms-Mac test4 % git push
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Delta compression using up to 2 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 900 bytes | 900.00 KiB/s, done.
Total 2 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To github.uio.no:amedov/test4.git
   0f7d08a..09d77c5  master -> master

6   How to use multiple SSH keys with the same user

If you want to clone repositories using impersonal users, the solution is to add deploy keys to a repository. Note that it is not possible to reuse the same SSH key pair for multiple repositories as deploy keys in Github, as Github considers the SSH key pair used in a repository to be globally unique.

In situations where you need to clone multiple repositories using impersonal users, you need to configure this on the client side. Below is a relatively OS-agnostic solution to the problem.

6.1   For git versions older than 2.1

This is most relevant for RHEL7 servers, as Windows servers are not dependent on the git version from a given repository. For older versions, you can either use the environment variable GIT_SSH to set which key to use when performing a git operation, or you can do it by creating custom hostname entries in the SSH config file. The latter is recommended, as the first option assumes that you mess around with wrapper scripts.

Given that you have two repositories, driftsrepo1 and driftsrepo2, you add the following entry in .ssh/config:

Host driftsrepo1
Hostname github.uio.no
  IdentityFile /home/driftsbruker/.ssh/driftsrepo1
    User git
Host driftsrepo2
Hostname github.uio.no
IdentityFile /home/driftsbruker/.ssh/driftsrepo2
User git

When cloning the repository, you refer to the hostname you created above like this:

git clone driftsrepo1:ITI-BSD/driftsrepo1.git
Cloning into 'driftsrepo1'...
remote: Enumerating objects: 93, done.
remote: Total 93 (delta 0), reused 0 (delta 0), pack-reused 93
Receiving objects: 100% (93/93), 40.30 KiB | 0 bytes/s, done.
Resolving deltas: 100% (47/47), done.

After this, all future git operations will use "driftsrepo1" as the host. This can be confirmed by checking the .git/config file in a given repository:

server $ cat .git/config
[core]
                                repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
[remote "origin"]
        url = git@driftsrepo1:ITI-BSD/driftsrepo1.git
        fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
        remote = origin
        merge = refs/heads/master

A couple of things to keep in mind if you choose to use the ssh-config file as a solution:

  • Only the alias name is valid. Not alias.uio.no or equivalent.
  • Tunneling will require using the alias name.
  • If you have a machine with the same short name as the repository name (e.g., driftsrepo1.uio.no), you may encounter host key conflicts. Therefore, consider using host key aliases for the host block in ~/.ssh/config.

The best workaround is still to upgrade to an OS with a newer git version, such as RHEL8.

6.2   For git 2.1 and newer

By setting the following configuration in the repository where you want to perform git operations with a specific key, it will override which key git uses for pull and push operations on a given repository:

git config --local core.sshCommand "ssh -i /full/path/til/n?kkel"

7   How to transfer a repository from Bitbucket or other Git solutions

In the following example, we will transfer the "migration_repo" from Bitbucket to Github. First, create a new repository in the relevant organization by navigating to https://github.uio.no/organizations/IT-BSD/repositories/new, replacing IT-BSD with your organization. This will bring up a webpage where you can create a new repository. The repository created will be called migration_repo.

When creating the repository, it can only be private. This means that if you want all teams in your organization to have access to the repository, you set it to internal. If not, set it to private, and then you need to specify which teams should have access to the repository.

Note that by default, the repository only grants write access to the person who created it, so even for internal repositories, you need to define who should have more than just read access to a given repository.

Next, you need to change the remote URL for the repository you want to transfer. This requires that you have cloned the repository to a client/server and have the latest content in the repository. Here you can see that I have Bitbucket as the remote URL:

migration_repo server$git remote -v
origin  ssh://git@bitbucket.usit.uio.no:7999/bsd/migration_repo.git (fetch)
origin  ssh://git@bitbucket.usit.uio.no:7999/bsd/migration_repo.git (push)

System Message: WARNING/2 ({DAVSYNC3}github-for-it-staff.rst, line 582)

Literal block ends without a blank line; unexpected unindent.

A repository can have multiple remotes, so you need to adjust this based on your setup, but here we are assuming that we only want to change the configuration for the origin remote. Here I configure the new remote to point to git@github.uio.no:IT-BSD/migration_repo.git:

migration_repo server$git remote set-url origin git@github.uio.no:IT-BSD/migration_repo.git
migration_repo server$git remote -v
origin  git@github.uio.no:IT-BSD/migration_repo.git (fetch)
origin  git@github.uio.no:IT-BSD/migration_repo.git (push)

Once this is done, you only need to run git push --mirror, and all files, commits, remotes, tags, and branches will be pushed to the new repository on Github:

migration_repo server$git push --mirror
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Writing objects: 100% (3/3), 206 bytes | 206.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To github.uio.no:IT-BSD/migration_repo.git
 * [new branch]      master -> master

If you only want to push refs under refs/heads/ (which also includes all branches), use git push --all.

If you don't want to include all branches, a regular git push is sufficient.

To prevent anyone from continuing to push code to the old repository in Bitbucket, it is recommended to delete the files in the Bitbucket repository and leave a message indicating that the repository has been moved to Github.

8   Commit signing

8.1   Commit signing

Some repositories require signing commits with a GPG key to authenticate the content of the commit. It is best to sign all commits, and you can set this as the default with the following setting:

git config --global commit.gpgsign true
git config --global user.signingkey = DIN_GPG_KEY_ID

Refer to the guide above on how to retrieve YOUR_GPG_KEY_ID.

If, instead, you want to do this differently from repository to repository or commit to commit (not recommended), you can add -S when making a git commit:

git commit -S

8.2   Cleaning up unsigned commits

If you succumb to the temptation to make an unsigned commit that turns out to require signing, you can change this with the following command:

git commit --amend -S

If, for example, your last four commits are unsigned, you can change this by rebasing:

git rebase -i HEAD~4 --exec 'git commit --amend --no-edit --no-verify -S'

9   Importing GPG keys to Github Actions runners

On our Github Actions runners, a script is set up to check whether a commit is signed with a known and valid GPG key before Actions jobs run. If the job is not signed with a known GPG key, it will fail. The solution is to import your public GPG key into the runner's GPG store.

The keys are stored under gh-runner-$RUNNERSERVER.uio.no:/opt/gh-runner-gpg/pubring.kbx. All owners of such a runner have access to the server with their operations user and can import the necessary GPG keys.

First, retrieve and upload the GPG key:

gpg --armor --export youremail@usit.uio.no| ssh ops-user@gh-runner-$RUNNERSERVER.uio.no "cat > ~/yourusername.asc"

Then log in to the server with your operations user and run the following command to import the key you just uploaded:

sudo /opt/gh-runner-scripts/gpg-key-import.sh  ~/yourusername.asc

Afterwards, you can either create a new commit or trigger a re-run of the job in the Github Actions tab of your repository.

By Alison Wartenberg
Published Oct. 17, 2024 3:00 PM - Last modified Nov. 12, 2024 2:02 PM