From 453391ea8802747670fd7fc608ce4ad5c1d3ba1d Mon Sep 17 00:00:00 2001 From: Pengfei Ni Date: Fri, 4 Nov 2016 19:50:50 +0800 Subject: [PATCH 1/6] CRI: add security context for sandbox/container --- pkg/kubelet/api/v1alpha1/runtime/api.proto | 81 ++++++++++++++-------- 1 file changed, 52 insertions(+), 29 deletions(-) diff --git a/pkg/kubelet/api/v1alpha1/runtime/api.proto b/pkg/kubelet/api/v1alpha1/runtime/api.proto index 3abcb7a34d2..732cc7a5267 100644 --- a/pkg/kubelet/api/v1alpha1/runtime/api.proto +++ b/pkg/kubelet/api/v1alpha1/runtime/api.proto @@ -148,6 +148,26 @@ message NamespaceOption { optional bool host_ipc = 3; } +// LinuxSandboxSecurityContext holds linux security configuration that will be +// applied to a sandbox. Note that: +// 1) It does not apply to containers in the pods. +// 2) It may not be applicable to a PodSandbox which does not contain any running +// process. +message LinuxSandboxSecurityContext { + // The configurations for the sandbox's namespaces. + // This will be used only if the PodSandbox uses namespace for isolation. + optional NamespaceOption namespace_options = 1; + // Optional SELinux context to be applied. + optional SELinuxOption selinux_options = 2; + // The UID to run the entrypoint of the sandbox process. + optional int64 run_as_user = 3; + // If set, the root filesystem of the sandbox is read-only. + optional bool readonly_rootfs = 4; + // A list of groups applied to the first process run in the sandbox, in addition + // to the sandbox's primary GID. + repeated int64 supplemental_groups = 5; +} + // LinuxPodSandboxConfig holds platform-specific configurations for Linux // host platforms and Linux-based containers. message LinuxPodSandboxConfig { @@ -155,9 +175,8 @@ message LinuxPodSandboxConfig { // The cgroupfs style syntax will be used, but the container runtime can // convert it to systemd semantics if needed. optional string cgroup_parent = 1; - // The configurations for the sandbox's namespaces. - // This will be used only if the PodSandbox uses namespace for isolation. - optional NamespaceOption namespace_options = 2; + // LinuxSandboxSecurityContext holds sandbox security attributes. + optional LinuxSandboxSecurityContext security_context = 2; } // PodSandboxMetadata holds all necessary information for building the sandbox name. @@ -409,26 +428,34 @@ message Capability { repeated string drop_capabilities = 2; } +// LinuxContainerSecurityContext holds linux security configuration that will be applied to a container. +message LinuxContainerSecurityContext { + // Capabilities to add or drop. + optional Capability capabilities = 1; + // If set, run container in privileged mode. + optional bool privileged = 2; + // The configurations for the container's namespaces. + // This will be used only if the container uses namespace for isolation. + optional NamespaceOption namespace_options = 3; + // Optional SELinux context to be applied. + optional SELinuxOption selinux_options = 4; + // The UID to run the the container process as. + // Defaults to user specified in image metadata if unspecified. + optional int64 run_as_user = 5; + // If set, the root filesystem of the container is read-only. + optional bool readonly_rootfs = 6; + // A list of groups applied to the first process run in the container, in addition + // to the container's primary GID. + repeated int64 supplemental_groups = 7; +} + // LinuxContainerConfig contains platform-specific configuration for // Linux-based containers. message LinuxContainerConfig { // Resources specification for the container. optional LinuxContainerResources resources = 1; - // Capabilities to add or drop. - optional Capability capabilities = 2; - // Optional SELinux context to be applied. - optional SELinuxOption selinux_options = 3; - // User contains the user for the container process. - optional LinuxUser user = 4; -} - -message LinuxUser { - // uid specifies the user ID the container process has. - optional int64 uid = 1; - // gid specifies the group ID the container process has. - optional int64 gid = 2; - // additional_gids specifies additional GIDs the container process has. - repeated int64 additional_gids = 3; + // LinuxContainerSecurityContext configuration for the container. + optional LinuxContainerSecurityContext security_context = 2; } // ContainerMetadata holds all necessary information for building the container @@ -488,11 +515,6 @@ message ContainerConfig { // Annotations is an unstructured key value map that may be set by external // tools to store and retrieve arbitrary metadata. map annotations = 10; - // If set, run container in privileged mode. - // Processes in privileged containers are essentially equivalent to root on the host. - optional bool privileged = 11; - // If set, the root filesystem of the container is read-only. - optional bool readonly_rootfs = 12; // Path relative to PodSandboxConfig.LogDirectory for container to store // the log (STDOUT and STDERR) on the host. // E.g., @@ -503,19 +525,18 @@ message ContainerConfig { // container logs are under active discussion in // https://issues.k8s.io/24677. There *may* be future change of direction // for logging as the discussion carries on. - optional string log_path = 13; - // The hash of container config + optional string log_path = 11; // Variables for interactive containers, these have very specialized // use-cases (e.g. debugging). // TODO: Determine if we need to continue supporting these fields that are // part of Kubernetes's Container Spec. - optional bool stdin = 14; - optional bool stdin_once = 15; - optional bool tty = 16; + optional bool stdin = 12; + optional bool stdin_once = 13; + optional bool tty = 14; // Linux contains configuration specific to Linux containers. - optional LinuxContainerConfig linux = 17; + optional LinuxContainerConfig linux = 15; } message CreateContainerRequest { @@ -737,6 +758,8 @@ message Image { repeated string repo_digests = 3; // The size of the image in bytes. optional uint64 size = 4; + // The uid that will run the command(s). + optional int64 uid = 5; } message ListImagesResponse { From 766b570c19ee9ac80343ec0b371440b50dc94dd6 Mon Sep 17 00:00:00 2001 From: Pengfei Ni Date: Fri, 4 Nov 2016 19:51:36 +0800 Subject: [PATCH 2/6] run hack/update-generated-runtime.sh --- pkg/kubelet/api/v1alpha1/runtime/api.pb.go | 817 +++++++++++---------- 1 file changed, 449 insertions(+), 368 deletions(-) diff --git a/pkg/kubelet/api/v1alpha1/runtime/api.pb.go b/pkg/kubelet/api/v1alpha1/runtime/api.pb.go index b4ec4a2ab9e..11a19fdcd11 100644 --- a/pkg/kubelet/api/v1alpha1/runtime/api.pb.go +++ b/pkg/kubelet/api/v1alpha1/runtime/api.pb.go @@ -31,6 +31,7 @@ It has these top-level messages: PortMapping Mount NamespaceOption + LinuxSandboxSecurityContext LinuxPodSandboxConfig PodSandboxMetadata PodSandboxConfig @@ -55,8 +56,8 @@ It has these top-level messages: LinuxContainerResources SELinuxOption Capability + LinuxContainerSecurityContext LinuxContainerConfig - LinuxUser ContainerMetadata Device ContainerConfig @@ -463,6 +464,67 @@ func (m *NamespaceOption) GetHostIpc() bool { return false } +// LinuxSandboxSecurityContext holds linux security configuration that will be +// applied to a sandbox. Note that: +// 1) It does not apply to containers in the pods. +// 2) It may not be applicable to a PodSandbox which does not contain any running +// process. +type LinuxSandboxSecurityContext struct { + // The configurations for the sandbox's namespaces. + // This will be used only if the PodSandbox uses namespace for isolation. + NamespaceOptions *NamespaceOption `protobuf:"bytes,1,opt,name=namespace_options,json=namespaceOptions" json:"namespace_options,omitempty"` + // Optional SELinux context to be applied. + SelinuxOptions *SELinuxOption `protobuf:"bytes,2,opt,name=selinux_options,json=selinuxOptions" json:"selinux_options,omitempty"` + // The UID to run the entrypoint of the sandbox process. + RunAsUser *int64 `protobuf:"varint,3,opt,name=run_as_user,json=runAsUser" json:"run_as_user,omitempty"` + // If set, the root filesystem of the sandbox is read-only. + ReadonlyRootfs *bool `protobuf:"varint,4,opt,name=readonly_rootfs,json=readonlyRootfs" json:"readonly_rootfs,omitempty"` + // A list of groups applied to the first process run in the sandbox, in addition + // to the sandbox's primary GID. + SupplementalGroups []int64 `protobuf:"varint,5,rep,name=supplemental_groups,json=supplementalGroups" json:"supplemental_groups,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *LinuxSandboxSecurityContext) Reset() { *m = LinuxSandboxSecurityContext{} } +func (m *LinuxSandboxSecurityContext) String() string { return proto.CompactTextString(m) } +func (*LinuxSandboxSecurityContext) ProtoMessage() {} +func (*LinuxSandboxSecurityContext) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{6} } + +func (m *LinuxSandboxSecurityContext) GetNamespaceOptions() *NamespaceOption { + if m != nil { + return m.NamespaceOptions + } + return nil +} + +func (m *LinuxSandboxSecurityContext) GetSelinuxOptions() *SELinuxOption { + if m != nil { + return m.SelinuxOptions + } + return nil +} + +func (m *LinuxSandboxSecurityContext) GetRunAsUser() int64 { + if m != nil && m.RunAsUser != nil { + return *m.RunAsUser + } + return 0 +} + +func (m *LinuxSandboxSecurityContext) GetReadonlyRootfs() bool { + if m != nil && m.ReadonlyRootfs != nil { + return *m.ReadonlyRootfs + } + return false +} + +func (m *LinuxSandboxSecurityContext) GetSupplementalGroups() []int64 { + if m != nil { + return m.SupplementalGroups + } + return nil +} + // LinuxPodSandboxConfig holds platform-specific configurations for Linux // host platforms and Linux-based containers. type LinuxPodSandboxConfig struct { @@ -470,16 +532,15 @@ type LinuxPodSandboxConfig struct { // The cgroupfs style syntax will be used, but the container runtime can // convert it to systemd semantics if needed. CgroupParent *string `protobuf:"bytes,1,opt,name=cgroup_parent,json=cgroupParent" json:"cgroup_parent,omitempty"` - // The configurations for the sandbox's namespaces. - // This will be used only if the PodSandbox uses namespace for isolation. - NamespaceOptions *NamespaceOption `protobuf:"bytes,2,opt,name=namespace_options,json=namespaceOptions" json:"namespace_options,omitempty"` - XXX_unrecognized []byte `json:"-"` + // LinuxSandboxSecurityContext holds sandbox security attributes. + SecurityContext *LinuxSandboxSecurityContext `protobuf:"bytes,2,opt,name=security_context,json=securityContext" json:"security_context,omitempty"` + XXX_unrecognized []byte `json:"-"` } func (m *LinuxPodSandboxConfig) Reset() { *m = LinuxPodSandboxConfig{} } func (m *LinuxPodSandboxConfig) String() string { return proto.CompactTextString(m) } func (*LinuxPodSandboxConfig) ProtoMessage() {} -func (*LinuxPodSandboxConfig) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{6} } +func (*LinuxPodSandboxConfig) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{7} } func (m *LinuxPodSandboxConfig) GetCgroupParent() string { if m != nil && m.CgroupParent != nil { @@ -488,9 +549,9 @@ func (m *LinuxPodSandboxConfig) GetCgroupParent() string { return "" } -func (m *LinuxPodSandboxConfig) GetNamespaceOptions() *NamespaceOption { +func (m *LinuxPodSandboxConfig) GetSecurityContext() *LinuxSandboxSecurityContext { if m != nil { - return m.NamespaceOptions + return m.SecurityContext } return nil } @@ -514,7 +575,7 @@ type PodSandboxMetadata struct { func (m *PodSandboxMetadata) Reset() { *m = PodSandboxMetadata{} } func (m *PodSandboxMetadata) String() string { return proto.CompactTextString(m) } func (*PodSandboxMetadata) ProtoMessage() {} -func (*PodSandboxMetadata) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{7} } +func (*PodSandboxMetadata) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{8} } func (m *PodSandboxMetadata) GetName() string { if m != nil && m.Name != nil { @@ -615,7 +676,7 @@ type PodSandboxConfig struct { func (m *PodSandboxConfig) Reset() { *m = PodSandboxConfig{} } func (m *PodSandboxConfig) String() string { return proto.CompactTextString(m) } func (*PodSandboxConfig) ProtoMessage() {} -func (*PodSandboxConfig) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{8} } +func (*PodSandboxConfig) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{9} } func (m *PodSandboxConfig) GetMetadata() *PodSandboxMetadata { if m != nil { @@ -682,7 +743,7 @@ type RunPodSandboxRequest struct { func (m *RunPodSandboxRequest) Reset() { *m = RunPodSandboxRequest{} } func (m *RunPodSandboxRequest) String() string { return proto.CompactTextString(m) } func (*RunPodSandboxRequest) ProtoMessage() {} -func (*RunPodSandboxRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{9} } +func (*RunPodSandboxRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{10} } func (m *RunPodSandboxRequest) GetConfig() *PodSandboxConfig { if m != nil { @@ -700,7 +761,7 @@ type RunPodSandboxResponse struct { func (m *RunPodSandboxResponse) Reset() { *m = RunPodSandboxResponse{} } func (m *RunPodSandboxResponse) String() string { return proto.CompactTextString(m) } func (*RunPodSandboxResponse) ProtoMessage() {} -func (*RunPodSandboxResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{10} } +func (*RunPodSandboxResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{11} } func (m *RunPodSandboxResponse) GetPodSandboxId() string { if m != nil && m.PodSandboxId != nil { @@ -718,7 +779,7 @@ type StopPodSandboxRequest struct { func (m *StopPodSandboxRequest) Reset() { *m = StopPodSandboxRequest{} } func (m *StopPodSandboxRequest) String() string { return proto.CompactTextString(m) } func (*StopPodSandboxRequest) ProtoMessage() {} -func (*StopPodSandboxRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{11} } +func (*StopPodSandboxRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{12} } func (m *StopPodSandboxRequest) GetPodSandboxId() string { if m != nil && m.PodSandboxId != nil { @@ -734,7 +795,7 @@ type StopPodSandboxResponse struct { func (m *StopPodSandboxResponse) Reset() { *m = StopPodSandboxResponse{} } func (m *StopPodSandboxResponse) String() string { return proto.CompactTextString(m) } func (*StopPodSandboxResponse) ProtoMessage() {} -func (*StopPodSandboxResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{12} } +func (*StopPodSandboxResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{13} } type RemovePodSandboxRequest struct { // The id of the PodSandbox @@ -745,7 +806,7 @@ type RemovePodSandboxRequest struct { func (m *RemovePodSandboxRequest) Reset() { *m = RemovePodSandboxRequest{} } func (m *RemovePodSandboxRequest) String() string { return proto.CompactTextString(m) } func (*RemovePodSandboxRequest) ProtoMessage() {} -func (*RemovePodSandboxRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{13} } +func (*RemovePodSandboxRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{14} } func (m *RemovePodSandboxRequest) GetPodSandboxId() string { if m != nil && m.PodSandboxId != nil { @@ -761,7 +822,7 @@ type RemovePodSandboxResponse struct { func (m *RemovePodSandboxResponse) Reset() { *m = RemovePodSandboxResponse{} } func (m *RemovePodSandboxResponse) String() string { return proto.CompactTextString(m) } func (*RemovePodSandboxResponse) ProtoMessage() {} -func (*RemovePodSandboxResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{14} } +func (*RemovePodSandboxResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{15} } type PodSandboxStatusRequest struct { // The id of the PodSandbox @@ -772,7 +833,7 @@ type PodSandboxStatusRequest struct { func (m *PodSandboxStatusRequest) Reset() { *m = PodSandboxStatusRequest{} } func (m *PodSandboxStatusRequest) String() string { return proto.CompactTextString(m) } func (*PodSandboxStatusRequest) ProtoMessage() {} -func (*PodSandboxStatusRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{15} } +func (*PodSandboxStatusRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{16} } func (m *PodSandboxStatusRequest) GetPodSandboxId() string { if m != nil && m.PodSandboxId != nil { @@ -791,7 +852,7 @@ type PodSandboxNetworkStatus struct { func (m *PodSandboxNetworkStatus) Reset() { *m = PodSandboxNetworkStatus{} } func (m *PodSandboxNetworkStatus) String() string { return proto.CompactTextString(m) } func (*PodSandboxNetworkStatus) ProtoMessage() {} -func (*PodSandboxNetworkStatus) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{16} } +func (*PodSandboxNetworkStatus) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{17} } func (m *PodSandboxNetworkStatus) GetIp() string { if m != nil && m.Ip != nil { @@ -812,7 +873,7 @@ type Namespace struct { func (m *Namespace) Reset() { *m = Namespace{} } func (m *Namespace) String() string { return proto.CompactTextString(m) } func (*Namespace) ProtoMessage() {} -func (*Namespace) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{17} } +func (*Namespace) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{18} } func (m *Namespace) GetNetwork() string { if m != nil && m.Network != nil { @@ -838,7 +899,7 @@ type LinuxPodSandboxStatus struct { func (m *LinuxPodSandboxStatus) Reset() { *m = LinuxPodSandboxStatus{} } func (m *LinuxPodSandboxStatus) String() string { return proto.CompactTextString(m) } func (*LinuxPodSandboxStatus) ProtoMessage() {} -func (*LinuxPodSandboxStatus) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{18} } +func (*LinuxPodSandboxStatus) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{19} } func (m *LinuxPodSandboxStatus) GetNamespaces() *Namespace { if m != nil { @@ -872,7 +933,7 @@ type PodSandboxStatus struct { func (m *PodSandboxStatus) Reset() { *m = PodSandboxStatus{} } func (m *PodSandboxStatus) String() string { return proto.CompactTextString(m) } func (*PodSandboxStatus) ProtoMessage() {} -func (*PodSandboxStatus) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{19} } +func (*PodSandboxStatus) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{20} } func (m *PodSandboxStatus) GetId() string { if m != nil && m.Id != nil { @@ -939,7 +1000,7 @@ type PodSandboxStatusResponse struct { func (m *PodSandboxStatusResponse) Reset() { *m = PodSandboxStatusResponse{} } func (m *PodSandboxStatusResponse) String() string { return proto.CompactTextString(m) } func (*PodSandboxStatusResponse) ProtoMessage() {} -func (*PodSandboxStatusResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{20} } +func (*PodSandboxStatusResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{21} } func (m *PodSandboxStatusResponse) GetStatus() *PodSandboxStatus { if m != nil { @@ -965,7 +1026,7 @@ type PodSandboxFilter struct { func (m *PodSandboxFilter) Reset() { *m = PodSandboxFilter{} } func (m *PodSandboxFilter) String() string { return proto.CompactTextString(m) } func (*PodSandboxFilter) ProtoMessage() {} -func (*PodSandboxFilter) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{21} } +func (*PodSandboxFilter) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{22} } func (m *PodSandboxFilter) GetId() string { if m != nil && m.Id != nil { @@ -997,7 +1058,7 @@ type ListPodSandboxRequest struct { func (m *ListPodSandboxRequest) Reset() { *m = ListPodSandboxRequest{} } func (m *ListPodSandboxRequest) String() string { return proto.CompactTextString(m) } func (*ListPodSandboxRequest) ProtoMessage() {} -func (*ListPodSandboxRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{22} } +func (*ListPodSandboxRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{23} } func (m *ListPodSandboxRequest) GetFilter() *PodSandboxFilter { if m != nil { @@ -1027,7 +1088,7 @@ type PodSandbox struct { func (m *PodSandbox) Reset() { *m = PodSandbox{} } func (m *PodSandbox) String() string { return proto.CompactTextString(m) } func (*PodSandbox) ProtoMessage() {} -func (*PodSandbox) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{23} } +func (*PodSandbox) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{24} } func (m *PodSandbox) GetId() string { if m != nil && m.Id != nil { @@ -1080,7 +1141,7 @@ type ListPodSandboxResponse struct { func (m *ListPodSandboxResponse) Reset() { *m = ListPodSandboxResponse{} } func (m *ListPodSandboxResponse) String() string { return proto.CompactTextString(m) } func (*ListPodSandboxResponse) ProtoMessage() {} -func (*ListPodSandboxResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{24} } +func (*ListPodSandboxResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{25} } func (m *ListPodSandboxResponse) GetItems() []*PodSandbox { if m != nil { @@ -1101,7 +1162,7 @@ type ImageSpec struct { func (m *ImageSpec) Reset() { *m = ImageSpec{} } func (m *ImageSpec) String() string { return proto.CompactTextString(m) } func (*ImageSpec) ProtoMessage() {} -func (*ImageSpec) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{25} } +func (*ImageSpec) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{26} } func (m *ImageSpec) GetImage() string { if m != nil && m.Image != nil { @@ -1119,7 +1180,7 @@ type KeyValue struct { func (m *KeyValue) Reset() { *m = KeyValue{} } func (m *KeyValue) String() string { return proto.CompactTextString(m) } func (*KeyValue) ProtoMessage() {} -func (*KeyValue) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{26} } +func (*KeyValue) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{27} } func (m *KeyValue) GetKey() string { if m != nil && m.Key != nil { @@ -1156,7 +1217,7 @@ type LinuxContainerResources struct { func (m *LinuxContainerResources) Reset() { *m = LinuxContainerResources{} } func (m *LinuxContainerResources) String() string { return proto.CompactTextString(m) } func (*LinuxContainerResources) ProtoMessage() {} -func (*LinuxContainerResources) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{27} } +func (*LinuxContainerResources) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{28} } func (m *LinuxContainerResources) GetCpuPeriod() int64 { if m != nil && m.CpuPeriod != nil { @@ -1205,7 +1266,7 @@ type SELinuxOption struct { func (m *SELinuxOption) Reset() { *m = SELinuxOption{} } func (m *SELinuxOption) String() string { return proto.CompactTextString(m) } func (*SELinuxOption) ProtoMessage() {} -func (*SELinuxOption) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{28} } +func (*SELinuxOption) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{29} } func (m *SELinuxOption) GetUser() string { if m != nil && m.User != nil { @@ -1247,7 +1308,7 @@ type Capability struct { func (m *Capability) Reset() { *m = Capability{} } func (m *Capability) String() string { return proto.CompactTextString(m) } func (*Capability) ProtoMessage() {} -func (*Capability) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{29} } +func (*Capability) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{30} } func (m *Capability) GetAddCapabilities() []string { if m != nil { @@ -1263,24 +1324,98 @@ func (m *Capability) GetDropCapabilities() []string { return nil } +// LinuxContainerSecurityContext holds linux security configuration that will be applied to a container. +type LinuxContainerSecurityContext struct { + // Capabilities to add or drop. + Capabilities *Capability `protobuf:"bytes,1,opt,name=capabilities" json:"capabilities,omitempty"` + // If set, run container in privileged mode. + Privileged *bool `protobuf:"varint,2,opt,name=privileged" json:"privileged,omitempty"` + // The configurations for the container's namespaces. + // This will be used only if the container uses namespace for isolation. + NamespaceOptions *NamespaceOption `protobuf:"bytes,3,opt,name=namespace_options,json=namespaceOptions" json:"namespace_options,omitempty"` + // Optional SELinux context to be applied. + SelinuxOptions *SELinuxOption `protobuf:"bytes,4,opt,name=selinux_options,json=selinuxOptions" json:"selinux_options,omitempty"` + // The UID to run the the container process as. + // Defaults to user specified in image metadata if unspecified. + RunAsUser *int64 `protobuf:"varint,5,opt,name=run_as_user,json=runAsUser" json:"run_as_user,omitempty"` + // If set, the root filesystem of the container is read-only. + ReadonlyRootfs *bool `protobuf:"varint,6,opt,name=readonly_rootfs,json=readonlyRootfs" json:"readonly_rootfs,omitempty"` + // A list of groups applied to the first process run in the container, in addition + // to the container's primary GID. + SupplementalGroups []int64 `protobuf:"varint,7,rep,name=supplemental_groups,json=supplementalGroups" json:"supplemental_groups,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *LinuxContainerSecurityContext) Reset() { *m = LinuxContainerSecurityContext{} } +func (m *LinuxContainerSecurityContext) String() string { return proto.CompactTextString(m) } +func (*LinuxContainerSecurityContext) ProtoMessage() {} +func (*LinuxContainerSecurityContext) Descriptor() ([]byte, []int) { + return fileDescriptorApi, []int{31} +} + +func (m *LinuxContainerSecurityContext) GetCapabilities() *Capability { + if m != nil { + return m.Capabilities + } + return nil +} + +func (m *LinuxContainerSecurityContext) GetPrivileged() bool { + if m != nil && m.Privileged != nil { + return *m.Privileged + } + return false +} + +func (m *LinuxContainerSecurityContext) GetNamespaceOptions() *NamespaceOption { + if m != nil { + return m.NamespaceOptions + } + return nil +} + +func (m *LinuxContainerSecurityContext) GetSelinuxOptions() *SELinuxOption { + if m != nil { + return m.SelinuxOptions + } + return nil +} + +func (m *LinuxContainerSecurityContext) GetRunAsUser() int64 { + if m != nil && m.RunAsUser != nil { + return *m.RunAsUser + } + return 0 +} + +func (m *LinuxContainerSecurityContext) GetReadonlyRootfs() bool { + if m != nil && m.ReadonlyRootfs != nil { + return *m.ReadonlyRootfs + } + return false +} + +func (m *LinuxContainerSecurityContext) GetSupplementalGroups() []int64 { + if m != nil { + return m.SupplementalGroups + } + return nil +} + // LinuxContainerConfig contains platform-specific configuration for // Linux-based containers. type LinuxContainerConfig struct { // Resources specification for the container. Resources *LinuxContainerResources `protobuf:"bytes,1,opt,name=resources" json:"resources,omitempty"` - // Capabilities to add or drop. - Capabilities *Capability `protobuf:"bytes,2,opt,name=capabilities" json:"capabilities,omitempty"` - // Optional SELinux context to be applied. - SelinuxOptions *SELinuxOption `protobuf:"bytes,3,opt,name=selinux_options,json=selinuxOptions" json:"selinux_options,omitempty"` - // User contains the user for the container process. - User *LinuxUser `protobuf:"bytes,4,opt,name=user" json:"user,omitempty"` - XXX_unrecognized []byte `json:"-"` + // LinuxContainerSecurityContext configuration for the container. + SecurityContext *LinuxContainerSecurityContext `protobuf:"bytes,2,opt,name=security_context,json=securityContext" json:"security_context,omitempty"` + XXX_unrecognized []byte `json:"-"` } func (m *LinuxContainerConfig) Reset() { *m = LinuxContainerConfig{} } func (m *LinuxContainerConfig) String() string { return proto.CompactTextString(m) } func (*LinuxContainerConfig) ProtoMessage() {} -func (*LinuxContainerConfig) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{30} } +func (*LinuxContainerConfig) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{32} } func (m *LinuxContainerConfig) GetResources() *LinuxContainerResources { if m != nil { @@ -1289,59 +1424,9 @@ func (m *LinuxContainerConfig) GetResources() *LinuxContainerResources { return nil } -func (m *LinuxContainerConfig) GetCapabilities() *Capability { +func (m *LinuxContainerConfig) GetSecurityContext() *LinuxContainerSecurityContext { if m != nil { - return m.Capabilities - } - return nil -} - -func (m *LinuxContainerConfig) GetSelinuxOptions() *SELinuxOption { - if m != nil { - return m.SelinuxOptions - } - return nil -} - -func (m *LinuxContainerConfig) GetUser() *LinuxUser { - if m != nil { - return m.User - } - return nil -} - -type LinuxUser struct { - // uid specifies the user ID the container process has. - Uid *int64 `protobuf:"varint,1,opt,name=uid" json:"uid,omitempty"` - // gid specifies the group ID the container process has. - Gid *int64 `protobuf:"varint,2,opt,name=gid" json:"gid,omitempty"` - // additional_gids specifies additional GIDs the container process has. - AdditionalGids []int64 `protobuf:"varint,3,rep,name=additional_gids,json=additionalGids" json:"additional_gids,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *LinuxUser) Reset() { *m = LinuxUser{} } -func (m *LinuxUser) String() string { return proto.CompactTextString(m) } -func (*LinuxUser) ProtoMessage() {} -func (*LinuxUser) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{31} } - -func (m *LinuxUser) GetUid() int64 { - if m != nil && m.Uid != nil { - return *m.Uid - } - return 0 -} - -func (m *LinuxUser) GetGid() int64 { - if m != nil && m.Gid != nil { - return *m.Gid - } - return 0 -} - -func (m *LinuxUser) GetAdditionalGids() []int64 { - if m != nil { - return m.AdditionalGids + return m.SecurityContext } return nil } @@ -1362,7 +1447,7 @@ type ContainerMetadata struct { func (m *ContainerMetadata) Reset() { *m = ContainerMetadata{} } func (m *ContainerMetadata) String() string { return proto.CompactTextString(m) } func (*ContainerMetadata) ProtoMessage() {} -func (*ContainerMetadata) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{32} } +func (*ContainerMetadata) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{33} } func (m *ContainerMetadata) GetName() string { if m != nil && m.Name != nil { @@ -1395,7 +1480,7 @@ type Device struct { func (m *Device) Reset() { *m = Device{} } func (m *Device) String() string { return proto.CompactTextString(m) } func (*Device) ProtoMessage() {} -func (*Device) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{33} } +func (*Device) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{34} } func (m *Device) GetContainerPath() string { if m != nil && m.ContainerPath != nil { @@ -1450,11 +1535,6 @@ type ContainerConfig struct { // Annotations is an unstructured key value map that may be set by external // tools to store and retrieve arbitrary metadata. Annotations map[string]string `protobuf:"bytes,10,rep,name=annotations" json:"annotations,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - // If set, run container in privileged mode. - // Processes in privileged containers are essentially equivalent to root on the host. - Privileged *bool `protobuf:"varint,11,opt,name=privileged" json:"privileged,omitempty"` - // If set, the root filesystem of the container is read-only. - ReadonlyRootfs *bool `protobuf:"varint,12,opt,name=readonly_rootfs,json=readonlyRootfs" json:"readonly_rootfs,omitempty"` // Path relative to PodSandboxConfig.LogDirectory for container to store // the log (STDOUT and STDERR) on the host. // E.g., @@ -1465,23 +1545,23 @@ type ContainerConfig struct { // container logs are under active discussion in // https://issues.k8s.io/24677. There *may* be future change of direction // for logging as the discussion carries on. - LogPath *string `protobuf:"bytes,13,opt,name=log_path,json=logPath" json:"log_path,omitempty"` + LogPath *string `protobuf:"bytes,11,opt,name=log_path,json=logPath" json:"log_path,omitempty"` // Variables for interactive containers, these have very specialized // use-cases (e.g. debugging). // TODO: Determine if we need to continue supporting these fields that are // part of Kubernetes's Container Spec. - Stdin *bool `protobuf:"varint,14,opt,name=stdin" json:"stdin,omitempty"` - StdinOnce *bool `protobuf:"varint,15,opt,name=stdin_once,json=stdinOnce" json:"stdin_once,omitempty"` - Tty *bool `protobuf:"varint,16,opt,name=tty" json:"tty,omitempty"` + Stdin *bool `protobuf:"varint,12,opt,name=stdin" json:"stdin,omitempty"` + StdinOnce *bool `protobuf:"varint,13,opt,name=stdin_once,json=stdinOnce" json:"stdin_once,omitempty"` + Tty *bool `protobuf:"varint,14,opt,name=tty" json:"tty,omitempty"` // Linux contains configuration specific to Linux containers. - Linux *LinuxContainerConfig `protobuf:"bytes,17,opt,name=linux" json:"linux,omitempty"` + Linux *LinuxContainerConfig `protobuf:"bytes,15,opt,name=linux" json:"linux,omitempty"` XXX_unrecognized []byte `json:"-"` } func (m *ContainerConfig) Reset() { *m = ContainerConfig{} } func (m *ContainerConfig) String() string { return proto.CompactTextString(m) } func (*ContainerConfig) ProtoMessage() {} -func (*ContainerConfig) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{34} } +func (*ContainerConfig) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{35} } func (m *ContainerConfig) GetMetadata() *ContainerMetadata { if m != nil { @@ -1553,20 +1633,6 @@ func (m *ContainerConfig) GetAnnotations() map[string]string { return nil } -func (m *ContainerConfig) GetPrivileged() bool { - if m != nil && m.Privileged != nil { - return *m.Privileged - } - return false -} - -func (m *ContainerConfig) GetReadonlyRootfs() bool { - if m != nil && m.ReadonlyRootfs != nil { - return *m.ReadonlyRootfs - } - return false -} - func (m *ContainerConfig) GetLogPath() string { if m != nil && m.LogPath != nil { return *m.LogPath @@ -1618,7 +1684,7 @@ type CreateContainerRequest struct { func (m *CreateContainerRequest) Reset() { *m = CreateContainerRequest{} } func (m *CreateContainerRequest) String() string { return proto.CompactTextString(m) } func (*CreateContainerRequest) ProtoMessage() {} -func (*CreateContainerRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{35} } +func (*CreateContainerRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{36} } func (m *CreateContainerRequest) GetPodSandboxId() string { if m != nil && m.PodSandboxId != nil { @@ -1650,7 +1716,7 @@ type CreateContainerResponse struct { func (m *CreateContainerResponse) Reset() { *m = CreateContainerResponse{} } func (m *CreateContainerResponse) String() string { return proto.CompactTextString(m) } func (*CreateContainerResponse) ProtoMessage() {} -func (*CreateContainerResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{36} } +func (*CreateContainerResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{37} } func (m *CreateContainerResponse) GetContainerId() string { if m != nil && m.ContainerId != nil { @@ -1668,7 +1734,7 @@ type StartContainerRequest struct { func (m *StartContainerRequest) Reset() { *m = StartContainerRequest{} } func (m *StartContainerRequest) String() string { return proto.CompactTextString(m) } func (*StartContainerRequest) ProtoMessage() {} -func (*StartContainerRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{37} } +func (*StartContainerRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{38} } func (m *StartContainerRequest) GetContainerId() string { if m != nil && m.ContainerId != nil { @@ -1684,7 +1750,7 @@ type StartContainerResponse struct { func (m *StartContainerResponse) Reset() { *m = StartContainerResponse{} } func (m *StartContainerResponse) String() string { return proto.CompactTextString(m) } func (*StartContainerResponse) ProtoMessage() {} -func (*StartContainerResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{38} } +func (*StartContainerResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{39} } type StopContainerRequest struct { // The id of the container @@ -1697,7 +1763,7 @@ type StopContainerRequest struct { func (m *StopContainerRequest) Reset() { *m = StopContainerRequest{} } func (m *StopContainerRequest) String() string { return proto.CompactTextString(m) } func (*StopContainerRequest) ProtoMessage() {} -func (*StopContainerRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{39} } +func (*StopContainerRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{40} } func (m *StopContainerRequest) GetContainerId() string { if m != nil && m.ContainerId != nil { @@ -1720,7 +1786,7 @@ type StopContainerResponse struct { func (m *StopContainerResponse) Reset() { *m = StopContainerResponse{} } func (m *StopContainerResponse) String() string { return proto.CompactTextString(m) } func (*StopContainerResponse) ProtoMessage() {} -func (*StopContainerResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{40} } +func (*StopContainerResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{41} } type RemoveContainerRequest struct { // The id of the container @@ -1731,7 +1797,7 @@ type RemoveContainerRequest struct { func (m *RemoveContainerRequest) Reset() { *m = RemoveContainerRequest{} } func (m *RemoveContainerRequest) String() string { return proto.CompactTextString(m) } func (*RemoveContainerRequest) ProtoMessage() {} -func (*RemoveContainerRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{41} } +func (*RemoveContainerRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{42} } func (m *RemoveContainerRequest) GetContainerId() string { if m != nil && m.ContainerId != nil { @@ -1747,7 +1813,7 @@ type RemoveContainerResponse struct { func (m *RemoveContainerResponse) Reset() { *m = RemoveContainerResponse{} } func (m *RemoveContainerResponse) String() string { return proto.CompactTextString(m) } func (*RemoveContainerResponse) ProtoMessage() {} -func (*RemoveContainerResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{42} } +func (*RemoveContainerResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{43} } // ContainerFilter is used to filter containers. // All those fields are combined with 'AND' @@ -1768,7 +1834,7 @@ type ContainerFilter struct { func (m *ContainerFilter) Reset() { *m = ContainerFilter{} } func (m *ContainerFilter) String() string { return proto.CompactTextString(m) } func (*ContainerFilter) ProtoMessage() {} -func (*ContainerFilter) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{43} } +func (*ContainerFilter) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{44} } func (m *ContainerFilter) GetId() string { if m != nil && m.Id != nil { @@ -1806,7 +1872,7 @@ type ListContainersRequest struct { func (m *ListContainersRequest) Reset() { *m = ListContainersRequest{} } func (m *ListContainersRequest) String() string { return proto.CompactTextString(m) } func (*ListContainersRequest) ProtoMessage() {} -func (*ListContainersRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{44} } +func (*ListContainersRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{45} } func (m *ListContainersRequest) GetFilter() *ContainerFilter { if m != nil { @@ -1845,7 +1911,7 @@ type Container struct { func (m *Container) Reset() { *m = Container{} } func (m *Container) String() string { return proto.CompactTextString(m) } func (*Container) ProtoMessage() {} -func (*Container) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{45} } +func (*Container) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{46} } func (m *Container) GetId() string { if m != nil && m.Id != nil { @@ -1919,7 +1985,7 @@ type ListContainersResponse struct { func (m *ListContainersResponse) Reset() { *m = ListContainersResponse{} } func (m *ListContainersResponse) String() string { return proto.CompactTextString(m) } func (*ListContainersResponse) ProtoMessage() {} -func (*ListContainersResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{46} } +func (*ListContainersResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{47} } func (m *ListContainersResponse) GetContainers() []*Container { if m != nil { @@ -1937,7 +2003,7 @@ type ContainerStatusRequest struct { func (m *ContainerStatusRequest) Reset() { *m = ContainerStatusRequest{} } func (m *ContainerStatusRequest) String() string { return proto.CompactTextString(m) } func (*ContainerStatusRequest) ProtoMessage() {} -func (*ContainerStatusRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{47} } +func (*ContainerStatusRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{48} } func (m *ContainerStatusRequest) GetContainerId() string { if m != nil && m.ContainerId != nil { @@ -1984,7 +2050,7 @@ type ContainerStatus struct { func (m *ContainerStatus) Reset() { *m = ContainerStatus{} } func (m *ContainerStatus) String() string { return proto.CompactTextString(m) } func (*ContainerStatus) ProtoMessage() {} -func (*ContainerStatus) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{48} } +func (*ContainerStatus) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{49} } func (m *ContainerStatus) GetId() string { if m != nil && m.Id != nil { @@ -2093,7 +2159,7 @@ type ContainerStatusResponse struct { func (m *ContainerStatusResponse) Reset() { *m = ContainerStatusResponse{} } func (m *ContainerStatusResponse) String() string { return proto.CompactTextString(m) } func (*ContainerStatusResponse) ProtoMessage() {} -func (*ContainerStatusResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{49} } +func (*ContainerStatusResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{50} } func (m *ContainerStatusResponse) GetStatus() *ContainerStatus { if m != nil { @@ -2115,7 +2181,7 @@ type ExecSyncRequest struct { func (m *ExecSyncRequest) Reset() { *m = ExecSyncRequest{} } func (m *ExecSyncRequest) String() string { return proto.CompactTextString(m) } func (*ExecSyncRequest) ProtoMessage() {} -func (*ExecSyncRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{50} } +func (*ExecSyncRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{51} } func (m *ExecSyncRequest) GetContainerId() string { if m != nil && m.ContainerId != nil { @@ -2151,7 +2217,7 @@ type ExecSyncResponse struct { func (m *ExecSyncResponse) Reset() { *m = ExecSyncResponse{} } func (m *ExecSyncResponse) String() string { return proto.CompactTextString(m) } func (*ExecSyncResponse) ProtoMessage() {} -func (*ExecSyncResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{51} } +func (*ExecSyncResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{52} } func (m *ExecSyncResponse) GetStdout() []byte { if m != nil { @@ -2189,7 +2255,7 @@ type ExecRequest struct { func (m *ExecRequest) Reset() { *m = ExecRequest{} } func (m *ExecRequest) String() string { return proto.CompactTextString(m) } func (*ExecRequest) ProtoMessage() {} -func (*ExecRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{52} } +func (*ExecRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{53} } func (m *ExecRequest) GetContainerId() string { if m != nil && m.ContainerId != nil { @@ -2228,7 +2294,7 @@ type ExecResponse struct { func (m *ExecResponse) Reset() { *m = ExecResponse{} } func (m *ExecResponse) String() string { return proto.CompactTextString(m) } func (*ExecResponse) ProtoMessage() {} -func (*ExecResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{53} } +func (*ExecResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{54} } func (m *ExecResponse) GetUrl() string { if m != nil && m.Url != nil { @@ -2248,7 +2314,7 @@ type AttachRequest struct { func (m *AttachRequest) Reset() { *m = AttachRequest{} } func (m *AttachRequest) String() string { return proto.CompactTextString(m) } func (*AttachRequest) ProtoMessage() {} -func (*AttachRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{54} } +func (*AttachRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{55} } func (m *AttachRequest) GetContainerId() string { if m != nil && m.ContainerId != nil { @@ -2273,7 +2339,7 @@ type AttachResponse struct { func (m *AttachResponse) Reset() { *m = AttachResponse{} } func (m *AttachResponse) String() string { return proto.CompactTextString(m) } func (*AttachResponse) ProtoMessage() {} -func (*AttachResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{55} } +func (*AttachResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{56} } func (m *AttachResponse) GetUrl() string { if m != nil && m.Url != nil { @@ -2293,7 +2359,7 @@ type PortForwardRequest struct { func (m *PortForwardRequest) Reset() { *m = PortForwardRequest{} } func (m *PortForwardRequest) String() string { return proto.CompactTextString(m) } func (*PortForwardRequest) ProtoMessage() {} -func (*PortForwardRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{56} } +func (*PortForwardRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{57} } func (m *PortForwardRequest) GetPodSandboxId() string { if m != nil && m.PodSandboxId != nil { @@ -2318,7 +2384,7 @@ type PortForwardResponse struct { func (m *PortForwardResponse) Reset() { *m = PortForwardResponse{} } func (m *PortForwardResponse) String() string { return proto.CompactTextString(m) } func (*PortForwardResponse) ProtoMessage() {} -func (*PortForwardResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{57} } +func (*PortForwardResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{58} } func (m *PortForwardResponse) GetUrl() string { if m != nil && m.Url != nil { @@ -2336,7 +2402,7 @@ type ImageFilter struct { func (m *ImageFilter) Reset() { *m = ImageFilter{} } func (m *ImageFilter) String() string { return proto.CompactTextString(m) } func (*ImageFilter) ProtoMessage() {} -func (*ImageFilter) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{58} } +func (*ImageFilter) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{59} } func (m *ImageFilter) GetImage() *ImageSpec { if m != nil { @@ -2354,7 +2420,7 @@ type ListImagesRequest struct { func (m *ListImagesRequest) Reset() { *m = ListImagesRequest{} } func (m *ListImagesRequest) String() string { return proto.CompactTextString(m) } func (*ListImagesRequest) ProtoMessage() {} -func (*ListImagesRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{59} } +func (*ListImagesRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{60} } func (m *ListImagesRequest) GetFilter() *ImageFilter { if m != nil { @@ -2372,14 +2438,16 @@ type Image struct { // Digests by which this image is known. RepoDigests []string `protobuf:"bytes,3,rep,name=repo_digests,json=repoDigests" json:"repo_digests,omitempty"` // The size of the image in bytes. - Size_ *uint64 `protobuf:"varint,4,opt,name=size" json:"size,omitempty"` - XXX_unrecognized []byte `json:"-"` + Size_ *uint64 `protobuf:"varint,4,opt,name=size" json:"size,omitempty"` + // The uid that will run the command(s). + Uid *int64 `protobuf:"varint,5,opt,name=uid" json:"uid,omitempty"` + XXX_unrecognized []byte `json:"-"` } func (m *Image) Reset() { *m = Image{} } func (m *Image) String() string { return proto.CompactTextString(m) } func (*Image) ProtoMessage() {} -func (*Image) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{60} } +func (*Image) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{61} } func (m *Image) GetId() string { if m != nil && m.Id != nil { @@ -2409,6 +2477,13 @@ func (m *Image) GetSize_() uint64 { return 0 } +func (m *Image) GetUid() int64 { + if m != nil && m.Uid != nil { + return *m.Uid + } + return 0 +} + type ListImagesResponse struct { // List of images Images []*Image `protobuf:"bytes,1,rep,name=images" json:"images,omitempty"` @@ -2418,7 +2493,7 @@ type ListImagesResponse struct { func (m *ListImagesResponse) Reset() { *m = ListImagesResponse{} } func (m *ListImagesResponse) String() string { return proto.CompactTextString(m) } func (*ListImagesResponse) ProtoMessage() {} -func (*ListImagesResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{61} } +func (*ListImagesResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{62} } func (m *ListImagesResponse) GetImages() []*Image { if m != nil { @@ -2436,7 +2511,7 @@ type ImageStatusRequest struct { func (m *ImageStatusRequest) Reset() { *m = ImageStatusRequest{} } func (m *ImageStatusRequest) String() string { return proto.CompactTextString(m) } func (*ImageStatusRequest) ProtoMessage() {} -func (*ImageStatusRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{62} } +func (*ImageStatusRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{63} } func (m *ImageStatusRequest) GetImage() *ImageSpec { if m != nil { @@ -2454,7 +2529,7 @@ type ImageStatusResponse struct { func (m *ImageStatusResponse) Reset() { *m = ImageStatusResponse{} } func (m *ImageStatusResponse) String() string { return proto.CompactTextString(m) } func (*ImageStatusResponse) ProtoMessage() {} -func (*ImageStatusResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{63} } +func (*ImageStatusResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{64} } func (m *ImageStatusResponse) GetImage() *Image { if m != nil { @@ -2480,7 +2555,7 @@ type AuthConfig struct { func (m *AuthConfig) Reset() { *m = AuthConfig{} } func (m *AuthConfig) String() string { return proto.CompactTextString(m) } func (*AuthConfig) ProtoMessage() {} -func (*AuthConfig) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{64} } +func (*AuthConfig) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{65} } func (m *AuthConfig) GetUsername() string { if m != nil && m.Username != nil { @@ -2537,7 +2612,7 @@ type PullImageRequest struct { func (m *PullImageRequest) Reset() { *m = PullImageRequest{} } func (m *PullImageRequest) String() string { return proto.CompactTextString(m) } func (*PullImageRequest) ProtoMessage() {} -func (*PullImageRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{65} } +func (*PullImageRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{66} } func (m *PullImageRequest) GetImage() *ImageSpec { if m != nil { @@ -2567,7 +2642,7 @@ type PullImageResponse struct { func (m *PullImageResponse) Reset() { *m = PullImageResponse{} } func (m *PullImageResponse) String() string { return proto.CompactTextString(m) } func (*PullImageResponse) ProtoMessage() {} -func (*PullImageResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{66} } +func (*PullImageResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{67} } type RemoveImageRequest struct { // The spec of the image @@ -2578,7 +2653,7 @@ type RemoveImageRequest struct { func (m *RemoveImageRequest) Reset() { *m = RemoveImageRequest{} } func (m *RemoveImageRequest) String() string { return proto.CompactTextString(m) } func (*RemoveImageRequest) ProtoMessage() {} -func (*RemoveImageRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{67} } +func (*RemoveImageRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{68} } func (m *RemoveImageRequest) GetImage() *ImageSpec { if m != nil { @@ -2594,7 +2669,7 @@ type RemoveImageResponse struct { func (m *RemoveImageResponse) Reset() { *m = RemoveImageResponse{} } func (m *RemoveImageResponse) String() string { return proto.CompactTextString(m) } func (*RemoveImageResponse) ProtoMessage() {} -func (*RemoveImageResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{68} } +func (*RemoveImageResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{69} } type NetworkConfig struct { // The CIDR to use for pod IP addresses @@ -2605,7 +2680,7 @@ type NetworkConfig struct { func (m *NetworkConfig) Reset() { *m = NetworkConfig{} } func (m *NetworkConfig) String() string { return proto.CompactTextString(m) } func (*NetworkConfig) ProtoMessage() {} -func (*NetworkConfig) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{69} } +func (*NetworkConfig) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{70} } func (m *NetworkConfig) GetPodCidr() string { if m != nil && m.PodCidr != nil { @@ -2622,7 +2697,7 @@ type RuntimeConfig struct { func (m *RuntimeConfig) Reset() { *m = RuntimeConfig{} } func (m *RuntimeConfig) String() string { return proto.CompactTextString(m) } func (*RuntimeConfig) ProtoMessage() {} -func (*RuntimeConfig) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{70} } +func (*RuntimeConfig) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{71} } func (m *RuntimeConfig) GetNetworkConfig() *NetworkConfig { if m != nil { @@ -2639,7 +2714,7 @@ type UpdateRuntimeConfigRequest struct { func (m *UpdateRuntimeConfigRequest) Reset() { *m = UpdateRuntimeConfigRequest{} } func (m *UpdateRuntimeConfigRequest) String() string { return proto.CompactTextString(m) } func (*UpdateRuntimeConfigRequest) ProtoMessage() {} -func (*UpdateRuntimeConfigRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{71} } +func (*UpdateRuntimeConfigRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{72} } func (m *UpdateRuntimeConfigRequest) GetRuntimeConfig() *RuntimeConfig { if m != nil { @@ -2655,7 +2730,7 @@ type UpdateRuntimeConfigResponse struct { func (m *UpdateRuntimeConfigResponse) Reset() { *m = UpdateRuntimeConfigResponse{} } func (m *UpdateRuntimeConfigResponse) String() string { return proto.CompactTextString(m) } func (*UpdateRuntimeConfigResponse) ProtoMessage() {} -func (*UpdateRuntimeConfigResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{72} } +func (*UpdateRuntimeConfigResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{73} } // RuntimeCondition contains condition information for the runtime. // There are 2 kinds of runtime conditions: @@ -2685,7 +2760,7 @@ type RuntimeCondition struct { func (m *RuntimeCondition) Reset() { *m = RuntimeCondition{} } func (m *RuntimeCondition) String() string { return proto.CompactTextString(m) } func (*RuntimeCondition) ProtoMessage() {} -func (*RuntimeCondition) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{73} } +func (*RuntimeCondition) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{74} } func (m *RuntimeCondition) GetType() string { if m != nil && m.Type != nil { @@ -2725,7 +2800,7 @@ type RuntimeStatus struct { func (m *RuntimeStatus) Reset() { *m = RuntimeStatus{} } func (m *RuntimeStatus) String() string { return proto.CompactTextString(m) } func (*RuntimeStatus) ProtoMessage() {} -func (*RuntimeStatus) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{74} } +func (*RuntimeStatus) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{75} } func (m *RuntimeStatus) GetConditions() []*RuntimeCondition { if m != nil { @@ -2741,7 +2816,7 @@ type StatusRequest struct { func (m *StatusRequest) Reset() { *m = StatusRequest{} } func (m *StatusRequest) String() string { return proto.CompactTextString(m) } func (*StatusRequest) ProtoMessage() {} -func (*StatusRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{75} } +func (*StatusRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{76} } type StatusResponse struct { // The status of the Runtime. @@ -2752,7 +2827,7 @@ type StatusResponse struct { func (m *StatusResponse) Reset() { *m = StatusResponse{} } func (m *StatusResponse) String() string { return proto.CompactTextString(m) } func (*StatusResponse) ProtoMessage() {} -func (*StatusResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{76} } +func (*StatusResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{77} } func (m *StatusResponse) GetStatus() *RuntimeStatus { if m != nil { @@ -2768,6 +2843,7 @@ func init() { proto.RegisterType((*PortMapping)(nil), "runtime.PortMapping") proto.RegisterType((*Mount)(nil), "runtime.Mount") proto.RegisterType((*NamespaceOption)(nil), "runtime.NamespaceOption") + proto.RegisterType((*LinuxSandboxSecurityContext)(nil), "runtime.LinuxSandboxSecurityContext") proto.RegisterType((*LinuxPodSandboxConfig)(nil), "runtime.LinuxPodSandboxConfig") proto.RegisterType((*PodSandboxMetadata)(nil), "runtime.PodSandboxMetadata") proto.RegisterType((*PodSandboxConfig)(nil), "runtime.PodSandboxConfig") @@ -2792,8 +2868,8 @@ func init() { proto.RegisterType((*LinuxContainerResources)(nil), "runtime.LinuxContainerResources") proto.RegisterType((*SELinuxOption)(nil), "runtime.SELinuxOption") proto.RegisterType((*Capability)(nil), "runtime.Capability") + proto.RegisterType((*LinuxContainerSecurityContext)(nil), "runtime.LinuxContainerSecurityContext") proto.RegisterType((*LinuxContainerConfig)(nil), "runtime.LinuxContainerConfig") - proto.RegisterType((*LinuxUser)(nil), "runtime.LinuxUser") proto.RegisterType((*ContainerMetadata)(nil), "runtime.ContainerMetadata") proto.RegisterType((*Device)(nil), "runtime.Device") proto.RegisterType((*ContainerConfig)(nil), "runtime.ContainerConfig") @@ -3725,209 +3801,214 @@ var _ImageService_serviceDesc = grpc.ServiceDesc{ } var fileDescriptorApi = []byte{ - // 3262 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xcc, 0x3a, 0x4d, 0x73, 0x1b, 0xc7, - 0xb1, 0x04, 0x40, 0x82, 0x40, 0x83, 0x00, 0xc1, 0x11, 0x45, 0x42, 0xa0, 0x25, 0x51, 0x6b, 0xcb, - 0x96, 0x64, 0x9b, 0x65, 0xf1, 0xbd, 0x67, 0x3d, 0xcb, 0x96, 0x6c, 0x98, 0xa4, 0xfd, 0x68, 0x49, - 0x10, 0xdf, 0x40, 0x72, 0xec, 0xf2, 0x61, 0xb3, 0xc2, 0x8e, 0xc0, 0x95, 0x80, 0xdd, 0xf5, 0xec, - 0x82, 0x16, 0x73, 0xcd, 0x25, 0x87, 0x1c, 0x72, 0xcd, 0x2d, 0x95, 0x4a, 0x95, 0xab, 0x92, 0x5b, - 0xaa, 0x52, 0x95, 0xff, 0x90, 0xca, 0x0f, 0xc9, 0x3f, 0xc8, 0x31, 0x35, 0x9f, 0x3b, 0xfb, 0x01, - 0x9a, 0x94, 0x53, 0xb1, 0x6e, 0x3b, 0x3d, 0xdd, 0x3d, 0x3d, 0xdd, 0x3d, 0x3d, 0xdd, 0x3d, 0x0b, - 0x75, 0x27, 0xf4, 0xb6, 0x42, 0x1a, 0xc4, 0x01, 0x5a, 0xa4, 0x53, 0x3f, 0xf6, 0x26, 0xc4, 0xba, - 0x01, 0xad, 0x2f, 0x09, 0x8d, 0xbc, 0xc0, 0xc7, 0xe4, 0xdb, 0x29, 0x89, 0x62, 0xd4, 0x81, 0xc5, - 0x23, 0x01, 0xe9, 0x94, 0x36, 0x4b, 0xd7, 0xea, 0x58, 0x0d, 0xad, 0xef, 0x4b, 0xb0, 0xac, 0x91, - 0xa3, 0x30, 0xf0, 0x23, 0x32, 0x1b, 0x1b, 0x5d, 0x81, 0x25, 0xb9, 0x88, 0xed, 0x3b, 0x13, 0xd2, - 0x29, 0xf3, 0xe9, 0x86, 0x84, 0xf5, 0x9d, 0x09, 0x41, 0x6f, 0xc1, 0xb2, 0x42, 0x51, 0x4c, 0x2a, - 0x1c, 0xab, 0x25, 0xc1, 0x72, 0x35, 0xb4, 0x05, 0xe7, 0x14, 0xa2, 0x13, 0x7a, 0x1a, 0x79, 0x9e, - 0x23, 0xaf, 0xc8, 0xa9, 0x5e, 0xe8, 0x49, 0x7c, 0xeb, 0x1b, 0xa8, 0xef, 0xf6, 0x07, 0x3b, 0x81, - 0xff, 0xd4, 0x1b, 0x31, 0x11, 0x23, 0x42, 0x19, 0x4d, 0xa7, 0xb4, 0x59, 0x61, 0x22, 0xca, 0x21, - 0xea, 0x42, 0x2d, 0x22, 0x0e, 0x1d, 0x1e, 0x92, 0xa8, 0x53, 0xe6, 0x53, 0x7a, 0xcc, 0xa8, 0x82, - 0x30, 0xf6, 0x02, 0x3f, 0xea, 0x54, 0x04, 0x95, 0x1c, 0x5a, 0xbf, 0x2d, 0x41, 0xe3, 0x20, 0xa0, - 0xf1, 0x03, 0x27, 0x0c, 0x3d, 0x7f, 0x84, 0xde, 0x85, 0x1a, 0x57, 0xea, 0x30, 0x18, 0x73, 0x1d, - 0xb4, 0xb6, 0x57, 0xb6, 0xa4, 0x48, 0x5b, 0x07, 0x72, 0x02, 0x6b, 0x14, 0x74, 0x15, 0x5a, 0xc3, - 0xc0, 0x8f, 0x1d, 0xcf, 0x27, 0xd4, 0x0e, 0x03, 0x1a, 0x73, 0xcd, 0x2c, 0xe0, 0xa6, 0x86, 0x32, - 0xe6, 0x68, 0x03, 0xea, 0x87, 0x41, 0x14, 0x0b, 0x8c, 0x0a, 0xc7, 0xa8, 0x31, 0x00, 0x9f, 0x5c, - 0x87, 0x45, 0x3e, 0xe9, 0x85, 0x52, 0x07, 0x55, 0x36, 0xdc, 0x0f, 0xad, 0xdf, 0x94, 0x60, 0xe1, - 0x41, 0x30, 0xf5, 0xe3, 0xcc, 0x32, 0x4e, 0x7c, 0x28, 0xed, 0x63, 0x2c, 0xe3, 0xc4, 0x87, 0xc9, - 0x32, 0x0c, 0x43, 0x98, 0x48, 0x2c, 0xc3, 0x26, 0xbb, 0x50, 0xa3, 0xc4, 0x71, 0x03, 0x7f, 0x7c, - 0xcc, 0x45, 0xa8, 0x61, 0x3d, 0x66, 0xb6, 0x8b, 0xc8, 0xd8, 0xf3, 0xa7, 0x2f, 0x6c, 0x4a, 0xc6, - 0xce, 0x13, 0x32, 0xe6, 0xa2, 0xd4, 0x70, 0x4b, 0x82, 0xb1, 0x80, 0x5a, 0xcf, 0x60, 0x99, 0x19, - 0x3b, 0x0a, 0x9d, 0x21, 0x79, 0xc8, 0x55, 0xc8, 0x5c, 0x83, 0x2f, 0xea, 0x93, 0xf8, 0xbb, 0x80, - 0x3e, 0xe7, 0x92, 0xd5, 0x70, 0x83, 0xc1, 0xfa, 0x02, 0x84, 0x2e, 0x40, 0x4d, 0xc8, 0xe5, 0xb9, - 0x5c, 0xac, 0x1a, 0xe6, 0x3b, 0x3e, 0xf0, 0x5c, 0x3d, 0xe5, 0x85, 0x43, 0x29, 0xd5, 0xa2, 0xd8, - 0xfd, 0xd0, 0xfa, 0x65, 0x09, 0xce, 0xdf, 0x67, 0x8b, 0x1f, 0x04, 0xee, 0xc0, 0xf1, 0xdd, 0x27, - 0xc1, 0x0b, 0xe9, 0x04, 0xaf, 0x43, 0x73, 0x38, 0xa2, 0xc1, 0x34, 0xb4, 0x43, 0x87, 0x12, 0x3f, - 0x96, 0xda, 0x58, 0x12, 0xc0, 0x03, 0x0e, 0x43, 0x7b, 0xb0, 0xe2, 0x2b, 0x51, 0x6d, 0x65, 0x7d, - 0xb6, 0x7a, 0x63, 0xbb, 0xa3, 0x4d, 0x9a, 0xd9, 0x0c, 0x6e, 0xfb, 0x69, 0x40, 0x64, 0x51, 0x40, - 0xc9, 0xfa, 0x0f, 0x48, 0xec, 0xb8, 0x4e, 0xec, 0x20, 0x04, 0xf3, 0xfc, 0x1c, 0x88, 0x85, 0xf9, - 0x37, 0x6a, 0x43, 0x65, 0x2a, 0x37, 0x58, 0xc7, 0xec, 0x13, 0xbd, 0x06, 0x75, 0xcd, 0x4f, 0x1e, - 0x86, 0x04, 0xc0, 0x9c, 0xd2, 0x89, 0x63, 0x32, 0x09, 0x63, 0xae, 0xec, 0x26, 0x56, 0x43, 0xeb, - 0xaf, 0xf3, 0xd0, 0xce, 0x6d, 0xfa, 0x16, 0xd4, 0x26, 0x72, 0x79, 0xbe, 0x6c, 0x63, 0x7b, 0x23, - 0xf1, 0xcc, 0x9c, 0x84, 0x58, 0x23, 0x33, 0xc3, 0x33, 0x95, 0x1a, 0xe7, 0x56, 0x8f, 0x99, 0x26, - 0xc7, 0xc1, 0xc8, 0x76, 0x3d, 0x4a, 0x86, 0x71, 0x40, 0x8f, 0xa5, 0x94, 0x4b, 0xe3, 0x60, 0xb4, - 0xab, 0x60, 0xe8, 0x26, 0x80, 0xeb, 0x47, 0xf6, 0x90, 0xcb, 0xc1, 0x65, 0x6d, 0x6c, 0x23, 0xbd, - 0xb6, 0x3e, 0x9b, 0xb8, 0xee, 0xfa, 0x91, 0x14, 0xf6, 0x03, 0x68, 0x32, 0x5f, 0xb7, 0x27, 0xe2, - 0x58, 0x45, 0x9d, 0x85, 0xcd, 0xca, 0xb5, 0xc6, 0xf6, 0xaa, 0x21, 0xb1, 0x3e, 0x73, 0x78, 0x29, - 0x4c, 0x06, 0x11, 0xba, 0x03, 0x55, 0xee, 0x6b, 0x51, 0xa7, 0xca, 0x69, 0xae, 0x16, 0xec, 0x52, - 0xac, 0xb2, 0x75, 0x9f, 0xe3, 0xed, 0xf9, 0x31, 0x3d, 0xc6, 0x92, 0x08, 0xdd, 0x87, 0x86, 0xe3, - 0xfb, 0x41, 0xec, 0x08, 0x83, 0x2f, 0x72, 0x1e, 0x37, 0x66, 0xf3, 0xe8, 0x25, 0xc8, 0x82, 0x91, - 0x49, 0x8e, 0xfe, 0x1b, 0x16, 0xb8, 0xff, 0x77, 0x6a, 0x7c, 0xd7, 0x97, 0x34, 0x9f, 0x42, 0xc7, - 0xc4, 0x02, 0xb9, 0xfb, 0x01, 0x34, 0x0c, 0xd1, 0x98, 0x63, 0x3c, 0x27, 0xc7, 0xd2, 0x57, 0xd8, - 0x27, 0x5a, 0x85, 0x85, 0x23, 0x67, 0x3c, 0x55, 0xf6, 0x10, 0x83, 0xdb, 0xe5, 0xff, 0x2d, 0x75, - 0xef, 0x42, 0x3b, 0x2b, 0xd1, 0x59, 0xe8, 0xad, 0x7d, 0x58, 0xc5, 0x53, 0x3f, 0x11, 0x4c, 0x5d, - 0x04, 0x37, 0xa1, 0x2a, 0xed, 0x27, 0x7c, 0xe7, 0xc2, 0x4c, 0x8d, 0x60, 0x89, 0x68, 0xdd, 0x81, - 0xf3, 0x19, 0x56, 0xf2, 0x9a, 0x78, 0x03, 0x5a, 0x61, 0xe0, 0xda, 0x91, 0x00, 0xdb, 0x9e, 0xab, - 0xce, 0x5f, 0xa8, 0x71, 0xf7, 0x5d, 0x46, 0x3e, 0x88, 0x83, 0x30, 0x2f, 0xca, 0xe9, 0xc8, 0x3b, - 0xb0, 0x96, 0x25, 0x17, 0xcb, 0x5b, 0x1f, 0xc3, 0x3a, 0x26, 0x93, 0xe0, 0x88, 0xbc, 0x2c, 0xeb, - 0x2e, 0x74, 0xf2, 0x0c, 0x12, 0xe6, 0x09, 0x74, 0x10, 0x3b, 0xf1, 0x34, 0x3a, 0x1b, 0xf3, 0xeb, - 0x26, 0x03, 0x19, 0x00, 0x05, 0x1f, 0xd4, 0x82, 0xb2, 0x17, 0x4a, 0xa2, 0xb2, 0x17, 0x5a, 0x5f, - 0x43, 0xbd, 0x6f, 0x46, 0x03, 0x33, 0x82, 0xd6, 0xb1, 0x1a, 0xa2, 0xed, 0xe4, 0xf2, 0xfa, 0xa1, - 0xf0, 0xa5, 0xaf, 0xb5, 0x7b, 0xb9, 0xd0, 0x29, 0x65, 0xd8, 0x06, 0xd0, 0x11, 0x28, 0x92, 0xbe, - 0x80, 0xf2, 0xfc, 0xb0, 0x81, 0x65, 0xfd, 0x21, 0x15, 0x8e, 0x8c, 0xcd, 0xb8, 0x7a, 0x33, 0x6e, - 0x2a, 0x3c, 0x95, 0xcf, 0x12, 0x9e, 0xb6, 0x60, 0x21, 0x8a, 0x9d, 0x58, 0x04, 0xc8, 0x96, 0xb1, - 0xb9, 0xf4, 0x92, 0x04, 0x0b, 0x34, 0x74, 0x11, 0x60, 0x48, 0x89, 0x13, 0x13, 0xd7, 0x76, 0x44, - 0xe4, 0xac, 0xe0, 0xba, 0x84, 0xf4, 0x62, 0x74, 0x3b, 0xd1, 0xe3, 0x02, 0x17, 0x63, 0xb3, 0x80, - 0x61, 0xca, 0x2e, 0x89, 0xa6, 0xf5, 0x69, 0xaf, 0x9e, 0x7c, 0xda, 0x25, 0x9d, 0x40, 0x36, 0x02, - 0xd6, 0xe2, 0xcc, 0x80, 0x25, 0x28, 0x4e, 0x13, 0xb0, 0x6a, 0x33, 0x03, 0x96, 0xe4, 0x71, 0x62, - 0xc0, 0xfa, 0x29, 0x43, 0xcf, 0x03, 0xe8, 0xe4, 0x8f, 0x8e, 0x0c, 0x19, 0x37, 0xa1, 0x1a, 0x71, - 0xc8, 0x09, 0xe1, 0x47, 0x92, 0x48, 0x44, 0xeb, 0x1f, 0x25, 0xd3, 0xeb, 0x3e, 0xf3, 0xc6, 0x31, - 0xa1, 0x39, 0xaf, 0xd3, 0xce, 0x53, 0x3e, 0x9d, 0xf3, 0x0c, 0xa0, 0xc5, 0xd5, 0x6e, 0x47, 0x64, - 0xcc, 0x6f, 0x37, 0x9e, 0x0f, 0x36, 0xb6, 0xdf, 0x29, 0x20, 0x14, 0x4b, 0x0a, 0x9b, 0x0d, 0x24, - 0xba, 0xd0, 0x78, 0x73, 0x6c, 0xc2, 0xba, 0x9f, 0x00, 0xca, 0x23, 0x9d, 0x49, 0x75, 0x5f, 0xb0, - 0xe3, 0xca, 0xd2, 0xc1, 0x82, 0xb0, 0xfd, 0x94, 0x8b, 0x71, 0x82, 0xde, 0x84, 0x9c, 0x58, 0x22, - 0x5a, 0xbf, 0xab, 0x00, 0x24, 0x93, 0xaf, 0xec, 0x39, 0xbd, 0xa5, 0x4f, 0x8d, 0x48, 0x0d, 0x2e, - 0x17, 0xf0, 0x2b, 0x3c, 0x2f, 0x9f, 0xa5, 0xcf, 0x8b, 0x48, 0x12, 0xde, 0x28, 0xa2, 0x7e, 0x65, - 0x4f, 0xca, 0x0e, 0xac, 0x65, 0xcd, 0x2d, 0xcf, 0xc9, 0x75, 0x58, 0xf0, 0x62, 0x32, 0x11, 0xc5, - 0x4d, 0x63, 0xfb, 0x5c, 0xc1, 0xb6, 0xb0, 0xc0, 0xb0, 0xae, 0x40, 0x7d, 0x7f, 0xe2, 0x8c, 0xc8, - 0x20, 0x24, 0x43, 0xb6, 0x96, 0xc7, 0x06, 0x72, 0x7d, 0x31, 0xb0, 0xb6, 0xa1, 0x76, 0x8f, 0x1c, - 0x7f, 0xc9, 0xd6, 0x3d, 0xad, 0x7c, 0xd6, 0xdf, 0x4a, 0xb0, 0xce, 0xc3, 0xdd, 0x8e, 0x2a, 0x2d, - 0x30, 0x89, 0x82, 0x29, 0x1d, 0x92, 0x88, 0x9b, 0x34, 0x9c, 0xda, 0x21, 0xa1, 0x5e, 0x20, 0x7c, - 0x8a, 0x99, 0x34, 0x9c, 0x1e, 0x70, 0x00, 0x2b, 0x3f, 0xd8, 0xf4, 0xb7, 0xd3, 0x40, 0xfa, 0x56, - 0x05, 0xd7, 0x86, 0xe1, 0xf4, 0xff, 0xd9, 0x58, 0xd1, 0x46, 0x87, 0x0e, 0x25, 0x11, 0xf7, 0x21, - 0x41, 0x3b, 0xe0, 0x00, 0x74, 0x13, 0xce, 0x4f, 0xc8, 0x24, 0xa0, 0xc7, 0xf6, 0xd8, 0x9b, 0x78, - 0xb1, 0xed, 0xf9, 0xf6, 0x93, 0xe3, 0x98, 0x44, 0xd2, 0x71, 0x90, 0x98, 0xbc, 0xcf, 0xe6, 0xf6, - 0xfd, 0x4f, 0xd9, 0x0c, 0xb2, 0xa0, 0x19, 0x04, 0x13, 0x3b, 0x1a, 0x06, 0x94, 0xd8, 0x8e, 0xfb, - 0x8c, 0xc7, 0xfb, 0x0a, 0x6e, 0x04, 0xc1, 0x64, 0xc0, 0x60, 0x3d, 0xf7, 0x99, 0xe5, 0x40, 0x73, - 0xb0, 0xc7, 0xb7, 0x23, 0xab, 0x15, 0x04, 0xf3, 0xd3, 0x48, 0x1e, 0xa7, 0x3a, 0xe6, 0xdf, 0x0c, - 0x46, 0x83, 0xb1, 0xd2, 0x03, 0xff, 0x66, 0xb0, 0xf8, 0x38, 0x54, 0x59, 0x3b, 0xff, 0x66, 0x0a, - 0x1b, 0x93, 0x23, 0x59, 0x1b, 0xd5, 0xb1, 0x18, 0x58, 0x2e, 0xc0, 0x8e, 0x13, 0x3a, 0x4f, 0xbc, - 0xb1, 0x17, 0x1f, 0xa3, 0xeb, 0xd0, 0x76, 0x5c, 0xd7, 0x1e, 0x2a, 0x88, 0x47, 0x54, 0xa1, 0xba, - 0xec, 0xb8, 0xee, 0x8e, 0x01, 0x46, 0x6f, 0xc3, 0x8a, 0x4b, 0x83, 0x30, 0x8d, 0x2b, 0x2a, 0xd7, - 0x36, 0x9b, 0x30, 0x91, 0xad, 0x7f, 0x96, 0x60, 0x35, 0x6d, 0x16, 0x99, 0x69, 0xdf, 0x85, 0x3a, - 0x55, 0x06, 0x92, 0x41, 0x62, 0x33, 0x7d, 0x6f, 0xe5, 0x0d, 0x89, 0x13, 0x12, 0x74, 0x0b, 0x96, - 0x32, 0x02, 0x94, 0x52, 0x8e, 0x97, 0xec, 0x0d, 0xa7, 0x10, 0xd1, 0xc7, 0x49, 0xcd, 0x98, 0xd4, - 0xd6, 0x8c, 0x76, 0x4d, 0xd3, 0xa6, 0x54, 0xaf, 0x6b, 0x49, 0x59, 0x59, 0xa1, 0x37, 0xa5, 0x29, - 0xb2, 0x05, 0x05, 0xa7, 0x79, 0x1c, 0x11, 0x2a, 0xcc, 0x63, 0x7d, 0x05, 0x75, 0x0d, 0x52, 0x45, - 0x96, 0xf0, 0x3d, 0x5e, 0x64, 0xb5, 0xa1, 0x32, 0x92, 0x65, 0x57, 0x05, 0xb3, 0x4f, 0x56, 0xcd, - 0x3a, 0xae, 0xeb, 0xb1, 0x55, 0x9c, 0xb1, 0x3d, 0xf2, 0x5c, 0x51, 0xf5, 0x57, 0x70, 0x2b, 0x01, - 0x7f, 0xee, 0xb9, 0x91, 0xd5, 0x83, 0x15, 0xad, 0x9c, 0x13, 0x4b, 0x3b, 0xa3, 0x54, 0x2b, 0xa7, - 0x4b, 0x35, 0x1f, 0xaa, 0xbb, 0xe4, 0xc8, 0x1b, 0x92, 0x7f, 0x4b, 0x8d, 0xbe, 0x09, 0x8d, 0x90, - 0xd0, 0x89, 0x17, 0x45, 0x5a, 0x9f, 0x75, 0x6c, 0x82, 0xac, 0xdf, 0x57, 0x61, 0x39, 0xeb, 0x02, - 0xef, 0xe7, 0x2a, 0xc3, 0x6e, 0x62, 0xbe, 0xec, 0xfe, 0x8c, 0x88, 0x7e, 0x4d, 0x05, 0x8d, 0x72, - 0xc6, 0x02, 0x3a, 0xae, 0xc8, 0x40, 0xc2, 0xf6, 0x3f, 0x0c, 0x26, 0x13, 0xc7, 0x77, 0x55, 0xff, - 0x44, 0x0e, 0x99, 0xb6, 0x1c, 0x3a, 0x62, 0xc7, 0x94, 0x81, 0xf9, 0x37, 0xba, 0x0c, 0x0d, 0x96, - 0x4e, 0x79, 0x3e, 0x2f, 0x2c, 0xf9, 0xb1, 0xac, 0x63, 0x90, 0xa0, 0x5d, 0x8f, 0xa2, 0xab, 0x30, - 0x4f, 0xfc, 0x23, 0x15, 0xbb, 0x93, 0x06, 0x8b, 0x0a, 0x56, 0x98, 0x4f, 0xa3, 0x37, 0xa1, 0x3a, - 0x09, 0xa6, 0x7e, 0xac, 0x12, 0xab, 0x96, 0x46, 0xe4, 0x5d, 0x11, 0x2c, 0x67, 0xd1, 0x75, 0x58, - 0x74, 0xb9, 0x0d, 0x54, 0xf6, 0xb4, 0x9c, 0x14, 0xa7, 0x1c, 0x8e, 0xd5, 0x3c, 0xfa, 0x48, 0xdf, - 0x3a, 0xf5, 0xcc, 0xbd, 0x91, 0x51, 0x6a, 0xe1, 0xd5, 0x73, 0x2f, 0x7d, 0xf5, 0x00, 0x67, 0x71, - 0x7d, 0x26, 0x8b, 0x93, 0x4b, 0xcb, 0x4b, 0x00, 0x21, 0xf5, 0x8e, 0xbc, 0x31, 0x19, 0x11, 0xb7, - 0xd3, 0xe0, 0xbd, 0x0f, 0x03, 0xc2, 0xfb, 0x69, 0xb2, 0x3f, 0x63, 0xd3, 0x20, 0x88, 0x9f, 0x46, - 0x9d, 0x25, 0xd1, 0x93, 0x51, 0x60, 0xcc, 0xa1, 0xe8, 0x02, 0xd4, 0x58, 0x0d, 0xcf, 0x1d, 0xaa, - 0x29, 0x4a, 0x87, 0x71, 0x30, 0xe2, 0xfe, 0xb4, 0xca, 0xee, 0x6c, 0xd7, 0xf3, 0x3b, 0x2d, 0x4e, - 0x29, 0x06, 0x2c, 0x14, 0xf3, 0x0f, 0x3b, 0xf0, 0x87, 0xa4, 0xb3, 0xcc, 0xa7, 0xea, 0x1c, 0xf2, - 0xd0, 0x1f, 0xf2, 0x9b, 0x22, 0x8e, 0x8f, 0x3b, 0x6d, 0x0e, 0x67, 0x9f, 0xe8, 0xbf, 0x54, 0x5e, - 0xbc, 0xc2, 0x1d, 0xe5, 0xe2, 0x8c, 0xf8, 0xf2, 0xca, 0x14, 0xc1, 0x7f, 0x2e, 0xc1, 0xda, 0x0e, - 0xcf, 0x34, 0x8c, 0xd8, 0x77, 0x86, 0x22, 0x0e, 0xbd, 0xa7, 0xab, 0xe5, 0x6c, 0xc5, 0x95, 0xdd, - 0xac, 0xc4, 0x43, 0x9f, 0x40, 0x4b, 0xf1, 0x94, 0x94, 0x95, 0x1f, 0xaa, 0xb3, 0x9b, 0x91, 0x39, - 0xb4, 0x3e, 0x82, 0xf5, 0x9c, 0xcc, 0x32, 0x2b, 0xb8, 0x02, 0x4b, 0x49, 0x68, 0xd1, 0x22, 0x37, - 0x34, 0x6c, 0xdf, 0xb5, 0x6e, 0xb3, 0x6a, 0xdb, 0xa1, 0x71, 0x6e, 0xc3, 0xa7, 0xa0, 0xe5, 0xa5, - 0x76, 0x9a, 0x56, 0x56, 0xc3, 0x03, 0x58, 0x65, 0x45, 0xf8, 0x4b, 0x30, 0x65, 0x21, 0x83, 0x6d, - 0x3b, 0x98, 0xc6, 0x32, 0x34, 0xab, 0xa1, 0xb5, 0x2e, 0x1a, 0x03, 0xf9, 0xd5, 0x3e, 0x84, 0x35, - 0x51, 0x97, 0xbf, 0xcc, 0x26, 0x2e, 0xa8, 0xae, 0x40, 0x9e, 0xef, 0xaf, 0xcb, 0x46, 0xcc, 0x9c, - 0x51, 0x48, 0xbc, 0x9b, 0x2e, 0x24, 0xd6, 0xf3, 0x06, 0x4f, 0x25, 0xb7, 0x79, 0x37, 0xaa, 0x14, - 0xb8, 0x11, 0xce, 0x55, 0x1b, 0xf3, 0x3c, 0x64, 0xbc, 0x9d, 0xe7, 0xfe, 0x1f, 0x2c, 0x36, 0xf6, - 0x45, 0xb1, 0xa1, 0x97, 0xd6, 0x0d, 0x8e, 0xf7, 0x32, 0xc5, 0x46, 0x67, 0x96, 0x98, 0xba, 0xd6, - 0xf8, 0xd5, 0x3c, 0xd4, 0xf5, 0x5c, 0x4e, 0xa7, 0x79, 0x25, 0x95, 0x0b, 0x94, 0x64, 0xde, 0x5e, - 0x95, 0x97, 0xb9, 0xbd, 0xe6, 0x7f, 0xe8, 0xf6, 0xda, 0x80, 0x3a, 0xff, 0xb0, 0x29, 0x79, 0x2a, - 0x6f, 0xa3, 0x1a, 0x07, 0x60, 0xf2, 0x34, 0x31, 0x7c, 0xf5, 0x54, 0x86, 0x4f, 0x57, 0x35, 0x8b, - 0xd9, 0xaa, 0xe6, 0x7d, 0x7d, 0xbf, 0x88, 0x9b, 0xe8, 0x52, 0x9e, 0x5d, 0xe1, 0xcd, 0xb2, 0x97, - 0xbe, 0x59, 0xc4, 0xe5, 0xf4, 0x7a, 0x01, 0xf1, 0x2b, 0x5b, 0xd3, 0xdc, 0x17, 0x35, 0x8d, 0xe9, - 0x55, 0x32, 0x7a, 0x6d, 0x03, 0xe8, 0x83, 0xaa, 0x0a, 0x1b, 0x94, 0xdf, 0x1a, 0x36, 0xb0, 0x58, - 0x28, 0x48, 0xe9, 0x3f, 0xe9, 0xc2, 0x9d, 0x22, 0x14, 0xfc, 0x69, 0xc1, 0x38, 0xef, 0x33, 0xda, - 0x55, 0xef, 0xe7, 0xca, 0xe0, 0xd3, 0x79, 0xdd, 0xbb, 0xe9, 0x2a, 0xf8, 0x6c, 0xee, 0x92, 0x2b, - 0x82, 0xf9, 0x4d, 0xec, 0x50, 0x39, 0x2d, 0xea, 0x97, 0xba, 0x84, 0xf4, 0x62, 0x96, 0x48, 0x3d, - 0xf5, 0x7c, 0x2f, 0x3a, 0x14, 0xf3, 0x55, 0x3e, 0x0f, 0x0a, 0xd4, 0xe3, 0xef, 0x4a, 0xe4, 0x85, - 0x17, 0xdb, 0xc3, 0xc0, 0x25, 0xdc, 0x19, 0x17, 0x70, 0x8d, 0x01, 0x76, 0x02, 0x97, 0x24, 0x07, - 0xa4, 0x76, 0xa6, 0x03, 0x52, 0xcf, 0x1c, 0x90, 0x35, 0xa8, 0x52, 0xe2, 0x44, 0x81, 0xdf, 0x01, - 0xf1, 0x3a, 0x25, 0x46, 0x2c, 0xc0, 0x4f, 0x48, 0x14, 0xb1, 0x05, 0x1a, 0x22, 0xeb, 0x90, 0x43, - 0x23, 0xc9, 0x5a, 0x9a, 0x95, 0x64, 0x9d, 0xd0, 0x0f, 0xcb, 0x24, 0x59, 0xcd, 0x59, 0x49, 0xd6, - 0x69, 0xda, 0x61, 0x46, 0x0a, 0xd9, 0x3a, 0x29, 0x85, 0xfc, 0x29, 0x0f, 0xce, 0x3d, 0x58, 0xcf, - 0xb9, 0xba, 0x3c, 0x39, 0xef, 0x65, 0xba, 0x66, 0x9d, 0x59, 0x5a, 0xd0, 0x4d, 0xb3, 0x9f, 0xc3, - 0xf2, 0xde, 0x0b, 0x32, 0x1c, 0x1c, 0xfb, 0xc3, 0x33, 0xdc, 0xd5, 0x6d, 0xa8, 0x0c, 0x27, 0xae, - 0xac, 0x3d, 0xd9, 0xa7, 0x79, 0x7b, 0x57, 0xd2, 0xb7, 0xb7, 0x0d, 0xed, 0x64, 0x05, 0x29, 0xe7, - 0x1a, 0x93, 0xd3, 0x65, 0xc8, 0x8c, 0xf9, 0x12, 0x96, 0x23, 0x09, 0x27, 0x94, 0xf2, 0x5d, 0x0b, - 0x38, 0xa1, 0x34, 0xed, 0xb6, 0x95, 0xb4, 0xdb, 0x5a, 0xcf, 0xa0, 0xc1, 0x16, 0xf8, 0x51, 0xe2, - 0xcb, 0x14, 0xb6, 0x92, 0xa4, 0xb0, 0x3a, 0x13, 0x9e, 0x37, 0x32, 0x61, 0x6b, 0x13, 0x96, 0xc4, - 0x5a, 0x72, 0x23, 0xac, 0xba, 0xa4, 0x63, 0x65, 0xb7, 0x29, 0x1d, 0x5b, 0xff, 0x07, 0xcd, 0x5e, - 0x1c, 0x3b, 0xc3, 0xc3, 0x33, 0xc8, 0xa3, 0xd7, 0x2a, 0x9b, 0x6b, 0x59, 0xd0, 0x52, 0x9c, 0x66, - 0xae, 0xd6, 0x07, 0x74, 0x10, 0xd0, 0xf8, 0xb3, 0x80, 0x7e, 0xe7, 0x50, 0xf7, 0x6c, 0x39, 0x2b, - 0x82, 0x79, 0xf9, 0x00, 0x5d, 0xb9, 0xb6, 0x80, 0xf9, 0xb7, 0xf5, 0x16, 0x9c, 0x4b, 0xf1, 0x9b, - 0xb9, 0xf0, 0x2d, 0x68, 0xf0, 0xa8, 0x20, 0xb3, 0xa3, 0x6b, 0x66, 0x3b, 0xe9, 0xa4, 0xd0, 0xc1, - 0x4a, 0x68, 0x16, 0xf6, 0x39, 0x5c, 0xc7, 0xe8, 0x77, 0x32, 0x89, 0xc4, 0x6a, 0x9a, 0x3e, 0x93, - 0x44, 0x3c, 0x87, 0x05, 0x0e, 0xce, 0xc5, 0xe8, 0x0d, 0xa8, 0x53, 0x12, 0x06, 0x76, 0xec, 0x8c, - 0xf4, 0x93, 0x3e, 0x03, 0x3c, 0x72, 0x46, 0x11, 0xff, 0x23, 0x81, 0x4d, 0xba, 0xde, 0x88, 0x44, - 0xb1, 0x7a, 0xd7, 0x6f, 0x30, 0xd8, 0xae, 0x00, 0x31, 0x8d, 0x44, 0xde, 0x2f, 0x44, 0x82, 0x30, - 0x8f, 0xf9, 0xb7, 0xf5, 0x11, 0x20, 0x53, 0x5e, 0xa9, 0x90, 0x37, 0xa1, 0xca, 0xb7, 0xa3, 0xae, - 0xa7, 0x56, 0x5a, 0x60, 0x2c, 0x67, 0xad, 0xbb, 0x80, 0x84, 0x06, 0x52, 0x57, 0xd2, 0xe9, 0xb5, - 0xf5, 0x21, 0x9c, 0x4b, 0xd1, 0xeb, 0x07, 0xb5, 0x14, 0x83, 0xec, 0xea, 0x92, 0xf8, 0xef, 0x25, - 0x80, 0xde, 0x34, 0x3e, 0x94, 0x55, 0x7f, 0x17, 0x6a, 0xd3, 0x88, 0x50, 0xa3, 0x57, 0xa1, 0xc7, - 0x6c, 0x2e, 0x74, 0xa2, 0xe8, 0xbb, 0x80, 0xaa, 0x9c, 0x4b, 0x8f, 0x79, 0xc5, 0x3e, 0x8d, 0x0f, - 0x55, 0x67, 0x8b, 0x7d, 0xa3, 0xab, 0xd0, 0x12, 0xbf, 0x51, 0xd8, 0x8e, 0xeb, 0x52, 0x12, 0x45, - 0xb2, 0xc5, 0xd5, 0x14, 0xd0, 0x9e, 0x00, 0x32, 0x34, 0xcf, 0x25, 0x7e, 0xec, 0xc5, 0xc7, 0x76, - 0x1c, 0x3c, 0x27, 0xbe, 0xcc, 0xa6, 0x9a, 0x0a, 0xfa, 0x88, 0x01, 0x19, 0x1a, 0x25, 0x23, 0x2f, - 0x8a, 0xa9, 0x42, 0xab, 0x0a, 0x34, 0x05, 0xe5, 0x68, 0xd6, 0xf7, 0x25, 0x68, 0x1f, 0x4c, 0xc7, - 0x63, 0xb1, 0xc9, 0xb3, 0xea, 0x12, 0xbd, 0x25, 0xf7, 0x91, 0x6d, 0x58, 0x25, 0x2a, 0x92, 0x9b, - 0xfb, 0xf1, 0xa5, 0xd9, 0x39, 0x58, 0x31, 0x04, 0x95, 0x55, 0xc5, 0x5d, 0x40, 0xa2, 0xe0, 0x78, - 0x39, 0xf9, 0xad, 0xf3, 0x70, 0x2e, 0x45, 0x2f, 0xd9, 0xde, 0x80, 0xa6, 0x7c, 0x9d, 0x92, 0x76, - 0xbe, 0x00, 0x35, 0x76, 0xfa, 0x87, 0x9e, 0xab, 0xba, 0x96, 0x8b, 0x61, 0xe0, 0xee, 0x78, 0x2e, - 0xb5, 0xfa, 0xd0, 0xc4, 0x82, 0xbd, 0xc4, 0xbd, 0x03, 0x2d, 0xf9, 0x96, 0x65, 0xa7, 0x5e, 0x7b, - 0x93, 0x96, 0x5c, 0x8a, 0x37, 0x6e, 0xfa, 0xe6, 0xd0, 0xfa, 0x06, 0xba, 0x8f, 0x43, 0x97, 0xa5, - 0x2f, 0x26, 0x57, 0xb5, 0xb5, 0x3b, 0xa0, 0xfe, 0xe4, 0x99, 0xc5, 0x3c, 0x4d, 0xd6, 0xa4, 0xe6, - 0xd0, 0xba, 0x08, 0x1b, 0x85, 0xcc, 0xe5, 0xbe, 0x43, 0x68, 0x27, 0x13, 0xa2, 0x4b, 0xa7, 0x9b, - 0xb0, 0x25, 0xa3, 0x09, 0xbb, 0xa6, 0xef, 0x44, 0x11, 0x5d, 0xe5, 0xc8, 0x48, 0x53, 0x2a, 0xb3, - 0xd2, 0x94, 0xf9, 0x54, 0x9a, 0x62, 0x7d, 0xa1, 0xb5, 0x27, 0x73, 0xc4, 0x0f, 0x78, 0xa2, 0x2a, - 0xd6, 0x56, 0x91, 0xe0, 0x42, 0xc1, 0xe6, 0x04, 0x06, 0x36, 0x90, 0xad, 0x65, 0x68, 0xa6, 0x62, - 0x82, 0xf5, 0x09, 0xb4, 0x32, 0x87, 0x7c, 0x2b, 0x73, 0x99, 0xe7, 0xd4, 0x96, 0xbe, 0xca, 0x6f, - 0xbc, 0x06, 0x35, 0xf5, 0xc3, 0x11, 0x5a, 0x84, 0xca, 0xa3, 0x9d, 0x83, 0xf6, 0x1c, 0xfb, 0x78, - 0xbc, 0x7b, 0xd0, 0x2e, 0xdd, 0xb8, 0x0d, 0xcb, 0x99, 0x77, 0x17, 0xb4, 0x02, 0xcd, 0x41, 0xaf, - 0xbf, 0xfb, 0xe9, 0xc3, 0xaf, 0x6c, 0xbc, 0xd7, 0xdb, 0xfd, 0xba, 0x3d, 0x87, 0x56, 0xa1, 0xad, - 0x40, 0xfd, 0x87, 0x8f, 0x04, 0xb4, 0x74, 0xe3, 0x39, 0xb4, 0xd2, 0xd9, 0x2a, 0x3a, 0x0f, 0x2b, - 0x3b, 0x0f, 0xfb, 0x8f, 0x7a, 0xfb, 0xfd, 0x3d, 0x6c, 0xef, 0xe0, 0xbd, 0xde, 0xa3, 0xbd, 0xdd, - 0xf6, 0x5c, 0x1a, 0x8c, 0x1f, 0xf7, 0xfb, 0xfb, 0xfd, 0xcf, 0xdb, 0x25, 0xc6, 0x35, 0x01, 0xef, - 0x7d, 0xb5, 0xcf, 0x90, 0xcb, 0x69, 0xe4, 0xc7, 0xfd, 0x7b, 0xfd, 0x87, 0x3f, 0xeb, 0xb7, 0x2b, - 0xdb, 0x7f, 0x6c, 0x40, 0x4b, 0x6d, 0x90, 0x50, 0xde, 0x29, 0xbd, 0x0b, 0x8b, 0xea, 0x5f, 0xb0, - 0x24, 0x7f, 0x4e, 0xff, 0xb8, 0xd6, 0xed, 0xe4, 0x27, 0xa4, 0xa3, 0xcc, 0xa1, 0x03, 0x6e, 0x38, - 0xe3, 0x8d, 0xeb, 0xa2, 0xa9, 0xca, 0xdc, 0x23, 0x5a, 0xf7, 0xd2, 0xac, 0x69, 0xcd, 0x71, 0xc0, - 0xac, 0x65, 0xfe, 0x6c, 0x80, 0x12, 0x9a, 0xc2, 0x9f, 0x18, 0xba, 0x97, 0x67, 0xce, 0x6b, 0xa6, - 0x5f, 0x43, 0x3b, 0xfb, 0x9b, 0x01, 0x4a, 0x5a, 0xf3, 0x33, 0x7e, 0x61, 0xe8, 0x5e, 0x39, 0x01, - 0xc3, 0x64, 0x9d, 0x7b, 0x90, 0xdf, 0x9c, 0xfd, 0xa4, 0x9a, 0x63, 0x3d, 0xeb, 0x9d, 0x56, 0xa8, - 0x22, 0xfd, 0x36, 0x85, 0xcc, 0x67, 0xf0, 0x82, 0x37, 0x4a, 0x43, 0x15, 0xc5, 0x8f, 0x5a, 0xd6, - 0x1c, 0xfa, 0x12, 0x96, 0x33, 0xbd, 0x2d, 0x94, 0x50, 0x15, 0x77, 0xea, 0xba, 0x9b, 0xb3, 0x11, - 0xd2, 0x76, 0x33, 0x3b, 0x57, 0x29, 0xbb, 0x15, 0xb4, 0xc3, 0x52, 0x76, 0x2b, 0x6c, 0x79, 0x71, - 0xf7, 0x4a, 0xf5, 0xa7, 0x0c, 0xf7, 0x2a, 0x6a, 0x86, 0x75, 0x2f, 0xcd, 0x9a, 0x36, 0xb7, 0x9f, - 0xe9, 0x4d, 0x19, 0xdb, 0x2f, 0x6e, 0x79, 0x75, 0x37, 0x67, 0x23, 0x64, 0x6d, 0x95, 0xd4, 0xdc, - 0x19, 0x5b, 0xe5, 0x5a, 0x3c, 0x19, 0x5b, 0xe5, 0x8b, 0x75, 0x69, 0xab, 0x4c, 0xf1, 0x7c, 0x79, - 0x66, 0xdd, 0x91, 0xb7, 0x55, 0x71, 0x29, 0x63, 0xcd, 0xa1, 0x1e, 0xd4, 0x54, 0xe1, 0x80, 0x92, - 0xd3, 0x9d, 0xa9, 0x56, 0xba, 0x17, 0x0a, 0x66, 0x34, 0x8b, 0xff, 0x81, 0x79, 0x06, 0x45, 0xab, - 0x29, 0x24, 0x45, 0x7a, 0x3e, 0x03, 0xd5, 0x64, 0x1f, 0x42, 0x55, 0x64, 0xde, 0x28, 0x89, 0xb9, - 0xa9, 0xa4, 0xbe, 0xbb, 0x9e, 0x83, 0x6b, 0xe2, 0x2f, 0xc4, 0xff, 0xa1, 0x32, 0x85, 0x46, 0x1b, - 0xa9, 0x3f, 0xd8, 0xd2, 0x89, 0x7a, 0xf7, 0xb5, 0xe2, 0x49, 0xcd, 0xeb, 0x09, 0x9c, 0x2b, 0xb8, - 0x02, 0x51, 0xd2, 0xe7, 0x99, 0x7d, 0xfb, 0x76, 0xdf, 0x38, 0x19, 0xc9, 0xdc, 0xac, 0xb4, 0xda, - 0x9a, 0xe9, 0xea, 0x86, 0xb1, 0xd6, 0x73, 0x70, 0x45, 0xbc, 0xfd, 0x97, 0x32, 0x2c, 0x89, 0x44, - 0x45, 0x86, 0xea, 0xcf, 0x01, 0x92, 0x74, 0x19, 0x75, 0x53, 0xde, 0x93, 0xca, 0xf9, 0xbb, 0x1b, - 0x85, 0x73, 0xa6, 0x1a, 0x8d, 0xcc, 0xd7, 0x50, 0x63, 0x3e, 0x9f, 0x36, 0xd4, 0x58, 0x90, 0x2c, - 0x5b, 0x73, 0x68, 0x17, 0xea, 0x3a, 0x1d, 0x43, 0x46, 0x16, 0x97, 0xc9, 0x25, 0xbb, 0xdd, 0xa2, - 0x29, 0x53, 0x22, 0x23, 0xff, 0x32, 0x24, 0xca, 0x67, 0x75, 0x86, 0x44, 0x45, 0x29, 0xdb, 0xdc, - 0xbf, 0x02, 0x00, 0x00, 0xff, 0xff, 0x1d, 0x33, 0x75, 0xd6, 0x8d, 0x2d, 0x00, 0x00, + // 3342 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xcc, 0x3a, 0xcd, 0x72, 0x1b, 0xc7, + 0xd1, 0x04, 0x40, 0x82, 0x40, 0x83, 0x00, 0xc1, 0x21, 0x45, 0x42, 0xa0, 0x25, 0x51, 0x6b, 0xc9, + 0x96, 0x64, 0x5b, 0x9f, 0xc5, 0x2f, 0xb1, 0x62, 0xd9, 0x92, 0x0d, 0x93, 0xb4, 0x43, 0x4b, 0x82, + 0xe8, 0x85, 0xe4, 0xd8, 0xe5, 0xc3, 0x66, 0x85, 0x1d, 0x82, 0x2b, 0x01, 0xbb, 0xeb, 0xd9, 0x01, + 0x2d, 0xa6, 0x2a, 0xf7, 0x1c, 0x92, 0xaa, 0x5c, 0x73, 0x4a, 0x0e, 0xa9, 0x72, 0x25, 0xb9, 0xa5, + 0x2a, 0x55, 0x79, 0x87, 0x54, 0x1e, 0x20, 0x8f, 0x90, 0x57, 0xc8, 0x29, 0x35, 0x7f, 0xbb, 0xb3, + 0x7f, 0x14, 0x29, 0xbb, 0x62, 0xdd, 0x76, 0x7a, 0x7a, 0x7a, 0x7a, 0xba, 0x7b, 0xfa, 0x6f, 0x07, + 0xea, 0x76, 0xe0, 0x5e, 0x0f, 0x88, 0x4f, 0x7d, 0x34, 0x4f, 0xa6, 0x1e, 0x75, 0x27, 0xd8, 0xb8, + 0x06, 0xad, 0xcf, 0x31, 0x09, 0x5d, 0xdf, 0x33, 0xf1, 0xd7, 0x53, 0x1c, 0x52, 0xd4, 0x81, 0xf9, + 0x43, 0x01, 0xe9, 0x94, 0x36, 0x4a, 0x57, 0xea, 0xa6, 0x1a, 0x1a, 0xdf, 0x96, 0x60, 0x31, 0x42, + 0x0e, 0x03, 0xdf, 0x0b, 0x71, 0x31, 0x36, 0xba, 0x08, 0x0b, 0x72, 0x13, 0xcb, 0xb3, 0x27, 0xb8, + 0x53, 0xe6, 0xd3, 0x0d, 0x09, 0xeb, 0xdb, 0x13, 0x8c, 0x5e, 0x87, 0x45, 0x85, 0xa2, 0x88, 0x54, + 0x38, 0x56, 0x4b, 0x82, 0xe5, 0x6e, 0xe8, 0x3a, 0x2c, 0x2b, 0x44, 0x3b, 0x70, 0x23, 0xe4, 0x59, + 0x8e, 0xbc, 0x24, 0xa7, 0x7a, 0x81, 0x2b, 0xf1, 0x8d, 0xaf, 0xa0, 0xbe, 0xdd, 0x1f, 0x6c, 0xf9, + 0xde, 0xbe, 0x3b, 0x62, 0x2c, 0x86, 0x98, 0xb0, 0x35, 0x9d, 0xd2, 0x46, 0x85, 0xb1, 0x28, 0x87, + 0xa8, 0x0b, 0xb5, 0x10, 0xdb, 0x64, 0x78, 0x80, 0xc3, 0x4e, 0x99, 0x4f, 0x45, 0x63, 0xb6, 0xca, + 0x0f, 0xa8, 0xeb, 0x7b, 0x61, 0xa7, 0x22, 0x56, 0xc9, 0xa1, 0xf1, 0xbb, 0x12, 0x34, 0xf6, 0x7c, + 0x42, 0xef, 0xdb, 0x41, 0xe0, 0x7a, 0x23, 0xf4, 0x16, 0xd4, 0xb8, 0x50, 0x87, 0xfe, 0x98, 0xcb, + 0xa0, 0xb5, 0xb9, 0x74, 0x5d, 0xb2, 0x74, 0x7d, 0x4f, 0x4e, 0x98, 0x11, 0x0a, 0xba, 0x0c, 0xad, + 0xa1, 0xef, 0x51, 0xdb, 0xf5, 0x30, 0xb1, 0x02, 0x9f, 0x50, 0x2e, 0x99, 0x39, 0xb3, 0x19, 0x41, + 0x19, 0x71, 0xb4, 0x0e, 0xf5, 0x03, 0x3f, 0xa4, 0x02, 0xa3, 0xc2, 0x31, 0x6a, 0x0c, 0xc0, 0x27, + 0xd7, 0x60, 0x9e, 0x4f, 0xba, 0x81, 0x94, 0x41, 0x95, 0x0d, 0x77, 0x03, 0xe3, 0xb7, 0x25, 0x98, + 0xbb, 0xef, 0x4f, 0x3d, 0x9a, 0xda, 0xc6, 0xa6, 0x07, 0x52, 0x3f, 0xda, 0x36, 0x36, 0x3d, 0x88, + 0xb7, 0x61, 0x18, 0x42, 0x45, 0x62, 0x1b, 0x36, 0xd9, 0x85, 0x1a, 0xc1, 0xb6, 0xe3, 0x7b, 0xe3, + 0x23, 0xce, 0x42, 0xcd, 0x8c, 0xc6, 0x4c, 0x77, 0x21, 0x1e, 0xbb, 0xde, 0xf4, 0x99, 0x45, 0xf0, + 0xd8, 0x7e, 0x8c, 0xc7, 0x9c, 0x95, 0x9a, 0xd9, 0x92, 0x60, 0x53, 0x40, 0x8d, 0x27, 0xb0, 0xc8, + 0x94, 0x1d, 0x06, 0xf6, 0x10, 0x3f, 0xe0, 0x22, 0x64, 0xa6, 0xc1, 0x37, 0xf5, 0x30, 0xfd, 0xc6, + 0x27, 0x4f, 0x39, 0x67, 0x35, 0xb3, 0xc1, 0x60, 0x7d, 0x01, 0x42, 0x67, 0xa1, 0x26, 0xf8, 0x72, + 0x1d, 0xce, 0x56, 0xcd, 0xe4, 0x27, 0xde, 0x73, 0x9d, 0x68, 0xca, 0x0d, 0x86, 0x92, 0xab, 0x79, + 0x71, 0xfa, 0xa1, 0xf1, 0xfb, 0x32, 0xac, 0xdf, 0x63, 0x9b, 0x0f, 0x6c, 0xcf, 0x79, 0xec, 0x3f, + 0x1b, 0xe0, 0xe1, 0x94, 0xb8, 0xf4, 0x68, 0xcb, 0xf7, 0x28, 0x7e, 0x46, 0xd1, 0x0e, 0x2c, 0x79, + 0x8a, 0x17, 0x4b, 0xa9, 0x97, 0xed, 0xde, 0xd8, 0xec, 0x44, 0x3a, 0x4b, 0x71, 0x6b, 0xb6, 0xbd, + 0x24, 0x20, 0x44, 0x1f, 0xc4, 0x67, 0x57, 0x44, 0xca, 0x9c, 0xc8, 0x6a, 0x44, 0x64, 0xb0, 0xc3, + 0xf9, 0x90, 0x24, 0x94, 0x4c, 0x14, 0x81, 0xf3, 0xc0, 0xee, 0x81, 0x65, 0x87, 0xd6, 0x34, 0xc4, + 0x84, 0x9f, 0xa2, 0x62, 0xd6, 0xc9, 0xd4, 0xeb, 0x85, 0x8f, 0x42, 0x4c, 0xf8, 0xc5, 0x90, 0x82, + 0xb6, 0x88, 0xef, 0xd3, 0xfd, 0x50, 0x09, 0x57, 0x81, 0x4d, 0x0e, 0x45, 0xff, 0x07, 0xcb, 0xe1, + 0x34, 0x08, 0xc6, 0x78, 0x82, 0x3d, 0x6a, 0x8f, 0xad, 0x11, 0xf1, 0xa7, 0x41, 0xd8, 0x99, 0xdb, + 0xa8, 0x5c, 0xa9, 0x98, 0x48, 0x9f, 0xfa, 0x84, 0xcf, 0x18, 0xbf, 0x29, 0xc1, 0x19, 0xce, 0xd9, + 0x9e, 0xef, 0x48, 0x21, 0xc9, 0x6b, 0xf2, 0x2a, 0x34, 0x87, 0x7c, 0xb9, 0x15, 0xd8, 0x04, 0x7b, + 0x54, 0xda, 0xcb, 0x82, 0x00, 0xee, 0x71, 0x18, 0x7a, 0x00, 0xed, 0x50, 0xca, 0xd4, 0x1a, 0x0a, + 0xa1, 0xca, 0xa3, 0x5f, 0x8a, 0x8e, 0x7e, 0x8c, 0x02, 0xcc, 0xc5, 0x30, 0x09, 0x30, 0x08, 0xa0, + 0x98, 0x93, 0xfb, 0x98, 0xda, 0x8e, 0x4d, 0x6d, 0x84, 0x60, 0x96, 0xfb, 0x0c, 0xc1, 0x02, 0xff, + 0x46, 0x6d, 0xa8, 0x4c, 0xa5, 0x31, 0xd4, 0x4d, 0xf6, 0x89, 0x5e, 0x81, 0x7a, 0xa4, 0x1a, 0xe9, + 0x38, 0x62, 0x00, 0xbb, 0xc0, 0x36, 0xa5, 0x78, 0x12, 0x50, 0x2e, 0xbb, 0xa6, 0xa9, 0x86, 0xc6, + 0xdf, 0x67, 0xa1, 0x9d, 0x39, 0xfe, 0x4d, 0xa8, 0x4d, 0xe4, 0xf6, 0xd2, 0x22, 0xd6, 0xe3, 0x5b, + 0x9c, 0xe1, 0xd0, 0x8c, 0x90, 0xd9, 0x25, 0x61, 0xe6, 0xa7, 0xf9, 0xb8, 0x68, 0xcc, 0x64, 0x3a, + 0xf6, 0x47, 0x96, 0xe3, 0x12, 0x3c, 0xa4, 0x3e, 0x39, 0x92, 0x5c, 0x2e, 0x8c, 0xfd, 0xd1, 0xb6, + 0x82, 0xa1, 0x1b, 0x00, 0x8e, 0x17, 0x32, 0x71, 0xee, 0xbb, 0x23, 0xce, 0x6b, 0x63, 0x13, 0x45, + 0x7b, 0x47, 0x7e, 0xcc, 0xac, 0x3b, 0x5e, 0x28, 0x99, 0x7d, 0x17, 0x9a, 0xcc, 0x2f, 0x58, 0x13, + 0xe1, 0x82, 0x84, 0xc2, 0x1b, 0x9b, 0x2b, 0x1a, 0xc7, 0x91, 0x7f, 0x32, 0x17, 0x82, 0x78, 0x10, + 0xa2, 0xdb, 0x50, 0xe5, 0xf7, 0x32, 0xec, 0x54, 0xf9, 0x9a, 0xcb, 0x39, 0xa7, 0x14, 0xbb, 0x5c, + 0xbf, 0xc7, 0xf1, 0x76, 0x3c, 0x4a, 0x8e, 0x4c, 0xb9, 0x08, 0xdd, 0x83, 0x86, 0xed, 0x79, 0x3e, + 0xb5, 0x85, 0xd9, 0xcf, 0x73, 0x1a, 0xd7, 0x8a, 0x69, 0xf4, 0x62, 0x64, 0x41, 0x48, 0x5f, 0x8e, + 0x7e, 0x04, 0x73, 0xfc, 0x5e, 0x74, 0x6a, 0xfc, 0xd4, 0xe7, 0x93, 0x36, 0x94, 0x26, 0x66, 0x0a, + 0xe4, 0xee, 0xbb, 0xd0, 0xd0, 0x58, 0x63, 0x86, 0xf1, 0x14, 0x1f, 0x49, 0x5b, 0x61, 0x9f, 0x68, + 0x05, 0xe6, 0x0e, 0xed, 0xf1, 0x54, 0xe9, 0x43, 0x0c, 0x6e, 0x95, 0x7f, 0x52, 0xea, 0xde, 0x81, + 0x76, 0x9a, 0xa3, 0xd3, 0xac, 0x37, 0x76, 0x61, 0xc5, 0x9c, 0x7a, 0x31, 0x63, 0x2a, 0x68, 0xde, + 0x80, 0xaa, 0xd4, 0x9f, 0xb0, 0x9d, 0xb3, 0x85, 0x12, 0x31, 0x25, 0xa2, 0x71, 0x1b, 0xce, 0xa4, + 0x48, 0xc9, 0x90, 0x7a, 0x09, 0x5a, 0x81, 0xef, 0x58, 0xa1, 0x00, 0x5b, 0xae, 0xa3, 0x6e, 0x62, + 0x10, 0xe1, 0xee, 0x3a, 0x6c, 0xf9, 0x80, 0xfa, 0x41, 0x96, 0x95, 0x93, 0x2d, 0xef, 0xc0, 0x6a, + 0x7a, 0xb9, 0xd8, 0xde, 0xf8, 0x00, 0xd6, 0x4c, 0x3c, 0xf1, 0x0f, 0xf1, 0x8b, 0x92, 0xee, 0x42, + 0x27, 0x4b, 0x20, 0x26, 0x1e, 0x43, 0x07, 0xd4, 0xa6, 0xd3, 0xf0, 0x74, 0xc4, 0xaf, 0xea, 0x04, + 0x64, 0xb0, 0x10, 0x74, 0x50, 0x0b, 0xca, 0x6e, 0x20, 0x17, 0x95, 0xdd, 0xc0, 0xf8, 0x12, 0xea, + 0x7d, 0xdd, 0x1b, 0xe8, 0xd1, 0xa6, 0x6e, 0xaa, 0x21, 0xda, 0x8c, 0x03, 0x7d, 0xf9, 0x39, 0x91, + 0x20, 0x4a, 0x01, 0xee, 0x66, 0x9c, 0xa8, 0xe4, 0x61, 0x13, 0x20, 0xf2, 0x40, 0x2a, 0xb2, 0xa0, + 0x2c, 0x3d, 0x53, 0xc3, 0x32, 0xfe, 0x98, 0x70, 0x47, 0xda, 0x61, 0x9c, 0xe8, 0x30, 0x4e, 0xc2, + 0x3d, 0x95, 0x4f, 0xe3, 0x9e, 0xae, 0xc3, 0x5c, 0x48, 0x6d, 0x2a, 0x1c, 0x64, 0x4b, 0x3b, 0x5c, + 0x72, 0x4b, 0x6c, 0x0a, 0x34, 0x74, 0x0e, 0x60, 0x48, 0xb0, 0x4d, 0xb1, 0x63, 0xd9, 0xc2, 0x73, + 0x56, 0xcc, 0xba, 0x84, 0xf4, 0x28, 0xba, 0x15, 0xcb, 0x71, 0x8e, 0xb3, 0xb1, 0x91, 0x43, 0x30, + 0xa1, 0x97, 0x58, 0xd2, 0xd1, 0x6d, 0xaf, 0x1e, 0x7f, 0xdb, 0xe5, 0x3a, 0x81, 0xac, 0x39, 0xac, + 0xf9, 0x42, 0x87, 0x25, 0x56, 0x9c, 0xc4, 0x61, 0xd5, 0x0a, 0x1d, 0x96, 0xa4, 0x71, 0xac, 0xc3, + 0xfa, 0x21, 0x5d, 0xcf, 0x7d, 0xe8, 0x64, 0xaf, 0x8e, 0x74, 0x19, 0x37, 0xa0, 0x1a, 0x72, 0xc8, + 0x31, 0xee, 0x47, 0x2e, 0x91, 0x88, 0xc6, 0xbf, 0x4b, 0xba, 0xd5, 0x7d, 0xec, 0x8e, 0x29, 0x26, + 0x19, 0xab, 0x8b, 0x8c, 0xa7, 0x7c, 0x32, 0xe3, 0x19, 0x40, 0x8b, 0x8b, 0xdd, 0x0a, 0xf1, 0x98, + 0x47, 0x37, 0x9e, 0x3b, 0x37, 0x36, 0xdf, 0xcc, 0x59, 0x28, 0xb6, 0x14, 0x3a, 0x1b, 0x48, 0x74, + 0x21, 0xf1, 0xe6, 0x58, 0x87, 0x75, 0x3f, 0x04, 0x94, 0x45, 0x3a, 0x95, 0xe8, 0x3e, 0x65, 0xd7, + 0x95, 0xa5, 0xce, 0x39, 0x6e, 0x7b, 0x9f, 0xb3, 0x71, 0x8c, 0xdc, 0x04, 0x9f, 0xa6, 0x44, 0x34, + 0xfe, 0x50, 0x01, 0x88, 0x27, 0x5f, 0xda, 0x7b, 0x7a, 0x33, 0xba, 0x35, 0x22, 0x35, 0xb8, 0x90, + 0x43, 0x2f, 0xf7, 0xbe, 0x7c, 0x9c, 0xbc, 0x2f, 0x22, 0x49, 0xb8, 0x94, 0xb7, 0xfa, 0xa5, 0xbd, + 0x29, 0x5b, 0xb0, 0x9a, 0x56, 0xb7, 0xbc, 0x27, 0x57, 0x61, 0xce, 0xa5, 0x78, 0x22, 0x0a, 0xc1, + 0xc6, 0xe6, 0x72, 0xce, 0xb1, 0x4c, 0x81, 0x61, 0x5c, 0x84, 0xfa, 0xee, 0xc4, 0x1e, 0xe1, 0x41, + 0x80, 0x87, 0x6c, 0x2f, 0x97, 0x0d, 0xe4, 0xfe, 0x62, 0x60, 0x6c, 0x42, 0xed, 0x2e, 0x3e, 0xfa, + 0x9c, 0xed, 0x7b, 0x52, 0xfe, 0x8c, 0x7f, 0x94, 0x60, 0x8d, 0xbb, 0xbb, 0x2d, 0x55, 0x86, 0x99, + 0x38, 0xf4, 0xa7, 0x64, 0x88, 0x43, 0xae, 0xd2, 0x60, 0x6a, 0x05, 0x98, 0xb8, 0xbe, 0xb0, 0x29, + 0xa6, 0xd2, 0x60, 0xba, 0xc7, 0x01, 0xac, 0x54, 0x63, 0xd3, 0x5f, 0x4f, 0x7d, 0x69, 0x5b, 0x15, + 0xb3, 0x36, 0x0c, 0xa6, 0x9f, 0xb1, 0xb1, 0x5a, 0x1b, 0x1e, 0xd8, 0x04, 0x87, 0xaa, 0xa0, 0x18, + 0x06, 0xd3, 0x01, 0x07, 0xa0, 0x1b, 0x70, 0x66, 0x82, 0x27, 0x3e, 0x39, 0xb2, 0xc6, 0xee, 0xc4, + 0xa5, 0x96, 0xeb, 0x59, 0x8f, 0x8f, 0x28, 0x0e, 0xa5, 0xe1, 0x20, 0x31, 0x79, 0x8f, 0xcd, 0xed, + 0x7a, 0x1f, 0xb1, 0x19, 0x64, 0x40, 0xd3, 0xf7, 0x27, 0x56, 0x38, 0xf4, 0x09, 0xb6, 0x6c, 0xe7, + 0x09, 0xf7, 0xf7, 0x15, 0xb3, 0xe1, 0xfb, 0x93, 0x01, 0x83, 0xf5, 0x9c, 0x27, 0x86, 0x0d, 0xcd, + 0x44, 0xa1, 0xc3, 0x12, 0x77, 0x5e, 0xd1, 0xc8, 0xc4, 0x9d, 0x7d, 0x33, 0x18, 0xf1, 0xc7, 0x4a, + 0x0e, 0xfc, 0x9b, 0xc1, 0xe8, 0x51, 0xa0, 0xb2, 0x76, 0xfe, 0xcd, 0x04, 0x36, 0xc6, 0x87, 0xb2, + 0x8e, 0xac, 0x9b, 0x62, 0x60, 0x38, 0x00, 0x5b, 0x76, 0x60, 0x3f, 0x76, 0xc7, 0x2e, 0x3d, 0x42, + 0x57, 0xa1, 0x6d, 0x3b, 0x8e, 0x35, 0x54, 0x10, 0x17, 0xab, 0xa2, 0x7e, 0xd1, 0x76, 0x9c, 0x2d, + 0x0d, 0x8c, 0xde, 0x80, 0x25, 0x87, 0xf8, 0x41, 0x12, 0x57, 0x54, 0xf9, 0x6d, 0x36, 0xa1, 0x23, + 0x1b, 0xff, 0x29, 0xc3, 0xb9, 0xa4, 0x5a, 0xd2, 0xa5, 0xe3, 0x4d, 0x58, 0x48, 0xed, 0x5a, 0x4a, + 0x58, 0x50, 0xcc, 0xa4, 0x99, 0x40, 0x44, 0xe7, 0x01, 0x02, 0xe2, 0x1e, 0xba, 0x63, 0x3c, 0xc2, + 0xaa, 0x96, 0xd5, 0x20, 0xf9, 0x35, 0x69, 0xe5, 0xfb, 0xa8, 0x49, 0x67, 0xbf, 0x4b, 0x4d, 0x3a, + 0x77, 0x82, 0x9a, 0xb4, 0x7a, 0x9a, 0x9a, 0x74, 0xbe, 0xb0, 0x26, 0xfd, 0x53, 0x09, 0x56, 0x92, + 0xc2, 0x97, 0x65, 0xce, 0x1d, 0xa8, 0x13, 0x75, 0x3b, 0xa4, 0xc0, 0x37, 0x92, 0x49, 0x43, 0xf6, + 0x16, 0x99, 0xf1, 0x12, 0xf4, 0x59, 0x61, 0xb5, 0xfa, 0x5a, 0x01, 0x99, 0xe7, 0xd6, 0xab, 0x3d, + 0x58, 0x8a, 0x90, 0x8f, 0x2d, 0x57, 0xb5, 0xf2, 0xb3, 0x9c, 0x2c, 0x3f, 0x3d, 0xa8, 0x6e, 0xe3, + 0x43, 0x77, 0x88, 0xbf, 0x97, 0x1e, 0xcd, 0x06, 0x34, 0x02, 0x4c, 0x26, 0x6e, 0x18, 0x46, 0x86, + 0x53, 0x37, 0x75, 0x90, 0xf1, 0xaf, 0x39, 0x58, 0x4c, 0x4b, 0xf6, 0x9d, 0x4c, 0xb5, 0xdb, 0x8d, + 0x2d, 0x39, 0x7d, 0x3e, 0x2d, 0x4a, 0x5d, 0x51, 0x8e, 0xb0, 0x9c, 0x4a, 0x6d, 0x23, 0x5f, 0x29, + 0x9d, 0x23, 0x3b, 0xff, 0xd0, 0x9f, 0x4c, 0x6c, 0xcf, 0x51, 0xfd, 0x33, 0x39, 0x64, 0xd2, 0xb2, + 0xc9, 0x88, 0x99, 0x27, 0x03, 0xf3, 0x6f, 0x74, 0x01, 0x1a, 0x2c, 0x45, 0x74, 0x3d, 0x5e, 0x2c, + 0x73, 0xe3, 0xab, 0x9b, 0x20, 0x41, 0xdb, 0x2e, 0x41, 0x97, 0x61, 0x16, 0x7b, 0x87, 0x2a, 0x1e, + 0xc5, 0x0d, 0x36, 0xe5, 0x80, 0x4d, 0x3e, 0x8d, 0x5e, 0x83, 0xea, 0xc4, 0x9f, 0x7a, 0x54, 0x25, + 0x8b, 0xad, 0x08, 0x91, 0x77, 0xc5, 0x4c, 0x39, 0x8b, 0xae, 0xc2, 0xbc, 0xc3, 0x75, 0xa0, 0x32, + 0xc2, 0xc5, 0xb8, 0xe0, 0xe6, 0x70, 0x53, 0xcd, 0xa3, 0xf7, 0xa3, 0x48, 0x5a, 0x4f, 0xc5, 0xc2, + 0x94, 0x50, 0x73, 0xc3, 0xe9, 0xdd, 0x64, 0x38, 0x05, 0x4e, 0xe2, 0x6a, 0x21, 0x89, 0xe3, 0xcb, + 0xe5, 0xb3, 0x50, 0x1b, 0xfb, 0x23, 0x61, 0x07, 0x0d, 0x51, 0xc5, 0x8c, 0xfd, 0x11, 0x37, 0x83, + 0x15, 0x96, 0x3e, 0x38, 0xae, 0xd7, 0x59, 0xe0, 0x77, 0x52, 0x0c, 0x58, 0x54, 0xe0, 0x1f, 0x96, + 0xef, 0x0d, 0x71, 0xa7, 0xc9, 0xa7, 0xea, 0x1c, 0xf2, 0xc0, 0x1b, 0xf2, 0xa0, 0x45, 0xe9, 0x51, + 0xa7, 0xc5, 0xe1, 0xec, 0x13, 0xfd, 0xbf, 0x4a, 0xd1, 0x17, 0xb9, 0x7e, 0xcf, 0x15, 0x5c, 0x93, + 0x97, 0xa6, 0x1e, 0xff, 0x6b, 0x09, 0x56, 0xb7, 0x78, 0xd2, 0xa3, 0x79, 0x82, 0x53, 0xd4, 0x93, + 0xe8, 0xed, 0xa8, 0x70, 0x4f, 0x17, 0x7f, 0xe9, 0xc3, 0x4a, 0x3c, 0xf4, 0x21, 0xb4, 0x14, 0x4d, + 0xb9, 0xb2, 0xf2, 0xbc, 0x92, 0xbf, 0x19, 0xea, 0x43, 0xe3, 0x7d, 0x58, 0xcb, 0xf0, 0x2c, 0x13, + 0x94, 0x8b, 0xb0, 0x10, 0x7b, 0x84, 0x88, 0xe5, 0x46, 0x04, 0xdb, 0x75, 0x8c, 0x5b, 0xac, 0xf0, + 0xb7, 0x09, 0xcd, 0x1c, 0xf8, 0x04, 0x6b, 0x79, 0xd5, 0x9f, 0x5c, 0x2b, 0x0b, 0xf3, 0x01, 0xac, + 0x0c, 0xa8, 0x1f, 0xbc, 0x00, 0x51, 0x76, 0xd3, 0xd9, 0xb1, 0xfd, 0x29, 0x95, 0x59, 0x89, 0x1a, + 0x1a, 0x6b, 0xa2, 0x47, 0x91, 0xdd, 0xed, 0x3d, 0x58, 0x15, 0x2d, 0x82, 0x17, 0x39, 0xc4, 0x59, + 0xd5, 0xa0, 0xc8, 0xd2, 0xfd, 0x75, 0x59, 0x73, 0x75, 0x05, 0x35, 0xcd, 0x5b, 0xc9, 0x9a, 0x66, + 0x2d, 0xab, 0xf0, 0x44, 0x9e, 0x9d, 0x35, 0xa3, 0x4a, 0x8e, 0x19, 0x99, 0x99, 0xc2, 0x67, 0x96, + 0xdf, 0xf4, 0x37, 0xb2, 0xd4, 0xff, 0x87, 0x75, 0xcf, 0xae, 0xa8, 0x7b, 0xa2, 0xad, 0xa3, 0x5e, + 0xcb, 0xdb, 0xa9, 0xba, 0xa7, 0x53, 0xc4, 0x66, 0x54, 0xf6, 0xfc, 0x6a, 0x16, 0xea, 0xd1, 0x5c, + 0x46, 0xa6, 0x59, 0x21, 0x95, 0x73, 0x84, 0xa4, 0x07, 0x9d, 0xca, 0x8b, 0x04, 0x9d, 0xd9, 0xe7, + 0x05, 0x9d, 0x75, 0xa8, 0xf3, 0x0f, 0x8b, 0xe0, 0x7d, 0x19, 0x44, 0x6a, 0x1c, 0x60, 0xe2, 0xfd, + 0x58, 0xf1, 0xd5, 0x13, 0x29, 0x3e, 0x59, 0x60, 0xcd, 0xa7, 0x0b, 0xac, 0x77, 0xa2, 0xb0, 0x20, + 0x02, 0xc8, 0xf9, 0x2c, 0xb9, 0xdc, 0x80, 0xb0, 0x93, 0x0c, 0x08, 0x22, 0xa6, 0xbc, 0x9a, 0xb3, + 0xf8, 0xa5, 0x2d, 0xaf, 0xee, 0x89, 0xf2, 0x4a, 0xb7, 0x2a, 0xe9, 0xbd, 0x36, 0x01, 0xa2, 0x8b, + 0xaa, 0x6a, 0x2c, 0x94, 0x3d, 0x9a, 0xa9, 0x61, 0x31, 0x57, 0x90, 0x90, 0x7f, 0xdc, 0x10, 0x3c, + 0x81, 0x2b, 0xf8, 0x8b, 0x9e, 0xda, 0x14, 0x74, 0xce, 0xde, 0xc9, 0x54, 0xe4, 0x27, 0xb3, 0xba, + 0xb7, 0x92, 0x05, 0xf9, 0xe9, 0xcc, 0x25, 0x53, 0x8f, 0xf3, 0x48, 0x6c, 0x13, 0x39, 0x2d, 0x93, + 0x6b, 0x09, 0xe9, 0x51, 0x96, 0xff, 0xec, 0xbb, 0x9e, 0x1b, 0x1e, 0x88, 0xf9, 0x2a, 0x9f, 0x07, + 0x05, 0xea, 0xf1, 0xdf, 0x81, 0xf8, 0x99, 0x4b, 0xad, 0xa1, 0xef, 0x60, 0x6e, 0x8c, 0x73, 0x66, + 0x8d, 0x01, 0xb6, 0x7c, 0x07, 0xc7, 0x17, 0xa4, 0x76, 0xaa, 0x0b, 0x52, 0x4f, 0x5d, 0x90, 0x55, + 0xa8, 0x12, 0x6c, 0x87, 0xbe, 0xd7, 0x01, 0xf1, 0x53, 0x51, 0x8c, 0x98, 0x83, 0x9f, 0xe0, 0x30, + 0x64, 0x1b, 0xc8, 0xac, 0x43, 0x0e, 0xb5, 0xdc, 0x68, 0xa1, 0x28, 0x37, 0x3a, 0xa6, 0x35, 0x97, + 0xca, 0x8d, 0x9a, 0x45, 0xb9, 0xd1, 0x49, 0x3a, 0x73, 0x5a, 0xe6, 0xd7, 0x3a, 0x2e, 0xf3, 0xfb, + 0x21, 0x2f, 0xce, 0x5d, 0x58, 0xcb, 0x98, 0xba, 0xbc, 0x39, 0x6f, 0xa7, 0x1a, 0x78, 0x9d, 0x22, + 0x29, 0x44, 0xfd, 0xbb, 0x9f, 0xc3, 0xe2, 0xce, 0x33, 0x3c, 0x1c, 0x1c, 0x79, 0xc3, 0x53, 0xc4, + 0xea, 0x36, 0x54, 0x86, 0x13, 0x47, 0x96, 0xc1, 0xec, 0x53, 0x8f, 0xde, 0x95, 0x64, 0xf4, 0xb6, + 0xa0, 0x1d, 0xef, 0x20, 0xf9, 0x5c, 0x65, 0x7c, 0x3a, 0x0c, 0x99, 0x11, 0x5f, 0x30, 0xe5, 0x48, + 0xc2, 0x31, 0x21, 0xfc, 0xd4, 0x02, 0x8e, 0x09, 0x49, 0x9a, 0x6d, 0x25, 0x69, 0xb6, 0xc6, 0x13, + 0x68, 0xb0, 0x0d, 0xbe, 0x13, 0xfb, 0x32, 0x85, 0xad, 0xc4, 0x29, 0x6c, 0x94, 0x09, 0xcf, 0x6a, + 0x99, 0xb0, 0xb1, 0x01, 0x0b, 0x62, 0x2f, 0x79, 0x90, 0x36, 0x54, 0xa6, 0x64, 0xac, 0xf4, 0x36, + 0x25, 0x63, 0xe3, 0xa7, 0xd0, 0xec, 0x51, 0x6a, 0x0f, 0x0f, 0x4e, 0xc1, 0x4f, 0xb4, 0x57, 0x59, + 0xdf, 0xcb, 0x80, 0x96, 0xa2, 0x54, 0xb8, 0x5b, 0x1f, 0xd0, 0x9e, 0x4f, 0xe8, 0xc7, 0x3e, 0xf9, + 0xc6, 0x26, 0xce, 0xe9, 0x72, 0x56, 0x04, 0xb3, 0xf2, 0xdd, 0x40, 0xe5, 0xca, 0x9c, 0xc9, 0xbf, + 0x8d, 0xd7, 0x61, 0x39, 0x41, 0xaf, 0x70, 0xe3, 0x9b, 0xd0, 0xe0, 0x5e, 0x41, 0x66, 0x47, 0x57, + 0xf4, 0xce, 0xd6, 0x71, 0xae, 0x83, 0x55, 0xbe, 0xcc, 0xed, 0x73, 0x78, 0xe4, 0xa3, 0xdf, 0x4c, + 0x25, 0x12, 0x2b, 0xc9, 0xf5, 0xa9, 0x24, 0xe2, 0x97, 0x30, 0xc7, 0xc1, 0x19, 0x1f, 0xbd, 0xce, + 0x0a, 0xfd, 0xc0, 0xb7, 0xa8, 0x3d, 0x8a, 0x5e, 0x62, 0x30, 0xc0, 0x43, 0x7b, 0x14, 0xf2, 0x87, + 0x24, 0x6c, 0xd2, 0x71, 0x47, 0x38, 0xa4, 0xea, 0x39, 0x46, 0x83, 0xc1, 0xb6, 0x05, 0x88, 0x49, + 0x24, 0x74, 0x7f, 0x21, 0x12, 0x84, 0x59, 0x93, 0x7f, 0xab, 0xff, 0xc5, 0xc2, 0xd5, 0xb2, 0x4f, + 0xe3, 0x7d, 0x40, 0xfa, 0x09, 0xa4, 0x88, 0x5e, 0x83, 0x2a, 0x3f, 0xa0, 0x0a, 0x58, 0xad, 0xe4, + 0x11, 0x4c, 0x39, 0x6b, 0xdc, 0x01, 0x24, 0x64, 0x92, 0x08, 0x52, 0x27, 0x97, 0xdf, 0x7b, 0xb0, + 0x9c, 0x58, 0x1f, 0xfd, 0xed, 0x4b, 0x10, 0x48, 0xef, 0x2e, 0x17, 0xff, 0xb3, 0x04, 0xd0, 0x9b, + 0xd2, 0x03, 0x59, 0xbe, 0x77, 0xa1, 0x36, 0x0d, 0x31, 0xd1, 0x9a, 0x0e, 0xd1, 0x98, 0xcd, 0x05, + 0x76, 0x18, 0x7e, 0xe3, 0x13, 0x95, 0x85, 0x45, 0x63, 0x5e, 0x7a, 0x4f, 0xe9, 0x81, 0x6a, 0xbb, + 0xb1, 0x6f, 0x74, 0x19, 0x5a, 0xe2, 0x3d, 0x8c, 0x65, 0x3b, 0x0e, 0xc1, 0x61, 0x28, 0xfb, 0x6f, + 0x4d, 0x01, 0xed, 0x09, 0x20, 0x43, 0x73, 0x1d, 0xec, 0x51, 0x97, 0x1e, 0x59, 0xd4, 0x7f, 0x8a, + 0x3d, 0x99, 0x5f, 0x35, 0x15, 0xf4, 0x21, 0x03, 0x32, 0x34, 0x82, 0x47, 0x6e, 0x48, 0x89, 0x42, + 0xab, 0x0a, 0x34, 0x05, 0xe5, 0x68, 0xc6, 0xb7, 0x25, 0x68, 0xef, 0x4d, 0xc7, 0x63, 0x71, 0xc8, + 0xd3, 0xca, 0x12, 0xbd, 0x2e, 0xcf, 0x51, 0x4e, 0x35, 0xe1, 0x62, 0x11, 0xc9, 0xc3, 0x7d, 0xf7, + 0x62, 0x6d, 0x19, 0x96, 0x34, 0x46, 0x65, 0x9d, 0x71, 0x07, 0x90, 0x28, 0x41, 0x5e, 0x8c, 0x7f, + 0xe3, 0x0c, 0x2c, 0x27, 0xd6, 0x4b, 0xb2, 0xd7, 0xa0, 0x29, 0x7f, 0x9d, 0x49, 0x3d, 0x9f, 0x85, + 0x1a, 0xf3, 0x07, 0x43, 0xd7, 0x51, 0x2d, 0xd5, 0xf9, 0xc0, 0x77, 0xb6, 0x5c, 0x87, 0x18, 0x7d, + 0x68, 0x9a, 0x82, 0xbc, 0xc4, 0xbd, 0x0d, 0x2d, 0xf9, 0xa3, 0xcd, 0x4a, 0xfc, 0x8a, 0x8e, 0xfb, + 0x7f, 0x09, 0xda, 0x66, 0xd3, 0xd3, 0x87, 0xc6, 0x57, 0xd0, 0x7d, 0x14, 0x38, 0x2c, 0xa1, 0xd1, + 0xa9, 0xaa, 0xa3, 0xdd, 0x06, 0xf5, 0x24, 0xab, 0x88, 0x78, 0x72, 0x59, 0x93, 0xe8, 0x43, 0xe3, + 0x1c, 0xac, 0xe7, 0x12, 0x97, 0xe7, 0x0e, 0xa0, 0x1d, 0x4f, 0x38, 0xae, 0xea, 0x24, 0xf3, 0x0e, + 0x71, 0x49, 0xeb, 0x10, 0xaf, 0x46, 0x51, 0x52, 0xf8, 0x5b, 0x39, 0xd2, 0x12, 0x97, 0x4a, 0x51, + 0xe2, 0x32, 0x9b, 0x48, 0x5c, 0x8c, 0x4f, 0x23, 0xe9, 0xc9, 0xac, 0xf1, 0x5d, 0x9e, 0xba, 0x8a, + 0xbd, 0x95, 0x27, 0x38, 0x9b, 0x73, 0x38, 0x81, 0x61, 0x6a, 0xc8, 0xc6, 0x22, 0x34, 0x13, 0x3e, + 0xc1, 0xf8, 0x10, 0x5a, 0xa9, 0x4b, 0x7e, 0x3d, 0x15, 0xde, 0x33, 0x62, 0x4b, 0x06, 0xf7, 0x6b, + 0xaf, 0x40, 0x4d, 0xbd, 0x1c, 0x43, 0xf3, 0x50, 0x79, 0xb8, 0xb5, 0xd7, 0x9e, 0x61, 0x1f, 0x8f, + 0xb6, 0xf7, 0xda, 0xa5, 0x6b, 0xb7, 0x60, 0x31, 0xf5, 0x53, 0x08, 0x2d, 0x41, 0x73, 0xd0, 0xeb, + 0x6f, 0x7f, 0xf4, 0xe0, 0x0b, 0xcb, 0xdc, 0xe9, 0x6d, 0x7f, 0xd9, 0x9e, 0x41, 0x2b, 0xd0, 0x56, + 0xa0, 0xfe, 0x83, 0x87, 0x02, 0x5a, 0xba, 0xf6, 0x14, 0x5a, 0xc9, 0xfc, 0x15, 0x9d, 0x81, 0xa5, + 0xad, 0x07, 0xfd, 0x87, 0xbd, 0xdd, 0xfe, 0x8e, 0x69, 0x6d, 0x99, 0x3b, 0xbd, 0x87, 0x3b, 0xdb, + 0xed, 0x99, 0x24, 0xd8, 0x7c, 0xd4, 0xef, 0xef, 0xf6, 0x3f, 0x69, 0x97, 0x18, 0xd5, 0x18, 0xbc, + 0xf3, 0xc5, 0x2e, 0x43, 0x2e, 0x27, 0x91, 0x1f, 0xf5, 0xef, 0xf6, 0x1f, 0xfc, 0xac, 0xdf, 0xae, + 0x6c, 0xfe, 0xb9, 0x01, 0x2d, 0x75, 0x40, 0x4c, 0x78, 0xcb, 0xf3, 0x0e, 0xcc, 0xab, 0x47, 0x7d, + 0x71, 0x46, 0x9d, 0x7c, 0x81, 0xd8, 0xed, 0x64, 0x27, 0xa4, 0xa1, 0xcc, 0xa0, 0x3d, 0xae, 0x38, + 0xed, 0x07, 0xdc, 0x39, 0x5d, 0x94, 0x99, 0x3f, 0x7c, 0xdd, 0xf3, 0x45, 0xd3, 0x11, 0xc5, 0x01, + 0xd3, 0x96, 0xfe, 0x12, 0x02, 0xc5, 0x6b, 0x72, 0x5f, 0x58, 0x74, 0x2f, 0x14, 0xce, 0x47, 0x44, + 0xbf, 0x84, 0x76, 0xfa, 0x0d, 0x04, 0x8a, 0x5b, 0xd7, 0x05, 0xef, 0x2b, 0xba, 0x17, 0x8f, 0xc1, + 0xd0, 0x49, 0x67, 0x5e, 0x0b, 0x6c, 0x14, 0xff, 0xef, 0xcd, 0x90, 0x2e, 0xfa, 0x89, 0x2c, 0x44, + 0x91, 0xfc, 0x71, 0x86, 0xf4, 0x7f, 0xf4, 0x39, 0x3f, 0x50, 0x35, 0x51, 0xe4, 0xff, 0x71, 0x33, + 0x66, 0xd0, 0xe7, 0xb0, 0x98, 0xea, 0x76, 0xa1, 0x78, 0x55, 0x7e, 0xef, 0xae, 0xbb, 0x51, 0x8c, + 0x90, 0xd4, 0x9b, 0xde, 0xcb, 0x4a, 0xe8, 0x2d, 0xa7, 0x41, 0x96, 0xd0, 0x5b, 0x6e, 0x13, 0x8c, + 0x9b, 0x57, 0xa2, 0x63, 0xa5, 0x99, 0x57, 0x5e, 0x7b, 0xac, 0x7b, 0xbe, 0x68, 0x5a, 0x3f, 0x7e, + 0xaa, 0x5b, 0xa5, 0x1d, 0x3f, 0xbf, 0x09, 0xd6, 0xdd, 0x28, 0x46, 0x48, 0xeb, 0x2a, 0xae, 0xc2, + 0x53, 0xba, 0xca, 0x34, 0x7d, 0x52, 0xba, 0xca, 0x96, 0xef, 0x52, 0x57, 0xa9, 0x72, 0xfa, 0x42, + 0x61, 0x25, 0x92, 0xd5, 0x55, 0x7e, 0x71, 0x63, 0xcc, 0xa0, 0x1e, 0xd4, 0x54, 0x29, 0x81, 0xe2, + 0xdb, 0x9d, 0xaa, 0x5f, 0xba, 0x67, 0x73, 0x66, 0x22, 0x12, 0x3f, 0x86, 0x59, 0x06, 0x45, 0x2b, + 0x09, 0x24, 0xb5, 0xf4, 0x4c, 0x0a, 0x1a, 0x2d, 0x7b, 0x0f, 0xaa, 0x22, 0x17, 0x47, 0xb1, 0xcf, + 0x4d, 0xa4, 0xf9, 0xdd, 0xb5, 0x0c, 0x3c, 0x5a, 0xfc, 0xa9, 0x78, 0xe8, 0x2b, 0x93, 0x6a, 0xb4, + 0x9e, 0x78, 0x5e, 0x97, 0x4c, 0xdd, 0xbb, 0xaf, 0xe4, 0x4f, 0x46, 0xb4, 0x1e, 0xc3, 0x72, 0x4e, + 0x08, 0x44, 0x71, 0xe7, 0xa7, 0x38, 0xfa, 0x76, 0x2f, 0x1d, 0x8f, 0xa4, 0x1f, 0x56, 0x6a, 0x6d, + 0x55, 0x37, 0x75, 0x4d, 0x59, 0x6b, 0x19, 0xb8, 0x5a, 0xbc, 0xf9, 0xb7, 0x32, 0x2c, 0x88, 0x44, + 0x45, 0xba, 0xea, 0x4f, 0x00, 0xe2, 0x74, 0x19, 0x75, 0x13, 0xd6, 0x93, 0xa8, 0x02, 0xba, 0xeb, + 0xb9, 0x73, 0xba, 0x18, 0xb5, 0xcc, 0x57, 0x13, 0x63, 0x36, 0x9f, 0xd6, 0xc4, 0x98, 0x93, 0x2c, + 0x1b, 0x33, 0x68, 0x1b, 0xea, 0x51, 0x3a, 0x86, 0xb4, 0x2c, 0x2e, 0x95, 0x4b, 0x76, 0xbb, 0x79, + 0x53, 0x3a, 0x47, 0x5a, 0xfe, 0xa5, 0x71, 0x94, 0xcd, 0xea, 0x34, 0x8e, 0xf2, 0x52, 0xb6, 0x99, + 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0x53, 0x61, 0x56, 0xc3, 0x56, 0x2f, 0x00, 0x00, } From 476cd96098d68f00782249c23daab06c5beba3ab Mon Sep 17 00:00:00 2001 From: Pengfei Ni Date: Fri, 4 Nov 2016 19:52:31 +0800 Subject: [PATCH 3/6] run hack/update-bazel.sh --- pkg/kubelet/dockershim/BUILD | 5 +++++ pkg/kubelet/kuberuntime/BUILD | 3 +++ 2 files changed, 8 insertions(+) diff --git a/pkg/kubelet/dockershim/BUILD b/pkg/kubelet/dockershim/BUILD index 444774922fa..324acb06592 100644 --- a/pkg/kubelet/dockershim/BUILD +++ b/pkg/kubelet/dockershim/BUILD @@ -23,6 +23,7 @@ go_library( "helpers.go", "legacy.go", "naming.go", + "security_context.go", ], tags = ["automanaged"], deps = [ @@ -41,6 +42,7 @@ go_library( "//pkg/kubelet/server/streaming:go_default_library", "//pkg/kubelet/types:go_default_library", "//pkg/kubelet/util/ioutils:go_default_library", + "//pkg/securitycontext:go_default_library", "//pkg/util/term:go_default_library", "//vendor:github.com/docker/engine-api/types", "//vendor:github.com/docker/engine-api/types/container", @@ -63,6 +65,7 @@ go_test( "docker_service_test.go", "helpers_test.go", "naming_test.go", + "security_context_test.go", ], library = "go_default_library", tags = ["automanaged"], @@ -76,8 +79,10 @@ go_test( "//pkg/kubelet/network/mock_network:go_default_library", "//pkg/kubelet/types:go_default_library", "//pkg/security/apparmor:go_default_library", + "//pkg/securitycontext:go_default_library", "//pkg/util/clock:go_default_library", "//vendor:github.com/docker/engine-api/types", + "//vendor:github.com/docker/engine-api/types/container", "//vendor:github.com/golang/mock/gomock", "//vendor:github.com/stretchr/testify/assert", ], diff --git a/pkg/kubelet/kuberuntime/BUILD b/pkg/kubelet/kuberuntime/BUILD index 98b62fb4b6d..dc3d5449304 100644 --- a/pkg/kubelet/kuberuntime/BUILD +++ b/pkg/kubelet/kuberuntime/BUILD @@ -25,6 +25,7 @@ go_library( "kuberuntime_sandbox.go", "labels.go", "legacy.go", + "security_context.go", ], tags = ["automanaged"], deps = [ @@ -47,11 +48,13 @@ go_library( "//pkg/kubelet/types:go_default_library", "//pkg/kubelet/util/cache:go_default_library", "//pkg/kubelet/util/format:go_default_library", + "//pkg/securitycontext:go_default_library", "//pkg/types:go_default_library", "//pkg/util/errors:go_default_library", "//pkg/util/flowcontrol:go_default_library", "//pkg/util/parsers:go_default_library", "//pkg/util/runtime:go_default_library", + "//pkg/util/selinux:go_default_library", "//pkg/util/sets:go_default_library", "//pkg/util/term:go_default_library", "//vendor:github.com/coreos/go-semver/semver", From 3df60eb1638c09b565047bc61a5697c25b34c86f Mon Sep 17 00:00:00 2001 From: Pengfei Ni Date: Fri, 4 Nov 2016 19:53:19 +0800 Subject: [PATCH 4/6] Implement security context in kuberuntime --- pkg/kubelet/kuberuntime/helpers.go | 10 ++ .../kuberuntime/kuberuntime_container.go | 94 +++++-------- .../kuberuntime/kuberuntime_sandbox.go | 43 ++++-- pkg/kubelet/kuberuntime/security_context.go | 128 ++++++++++++++++++ 4 files changed, 202 insertions(+), 73 deletions(-) create mode 100644 pkg/kubelet/kuberuntime/security_context.go diff --git a/pkg/kubelet/kuberuntime/helpers.go b/pkg/kubelet/kuberuntime/helpers.go index f17853e0535..510096c47e6 100644 --- a/pkg/kubelet/kuberuntime/helpers.go +++ b/pkg/kubelet/kuberuntime/helpers.go @@ -146,6 +146,16 @@ func getContainerSpec(pod *api.Pod, containerName string) *api.Container { return nil } +// getImageUID gets uid that will run the command(s) from image. +func (m *kubeGenericRuntimeManager) getImageUser(image string) (int64, error) { + imageStatus, err := m.imageService.ImageStatus(&runtimeApi.ImageSpec{Image: &image}) + if err != nil { + return 0, err + } + + return imageStatus.GetUid(), nil +} + // isContainerFailed returns true if container has exited and exitcode is not zero. func isContainerFailed(status *kubecontainer.ContainerStatus) bool { if status.State == kubecontainer.ContainerStateExited && status.ExitCode != 0 { diff --git a/pkg/kubelet/kuberuntime/kuberuntime_container.go b/pkg/kubelet/kuberuntime/kuberuntime_container.go index 2ae10fedb01..a27243f287c 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_container.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_container.go @@ -40,6 +40,7 @@ import ( "k8s.io/kubernetes/pkg/kubelet/util/format" kubetypes "k8s.io/kubernetes/pkg/types" utilruntime "k8s.io/kubernetes/pkg/util/runtime" + "k8s.io/kubernetes/pkg/util/selinux" "k8s.io/kubernetes/pkg/util/sets" "k8s.io/kubernetes/pkg/util/term" ) @@ -136,9 +137,17 @@ func (m *kubeGenericRuntimeManager) generateContainerConfig(container *api.Conta return nil, err } + // Verify RunAsNonRoot. + imageUser, err := m.getImageUser(container.Image) + if err != nil { + return nil, err + } + if err := verifyRunAsNonRoot(pod, container, imageUser); err != nil { + return nil, err + } + command, args := kubecontainer.ExpandContainerCommandAndArgs(container, opts.Envs) containerLogsPath := buildContainerLogsPath(container.Name, restartCount) - podHasSELinuxLabel := pod.Spec.SecurityContext != nil && pod.Spec.SecurityContext.SELinuxOptions != nil restartCountUint32 := uint32(restartCount) config := &runtimeApi.ContainerConfig{ Metadata: &runtimeApi.ContainerMetadata{ @@ -151,24 +160,13 @@ func (m *kubeGenericRuntimeManager) generateContainerConfig(container *api.Conta WorkingDir: &container.WorkingDir, Labels: newContainerLabels(container, pod), Annotations: newContainerAnnotations(container, pod, restartCount), - Mounts: m.makeMounts(opts, container, podHasSELinuxLabel), Devices: makeDevices(opts), + Mounts: m.makeMounts(opts, container), LogPath: &containerLogsPath, Stdin: &container.Stdin, StdinOnce: &container.StdinOnce, Tty: &container.TTY, - Linux: m.generateLinuxContainerConfig(container, pod), - } - - // set privileged and readonlyRootfs - if container.SecurityContext != nil { - securityContext := container.SecurityContext - if securityContext.Privileged != nil { - config.Privileged = securityContext.Privileged - } - if securityContext.ReadOnlyRootFilesystem != nil { - config.ReadonlyRootfs = securityContext.ReadOnlyRootFilesystem - } + Linux: m.generateLinuxContainerConfig(container, pod, imageUser), } // set environment variables @@ -186,9 +184,10 @@ func (m *kubeGenericRuntimeManager) generateContainerConfig(container *api.Conta } // generateLinuxContainerConfig generates linux container config for kubelet runtime api. -func (m *kubeGenericRuntimeManager) generateLinuxContainerConfig(container *api.Container, pod *api.Pod) *runtimeApi.LinuxContainerConfig { - linuxConfig := &runtimeApi.LinuxContainerConfig{ - Resources: &runtimeApi.LinuxContainerResources{}, +func (m *kubeGenericRuntimeManager) generateLinuxContainerConfig(container *api.Container, pod *api.Pod, imageUser int64) *runtimeApi.LinuxContainerConfig { + lc := &runtimeApi.LinuxContainerConfig{ + Resources: &runtimeApi.LinuxContainerResources{}, + SecurityContext: m.determineEffectiveSecurityContext(pod, container, imageUser), } // set linux container resources @@ -208,49 +207,23 @@ func (m *kubeGenericRuntimeManager) generateLinuxContainerConfig(container *api. // of CPU shares. cpuShares = milliCPUToShares(cpuRequest.MilliValue()) } - linuxConfig.Resources.CpuShares = &cpuShares + lc.Resources.CpuShares = &cpuShares if memoryLimit != 0 { - linuxConfig.Resources.MemoryLimitInBytes = &memoryLimit + lc.Resources.MemoryLimitInBytes = &memoryLimit } // Set OOM score of the container based on qos policy. Processes in lower-priority pods should // be killed first if the system runs out of memory. - linuxConfig.Resources.OomScoreAdj = &oomScoreAdj + lc.Resources.OomScoreAdj = &oomScoreAdj if m.cpuCFSQuota { // if cpuLimit.Amount is nil, then the appropriate default value is returned // to allow full usage of cpu resource. cpuQuota, cpuPeriod := milliCPUToQuota(cpuLimit.MilliValue()) - linuxConfig.Resources.CpuQuota = &cpuQuota - linuxConfig.Resources.CpuPeriod = &cpuPeriod + lc.Resources.CpuQuota = &cpuQuota + lc.Resources.CpuPeriod = &cpuPeriod } - // set security context options - if container.SecurityContext != nil { - securityContext := container.SecurityContext - if securityContext.Capabilities != nil { - linuxConfig.Capabilities = &runtimeApi.Capability{ - AddCapabilities: make([]string, len(securityContext.Capabilities.Add)), - DropCapabilities: make([]string, len(securityContext.Capabilities.Drop)), - } - for index, value := range securityContext.Capabilities.Add { - linuxConfig.Capabilities.AddCapabilities[index] = string(value) - } - for index, value := range securityContext.Capabilities.Drop { - linuxConfig.Capabilities.DropCapabilities[index] = string(value) - } - } - - if securityContext.SELinuxOptions != nil { - linuxConfig.SelinuxOptions = &runtimeApi.SELinuxOption{ - User: &securityContext.SELinuxOptions.User, - Role: &securityContext.SELinuxOptions.Role, - Type: &securityContext.SELinuxOptions.Type, - Level: &securityContext.SELinuxOptions.Level, - } - } - } - - return linuxConfig + return lc } // makeDevices generates container devices for kubelet runtime api. @@ -270,21 +243,20 @@ func makeDevices(opts *kubecontainer.RunContainerOptions) []*runtimeApi.Device { } // makeMounts generates container volume mounts for kubelet runtime api. -func (m *kubeGenericRuntimeManager) makeMounts(opts *kubecontainer.RunContainerOptions, container *api.Container, podHasSELinuxLabel bool) []*runtimeApi.Mount { +func (m *kubeGenericRuntimeManager) makeMounts(opts *kubecontainer.RunContainerOptions, container *api.Container) []*runtimeApi.Mount { volumeMounts := []*runtimeApi.Mount{} for idx := range opts.Mounts { v := opts.Mounts[idx] - m := &runtimeApi.Mount{ - HostPath: &v.HostPath, - ContainerPath: &v.ContainerPath, - Readonly: &v.ReadOnly, - } - if podHasSELinuxLabel && v.SELinuxRelabel { - m.SelinuxRelabel = &v.SELinuxRelabel + selinuxRelabel := v.SELinuxRelabel && selinux.SELinuxEnabled() + mount := &runtimeApi.Mount{ + HostPath: &v.HostPath, + ContainerPath: &v.ContainerPath, + Readonly: &v.ReadOnly, + SelinuxRelabel: &selinuxRelabel, } - volumeMounts = append(volumeMounts, m) + volumeMounts = append(volumeMounts, mount) } // The reason we create and mount the log file in here (not in kubelet) is because @@ -301,9 +273,11 @@ func (m *kubeGenericRuntimeManager) makeMounts(opts *kubecontainer.RunContainerO glog.Errorf("Error on creating termination-log file %q: %v", containerLogPath, err) } else { fs.Close() + selinuxRelabel := selinux.SELinuxEnabled() volumeMounts = append(volumeMounts, &runtimeApi.Mount{ - HostPath: &containerLogPath, - ContainerPath: &container.TerminationMessagePath, + HostPath: &containerLogPath, + ContainerPath: &container.TerminationMessagePath, + SelinuxRelabel: &selinuxRelabel, }) } } diff --git a/pkg/kubelet/kuberuntime/kuberuntime_sandbox.go b/pkg/kubelet/kuberuntime/kuberuntime_sandbox.go index f7ac7e41cc7..3333e8e0aab 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_sandbox.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_sandbox.go @@ -120,7 +120,7 @@ func (m *kubeGenericRuntimeManager) generatePodSandboxConfig(pod *api.Pod, attem // TODO: refactor kubelet to get cgroup parent for pod instead of containers cgroupParent = opts.CgroupParent } - podSandboxConfig.Linux = generatePodSandboxLinuxConfig(pod, cgroupParent) + podSandboxConfig.Linux = m.generatePodSandboxLinuxConfig(pod, cgroupParent) if len(portMappings) > 0 { podSandboxConfig.PortMappings = portMappings } @@ -129,26 +129,43 @@ func (m *kubeGenericRuntimeManager) generatePodSandboxConfig(pod *api.Pod, attem } // generatePodSandboxLinuxConfig generates LinuxPodSandboxConfig from api.Pod. -func generatePodSandboxLinuxConfig(pod *api.Pod, cgroupParent string) *runtimeApi.LinuxPodSandboxConfig { +func (m *kubeGenericRuntimeManager) generatePodSandboxLinuxConfig(pod *api.Pod, cgroupParent string) *runtimeApi.LinuxPodSandboxConfig { if pod.Spec.SecurityContext == nil && cgroupParent == "" { return nil } - linuxPodSandboxConfig := &runtimeApi.LinuxPodSandboxConfig{} + lc := &runtimeApi.LinuxPodSandboxConfig{} + if cgroupParent != "" { + lc.CgroupParent = &cgroupParent + } if pod.Spec.SecurityContext != nil { - securityContext := pod.Spec.SecurityContext - linuxPodSandboxConfig.NamespaceOptions = &runtimeApi.NamespaceOption{ - HostNetwork: &securityContext.HostNetwork, - HostIpc: &securityContext.HostIPC, - HostPid: &securityContext.HostPID, + sc := pod.Spec.SecurityContext + lc.SecurityContext = &runtimeApi.LinuxSandboxSecurityContext{ + NamespaceOptions: &runtimeApi.NamespaceOption{ + HostNetwork: &sc.HostNetwork, + HostIpc: &sc.HostIPC, + HostPid: &sc.HostPID, + }, + RunAsUser: sc.RunAsUser, + } + + if groups := m.runtimeHelper.GetExtraSupplementalGroupsForPod(pod); len(groups) > 0 { + lc.SecurityContext.SupplementalGroups = append(lc.SecurityContext.SupplementalGroups, groups...) + } + if sc.SupplementalGroups != nil { + lc.SecurityContext.SupplementalGroups = append(lc.SecurityContext.SupplementalGroups, sc.SupplementalGroups...) + } + if sc.SELinuxOptions != nil { + lc.SecurityContext.SelinuxOptions = &runtimeApi.SELinuxOption{ + User: &sc.SELinuxOptions.User, + Role: &sc.SELinuxOptions.Role, + Type: &sc.SELinuxOptions.Type, + Level: &sc.SELinuxOptions.Level, + } } } - if cgroupParent != "" { - linuxPodSandboxConfig.CgroupParent = &cgroupParent - } - - return linuxPodSandboxConfig + return lc } // getKubeletSandboxes lists all (or just the running) sandboxes managed by kubelet. diff --git a/pkg/kubelet/kuberuntime/security_context.go b/pkg/kubelet/kuberuntime/security_context.go new file mode 100644 index 00000000000..71ca4b54905 --- /dev/null +++ b/pkg/kubelet/kuberuntime/security_context.go @@ -0,0 +1,128 @@ +/* +Copyright 2016 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 kuberuntime + +import ( + "fmt" + + "k8s.io/kubernetes/pkg/api" + runtimeapi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime" + "k8s.io/kubernetes/pkg/securitycontext" +) + +// determineEffectiveSecurityContext gets container's security context from api.Pod and api.Container. +func (m *kubeGenericRuntimeManager) determineEffectiveSecurityContext(pod *api.Pod, container *api.Container, imageUser int64) *runtimeapi.LinuxContainerSecurityContext { + effectiveSc := securitycontext.DetermineEffectiveSecurityContext(pod, container) + synthesized := convertToRuntimeSecurityContext(effectiveSc) + if synthesized == nil { + synthesized = &runtimeapi.LinuxContainerSecurityContext{} + } + + // set RunAsUser. + if synthesized.RunAsUser == nil { + synthesized.RunAsUser = &imageUser + } + + // set namespace options and supplemental groups. + podSc := pod.Spec.SecurityContext + if podSc == nil { + return synthesized + } + synthesized.NamespaceOptions = &runtimeapi.NamespaceOption{ + HostNetwork: &podSc.HostNetwork, + HostIpc: &podSc.HostIPC, + HostPid: &podSc.HostPID, + } + if podSc.FSGroup != nil { + synthesized.SupplementalGroups = append(synthesized.SupplementalGroups, *podSc.FSGroup) + } + if groups := m.runtimeHelper.GetExtraSupplementalGroupsForPod(pod); len(groups) > 0 { + synthesized.SupplementalGroups = append(synthesized.SupplementalGroups, groups...) + } + if podSc.SupplementalGroups != nil { + synthesized.SupplementalGroups = append(synthesized.SupplementalGroups, podSc.SupplementalGroups...) + } + + return synthesized +} + +// verifyRunAsNonRoot verifies RunAsNonRoot. +func verifyRunAsNonRoot(pod *api.Pod, container *api.Container, imageUser int64) error { + effectiveSc := securitycontext.DetermineEffectiveSecurityContext(pod, container) + if effectiveSc == nil || effectiveSc.RunAsNonRoot == nil { + return nil + } + + if effectiveSc.RunAsUser != nil && *effectiveSc.RunAsUser == 0 { + return fmt.Errorf("container's runAsUser breaks non-root policy") + } + + if imageUser == 0 { + return fmt.Errorf("container has runAsNonRoot and image will run as root") + } + + return nil +} + +// convertToRuntimeSecurityContext converts api.SecurityContext to runtimeapi.SecurityContext. +func convertToRuntimeSecurityContext(securityContext *api.SecurityContext) *runtimeapi.LinuxContainerSecurityContext { + if securityContext == nil { + return nil + } + + return &runtimeapi.LinuxContainerSecurityContext{ + RunAsUser: securityContext.RunAsUser, + Privileged: securityContext.Privileged, + ReadonlyRootfs: securityContext.ReadOnlyRootFilesystem, + Capabilities: convertToRuntimeCapabilities(securityContext.Capabilities), + SelinuxOptions: convertToRuntimeSELinuxOption(securityContext.SELinuxOptions), + } +} + +// convertToRuntimeSELinuxOption converts api.SELinuxOptions to runtimeapi.SELinuxOption. +func convertToRuntimeSELinuxOption(opts *api.SELinuxOptions) *runtimeapi.SELinuxOption { + if opts == nil { + return nil + } + + return &runtimeapi.SELinuxOption{ + User: &opts.User, + Role: &opts.Role, + Type: &opts.Type, + Level: &opts.Level, + } +} + +// convertToRuntimeCapabilities converts api.Capabilities to runtimeapi.Capability. +func convertToRuntimeCapabilities(opts *api.Capabilities) *runtimeapi.Capability { + if opts == nil { + return nil + } + + capabilities := &runtimeapi.Capability{ + AddCapabilities: make([]string, len(opts.Add)), + DropCapabilities: make([]string, len(opts.Drop)), + } + for index, value := range opts.Add { + capabilities.AddCapabilities[index] = string(value) + } + for index, value := range opts.Drop { + capabilities.DropCapabilities[index] = string(value) + } + + return capabilities +} From 3aee57d4ae87d6cc6ce8a8386738287664210139 Mon Sep 17 00:00:00 2001 From: Pengfei Ni Date: Fri, 4 Nov 2016 19:54:07 +0800 Subject: [PATCH 5/6] Add security context support in dockershim --- pkg/kubelet/dockershim/convert.go | 15 +- pkg/kubelet/dockershim/docker_container.go | 32 +-- pkg/kubelet/dockershim/docker_sandbox.go | 41 ++- pkg/kubelet/dockershim/docker_sandbox_test.go | 8 +- pkg/kubelet/dockershim/helpers.go | 7 +- pkg/kubelet/dockershim/security_context.go | 158 +++++++++++ .../dockershim/security_context_test.go | 257 ++++++++++++++++++ pkg/kubelet/dockertools/docker_manager.go | 6 +- .../dockertools/docker_manager_test.go | 2 +- pkg/securitycontext/provider.go | 15 +- pkg/securitycontext/provider_test.go | 16 +- pkg/securitycontext/types.go | 10 +- 12 files changed, 496 insertions(+), 71 deletions(-) create mode 100644 pkg/kubelet/dockershim/security_context.go create mode 100644 pkg/kubelet/dockershim/security_context_test.go diff --git a/pkg/kubelet/dockershim/convert.go b/pkg/kubelet/dockershim/convert.go index 7e350f5596a..25e5851ae6c 100644 --- a/pkg/kubelet/dockershim/convert.go +++ b/pkg/kubelet/dockershim/convert.go @@ -18,12 +18,14 @@ package dockershim import ( "fmt" + "strconv" "strings" "time" dockertypes "github.com/docker/engine-api/types" runtimeApi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime" + "k8s.io/kubernetes/pkg/kubelet/dockertools" ) // This file contains helper functions to convert docker API types to runtime @@ -55,14 +57,25 @@ func imageInspectToRuntimeAPIImage(image *dockertypes.ImageInspect) (*runtimeApi return nil, fmt.Errorf("unable to convert a nil pointer to a runtime API image") } + var err error + var uid int64 size := uint64(image.VirtualSize) + imageUid := dockertools.GetUidFromUser(image.Config.User) + // Convert image UID to int64 format. Not that it assumes the process in + // the image is running as root if image.Config.User is not set. + if imageUid != "" { + uid, err = strconv.ParseInt(imageUid, 10, 64) + if err != nil { + return nil, fmt.Errorf("non-numeric user (%q)", imageUid) + } + } return &runtimeApi.Image{ Id: &image.ID, RepoTags: image.RepoTags, RepoDigests: image.RepoDigests, Size_: &size, + Uid: &uid, }, nil - } func toPullableImageID(id string, image *dockertypes.ImageInspect) string { diff --git a/pkg/kubelet/dockershim/docker_container.go b/pkg/kubelet/dockershim/docker_container.go index a62aa152c30..ad8438184bb 100644 --- a/pkg/kubelet/dockershim/docker_container.go +++ b/pkg/kubelet/dockershim/docker_container.go @@ -120,34 +120,15 @@ func (ds *dockerService) CreateContainer(podSandboxID string, config *runtimeApi // Fill the HostConfig. hc := &dockercontainer.HostConfig{ - Binds: generateMountBindings(config.GetMounts()), - ReadonlyRootfs: config.GetReadonlyRootfs(), - Privileged: config.GetPrivileged(), + Binds: generateMountBindings(config.GetMounts()), } - // Apply options derived from the sandbox config. + // Apply cgroupsParent derived from the sandbox config. if lc := sandboxConfig.GetLinux(); lc != nil { // Apply Cgroup options. // TODO: Check if this works with per-pod cgroups. // TODO: we need to pass the cgroup in syntax expected by cgroup driver but shim does not use docker info yet... hc.CgroupParent = lc.GetCgroupParent() - - // Apply namespace options. - sandboxNSMode := fmt.Sprintf("container:%v", podSandboxID) - hc.NetworkMode = dockercontainer.NetworkMode(sandboxNSMode) - hc.IpcMode = dockercontainer.IpcMode(sandboxNSMode) - hc.UTSMode = "" - hc.PidMode = "" - - nsOpts := lc.GetNamespaceOptions() - if nsOpts != nil { - if nsOpts.GetHostNetwork() { - hc.UTSMode = namespaceModeHost - } - if nsOpts.GetHostPid() { - hc.PidMode = namespaceModeHost - } - } } // Apply Linux-specific options if applicable. @@ -167,6 +148,9 @@ func (ds *dockerService) CreateContainer(podSandboxID string, config *runtimeApi hc.OomScoreAdj = int(rOpts.GetOomScoreAdj()) } // Note: ShmSize is handled in kube_docker_client.go + + // Apply security context. + applyContainerSecurityContext(lc, podSandboxID, createConfig.Config, hc) } // Set devices for container. @@ -180,12 +164,12 @@ func (ds *dockerService) CreateContainer(podSandboxID string, config *runtimeApi } hc.Resources.Devices = devices - var err error - hc.SecurityOpt, err = getContainerSecurityOpts(config.Metadata.GetName(), sandboxConfig, ds.seccompProfileRoot) + // Apply appArmor and seccomp options. + securityOpts, err := getContainerSecurityOpts(config.Metadata.GetName(), sandboxConfig, ds.seccompProfileRoot) if err != nil { return "", fmt.Errorf("failed to generate container security options for container %q: %v", config.Metadata.GetName(), err) } - // TODO: Add or drop capabilities. + hc.SecurityOpt = append(hc.SecurityOpt, securityOpts...) createConfig.HostConfig = hc createResp, err := ds.client.CreateContainer(createConfig) diff --git a/pkg/kubelet/dockershim/docker_sandbox.go b/pkg/kubelet/dockershim/docker_sandbox.go index 171aa51987e..fe9fa142e35 100644 --- a/pkg/kubelet/dockershim/docker_sandbox.go +++ b/pkg/kubelet/dockershim/docker_sandbox.go @@ -79,7 +79,7 @@ func (ds *dockerService) RunPodSandbox(config *runtimeApi.PodSandboxConfig) (str if err != nil { return createResp.ID, fmt.Errorf("failed to start sandbox container for pod %q: %v", config.Metadata.GetName(), err) } - if config.GetLinux().GetNamespaceOptions().GetHostNetwork() { + if config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetHostNetwork() { return createResp.ID, nil } @@ -286,6 +286,18 @@ func (ds *dockerService) ListPodSandbox(filter *runtimeApi.PodSandboxFilter) ([] return result, nil } +// applySandboxLinuxOptions applies LinuxPodSandboxConfig to dockercontainer.HostConfig and dockercontainer.ContainerCreateConfig. +func (ds *dockerService) applySandboxLinuxOptions(hc *dockercontainer.HostConfig, lc *runtimeApi.LinuxPodSandboxConfig, createConfig *dockertypes.ContainerCreateConfig, image string) error { + // Apply Cgroup options. + // TODO: Check if this works with per-pod cgroups. + hc.CgroupParent = lc.GetCgroupParent() + // Apply security context. + applySandboxSecurityContext(lc, createConfig.Config, hc) + + return nil +} + +// makeSandboxDockerConfig returns dockertypes.ContainerCreateConfig based on runtimeApi.PodSandboxConfig. func (ds *dockerService) makeSandboxDockerConfig(c *runtimeApi.PodSandboxConfig, image string) (*dockertypes.ContainerCreateConfig, error) { // Merge annotations and labels because docker supports only labels. labels := makeLabels(c.GetLabels(), c.GetAnnotations()) @@ -316,29 +328,11 @@ func (ds *dockerService) makeSandboxDockerConfig(c *runtimeApi.PodSandboxConfig, // Apply linux-specific options. if lc := c.GetLinux(); lc != nil { - // Apply Cgroup options. - // TODO: Check if this works with per-pod cgroups. - hc.CgroupParent = lc.GetCgroupParent() - - // Apply namespace options. - hc.NetworkMode, hc.UTSMode, hc.PidMode = "", "", "" - nsOpts := lc.GetNamespaceOptions() - if nsOpts != nil { - if nsOpts.GetHostNetwork() { - hc.NetworkMode = namespaceModeHost - } else { - // Assume kubelet uses either the cni or the kubenet plugin. - // TODO: support docker networking. - hc.NetworkMode = "none" - } - if nsOpts.GetHostIpc() { - hc.IpcMode = namespaceModeHost - } - if nsOpts.GetHostPid() { - hc.PidMode = namespaceModeHost - } + if err := ds.applySandboxLinuxOptions(hc, lc, createConfig, image); err != nil { + return nil, err } } + // Set port mappings. exposedPorts, portBindings := makePortsAndBindings(c.GetPortMappings()) createConfig.Config.ExposedPorts = exposedPorts @@ -355,10 +349,11 @@ func (ds *dockerService) makeSandboxDockerConfig(c *runtimeApi.PodSandboxConfig, setSandboxResources(hc) // Set security options. - hc.SecurityOpt, err = getSandboxSecurityOpts(c, ds.seccompProfileRoot) + securityOpts, err := getSandboxSecurityOpts(c, ds.seccompProfileRoot) if err != nil { return nil, fmt.Errorf("failed to generate sandbox security options for sandbox %q: %v", c.Metadata.GetName(), err) } + hc.SecurityOpt = append(hc.SecurityOpt, securityOpts...) return createConfig, nil } diff --git a/pkg/kubelet/dockershim/docker_sandbox_test.go b/pkg/kubelet/dockershim/docker_sandbox_test.go index bf49c25628a..329690b1ca9 100644 --- a/pkg/kubelet/dockershim/docker_sandbox_test.go +++ b/pkg/kubelet/dockershim/docker_sandbox_test.go @@ -186,7 +186,13 @@ func TestHostNetworkPluginInvocation(t *testing.T) { map[string]string{"annotation": ns}, ) hostNetwork := true - c.Linux = &runtimeApi.LinuxPodSandboxConfig{NamespaceOptions: &runtimeApi.NamespaceOption{HostNetwork: &hostNetwork}} + c.Linux = &runtimeApi.LinuxPodSandboxConfig{ + SecurityContext: &runtimeApi.LinuxSandboxSecurityContext{ + NamespaceOptions: &runtimeApi.NamespaceOption{ + HostNetwork: &hostNetwork, + }, + }, + } cID := kubecontainer.ContainerID{Type: runtimeName, ID: fmt.Sprintf("/%v", makeSandboxName(c))} // No calls to network plugin are expected diff --git a/pkg/kubelet/dockershim/helpers.go b/pkg/kubelet/dockershim/helpers.go index 0b67c650625..111388f97ba 100644 --- a/pkg/kubelet/dockershim/helpers.go +++ b/pkg/kubelet/dockershim/helpers.go @@ -123,13 +123,18 @@ func extractLabels(input map[string]string) (map[string]string, map[string]strin // '::Z', if the volume requires SELinux // relabeling and the pod provides an SELinux label func generateMountBindings(mounts []*runtimeApi.Mount) (result []string) { - // TODO: resolve podHasSELinuxLabel for _, m := range mounts { bind := fmt.Sprintf("%s:%s", m.GetHostPath(), m.GetContainerPath()) readOnly := m.GetReadonly() if readOnly { bind += ":ro" } + // Only request relabeling if the pod provides an SELinux context. If the pod + // does not provide an SELinux context relabeling will label the volume with + // the container's randomly allocated MCS label. This would restrict access + // to the volume to the container which mounts it first. + // TODO: always relabel if SELinux is enabled and the volume support relabeling + // (refer #33951 and #33663). if m.GetSelinuxRelabel() { if readOnly { bind += ",Z" diff --git a/pkg/kubelet/dockershim/security_context.go b/pkg/kubelet/dockershim/security_context.go new file mode 100644 index 00000000000..db56d149ba4 --- /dev/null +++ b/pkg/kubelet/dockershim/security_context.go @@ -0,0 +1,158 @@ +/* +Copyright 2016 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 dockershim + +import ( + "fmt" + "strconv" + + dockercontainer "github.com/docker/engine-api/types/container" + + "k8s.io/kubernetes/pkg/api" + runtimeapi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime" + "k8s.io/kubernetes/pkg/securitycontext" +) + +// applySandboxSecurityContext updates docker sandbox options according to security context. +func applySandboxSecurityContext(lc *runtimeapi.LinuxPodSandboxConfig, config *dockercontainer.Config, hc *dockercontainer.HostConfig) { + if lc == nil { + return + } + + var sc *runtimeapi.LinuxContainerSecurityContext + if lc.SecurityContext != nil { + sc = &runtimeapi.LinuxContainerSecurityContext{ + // TODO: We skip application of supplemental groups to the + // sandbox container to work around a runc issue which + // requires containers to have the '/etc/group'. For more + // information see: https://github.com/opencontainers/runc/pull/313. + // This can be removed once the fix makes it into the required + // version of docker. + RunAsUser: lc.SecurityContext.RunAsUser, + ReadonlyRootfs: lc.SecurityContext.ReadonlyRootfs, + SelinuxOptions: lc.SecurityContext.SelinuxOptions, + NamespaceOptions: lc.SecurityContext.NamespaceOptions, + } + } + + modifyContainerConfig(sc, config) + modifyHostConfig(sc, "", hc) +} + +// applyContainerSecurityContext updates docker container options according to security context. +func applyContainerSecurityContext(lc *runtimeapi.LinuxContainerConfig, sandboxID string, config *dockercontainer.Config, hc *dockercontainer.HostConfig) { + if lc == nil { + return + } + + modifyContainerConfig(lc.SecurityContext, config) + modifyHostConfig(lc.SecurityContext, sandboxID, hc) + return +} + +// modifyContainerConfig applies container security context config to dockercontainer.Config. +func modifyContainerConfig(sc *runtimeapi.LinuxContainerSecurityContext, config *dockercontainer.Config) { + if sc != nil && sc.RunAsUser != nil { + config.User = strconv.FormatInt(sc.GetRunAsUser(), 10) + } +} + +// modifyHostConfig applies security context config to dockercontainer.HostConfig. +func modifyHostConfig(sc *runtimeapi.LinuxContainerSecurityContext, sandboxID string, hostConfig *dockercontainer.HostConfig) { + // Apply namespace options. + modifyNamespaceOptions(sc.GetNamespaceOptions(), sandboxID, hostConfig) + + if sc == nil { + return + } + + // Apply supplemental groups. + for _, group := range sc.SupplementalGroups { + hostConfig.GroupAdd = append(hostConfig.GroupAdd, strconv.FormatInt(group, 10)) + } + + // Apply security context for the container. + if sc.Privileged != nil { + hostConfig.Privileged = sc.GetPrivileged() + } + if sc.ReadonlyRootfs != nil { + hostConfig.ReadonlyRootfs = sc.GetReadonlyRootfs() + } + if sc.Capabilities != nil { + hostConfig.CapAdd = sc.GetCapabilities().GetAddCapabilities() + hostConfig.CapDrop = sc.GetCapabilities().GetDropCapabilities() + } + if sc.SelinuxOptions != nil { + hostConfig.SecurityOpt = securitycontext.ModifySecurityOptions( + hostConfig.SecurityOpt, + &api.SELinuxOptions{ + User: sc.SelinuxOptions.GetUser(), + Role: sc.SelinuxOptions.GetRole(), + Type: sc.SelinuxOptions.GetType(), + Level: sc.SelinuxOptions.GetLevel(), + }, + ) + } +} + +// modifyNamespaceOptions applies namespaceoptions to dockercontainer.HostConfig. +func modifyNamespaceOptions(nsOpts *runtimeapi.NamespaceOption, sandboxID string, hostConfig *dockercontainer.HostConfig) { + hostNetwork := false + if nsOpts != nil { + if nsOpts.HostNetwork != nil { + hostNetwork = nsOpts.GetHostNetwork() + } + if nsOpts.GetHostPid() { + hostConfig.PidMode = namespaceModeHost + } + if nsOpts.GetHostIpc() { + hostConfig.IpcMode = namespaceModeHost + } + } + + // Set for sandbox if sandboxID is not provided. + if sandboxID == "" { + modifyHostNetworkOptionForSandbox(hostNetwork, hostConfig) + } else { + // Set for container is sandboxID is provided. + modifyHostNetworkOptionForContainer(hostNetwork, sandboxID, hostConfig) + } +} + +// modifyHostNetworkOptionForSandbox applies NetworkMode/UTSMode to sandbox's dockercontainer.HostConfig. +func modifyHostNetworkOptionForSandbox(hostNetwork bool, hc *dockercontainer.HostConfig) { + if hostNetwork { + hc.NetworkMode = namespaceModeHost + } else { + // Assume kubelet uses either the cni or the kubenet plugin. + // TODO: support docker networking. + hc.NetworkMode = "none" + } +} + +// modifyHostNetworkOptionForContainer applies NetworkMode/UTSMode to container's dockercontainer.HostConfig. +func modifyHostNetworkOptionForContainer(hostNetwork bool, sandboxID string, hc *dockercontainer.HostConfig) { + sandboxNSMode := fmt.Sprintf("container:%v", sandboxID) + hc.NetworkMode = dockercontainer.NetworkMode(sandboxNSMode) + hc.IpcMode = dockercontainer.IpcMode(sandboxNSMode) + hc.UTSMode = "" + hc.PidMode = "" + + if hostNetwork { + hc.UTSMode = namespaceModeHost + } +} diff --git a/pkg/kubelet/dockershim/security_context_test.go b/pkg/kubelet/dockershim/security_context_test.go new file mode 100644 index 00000000000..b22dc396b0f --- /dev/null +++ b/pkg/kubelet/dockershim/security_context_test.go @@ -0,0 +1,257 @@ +/* +Copyright 2016 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 dockershim + +import ( + "fmt" + "strconv" + "testing" + + dockercontainer "github.com/docker/engine-api/types/container" + "github.com/stretchr/testify/assert" + + runtimeapi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime" + "k8s.io/kubernetes/pkg/securitycontext" +) + +func TestModifyContainerConfig(t *testing.T) { + var uid int64 = 123 + + cases := []struct { + name string + sc *runtimeapi.LinuxContainerSecurityContext + expected *dockercontainer.Config + }{ + { + name: "container.SecurityContext.RunAsUser set", + sc: &runtimeapi.LinuxContainerSecurityContext{ + RunAsUser: &uid, + }, + expected: &dockercontainer.Config{ + User: strconv.FormatInt(uid, 10), + }, + }, + { + name: "no RunAsUser value set", + sc: &runtimeapi.LinuxContainerSecurityContext{}, + expected: &dockercontainer.Config{}, + }, + } + + for _, tc := range cases { + dockerCfg := &dockercontainer.Config{} + modifyContainerConfig(tc.sc, dockerCfg) + assert.Equal(t, tc.expected, dockerCfg, "[Test case %q]", tc.name) + } +} + +func TestModifyHostConfig(t *testing.T) { + priv := true + setPrivSC := &runtimeapi.LinuxContainerSecurityContext{} + setPrivSC.Privileged = &priv + setPrivHC := &dockercontainer.HostConfig{ + Privileged: true, + NetworkMode: "none", + } + setCapsHC := &dockercontainer.HostConfig{ + NetworkMode: "none", + CapAdd: []string{"addCapA", "addCapB"}, + CapDrop: []string{"dropCapA", "dropCapB"}, + } + setSELinuxHC := &dockercontainer.HostConfig{ + NetworkMode: "none", + SecurityOpt: []string{ + fmt.Sprintf("%s:%s", securitycontext.DockerLabelUser, "user"), + fmt.Sprintf("%s:%s", securitycontext.DockerLabelRole, "role"), + fmt.Sprintf("%s:%s", securitycontext.DockerLabelType, "type"), + fmt.Sprintf("%s:%s", securitycontext.DockerLabelLevel, "level"), + }, + } + + cases := []struct { + name string + sc *runtimeapi.LinuxContainerSecurityContext + expected *dockercontainer.HostConfig + }{ + { + name: "fully set container.SecurityContext", + sc: fullValidSecurityContext(), + expected: fullValidHostConfig(), + }, + { + name: "container.SecurityContext.Privileged", + sc: setPrivSC, + expected: setPrivHC, + }, + { + name: "container.SecurityContext.Capabilities", + sc: &runtimeapi.LinuxContainerSecurityContext{ + Capabilities: inputCapabilities(), + }, + expected: setCapsHC, + }, + { + name: "container.SecurityContext.SELinuxOptions", + sc: &runtimeapi.LinuxContainerSecurityContext{ + SelinuxOptions: inputSELinuxOptions(), + }, + expected: setSELinuxHC, + }, + } + + for _, tc := range cases { + dockerCfg := &dockercontainer.HostConfig{} + modifyHostConfig(tc.sc, "", dockerCfg) + assert.Equal(t, tc.expected, dockerCfg, "[Test case %q]", tc.name) + } +} + +func TestModifyHostConfigWithGroups(t *testing.T) { + supplementalGroupsSC := &runtimeapi.LinuxContainerSecurityContext{} + supplementalGroupsSC.SupplementalGroups = []int64{2222} + supplementalGroupHC := &dockercontainer.HostConfig{NetworkMode: "none"} + supplementalGroupHC.GroupAdd = []string{"2222"} + + testCases := []struct { + name string + securityContext *runtimeapi.LinuxContainerSecurityContext + expected *dockercontainer.HostConfig + }{ + { + name: "nil", + securityContext: nil, + expected: &dockercontainer.HostConfig{NetworkMode: "none"}, + }, + { + name: "SupplementalGroup", + securityContext: supplementalGroupsSC, + expected: supplementalGroupHC, + }, + } + + for _, tc := range testCases { + dockerCfg := &dockercontainer.HostConfig{} + modifyHostConfig(tc.securityContext, "", dockerCfg) + assert.Equal(t, tc.expected, dockerCfg, "[Test case %q]", tc.name) + } +} + +func TestModifyHostConfigWithSandboxID(t *testing.T) { + priv := true + sandboxID := "sandbox" + sandboxNSMode := fmt.Sprintf("container:%v", sandboxID) + setPrivSC := &runtimeapi.LinuxContainerSecurityContext{} + setPrivSC.Privileged = &priv + setPrivHC := &dockercontainer.HostConfig{ + Privileged: true, + IpcMode: dockercontainer.IpcMode(sandboxNSMode), + NetworkMode: dockercontainer.NetworkMode(sandboxNSMode), + } + setCapsHC := &dockercontainer.HostConfig{ + CapAdd: []string{"addCapA", "addCapB"}, + CapDrop: []string{"dropCapA", "dropCapB"}, + IpcMode: dockercontainer.IpcMode(sandboxNSMode), + NetworkMode: dockercontainer.NetworkMode(sandboxNSMode), + } + setSELinuxHC := &dockercontainer.HostConfig{ + SecurityOpt: []string{ + fmt.Sprintf("%s:%s", securitycontext.DockerLabelUser, "user"), + fmt.Sprintf("%s:%s", securitycontext.DockerLabelRole, "role"), + fmt.Sprintf("%s:%s", securitycontext.DockerLabelType, "type"), + fmt.Sprintf("%s:%s", securitycontext.DockerLabelLevel, "level"), + }, + IpcMode: dockercontainer.IpcMode(sandboxNSMode), + NetworkMode: dockercontainer.NetworkMode(sandboxNSMode), + } + + cases := []struct { + name string + sc *runtimeapi.LinuxContainerSecurityContext + expected *dockercontainer.HostConfig + }{ + { + name: "container.SecurityContext.Privileged", + sc: setPrivSC, + expected: setPrivHC, + }, + { + name: "container.SecurityContext.Capabilities", + sc: &runtimeapi.LinuxContainerSecurityContext{ + Capabilities: inputCapabilities(), + }, + expected: setCapsHC, + }, + { + name: "container.SecurityContext.SELinuxOptions", + sc: &runtimeapi.LinuxContainerSecurityContext{ + SelinuxOptions: inputSELinuxOptions(), + }, + expected: setSELinuxHC, + }, + } + + for _, tc := range cases { + dockerCfg := &dockercontainer.HostConfig{} + modifyHostConfig(tc.sc, sandboxID, dockerCfg) + assert.Equal(t, tc.expected, dockerCfg, "[Test case %q]", tc.name) + } +} + +func fullValidSecurityContext() *runtimeapi.LinuxContainerSecurityContext { + priv := true + return &runtimeapi.LinuxContainerSecurityContext{ + Privileged: &priv, + Capabilities: inputCapabilities(), + SelinuxOptions: inputSELinuxOptions(), + } +} + +func inputCapabilities() *runtimeapi.Capability { + return &runtimeapi.Capability{ + AddCapabilities: []string{"addCapA", "addCapB"}, + DropCapabilities: []string{"dropCapA", "dropCapB"}, + } +} + +func inputSELinuxOptions() *runtimeapi.SELinuxOption { + user := "user" + role := "role" + stype := "type" + level := "level" + + return &runtimeapi.SELinuxOption{ + User: &user, + Role: &role, + Type: &stype, + Level: &level, + } +} + +func fullValidHostConfig() *dockercontainer.HostConfig { + return &dockercontainer.HostConfig{ + Privileged: true, + NetworkMode: "none", + CapAdd: []string{"addCapA", "addCapB"}, + CapDrop: []string{"dropCapA", "dropCapB"}, + SecurityOpt: []string{ + fmt.Sprintf("%s:%s", securitycontext.DockerLabelUser, "user"), + fmt.Sprintf("%s:%s", securitycontext.DockerLabelRole, "role"), + fmt.Sprintf("%s:%s", securitycontext.DockerLabelType, "type"), + fmt.Sprintf("%s:%s", securitycontext.DockerLabelLevel, "level"), + }, + } +} diff --git a/pkg/kubelet/dockertools/docker_manager.go b/pkg/kubelet/dockertools/docker_manager.go index 55a5ba1ae7c..e34debc1fe5 100644 --- a/pkg/kubelet/dockertools/docker_manager.go +++ b/pkg/kubelet/dockertools/docker_manager.go @@ -2474,7 +2474,7 @@ func (dm *DockerManager) isImageRoot(image string) (bool, error) { return false, fmt.Errorf("unable to inspect image %s, nil Config", image) } - user := getUidFromUser(img.Config.User) + user := GetUidFromUser(img.Config.User) // if no user is defined container will run as root if user == "" { return true, nil @@ -2488,8 +2488,8 @@ func (dm *DockerManager) isImageRoot(image string) (bool, error) { return uid == 0, nil } -// getUidFromUser splits the uid out of an uid:gid string. -func getUidFromUser(id string) string { +// GetUidFromUser splits the uid out of an uid:gid string. +func GetUidFromUser(id string) string { if id == "" { return id } diff --git a/pkg/kubelet/dockertools/docker_manager_test.go b/pkg/kubelet/dockertools/docker_manager_test.go index a350def7bff..592c09673e9 100644 --- a/pkg/kubelet/dockertools/docker_manager_test.go +++ b/pkg/kubelet/dockertools/docker_manager_test.go @@ -1454,7 +1454,7 @@ func TestGetUidFromUser(t *testing.T) { }, } for k, v := range tests { - actual := getUidFromUser(v.input) + actual := GetUidFromUser(v.input) if actual != v.expect { t.Errorf("%s failed. Expected %s but got %s", k, v.expect, actual) } diff --git a/pkg/securitycontext/provider.go b/pkg/securitycontext/provider.go index 524aa772353..1b17a2abc0c 100644 --- a/pkg/securitycontext/provider.go +++ b/pkg/securitycontext/provider.go @@ -91,13 +91,20 @@ func (p SimpleSecurityContextProvider) ModifyHostConfig(pod *api.Pod, container } if effectiveSC.SELinuxOptions != nil { - hostConfig.SecurityOpt = modifySecurityOption(hostConfig.SecurityOpt, dockerLabelUser, effectiveSC.SELinuxOptions.User) - hostConfig.SecurityOpt = modifySecurityOption(hostConfig.SecurityOpt, dockerLabelRole, effectiveSC.SELinuxOptions.Role) - hostConfig.SecurityOpt = modifySecurityOption(hostConfig.SecurityOpt, dockerLabelType, effectiveSC.SELinuxOptions.Type) - hostConfig.SecurityOpt = modifySecurityOption(hostConfig.SecurityOpt, dockerLabelLevel, effectiveSC.SELinuxOptions.Level) + hostConfig.SecurityOpt = ModifySecurityOptions(hostConfig.SecurityOpt, effectiveSC.SELinuxOptions) } } +// ModifySecurityOptions adds SELinux options to config. +func ModifySecurityOptions(config []string, selinuxOpts *api.SELinuxOptions) []string { + config = modifySecurityOption(config, DockerLabelUser, selinuxOpts.User) + config = modifySecurityOption(config, DockerLabelRole, selinuxOpts.Role) + config = modifySecurityOption(config, DockerLabelType, selinuxOpts.Type) + config = modifySecurityOption(config, DockerLabelLevel, selinuxOpts.Level) + + return config +} + // modifySecurityOption adds the security option of name to the config array with value in the form // of name:value func modifySecurityOption(config []string, name, value string) []string { diff --git a/pkg/securitycontext/provider_test.go b/pkg/securitycontext/provider_test.go index 37012039b51..0c955647ba4 100644 --- a/pkg/securitycontext/provider_test.go +++ b/pkg/securitycontext/provider_test.go @@ -104,10 +104,10 @@ func TestModifyHostConfig(t *testing.T) { setSELinuxHC := &dockercontainer.HostConfig{} setSELinuxHC.SecurityOpt = []string{ - fmt.Sprintf("%s:%s", dockerLabelUser, "user"), - fmt.Sprintf("%s:%s", dockerLabelRole, "role"), - fmt.Sprintf("%s:%s", dockerLabelType, "type"), - fmt.Sprintf("%s:%s", dockerLabelLevel, "level"), + fmt.Sprintf("%s:%s", DockerLabelUser, "user"), + fmt.Sprintf("%s:%s", DockerLabelRole, "role"), + fmt.Sprintf("%s:%s", DockerLabelType, "type"), + fmt.Sprintf("%s:%s", DockerLabelLevel, "level"), } // seLinuxLabelsSC := fullValidSecurityContext() @@ -325,10 +325,10 @@ func fullValidHostConfig() *dockercontainer.HostConfig { CapAdd: []string{"addCapA", "addCapB"}, CapDrop: []string{"dropCapA", "dropCapB"}, SecurityOpt: []string{ - fmt.Sprintf("%s:%s", dockerLabelUser, "user"), - fmt.Sprintf("%s:%s", dockerLabelRole, "role"), - fmt.Sprintf("%s:%s", dockerLabelType, "type"), - fmt.Sprintf("%s:%s", dockerLabelLevel, "level"), + fmt.Sprintf("%s:%s", DockerLabelUser, "user"), + fmt.Sprintf("%s:%s", DockerLabelRole, "role"), + fmt.Sprintf("%s:%s", DockerLabelType, "type"), + fmt.Sprintf("%s:%s", DockerLabelLevel, "level"), }, } } diff --git a/pkg/securitycontext/types.go b/pkg/securitycontext/types.go index 2ab2d0390b5..500c2ba2b64 100644 --- a/pkg/securitycontext/types.go +++ b/pkg/securitycontext/types.go @@ -41,9 +41,9 @@ type SecurityContextProvider interface { } const ( - dockerLabelUser string = "label:user" - dockerLabelRole string = "label:role" - dockerLabelType string = "label:type" - dockerLabelLevel string = "label:level" - dockerLabelDisable string = "label:disable" + DockerLabelUser string = "label:user" + DockerLabelRole string = "label:role" + DockerLabelType string = "label:type" + DockerLabelLevel string = "label:level" + DockerLabelDisable string = "label:disable" ) From f8e5f81fedd5243b9d7f690a9c0738794db15899 Mon Sep 17 00:00:00 2001 From: Pengfei Ni Date: Mon, 7 Nov 2016 11:41:06 +0800 Subject: [PATCH 6/6] cleanup TODOs in dockershim --- pkg/kubelet/dockershim/helpers.go | 2 -- pkg/kubelet/dockershim/security_context.go | 17 ++++++----------- pkg/kubelet/dockershim/security_context_test.go | 8 ++++++++ pkg/kubelet/kuberuntime/kuberuntime_sandbox.go | 3 +++ 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/pkg/kubelet/dockershim/helpers.go b/pkg/kubelet/dockershim/helpers.go index 111388f97ba..9d7ec54d5aa 100644 --- a/pkg/kubelet/dockershim/helpers.go +++ b/pkg/kubelet/dockershim/helpers.go @@ -133,8 +133,6 @@ func generateMountBindings(mounts []*runtimeApi.Mount) (result []string) { // does not provide an SELinux context relabeling will label the volume with // the container's randomly allocated MCS label. This would restrict access // to the volume to the container which mounts it first. - // TODO: always relabel if SELinux is enabled and the volume support relabeling - // (refer #33951 and #33663). if m.GetSelinuxRelabel() { if readOnly { bind += ",Z" diff --git a/pkg/kubelet/dockershim/security_context.go b/pkg/kubelet/dockershim/security_context.go index db56d149ba4..102fbd84401 100644 --- a/pkg/kubelet/dockershim/security_context.go +++ b/pkg/kubelet/dockershim/security_context.go @@ -36,16 +36,11 @@ func applySandboxSecurityContext(lc *runtimeapi.LinuxPodSandboxConfig, config *d var sc *runtimeapi.LinuxContainerSecurityContext if lc.SecurityContext != nil { sc = &runtimeapi.LinuxContainerSecurityContext{ - // TODO: We skip application of supplemental groups to the - // sandbox container to work around a runc issue which - // requires containers to have the '/etc/group'. For more - // information see: https://github.com/opencontainers/runc/pull/313. - // This can be removed once the fix makes it into the required - // version of docker. - RunAsUser: lc.SecurityContext.RunAsUser, - ReadonlyRootfs: lc.SecurityContext.ReadonlyRootfs, - SelinuxOptions: lc.SecurityContext.SelinuxOptions, - NamespaceOptions: lc.SecurityContext.NamespaceOptions, + SupplementalGroups: lc.SecurityContext.SupplementalGroups, + RunAsUser: lc.SecurityContext.RunAsUser, + ReadonlyRootfs: lc.SecurityContext.ReadonlyRootfs, + SelinuxOptions: lc.SecurityContext.SelinuxOptions, + NamespaceOptions: lc.SecurityContext.NamespaceOptions, } } @@ -128,7 +123,7 @@ func modifyNamespaceOptions(nsOpts *runtimeapi.NamespaceOption, sandboxID string if sandboxID == "" { modifyHostNetworkOptionForSandbox(hostNetwork, hostConfig) } else { - // Set for container is sandboxID is provided. + // Set for container if sandboxID is provided. modifyHostNetworkOptionForContainer(hostNetwork, sandboxID, hostConfig) } } diff --git a/pkg/kubelet/dockershim/security_context_test.go b/pkg/kubelet/dockershim/security_context_test.go index b22dc396b0f..859b737d861 100644 --- a/pkg/kubelet/dockershim/security_context_test.go +++ b/pkg/kubelet/dockershim/security_context_test.go @@ -61,6 +61,9 @@ func TestModifyContainerConfig(t *testing.T) { func TestModifyHostConfig(t *testing.T) { priv := true + setNetworkHC := &dockercontainer.HostConfig{ + NetworkMode: "none", + } setPrivSC := &runtimeapi.LinuxContainerSecurityContext{} setPrivSC.Privileged = &priv setPrivHC := &dockercontainer.HostConfig{ @@ -92,6 +95,11 @@ func TestModifyHostConfig(t *testing.T) { sc: fullValidSecurityContext(), expected: fullValidHostConfig(), }, + { + name: "empty container.SecurityContext", + sc: &runtimeapi.LinuxContainerSecurityContext{}, + expected: setNetworkHC, + }, { name: "container.SecurityContext.Privileged", sc: setPrivSC, diff --git a/pkg/kubelet/kuberuntime/kuberuntime_sandbox.go b/pkg/kubelet/kuberuntime/kuberuntime_sandbox.go index 3333e8e0aab..2374ecd4e31 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_sandbox.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_sandbox.go @@ -149,6 +149,9 @@ func (m *kubeGenericRuntimeManager) generatePodSandboxLinuxConfig(pod *api.Pod, RunAsUser: sc.RunAsUser, } + if sc.FSGroup != nil { + lc.SecurityContext.SupplementalGroups = append(lc.SecurityContext.SupplementalGroups, *sc.FSGroup) + } if groups := m.runtimeHelper.GetExtraSupplementalGroupsForPod(pod); len(groups) > 0 { lc.SecurityContext.SupplementalGroups = append(lc.SecurityContext.SupplementalGroups, groups...) }