Home > other >  As an end user, how can I get my shared Docker runner to trust an internally-signed SSL certificate?
As an end user, how can I get my shared Docker runner to trust an internally-signed SSL certificate?

Time:02-25

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:

  1. Navigate to the GitLab web interface in Chrome
  2. Click the lock in the address bar to the left of the address
  3. Click on Connection is secure
  4. Click on Certificate is valid
  5. In the new window that opens, go to the Details tab
  6. 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:

  1. Navigate to SettingsCI/CD in the web interface and expand the Variables section.
  2. Click Add variable
  3. Set the variable's Key to GIT_SSL_CAINFO (the environment variable Git will look for)
  4. Paste the contents of server-name.crt into the Value field
  5. 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.

  1. 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.

  2. 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 runs update-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.

  • Related