Skip to content
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

Limit kubelets from updating their own labels when NodeRestriction is enabled #68267

Merged
merged 1 commit into from
Nov 15, 2018

Conversation

liggitt
Copy link
Member

@liggitt liggitt commented Sep 5, 2018

Implements phase 1 of https://github.com/kubernetes/community/blob/master/keps/sig-auth/0000-20170814-bounding-self-labeling-kubelets.md#implementation-timeline

Docs PR in kubernetes/website#10944

This PR:

  • Prevents kubelets from adding/modifying labels prefixed with node-restriction.kubernetes.io on their Node objects
  • Restricts which kubernetes.io labels kubelets can set when updating their Node objects to an allowed set of labels and label prefixes
  • Warns on kubelet startup if kubernetes.io labels outside that set are passed via --node-labels (will escalate to an error in v1.15)
  • Warns in admission if kubernetes.io labels outside that set are passed on Node creation (will escalate to a forbidden error in v1.17)

/sig auth
/sig node
/sig storage

/cc @mikedanese @verult @saad-ali @vishh

kube-apiserver: the `NodeRestriction` admission plugin now prevents kubelets from modifying `Node` labels prefixed with `node-restriction.kubernetes.io/`. The `node-restriction.kubernetes.io/` label prefix is reserved for cluster administrators to use for labeling `Node` objects to target workloads to nodes in a way that kubelets cannot modify or spoof.

kubelet: it is now deprecated to use the `--node-labels` flag to set `kubernetes.io/` and `k8s.io/`-prefixed labels other than the following labels:
* `kubernetes.io/hostname`
* `kubernetes.io/instance-type`
* `kubernetes.io/os`
* `kubernetes.io/arch`
* `beta.kubernetes.io/instance-type`
* `beta.kubernetes.io/os`
* `beta.kubernetes.io/arch`
* `failure-domain.kubernetes.io/zone`
* `failure-domain.kubernetes.io/region`
* `failure-domain.beta.kubernetes.io/zone`
* `failure-domain.beta.kubernetes.io/region`
* `[*.]kubelet.kubernetes.io/*`
* `[*.]node.kubernetes.io/*`
Setting other `kubernetes.io/`- and `k8s.io/`-prefixed labels using the `--node-labels` flag will produce a warning in v1.13, and be disallowed in v1.15. Setting labels that are not prefixed with `kubernetes.io/` or `k8s.io/` is still permitted.

@k8s-ci-robot k8s-ci-robot added sig/auth Categorizes an issue or PR as relevant to SIG Auth. size/M Denotes a PR that changes 30-99 lines, ignoring generated files. do-not-merge/release-note-label-needed Indicates that a PR should not merge because it's missing one of the release note labels. sig/node Categorizes an issue or PR as relevant to SIG Node. sig/storage Categorizes an issue or PR as relevant to SIG Storage. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. approved Indicates a PR has been approved by an approver from all required OWNERS files. release-note Denotes a PR that will be considered when it comes time to generate release notes. and removed do-not-merge/release-note-label-needed Indicates that a PR should not merge because it's missing one of the release note labels. labels Sep 5, 2018
@liggitt
Copy link
Member Author

liggitt commented Sep 5, 2018

cc @vikaschoudhary16 @derekwaynecarr since the plugin watcher looks to be the most immediate source of expanding kubelet self-labeling.

is that attempting to go to beta in 1.12?
yes, in #68200

edit: talked with @verult, #67684 is the PR that adds self-labeling to the kubelet for CSI drivers. it is currently behind the PluginWatcher gate, but if that goes to beta, we risk shipping 1.12 with uncontrolled self-updates by kubelets.

can we fence that capability of that PR until we can coordinate label controls for kubelets?

@liggitt liggitt assigned liggitt and unassigned liggitt Sep 22, 2018
@dims
Copy link
Member

dims commented Sep 24, 2018

/assign @yujuhong

@vishh
Copy link
Contributor

vishh commented Sep 28, 2018

@liggitt

Use cases like device plugins and CSI drivers intend to use self-added labels to express topology, which is fine, but those use cases need to be coordinated with controls the cluster-admin can use to ensure labels remain useful for partitioning a cluster along security-related boundaries

Can you explain this more? I want to make sure usability isn't compromised a lot. Poking a hole in RBAC isn't safe today for node level daemons.

@liggitt
Copy link
Member Author

liggitt commented Oct 5, 2018

Can you explain this more? I want to make sure usability isn't compromised a lot. Poking a hole in RBAC isn't safe today for node level daemons.

For things the kubelet is expected to self-report topology for (device drivers and CSI come to mind), one possibility would be to have a registration object for the device class or CSI driver that includes the list of label keys that will be used for topology. For example, CSI has the CSIDriver object which would be a natural place to put that info (and has benefits beyond authorization... today the CSI provisioner has to pick a node at random to determine what the topology keys are).

That registration object would not be kubelet-writeable. The node admission plugin could then allow kubelets to self-set labels that were designated as topology labels by one of those registration objects.

@vishh
Copy link
Contributor

vishh commented Oct 8, 2018 via email

@liggitt
Copy link
Member Author

liggitt commented Oct 8, 2018

How is auth managed for the plugins that write this secondary object which will then get copied over to the Node Object?

Either the cluster admin or something at the control plane level would be expected to set those objects up (it could be part of the manifest or add-on that set up the device driver or CSI plugin)

@k8s-ci-robot k8s-ci-robot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Oct 17, 2018
@liggitt
Copy link
Member Author

liggitt commented Oct 23, 2018

cc @kubernetes/sig-auth-pr-reviews @kubernetes/sig-node-pr-reviews @kubernetes/sig-storage-pr-reviews

@liggitt liggitt added this to the v1.13 milestone Oct 23, 2018
Copy link
Member

@mikedanese mikedanese left a comment

Choose a reason for hiding this comment

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

Looks reasonable. Who needs to sign off on this?

plugin/pkg/admission/noderestriction/admission.go Outdated Show resolved Hide resolved
{
name: "allow create of my node with labels",
podsGetter: noExistingPods,
attributes: admission.NewAttributesRecord(mynodeObjLabelA, nil, nodeKind, mynodeObj.Namespace, "", nodeResource, "", admission.Create, false, mynode),
Copy link
Member

Choose a reason for hiding this comment

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

s/mynodeObj.Namespace/mynodeObjLabelA.Namespace/ here and below? Or just omit it. We are already omitting the name and nodes aren't namespaced. It looks like a number of other test cases are sloppy as well.

Copy link
Member Author

Choose a reason for hiding this comment

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

it doesn't actually bother me to pass the empty object namespace in, and the name of all the mynode*test fixtures is identical, the point of the different ones is to change other fields in the object. will address separately if desired, trying to keep the test diff readable.

@mikedanese
Copy link
Member

/lgtm
/approve

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Nov 14, 2018
@liggitt
Copy link
Member Author

liggitt commented Nov 14, 2018

/assign derekwaynecarr tallclair
for pkg/kubelet approval

@derekwaynecarr
Copy link
Member

kubelet changes look good to me.

/lgtm
/approve

@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: derekwaynecarr, liggitt, mikedanese

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 /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Nov 15, 2018
@liggitt
Copy link
Member Author

liggitt commented Nov 15, 2018

/retest

@k8s-ci-robot k8s-ci-robot merged commit 504466c into kubernetes:master Nov 15, 2018
@liggitt liggitt deleted the node-label-update branch November 16, 2018 21:23
@kfox1111
Copy link

kfox1111 commented Dec 4, 2018

Saw this in the release notes. This is very good to see.

One thing I don't understand though. To really solve the issue, all usage of labels that could ever have security ramifications now would be required to be prefixed with kubernetes.io/ or k8s.io/
But most of the time its user workload. So we are encouraging users to come up with their own labels under the kubernetes.io/ or k8s.io/ spaces?

Thanks,
Kevin

@liggitt
Copy link
Member Author

liggitt commented Dec 4, 2018

all usage of labels that could ever have security ramifications now would be required to be prefixed with kubernetes.io/ or k8s.io/
But most of the time its user workload. So we are encouraging users to come up with their own labels under the kubernetes.io/ or k8s.io/ spaces?

See https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#noderestriction for a label prefix specifically reserved for this use:

Prevents kubelets from adding/removing/updating labels with a node-restriction.kubernetes.io/ prefix. This label prefix is reserved for administrators to label their Node objects for workload isolation purposes, and kubelets will not be allowed to modify labels with that prefix.

@kfox1111
Copy link

kfox1111 commented Dec 4, 2018

Ah. ok. So, the recommendation is in general, "always prefix your node labels with node-restriction.kubernetes.io/"?

@liggitt
Copy link
Member Author

liggitt commented Dec 4, 2018

So, the recommendation is in general, "always prefix your node labels with node-restriction.kubernetes.io/"?

For the labels you don't want kubelets setting, if you want to use the built-in protection. You can also add your own admission checks to protect non-kubernetes labels.

@kfox1111
Copy link

kfox1111 commented Dec 4, 2018

Ok. Yeah, was just looking for general advice to give to new users to avoid issues. Since its always safe, and doesn't have an extra cost, its "always prefix your node labels with node-restriction.kubernetes.io/" (unless you know what you are doing). Thanks. :)

@ravilr
Copy link
Contributor

ravilr commented Mar 1, 2019

@liggitt 'node-role.kubernetes.io/master' and 'node-role.kubernetes.io/node' seems to be used across projects. Can you please give some direction on what do you think about whitelisting this as allowed set of labels ?

LabelNodeRoleMaster = "node-role.kubernetes.io/master"

Also across kubeadm, kubespray

@pires
Copy link
Contributor

pires commented Apr 16, 2019

Conformance tests will also be broken if this annotation is not used for control-plane nodes and they're unschedulable, eg with taints. See https://github.com/kubernetes/kubernetes/blob/v1.14.1/test/e2e/framework/util.go#L2755-L2760

@liggitt
Copy link
Member Author

liggitt commented Apr 16, 2019

that label is not appropriate for use in a conformance test, as it is not official API and is not maintained by kubernetes components

@liggitt
Copy link
Member Author

liggitt commented Apr 16, 2019

opened #76654 to let the e2e/conformance invoker select which nodes they think should be scheduleable, rather than hard-code handling of a label

@liggitt
Copy link
Member Author

liggitt commented Apr 16, 2019

Can you please give some direction on what do you think about whitelisting this as allowed set of labels ?

Letting arbitrary nodes self-label as a master node is not reasonable. That label is likely to be used in daemonset nodeSelectors running highly-privileged components.

@liggitt
Copy link
Member Author

liggitt commented Apr 16, 2019

kubeadm does not set that label using self-labeling, but applies it using the superuser client at cluster startup:

https://github.com/kubernetes/kubernetes/blob/master/cmd/kubeadm/app/phases/markcontrolplane/markcontrolplane.go#L28-L44

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. area/kubelet cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. release-note Denotes a PR that will be considered when it comes time to generate release notes. sig/auth Categorizes an issue or PR as relevant to SIG Auth. sig/node Categorizes an issue or PR as relevant to SIG Node. sig/storage Categorizes an issue or PR as relevant to SIG Storage. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet