-
Notifications
You must be signed in to change notification settings - Fork 30
PolicyContext: add new SetRejectInsecure
method
#355
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
I initially went that way so have code for this as well if we want to compare. Keeping it in draft for now until there's agreement on the approach. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
Just a very quick drive-by, looking at the implementation. The much more important part is designing the semantics of the new option, and I don’t have an opinion on that yet.
Thanks for starting this! I think in the general case what we also want here is something like |
I did briefly look at that. Worth noting that e.g. skopeo today has an |
There’s a degree of implementation difficulty for Podman: Skopeo has the policy configuration centralized, as a top-level option; AFAIK Podman does not, really. So, an option would have to be added to each subcommand individually, or the policy setup would need to be fairly significantly refactored. (Complicating this even more, for Podman, is the “remote” mode where the CLI is an API client to a server on a different VM / machine. Even if we did centralize the CLI handling, we would still need to add the “reject insecure” field (and the pre-existing “signature policy path”) to every single API operation individually. That’s one of the reasons the |
In bootc, we want the ability to assert that signature verification is enforced, but there are no mechanisms for this in the library. Add a new `SetRejectInsecure` method on the `PolicyContext` object which would allow this. Add a new `isInsecure` method on the `PolicyRequirement` interface which then allows `IsRunningImageAllowed` to detect if at least one secure requirement was present. Test generation was `Assisted-by: Claude Code v1.0.120`. Part of containers/skopeo#1829. Signed-off-by: Jonathan Lebon <[email protected]>
✅ A new PR has been created in buildah to vendor these changes: containers/buildah#6409 |
} | ||
|
||
func (pr *prSignedBaseLayer) isInsecure() bool { | ||
return false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Deciding whether “signed base layer” is “secure” is … a weird question. Not really an interesting question, given that this is an unusable stub…
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I guess I should probably just flip this to true
for now and add a FIXME here too to reconsider once it's implemented. It definitely stresses the binary secure vs insecure logic, so it might have to be reworked a bit at that point based on what semantics we want.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reading #355 (comment) , if the semantics is “we authenticated the image at least once”, prSignedBaseLayer
does not meaningfully do that — a child layer on top of the signed ones can change the image in unrestricted ways.
So I think this should just be true
, and no FIXME necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, I left only a nit.
return false, PolicyRequirementError(fmt.Sprintf("No secure policy found for image %s.", transports.ImageName(image.Reference()))) | ||
} | ||
|
||
// We have tested that len(reqs) != 0, so at least one req must have explicitly allowed this image. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Is it needed to update this comment? It seems that having at least one req allowed is not enough to get to R312, since R299 will do a early return if at least one req is not allowed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Either way, I don’t think this PR changes the situation.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment is trying to say “if we get to this point, len(reqs) > 0
and there was at least one req
where allowed == true
”, not “if len(reqs) > 0
and there was at least one req
where allowed == true
, we always get to this point”.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A full review now.
// layers. Users must validate that the layers match their expected digests. | ||
isRunningImageAllowed(ctx context.Context, image private.UnparsedImage) (bool, error) | ||
|
||
// isInsecure returns true if the requirement allows images without any signatures. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
“allows images with unauthenticated contents”, per #355 (comment) ?
(A possible hypothetical to think about is a PolicyRequirement
that “the input reference is a digested reference” — in that case the contents of the image would be authenticated, but by the caller-provided input, not cryptographically. “allows images with unsigned contents”, maybe? Which of the two?)
// SetRejectInsecure modifies insecure policy requirement handling. If | ||
// passed `true`, policy checking by IsRunningImageAllowed will ignore the | ||
// "insecureAcceptAnything" policy type. | ||
func (pc *PolicyContext) SetRejectInsecure(val bool) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The description (and name?) will need updating per the “authenticated contents”/“signed contents” discussion elsewhere.
(Choose the semantics that bootc needs; we can always add one more option with some other semantics in the future if it turned out to be necessary for other users.)
} | ||
|
||
if pc.rejectInsecure && !wasSecure { | ||
return false, PolicyRequirementError(fmt.Sprintf("No secure policy found for image %s.", transports.ImageName(image.Reference()))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
policyIdentityLogName
would be a bit more appropriate, it would more directly point at the relevant policy.json
scope.
// SetRejectInsecure modifies insecure policy requirement handling. If | ||
// passed `true`, policy checking by IsRunningImageAllowed will ignore the | ||
// "insecureAcceptAnything" policy type. | ||
func (pc *PolicyContext) SetRejectInsecure(val bool) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Thinking whether this should reject repeated calls, as an indication of a confused caller … we’d have to add an error return, and all callers would need to check it for all of this to make a difference — that wouldn’t really work, let’s not do that.)
// insecureAcceptAnything only: should be rejected (leaves no secure requirements) | ||
img = pcImageMock(t, "fixtures/dir-img-valid", "testing/manifest:insecureOnly") | ||
res, err = pc.IsRunningImageAllowed(context.Background(), img) | ||
assert.Equal(t, false, res) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assertRunningRejectedPolicyRequirement
please, in both of the “error” situations.
In bootc, we want the ability to assert that signature verification is enforced, but there are no mechanisms for this in the library.
Add a new
SetRejectInsecure
method on thePolicyContext
object which would allow this.Since this only changes the behaviour of the
insecureAcceptAnything
policy requirement, rather than extending the policy requirement interface, I went with a filtering approach directly inIsRunningImageAllowed()
.Test generation was
Assisted-by: Claude Code v1.0.120
.Part of containers/skopeo#1829.