Skip to content

Use unified configfile parser for policy.json#711

Open
jankaluza wants to merge 4 commits intocontainers:mainfrom
jankaluza:policy.json
Open

Use unified configfile parser for policy.json#711
jankaluza wants to merge 4 commits intocontainers:mainfrom
jankaluza:policy.json

Conversation

@jankaluza
Copy link
Copy Markdown
Member

@jankaluza jankaluza commented Mar 23, 2026

This PR switches policy.json loading to the unified storage/pkg/configfile parser instead of maintaining separate lookup logic in image/signature.

The SignaturePolicyPath support is preserved, so explicit callers continue to work as before. The policy loader also now uses CONTAINERS_POLICY_JSON for environment-based override. The CONTAINERS_POLICY_JSON_OVERRIDE remains ignored for policy.json because drop-in loading is disabled for that this configuration file.

It also extends the configfile API to return the paths it searched. This is showed to users when there is no policy.json found.

Fixes: #207
Fixes: #202

@github-actions github-actions bot added common Related to "common" package image Related to "image" package labels Mar 23, 2026
@jankaluza
Copy link
Copy Markdown
Member Author

@Luap99 , Hi, could you please check if this PR makes a sense? I also added two questions for parts of code I'm not sure about...

Copy link
Copy Markdown
Contributor

@mtrmac mtrmac left a comment

Choose a reason for hiding this comment

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

Just an extremely brief skim.

@github-actions github-actions bot added the storage Related to "storage" package label Mar 24, 2026
@jankaluza jankaluza changed the title WIP: Use unified configfile parser for policy.json Use unified configfile parser for policy.json Mar 24, 2026
Copy link
Copy Markdown
Member

@Luap99 Luap99 left a comment

Choose a reason for hiding this comment

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

it would be good to if you can squash the re-add SignaturePolicyPath commits, i.e when reviewing this it makes no sense to look at something getting remove to be added again. It also break git bisect most likely when vendoring from another repo.

}

if conf.EnvironmentName != "" {
if conf.EnvironmentName != "" && !conf.DoNotLoadDropInFiles {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

please add a new test case here for that behavior

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.

And document that behavior! It’s rather unexpected based on plain reading of the current option (although there is some logic to it).

Probably not, but maybe we’d want s/DoNotLoadDropInFiles/DropInFilesUnsupported/ ?!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I am in favour of naming it DropInFilesUnsupported, though then I guess we would want to rename DoNotLoadMainFiles as well to MainFilesUnsupported? I suppose we could rename that outside of the scope of this PR if wanted.

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.

I kind of think of them as different dimensions: “do not load a file at $this path” is more of a directive vs. “the consumer cannot process multiple drop-ins regardless of names” is more of a capability declaration, but that’s a very weak reasoning.

I’m also quite fine with leaving the name as is.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I would remove that in another PR if possible to not add more unrelated changes to this one if that's fine for you. I added the documentation part, that's good point :-).

Copy link
Copy Markdown
Contributor

@mtrmac mtrmac left a comment

Choose a reason for hiding this comment

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

Thanks!

}

if conf.EnvironmentName != "" {
if conf.EnvironmentName != "" && !conf.DoNotLoadDropInFiles {
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.

And document that behavior! It’s rather unexpected based on plain reading of the current option (although there is some logic to it).

Probably not, but maybe we’d want s/DoNotLoadDropInFiles/DropInFilesUnsupported/ ?!

@jankaluza jankaluza force-pushed the policy.json branch 3 times, most recently from 89fd676 to d9da724 Compare March 30, 2026 14:07
Copy link
Copy Markdown
Contributor

@mtrmac mtrmac left a comment

Choose a reason for hiding this comment

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

I didn’t carefully read the added tests or think about coverage, I’m hoping for a simpler version first.

There are also a bunch of earlier outstanding review comments.

// Expected ENOENT errors are already ignored in this function and must not be handled again by callers.
// The given File options must not be nil and populated with valid options.
//
// The _OVERRIDE environment is ignored if DoNotLoadDropInFiles is set.
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.

This does not talk about _OVERRIDE so this is a bit of an unexpected place to suddenly go into this detail.


OTOH the EnvironmentName field does not document _OVERRIDE, and I think it should. That might also be a place to add that note.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This comment is still open, documenting this behavior on the function comment feels odd and duplicated. Having it as part of the struct field comments seem enough.

@packit-as-a-service
Copy link
Copy Markdown

Packit jobs failed. @containers/packit-build please check.

Copy link
Copy Markdown
Member

@Luap99 Luap99 left a comment

Choose a reason for hiding this comment

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

(commit 3 should be squashed into commit 1 and that one needs WIP stripped)

@Luap99
Copy link
Copy Markdown
Member

Luap99 commented Apr 8, 2026

@mtrmac are you fine with the new approach suggested by me?

@jankaluza Generally speaking I would like to see a "clean" history, i.e. not add ReadWithPaths just to remove it again as this makes reviewing harder but lets with for @mtrmac feedback first

@jankaluza
Copy link
Copy Markdown
Member Author

@Luap99 , yeah, I will squash the commits before merge.

Copy link
Copy Markdown
Contributor

@mtrmac mtrmac left a comment

Choose a reason for hiding this comment

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

Sure, the ErrorIfNotFound approach is (given the signature-side test) fine. We can rework storage/configfile as needed. ACK overall.

Some outstanding nits:

Replace custom path resolution with configfile.Read and remove
legacy SignaturePolicyPath defaults and helpers.

Fixes: containers#207
Fixes: containers#202

Signed-off-by: Jan Kaluza <jkaluza@redhat.com>
This commit introduces `File.ErrorIfNotFound`. If it is true, the Read
returns an error which contains all the paths it tried when searching
for a config file.

It uses this in DefaultPolicy() to include the searched paths in
the error message when no policy file is found.

The useless policy_paths_*.go files are removed.

Signed-off-by: Jan Kaluza <jkaluza@redhat.com>
// Expected ENOENT errors are already ignored in this function and must not be handled again by callers.
// The given File options must not be nil and populated with valid options.
//
// The _OVERRIDE environment is ignored if DoNotLoadDropInFiles is set.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This comment is still open, documenting this behavior on the function comment feels odd and duplicated. Having it as part of the struct field comments seem enough.

Return an error if multiple policy files are encountered, which should
not happen with configfile.Read.

Update tests to use full Policy comparisons and cover nil/empty
SystemContext cases.

Clarify CONTAINERS_POLICY_JSON and *_OVERRIDE behavior in docs.

Signed-off-by: Jan Kaluza <jkaluza@redhat.com>
@jankaluza
Copy link
Copy Markdown
Member Author

@Luap99 , I fixed the issues you've pointed out.

Copy link
Copy Markdown
Member

@Luap99 Luap99 left a comment

Choose a reason for hiding this comment

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

Thanks, LGTM overall though I have not checked the policy.json tests in detail. I defer that to @mtrmac.

Did you run this trough podman and buildah CI to make sure they are no problmes and we can vendor this cleanly there?

@jankaluza
Copy link
Copy Markdown
Member Author

I have not checked buildah. I'll do that first thing tomorrow morning.

Introduce ErrConfigFileNotFound error. This can be used by API caller
to detect the File not found error and handle this situation.

Signed-off-by: Jan Kaluza <jkaluza@redhat.com>
@jankaluza
Copy link
Copy Markdown
Member Author

@Luap99, I've added one more commit.

@jankaluza
Copy link
Copy Markdown
Member Author

@jankaluza
Copy link
Copy Markdown
Member Author

}
if policy != nil {
// Coverage: This should never happen, configfile.Read ensures at most one policy file.
return nil, fmt.Errorf("internal error: expected at most one policy file, got another item %q", item.Name) //nolint:revive
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.

What is the nolint directive supposed to silence? (We don’t have revive enabled and) when removing that directive and manually running golangci-lint run --max-issues-per-linter 0 --max-same-issues 0 --enable=revive ./image/signature I see nothing reported on this line.

If it is truly necessary, please use //nolint:revive // a short explanation what this is trying to silence and/or why silencing that is OK

}

if conf.ErrorIfNotFound && !foundAny {
yield(nil, fmt.Errorf("%w: no %s file found; searched paths: %q", ErrConfigFileNotFound, configFileName, usedPaths))
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.

I’m not asking for any change, just noting the possibility: If you want ErrConfigFileNotFound to be used without using any part of its error text, it is possible to use %.0w with Errorf.

By default, the policy is read from `$XDG_CONFIG_HOME/containers/policy.json` (or from `$HOME/.config/containers/policy.json` if `$XDG_CONFIG_HOME` is unset), if it exists; otherwise from `/etc/containers/policy.json`; otherwise from `/usr/share/containers/policy.json`. Applications performing verification may allow using a different policy instead.

If `CONTAINERS_POLICY_JSON` is set, it specifies the policy file to use,
unless overridden by application-specific configuration.
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.

(Absolutely non-blocking: This works fine.

“the policy is read from $CONTAINERS_POLICY_JSON if set; otherwise from $HOME … ; … /usr/share…. Applications … may allow using a different policy instead” might be a simpler way to say the same thing, representing this as a single linear order, and not repeating the application-specific part.


Also, pre-existing, maybe s/may allow using/may choose to use.)

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

Labels

common Related to "common" package image Related to "image" package storage Related to "storage" package

Projects

None yet

3 participants