Skip to content
This repository has been archived by the owner on Jun 8, 2022. It is now read-only.

Add support for security context #320

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions apis/core/v1alpha2/core_workload_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,55 @@ type ContainerHealthProbe struct {
FailureThreshold *int32 `json:"failureThreshold,omitempty"`
}

// Capability represent POSIX capabilities type
type Capability string

// Capabilities to be added and removed from running containers.
type Capabilities struct {
// Added capabilities
// +optional
Add []Capability `json:"add,omitempty" protobuf:"bytes,1,rep,name=add,casttype=Capability"`
// Removed capabilities
// +optional
Drop []Capability `json:"drop,omitempty" protobuf:"bytes,2,rep,name=drop,casttype=Capability"`
}

// SecurityContext holds security configuration that will be applied to a container.
type SecurityContext struct {
// The capabilities to add/drop when running containers.
// Defaults to the default set of capabilities granted by the container runtime.
// +optional
Capabilities *Capabilities `json:"capabilities,omitempty" protobuf:"bytes,1,opt,name=capabilities"`
// Run container in privileged mode.
// Processes in privileged containers are essentially equivalent to root on the host.
// Defaults to false.
// +optional
Privileged *bool `json:"privileged,omitempty" protobuf:"varint,2,opt,name=privileged"`
// The UID to run the entrypoint of the container process.
// Defaults to user specified in image metadata if unspecified.
// +optional
RunAsUser *int64 `json:"runAsUser,omitempty" protobuf:"varint,4,opt,name=runAsUser"`
// The GID to run the entrypoint of the container process.
// Uses runtime default if unset.
// +optional
RunAsGroup *int64 `json:"runAsGroup,omitempty" protobuf:"varint,8,opt,name=runAsGroup"`
// Indicates that the container must run as a non-root user.
// +optional
RunAsNonRoot *bool `json:"runAsNonRoot,omitempty" protobuf:"varint,5,opt,name=runAsNonRoot"`
// Whether this container has a read-only root filesystem.
// Default is false.
// +optional
ReadOnlyRootFilesystem *bool `json:"readOnlyRootFilesystem,omitempty" protobuf:"varint,6,opt,name=readOnlyRootFilesystem"`
// AllowPrivilegeEscalation controls whether a process can gain more
// privileges than its parent process. This bool directly controls if
// the no_new_privs flag will be set on the container process.
// AllowPrivilegeEscalation is true always when the container is:
// 1) run as Privileged
// 2) has CAP_SYS_ADMIN
// +optional
AllowPrivilegeEscalation *bool `json:"allowPrivilegeEscalation,omitempty" protobuf:"varint,7,opt,name=allowPrivilegeEscalation"`
}

// A Container represents an Open Containers Initiative (OCI) container.
type Container struct {
// Name of this container. Must be unique within its workload.
Expand Down Expand Up @@ -354,6 +403,10 @@ type Container struct {
// credentials required to pull this container's image can be loaded.
// +optional
ImagePullSecret *string `json:"imagePullSecret,omitempty"`

// Security options the container should run with.
// +optional
SecurityContext *SecurityContext `json:"securityContext,omitempty"`
}

// A ContainerizedWorkloadSpec defines the desired state of a
Expand Down
80 changes: 80 additions & 0 deletions apis/core/v1alpha2/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,46 @@ spec:
- cpu
- memory
type: object
securityContext:
description: Security options the container should run with.
properties:
allowPrivilegeEscalation:
description: 'AllowPrivilegeEscalation controls whether a process can gain more privileges than its parent process. This bool directly controls if the no_new_privs flag will be set on the container process. AllowPrivilegeEscalation is true always when the container is: 1) run as Privileged 2) has CAP_SYS_ADMIN'
type: boolean
capabilities:
description: The capabilities to add/drop when running containers. Defaults to the default set of capabilities granted by the container runtime.
properties:
add:
description: Added capabilities
items:
description: Capability represent POSIX capabilities type
type: string
type: array
drop:
description: Removed capabilities
items:
description: Capability represent POSIX capabilities type
type: string
type: array
type: object
privileged:
description: Run container in privileged mode. Processes in privileged containers are essentially equivalent to root on the host. Defaults to false.
type: boolean
readOnlyRootFilesystem:
description: Whether this container has a read-only root filesystem. Default is false.
type: boolean
runAsGroup:
description: The GID to run the entrypoint of the container process. Uses runtime default if unset.
format: int64
type: integer
runAsNonRoot:
description: Indicates that the container must run as a non-root user.
type: boolean
runAsUser:
description: The UID to run the entrypoint of the container process. Defaults to user specified in image metadata if unspecified.
format: int64
type: integer
type: object
required:
- image
- name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,46 @@ spec:
- cpu
- memory
type: object
securityContext:
description: Security options the container should run with.
properties:
allowPrivilegeEscalation:
description: 'AllowPrivilegeEscalation controls whether a process can gain more privileges than its parent process. This bool directly controls if the no_new_privs flag will be set on the container process. AllowPrivilegeEscalation is true always when the container is: 1) run as Privileged 2) has CAP_SYS_ADMIN'
type: boolean
capabilities:
description: The capabilities to add/drop when running containers. Defaults to the default set of capabilities granted by the container runtime.
properties:
add:
description: Added capabilities
items:
description: Capability represent POSIX capabilities type
type: string
type: array
drop:
description: Removed capabilities
items:
description: Capability represent POSIX capabilities type
type: string
type: array
type: object
privileged:
description: Run container in privileged mode. Processes in privileged containers are essentially equivalent to root on the host. Defaults to false.
type: boolean
readOnlyRootFilesystem:
description: Whether this container has a read-only root filesystem. Default is false.
type: boolean
runAsGroup:
description: The GID to run the entrypoint of the container process. Uses runtime default if unset.
format: int64
type: integer
runAsNonRoot:
description: Indicates that the container must run as a non-root user.
type: boolean
runAsUser:
description: The UID to run the entrypoint of the container process. Defaults to user specified in image metadata if unspecified.
format: int64
type: integer
type: object
required:
- image
- name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,10 @@ func TranslateContainerWorkload(ctx context.Context, w oam.Workload) ([]oam.Obje
d.Spec.Template.Spec.Volumes = append(d.Spec.Template.Spec.Volumes, v)
}

if container.SecurityContext != nil {
kubernetesContainer.SecurityContext = translateSecurityContext(container.SecurityContext)
}

d.Spec.Template.Spec.Containers = append(d.Spec.Template.Spec.Containers, kubernetesContainer)
}

Expand All @@ -275,6 +279,34 @@ func TranslateContainerWorkload(ctx context.Context, w oam.Workload) ([]oam.Obje
return []oam.Object{d}, nil
}

// translateSecurityContext transforms a OAM security context into a Kubernetes one.
func translateSecurityContext(secCtx *v1alpha2.SecurityContext) *corev1.SecurityContext {
result := &corev1.SecurityContext{
Privileged: secCtx.Privileged,
RunAsUser: secCtx.RunAsUser,
RunAsGroup: secCtx.RunAsGroup,
RunAsNonRoot: secCtx.RunAsNonRoot,
ReadOnlyRootFilesystem: secCtx.ReadOnlyRootFilesystem,
AllowPrivilegeEscalation: secCtx.AllowPrivilegeEscalation,
}
if secCtx.Capabilities != nil {
add := make([]corev1.Capability, 0)
drop := make([]corev1.Capability, 0)
for _, toAdd := range secCtx.Capabilities.Add {
add = append(add, corev1.Capability(toAdd))
}
for _, toDrop := range secCtx.Capabilities.Drop {
drop = append(drop, corev1.Capability(toDrop))
}
cap := &corev1.Capabilities{
Add: add,
Drop: drop,
}
result.Capabilities = cap
}
return result
}

func translateConfigFileToVolume(cf v1alpha2.ContainerConfigFile, wlName, containerName string) (v corev1.Volume, vm corev1.VolumeMount) {
mountPath, _ := path.Split(cf.Path)
// translate into ConfigMap Volume
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,9 @@ func TestContainerizedWorkloadTranslator(t *testing.T) {
"dapr.io/enabled": "true",
}
dmAnnotation := cwAnnotation
flagEnabled := true
var secIDValue int64 = 1000

type args struct {
w oam.Workload
}
Expand Down Expand Up @@ -319,6 +322,50 @@ func TestContainerizedWorkloadTranslator(t *testing.T) {
},
}))}},
},
"SuccessfulWithSecurityContext": {
reason: "A ContainerizedWorkload with security context should be successfully translated into a deployment.",
args: args{
w: containerizedWorkload(cwWithContainer(v1alpha2.Container{
Name: "cool-container",
Image: "cool/image:latest",
Command: []string{"run"},
Arguments: []string{"--coolflag"},
SecurityContext: &v1alpha2.SecurityContext{
Capabilities: &v1alpha2.Capabilities{
Add: []v1alpha2.Capability{"ADD"},
Drop: []v1alpha2.Capability{"DROP"},
},
Privileged: &flagEnabled,
RunAsUser: &secIDValue,
RunAsGroup: &secIDValue,
RunAsNonRoot: &flagEnabled,
ReadOnlyRootFilesystem: &flagEnabled,
AllowPrivilegeEscalation: &flagEnabled,
},
})),
},
want: want{result: []oam.Object{deployment(dmWithContainer(corev1.Container{
Name: "cool-container",
Image: "cool/image:latest",
Command: []string{"run"},
Args: []string{"--coolflag"},
SecurityContext: &corev1.SecurityContext{
Capabilities: &corev1.Capabilities{
Add: []corev1.Capability{"ADD"},
Drop: []corev1.Capability{"DROP"},
},
Privileged: &flagEnabled,
SELinuxOptions: nil,
WindowsOptions: nil,
RunAsUser: &secIDValue,
RunAsGroup: &secIDValue,
RunAsNonRoot: &flagEnabled,
ReadOnlyRootFilesystem: &flagEnabled,
AllowPrivilegeEscalation: &flagEnabled,
ProcMount: nil,
},
}))}},
},
}

for name, tc := range cases {
Expand Down