Configure Commit Signing on Linux with Your CAC
Overview
This article explains what commit signing is and how to configure your Linux machine to sign Git commits with your CAC.
All commits must be signed using either a CAC or a GPG key. Developers with a CAC can configure Git to sign commits using their CAC certificate. For projects operating in IL4 and IL5 environments, CAC signing is required for all commits.
If you do not use a CAC for commit signing, follow the How to Commit Sign with GPG Guide.
WARNING
Party Bus does not support commit signing through IDE integrations. If you create commits in an IDE, use the command line to sign them. Do not submit Party Bus support requests for IDE-specific commit signing issues.
INFO
These instructions have been tested on Ubuntu 20.04 LTS. Other Linux distributions may require additional configuration. Updates to GPG packages may affect CAC detection.
Prerequisites
Before you begin:
Ensure your Linux system supports CAC authentication and that you have
sudoaccess.Install the required smart card packages.
shellsudo apt install libpcsclite1 pcscd pcsc-toolsEnable and start the smart card service.
shellsudo systemctl enable pcscd --nowInsert your CAC.
Verify that the CAC reader is detected.
shellpcsc_scan -rIf successful, the output displays your connected reader and CAC information. Press CTRL+C to exit.
For additional CAC configuration information, see the Ubuntu CAC documentation.
Confirm Your GitLab Commit Email Address
After identifying your CAC signing certificate, verify that your GitLab commit email matches the email address on the certificate.
- Open User Settings > Emails .
- Find the email address marked with the
icon.
- Verify that the commit email matches the email address on your CAC signing certificate.
If the correct email address is not listed:
Submit a request for GitLab commit sign email validation .
- For repo1.dso.mil, contact the Iron Bank team instead.
Wait until the request is complete.
Open User Settings > Profile.
Select the newly added CAC CDS email address as your Commit Email.
WARNING
Do not add the email address to GitLab yourself. User-added email addresses require email verification, but GitLab on P1 cannot send verification emails. The email address must be added and verified through the service request.
If multiple developers need commit email validation, submit a single request that includes all users. If the team is not yet in the pipeline queue, add the information to the COT Epic in Jira.
Prepare GnuPG for CAC Signing
This section prepares GnuPG to communicate with your CAC.
Install GnuPG and smart card tools.
Shellsudo apt -y install gpg coolkey dirmngr gnupg2 gnupg-pkcs11-scd openscVerify the GnuPG installation.
shellgpgconfVerify that
gpg,gpgsm,gpg-agent,scdaemon, anddirmngrare present in the output.Create the PKCS#11 configuration file.
shellnano ~/.gnupg/gnupg-pkcs11-scd.confAdd the following configuration:
shellproviders p1 provider-p1-library /usr/lib/pkcs11/libcoolkeypk11.so providers smartcardhsm provider-smartcardhsm-library /usr/lib/x86_64-linux-gnu/opensc-pkcs11.soConfigure the GPG agent.
shellnano ~/.gnupg/gpg-agent.confAdd:
shellscdaemon-program /usr/bin/gnupg-pkcs11-scd(OPTIONAL) Enable terminal PIN entry.
shellecho 'pinentry-program /usr/local/bin/pinentry-curses' >> ~/.gnupg/gpg-agent.conf echo 'export GPG_TTY=$(tty)' >> ~/.bashrcVerify smart card detection.
shellgpg --card-statusDownload and install the DoD PKI certificate chain.
shellwget https://dl.dod.cyber.mil/wp-content/uploads/pki-pke/zip/unclass-certificates_pkcs7_v5-6_dod.zip unzip unclass-certificates_pkcs7_v5-6_dod.zip sudo cp Certificates_PKCS7_v5.6_DoD/DoD_PKE_CA_chain.pem /usr/local/share/ca-certificates/DoD_PKE_CA_chain.crt sudo cp Certificates_PKCS7_v5.6_DoD/DoD_PKE_CA_chain.pem /etc/ssl/certs/DoD_PKE_CA_chain.crt sudo update-ca-certificatesList the certificates on the CAC.
shellpkcs15-tool --list-certificatesshell#$ pkcs15-tool --list-certificates Using reader with a card: Identive SCR33xx v2.0 USB SC Reader X.509 Certificate [Certificate for PIV Authentication] Object Flags : [0x00] Authority : no Path : ID : 01 Encoded serial : 02 03 0F0000 X.509 Certificate [Certificate for Digital Signature] Object Flags : [0x00] Authority : no Path : ID : 02 Encoded serial : 02 03 123456 X.509 Certificate [Certificate for Key Management] Object Flags : [0x00] Authority : no Path : ID : 03 Encoded serial : 02 03 000000 X.509 Certificate [Certificate for Card Authentication] Object Flags : [0x00] Authority : no Path : ID : 04 Encoded serial : 02 03 000000Record the ID for the X.509 Certificate [Certificate for Digital Signature] entry. You will use this value in the next step.
Run the following to import the Root CRL for your certificate, using the ID from the previous step. Replace
< FILENAME >with the file downloaded in the previous step.shellpkcs15-tool --read-certificate < ID > > mycert.crt wget $(openssl x509 -in mycert.crt -text | grep "CA Issuers" | awk '{ print $4 }' | sed 's/URI://g')Note the file downloaded in the previous
wgetstep and copy its name into the following commandsshelltouch ~/.gnupg/trustlist.txt dirmngr --fetch-crl $(openssl x509 -inform der -in < FILENAME >.cer -text | grep crl | grep -v "CA Issuers" | sed 's/URI://g') gpgsm --import < FILENAME >.cer gpgsm --import mycert.crtRestart your GPG agent to use your new settings from the previous steps
shellgpgconf --kill allIdentify your signing email address and signing key by running:
shellsigningEmail=$(gpgsm --list-secret-keys | grep aka | awk '{ print $2 }') signingKey=$( gpgsm --list-secret-keys | egrep '(key usage|ID)' | grep -B 1 digitalSignature | awk '/ID/ {print $2}')Verify the values.
Shellecho $signingEmail echo $signingKeyConfirm that:
- The email address matches the email address associated with your CAC.
- The signing key corresponds to your Digital Signature certificate.
Configure Git
Configure Git to use your CAC certificate when signing commits. If you already have Git configured for other accounts or repositories, adjust these steps as needed.
Identify your Git email address and signing key.
Run the following commands:ShellsigningEmail=$(gpgsm --list-secret-keys | grep aka | awk '{ print $2 }') signingKey=$(gpgsm --list-secret-keys | egrep '(key usage|ID)' | grep -B 1 digitalSignature | awk '/ID/ {print $2}')Configure Git to sign commits using your CAC certificate.
Shellgit config --global user.email "$signingEmail" git config --global user.signingkey "$signingKey" git config --global gpg.format x509 git config --global gpg.x509.program gpgsm git config --global commit.gpgsign trueVerify the Git configuration.
Shellgit config --list | grep -E 'user|gpg|commit'Confirm the output includes:
- Your CAC-associated email address.
- Your signing key.
gpgsmforgpg.x509.program.x509forgpg.format.trueforcommit.gpgsign.
Verify Git Commit Signing
Create a test commit.
Shellgit commit -m "test commit signing"If prompted, trust the DoD Root CA. After trusting the certificate, retry the commit.
Enter your CAC PIN when prompted.
Verify that the commit was signed.
Shellgit log --show-signatureThe commit should display a valid signature and appear as Verified in GitLab. If the commit is not marked Verified, see the troubleshooting information.
Troubleshooting
CAC PIN prompts fail after reboot or reconnecting your CAC
If commit signing stops working after restarting your computer or reconnecting your CAC, restart the GPG agent:
gpgconf --kill allAfter restarting the agent, try signing a commit again.
Multiple PIN or certificate trust prompts appear during signing
If you use a non-GUI PIN entry method (such as pinentry-curses), the first commit signing attempt may prompt you multiple times for your CAC PIN and certificate trust.
To initialize authentication and reduce repeated prompts, run:
gpgsm --status-fd=2 -bsau "$signingKey"After completing the prompts, try signing a commit again.