Feat: Add corporate certificates to Build APIs#2107
Feat: Add corporate certificates to Build APIs#2107sayan-biswas wants to merge 1 commit intoshipwright-io:mainfrom
Conversation
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
fe07158 to
b4af1ae
Compare
|
/retest |
There was a problem hiding this comment.
Pull request overview
This PR adds support for corporate/custom Root CA certificates to the Build and BuildRun APIs. The feature allows users to specify CA bundles via Secret or ConfigMap references at both the Build and BuildRun levels, with the BuildRun specification taking precedence. The certificates are mounted into workload containers and relevant environment variables are configured.
Changes:
- Added CA bundle API types (
CABundle,SourceObjectKeySelector) for Build/BuildRun specifications - Implemented CA bundle validation logic in the validate package
- Implemented CA bundle volume and environment variable injection for TaskRun/PipelineRun execution
- Added CA bundle parameter definitions to task specifications
- Enhanced error handling in
taskrun_generator.goto properly check errors from called functions
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| pkg/apis/build/v1beta1/cabundle.go | New API types for CA bundle references |
| pkg/apis/build/v1beta1/build_types.go | Added CABundle field to BuildSpec and new BuildReason constant |
| pkg/apis/build/v1beta1/buildrun_types.go | Added CABundle field to BuildRunSpec |
| pkg/cabundle/cabundle.go | Core CA bundle validation and volume/environment variable generation |
| pkg/cabundle/cabundle_test.go | Comprehensive tests for CA bundle handling |
| pkg/cabundle/suite_test.go | Test suite setup |
| pkg/validate/cabundle.go | Validation logic for Build CA bundle references |
| pkg/validate/validate.go | Added Certificates constant and validation case |
| pkg/reconciler/buildrun/resources/cabundle.go | TaskRun/PipelineRun certificate injection |
| pkg/reconciler/buildrun/resources/taskrun.go | Added paramCABundle constant |
| pkg/reconciler/buildrun/resources/resource_builders.go | CA bundle parameter specifications and values |
| pkg/reconciler/buildrun/resources/taskrun_generator.go | Enhanced error handling and certificate injection |
| pkg/reconciler/buildrun/buildrun.go | Added CA bundle validation to reconciliation |
| deploy/crds/shipwright.io_builds.yaml | Updated Build CRD |
| deploy/crds/shipwright.io_buildruns.yaml | Updated BuildRun CRD |
| test/utils/v1beta1/pipelinerun.go | Added copyright header |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
b4af1ae to
5da79ab
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 16 out of 16 changed files in this pull request and generated 6 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
5da79ab to
8df886b
Compare
8df886b to
584410e
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 15 out of 15 changed files in this pull request and generated 12 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
584410e to
eea9bd4
Compare
57586d0 to
e912647
Compare
avinal
left a comment
There was a problem hiding this comment.
In my testing, builds using TaskRuns ran successfully, but builds using PipelineRuns failed due to nil pointer error.
Apart from that, it seems deepcopygen was not rerun.
| if pipelineRun != nil { | ||
| pipelineRun.Spec.TaskRunTemplate.PodTemplate.Volumes = append(pipelineRun.Spec.TaskRunTemplate.PodTemplate.Volumes, *volume) | ||
| for _, e := range envVar { | ||
| if !hasEnvVarByName(pipelineRun.Spec.TaskRunTemplate.PodTemplate.Env, e.Name) { | ||
| pipelineRun.Spec.TaskRunTemplate.PodTemplate.Env = append(pipelineRun.Spec.TaskRunTemplate.PodTemplate.Env, e) |
There was a problem hiding this comment.
Couple of issues here:
- While testing PipelineRun it gives a nil pointer error; it seems PodTemplate is never initialized. Need to initialize and add a nil check here. Please refer the log.
- Volume is not added to PipelineRun but it is added to TaskRun steps at line 47? Am I missing anything?
PipelineRun BuildRun Logs
{"level":"debug","ts":"2026-04-28T11:28:41Z","msg":"starting reconciling request from a BuildRun or TaskRun event","controller":"buildrun-controller","object":{"name":"test-cabundle-pipelinerun-ckj5t","namespace":"default"},"namespace":"default","name":"test-cabundle-pipelinerun-ckj5t","reconcileID":"a0bcc484-435b-4990-9469-8f81ebe71764","namespace":"default","name":"test-cabundle-pipelinerun-ckj5t"}
{"level":"info","ts":"2026-04-28T11:28:41Z","msg":"updating BuildRun status","controller":"buildrun-controller","object":{"name":"test-cabundle-pipelinerun-ckj5t","namespace":"default"},"namespace":"default","name":"test-cabundle-pipelinerun-ckj5t","reconcileID":"a0bcc484-435b-4990-9469-8f81ebe71764","namespace":"default","name":"test-cabundle-pipelinerun-ckj5t"}
{"level":"info","ts":"2026-04-28T11:28:41Z","msg":"falling back to default serviceAccount","controller":"buildrun-controller","object":{"name":"test-cabundle-pipelinerun-ckj5t","namespace":"default"},"namespace":"default","name":"test-cabundle-pipelinerun-ckj5t","reconcileID":"a0bcc484-435b-4990-9469-8f81ebe71764","namespace":"default"}
{"level":"debug","ts":"2026-04-28T11:28:41Z","msg":"retrieving ClusterBuildStrategy","controller":"buildrun-controller","object":{"name":"test-cabundle-pipelinerun-ckj5t","namespace":"default"},"namespace":"default","name":"test-cabundle-pipelinerun-ckj5t","reconcileID":"a0bcc484-435b-4990-9469-8f81ebe71764","namespace":"default","name":"test-cabundle"}
{"level":"error","ts":"2026-04-28T11:28:41Z","msg":"Observed a panic","controller":"buildrun-controller","object":{"name":"test-cabundle-pipelinerun-ckj5t","namespace":"default"},"namespace":"default","name":"test-cabundle-pipelinerun-ckj5t","reconcileID":"a0bcc484-435b-4990-9469-8f81ebe71764","panic":"runtime error: invalid memory address or nil pointer dereference","panicGoValue":"\"invalid memory address or nil pointer dereference\"","stacktrace":"goroutine 420 [running]:\nk8s.io/apimachinery/pkg/util/runtime.logPanic({0x233fa50, 0x13a14b22ba40}, {0x1e93ac0, 0x38302b0})\n\tk8s.io/apimachinery@v0.34.4/pkg/util/runtime/runtime.go:132 +0xbc\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller[...]).Reconcile.func1()\n\tsigs.k8s.io/controller-runtime@v0.22.5/pkg/internal/controller/controller.go:198 +0x103\npanic({0x1e93ac0?, 0x38302b0?})\n\truntime/panic.go:860 +0x13a\ngithub.com/shipwright-io/build/pkg/reconciler/buildrun/resources.addCertificates(0x0, 0x13a14a6ebb08, 0x13a14b3c7410?, 0x0?)\n\tgithub.com/shipwright-io/build/pkg/reconciler/buildrun/resources/cabundle.go:52 +0x3f3\ngithub.com/shipwright-io/build/pkg/reconciler/buildrun/resources.(*PipelineRunGenerator).ApplyInfrastructureConfiguration(0x13a14aee73e0)\n\tgithub.com/shipwright-io/build/pkg/reconciler/buildrun/resources/pipelinerun_generator.go:225 +0x3d6\ngithub.com/shipwright-io/build/pkg/reconciler/buildrun/resources.GenerateBuildRunExecutor(0x0?, 0x0?, {0x234f840?, 0x13a14ad49340?}, {0x234dff0, 0x13a14aee73e0})\n\tgithub.com/shipwright-io/build/pkg/reconciler/buildrun/resources/executor_generator.go:96 +0x350\ngithub.com/shipwright-io/build/pkg/reconciler/buildrun/resources.GeneratePipelineRun(0x13a14a7ee408, 0x13a14a6eb688, 0x13a14a6eab48, {0x13a14ac92a40, 0x7}, {0x234f840, 0x13a14ad49340})\n\tgithub.com/shipwright-io/build/pkg/reconciler/buildrun/resources/pipelinerun.go:26 +0xe7\ngithub.com/shipwright-io/build/pkg/reconciler/buildrun.(*TektonPipelineRunImageBuildRunnerFactory).CreateImageBuildRunner(0x0?, {0x233faf8, 0x13a14af7c3f0}, {0x2357d08, 0x13a14a6f54d0}, 0x7f175dd56cd8?, 0x236c818?, {0x234f840?, 0x13a14ad49340?}, 0x13a14a6eb688, ...)\n\tgithub.com/shipwright-io/build/pkg/reconciler/buildrun/pipelinerun_runner.go:223 +0x70\ngithub.com/shipwright-io/build/pkg/reconciler/buildrun.(*ReconcileBuildRun).Reconcile(0x13a14a6f84c0, {0x233fa50?, 0x13a14b22ba40?}, {{{0x13a14ad09ec6?, 0x13a14b22ba40?}, {0x13a14b234120?, 0x0?}}})\n\tgithub.com/shipwright-io/build/pkg/reconciler/buildrun/buildrun.go:339 +0x3445\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller[...]).Reconcile(0x13a14b22b9b0?, {0x233fa50?, 0x13a14b22ba40}, {{{0x13a14ad09ec6, 0x0?}, {0x13a14b234120?, 0x0?}}})\n\tsigs.k8s.io/controller-runtime@v0.22.5/pkg/internal/controller/controller.go:216 +0x165\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller[...]).reconcileHandler(0x236c700, {0x233fa88, 0x13a14a793ea0}, {{{0x13a14ad09ec6, 0x7}, {0x13a14b234120, 0x1f}}}, 0x0)\n\tsigs.k8s.io/controller-runtime@v0.22.5/pkg/internal/controller/controller.go:461 +0x377\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller[...]).processNextWorkItem(0x236c700, {0x233fa88, 0x13a14a793ea0})\n\tsigs.k8s.io/controller-runtime@v0.22.5/pkg/internal/controller/controller.go:421 +0x1f8\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller[...]).Start.func1.1()\n\tsigs.k8s.io/controller-runtime@v0.22.5/pkg/internal/controller/controller.go:296 +0x85\ncreated by sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller[...]).Start.func1 in goroutine 181\n\tsigs.k8s.io/controller-runtime@v0.22.5/pkg/internal/controller/controller.go:292 +0x26b\n","stacktrace":"k8s.io/apimachinery/pkg/util/runtime.logPanic\n\tk8s.io/apimachinery@v0.34.4/pkg/util/runtime/runtime.go:142\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller[...]).Reconcile.func1\n\tsigs.k8s.io/controller-runtime@v0.22.5/pkg/internal/controller/controller.go:198\nruntime.gopanic\n\truntime/panic.go:860\nruntime.panicmem\n\truntime/panic.go:336\nruntime.sigpanic\n\truntime/signal_unix.go:931\ngithub.com/shipwright-io/build/pkg/reconciler/buildrun/resources.addCertificates\n\tgithub.com/shipwright-io/build/pkg/reconciler/buildrun/resources/cabundle.go:52\ngithub.com/shipwright-io/build/pkg/reconciler/buildrun/resources.(*PipelineRunGenerator).ApplyInfrastructureConfiguration\n\tgithub.com/shipwright-io/build/pkg/reconciler/buildrun/resources/pipelinerun_generator.go:225\ngithub.com/shipwright-io/build/pkg/reconciler/buildrun/resources.GenerateBuildRunExecutor\n\tgithub.com/shipwright-io/build/pkg/reconciler/buildrun/resources/executor_generator.go:96\ngithub.com/shipwright-io/build/pkg/reconciler/buildrun/resources.GeneratePipelineRun\n\tgithub.com/shipwright-io/build/pkg/reconciler/buildrun/resources/pipelinerun.go:26\ngithub.com/shipwright-io/build/pkg/reconciler/buildrun.(*TektonPipelineRunImageBuildRunnerFactory).CreateImageBuildRunner\n\tgithub.com/shipwright-io/build/pkg/reconciler/buildrun/pipelinerun_runner.go:223\ngithub.com/shipwright-io/build/pkg/reconciler/buildrun.(*ReconcileBuildRun).Reconcile\n\tgithub.com/shipwright-io/build/pkg/reconciler/buildrun/buildrun.go:339\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller[...]).Reconcile\n\tsigs.k8s.io/controller-runtime@v0.22.5/pkg/internal/controller/controller.go:216\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller[...]).reconcileHandler\n\tsigs.k8s.io/controller-runtime@v0.22.5/pkg/internal/controller/controller.go:461\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller[...]).processNextWorkItem\n\tsigs.k8s.io/controller-runtime@v0.22.5/pkg/internal/controller/controller.go:421\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller[...]).Start.func1.1\n\tsigs.k8s.io/controller-runtime@v0.22.5/pkg/internal/controller/controller.go:296"}
{"level":"error","ts":"2026-04-28T11:28:41Z","msg":"Reconciler error","controller":"buildrun-controller","object":{"name":"test-cabundle-pipelinerun-ckj5t","namespace":"default"},"namespace":"default","name":"test-cabundle-pipelinerun-ckj5t","reconcileID":"a0bcc484-435b-4990-9469-8f81ebe71764","error":"panic: runtime error: invalid memory address or nil pointer dereference [recovered]","stacktrace":"sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller[...]).reconcileHandler\n\tsigs.k8s.io/controller-runtime@v0.22.5/pkg/internal/controller/controller.go:474\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller[...]).processNextWorkItem\n\tsigs.k8s.io/controller-runtime@v0.22.5/pkg/internal/controller/controller.go:421\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller[...]).Start.func1.1\n\tsigs.k8s.io/controller-runtime@v0.22.5/pkg/internal/controller/controller.go:296"}
There was a problem hiding this comment.
Fixed the error and added Volumes to pipeline.
| } | ||
| } | ||
|
|
||
| return nil |
There was a problem hiding this comment.
This function always returns nil. Is that on purpose, or some error should be returned?
There was a problem hiding this comment.
Yes.. To match the other functions there. Might require in future.
| switch o := object.(type) { | ||
| case *corev1.Secret: | ||
| data = o.Data[ca.Secret.Key] | ||
| case *corev1.ConfigMap: | ||
| data = []byte(o.Data[ca.ConfigMap.Key]) | ||
| } | ||
|
|
||
| // Parse and validate each certificate in the PEM data | ||
| block, rest := pem.Decode(data) | ||
| if block == nil { | ||
| return fmt.Errorf("no certificate present in CA bundle") | ||
| } |
There was a problem hiding this comment.
I believe in case the key doesn't exist, we should return a proper error and not rely on Decode() to finally return that "Certificate is not present". This way we will know what exactly is wrong.
There was a problem hiding this comment.
In the API the key field is not optional.
| Name: fmt.Sprintf("%s-%s", prefixParamsResultsVolumes, paramCABundle), | ||
| Description: "The CA Bundle file used to access secure endpoints", | ||
| Type: pipelineapi.ParamTypeString, | ||
| }, |
There was a problem hiding this comment.
It seems the paramCABundle is always added even if there is nothing configured, should this be inside a if paramCABundle != nil kind of block?
There was a problem hiding this comment.
Updated the login to make the parameter empty if the CA bundle is not provided.
| } | ||
|
|
||
| // BuildRunFields runs field validations against a BuildRun to detect | ||
| // disallowed field combinations and issues |
There was a problem hiding this comment.
Should there be a conflict/preference check for Build/BuildRun? For example, if cabundle is added to both Build and BuildRun. Currently, BuildRun wins because of how addCertificate function is defined. Is that intended?
There was a problem hiding this comment.
The priority is BuildRun >> Build
Reference: shipwright-io/community#281 # Changes: - Added APIs to allow user to define custom Root CAs in Build and BuildRun APIs - Add unit tests Signed-off-by: Sayan Biswas <sabiswas@redhat.com>
| return generateTaskSpecVolumes( | ||
| if err = generateTaskSpecVolumes( | ||
| g.taskRun.Spec.TaskSpec, | ||
| execCtx.volumeMounts, | ||
| execCtx.strategyVolumes, | ||
| execCtx.buildVolumes, | ||
| execCtx.buildRunVolumes, | ||
| ) | ||
| ); err != nil { | ||
| return err | ||
| } | ||
|
|
||
| return nil |
There was a problem hiding this comment.
The original code can be left as is.
if err is nil, nil is returned and if err is not nil, err is returned, so the value of err is returned in all cases. Therefore, return generateTaskSpecVolumes( is already doing the right thing.
| return generateTaskSpecVolumes( | |
| if err = generateTaskSpecVolumes( | |
| g.taskRun.Spec.TaskSpec, | |
| execCtx.volumeMounts, | |
| execCtx.strategyVolumes, | |
| execCtx.buildVolumes, | |
| execCtx.buildRunVolumes, | |
| ) | |
| ); err != nil { | |
| return err | |
| } | |
| return nil | |
| return generateTaskSpecVolumes( |
There was a problem hiding this comment.
Yes.. This part of the code was already correct. Made this change to improve the code readability and match the other function.
| if err := applyParameters(g.taskRun, g.build, g.buildRun, g.strategy); err != nil { | ||
| return err | ||
| } | ||
|
|
||
| return nil |
There was a problem hiding this comment.
Same as above, the original return statement should stay as is.
| c.Build.Status.Reason = ptr.To[buildapi.BuildReason](buildapi.CABundleNotValid) | ||
| c.Build.Status.Message = ptr.To(err.Error()) | ||
| } | ||
| return nil |
There was a problem hiding this comment.
Shouldn't this be return err ? Otherwise you have a function with an error return type that never returns an error.
Changes:
Submitter Checklist
See the contributor guide
for details on coding conventions, github and prow interactions, and the code review process.
Release Notes