Skip to content

feat(ssl-certs): add --ssl-certs flag to bundle CA certificates into images#81

Open
feloy wants to merge 1 commit into
openkaiden:mainfrom
feloy:certs
Open

feat(ssl-certs): add --ssl-certs flag to bundle CA certificates into images#81
feloy wants to merge 1 commit into
openkaiden:mainfrom
feloy:certs

Conversation

@feloy

@feloy feloy commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Enterprise environments that intercept HTTPS traffic with corporate proxies need a custom CA certificate trusted both during the build (so dnf/apt can reach repos) and at runtime (so the agent API calls work). The flag accepts an optional FILE; omitting the value triggers auto-discovery across 7 common Linux CA bundle paths. Certs are installed in the final image via update-ca-trust (DNF) or update-ca-certificates (Ubuntu), and persist into the final sandbox image via the FROM system AS final inheritance.

To test auto-discover mode (uses the host's CA bundle if present):

  openshell-image-builder --ssl-certs= myimage:latest

To test explicit file mode:

  openshell-image-builder \
    --ssl-certs /etc/ssl/certs/ca-certificates.crt \
    myimage:latest

To verify the cert landed in the final image — Ubuntu base (default):

  podman run --rm myimage:latest -c \
    'test -f /usr/local/share/ca-certificates/system-ca.crt && echo found'

To test with other base images, create a config.toml first. DNF-based images (Fedora, UBI, Hummingbird) store the cert under the pki trust path instead. Example configs and the verification command:

  # Fedora
  echo '[openshell_image_builder.base_image]
  image = "fedora"
  tag = "latest"' > /tmp/myconfig/config.toml

  # UBI
  echo '[openshell_image_builder.base_image]
  image = "ubi"
  tag = "latest"' > /tmp/myconfig/config.toml

  # Hummingbird
  echo '[openshell_image_builder.base_image]
  image = "hummingbird"
  tag = "latest-builder"' > /tmp/myconfig/config.toml

Then build and verify:

  openshell-image-builder \
    --config /tmp/myconfig \
    --ssl-certs /etc/ssl/certs/ca-certificates.crt \
    myimage:latest
  podman run --rm myimage:latest -c \
    'test -f /etc/pki/ca-trust/source/anchors/system-ca.crt && echo found'

To verify error on a missing file:

  openshell-image-builder --ssl-certs /nonexistent/bundle.crt myimage:latest
  # exits non-zero with an OS error

Closes #62

@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown

Review Change Stack

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c0e74af7-7097-4b95-8def-ecbd29fbcc23

📥 Commits

Reviewing files that changed from the base of the PR and between 0d33b32 and f5b235f.

📒 Files selected for processing (7)
  • .agents/skills/add-cli-flag/SKILL.md
  • README.md
  • src/certs.rs
  • src/containerfile.rs
  • src/main.rs
  • tests/fixtures/test-ca.crt
  • tests/integration_test.rs
✅ Files skipped from review due to trivial changes (2)
  • tests/fixtures/test-ca.crt
  • .agents/skills/add-cli-flag/SKILL.md
🚧 Files skipped from review as they are similar to previous changes (4)
  • tests/integration_test.rs
  • src/certs.rs
  • src/containerfile.rs
  • src/main.rs

📝 Walkthrough

Walkthrough

This PR adds a new --ssl-certs CLI option, implements CA certificate discovery and staging into the build context, conditionally injects cert installation into generated Containerfiles for Ubuntu and DNF-based images, and includes unit/integration tests plus documentation and a PEM test fixture.

Changes

Add system CA certificates support

Layer / File(s) Summary
Certificate discovery and staging utilities
src/certs.rs
Defines SYSTEM_CA_CERT_PATHS, implements find_system_ca_certificates, copy_from_paths, copy_from_file, writes discovered/explicit cert to context_dir/certs/system-ca.crt, and unit tests for discovery and copy semantics.
Containerfile CA certificate injection
src/containerfile.rs
generate() gains with_ca_certs: bool; Ubuntu and DNF system-stage renderers conditionally emit COPY certs/system-ca.crt and run trust-store update commands; tests and helpers updated to exercise inclusion/omission and ordering.
CLI option parsing and build pipeline integration
src/main.rs
Adds --ssl-certs to Cli, converts to Option<Option<PathBuf>>, stages certs via certs::copy_from_paths or copy_from_file, passes ca_certs_copied into containerfile::generate(), and updates/extends tests including ContainerfileCapture.
Integration tests and fixtures
tests/integration_test.rs, tests/fixtures/test-ca.crt
Adds Ubuntu/Fedora SSL-certs image singletons, build helpers that pass --ssl-certs, ignored integration tests to verify the staged CA bundle inside images and absence when not used, and a PEM fixture. Cleanup list updated.
User documentation
README.md, .agents/skills/add-cli-flag/SKILL.md
Adds "Enterprise environments" section, expands the Full option reference with --ssl-certs=[FILE], and updates skill guidance and examples to show ssl_certs: Option<Option<PathBuf>> wiring and test invocation.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and accurately summarizes the main change: adding a --ssl-certs flag for bundling CA certificates into images.
Description check ✅ Passed The description is highly relevant, explaining the enterprise use case, providing multiple usage examples for auto-discovery and explicit file modes, verification steps for different base images, and error behavior.
Linked Issues check ✅ Passed The PR fulfills the linked issue #62 requirement by implementing support for including system CA certificates in built images for corporate proxy environments during build and runtime.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the --ssl-certs flag feature: CA cert discovery/copying, containerfile generation with cert installation steps, CLI wiring, documentation, tests, and fixtures.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/containerfile.rs (1)

190-220: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Move Ubuntu CA trust setup before the first apt-get network call.

The Ubuntu path currently installs the custom CA only after apt-get update && apt-get install, so it cannot help the package manager trust a corporate MITM/proxy during the build. That misses the core --ssl-certs objective for Ubuntu images, and the test at Lines 1005-1014 now hard-codes that wrong order.

Also applies to: 1005-1014

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/containerfile.rs` around lines 190 - 220, The CA install block is placed
after the apt-get install so custom CA can't be used by the package manager
during build; in the function ubuntu_system_stage move the ca_cert_section (the
COPY certs/... and update-ca-certificates) to appear before the RUN apt-get
update && apt-get install... line in the formatted Dockerfile string so the CA
is installed prior to any network package operations (also update the
corresponding test that asserts order around the same block referenced at lines
~1005-1014 to reflect the new order).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/certs.rs`:
- Around line 67-69: copy_from_file currently treats a zero-byte file as success
and calls write_cert_to_context, which makes callers (e.g., src/main.rs) think
CA certs were staged; change copy_from_file to read the file into content, check
if content.is_empty(), and if so return an Err (e.g.,
io::Error::new(io::ErrorKind::InvalidData, "empty certificate bundle")) instead
of calling write_cert_to_context; keep the existing success path unchanged so
non-empty files still call write_cert_to_context.

---

Outside diff comments:
In `@src/containerfile.rs`:
- Around line 190-220: The CA install block is placed after the apt-get install
so custom CA can't be used by the package manager during build; in the function
ubuntu_system_stage move the ca_cert_section (the COPY certs/... and
update-ca-certificates) to appear before the RUN apt-get update && apt-get
install... line in the formatted Dockerfile string so the CA is installed prior
to any network package operations (also update the corresponding test that
asserts order around the same block referenced at lines ~1005-1014 to reflect
the new order).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9ba0a052-9564-4889-b4d5-08095327b9a5

📥 Commits

Reviewing files that changed from the base of the PR and between 36d30a2 and 0d33b32.

📒 Files selected for processing (7)
  • .agents/skills/add-cli-flag/SKILL.md
  • README.md
  • src/certs.rs
  • src/containerfile.rs
  • src/main.rs
  • tests/fixtures/test-ca.crt
  • tests/integration_test.rs

Comment thread src/certs.rs
@codecov

codecov Bot commented Jun 8, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.18182% with 5 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/main.rs 94.79% 5 Missing ⚠️

📢 Thoughts on this report? Let us know!

@feloy

feloy commented Jun 8, 2026

Copy link
Copy Markdown
Contributor Author

@wherka-ama this is a port of the PR openkaiden/kdn#556 , this repo being the new way to build images for kaiden

@feloy feloy requested review from benoitf, jeffmaury and slemeur June 8, 2026 12:51
…images

Enterprise environments that intercept HTTPS traffic with corporate
proxies need a custom CA certificate trusted both during the build
(so dnf/apt can reach repos) and at runtime (so the agent API calls
work). The flag accepts an optional FILE; omitting the value triggers
auto-discovery across 7 common Linux CA bundle paths. Certs are
installed in the final image via update-ca-trust (DNF) or
update-ca-certificates (Ubuntu), and persist into the final sandbox
image via the FROM system AS final inheritance.

To test auto-discover mode (uses the host's CA bundle if present):
  openshell-image-builder --ssl-certs= myimage:latest

To test explicit file mode:
  openshell-image-builder \
    --ssl-certs /etc/ssl/certs/ca-certificates.crt \
    myimage:latest

To verify the cert landed in the final image — Ubuntu base (default):
  podman run --rm myimage:latest -c \
    'test -f /usr/local/share/ca-certificates/system-ca.crt && echo found'

To test with other base images, create a config.toml first. DNF-based
images (Fedora, UBI, Hummingbird) store the cert under the pki trust
path instead. Example configs and the verification command:

  # Fedora
  echo '[openshell_image_builder.base_image]
  image = "fedora"
  tag = "latest"' > /tmp/myconfig/config.toml

  # UBI
  echo '[openshell_image_builder.base_image]
  image = "ubi"
  tag = "latest"' > /tmp/myconfig/config.toml

  # Hummingbird
  echo '[openshell_image_builder.base_image]
  image = "hummingbird"
  tag = "latest-builder"' > /tmp/myconfig/config.toml

Then build and verify:
  openshell-image-builder \
    --config /tmp/myconfig \
    --ssl-certs /etc/ssl/certs/ca-certificates.crt \
    myimage:latest
  podman run --rm myimage:latest -c \
    'test -f /etc/pki/ca-trust/source/anchors/system-ca.crt && echo found'

To verify error on a missing file:
  openshell-image-builder --ssl-certs /nonexistent/bundle.crt myimage:latest
  # exits non-zero with an OS error

Closes openkaiden#62

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Philippe Martin <phmartin@redhat.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@README.md`:
- Line 25: The heading "### workspace.json fields" jumps from H1 to H3; change
that heading to H2 (replace "### workspace.json fields" with "## workspace.json
fields") or alternatively insert the missing parent H2 above it so the document
follows a proper H1→H2→H3 hierarchy; update any adjacent table-of-contents or
anchors if present to reflect the new heading level.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c0e74af7-7097-4b95-8def-ecbd29fbcc23

📥 Commits

Reviewing files that changed from the base of the PR and between 0d33b32 and f5b235f.

📒 Files selected for processing (7)
  • .agents/skills/add-cli-flag/SKILL.md
  • README.md
  • src/certs.rs
  • src/containerfile.rs
  • src/main.rs
  • tests/fixtures/test-ca.crt
  • tests/integration_test.rs
✅ Files skipped from review due to trivial changes (2)
  • tests/fixtures/test-ca.crt
  • .agents/skills/add-cli-flag/SKILL.md
🚧 Files skipped from review as they are similar to previous changes (4)
  • tests/integration_test.rs
  • src/certs.rs
  • src/containerfile.rs
  • src/main.rs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@README.md`:
- Line 25: The heading "### workspace.json fields" jumps from H1 to H3; change
that heading to H2 (replace "### workspace.json fields" with "## workspace.json
fields") or alternatively insert the missing parent H2 above it so the document
follows a proper H1→H2→H3 hierarchy; update any adjacent table-of-contents or
anchors if present to reflect the new heading level.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c0e74af7-7097-4b95-8def-ecbd29fbcc23

📥 Commits

Reviewing files that changed from the base of the PR and between 0d33b32 and f5b235f.

📒 Files selected for processing (7)
  • .agents/skills/add-cli-flag/SKILL.md
  • README.md
  • src/certs.rs
  • src/containerfile.rs
  • src/main.rs
  • tests/fixtures/test-ca.crt
  • tests/integration_test.rs
✅ Files skipped from review due to trivial changes (2)
  • tests/fixtures/test-ca.crt
  • .agents/skills/add-cli-flag/SKILL.md
🚧 Files skipped from review as they are similar to previous changes (4)
  • tests/integration_test.rs
  • src/certs.rs
  • src/containerfile.rs
  • src/main.rs
🛑 Comments failed to post (1)
README.md (1)

25-25: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix heading level jump at Line 25.

### workspace.json fields skips from H1 to H3, which violates MD001 and can break doc structure/navigation in some renderers. Use ## here (or insert the missing parent H2).

🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 25-25: Heading levels should only increment by one level at a time
Expected: h2; Actual: h3

(MD001, heading-increment)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` at line 25, The heading "### workspace.json fields" jumps from H1
to H3; change that heading to H2 (replace "### workspace.json fields" with "##
workspace.json fields") or alternatively insert the missing parent H2 above it
so the document follows a proper H1→H2→H3 hierarchy; update any adjacent
table-of-contents or anchors if present to reflect the new heading level.

Source: Linters/SAST tools

@jeffmaury jeffmaury left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

What about Windows ?

@feloy

feloy commented Jun 10, 2026

Copy link
Copy Markdown
Contributor Author

What about Windows ?

I would prefer to keep this PR focus on Linux, and create follow-up PRs for other systems

@feloy feloy requested a review from jeffmaury June 10, 2026 15:58

@benoitf benoitf left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I have a question

should it use the ssl cert automatically (without the empty --ssl-certs=)

I would assume that by default it reads them, that I can specify one or that I can disable it with another flag like --disable-ssl-certs but IMHO I'm finding the pattern --ssl-certs= not a classic pattern ?

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.

Add system CA certificates

3 participants