Skip to content

Commit

Permalink
Default Container Security Context For All Containers in Elasticsearch.
Browse files Browse the repository at this point in the history
Signed-off-by: pritamdas99 <[email protected]>
  • Loading branch information
pritamdas99 committed Nov 23, 2023
1 parent 8e497b9 commit 2aa4144
Show file tree
Hide file tree
Showing 2 changed files with 171 additions and 29 deletions.
114 changes: 114 additions & 0 deletions apis/dashboard/v1alpha1/elasticsearchdashboard_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ import (
api "kubedb.dev/apimachinery/apis/kubedb/v1alpha2"
amv "kubedb.dev/apimachinery/pkg/validator"

"github.com/pkg/errors"
"gomodules.xyz/pointer"
core "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
Expand Down Expand Up @@ -70,6 +72,42 @@ func (ed *ElasticsearchDashboard) SetupWebhookWithManager(mgr manager.Manager) e

var _ webhook.Defaulter = &ElasticsearchDashboard{}

func (ed *ElasticsearchDashboard) setDefaultContainerSecurityContext() {
containerSecurityContext := &core.SecurityContext{}
if ed.Spec.PodTemplate.Spec.ContainerSecurityContext != nil {
containerSecurityContext = ed.Spec.PodTemplate.Spec.ContainerSecurityContext
}
if containerSecurityContext.AllowPrivilegeEscalation == nil {
containerSecurityContext.AllowPrivilegeEscalation = pointer.BoolP(false)
}
if containerSecurityContext.RunAsNonRoot == nil {
containerSecurityContext.RunAsNonRoot = pointer.BoolP(true)
}
if containerSecurityContext.RunAsUser == nil {
containerSecurityContext.RunAsUser = pointer.Int64P(1000)
}
if containerSecurityContext.RunAsGroup == nil {
containerSecurityContext.RunAsGroup = pointer.Int64P(1000)
}
capabilities := &core.Capabilities{}
if containerSecurityContext.Capabilities != nil {
capabilities = containerSecurityContext.Capabilities
}
if len(capabilities.Drop) == 0 {
capabilities.Drop = []core.Capability{"ALL"}
}
containerSecurityContext.Capabilities = capabilities
seccomProfile := &core.SeccompProfile{}
if containerSecurityContext.SeccompProfile != nil {
seccomProfile = containerSecurityContext.SeccompProfile
}
if seccomProfile.Type == "" {
seccomProfile.Type = core.SeccompProfileTypeRuntimeDefault
}
containerSecurityContext.SeccompProfile = seccomProfile
ed.Spec.PodTemplate.Spec.ContainerSecurityContext = containerSecurityContext
}

// Default implements webhook.Defaulter so a webhook will be registered for the type
func (ed *ElasticsearchDashboard) Default() {
if ed.Spec.Replicas == nil {
Expand All @@ -85,6 +123,8 @@ func (ed *ElasticsearchDashboard) Default() {
edLog.Info(".Spec.TerminationPolicy have been set to TerminationPolicyWipeOut")
}

ed.setDefaultContainerSecurityContext()

if ed.Spec.EnableSSL {
if ed.Spec.TLS == nil {
ed.Spec.TLS = &kmapi.TLSConfig{}
Expand Down Expand Up @@ -144,6 +184,55 @@ func (ed *ElasticsearchDashboard) ValidateDelete() error {
ed.Name, allErr)
}

func validateContainerCapabilities(ed *ElasticsearchDashboard) error {
capabilities := ed.Spec.PodTemplate.Spec.ContainerSecurityContext.Capabilities
if len(capabilities.Add) > 0 {
return errors.Errorf("Can't add user provided capabilities")
}

if len(capabilities.Drop) != 1 {
return errors.Errorf("Can't drop more than one capability")
}

if capabilities.Drop[0] != "ALL" {
return errors.Errorf("Have to drop all capabilities")
}
return nil
}

func validateContainerUserAndGroup(ed *ElasticsearchDashboard) error {
if ed.Spec.PodTemplate.Spec.ContainerSecurityContext.RunAsGroup != nil && *ed.Spec.PodTemplate.Spec.ContainerSecurityContext.RunAsGroup != 1000 {
return errors.Errorf("elasticsearch should run as a group elasticsearch (ID=1000)")
}

if ed.Spec.PodTemplate.Spec.ContainerSecurityContext.RunAsUser != nil && *ed.Spec.PodTemplate.Spec.ContainerSecurityContext.RunAsUser != 1000 {
return errors.Errorf("elasticsearch should run as a user elasticsearch (ID=1000)")
}

return nil
}

func validateAllowedPriviledgeEscalation(ed *ElasticsearchDashboard) error {
if ed.Spec.PodTemplate.Spec.ContainerSecurityContext.AllowPrivilegeEscalation != nil && *ed.Spec.PodTemplate.Spec.ContainerSecurityContext.AllowPrivilegeEscalation {
return errors.Errorf("AllowedPrivilegeEscalation can't be true")
}
return nil
}

func validateRunAsNonRoot(ed *ElasticsearchDashboard) error {
if ed.Spec.PodTemplate.Spec.ContainerSecurityContext.RunAsNonRoot != nil && !*ed.Spec.PodTemplate.Spec.ContainerSecurityContext.RunAsNonRoot {
return errors.Errorf("RunAsNonRoot can't be false")
}
return nil
}

func validateSeccomprofile(ed *ElasticsearchDashboard) error {
if ed.Spec.PodTemplate.Spec.ContainerSecurityContext.SeccompProfile.Type != "" && ed.Spec.PodTemplate.Spec.ContainerSecurityContext.SeccompProfile.Type != core.SeccompProfileTypeRuntimeDefault {
return errors.Errorf("Seccomprofile type must be RuntimeDefault")
}
return nil
}

func (ed *ElasticsearchDashboard) Validate() error {
var allErr field.ErrorList

Expand Down Expand Up @@ -172,5 +261,30 @@ func (ed *ElasticsearchDashboard) Validate() error {
return nil
}

err := validateContainerUserAndGroup(ed)
if err != nil {
return err
}

err = validateContainerCapabilities(ed)
if err != nil {
return err
}

err = validateAllowedPriviledgeEscalation(ed)
if err != nil {
return nil
}

err = validateRunAsNonRoot(ed)
if err != nil {
return err
}

err = validateSeccomprofile(ed)
if err != nil {
return err
}

return apierrors.NewInvalid(schema.GroupKind{Group: "dashboard.kubedb.com", Kind: "ElasticsearchDashboard"}, ed.Name, allErr)
}
86 changes: 57 additions & 29 deletions apis/kubedb/v1alpha2/elasticsearch_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,61 @@ func (e Elasticsearch) StatsServiceLabels() map[string]string {
return e.ServiceLabels(StatsServiceAlias, map[string]string{LabelRole: RoleStats})
}

func setDefaultContainerSecurityContext(containerSecurityContext *core.SecurityContext) {
if containerSecurityContext.AllowPrivilegeEscalation == nil {
containerSecurityContext.AllowPrivilegeEscalation = pointer.BoolP(false)
}
if containerSecurityContext.RunAsNonRoot == nil {
containerSecurityContext.RunAsNonRoot = pointer.BoolP(true)
}
if containerSecurityContext.RunAsUser == nil {
containerSecurityContext.RunAsUser = pointer.Int64P(1000)
}
if containerSecurityContext.RunAsGroup == nil {
containerSecurityContext.RunAsGroup = pointer.Int64P(1000)
}
capabilities := &core.Capabilities{}
if containerSecurityContext.Capabilities != nil {
capabilities = containerSecurityContext.Capabilities
}
if len(capabilities.Drop) == 0 {
capabilities.Drop = []core.Capability{"ALL"}
}
containerSecurityContext.Capabilities = capabilities
seccomProfile := &core.SeccompProfile{}
if containerSecurityContext.SeccompProfile != nil {
seccomProfile = containerSecurityContext.SeccompProfile
}
if seccomProfile.Type == "" {
seccomProfile.Type = core.SeccompProfileTypeRuntimeDefault
}
containerSecurityContext.SeccompProfile = seccomProfile
}

func (e *Elasticsearch) setDefaultContainerSecurityContextForMonitor() {
containerSecurityContext := &core.SecurityContext{}
if e.Spec.Monitor != nil && e.Spec.Monitor.Agent.Vendor() == mona.VendorPrometheus {
if e.Spec.Monitor.Prometheus == nil {
setDefaultContainerSecurityContext(containerSecurityContext)
e.Spec.Monitor.Prometheus = &mona.PrometheusSpec{}
e.Spec.Monitor.Prometheus.Exporter.SecurityContext = containerSecurityContext
return
}
containerSecurityContext = e.Spec.Monitor.Prometheus.Exporter.SecurityContext
setDefaultContainerSecurityContext(containerSecurityContext)
e.Spec.Monitor.Prometheus.Exporter.SecurityContext = containerSecurityContext
}
}

func (e *Elasticsearch) setDefaultContainerSecurityContextForPodTemplate() {
containerSecurityContext := &core.SecurityContext{}
if e.Spec.PodTemplate.Spec.ContainerSecurityContext != nil {
containerSecurityContext = e.Spec.PodTemplate.Spec.ContainerSecurityContext
}
setDefaultContainerSecurityContext(containerSecurityContext)
e.Spec.PodTemplate.Spec.ContainerSecurityContext = containerSecurityContext
}

func (e *Elasticsearch) SetDefaults(esVersion *catalog.ElasticsearchVersion, topology *core_util.Topology) {
if e == nil {
return
Expand Down Expand Up @@ -561,35 +616,8 @@ func (e *Elasticsearch) SetDefaults(esVersion *catalog.ElasticsearchVersion, top
}
}

// set default kernel settings
// - Ref: https://www.elastic.co/guide/en/elasticsearch/reference/7.9/vm-max-map-count.html
if e.Spec.KernelSettings == nil {
e.Spec.KernelSettings = &KernelSettings{
Privileged: true,
Sysctls: []core.Sysctl{
{
Name: "vm.max_map_count",
Value: "262144",
},
},
}
}

if e.Spec.PodTemplate.Spec.ContainerSecurityContext == nil {
e.Spec.PodTemplate.Spec.ContainerSecurityContext = &core.SecurityContext{
Privileged: pointer.BoolP(false),
Capabilities: &core.Capabilities{
Add: []core.Capability{"IPC_LOCK", "SYS_RESOURCE"},
},
}
}

// Add default Elasticsearch UID
if e.Spec.PodTemplate.Spec.ContainerSecurityContext.RunAsUser == nil &&
esVersion.Spec.SecurityContext.RunAsUser != nil {
e.Spec.PodTemplate.Spec.ContainerSecurityContext.RunAsUser = esVersion.Spec.SecurityContext.RunAsUser
}

e.setDefaultContainerSecurityContextForPodTemplate()
e.setDefaultContainerSecurityContextForMonitor()
e.setDefaultAffinity(&e.Spec.PodTemplate, e.OffshootSelectors(), topology)
e.SetTLSDefaults(esVersion)
e.setDefaultInternalUsersAndRoleMappings(esVersion)
Expand Down

0 comments on commit 2aa4144

Please sign in to comment.