mirror of https://github.com/k3s-io/k3s
Merge pull request #1330 from brendandburns/privilege
Only allow privileged containers if API server flag set. Adds capabilities package.pull/6/head
commit
506f51b186
|
@ -28,6 +28,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/capabilities"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/master"
|
||||
|
@ -49,6 +50,7 @@ var (
|
|||
etcdServerList util.StringList
|
||||
machineList util.StringList
|
||||
corsAllowedOriginList util.StringList
|
||||
allowPrivileged = flag.Bool("allow_privileged", false, "If true, allow privileged containers.")
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -112,6 +114,10 @@ func main() {
|
|||
glog.Fatalf("-etcd_servers flag is required.")
|
||||
}
|
||||
|
||||
capabilities.InitializeCapabilities(capabilities.Capabilities{
|
||||
AllowPrivileged: *allowPrivileged,
|
||||
})
|
||||
|
||||
cloud := initCloudProvider(*cloudProvider, *cloudConfigFile)
|
||||
|
||||
podInfoGetter := &client.HTTPPodInfoGetter{
|
||||
|
|
|
@ -30,6 +30,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/capabilities"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/health"
|
||||
_ "github.com/GoogleCloudPlatform/kubernetes/pkg/healthz"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet"
|
||||
|
@ -59,7 +60,7 @@ var (
|
|||
dockerEndpoint = flag.String("docker_endpoint", "", "If non-empty, use this for the docker endpoint to communicate with")
|
||||
etcdServerList util.StringList
|
||||
rootDirectory = flag.String("root_dir", defaultRootDir, "Directory path for managing kubelet files (volume mounts,etc).")
|
||||
allowPrivileged = flag.Bool("allow_privileged", false, "If true, allow containers to request privileged mode.")
|
||||
allowPrivileged = flag.Bool("allow_privileged", false, "If true, allow containers to request privileged mode. [default=false]")
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -104,6 +105,10 @@ func main() {
|
|||
|
||||
etcd.SetLogger(util.NewLogger("etcd "))
|
||||
|
||||
capabilities.InitializeCapabilities(capabilities.Capabilities{
|
||||
AllowPrivileged: *allowPrivileged,
|
||||
})
|
||||
|
||||
dockerClient, err := docker.NewClient(getDockerEndpoint())
|
||||
if err != nil {
|
||||
glog.Fatal("Couldn't connect to docker.")
|
||||
|
@ -152,8 +157,7 @@ func main() {
|
|||
cadvisorClient,
|
||||
etcdClient,
|
||||
*rootDirectory,
|
||||
*syncFrequency,
|
||||
*allowPrivileged)
|
||||
*syncFrequency)
|
||||
|
||||
health.AddHealthChecker("exec", health.NewExecHealthChecker(k))
|
||||
health.AddHealthChecker("http", health.NewHTTPHealthChecker(&http.Client{}))
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
errs "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/capabilities"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||
)
|
||||
|
@ -226,12 +227,15 @@ func validateContainers(containers []api.Container, volumes util.StringSet) errs
|
|||
for i := range containers {
|
||||
cErrs := errs.ErrorList{}
|
||||
ctr := &containers[i] // so we can set default values
|
||||
capabilities := capabilities.GetCapabilities()
|
||||
if len(ctr.Name) == 0 {
|
||||
cErrs = append(cErrs, errs.NewFieldRequired("name", ctr.Name))
|
||||
} else if !util.IsDNSLabel(ctr.Name) {
|
||||
cErrs = append(cErrs, errs.NewFieldInvalid("name", ctr.Name))
|
||||
} else if allNames.Has(ctr.Name) {
|
||||
cErrs = append(cErrs, errs.NewFieldDuplicate("name", ctr.Name))
|
||||
} else if ctr.Privileged && !capabilities.AllowPrivileged {
|
||||
cErrs = append(cErrs, errs.NewFieldInvalid("privileged", ctr.Privileged))
|
||||
} else {
|
||||
allNames.Insert(ctr.Name)
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import (
|
|||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/capabilities"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||
)
|
||||
|
||||
|
@ -179,6 +180,9 @@ func TestValidateVolumeMounts(t *testing.T) {
|
|||
|
||||
func TestValidateContainers(t *testing.T) {
|
||||
volumes := util.StringSet{}
|
||||
capabilities.SetCapabilitiesForTests(capabilities.Capabilities{
|
||||
AllowPrivileged: true,
|
||||
})
|
||||
|
||||
successCase := []api.Container{
|
||||
{Name: "abc", Image: "image"},
|
||||
|
@ -193,11 +197,15 @@ func TestValidateContainers(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
{Name: "abc-1234", Image: "image", Privileged: true},
|
||||
}
|
||||
if errs := validateContainers(successCase, volumes); len(errs) != 0 {
|
||||
t.Errorf("expected success: %v", errs)
|
||||
}
|
||||
|
||||
capabilities.SetCapabilitiesForTests(capabilities.Capabilities{
|
||||
AllowPrivileged: false,
|
||||
})
|
||||
errorCases := map[string][]api.Container{
|
||||
"zero-length name": {{Name: "", Image: "image"}},
|
||||
"name > 63 characters": {{Name: strings.Repeat("a", 64), Image: "image"}},
|
||||
|
@ -248,6 +256,9 @@ func TestValidateContainers(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
"privilege disabled": {
|
||||
{Name: "abc", Image: "image", Privileged: true},
|
||||
},
|
||||
}
|
||||
for k, v := range errorCases {
|
||||
if errs := validateContainers(v, volumes); len(errs) == 0 {
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
Copyright 2014 Google Inc. All rights reserved.
|
||||
|
||||
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 capabilities
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Capabilities defines the set of capabilities available within the system.
|
||||
// For now these are global. Eventually they may be per-user
|
||||
type Capabilities struct {
|
||||
AllowPrivileged bool
|
||||
}
|
||||
|
||||
var once sync.Once
|
||||
var capabilities *Capabilities
|
||||
|
||||
// Initialize the capability set. This can only be done once per binary, subsequent calls are ignored.
|
||||
func InitializeCapabilities(c Capabilities) {
|
||||
// Only do this once
|
||||
once.Do(func() {
|
||||
capabilities = &c
|
||||
})
|
||||
}
|
||||
|
||||
// SetCapabilitiesForTests. Convenience method for testing. This should only be called from tests.
|
||||
func SetCapabilitiesForTests(c Capabilities) {
|
||||
capabilities = &c
|
||||
}
|
||||
|
||||
// Returns a read-only copy of the system capabilities.
|
||||
func GetCapabilities() Capabilities {
|
||||
if capabilities == nil {
|
||||
InitializeCapabilities(Capabilities{
|
||||
AllowPrivileged: false,
|
||||
})
|
||||
}
|
||||
return *capabilities
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
Copyright 2014 Google Inc. All rights reserved.
|
||||
|
||||
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 capbabilities manages system level capabilities
|
||||
package capabilities
|
|
@ -29,6 +29,7 @@ import (
|
|||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/capabilities"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/health"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/dockertools"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
|
||||
|
@ -67,19 +68,17 @@ func NewMainKubelet(
|
|||
cc CadvisorInterface,
|
||||
ec tools.EtcdClient,
|
||||
rd string,
|
||||
ri time.Duration,
|
||||
privileged bool) *Kubelet {
|
||||
ri time.Duration) *Kubelet {
|
||||
return &Kubelet{
|
||||
hostname: hn,
|
||||
dockerClient: dc,
|
||||
cadvisorClient: cc,
|
||||
etcdClient: ec,
|
||||
rootDirectory: rd,
|
||||
resyncInterval: ri,
|
||||
podWorkers: newPodWorkers(),
|
||||
runner: dockertools.NewDockerContainerCommandRunner(),
|
||||
httpClient: &http.Client{},
|
||||
allowPrivileged: privileged,
|
||||
hostname: hn,
|
||||
dockerClient: dc,
|
||||
cadvisorClient: cc,
|
||||
etcdClient: ec,
|
||||
rootDirectory: rd,
|
||||
resyncInterval: ri,
|
||||
podWorkers: newPodWorkers(),
|
||||
runner: dockertools.NewDockerContainerCommandRunner(),
|
||||
httpClient: &http.Client{},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,8 +120,6 @@ type Kubelet struct {
|
|||
runner dockertools.ContainerCommandRunner
|
||||
// Optional, client for http requests, defaults to empty client
|
||||
httpClient httpGetInterface
|
||||
// Optional, allow privileged containers, defaults to false
|
||||
allowPrivileged bool
|
||||
}
|
||||
|
||||
// Run starts the kubelet reacting to config updates
|
||||
|
@ -340,7 +337,7 @@ func (kl *Kubelet) runContainer(pod *Pod, container *api.Container, podVolumes v
|
|||
return "", err
|
||||
}
|
||||
privileged := false
|
||||
if kl.allowPrivileged {
|
||||
if capabilities.GetCapabilities().AllowPrivileged {
|
||||
privileged = container.Privileged
|
||||
} else if container.Privileged {
|
||||
return "", fmt.Errorf("Container requested privileged mode, but it is disallowed globally.")
|
||||
|
|
Loading…
Reference in New Issue