Skip to content

docs: add a how-to guide for securing a charm - #2721

Open
tonyandrewmeyer wants to merge 6 commits into
canonical:mainfrom
tonyandrewmeyer:docs/2656-secure-your-charm
Open

docs: add a how-to guide for securing a charm#2721
tonyandrewmeyer wants to merge 6 commits into
canonical:mainfrom
tonyandrewmeyer:docs/2656-secure-your-charm

Conversation

@tonyandrewmeyer

@tonyandrewmeyer tonyandrewmeyer commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

The security explanation finishes with a list of good practices, but there's nowhere task-oriented to send someone who has been asked to harden a charm, so this adds a how-to that turns those practices into sections you can work through: keeping sensitive data out of logs and traces, Juju secrets, HTTPS for tracing, static checks, keeping dependencies patched, restricting what the charm can do on its host, hardening the workload, checking the deployed ops version, documenting the posture, and reporting vulnerabilities. The explanation index now points at it, so you can go from why to what.

Preview.

Fixes #2656

The security explanation ends with a list of good practices, but there
was nowhere task-oriented to send someone who has been asked to harden
a charm. Turn those practices into a how-to they can work through, and
link the two pages to each other.
Comment thread docs/howto/index.md Outdated
@tonyandrewmeyer
tonyandrewmeyer marked this pull request as ready for review September 6, 2026 23:42

@james-garner-canonical james-garner-canonical 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.

Looks good. My review is mostly editorial, but two actual comments:

  1. The point about the workload surfacing information through hook tools and events is confusing to me -- I guess the meaning is that Juju may surface output directly from the workload? (May it? Is it not all charm mediated?)
  2. codespell seems like an odd recommendation for a security guide -- perhaps drop it or expand on the rationale.

Comment thread docs/howto/secure-your-charm.md Outdated
- {external+juju:ref}`Juju | Harden your deployment <harden-your-deployment>`
- {external+pebble:ref}`Pebble | Security <security>`

This guide walks through the actions that a charm author takes to harden a charm that uses Ops, and points to the parts of the [security explanation](#security) that describe why each action matters. Work through the steps that apply to your charm; not every workload needs every step.

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.

Suggested change
This guide walks through the actions that a charm author takes to harden a charm that uses Ops, and points to the parts of the [security explanation](#security) that describe why each action matters. Work through the steps that apply to your charm; not every workload needs every step.

or

Suggested change
This guide walks through the actions that a charm author takes to harden a charm that uses Ops, and points to the parts of the [security explanation](#security) that describe why each action matters. Work through the steps that apply to your charm; not every workload needs every step.
This guide covers how to to harden a charm that uses Ops. Not every step will apply to every charm. Read the security explanation for Ops itself at [](#security).

@tonyandrewmeyer tonyandrewmeyer Sep 10, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I've done a mix of this, making it smaller in particular. I don't think we need the link because it's just above this in the see first link.

Comment thread docs/howto/secure-your-charm.md Outdated

## Keep sensitive data out of the observable surface

Ops forwards charm logs to Juju through the `juju-log` hook command, buffers trace data locally, and lets the workload surface information back through hook commands and events. Any of these can end up in operator-visible places -- `juju debug-log`, `juju status`, trace receivers, crash reports, or the state database on disk.

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.

Suggested change
Ops forwards charm logs to Juju through the `juju-log` hook command, buffers trace data locally, and lets the workload surface information back through hook commands and events. Any of these can end up in operator-visible places -- `juju debug-log`, `juju status`, trace receivers, crash reports, or the state database on disk.
Ops calls the `juju-log` hook command to send charm logs to Juju. Trace data is buffered locally. The workload surfaces information back through hook commands and events. Any of these can end up in places visible to Juju users, like `juju debug-log`, `juju status`, trace receivers, crash reports, or the state database on disk.

I'm not actually sure what it means that the workload surfaces information back through hook commands and events though. Workloads don't call hook commands (though I guess a Juju aware workload in a machine charm could, if it got the timing right?), nor do they trigger events directly.

Comment thread docs/howto/secure-your-charm.md Outdated

## Store and share sensitive data with Juju secrets

Use {external+juju:ref}`Juju secrets <secret>` for anything that a charm needs to keep confidential -- credentials, tokens, TLS material, and so on. Juju stores the value, controls which units can read it, and rotates access when relations change.

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.

Suggested change
Use {external+juju:ref}`Juju secrets <secret>` for anything that a charm needs to keep confidential -- credentials, tokens, TLS material, and so on. Juju stores the value, controls which units can read it, and rotates access when relations change.
Use {external+juju:ref}`Juju secrets <secret>` for anything that a charm needs to keep confidential, like credentials, tokens, or TLS material. Juju stores the value, controls which units can read it, and rotates access when relations change.

Comment thread docs/howto/secure-your-charm.md Outdated
Comment thread docs/howto/secure-your-charm.md Outdated

- **`ruff`** for Python lint rules, including [`ruff`'s Bandit-derived security rules](https://docs.astral.sh/ruff/rules/#flake8-bandit-s). Enable the `S` rule set in `pyproject.toml`.
- **`zizmor`** for GitHub Actions workflow audits. Configure it to run on every push against the workflow files in `.github/workflows/`.
- **`codespell`** or an equivalent to catch typos in log messages and comments that would otherwise reach operators.

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.

IMO this doesn't really fit as a security practice.

Suggested change
- **`codespell`** or an equivalent to catch typos in log messages and comments that would otherwise reach operators.

Comment thread docs/howto/secure-your-charm.md Outdated

## Restrict what the charm can do on its host

Machine charms and Kubernetes charms have different levers here:

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.

Suggested change
Machine charms and Kubernetes charms have different levers here:
Machine charms and Kubernetes charms manage permissions in different ways.

Comment thread docs/howto/secure-your-charm.md Outdated

Machine charms and Kubernetes charms have different levers here:

**Machine charms.** Set an explicit `os.umask()` before creating files or directories the workload will use, so that group- and world-permissions are not inherited from whatever the calling context happened to be. Set ownership on files and directories the charm creates for the workload user.

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.

Suggested change
**Machine charms.** Set an explicit `os.umask()` before creating files or directories the workload will use, so that group- and world-permissions are not inherited from whatever the calling context happened to be. Set ownership on files and directories the charm creates for the workload user.
**Machine charms.** Set an explicit `os.umask()` before creating files or directories the workload will use, so that permissions are not inherited from whatever the calling context happened to be. Set ownership on files and directories the charm creates for the workload user.


**Machine charms.** Set an explicit `os.umask()` before creating files or directories the workload will use, so that group- and world-permissions are not inherited from whatever the calling context happened to be. Set ownership on files and directories the charm creates for the workload user.

**Kubernetes charms.** Prefer running the charm and its sidecar containers as a non-root user. Set the {external+charmcraft:ref}`charm-user key in charmcraft.yaml <charmcraft-yaml-key-charm-user>` to `non-root`, and set an explicit `uid` and `gid` on each container in `charmcraft.yaml`.

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.

Can we flag this somehow as a linking off point when we add broader docs for rootless charms? Maybe unnecessary.

Comment thread docs/howto/secure-your-charm.md Outdated
Comment on lines +103 to +104

The security explanation for Ops itself lives at [](#security); mirror that structure in your charm if it helps operators reason about the deployment.

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.

Suggested change
The security explanation for Ops itself lives at [](#security); mirror that structure in your charm if it helps operators reason about the deployment.

or

Suggested change
The security explanation for Ops itself lives at [](#security); mirror that structure in your charm if it helps operators reason about the deployment.
The security explanation for Ops itself lives at [](#security). It may be helpful to follow a similar structure for your charm's security documentation.

Comment thread docs/howto/secure-your-charm.md Outdated
---
myst:
html_meta:
description: Concrete steps for securing a charm that uses Ops -- handling sensitive data, restricting access, hardening dependencies, and reporting vulnerabilities.

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.

Is "hardening dependencies" accurate?

tonyandrewmeyer and others added 2 commits September 7, 2026 23:40
Correct the claim that the workload surfaces information through hook
commands and events: it is the charm that does the surfacing, including
anything it has read from the workload.

Drop the codespell recommendation, which is a documentation-quality
practice rather than a security one, and trim wording that repeated the
See first list or the section lead-in. Mention release cooldowns and
name stable as the destination for rebuilt charms.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014RHPGNMVAVc1duuTnfJwEJ
Vale's US spellcheck flags "cooldown", which the dependency-patching
section uses twice, so add it to the custom wordlist.

Also shorten the opening sentence, following review feedback.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U9L3maZSswQsHoPCZP57ch
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 how-to guide about securing a charm

2 participants