Jenkins — Level by Level›07 · Security and operations

Lesson 07 of 8 · Level 3 — Operating Jenkins

Security and operations

Run the controller like production infrastructure: configuration and plugins as code, SSO and least-privilege authorization, credentials scoped per team, script security, backups you've restored, and a routine for plugin and LTS upgrades driven by security advisories.

Advanced
Key wordsJenkins Configuration as CodeJCasCjenkins.yamlplugins.txtjenkins-plugin-cliauthorizationRole-based Authorization StrategySSOcredentialsfoldersscript approvalbackupsLTS upgradessecurity advisories

The controller is a high-value target

Jenkins holds credentials for registries, Git, clouds and sometimes clusters, and it runs code from many repositories. Treat it like production infrastructure with privileged access.

The controller is the building's key cabinet. It needs a strong lock, a list of who may open which drawer, a log of every opening, a spare set of keys stored safely elsewhere, and regular checks that the lock hasn't been quietly weakened.

Configuration as code

JCasC describes the controller in YAML:

# jenkins.yaml (excerpt)
jenkins:
  systemMessage: "Managed by JCasC: changes through Git only"
  numExecutors: 0
  securityRealm:
    oic:                                  # OpenID Connect SSO (oic-auth plugin); fields vary by plugin version
      clientId: jenkins
      clientSecret: "${OIDC_CLIENT_SECRET}"  # from a Kubernetes Secret, not in Git
      wellKnownOpenIDConfigurationUrl: https://sso.example.com/.well-known/openid-configuration
  authorizationStrategy:
    roleBased:
      roles:
        global:
          - name: admin
            permissions: [ "Overall/Administer" ]
            entries: [ { group: "jenkins-admins" } ]
          - name: read
            permissions: [ "Overall/Read" ]
            entries: [ { group: "engineering" } ]
unclassified:
  location:
    url: https://jenkins.example.com/

Plugins pinned in the controller image:

# plugins.txt: one plugin per line as id:version, pinned to versions you tested
configuration-as-code:<version>
kubernetes:<version>
workflow-aggregator:<version>
git:<version>
role-strategy:<version>
oic-auth:<version>

Generate the real list from a tested controller (the plugin manager, or jenkins-plugin-cli --list). Build a controller image with jenkins-plugin-cli --plugin-file plugins.txt, keep jenkins.yaml and plugins.txt in Git, and every change becomes a reviewed pull request.

Authentication and authorization

  • SSO (OIDC or SAML) with groups from your identity provider; no local accounts except a break-glass admin.
  • Least privilege: most people get read and build on their own folders; only admins get Overall/Administer (which is equivalent to full control of the controller).
  • API tokens per user or service; no shared accounts.

Credentials

  • Store in Jenkins credentials (or pull from Vault / cloud secret managers with the matching plugin).
  • Scope to folders per team; global scope only for shared, low-risk items.
  • Prefer short-lived credentials: OIDC to clouds, GitHub App tokens instead of personal tokens.
  • Rotate on a schedule and immediately when someone leaves.

Script security

Pipelines run in a Groovy sandbox; methods outside it need script approval by an admin. Approve rarely and carefully, since each approval widens what every pipeline can do. Keep powerful logic in the global shared library (trusted, reviewed code) instead.

Backups and disk

  • Back up JENKINS_HOME (volume snapshots or a backup job): config, credentials (with the secrets/ directory that decrypts them), job history.
  • Test a restore to a scratch controller regularly.
  • Disk fills from build history, workspaces and archived artifacts: build discarders everywhere, artifacts in an external store (S3, Artifactory), no heavy workspaces on the controller.

Upgrades

  • Follow the LTS line; read the changelog and upgrade guide for each baseline.
  • Subscribe to Jenkins security advisories; apply fixes for plugins you use quickly.
  • Upgrade a staging controller built from the same image and JCasC first, run a set of reference pipelines, then promote the image.
  • Remove unused plugins: fewer plugins, fewer vulnerabilities and fewer upgrade conflicts.

Try it: a controller from Git

  1. Build a controller image with a pinned plugins.txt (FROM jenkins/jenkins:lts-jdk21 + jenkins-plugin-cli).
  2. Add a jenkins.yaml with 0 executors, role-based authorization and a folder; start the controller with CASC_JENKINS_CONFIG.
  3. Change the system message in YAML, reload configuration as code, and see the change.
  4. Back up the volume, delete the container, and restore it into a new one; confirm jobs and credentials survive.

Recap

  • JCasC + pinned plugins.txt + Jenkinsfiles in repos = a controller you can rebuild from Git.
  • SSO, role-based least privilege, folder-scoped credentials, short-lived tokens.
  • Approve scripts sparingly; put trusted logic in the shared library.
  • Back up and test restores; control disk growth; upgrade LTS and plugins through staging, driven by security advisories.

This site is a public version of my personal engineering knowledge hub. It intentionally excludes confidential company information and internal operational details.