Class: Kube::Cluster::Middleware::SecurityContext

Inherits:
Kube::Cluster::Middleware show all
Defined in:
lib/kube/cluster/middleware/security_context.rb

Overview

Injects pod and container security contexts on pod-bearing resources.

Reads the app.kubernetes.io/security label. When the label is absent, the middleware applies the default profile.

Kube::Cluster["Deployment"].new {
  metadata.labels = { "app.kubernetes.io/security": "restricted" }
  ...
}

Available profiles: restricted (default), baseline.

stack do
  use Middleware::SecurityContext                      # default: restricted
  use Middleware::SecurityContext, default: :baseline  # change default
end

Constant Summary collapse

LABEL =
:"app.kubernetes.io/security"
PROFILES =
{
  "restricted" => {
    pod: {
      runAsNonRoot: true,
      runAsUser:    1000,
      runAsGroup:   1000,
      fsGroup:      1000,
      seccompProfile: { type: "RuntimeDefault" },
    },
    container: {
      allowPrivilegeEscalation: false,
      readOnlyRootFilesystem:   true,
      capabilities:             { drop: ["ALL"] },
    },
  },
  "baseline" => {
    pod: {
      runAsNonRoot: true,
      runAsUser:    1000,
      runAsGroup:   1000,
      fsGroup:      1000,
    },
    container: {
      allowPrivilegeEscalation: false,
    },
  },
}.freeze

Instance Method Summary collapse

Constructor Details

#initialize(default: :restricted) ⇒ SecurityContext

Returns a new instance of SecurityContext.



54
55
56
# File 'lib/kube/cluster/middleware/security_context.rb', line 54

def initialize(default: :restricted)
  @default = default.to_s
end

Instance Method Details

#call(manifest) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/kube/cluster/middleware/security_context.rb', line 58

def call(manifest)
  manifest.resources.map! do |resource|
    next resource unless resource.pod_bearing?

    profile_name = resource.label(LABEL) || @default
    profile = PROFILES.fetch(profile_name.to_s) do
      raise ArgumentError, "Unknown security profile: #{profile_name.inspect}. " \
        "Valid profiles: #{PROFILES.keys.join(', ')}"
    end

    h = resource.to_h
    pod_spec = resource.pod_template(h)
    next resource unless pod_spec

    pod_spec[:securityContext] = deep_merge(profile[:pod], pod_spec[:securityContext] || {})

    resource.each_container(pod_spec) do |container|
      container[:securityContext] = deep_merge(profile[:container], container[:securityContext] || {})
    end

    resource.rebuild(h)
  end
end