Skip to content
Draft
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
3 changes: 2 additions & 1 deletion docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ The following environment variables are available:
| `GIT_CONTAINER_IMAGE` | Custom container image for Git clone steps. If `GIT_CONTAINER_TEMPLATE` is also specifying an image, then the value for `GIT_CONTAINER_IMAGE` has precedence. |
| `BUNDLE_CONTAINER_TEMPLATE` | JSON representation of a [Container] template that is used for steps that pulls a bundle image to obtain the packaged source code. Default is `{"image": "ghcr.io/shipwright-io/build/bundle:latest", "command": ["/ko-app/bundle"], "env": [{"name": "HOME","value": "/shared-home"},{"name": "BUNDLE_SHOW_LISTING","value": "false"}], "securityContext":{"allowPrivilegeEscalation": false, "capabilities": {"drop": ["ALL"]}, "runAsUser":1000,"runAsGroup":1000}}` [^1]. The following properties are ignored as they are set by the controller: `args`, `name`. |
| `BUNDLE_CONTAINER_IMAGE` | Custom container image that pulls a bundle image to obtain the packaged source code. If `BUNDLE_IMAGE_CONTAINER_TEMPLATE` is also specifying an image, then the value for `BUNDLE_IMAGE_CONTAINER_IMAGE` has precedence. |
| `IMAGE_PROCESSING_CONTAINER_TEMPLATE` | JSON representation of a [Container](https://pkg.go.dev/k8s.io/api/core/v1#Container) template that is used for steps that processes the image. Default is `{"image": "ghcr.io/shipwright-io/build/image-processing:latest", "command": ["/ko-app/image-processing"], "env": [{"name": "HOME","value": "/shared-home"}], "securityContext": {"allowPrivilegeEscalation": false, "capabilities": {"add": ["DAC_OVERRIDE"], "drop": ["ALL"]}, "runAsUser": 0, "runAsgGroup": 0}}`. The following properties are ignored as they are set by the controller: `args`, `name`. |
| `IMAGE_PROCESSING_CONTAINER_TEMPLATE` | JSON representation of a [Container](https://pkg.go.dev/k8s.io/api/core/v1#Container) template that is used for steps that processes the image. Default is `{"image": "ghcr.io/shipwright-io/build/image-processing:latest", "command": ["/ko-app/image-processing"], "env": [{"name": "HOME","value": "/shared-home"}, {"name": "TRIVY_CACHE_DIR", "value": "/trivy-cache-data/trivy-cache"}], "securityContext": {"allowPrivilegeEscalation": false, "capabilities": {"add": ["DAC_OVERRIDE"], "drop": ["ALL"]}, "runAsUser": 0, "runAsGroup": 0}}`. The following properties are ignored as they are set by the controller: `args`, `name`. |
| `IMAGE_PROCESSING_CONTAINER_IMAGE` | Custom container image that is used for steps that processes the image. If `IMAGE_PROCESSING_CONTAINER_TEMPLATE` is also specifying an image, then the value for `IMAGE_PROCESSING_CONTAINER_IMAGE` has precedence. |
| `WAITER_CONTAINER_TEMPLATE` | JSON representation of a [Container] template that waits for local source code to be uploaded to it. Default is `{"image":"ghcr.io/shipwright-io/build/waiter:latest", "command": ["/ko-app/waiter"], "args": ["start"], "env": [{"name": "HOME","value": "/shared-home"}], "securityContext":{"allowPrivilegeEscalation": false, "capabilities": {"drop": ["ALL"]}, "runAsUser":1000,"runAsGroup":1000}}`. The following properties are ignored as they are set by the controller: `args`, `name`. |
| `WAITER_CONTAINER_IMAGE` | Custom container image that waits for local source code to be uploaded to it. If `WAITER_IMAGE_CONTAINER_TEMPLATE` is also specifying an image, then the value for `WAITER_IMAGE_CONTAINER_IMAGE` has precedence. |
Expand All @@ -37,6 +37,7 @@ The following environment variables are available:
| `KUBE_API_BURST` | Burst to use for the Kubernetes API client. See [Config.Burst]. A value of 0 or lower will use the default from client-go, which currently is 10. Default is 0. |
| `KUBE_API_QPS` | QPS to use for the Kubernetes API client. See [Config.QPS]. A value of 0 or lower will use the default from client-go, which currently is 5. Default is 0. |
| `VULNERABILITY_COUNT_LIMIT` | holds vulnerability count limit if vulnerability scan is enabled for the output image. If it is defined as 10, then it will output only 10 vulnerabilities sorted by severity in the buildrun status.Output. Default is 50. |
| `WRITABLE_HOME_DIR` | Specifies the mount path for writable home directories in build containers. Each container gets its own isolated emptyDir volume mounted at this path, enabling write operations when `readOnlyRootFilesystem: true` is used. Default is `/writable-home`. |

[^1]: The `runAsUser` and `runAsGroup` are dynamically overwritten depending on the build strategy that is used. See [Security Contexts](buildstrategies.md#security-contexts) for more information.

Expand Down
69 changes: 54 additions & 15 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,17 @@

// environment variable to hold vulnerability count limit
VulnerabilityCountLimitEnvVar = "VULNERABILITY_COUNT_LIMIT"

// Trivy related environment variables
trivyCacheDirEnvVar = "TRIVY_CACHE_DIR"

Check failure on line 84 in pkg/config/config.go

View workflow job for this annotation

GitHub Actions / Verify

const `trivyCacheDirEnvVar` is unused (unused)
// Default paths for Trivy
defaultTrivyCacheDir = "/trivy-cache-data/trivy-cache"

// Default writable home directory path inside containers
// Note: Each container gets its own isolated emptyDir volume mounted at this path
// The actual volume names are unique per container (e.g., shp-writable-home-step-name)
defaultWritableHomeDir = "/writable-home"
writableHomeDirEnvVar = "WRITABLE_HOME_DIR"
)

var (
Expand Down Expand Up @@ -107,6 +118,14 @@
KubeAPIOptions KubeAPIOptions
GitRewriteRule bool
VulnerabilityCountLimit int
ContainersWritableDir WritableDirsConfig
}

type WritableDirsConfig struct {
TrivyCacheDir string
// WritableHomeDir is the path where each container's writable home directory is mounted
// Each container gets its own isolated emptyDir volume at this mount path
WritableHomeDir string
}

// PrometheusConfig contains the specific configuration for the
Expand Down Expand Up @@ -163,22 +182,28 @@
TerminationLogPath: terminationLogPathDefault,
GitRewriteRule: false,
VulnerabilityCountLimit: 50,

ContainersWritableDir: WritableDirsConfig{
TrivyCacheDir: defaultTrivyCacheDir,
WritableHomeDir: defaultWritableHomeDir,
},
GitContainerTemplate: Step{
Image: gitDefaultImage,
Command: []string{
"/ko-app/git",
},
Env: []corev1.EnvVar{
// This directory is created in the base image as writable for everybody
{
Name: "HOME",
Value: "/shared-home",
Value: defaultWritableHomeDir,
},
{
Name: "GIT_SHOW_LISTING",
Value: "false",
},
{
Name: "TMPDIR",
Value: "/tmp",
},
},
SecurityContext: &corev1.SecurityContext{
AllowPrivilegeEscalation: ptr.To(false),
Expand All @@ -187,8 +212,9 @@
"ALL",
},
},
RunAsUser: nonRoot,
RunAsGroup: nonRoot,
RunAsUser: nonRoot,
RunAsGroup: nonRoot,
ReadOnlyRootFilesystem: ptr.To(true),
},
},

Expand All @@ -197,11 +223,10 @@
Command: []string{
"/ko-app/bundle",
},
// This directory is created in the base image as writable for everybody
Env: []corev1.EnvVar{
{
Name: "HOME",
Value: "/shared-home",
Value: defaultWritableHomeDir,
},
{
Name: "BUNDLE_SHOW_LISTING",
Expand All @@ -215,8 +240,9 @@
"ALL",
},
},
RunAsUser: nonRoot,
RunAsGroup: nonRoot,
RunAsUser: nonRoot,
RunAsGroup: nonRoot,
ReadOnlyRootFilesystem: ptr.To(true),
},
},

Expand All @@ -225,11 +251,10 @@
Command: []string{
"/ko-app/image-processing",
},
// This directory is created in the base image as writable for everybody
Env: []corev1.EnvVar{
{
Name: "HOME",
Value: "/shared-home",
Value: defaultWritableHomeDir,
},
},
// The image processing step runs after the build strategy steps where an arbitrary
Expand All @@ -241,6 +266,7 @@
AllowPrivilegeEscalation: ptr.To(false),
RunAsUser: root,
RunAsGroup: root,
ReadOnlyRootFilesystem: ptr.To(true),
Capabilities: &corev1.Capabilities{
Add: []corev1.Capability{
"DAC_OVERRIDE",
Expand All @@ -260,11 +286,10 @@
Args: []string{
"start",
},
// This directory is created in the base image as writable for everybody
Env: []corev1.EnvVar{
{
Name: "HOME",
Value: "/shared-home",
Value: defaultWritableHomeDir,
},
},
SecurityContext: &corev1.SecurityContext{
Expand All @@ -274,8 +299,9 @@
"ALL",
},
},
RunAsUser: nonRoot,
RunAsGroup: nonRoot,
RunAsUser: nonRoot,
RunAsGroup: nonRoot,
ReadOnlyRootFilesystem: ptr.To(true),
},
},

Expand Down Expand Up @@ -455,6 +481,11 @@
c.TerminationLogPath = terminationLogPath
}

// Update writable directory paths if environment variables are set
if err := updateWritableDirOption(&c.ContainersWritableDir.WritableHomeDir, writableHomeDirEnvVar); err != nil {
return err
}

return nil
}

Expand Down Expand Up @@ -509,3 +540,11 @@

return nil
}

// updateWritableDirOption updates the writable directory paths if the environment variable is set
func updateWritableDirOption(path *string, envVarName string) error {
if value := os.Getenv(envVarName); value != "" {
*path = value
}
return nil
}
18 changes: 12 additions & 6 deletions pkg/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,12 @@ var _ = Describe("Config", func() {
"/ko-app/git",
},
Env: []corev1.EnvVar{
{Name: "HOME", Value: "/shared-home"},
{Name: "HOME", Value: "/writable-home"},
{Name: "GIT_SHOW_LISTING", Value: "false"},
{
Name: "TMPDIR",
Value: "/tmp",
},
},
SecurityContext: &corev1.SecurityContext{
AllowPrivilegeEscalation: ptr.To(false),
Expand All @@ -142,8 +146,9 @@ var _ = Describe("Config", func() {
"ALL",
},
},
RunAsUser: nonRoot,
RunAsGroup: nonRoot,
RunAsUser: nonRoot,
RunAsGroup: nonRoot,
ReadOnlyRootFilesystem: ptr.To(true),
},
}))
})
Expand Down Expand Up @@ -235,16 +240,17 @@ var _ = Describe("Config", func() {
Image: "myregistry/custom/image",
Command: []string{"/ko-app/waiter"},
Args: []string{"start"},
Env: []corev1.EnvVar{{Name: "HOME", Value: "/shared-home"}},
Env: []corev1.EnvVar{{Name: "HOME", Value: "/writable-home"}},
SecurityContext: &corev1.SecurityContext{
AllowPrivilegeEscalation: ptr.To(false),
Capabilities: &corev1.Capabilities{
Drop: []corev1.Capability{
"ALL",
},
},
RunAsUser: nonRoot,
RunAsGroup: nonRoot,
RunAsUser: nonRoot,
RunAsGroup: nonRoot,
ReadOnlyRootFilesystem: ptr.To(true),
},
}))
})
Expand Down
18 changes: 17 additions & 1 deletion pkg/reconciler/buildrun/resources/image_processing.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,6 @@ func SetupImageProcessing(taskRun *pipelineapi.TaskRun, cfg *config.Config, crea
SecurityContext: cfg.ImageProcessingContainerTemplate.SecurityContext,
WorkingDir: cfg.ImageProcessingContainerTemplate.WorkingDir,
}

if volumeAdded {
imageProcessingStep.VolumeMounts = append(imageProcessingStep.VolumeMounts, core.VolumeMount{
Name: prefixedOutputDirectory,
Expand All @@ -201,6 +200,23 @@ func SetupImageProcessing(taskRun *pipelineapi.TaskRun, cfg *config.Config, crea
)
}

sources.AppendWriteableVolumes(taskRun.Spec.TaskSpec, &imageProcessingStep, cfg.ContainersWritableDir.WritableHomeDir)

taskRun.Spec.TaskSpec.Volumes = append(taskRun.Spec.TaskSpec.Volumes, core.Volume{
Name: "trivy-cache-data",
VolumeSource: core.VolumeSource{
EmptyDir: &core.EmptyDirVolumeSource{},
},
})
imageProcessingStep.VolumeMounts = append(imageProcessingStep.VolumeMounts, core.VolumeMount{
Name: "trivy-cache-data",
MountPath: cfg.ContainersWritableDir.TrivyCacheDir,
})

imageProcessingStep.Env = append(imageProcessingStep.Env, core.EnvVar{
Name: "TRIVY_CACHE_DIR",
Value: cfg.ContainersWritableDir.TrivyCacheDir,
})
// append the mutate step
taskRun.Spec.TaskSpec.Steps = append(taskRun.Spec.TaskSpec.Steps, imageProcessingStep)
}
Expand Down
1 change: 1 addition & 0 deletions pkg/reconciler/buildrun/resources/sources/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ func AppendBundleStep(cfg *config.Config, taskSpec *pipelineapi.TaskSpec, oci *b
bundleStep.Args = append(bundleStep.Args, "--prune")
}

AppendWriteableVolumes(taskSpec, &bundleStep, cfg.ContainersWritableDir.WritableHomeDir)
taskSpec.Steps = append(taskSpec.Steps, bundleStep)
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/reconciler/buildrun/resources/sources/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ func AppendGitStep(
secretMountPath,
)
}

AppendWriteableVolumes(taskSpec, &gitStep, cfg.ContainersWritableDir.WritableHomeDir)
// append the git step
taskSpec.Steps = append(taskSpec.Steps, gitStep)
}
Expand Down
8 changes: 4 additions & 4 deletions pkg/reconciler/buildrun/resources/sources/git_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ var _ = Describe("Git", func() {
})

It("adds a volume for the secret", func() {
Expect(len(taskSpec.Volumes)).To(Equal(1))
Expect(len(taskSpec.Volumes)).To(Equal(3))
Expect(taskSpec.Volumes[0].Name).To(Equal("shp-a-secret"))
Expect(taskSpec.Volumes[0].VolumeSource.Secret).NotTo(BeNil())
Expect(taskSpec.Volumes[0].VolumeSource.Secret.SecretName).To(Equal("a.secret"))
Expand All @@ -100,7 +100,7 @@ var _ = Describe("Git", func() {
"--result-file-source-timestamp", "$(results.shp-source-default-source-timestamp.path)",
"--secret-path", "/workspace/shp-source-secret",
}))
Expect(len(taskSpec.Steps[0].VolumeMounts)).To(Equal(1))
Expect(len(taskSpec.Steps[0].VolumeMounts)).To(Equal(3))
Expect(taskSpec.Steps[0].VolumeMounts[0].Name).To(Equal("shp-a-secret"))
Expect(taskSpec.Steps[0].VolumeMounts[0].MountPath).To(Equal("/workspace/shp-source-secret"))
Expect(taskSpec.Steps[0].VolumeMounts[0].ReadOnly).To(BeTrue())
Expand Down Expand Up @@ -188,7 +188,7 @@ var _ = Describe("Git", func() {
Revision: ptr.To(revision),
CloneSecret: ptr.To("another.secret"),
}, "default")

Expect(len(taskSpec.Steps)).To(Equal(1))
Expect(taskSpec.Steps[0].Args).To(ContainElements(
"--url", "https://github.com/shipwright-io/another-repo",
Expand All @@ -200,4 +200,4 @@ var _ = Describe("Git", func() {
Expect(taskSpec.Steps[0].VolumeMounts).To(ContainElement(HaveField("Name", "shp-another-secret")))
})
})
})
})
1 change: 1 addition & 0 deletions pkg/reconciler/buildrun/resources/sources/local_copy.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ func AppendLocalCopyStep(cfg *config.Config, taskSpec *pipelineapi.TaskSpec, tim
WorkingDir: cfg.WaiterContainerTemplate.WorkingDir,
}

AppendWriteableVolumes(taskSpec, &step, cfg.ContainersWritableDir.WritableHomeDir)
if timeout != nil {
step.Args = append(step.Args, fmt.Sprintf("--timeout=%s", timeout.Duration.String()))
}
Expand Down
Loading
Loading