mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-11-26 11:51:02 +00:00
Simple security context options (Kubernetes) (#2550)
This commit is contained in:
parent
ffb3bd806c
commit
3adb98b287
8 changed files with 298 additions and 72 deletions
|
@ -42,6 +42,10 @@ agent:
|
||||||
|
|
||||||
Additional annotations to apply to worker pods. Must be a YAML object, e.g. `{"example.com/test-annotation":"test-value"}`.
|
Additional annotations to apply to worker pods. Must be a YAML object, e.g. `{"example.com/test-annotation":"test-value"}`.
|
||||||
|
|
||||||
|
- `WOODPECKER_BACKEND_K8S_SECCTX_NONROOT` (default: `false`)
|
||||||
|
|
||||||
|
Determines if containers must be required to run as non-root users.
|
||||||
|
|
||||||
## Job specific configuration
|
## Job specific configuration
|
||||||
|
|
||||||
### Resources
|
### Resources
|
||||||
|
|
|
@ -57,6 +57,11 @@ var Flags = []cli.Flag{
|
||||||
Usage: "backend k8s additional worker pod annotations",
|
Usage: "backend k8s additional worker pod annotations",
|
||||||
Value: "",
|
Value: "",
|
||||||
},
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
EnvVars: []string{"WOODPECKER_BACKEND_K8S_SECCTX_NONROOT"},
|
||||||
|
Name: "backend-k8s-secctx-nonroot",
|
||||||
|
Usage: "`run as non root` Kubernetes security context option",
|
||||||
|
},
|
||||||
&cli.IntFlag{
|
&cli.IntFlag{
|
||||||
EnvVars: []string{"WOODPECKER_CONNECT_RETRY_COUNT"},
|
EnvVars: []string{"WOODPECKER_CONNECT_RETRY_COUNT"},
|
||||||
Name: "connect-retry-count",
|
Name: "connect-retry-count",
|
||||||
|
|
|
@ -61,6 +61,10 @@ type Config struct {
|
||||||
StorageRwx bool
|
StorageRwx bool
|
||||||
PodLabels map[string]string
|
PodLabels map[string]string
|
||||||
PodAnnotations map[string]string
|
PodAnnotations map[string]string
|
||||||
|
SecurityContext SecurityContextConfig
|
||||||
|
}
|
||||||
|
type SecurityContextConfig struct {
|
||||||
|
RunAsNonRoot bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func configFromCliContext(ctx context.Context) (*Config, error) {
|
func configFromCliContext(ctx context.Context) (*Config, error) {
|
||||||
|
@ -73,6 +77,9 @@ func configFromCliContext(ctx context.Context) (*Config, error) {
|
||||||
StorageRwx: c.Bool("backend-k8s-storage-rwx"),
|
StorageRwx: c.Bool("backend-k8s-storage-rwx"),
|
||||||
PodLabels: make(map[string]string), // just init empty map to prevent nil panic
|
PodLabels: make(map[string]string), // just init empty map to prevent nil panic
|
||||||
PodAnnotations: make(map[string]string), // just init empty map to prevent nil panic
|
PodAnnotations: make(map[string]string), // just init empty map to prevent nil panic
|
||||||
|
SecurityContext: SecurityContextConfig{
|
||||||
|
RunAsNonRoot: c.Bool("backend-k8s-secctx-nonroot"),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
// Unmarshal label and annotation settings here to ensure they're valid on startup
|
// Unmarshal label and annotation settings here to ensure they're valid on startup
|
||||||
if labels := c.String("backend-k8s-pod-labels"); labels != "" {
|
if labels := c.String("backend-k8s-pod-labels"); labels != "" {
|
||||||
|
@ -191,7 +198,7 @@ func (e *kube) SetupWorkflow(ctx context.Context, conf *types.Config, taskUUID s
|
||||||
|
|
||||||
// Start the pipeline step.
|
// Start the pipeline step.
|
||||||
func (e *kube) StartStep(ctx context.Context, step *types.Step, taskUUID string) error {
|
func (e *kube) StartStep(ctx context.Context, step *types.Step, taskUUID string) error {
|
||||||
pod, err := Pod(e.config.Namespace, step, e.config.PodLabels, e.config.PodAnnotations, e.goos)
|
pod, err := Pod(e.config.Namespace, step, e.config.PodLabels, e.config.PodAnnotations, e.goos, e.config.SecurityContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ import (
|
||||||
"go.woodpecker-ci.org/woodpecker/pipeline/backend/types"
|
"go.woodpecker-ci.org/woodpecker/pipeline/backend/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Pod(namespace string, step *types.Step, labels, annotations map[string]string, goos string) (*v1.Pod, error) {
|
func Pod(namespace string, step *types.Step, labels, annotations map[string]string, goos string, secCtxConf SecurityContextConfig) (*v1.Pod, error) {
|
||||||
var (
|
var (
|
||||||
vols []v1.Volume
|
vols []v1.Volume
|
||||||
volMounts []v1.VolumeMount
|
volMounts []v1.VolumeMount
|
||||||
|
@ -142,6 +142,11 @@ func Pod(namespace string, step *types.Step, labels, annotations map[string]stri
|
||||||
log.Trace().Msgf("Tolerations that will be used in the backend options: %v", beTolerations)
|
log.Trace().Msgf("Tolerations that will be used in the backend options: %v", beTolerations)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
beSecurityContext := step.BackendOptions.Kubernetes.SecurityContext
|
||||||
|
log.Trace().Interface("Security context", beSecurityContext).Msg("Security context that will be used for pods/containers")
|
||||||
|
podSecCtx := podSecurityContext(beSecurityContext, secCtxConf)
|
||||||
|
containerSecCtx := containerSecurityContext(beSecurityContext, step.Privileged)
|
||||||
|
|
||||||
pod := &v1.Pod{
|
pod := &v1.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: podName,
|
Name: podName,
|
||||||
|
@ -155,6 +160,7 @@ func Pod(namespace string, step *types.Step, labels, annotations map[string]stri
|
||||||
NodeSelector: nodeSelector,
|
NodeSelector: nodeSelector,
|
||||||
Tolerations: tolerations,
|
Tolerations: tolerations,
|
||||||
ServiceAccountName: serviceAccountName,
|
ServiceAccountName: serviceAccountName,
|
||||||
|
SecurityContext: podSecCtx,
|
||||||
Containers: []v1.Container{{
|
Containers: []v1.Container{{
|
||||||
Name: podName,
|
Name: podName,
|
||||||
Image: step.Image,
|
Image: step.Image,
|
||||||
|
@ -165,9 +171,7 @@ func Pod(namespace string, step *types.Step, labels, annotations map[string]stri
|
||||||
Env: mapToEnvVars(step.Environment),
|
Env: mapToEnvVars(step.Environment),
|
||||||
VolumeMounts: volMounts,
|
VolumeMounts: volMounts,
|
||||||
Resources: resourceRequirements,
|
Resources: resourceRequirements,
|
||||||
SecurityContext: &v1.SecurityContext{
|
SecurityContext: containerSecCtx,
|
||||||
Privileged: &step.Privileged,
|
|
||||||
},
|
|
||||||
}},
|
}},
|
||||||
ImagePullSecrets: []v1.LocalObjectReference{{Name: "regcred"}},
|
ImagePullSecrets: []v1.LocalObjectReference{{Name: "regcred"}},
|
||||||
Volumes: vols,
|
Volumes: vols,
|
||||||
|
@ -195,3 +199,55 @@ func volumeMountPath(i string) string {
|
||||||
}
|
}
|
||||||
return s[0]
|
return s[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func podSecurityContext(sc *types.SecurityContext, secCtxConf SecurityContextConfig) *v1.PodSecurityContext {
|
||||||
|
var (
|
||||||
|
nonRoot *bool
|
||||||
|
user *int64
|
||||||
|
group *int64
|
||||||
|
fsGroup *int64
|
||||||
|
)
|
||||||
|
|
||||||
|
if sc != nil && sc.RunAsNonRoot != nil {
|
||||||
|
if *sc.RunAsNonRoot {
|
||||||
|
nonRoot = sc.RunAsNonRoot // true
|
||||||
|
}
|
||||||
|
} else if secCtxConf.RunAsNonRoot {
|
||||||
|
nonRoot = &secCtxConf.RunAsNonRoot // true
|
||||||
|
}
|
||||||
|
|
||||||
|
if sc != nil {
|
||||||
|
user = sc.RunAsUser
|
||||||
|
group = sc.RunAsGroup
|
||||||
|
fsGroup = sc.FSGroup
|
||||||
|
}
|
||||||
|
|
||||||
|
if nonRoot == nil && user == nil && group == nil && fsGroup == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &v1.PodSecurityContext{
|
||||||
|
RunAsNonRoot: nonRoot,
|
||||||
|
RunAsUser: user,
|
||||||
|
RunAsGroup: group,
|
||||||
|
FSGroup: fsGroup,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func containerSecurityContext(sc *types.SecurityContext, stepPrivileged bool) *v1.SecurityContext {
|
||||||
|
var privileged *bool
|
||||||
|
|
||||||
|
if sc != nil && sc.Privileged != nil && *sc.Privileged {
|
||||||
|
privileged = sc.Privileged // true
|
||||||
|
} else if stepPrivileged {
|
||||||
|
privileged = &stepPrivileged // true
|
||||||
|
}
|
||||||
|
|
||||||
|
if privileged == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &v1.SecurityContext{
|
||||||
|
Privileged: privileged,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ type KubernetesBackendOptions struct {
|
||||||
ServiceAccountName string `json:"serviceAccountName,omitempty"`
|
ServiceAccountName string `json:"serviceAccountName,omitempty"`
|
||||||
NodeSelector map[string]string `json:"nodeSelector,omitempty"`
|
NodeSelector map[string]string `json:"nodeSelector,omitempty"`
|
||||||
Tolerations []Toleration `json:"tolerations,omitempty"`
|
Tolerations []Toleration `json:"tolerations,omitempty"`
|
||||||
|
SecurityContext *SecurityContext `json:"securityContext,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resources defines two maps for kubernetes resource definitions
|
// Resources defines two maps for kubernetes resource definitions
|
||||||
|
@ -51,3 +52,11 @@ const (
|
||||||
TolerationOpExists TolerationOperator = "Exists"
|
TolerationOpExists TolerationOperator = "Exists"
|
||||||
TolerationOpEqual TolerationOperator = "Equal"
|
TolerationOpEqual TolerationOperator = "Equal"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type SecurityContext struct {
|
||||||
|
Privileged *bool `json:"privileged,omitempty"`
|
||||||
|
RunAsNonRoot *bool `json:"runAsNonRoot,omitempty"`
|
||||||
|
RunAsUser *int64 `json:"runAsUser,omitempty"`
|
||||||
|
RunAsGroup *int64 `json:"runAsGroup,omitempty"`
|
||||||
|
FSGroup *int64 `json:"fsGroup,omitempty"`
|
||||||
|
}
|
||||||
|
|
|
@ -116,28 +116,9 @@ func (c *Compiler) createProcess(name string, container *yaml_types.Container, s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var tolerations []backend_types.Toleration
|
// Advanced backend settings
|
||||||
for _, t := range container.BackendOptions.Kubernetes.Tolerations {
|
|
||||||
tolerations = append(tolerations, backend_types.Toleration{
|
|
||||||
Key: t.Key,
|
|
||||||
Operator: backend_types.TolerationOperator(t.Operator),
|
|
||||||
Value: t.Value,
|
|
||||||
Effect: backend_types.TaintEffect(t.Effect),
|
|
||||||
TolerationSeconds: t.TolerationSeconds,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Kubernetes advanced settings
|
|
||||||
backendOptions := backend_types.BackendOptions{
|
backendOptions := backend_types.BackendOptions{
|
||||||
Kubernetes: backend_types.KubernetesBackendOptions{
|
Kubernetes: convertKubernetesBackendOptions(&container.BackendOptions.Kubernetes),
|
||||||
Resources: backend_types.Resources{
|
|
||||||
Limits: container.BackendOptions.Kubernetes.Resources.Limits,
|
|
||||||
Requests: container.BackendOptions.Kubernetes.Resources.Requests,
|
|
||||||
},
|
|
||||||
ServiceAccountName: container.BackendOptions.Kubernetes.ServiceAccountName,
|
|
||||||
NodeSelector: container.BackendOptions.Kubernetes.NodeSelector,
|
|
||||||
Tolerations: tolerations,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
memSwapLimit := int64(container.MemSwapLimit)
|
memSwapLimit := int64(container.MemSwapLimit)
|
||||||
|
@ -223,3 +204,40 @@ func (c *Compiler) stepWorkdir(container *yaml_types.Container) string {
|
||||||
}
|
}
|
||||||
return path.Join(c.base, c.path, container.Directory)
|
return path.Join(c.base, c.path, container.Directory)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func convertKubernetesBackendOptions(kubeOpt *yaml_types.KubernetesBackendOptions) backend_types.KubernetesBackendOptions {
|
||||||
|
resources := backend_types.Resources{
|
||||||
|
Limits: kubeOpt.Resources.Limits,
|
||||||
|
Requests: kubeOpt.Resources.Requests,
|
||||||
|
}
|
||||||
|
|
||||||
|
var tolerations []backend_types.Toleration
|
||||||
|
for _, t := range kubeOpt.Tolerations {
|
||||||
|
tolerations = append(tolerations, backend_types.Toleration{
|
||||||
|
Key: t.Key,
|
||||||
|
Operator: backend_types.TolerationOperator(t.Operator),
|
||||||
|
Value: t.Value,
|
||||||
|
Effect: backend_types.TaintEffect(t.Effect),
|
||||||
|
TolerationSeconds: t.TolerationSeconds,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
var securityContext *backend_types.SecurityContext
|
||||||
|
if kubeOpt.SecurityContext != nil {
|
||||||
|
securityContext = &backend_types.SecurityContext{
|
||||||
|
Privileged: kubeOpt.SecurityContext.Privileged,
|
||||||
|
RunAsNonRoot: kubeOpt.SecurityContext.RunAsNonRoot,
|
||||||
|
RunAsUser: kubeOpt.SecurityContext.RunAsUser,
|
||||||
|
RunAsGroup: kubeOpt.SecurityContext.RunAsGroup,
|
||||||
|
FSGroup: kubeOpt.SecurityContext.FSGroup,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return backend_types.KubernetesBackendOptions{
|
||||||
|
Resources: resources,
|
||||||
|
ServiceAccountName: kubeOpt.ServiceAccountName,
|
||||||
|
NodeSelector: kubeOpt.NodeSelector,
|
||||||
|
Tolerations: tolerations,
|
||||||
|
SecurityContext: securityContext,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -14,28 +14,58 @@
|
||||||
"variables": {
|
"variables": {
|
||||||
"description": "Use yaml aliases to define variables. Read more: https://woodpecker-ci.org/docs/usage/advanced-yaml-syntax"
|
"description": "Use yaml aliases to define variables. Read more: https://woodpecker-ci.org/docs/usage/advanced-yaml-syntax"
|
||||||
},
|
},
|
||||||
"clone": { "$ref": "#/definitions/clone" },
|
"clone": {
|
||||||
"skip_clone": { "type": "boolean" },
|
"$ref": "#/definitions/clone"
|
||||||
"branches": { "$ref": "#/definitions/branches" },
|
},
|
||||||
"when": { "$ref": "#/definitions/pipeline_when" },
|
"skip_clone": {
|
||||||
"steps": { "$ref": "#/definitions/step_list" },
|
"type": "boolean"
|
||||||
"pipeline": { "$ref": "#/definitions/step_list", "description": "deprecated, use steps" },
|
},
|
||||||
"services": { "$ref": "#/definitions/services" },
|
"branches": {
|
||||||
"workspace": { "$ref": "#/definitions/workspace" },
|
"$ref": "#/definitions/branches"
|
||||||
"matrix": { "$ref": "#/definitions/matrix" },
|
},
|
||||||
"platform": { "$ref": "#/definitions/platform" },
|
"when": {
|
||||||
"labels": { "$ref": "#/definitions/labels" },
|
"$ref": "#/definitions/pipeline_when"
|
||||||
|
},
|
||||||
|
"steps": {
|
||||||
|
"$ref": "#/definitions/step_list"
|
||||||
|
},
|
||||||
|
"pipeline": {
|
||||||
|
"$ref": "#/definitions/step_list",
|
||||||
|
"description": "deprecated, use steps"
|
||||||
|
},
|
||||||
|
"services": {
|
||||||
|
"$ref": "#/definitions/services"
|
||||||
|
},
|
||||||
|
"workspace": {
|
||||||
|
"$ref": "#/definitions/workspace"
|
||||||
|
},
|
||||||
|
"matrix": {
|
||||||
|
"$ref": "#/definitions/matrix"
|
||||||
|
},
|
||||||
|
"platform": {
|
||||||
|
"$ref": "#/definitions/platform"
|
||||||
|
},
|
||||||
|
"labels": {
|
||||||
|
"$ref": "#/definitions/labels"
|
||||||
|
},
|
||||||
"depends_on": {
|
"depends_on": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"minLength": 1,
|
"minLength": 1,
|
||||||
"items": { "type": "string" }
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"runs_on": {
|
"runs_on": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"minLength": 1,
|
"minLength": 1,
|
||||||
"items": { "type": "string" }
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"version": { "type": "number", "default": 1 }
|
"version": {
|
||||||
|
"type": "number",
|
||||||
|
"default": 1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"definitions": {
|
"definitions": {
|
||||||
"clone": {
|
"clone": {
|
||||||
|
@ -74,20 +104,28 @@
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
{
|
{
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": { "type": "string" },
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"minLength": 1
|
"minLength": 1
|
||||||
},
|
},
|
||||||
{ "type": "string" }
|
{
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"include": {
|
"include": {
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
{
|
{
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": { "type": "string" },
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"minLength": 1
|
"minLength": 1
|
||||||
},
|
},
|
||||||
{ "type": "string" }
|
{
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,8 +135,20 @@
|
||||||
"step_list": {
|
"step_list": {
|
||||||
"description": "The steps section defines a list of steps which will be executed serially, in the order in which they are defined. Read more: https://woodpecker-ci.org/docs/usage/pipeline-syntax",
|
"description": "The steps section defines a list of steps which will be executed serially, in the order in which they are defined. Read more: https://woodpecker-ci.org/docs/usage/pipeline-syntax",
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
{ "type": "object", "additionalProperties": { "$ref": "#/definitions/step" }, "minProperties": 1 },
|
{
|
||||||
{ "type": "array", "items": { "$ref": "#/definitions/step" }, "minLength": 1 }
|
"type": "object",
|
||||||
|
"additionalProperties": {
|
||||||
|
"$ref": "#/definitions/step"
|
||||||
|
},
|
||||||
|
"minProperties": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/step"
|
||||||
|
},
|
||||||
|
"minLength": 1
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"pipeline_when": {
|
"pipeline_when": {
|
||||||
|
@ -107,7 +157,9 @@
|
||||||
{
|
{
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"minLength": 1,
|
"minLength": 1,
|
||||||
"items": { "$ref": "#/definitions/pipeline_when_condition" }
|
"items": {
|
||||||
|
"$ref": "#/definitions/pipeline_when_condition"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"$ref": "#/definitions/pipeline_when_condition"
|
"$ref": "#/definitions/pipeline_when_condition"
|
||||||
|
@ -133,7 +185,9 @@
|
||||||
{
|
{
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"minLength": 1,
|
"minLength": 1,
|
||||||
"items": { "$ref": "#/definitions/event_enum" }
|
"items": {
|
||||||
|
"$ref": "#/definitions/event_enum"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"$ref": "#/definitions/event_enum"
|
"$ref": "#/definitions/event_enum"
|
||||||
|
@ -163,7 +217,9 @@
|
||||||
"path": {
|
"path": {
|
||||||
"description": "Execute a step only on commit with certain files added/removed/modified. Read more: https://woodpecker-ci.org/docs/usage/pipeline-syntax#path",
|
"description": "Execute a step only on commit with certain files added/removed/modified. Read more: https://woodpecker-ci.org/docs/usage/pipeline-syntax#path",
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
{ "type": "string" },
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
|
@ -264,7 +320,9 @@
|
||||||
{
|
{
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"minLength": 1,
|
"minLength": 1,
|
||||||
"items": { "$ref": "#/definitions/step_when_condition" }
|
"items": {
|
||||||
|
"$ref": "#/definitions/step_when_condition"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"$ref": "#/definitions/step_when_condition"
|
"$ref": "#/definitions/step_when_condition"
|
||||||
|
@ -290,7 +348,9 @@
|
||||||
{
|
{
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"minLength": 1,
|
"minLength": 1,
|
||||||
"items": { "$ref": "#/definitions/event_enum" }
|
"items": {
|
||||||
|
"$ref": "#/definitions/event_enum"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"$ref": "#/definitions/event_enum"
|
"$ref": "#/definitions/event_enum"
|
||||||
|
@ -311,7 +371,10 @@
|
||||||
{
|
{
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"minLength": 1,
|
"minLength": 1,
|
||||||
"items": { "type": "string", "enum": ["success", "failure"] }
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["success", "failure"]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
@ -341,7 +404,9 @@
|
||||||
"path": {
|
"path": {
|
||||||
"description": "Execute a step only on commit with certain files added/removed/modified. Read more: https://woodpecker-ci.org/docs/usage/pipeline-syntax#path",
|
"description": "Execute a step only on commit with certain files added/removed/modified. Read more: https://woodpecker-ci.org/docs/usage/pipeline-syntax#path",
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
{ "type": "string" },
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
|
@ -388,7 +453,9 @@
|
||||||
{
|
{
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"minLength": 1,
|
"minLength": 1,
|
||||||
"items": { "type": "string" }
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
@ -402,7 +469,9 @@
|
||||||
{
|
{
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"minLength": 1,
|
"minLength": 1,
|
||||||
"items": { "type": "string" }
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -414,7 +483,9 @@
|
||||||
{
|
{
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"minLength": 1,
|
"minLength": 1,
|
||||||
"items": { "type": "string" }
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -440,10 +511,14 @@
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
{
|
{
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": { "type": "string" },
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"minLength": 1
|
"minLength": 1
|
||||||
},
|
},
|
||||||
{ "type": "string" }
|
{
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"step_environment": {
|
"step_environment": {
|
||||||
|
@ -451,7 +526,9 @@
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
{
|
{
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": { "type": "string" },
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"minLength": 1
|
"minLength": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -467,13 +544,19 @@
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
{ "type": "string" },
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": ["source", "target"],
|
"required": ["source", "target"],
|
||||||
"properties": {
|
"properties": {
|
||||||
"source": { "type": "string" },
|
"source": {
|
||||||
"target": { "type": "string" }
|
"type": "string"
|
||||||
|
},
|
||||||
|
"target": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -490,7 +573,9 @@
|
||||||
"step_volumes": {
|
"step_volumes": {
|
||||||
"description": "Mount files or folders from the host machine into your step container. Read more: https://woodpecker-ci.org/docs/usage/volumes",
|
"description": "Mount files or folders from the host machine into your step container. Read more: https://woodpecker-ci.org/docs/usage/volumes",
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": { "type": "string" },
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"minLength": 1
|
"minLength": 1
|
||||||
},
|
},
|
||||||
"step_directory": {
|
"step_directory": {
|
||||||
|
@ -502,7 +587,7 @@
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"kubernetes": {
|
"kubernetes": {
|
||||||
"$ref": "#/definitions/step_backend_kubernetes_resources"
|
"$ref": "#/definitions/step_backend_kubernetes"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -512,6 +597,9 @@
|
||||||
"properties": {
|
"properties": {
|
||||||
"resources": {
|
"resources": {
|
||||||
"$ref": "#/definitions/step_backend_kubernetes_resources"
|
"$ref": "#/definitions/step_backend_kubernetes_resources"
|
||||||
|
},
|
||||||
|
"securityContext": {
|
||||||
|
"$ref": "#/definitions/step_backend_kubernetes_security_context"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -527,6 +615,27 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"step_backend_kubernetes_security_context": {
|
||||||
|
"description": "Pods / containers security context. Read more: https://woodpecker-ci.org/docs/administration/backends/kubernetes",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"privileged": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"runAsNonRoot": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"runAsUser": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"runAsGroup": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"fsGroup": {
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"step_kubernetes_resources_object": {
|
"step_kubernetes_resources_object": {
|
||||||
"description": "A list of kubernetes resource mappings",
|
"description": "A list of kubernetes resource mappings",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
@ -556,7 +665,9 @@
|
||||||
"services": {
|
"services": {
|
||||||
"description": "Read more: https://woodpecker-ci.org/docs/usage/services",
|
"description": "Read more: https://woodpecker-ci.org/docs/usage/services",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"additionalProperties": { "$ref": "#/definitions/service" },
|
"additionalProperties": {
|
||||||
|
"$ref": "#/definitions/service"
|
||||||
|
},
|
||||||
"minProperties": 1
|
"minProperties": 1
|
||||||
},
|
},
|
||||||
"service": {
|
"service": {
|
||||||
|
@ -597,7 +708,14 @@
|
||||||
"description": "expose ports to which other steps can connect to",
|
"description": "expose ports to which other steps can connect to",
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"oneOf": [{ "type": "number" }, { "type": "string" }]
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"minLength": 1
|
"minLength": 1
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ type KubernetesBackendOptions struct {
|
||||||
ServiceAccountName string `yaml:"serviceAccountName,omitempty"`
|
ServiceAccountName string `yaml:"serviceAccountName,omitempty"`
|
||||||
NodeSelector map[string]string `yaml:"nodeSelector,omitempty"`
|
NodeSelector map[string]string `yaml:"nodeSelector,omitempty"`
|
||||||
Tolerations []Toleration `yaml:"tolerations,omitempty"`
|
Tolerations []Toleration `yaml:"tolerations,omitempty"`
|
||||||
|
SecurityContext *SecurityContext `yaml:"securityContext,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Resources struct {
|
type Resources struct {
|
||||||
|
@ -53,3 +54,11 @@ const (
|
||||||
TolerationOpExists TolerationOperator = "Exists"
|
TolerationOpExists TolerationOperator = "Exists"
|
||||||
TolerationOpEqual TolerationOperator = "Equal"
|
TolerationOpEqual TolerationOperator = "Equal"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type SecurityContext struct {
|
||||||
|
Privileged *bool `yaml:"privileged,omitempty"`
|
||||||
|
RunAsNonRoot *bool `yaml:"runAsNonRoot,omitempty"`
|
||||||
|
RunAsUser *int64 `yaml:"runAsUser,omitempty"`
|
||||||
|
RunAsGroup *int64 `yaml:"runAsGroup,omitempty"`
|
||||||
|
FSGroup *int64 `yaml:"fsGroup,omitempty"`
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue