Skip to content

Commit e5aa70c

Browse files
shajia-deshawAgalin
authored andcommitted
feat: add configurable SecurityContext to InstanceSidecarConfiguration
Enable PSA compliance for the plugin side-car through optional `SecurityContext` field in `Archive` spec. Maintains backward compatibility with nil defaults. Signed-off-by: Afeedh Shaji <[email protected]>
1 parent 5afecab commit e5aa70c

File tree

6 files changed

+695
-10
lines changed

6 files changed

+695
-10
lines changed

api/v1/archive_types.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ type InstanceSidecarConfiguration struct {
3232
// Resources allocated for the sidecar
3333
// +optional
3434
Resources corev1.ResourceRequirements `json:"resources,omitempty"`
35+
// SecurityContext for the sidecar container
36+
// +optional
37+
SecurityContext *corev1.SecurityContext `json:"securityContext,omitempty"`
3538
}
3639

3740
// ArchiveSpec defines the desired state of Archive.

api/v1/zz_generated.deepcopy.go

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/pgbackrest.cnpg.opera.com_archives.yaml

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,198 @@ spec:
552552
More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
553553
type: object
554554
type: object
555+
securityContext:
556+
description: SecurityContext for the sidecar container
557+
properties:
558+
allowPrivilegeEscalation:
559+
description: |-
560+
AllowPrivilegeEscalation controls whether a process can gain more
561+
privileges than its parent process. This bool directly controls if
562+
the no_new_privs flag will be set on the container process.
563+
AllowPrivilegeEscalation is true always when the container is:
564+
1) run as Privileged
565+
2) has CAP_SYS_ADMIN
566+
Note that this field cannot be set when spec.os.name is windows.
567+
type: boolean
568+
appArmorProfile:
569+
description: |-
570+
appArmorProfile is the AppArmor options to use by this container. If set, this profile
571+
overrides the pod's appArmorProfile.
572+
Note that this field cannot be set when spec.os.name is windows.
573+
properties:
574+
localhostProfile:
575+
description: |-
576+
localhostProfile indicates a profile loaded on the node that should be used.
577+
The profile must be preconfigured on the node to work.
578+
Must match the loaded name of the profile.
579+
Must be set if and only if type is "Localhost".
580+
type: string
581+
type:
582+
description: |-
583+
type indicates which kind of AppArmor profile will be applied.
584+
Valid options are:
585+
Localhost - a profile pre-loaded on the node.
586+
RuntimeDefault - the container runtime's default profile.
587+
Unconfined - no AppArmor enforcement.
588+
type: string
589+
required:
590+
- type
591+
type: object
592+
capabilities:
593+
description: |-
594+
The capabilities to add/drop when running containers.
595+
Defaults to the default set of capabilities granted by the container runtime.
596+
Note that this field cannot be set when spec.os.name is windows.
597+
properties:
598+
add:
599+
description: Added capabilities
600+
items:
601+
description: Capability represent POSIX capabilities
602+
type
603+
type: string
604+
type: array
605+
x-kubernetes-list-type: atomic
606+
drop:
607+
description: Removed capabilities
608+
items:
609+
description: Capability represent POSIX capabilities
610+
type
611+
type: string
612+
type: array
613+
x-kubernetes-list-type: atomic
614+
type: object
615+
privileged:
616+
description: |-
617+
Run container in privileged mode.
618+
Processes in privileged containers are essentially equivalent to root on the host.
619+
Defaults to false.
620+
Note that this field cannot be set when spec.os.name is windows.
621+
type: boolean
622+
procMount:
623+
description: |-
624+
procMount denotes the type of proc mount to use for the containers.
625+
The default value is Default which uses the container runtime defaults for
626+
readonly paths and masked paths.
627+
This requires the ProcMountType feature flag to be enabled.
628+
Note that this field cannot be set when spec.os.name is windows.
629+
type: string
630+
readOnlyRootFilesystem:
631+
description: |-
632+
Whether this container has a read-only root filesystem.
633+
Default is false.
634+
Note that this field cannot be set when spec.os.name is windows.
635+
type: boolean
636+
runAsGroup:
637+
description: |-
638+
The GID to run the entrypoint of the container process.
639+
Uses runtime default if unset.
640+
May also be set in PodSecurityContext. If set in both SecurityContext and
641+
PodSecurityContext, the value specified in SecurityContext takes precedence.
642+
Note that this field cannot be set when spec.os.name is windows.
643+
format: int64
644+
type: integer
645+
runAsNonRoot:
646+
description: |-
647+
Indicates that the container must run as a non-root user.
648+
If true, the Kubelet will validate the image at runtime to ensure that it
649+
does not run as UID 0 (root) and fail to start the container if it does.
650+
If unset or false, no such validation will be performed.
651+
May also be set in PodSecurityContext. If set in both SecurityContext and
652+
PodSecurityContext, the value specified in SecurityContext takes precedence.
653+
type: boolean
654+
runAsUser:
655+
description: |-
656+
The UID to run the entrypoint of the container process.
657+
Defaults to user specified in image metadata if unspecified.
658+
May also be set in PodSecurityContext. If set in both SecurityContext and
659+
PodSecurityContext, the value specified in SecurityContext takes precedence.
660+
Note that this field cannot be set when spec.os.name is windows.
661+
format: int64
662+
type: integer
663+
seLinuxOptions:
664+
description: |-
665+
The SELinux context to be applied to the container.
666+
If unspecified, the container runtime will allocate a random SELinux context for each
667+
container. May also be set in PodSecurityContext. If set in both SecurityContext and
668+
PodSecurityContext, the value specified in SecurityContext takes precedence.
669+
Note that this field cannot be set when spec.os.name is windows.
670+
properties:
671+
level:
672+
description: Level is SELinux level label that applies
673+
to the container.
674+
type: string
675+
role:
676+
description: Role is a SELinux role label that applies
677+
to the container.
678+
type: string
679+
type:
680+
description: Type is a SELinux type label that applies
681+
to the container.
682+
type: string
683+
user:
684+
description: User is a SELinux user label that applies
685+
to the container.
686+
type: string
687+
type: object
688+
seccompProfile:
689+
description: |-
690+
The seccomp options to use by this container. If seccomp options are
691+
provided at both the pod & container level, the container options
692+
override the pod options.
693+
Note that this field cannot be set when spec.os.name is windows.
694+
properties:
695+
localhostProfile:
696+
description: |-
697+
localhostProfile indicates a profile defined in a file on the node should be used.
698+
The profile must be preconfigured on the node to work.
699+
Must be a descending path, relative to the kubelet's configured seccomp profile location.
700+
Must be set if type is "Localhost". Must NOT be set for any other type.
701+
type: string
702+
type:
703+
description: |-
704+
type indicates which kind of seccomp profile will be applied.
705+
Valid options are:
706+
707+
Localhost - a profile defined in a file on the node should be used.
708+
RuntimeDefault - the container runtime default profile should be used.
709+
Unconfined - no profile should be applied.
710+
type: string
711+
required:
712+
- type
713+
type: object
714+
windowsOptions:
715+
description: |-
716+
The Windows specific settings applied to all containers.
717+
If unspecified, the options from the PodSecurityContext will be used.
718+
If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence.
719+
Note that this field cannot be set when spec.os.name is linux.
720+
properties:
721+
gmsaCredentialSpec:
722+
description: |-
723+
GMSACredentialSpec is where the GMSA admission webhook
724+
(https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the
725+
GMSA credential spec named by the GMSACredentialSpecName field.
726+
type: string
727+
gmsaCredentialSpecName:
728+
description: GMSACredentialSpecName is the name of the
729+
GMSA credential spec to use.
730+
type: string
731+
hostProcess:
732+
description: |-
733+
HostProcess determines if a container should be run as a 'Host Process' container.
734+
All of a Pod's containers must have the same effective HostProcess value
735+
(it is not allowed to have a mix of HostProcess containers and non-HostProcess containers).
736+
In addition, if HostProcess is true then HostNetwork must also be set to true.
737+
type: boolean
738+
runAsUserName:
739+
description: |-
740+
The UserName in Windows to run the entrypoint of the container process.
741+
Defaults to the user specified in image metadata if unspecified.
742+
May also be set in PodSecurityContext. If set in both SecurityContext and
743+
PodSecurityContext, the value specified in SecurityContext takes precedence.
744+
type: string
745+
type: object
746+
type: object
555747
type: object
556748
required:
557749
- configuration

internal/cnpgi/operator/lifecycle.go

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,21 @@ func (impl LifecycleImplementation) calculateSidecarResources(
138138
return nil
139139
}
140140

141+
func (impl LifecycleImplementation) calculateSidecarSecurityContext(
142+
ctx context.Context,
143+
archive *pgbackrestv1.Archive,
144+
) *corev1.SecurityContext {
145+
contextLogger := log.FromContext(ctx).WithName("lifecycle")
146+
147+
if archive != nil && archive.Spec.InstanceSidecarConfiguration.SecurityContext != nil {
148+
contextLogger.Info("Loading sidecar security context definition from the archive object.")
149+
return archive.Spec.InstanceSidecarConfiguration.SecurityContext
150+
}
151+
152+
contextLogger.Info("Security context definition not found in the archive object, using default (no restrictions).")
153+
return nil
154+
}
155+
141156
func (impl LifecycleImplementation) getArchives(
142157
ctx context.Context,
143158
namespace string,
@@ -223,8 +238,9 @@ func (impl LifecycleImplementation) reconcileJob(
223238
return nil, err
224239
}
225240
resources := impl.calculateSidecarResources(ctx, recoveryArchive)
241+
securityContext := impl.calculateSidecarSecurityContext(ctx, recoveryArchive)
226242

227-
return reconcileJob(ctx, cluster, request, env, resources)
243+
return reconcileJob(ctx, cluster, request, env, resources, securityContext)
228244
}
229245

230246
func reconcileJob(
@@ -233,6 +249,7 @@ func reconcileJob(
233249
request *lifecycle.OperatorLifecycleRequest,
234250
env []corev1.EnvVar,
235251
resources *corev1.ResourceRequirements,
252+
securityContext *corev1.SecurityContext,
236253
) (*lifecycle.OperatorLifecycleResponse, error) {
237254
contextLogger := log.FromContext(ctx).WithName("lifecycle")
238255
if pluginConfig := cluster.GetRecoverySourcePlugin(); pluginConfig == nil || pluginConfig.Name != metadata.PluginName {
@@ -268,7 +285,7 @@ func reconcileJob(
268285
corev1.Container{
269286
Args: []string{"restore"},
270287
},
271-
env, resources,
288+
env, resources, securityContext,
272289
); err != nil {
273290
return nil, fmt.Errorf("while reconciling pod spec for job: %w", err)
274291
}
@@ -299,8 +316,9 @@ func (impl LifecycleImplementation) reconcilePod(
299316
return nil, err
300317
}
301318
resources := impl.calculateSidecarResources(ctx, archive)
319+
securityContext := impl.calculateSidecarSecurityContext(ctx, archive)
302320

303-
return reconcilePod(ctx, cluster, request, pluginConfiguration, env, resources)
321+
return reconcilePod(ctx, cluster, request, pluginConfiguration, env, resources, securityContext)
304322
}
305323

306324
func reconcilePod(
@@ -310,6 +328,7 @@ func reconcilePod(
310328
pluginConfiguration *config.PluginConfiguration,
311329
env []corev1.EnvVar,
312330
resources *corev1.ResourceRequirements,
331+
securityContext *corev1.SecurityContext,
313332
) (*lifecycle.OperatorLifecycleResponse, error) {
314333
pod, err := decoder.DecodePodJSON(request.GetObjectDefinition())
315334
if err != nil {
@@ -329,7 +348,7 @@ func reconcilePod(
329348
corev1.Container{
330349
Args: []string{"instance"},
331350
},
332-
env, resources,
351+
env, resources, securityContext,
333352
); err != nil {
334353
return nil, fmt.Errorf("while reconciling pod spec for pod: %w", err)
335354
}
@@ -355,6 +374,7 @@ func reconcilePodSpec(
355374
sidecarConfig corev1.Container,
356375
additionalEnvs []corev1.EnvVar,
357376
resources *corev1.ResourceRequirements,
377+
securityContext *corev1.SecurityContext,
358378
) error {
359379
envs := []corev1.EnvVar{
360380
{
@@ -428,6 +448,10 @@ func reconcilePodSpec(
428448
sidecarConfig.Resources = *resources
429449
}
430450

451+
if securityContext != nil {
452+
sidecarConfig.SecurityContext = securityContext
453+
}
454+
431455
if err := InjectPluginSidecarPodSpec(spec, &sidecarConfig, mainContainerName, true); err != nil {
432456
return err
433457
}

0 commit comments

Comments
 (0)