Include security options in the container created event

This commit is contained in:
Tim St. Clair
2016-08-26 15:32:48 -07:00
parent a3ccdfaa19
commit 785c83cc2d
2 changed files with 168 additions and 40 deletions

View File

@@ -18,6 +18,7 @@ package dockertools
import (
"bytes"
"crypto/md5"
"encoding/json"
"errors"
"fmt"
@@ -111,7 +112,7 @@ var (
podInfraContainerImagePullPolicy = api.PullIfNotPresent
// Default set of seccomp security options.
defaultSeccompOpt = []dockerOpt{{"seccomp", "unconfined"}}
defaultSeccompOpt = []dockerOpt{{"seccomp", "unconfined", ""}}
)
type DockerManager struct {
@@ -579,6 +580,10 @@ func (dm *DockerManager) runContainer(
if err != nil {
return kubecontainer.ContainerID{}, err
}
fmtSecurityOpts, err := dm.fmtDockerOpts(securityOpts)
if err != nil {
return kubecontainer.ContainerID{}, err
}
// Pod information is recorded on the container as labels to preserve it in the event the pod is deleted
// while the Kubelet is down and there is no information available to recover the pod.
@@ -658,7 +663,7 @@ func (dm *DockerManager) runContainer(
CPUShares: cpuShares,
Devices: devices,
},
SecurityOpt: securityOpts,
SecurityOpt: fmtSecurityOpts,
}
// Set sysctls if requested
@@ -733,7 +738,21 @@ func (dm *DockerManager) runContainer(
if len(createResp.Warnings) != 0 {
glog.V(2).Infof("Container %q of pod %q created with warnings: %v", container.Name, format.Pod(pod), createResp.Warnings)
}
dm.recorder.Eventf(ref, api.EventTypeNormal, events.CreatedContainer, "Created container with docker id %v", utilstrings.ShortenString(createResp.ID, 12))
createdEventMsg := fmt.Sprintf("Created container with docker id %v", utilstrings.ShortenString(createResp.ID, 12))
if len(securityOpts) > 0 {
var msgs []string
for _, opt := range securityOpts {
glog.Errorf("Logging security options: %+v", opt)
msg := opt.msg
if msg == "" {
msg = opt.value
}
msgs = append(msgs, fmt.Sprintf("%s=%s", opt.key, truncateMsg(msg, 256)))
}
createdEventMsg = fmt.Sprintf("%s; Security:[%s]", createdEventMsg, strings.Join(msgs, " "))
}
dm.recorder.Eventf(ref, api.EventTypeNormal, events.CreatedContainer, createdEventMsg)
if err = dm.client.StartContainer(createResp.ID); err != nil {
dm.recorder.Eventf(ref, api.EventTypeWarning, events.FailedToStartContainer,
@@ -1056,25 +1075,12 @@ func (dm *DockerManager) checkVersionCompatibility() error {
return nil
}
func (dm *DockerManager) getSecurityOpts(pod *api.Pod, ctrName string) ([]string, error) {
func (dm *DockerManager) fmtDockerOpts(opts []dockerOpt) ([]string, error) {
version, err := dm.APIVersion()
if err != nil {
return nil, err
}
var securityOpts []dockerOpt
if seccompOpts, err := dm.getSeccompOpts(pod, ctrName, version); err != nil {
return nil, err
} else {
securityOpts = append(securityOpts, seccompOpts...)
}
if appArmorOpts, err := dm.getAppArmorOpts(pod, ctrName); err != nil {
return nil, err
} else {
securityOpts = append(securityOpts, appArmorOpts...)
}
const (
// Docker changed the API for specifying options in v1.11
optSeparatorChangeVersion = "1.23" // Corresponds to docker 1.11.x
@@ -1089,19 +1095,44 @@ func (dm *DockerManager) getSecurityOpts(pod *api.Pod, ctrName string) ([]string
sep = optSeparatorOld
}
opts := make([]string, len(securityOpts))
for i, opt := range securityOpts {
opts[i] = fmt.Sprintf("%s%c%s", opt.key, sep, opt.value)
fmtOpts := make([]string, len(opts))
for i, opt := range opts {
fmtOpts[i] = fmt.Sprintf("%s%c%s", opt.key, sep, opt.value)
}
return opts, nil
return fmtOpts, nil
}
func (dm *DockerManager) getSecurityOpts(pod *api.Pod, ctrName string) ([]dockerOpt, error) {
var securityOpts []dockerOpt
if seccompOpts, err := dm.getSeccompOpts(pod, ctrName); err != nil {
return nil, err
} else {
securityOpts = append(securityOpts, seccompOpts...)
}
if appArmorOpts, err := dm.getAppArmorOpts(pod, ctrName); err != nil {
return nil, err
} else {
securityOpts = append(securityOpts, appArmorOpts...)
}
return securityOpts, nil
}
type dockerOpt struct {
// The key-value pair passed to docker.
key, value string
// The alternative value to use in log/event messages.
msg string
}
// Get the docker security options for seccomp.
func (dm *DockerManager) getSeccompOpts(pod *api.Pod, ctrName string, version kubecontainer.Version) ([]dockerOpt, error) {
func (dm *DockerManager) getSeccompOpts(pod *api.Pod, ctrName string) ([]dockerOpt, error) {
version, err := dm.APIVersion()
if err != nil {
return nil, err
}
// seccomp is only on docker versions >= v1.10
if result, err := version.Compare(dockerV110APIVersion); err != nil {
return nil, err
@@ -1144,8 +1175,10 @@ func (dm *DockerManager) getSeccompOpts(pod *api.Pod, ctrName string, version ku
if err := json.Compact(b, file); err != nil {
return nil, err
}
// Rather than the full profile, just put the filename & md5sum in the event log.
msg := fmt.Sprintf("%s(md5:%x)", name, md5.Sum(file))
return []dockerOpt{{"seccomp", b.String()}}, nil
return []dockerOpt{{"seccomp", b.String(), msg}}, nil
}
// Get the docker security options for AppArmor.
@@ -1158,7 +1191,7 @@ func (dm *DockerManager) getAppArmorOpts(pod *api.Pod, ctrName string) ([]docker
// Assume validation has already happened.
profileName := strings.TrimPrefix(profile, apparmor.ProfileNamePrefix)
return []dockerOpt{{"apparmor", profileName}}, nil
return []dockerOpt{{"apparmor", profileName, ""}}, nil
}
type dockerExitError struct {
@@ -2557,3 +2590,15 @@ func (dm *DockerManager) getVersionInfo() (versionInfo, error) {
daemonVersion: daemonVersion,
}, nil
}
// Truncate the message if it exceeds max length.
func truncateMsg(msg string, max int) string {
if len(msg) <= max {
return msg
}
glog.V(2).Infof("Truncated %s", msg)
const truncatedMsg = "..TRUNCATED.."
begin := (max - len(truncatedMsg)) / 2
end := len(msg) - (max - (len(truncatedMsg) + begin))
return msg[:begin] + truncatedMsg + msg[end:]
}