Skip to content
Français
Account: not signed in, sync available My learning
Select theme
Français

Securing Pulp: RBAC, content guards and signing

By updated

Improve this page

Pulp logo

This guide covers the security levers of Pulp: who can read or write (RBAC), who can download (content guards), what enters your repositories (filters), and how to guarantee integrity (signing). Intended audience: administrators who expose Pulp to several teams or in production. Prerequisites: a working Pulp instance and the CLI configured (see Installing Pulp). You will also see, plainly, what Pulp does not do natively when it comes to software supply chain security.

The security of an artifact manager comes down to three questions: who accesses what, what you let in, and can you trust what is stored. Pulp answers all three, but in its own way, with building blocks to assemble rather than a turnkey dashboard.

What you will learn

  • Restrict access with RBAC and its fine-grained roles.
  • Protect downloads with content guards.
  • Filter what comes in with --includes and --excludes.
  • Guarantee integrity with content signing.
  • Place Pulp honestly against vulnerability quarantine.

Controlling access with RBAC

Pulp includes a very granular role-based access control (RBAC). Each plugin brings its own roles, so you can authorize a team on the Python repositories without opening the RPM ones. The instance ships with more than 160 predefined roles out of the box.

Terminal window
pulp role list --limit 5

Roles follow an explicit naming scheme, for example python.pythonrepository_owner (full power over Python repositories) or rpm.rpmremote_viewer (read-only access to RPM remotes). A role is assigned to a user or to a group, on a specific object or globally.

  1. Create a dedicated service user for a team or a pipeline:

    Terminal window
    pulp user create --username ci-python --password "MotDePasseCI"
  2. Assign it a targeted role, here the management of Python repositories:

    Terminal window
    pulp user role-assignment add \
    --username ci-python \
    --role "python.pythonrepository_owner" \
    --object ""

    The empty object ("") grants the role at the global level; you can also restrict it to a specific repository through its href. The least privilege principle applies: a pipeline only receives the rights it needs.

Protecting downloads with content guards

RBAC governs the API. To control who downloads the distributed content, Pulp uses content guards, attached to a distribution. Several types coexist:

Content guardControlsUse case
RBACBased on Pulp rolesPrivate repository reserved for a team
HeaderAn expected HTTP headerFiltering done by an upstream proxy
x509A client certificateAccess through mutual certificates (mTLS)
CompositeA combination of the aboveMulti-criteria policies

An RBAC content guard attached to a distribution turns a public repository into an authenticated one: only users with the right role get the files. This is the access denial mechanism at the distribution level.

Filtering what enters your repositories

The first line of supply chain defense is to not copy everything. Remotes accept --includes and --excludes filters that define an allowlist or a denylist of packages to synchronize.

Terminal window
pulp python remote create \
--name pypi-maitrise \
--url https://pypi.org/ \
--includes '["requests", "urllib3", "certifi"]' \
--excludes '["requests<2.31.0"]'

Here, only three packages are synchronized, and the vulnerable versions of requests (before 2.31.0) are excluded from the repository. You control the exact inventory your machines can install, instead of relaying the whole upstream.

Guaranteeing integrity with signing

To prove that an artifact has not been tampered with, Pulp relies on signing services: signing mechanisms declared in the instance, which run a script backed by a GPG key. Container images follow another path, the Cosign signature being produced on the client side, with Pulp merely hosting it.

Terminal window
pulp signing-service list

Once a signing service is declared, several plugins use it: pulp_rpm signs the repository metadata and pulp_container signs the container manifests. Cosign signatures of images, for their part, are copied at synchronization and verified by the client. Combined with filtering at the entrance and Trivy scanning, signing closes the chain of trust. The full implementation, with Cosign for images and a GPG signing service for manifests, RPMs and collections, is detailed in the guide Signing Pulp artifacts.

Filtering on the presence of a signature is not verifying it

When syncing, Pulp can keep only the images that come with a signature, through the signed_only: true parameter of the request. It does not verify that signature, and the field's own documentation says it word for word: "Signatures are not verified". A forged signature, or one produced by any key at all, therefore passes this filter.

Verification stays on the client side, with cosign verify or podman's policy.json policy. The filter rules out unsigned content; it says nothing about who signed, and confusing the two buys a confidence that nothing backs.

Immutable versioning, a safety net

Each synchronization or upload creates an immutable repository version. A distribution points to a specific version: if a compromised package is published by mistake, you roll back to the previous version with one command, without restoring a backup. This native traceability is a security asset that is often underrated.

What Pulp does not do: vulnerability quarantine

Let us be clear to avoid a false expectation: Pulp does not ship with automatic quarantine of vulnerable packages. There is no native equivalent to the application firewall of Nexus (blocking a component based on its CVE score) or to the curation of Artifactory Xray.

Pulp provides the building blocks to build this guarantee, but you assemble the policy yourself:

  • Filter at the entrance with --includes / --excludes.
  • Scan with an external tool such as Trivy in CI, blocking the promotion of a vulnerable artifact.
  • Promote only validated content to a production repository.
  • Restrict access with RBAC and content guards.

This model takes more integration work than a commercial solution, but it relies entirely on open source tools and stays fully under your control.

Adding an artifact firewall upstream

To get closer to real admission control, you can place an artifact firewall such as Varnish Orca in front of Pulp. Orca is a vendor-agnostic virtual registry: its backend (remotes.url) accepts any HTTP registry, Pulp included. The flow becomes client -> Orca (allow/deny/quarantine decision) -> Pulp.

In the lab, Orca does proxy Pulp (PyPI index and download of artifacts served through Orca). The most direct setup is the container registry (/v2/ at the root, like a standard OCI registry); for PyPI, Orca's redirect wrapper requires aligning CONTENT_ORIGIN. The blocking decision itself remains a Premium feature of Orca.

Hands-on practice

The lab asks you to create a publishing account that can upload to a single repository, and nothing else. The validation covers both halves of the contract: what the account can do, and what it must not be able to do. It therefore checks that the account uploads to its repository, and that it fails to create another one or to touch a container repository. Since a new Pulp account is already read-only, this second half is what distinguishes a targeted role from an account with no rights.

Key takeaways

  • Pulp RBAC offers more than 160 fine-grained roles, per plugin, to apply least privilege.
  • Content guards (RBAC, header, x509, composite) control who downloads the distributed content.
  • The --includes / --excludes filters control what enters your repositories.
  • Signing services (GPG) sign metadata and manifests on the server side, Cosign signs images on the client side, but nothing is signed by default.
  • Pulp has no native CVE quarantine: you build it with an external scanner and a promotion policy.

Knowledge check

Eight questions on the two halves of an access contract: what an account can do, what it must not be able to do, and what Pulp does not do natively.

Knowledge check

Check what you have learned with this interactive quiz

8 questions
8 min
70% to pass

How it works

  • The timer starts when you click Start
  • Multiple choice, true/false and short answer questions
  • You can move between questions
  • Detailed results are shown at the end

Starts the quiz and the timer

Is this project useful to you?

The guides, courses, quizzes and labs stay free. If you use them regularly, you can contribute to their upkeep and development.

Become a supporting member (new tab) One-time support (new tab) Learn more

Follow the project on LinkedIn