-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
Additional registry whitelisting #17783
Additional registry whitelisting #17783
Conversation
7c8b944
to
842eba4
Compare
/test @openshift/sig-developer-experience I'm working on integration test now. Documentation is missing but otherwise ready for review. |
issue for the image registry tests: #17786 |
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.
will try to give this a more thorough review tomorrow.
|
||
// RegistryWhitelister decides whether given image pull specs are allowed by system's image policy. | ||
type RegistryWhitelister interface { | ||
// AdmitHostname returns error if the given host is allowed by the whitelist. |
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.
is not allowed?
// TODO: accept insecure flag | ||
WhitelistPullSpecs(pullSpecs ...string) | ||
// Copy returns a deep copy of the whitelister. This is useful for temporarily whitelisting additional | ||
// registires/pullSpecs before a specific validation. |
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.
typo on registries.
bf1d062
to
e8a26ae
Compare
Why are we doing this in admission again? |
There's no admission controller. The functionality is just located in the admission package since it's closely related. All the admission happens in ImageStream(Tag)'s strategy. I'll rename the package to avoid confusion. |
e00604b
to
46fd247
Compare
Rebased, moved logic from PTAL |
46fd247
to
befd2b5
Compare
Added integration test. |
Flake #17769 |
result := validation.ValidateObjectMeta(&stream.ObjectMeta, true, ValidateImageStreamName, field.NewPath("metadata")) | ||
|
||
// Ensure we can generate a valid docker image repository from namespace/name | ||
if len(stream.Namespace+"/"+stream.Name) > reference.NameTotalLengthMax { | ||
result = append(result, field.Invalid(field.NewPath("metadata", "name"), stream.Name, fmt.Sprintf("'namespace/name' cannot be longer than %d characters", reference.NameTotalLengthMax))) | ||
} | ||
|
||
insecureRepository := isRepositoryInsecure(stream) | ||
|
||
if len(stream.Spec.DockerImageRepository) != 0 { |
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.
we don't whitelist check stream.Spec.DockerImageRepository itself? Does something else prevent a user from importing a disallowed image via that mechanism?
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.
There's a prevention mechanism - the individual tags get refused. But I agree it would be better to admit this spec as well to avoid needless frequent import errors. I'll fix this.
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.
various questions on some of the port matching/denying behavior, but the fundamentals lgtm.
stringsutil "github.com/openshift/origin/pkg/util/strings" | ||
) | ||
|
||
// WhitelistTransport says whether the associated registry host shell be treated as secure or insecure. |
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.
s/shell/shall/
// <host>, <host>:<port> | ||
// where each component can contain wildcards like '*' or '??' to mach wide range of registries. If the | ||
// port is omitted, the default will be appended based on the given transport. If the transport is "any", | ||
// the given blob will match hosts with both :80 and :443 ports. |
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.
s/blob/glob/
pullSpecs: sets.NewString(), | ||
registryHostRetriever: registryHostRetriever, | ||
} | ||
// iterate in reversed order to make the patterns appear in the same order as given (patters are prepended) |
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.
s/patters/patterns/
"localhost:443": nil, | ||
"localhost:5000": fmt.Errorf(`registry "localhost:5000" not allowed by whitelist { "*:443" }`), | ||
"localhost:80": fmt.Errorf(`registry "localhost:80" not allowed by whitelist { "*:443" }`), | ||
"localhost": nil, |
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.
why are "localhost", "docker.io", and "example.com" allowed here, when they are not on port 443?
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.
That's because *
wildcard in the whitelist defaults to a secure port :443
. All the given hostnames also default to :443
because of the WhitelistTransportSecure
. Therefor, their ports will match.
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.
ok
hostnames: map[string]error{ | ||
"docker.io": nil, | ||
"example.com": nil, | ||
"localhost:443": fmt.Errorf(`registry "localhost:443" not allowed by whitelist { "*:80" }`), |
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.
why isn't 443 not allowed for "any transport"? especially when :80 is 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.
mkAllowed
creates AllowedRegistries
with Insecure
flag set. Therefor the whitelist looks like the error suggests: { "*:80" }
. Thus any given hostname must either have :80
port specified or be passed with one of {any, insecure}
transport.
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.
ok i think i understand this now as well.
"a.b.c.d.foo.com:80": nil, | ||
"domain.ltd": nil, | ||
"example.com": nil, | ||
"foo.com": fmt.Errorf(`registry "foo.com" not allowed by whitelist { "localhost:5000", "docker.io:80", "example.com:*", "registry.com:80", and 2 more ... }`), |
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.
on what basis is foo.com denied? the whitelist has *.foo.com and allow insecure.
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 whitelisted registry has .
as a prefix. Therefore it matches any sub-domain of foo.com
but not the domain itself. I'd like to avoid additional logic on special treating *.
. If the admin wants to match the domain as well, he can add the second entry without the leading *.
.
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.
i'm still unclear on this one. I would expect *.foo.com to match foo.com.
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.
discussed on irc
hp.host = parts[0] | ||
switch transport { | ||
case WhitelistTransportAny: | ||
hp.port = "*" |
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.
I've just realized this is way too benevolent. any
should mean either secure (:443
) or insecure (:80
) not "any transport protocol". I'll fix this.
Addressed comments. |
1a81d12
to
945f73d
Compare
@miminar lgtm, squash and i'll merge. |
/retest Please review the full test history for this PR and help us cut down flakes. |
/hold
Possibly, if someone has an integration that relied on working around the configured imagepolicy rules that weren't being enforced properly. Otherwise it's not obvious to me what this would break, do you have something in mind?
The backwards compatibility logic is that on update, @miminar has dynamically whitelisted existing values, so this logic only prevents the creation of new imagestreams w/ disallowed values, or the updating of an existing one that adds a new disallowed value.
Can you elaborate on this? This is image import, so someone specifies an image they want to import. Whether they fully qualify it or not doesn't matter to us, we're just going to see if it matches the allowed registries/imagespecs (fully qualified or otherwise) the admin specified. Assuming you mean that we should be automatically qualifying unqualified specifications, would you expect us to do that on the whitelist side, or the value being checked side? both? What would we default to? How does the existing image-import logic handle defaulting an unqualified import request? It looks to me like it just assumes docker.io, because this fails:
while this succeeds:
and this succeeds (via docker.io):
so it is not respecting the docker daemon search list, because this succeeds on my host:
|
63e2525
to
03f9742
Compare
Addressed the comments except for those answered by Ben since I agree with him. |
03f9742
to
a78e5eb
Compare
/retest |
Signed-off-by: Michal Minář <[email protected]>
a78e5eb
to
dd4851b
Compare
@miminar I talked with @smarterclayton, this is good to go but we'll need a follow up that updates the whitelisting logic in the following way: if the image the user wants to import/reference does not have a registry qualification on it, we need to prepend "docker.io" as the registry before checking it against the whitelist, because ultimately that is the registry we import from for unqualified image values. (or if you just want to make that change in this PR, that's fine too) |
I don't understand why a whitelisting/validation logic should do any changes to the input data at all. If desired, I can do a follow up. |
it's something the image import policy should have always been doing, because ultimately the image import logic is qualifying image values with "docker.io" if they are unqualified, so the whitelisting should be checking them as if they had that prefix. |
That's already the case for If I understand #18020 correctly, the qualification will be done for us in a level below (closer to etcd). If this PR merges as is before #18020, the whitelisting will be broken once #18020 merges (without touching the whitelister) because whitelister will treat unqualified images differently. So either
I'm fine with both variants. @bparees @frobware what do you think? |
@miminar my impression is they are unrelated. #18020 is due to a change in kubernetes behavior w/ respect to what image will get run when a pod which references an unqalified image name is created (prior to the latest kube release, the image would get qualified by the docker daemon. Now, unqualified images are always qualified as being from docker.io. Thus #18020 introduces a higher level qualifier that can qualify images differently before kube sees them and prepends docker.io) None of that has any bearing on how image importing is done. Image import, near as I can tell, always treated unqualified image references as coming from docker.io. And the image import whitelisting behavior should do the same (if someone tries to import an unqualified image name, we should prepend docker.io and then check it against the whitelist). It sounds like you're saying that already happens, so we're fine. Can you elaborate on how you think #18020 will break the image import whitelister? |
It won't actually break the whitelister. But there will be a mismatch between the whitelister always defaulting to But this "mismatching" could be fixed in a follow-up as well. |
@miminar i'm still unclear on one thing. if a user attempts to define an imagestream with a reference to "openshift/jenkins-2-centos7" and the whitelister only includes "docker.io" as an allowed registry, will this imagestream be allowed or not? in my opinion it should be, since we are going to import from docker.io in this case. |
@bparees in the current state of things, yes. However, with a follow-up, where the qualification rules get applied before/during whitelisting, it may no longer be the case. |
/hold cancel |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: bparees, miminar The full list of commands accepted by this bot can be found here.
Needs approval from an approver in each of these OWNERS Files:
You can indicate your approval by writing |
/retest Please review the full test history for this PR and help us cut down flakes. |
Flake #17694 |
/retest Please review the full test history for this PR and help us cut down flakes. |
Automatic merge from submit-queue. |
Adds validation to imagestreams and imagestreamtags that forbids new image pull specs not present on the whitelist.
Resolves bz#1505315