Added check for Windows Permissions

This commit is contained in:
Peri Thompson 2021-03-10 11:15:42 +00:00
parent 4740173f33
commit 46738b7f48
3 changed files with 122 additions and 15 deletions

View File

@ -1,5 +1,5 @@
/* /*
Copyright 2015 The Kubernetes Authors. Copyright 2021 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -25,7 +25,6 @@ import (
"math" "math"
"net" "net"
"net/http" "net/http"
"os"
"path" "path"
"path/filepath" "path/filepath"
"strconv" "strconv"
@ -260,6 +259,9 @@ HTTP server: The kubelet can also listen for HTTP and respond to a simple API
// add the kubelet config controller to kubeletDeps // add the kubelet config controller to kubeletDeps
kubeletDeps.KubeletConfigController = kubeletConfigController kubeletDeps.KubeletConfigController = kubeletConfigController
if err := checkPermissions(); err != nil {
klog.ErrorS(err, "kubelet running with insufficient permissions")
}
// set up signal context here in order to be reused by kubelet and docker shim // set up signal context here in order to be reused by kubelet and docker shim
ctx := genericapiserver.SetupSignalContext() ctx := genericapiserver.SetupSignalContext()
@ -430,15 +432,6 @@ func Run(ctx context.Context, s *options.KubeletServer, kubeDeps *kubelet.Depend
return nil return nil
} }
func checkPermissions() error {
if uid := os.Getuid(); uid != 0 {
return fmt.Errorf("kubelet needs to run as uid `0`. It is being run as %d", uid)
}
// TODO: Check if kubelet is running in the `initial` user namespace.
// http://man7.org/linux/man-pages/man7/user_namespaces.7.html
return nil
}
func setConfigz(cz *configz.Config, kc *kubeletconfiginternal.KubeletConfiguration) error { func setConfigz(cz *configz.Config, kc *kubeletconfiginternal.KubeletConfiguration) error {
scheme, _, err := kubeletscheme.NewSchemeAndCodecs() scheme, _, err := kubeletscheme.NewSchemeAndCodecs()
if err != nil { if err != nil {
@ -760,10 +753,6 @@ func run(ctx context.Context, s *options.KubeletServer, kubeDeps *kubelet.Depend
} }
} }
if err := checkPermissions(); err != nil {
klog.Error(err)
}
utilruntime.ReallyCrash = s.ReallyCrashForTesting utilruntime.ReallyCrash = s.ReallyCrashForTesting
// TODO(vmarmol): Do this through container config. // TODO(vmarmol): Do this through container config.

View File

@ -0,0 +1,33 @@
// +build !windows
/*
Copyright 2021 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package app
import (
"fmt"
"os"
)
func checkPermissions() error {
if uid := os.Getuid(); uid != 0 {
return fmt.Errorf("kubelet needs to run as uid `0`. It is being run as %d", uid)
}
// TODO: Check if kubelet is running in the `initial` user namespace.
// http://man7.org/linux/man-pages/man7/user_namespaces.7.html
return nil
}

View File

@ -0,0 +1,85 @@
// +build windows
/*
Copyright 2021 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package app
import (
"fmt"
"os/user"
"golang.org/x/sys/windows"
)
func isAdmin() (bool, error) {
// Get current user
u, err := user.Current()
if err != nil {
return false, fmt.Errorf("Error retrieving current user: %s", err)
}
// Get IDs of group user is a member of
ids, err := u.GroupIds()
if err != nil {
return false, fmt.Errorf("Error retrieving group ids: %s", err)
}
// Check for existence of BUILTIN\ADMINISTRATORS group id
for i := range ids {
// BUILTIN\ADMINISTRATORS
if "S-1-5-32-544" == ids[i] {
return true, nil
}
}
return false, nil
}
func checkPermissions() error {
//https://github.com/golang/go/issues/28804#issuecomment-505326268
var sid *windows.SID
var userIsAdmin bool
// https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-checktokenmembership
err := windows.AllocateAndInitializeSid(
&windows.SECURITY_NT_AUTHORITY,
2,
windows.SECURITY_BUILTIN_DOMAIN_RID,
windows.DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
&sid)
if err != nil {
return fmt.Errorf("Error while checking for elevated permissions: %s", err)
}
//We must free the sid to prevent security token leaks
defer windows.FreeSid(sid)
token := windows.Token(0)
userIsAdmin, err = isAdmin()
if err != nil {
return fmt.Errorf("Error while checking admin group membership: %s", err)
}
member, err := token.IsMember(sid)
if err != nil {
return fmt.Errorf("Error while checking for elevated permissions: %s", err)
}
if !member {
return fmt.Errorf("kubelet needs to run with administrator permissions. Run as admin is: %t, User in admin group: %t", member, userIsAdmin)
}
return nil
}