mirror of https://github.com/k3s-io/k3s
Improve flannel RBAC changes
Only wait for k3s-controller RBAC when AuthorizeNodeWithSelectors blocks kubelet from listing nodes Signed-off-by: Brad Davidson <brad.davidson@rancher.com>pull/11571/head
parent
dde2fef0c5
commit
6b0247fa4d
|
@ -69,14 +69,21 @@ func Prepare(ctx context.Context, nodeConfig *config.Node) error {
|
|||
func Run(ctx context.Context, nodeConfig *config.Node) error {
|
||||
logrus.Infof("Starting flannel with backend %s", nodeConfig.FlannelBackend)
|
||||
|
||||
if err := util.WaitForRBACReady(ctx, nodeConfig.AgentConfig.KubeConfigK3sController, util.DefaultAPIServerReadyTimeout, authorizationv1.ResourceAttributes{
|
||||
Verb: "list",
|
||||
Resource: "nodes",
|
||||
}, ""); err != nil {
|
||||
return errors.Wrap(err, "flannel failed to wait for RBAC")
|
||||
kubeConfig := nodeConfig.AgentConfig.KubeConfigKubelet
|
||||
resourceAttrs := authorizationv1.ResourceAttributes{Verb: "list", Resource: "nodes"}
|
||||
|
||||
// Compatibility code for AuthorizeNodeWithSelectors feature-gate.
|
||||
// If the kubelet cannot list nodes, then wait for the k3s-controller RBAC to become ready, and use that kubeconfig instead.
|
||||
if canListNodes, err := util.CheckRBAC(ctx, kubeConfig, resourceAttrs, ""); err != nil {
|
||||
return errors.Wrap(err, "failed to check if RBAC allows node list")
|
||||
} else if !canListNodes {
|
||||
kubeConfig = nodeConfig.AgentConfig.KubeConfigK3sController
|
||||
if err := util.WaitForRBACReady(ctx, kubeConfig, util.DefaultAPIServerReadyTimeout, resourceAttrs, ""); err != nil {
|
||||
return errors.Wrap(err, "flannel failed to wait for RBAC")
|
||||
}
|
||||
}
|
||||
|
||||
coreClient, err := util.GetClientSet(nodeConfig.AgentConfig.KubeConfigK3sController)
|
||||
coreClient, err := util.GetClientSet(kubeConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -90,7 +97,7 @@ func Run(ctx context.Context, nodeConfig *config.Node) error {
|
|||
return errors.Wrap(err, "failed to check netMode for flannel")
|
||||
}
|
||||
go func() {
|
||||
err := flannel(ctx, nodeConfig.FlannelIface, nodeConfig.FlannelConfFile, nodeConfig.AgentConfig.KubeConfigK3sController, nodeConfig.FlannelIPv6Masq, netMode)
|
||||
err := flannel(ctx, nodeConfig.FlannelIface, nodeConfig.FlannelConfFile, kubeConfig, nodeConfig.FlannelIPv6Masq, netMode)
|
||||
if err != nil && !errors.Is(err, context.Canceled) {
|
||||
logrus.Errorf("flannel exited: %v", err)
|
||||
os.Exit(1)
|
||||
|
|
|
@ -147,6 +147,34 @@ func WaitForRBACReady(ctx context.Context, kubeconfigPath string, timeout time.D
|
|||
return nil
|
||||
}
|
||||
|
||||
// CheckRBAC performs a single SelfSubjectAccessReview or SubjectAccessReview, returning a
|
||||
// boolean indicating whether or not the requested access would be allowed. This is basically
|
||||
// `kubectl auth can-i`.
|
||||
func CheckRBAC(ctx context.Context, kubeconfigPath string, ra authorizationv1.ResourceAttributes, user string, groups ...string) (bool, error) {
|
||||
restConfig, err := GetRESTConfig(kubeconfigPath)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
authClient, err := authorizationv1client.NewForConfig(restConfig)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var reviewFunc genericAccessReviewRequest
|
||||
if len(user) == 0 && len(groups) == 0 {
|
||||
reviewFunc = selfSubjectAccessReview(authClient, ra)
|
||||
} else {
|
||||
reviewFunc = subjectAccessReview(authClient, ra, user, groups)
|
||||
}
|
||||
|
||||
status, err := reviewFunc(ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return status.Allowed, nil
|
||||
}
|
||||
|
||||
// selfSubjectAccessReview returns a function that makes SelfSubjectAccessReview requests using the
|
||||
// provided client and attributes, returning a status or error.
|
||||
func selfSubjectAccessReview(authClient *authorizationv1client.AuthorizationV1Client, ra authorizationv1.ResourceAttributes) genericAccessReviewRequest {
|
||||
|
|
Loading…
Reference in New Issue