-
Notifications
You must be signed in to change notification settings - Fork 39k
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
node authorizer sets up access rules for dynamic config #60100
node authorizer sets up access rules for dynamic config #60100
Conversation
f708dfd
to
fa553c1
Compare
fa553c1
to
2c870de
Compare
I sent pings trying to get this approved for 1.10 milestone, if it doesn't, so be it. |
|
||
path := "nil" | ||
if node.Spec.ConfigSource != nil { | ||
path = fmt.Sprintf("/api/v1/namespaces/%s/configmaps/%s", namespace, name) |
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.
just log %s/%s namespace/name, no need to make the API path
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 do
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.
done
add a positive and negative test case to the auth/node integration test as well |
if ref := source.ConfigMapRef; ref != nil { | ||
count++ | ||
// name, namespace, and UID must all be non-empty for ConfigMapRef | ||
if ref.Name == "" || ref.Namespace == "" || string(ref.UID) == "" { |
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.
This has been a requirement of dynamic Kubelet config since the original proposal, to require users to be completely explicit (time and space) about which ConfigMap to use. If the UID in the config source doesn't match the UID of the ConfigMap, the Kubelet currently rejects it.
IIRC there were concerns along the lines of ConfigMaps being deleted and recreated with the same name but different content... though this is less of an issue today now that we have the --append-hash
option in kubectl (obviously the potential for in-place ConfigMap mutation still exists, but if users are using --append-hash
I wouldn't expect them to mutate the ConfigMap after creation).
The Kubelet also checkpoints by UID, so it was convenient to already have this specified in the object ref, though I guess if we relaxed this requirement it could just resolve the UID and stick it in the local copy of the config source when it first downloads the ConfigMap.
I can't remember other reasons to require UID, if any.
We should probably discuss this in parallel to this PR; if we relax the UID requirement there is other code that needs to change too, and I'd like to make all those changes in a single, isolated PR. I'm glad you brought this up; having this discussion prior to DKC beta was on my todo list.
|
||
path := "nil" | ||
if node.Spec.ConfigSource != nil { | ||
path = fmt.Sprintf("/api/v1/namespaces/%s/configmaps/%s", namespace, name) |
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 do
defer g.lock.Unlock() | ||
|
||
// nothing to do if we don't have a node | ||
if len(nodeName) > 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.
I guess I wouldn't expect us to get a node with an empty name, but would we catch such a case earlier than this?
// must be called under write lock | ||
// deletes edges from a given vertex type to a given vertex type | ||
// will also delete the "from" nodes if they are orphaned, but will not delete the "to" node | ||
func (g *Graph) deleteEdges_locked(fromType, toType vertexType, toNamespace, toName string) { |
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.
agree wrt tests, will add
pretty much indifferent on whether we make this a generic graph method
g.deleteEdges_locked(configMapVertexType, nodeVertexType, "", nodeName) | ||
|
||
// establish new edges if we have a real ConfigMap to reference | ||
if len(configMapName) > 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.
note to self, also handle empty namespace?
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.
done, now we also skip if the namespace is an empty string
func (g *Graph) DeleteNode(nodeName string) { | ||
g.lock.Lock() | ||
defer g.lock.Unlock() | ||
if len(nodeName) > 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.
this check probably also unnecessary wrt @liggitt's comment above
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 think this whole function is not needed (and was weird anyway, since it didn't actually delete the node)
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.
done
|
||
func (g *graphPopulator) deleteNode(obj interface{}) { | ||
node := obj.(*api.Node) | ||
g.graph.DeleteNode(node.Name) |
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.
Hmm, since we don't actually delete the Node from the graph anyway, that sounds like it'd work.
2c870de
to
1311235
Compare
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.
Updated, still have to add the integration test cases.
|
||
path := "nil" | ||
if node.Spec.ConfigSource != nil { | ||
path = fmt.Sprintf("/api/v1/namespaces/%s/configmaps/%s", namespace, name) |
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.
done
defer g.lock.Unlock() | ||
|
||
// nothing to do if we don't have a node | ||
if len(nodeName) > 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.
There's a similar len(nodeName)
check in this file in AddVolumeAttachment
, is there a reason for this one?
g.deleteEdges_locked(configMapVertexType, nodeVertexType, "", nodeName) | ||
|
||
// establish new edges if we have a real ConfigMap to reference | ||
if len(configMapName) > 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.
done, now we also skip if the namespace is an empty string
func (g *Graph) DeleteNode(nodeName string) { | ||
g.lock.Lock() | ||
defer g.lock.Unlock() | ||
if len(nodeName) > 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.
done
|
||
func (g *graphPopulator) deleteNode(obj interface{}) { | ||
node := obj.(*api.Node) | ||
g.graph.DeleteNode(node.Name) |
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.
done
// must be called under write lock | ||
// deletes edges from a given vertex type to a given vertex type | ||
// will also delete the "from" nodes if they are orphaned, but will not delete the "to" node | ||
func (g *Graph) deleteEdges_locked(fromType, toType vertexType, toNamespace, toName string) { |
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.
added some test cases
56e65a4
to
8069d89
Compare
8e6fdcb
to
105e546
Compare
4ef3454
to
7bb2e74
Compare
This PR makes the node authorizer automatically set up access rules for dynamic Kubelet config. I also added some validation to the node strategy, which I discovered we were missing while writing this.
7bb2e74
to
ab8dc12
Compare
/retest |
Name: "myconfigmapconfigsource", | ||
// validation just requires UID to be non-empty and it isn't necessary for GET, | ||
// so we just use a bogus one for the test | ||
UID: "uid", |
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.
if you have valid data from creating the configmap above, go ahead and set it here
/lgtm |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: liggitt, mtaufen The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
Automatic merge from submit-queue (batch tested with PRs 61829, 61908, 61307, 61872, 60100). If you want to cherry-pick this change to another branch, please follow the instructions here. |
This PR makes the node authorizer automatically set up access rules for
dynamic Kubelet config.
I also added some validation to the node strategy, which I discovered we
were missing while writing this.
This PR is based on another WIP from @liggitt.