Introduction

Jacamar CI

Jacamar CI is an open source project designed to be a bridge between traditional GitLab CI pipelines and HPC resources. All this is accomplished by first conforming to the supported custom executor model for executing jobs. Beyond this, Jacamar, manages additional responsibilities; user authorization, downscoping mechanisms, scheduler interactions, and a robust set of administrative configuration options.

Authorization and Downscoping

Within Jacamar-CI exists two primary applications, jacamar and jacamar-auth. Though it is possible to only use jacamar, doing so removes all potential for control over the authorization process as it is designed to be executed by the CI job user. Our ideal workflow would be to directly reference jacamar-auth from your GitLab configuration (/etc/gitlab-runner/config.toml). Thus, the process could be run by a privileged user. By trusting Jacamar with these advanced privileges you can then take advantage of the Authorization Flow. Allowing you to establish a level of trust with the requesting CI job user before ultimately downscoping permissions to their equivalent local user account.

../../../_images/jacamar_auth_arch.svg

Security Overview

By default, all GitLab CI jobs run as the single gitlab-runner user. If you require isolation between CI jobs on your runner hosts (e.g., for security on a multi-tenant system), Jacamar’s authorization coupled with downscoping functionality (i.e., setuid) should be utilized. This will ensure GitLab’s security model is enforced consistently, all the way from the server to user job execution on the host system. With the supported auth configuration, multiple users can share a single Jacamar executor securely, without the risk of one user accessing each other’s data.

While GitLab does its best to preserve isolation between users on the server (e.g., one user cannot access another user’s repository without permission). The default runner configuration does not enforce this same isolation. If CI jobs from different GitLab users are scheduled on the same traditional runner, one job can access any data the other job stores on the runner host’s filesystem. This is insecure.

Let’s examines several use cases where a runner with the ability to downscope to user permissions would be required:

  1. Basic runner data isolation: One user’s GitLab CI job cannot access the working directory or cached data of another user’s CI job. This is provided with setuid functionality by ensuring that each working directory and cache data directory are owned and only accessible by the user who initiated the job. All CI processes will run as the job initiator, ensuring file permissions are enforced.

  2. Account-specific resources: On some systems, certain resources and privileges are associated with specific user accounts. For example, at nearly all high performance computing facilities, CPU time allocations are associated with user accounts. CI jobs must run as specific users on the runner host in order to submit compute jobs to the batch system. Setuid functionality ensure that users can access these resources in addition to ensuring allocations are properly observed.

  3. Shared, sensitive data sets: At many sites, sensitive applications and data sets are deployed in a shared filesystem on multi-tenant resources, with access restricted to certain users or unix groups. Just as setuid jobs ensure that a runner’s working directory and cache data are protected, they also ensure that OS-level permissions are respected by CI jobs for shared data sets.