Skip to content

Add podman-entitlement GitHub Action. - #60

Merged
snecklifter merged 1 commit into
redhat-actions:mainfrom
adelton:podman-entitlement
Jul 28, 2026
Merged

Add podman-entitlement GitHub Action.#60
snecklifter merged 1 commit into
redhat-actions:mainfrom
adelton:podman-entitlement

Conversation

@adelton

@adelton adelton commented May 20, 2022

Copy link
Copy Markdown
Contributor

Description

When building images that need Red Hat content beyond what is available in the Universal Base Image repositories, Red Hat subscription is needed. To avoid changing the Dockerfile and invoke subscription-manager register manually, this GitHub Actions calls that step in separate temporary container and uses /etc/containers/mounts.conf to configure subsequent podman build invocations to have access to the entitlements.

Note that for example registry.access.redhat.com/ubi9-minimal does not have subscription-manager at all so the approach with tweaking the Dockerfile and somehow passing the subscription credentials to the podman build invocation which gets sometimes recommended would not work with those minimalistic images at all.

Related Issue(s)

Checklist

  • This PR includes a documentation change
  • This PR does not need a documentation change

  • This PR includes test changes
  • This PR's changes are already tested

  • This change is not user-facing
  • This change is a patch change
  • This change is a minor change
  • This change is a major (breaking) change

Changes made

  • Add new GitHub Action podman-entitlement

@adelton

adelton commented May 20, 2022

Copy link
Copy Markdown
Contributor Author

I've been playing with this approach for a while in https://github.com/adelton/redhat-entitlements because I'd need it for RHEL-based container image builds and tests of https://github.com/freeipa/freeipa-container. With RHEL 9 release this week, I updated and tested the approach to use ubi9.

I currently did not include any tests with this PR because

  • we'd need some valid subscription credentials in this repository to actually consume them and test the approach;
  • it might be useful to actually test this from some external repository, to make sure the redhat-actions/common/podman-entitlement "path" to the Action works.

Please let me know how you'd like tests for this Action to be laid out.

@adelton

adelton commented Sep 9, 2022

Copy link
Copy Markdown
Contributor Author

I've now updated the code to make it a bit more readable.

@snecklifter

Copy link
Copy Markdown
Contributor

Hi @adelton, apologies for the delay in responding to this PR.

Are you still interested in working on this? If so, it would be great to get an update on where things stand.

Thanks!

@adelton

adelton commented Jul 22, 2026

Copy link
Copy Markdown
Contributor Author

I've been using a copy of this code in https://github.com/freeipa/freeipa-container/ and its development and testing since I showed the code here:
https://github.com/freeipa/freeipa-container/blob/master/.github/actions/podman-entitlement/action.yml

So strictly speaking I don't need this code merged in this repo because my itch got scratched by carrying it where I use it.

If you or Red Hat folks overall would find it useful for the broader audience and would like to include and maintain it here, I'd be happy to revive the discussion here.

@snecklifter

Copy link
Copy Markdown
Contributor

Hi @adelton

It would be good if you could add it here, looks like a useful addition.

If you want to update the PR I'd be happy to review.

@adelton
adelton force-pushed the podman-entitlement branch from e7e3404 to 6a01ef0 Compare July 23, 2026 04:09
@adelton
adelton requested a review from snecklifter as a code owner July 23, 2026 04:09
@adelton

adelton commented Jul 23, 2026

Copy link
Copy Markdown
Contributor Author

I've updated the action to use UBI10, squashed it and rebased it on top main.

We might need some actions to test it but for that we'd need the some valid credentials (org and activationkey) defined as secrets (perhaps as redhat_org and redhat_activationkey) in this repo.

Of course, comments welcome, also possibly in light of this PR being an attempt to address #32, although I did not get any feedback from folks there since 2022, so not sure how valid or needed that issue still is.

@snecklifter snecklifter left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution — the action solves a real problem. I've left inline comments on the main issues. The script injection vulnerability is a blocker; the rest are improvements to bring this in line with the other actions in the repo.

Comment thread podman-entitlement/action.yml
Comment thread podman-entitlement/action.yml
Comment thread podman-entitlement/action.yml
Comment thread podman-entitlement/README.md
@snecklifter

Copy link
Copy Markdown
Contributor

Thanks for the updates @adelton — the injection fix and required fields look good. A few more items to address before merge:

Error handling

The current ; /usr/sbin/subscription-manager unregister at the end means the step's exit code comes from unregister, not from register or cp. If registration fails, unregister also fails (nothing to unregister), so it happens to work — but it's fragile. I'd recommend set -e with a trap instead:

bash -c 'set -e
  /usr/sbin/subscription-manager register \
    --org="$SM_ORG" --activationkey="$SM_KEY" --name="$SYSTEM_NAME"
  trap "/usr/sbin/subscription-manager unregister" EXIT
  cp /etc/pki/entitlement/* /etc/pki/entitlement-out/
  cp -r /etc/rhsm/ca /etc/rhsm/rhsm.conf /etc/rhsm-out'

This way:

  • The trap only activates after a successful registration
  • If cp fails, the step fails and unregister still runs
  • The exit code reflects the actual failure, not unregister's result

Testing without real credentials

We can test the full lifecycle with a mock subscription-manager. Add a test directory with a minimal container image:

# podman-entitlement/test/Dockerfile.mock
FROM registry.access.redhat.com/ubi10-micro
COPY subscription-manager /usr/sbin/subscription-manager
RUN chmod +x /usr/sbin/subscription-manager
# podman-entitlement/test/subscription-manager
#!/bin/bash
case "$1" in
  register)
    mkdir -p /etc/pki/entitlement /etc/rhsm/ca
    echo "mock-cert" > /etc/pki/entitlement/123456.pem
    echo "mock-key" > /etc/pki/entitlement/123456-key.pem
    echo "mock-ca" > /etc/rhsm/ca/redhat-uep.pem
    echo "mock-conf" > /etc/rhsm/rhsm.conf
    echo "System registered successfully."
    ;;
  unregister)
    echo "System unregistered."
    ;;
esac

Then CI can build the mock image, run the action with fake credentials, and verify that:

  1. mounts.conf gets the right entries
  2. A podman build with RUN test -f /run/secrets/etc-pki-entitlement/123456.pem succeeds
  3. The post step cleans everything up

No real Red Hat credentials needed.

Pre-merge housekeeping

  • CHANGELOG: Add an entry under a new v2.1.0 section — this is a new feature
  • Squash commits into a single clean commit before merge
  • Idempotency: Consider a guard before appending to mounts.conf: grep -q "/tmp/etc-pki-entitlement-${RUN_ID}" "$MOUNTS_CONF" 2>/dev/null && exit 0
  • README: Note that the image input must include subscription-manager and bash

@adelton

adelton commented Jul 27, 2026

Copy link
Copy Markdown
Contributor Author

For the trap, I was not fond of only setting at after a successful register. I feel like the subscription-manager register can fail with non-zero status for whatever reason even if the system got registered and usable credentials where stored in the system.

So in 7d8a263 I went with just setting the trap first thing in the bash script. The exit status of the trap won't affect the exit status of the script, so hopefully it achieves better robustness without downsides.

@adelton

adelton commented Jul 27, 2026

Copy link
Copy Markdown
Contributor Author

As for the CI testing, I'd much rather go with an "e2e" test with real credentials and a Dockerfile like

FROM registry.access.redhat.com/ubi10
RUN dnf install -y gssproxy

for which podman build is expected to fail without the entitlements, so it is easy to test the effect of the action on the actual podman build. The mock approach does not give any guarantee that the effect of the action on the actual podman behaviour is what the action promises to be, for various host operating systems and their versions.

@adelton

adelton commented Jul 27, 2026

Copy link
Copy Markdown
Contributor Author

Example of such end-to-end CI is in 279cc53, and example workflow run in my fork is https://github.com/adelton/redhat-actions-common/actions/runs/30263269719.

@snecklifter

Copy link
Copy Markdown
Contributor

For the trap, I was not fond of only setting at after a successful register.

That's a good call — placing the trap before register is more defensive and handles the edge case where register partially succeeds but exits non-zero. Since the trap's exit status doesn't override the script's, there's no downside. Looks good.

@snecklifter

Copy link
Copy Markdown
Contributor

As for the CI testing, I'd much rather go with an "e2e" test with real credentials

Fair point — the mock approach tests plumbing but not the actual podman behavior. The e2e test with dnf install -y gssproxy is a much stronger signal, and the CI workflow structure looks solid (negative test first, then action, then positive test, across multiple runners).

A few things to fix in the CI workflow before merge:

  1. Trigger is wrong. Currently triggers on push to branch podman-entitlement only. Once merged, CI won't run on future PRs. Should match the other workflows:

    on:
      push:
        branches: [main]
        paths:
          - 'podman-entitlement/**'
          - '.github/workflows/ci-podman-entitlement.yml'
      pull_request:
        paths:
          - 'podman-entitlement/**'
          - '.github/workflows/ci-podman-entitlement.yml'
  2. Guard on secrets. secrets.redhat_org won't be available on fork PRs. Gate the job so it skips cleanly rather than failing with empty credentials:

    jobs:
      podman:
        if: ${{ secrets.redhat_org != '' }}
  3. Your fork run proves it works — happy to merge based on that signal and set up the repo secrets afterward.

@adelton

adelton commented Jul 27, 2026

Copy link
Copy Markdown
Contributor Author

Per https://docs.github.com/en/actions/how-tos/write-workflows/choose-what-workflows-do/use-secrets:

Secrets cannot be directly referenced in if: conditionals. Instead, consider setting secrets as job-level environment variables, then referencing the environment variables to conditionally run steps in the job.

That approach seems wasteful as we have no use for any of the steps in the job if we don't have the secrets.

I can do a separate job to check for the entitlements, similar to https://github.com/freeipa/freeipa-container/blob/master/.github/workflows/test-rhel.yaml#L9-L28.

@adelton
adelton force-pushed the podman-entitlement branch from 2490953 to 43635c1 Compare July 27, 2026 14:35
@adelton

adelton commented Jul 27, 2026

Copy link
Copy Markdown
Contributor Author

Guard with a separate job shown in 43635c1.

Executed as https://github.com/adelton/redhat-actions-common/actions/runs/30275793011.

@adelton

adelton commented Jul 27, 2026

Copy link
Copy Markdown
Contributor Author

I will flip the branches: [podman-entitlement] to branches: [main] as one of the last steps before calling this PR done as it will prevent me from getting the work verified with a workflow run upon pushes to my branch.

Added a reminder in 963aade.

@adelton

adelton commented Jul 27, 2026

Copy link
Copy Markdown
Contributor Author

Changelog entry added in 70bb56a.

@snecklifter

Copy link
Copy Markdown
Contributor

This is looking great — nearly all feedback has been addressed. Two small things before the final squash:

  1. Version should be v2.1.0, not v2.0.1. A new action is a feature addition, which is a minor bump under semver — not a patch.

  2. Secret name casing is inconsistent. The test-secrets-exist job checks secrets.REDHAT_ORG (uppercase) but the podman job uses secrets.redhat_org (lowercase). GitHub secrets are case-insensitive so it works, but it's confusing to read. Would be cleaner to pick one convention throughout.

@adelton
adelton requested a review from a team as a code owner July 28, 2026 15:02
@adelton

adelton commented Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

Addressed both in b078724 and e947a5c.

Co-authored-by: Chris Brown <chribrow@redhat.com>
@adelton
adelton force-pushed the podman-entitlement branch from e947a5c to 14c6864 Compare July 28, 2026 15:08
@adelton

adelton commented Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

Rebased on main, fixed the branches: [main], squashed, force-pushed as a single commit 14c6864.

@snecklifter

Copy link
Copy Markdown
Contributor

Thanks @adelton for the contribution and for working through all the review feedback — this is a solid addition. Merged!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants