I have a project with a dependency that gets pulled in from a self-hosted GitLab server over HTTP, e.g.:
{
"name": "Project",
"version": "1.0.0",
"main": "index.js",
"dependencies": {
"some-dependency": "git http://user:[email protected]/group/project.git"
}
}
The GitLab server's SSL certificate is signed by an internal certificate authority connected to the company's Active Directory infrastructure. On domain machines, Chrome and Microsoft Edge automatically trust it via policy.
Git does not:
fatal: unable to access 'https://server.tld/group/project.git': server certificate verification failed.
On Windows, I can use the Schannel SSL back-end to make Git trust certificates signed by the internal CA:
git config --global http.sslBackend schannel
Since the schannel
SSL back-end is only available on Windows, that isn't an option for my tests running in a Docker runner on GitLab CI.
How can I install the project's dependencies on GitLab CI without completely disabling certificate checking?
Edit: I do not have admin access to the shared runners I'm using so I cannot install trusted SSL certs on them directly.
CodePudding user response:
Retrieve a copy of the certificate from a trusted source
It is important to verify that the certificate is genuine. Since Chrome already trusts the certificate via policy, we can safely retrieve the certificate from Chrome:
- Navigate to the GitLab web interface in Chrome
- Click the lock in the address bar to the left of the address
- Click on Connection is secure
- Click on Certificate is valid
- In the new window that opens, go to the Details tab
- Click the Copy to file... and save the certificate file somewhere, e.g. in a file called
server-name.crt
server-cert.crt
should contain something like
-----BEGIN CERTIFICATE-----
MIIJKoHjzstDxgmHL2j/LQ46PHAbnVYz/JlflAQl3AAjoy9VdtY1hkiG9otrEQmF
...
tMn95/0eWw3lqeduiv5ux982PpepGY3aozPyTzt/1P==
-----END CERTIFICATE-----
If you prefer to retrieve the cert another way, e.g. via the openssl
CLI tool, make sure to check its fingerprint against a reliable source. You can view the downloaded certificate's fingerprint like so:
openssl x509 -in server-cert.crt -noout -fingerprint
If you need another type of fingerprint you can request one, e.g. by adding an argument like -sha256
.
Use the certificate in your container
Now that we have a copy of the certificate we need to make Git aware of it during CI jobs. There are at least two options.
Option 1: Get Git to trust it directly.
Git has a setting for this:
http.sslCAInfo
File containing the certificates to verify the peer with when fetching or pushing over HTTPS. Can be overridden by the
GIT_SSL_CAINFO
environment variable.
Add a CI variable to the project:
- Navigate to Settings → CI/CD in the web interface and expand the Variables section.
- Click Add variable
- Set the variable's Key to
GIT_SSL_CAINFO
(the environment variable Git will look for) - Paste the contents of
server-name.crt
into the Value field - Change its Type from Variable to File
During jobs, GitLab CI will now create a temporary file, put the text of the certificate into that file, and set the GIT_SSL_CAINFO
environment variable to the file's path. Git will pick it up automatically.
This has the benefit of (probably) not requiring any code changes. Your existing GitLab CI job should "just work". This means you should be able to set the variable at the group level in case you have multiple projects that are affected.
Option 2: Get the operating system in the container to trust it.
I'll show one way to do this with a Debian- or Ubuntu-based image. Alpine, Fedora, etc. images may require a few tweaks.
Create a file variable as shown in the first part of Option 1 above, but give it a different Key. I'll use
TRUSTED_CERTS
here.Update your
gitlab-ci.yml
to pull the cert into the OS-level certificate store. One way to do that is shown here:default: before_script: # Add certificates contained in $TRUSTED_CERTS to OS-level certificate store - > [ -f "$TRUSTED_CERTS" ] && ln -s "$TRUSTED_CERTS" /usr/local/share/ca-certificates/trusted.crt && update-ca-certificates - yarn install # Installing dependencies should work now
If
$TRUSTED_CERTS
is set, this creates a symlink to that file in/usr/local/share/ca-certificates/
and then runsupdate-ca-certificates
to update the OS-level certificate store.
This option should make most tools trust the certificate at the expense of some additional complexity in the CI job.
Since the gitlab-ci.yml
file must be modified, it also can't be implemented at the group level as easily. A custom Docker base image that includes updated certificates could mitigate that.