Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cleanup: add disable_spire build tag for entrypoint command #8548

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
15 changes: 2 additions & 13 deletions cmd/entrypoint/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,12 @@ import (

"github.com/containerd/containerd/platforms"
"github.com/tektoncd/pipeline/cmd/entrypoint/subcommands"
featureFlags "github.com/tektoncd/pipeline/pkg/apis/config"
"github.com/tektoncd/pipeline/pkg/apis/pipeline"
v1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1"
"github.com/tektoncd/pipeline/pkg/credentials"
"github.com/tektoncd/pipeline/pkg/credentials/dockercreds"
"github.com/tektoncd/pipeline/pkg/credentials/gitcreds"
"github.com/tektoncd/pipeline/pkg/entrypoint"
"github.com/tektoncd/pipeline/pkg/spire"
"github.com/tektoncd/pipeline/pkg/spire/config"
"github.com/tektoncd/pipeline/pkg/termination"
)

Expand All @@ -59,9 +56,7 @@ var (
onError = flag.String("on_error", "", "Set to \"continue\" to ignore an error and continue when a container terminates with a non-zero exit code."+
" Set to \"stopAndFail\" to declare a failure with a step error and stop executing the rest of the steps.")
stepMetadataDir = flag.String("step_metadata_dir", "", "If specified, create directory to store the step metadata e.g. /tekton/steps/<step-name>/")
enableSpire = flag.Bool("enable_spire", false, "If specified by configmap, this enables spire signing and verification")
socketPath = flag.String("spire_socket_path", "unix:///spiffe-workload-api/spire-agent.sock", "Experimental: The SPIRE agent socket for SPIFFE workload API.")
resultExtractionMethod = flag.String("result_from", featureFlags.ResultExtractionMethodTerminationMessage, "The method using which to extract results from tasks. Default is using the termination message.")
resultExtractionMethod = flag.String("result_from", entrypoint.ResultExtractionMethodTerminationMessage, "The method using which to extract results from tasks. Default is using the termination message.")
)

const (
Expand Down Expand Up @@ -130,13 +125,7 @@ func main() {
}
}

var spireWorkloadAPI spire.EntrypointerAPIClient
if enableSpire != nil && *enableSpire && socketPath != nil && *socketPath != "" {
spireConfig := config.SpireConfig{
SocketPath: *socketPath,
}
spireWorkloadAPI = spire.NewEntrypointerAPIClient(&spireConfig)
}
spireWorkloadAPI := initializeSpireAPI()

e := entrypoint.Entrypointer{
Command: append(cmd, commandArgs...),
Expand Down
43 changes: 43 additions & 0 deletions cmd/entrypoint/spire.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//go:build !disable_spire

/*
Copyright 2025 The Tekton Authors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
"flag"
"log"

"github.com/tektoncd/pipeline/pkg/spire"
"github.com/tektoncd/pipeline/pkg/spire/config"
)

var (
enableSpire = flag.Bool("enable_spire", false, "If specified by configmap, this enables spire signing and verification")
socketPath = flag.String("spire_socket_path", "unix:///spiffe-workload-api/spire-agent.sock", "Experimental: The SPIRE agent socket for SPIFFE workload API.")
)

func initializeSpireAPI() spire.EntrypointerAPIClient {
if enableSpire != nil && *enableSpire && socketPath != nil && *socketPath != "" {
log.Println("SPIRE is enabled in this build, enableSpire is supported")
spireConfig := config.SpireConfig{
SocketPath: *socketPath,
}
return spire.NewEntrypointerAPIClient(&spireConfig)
}
return nil
}
47 changes: 47 additions & 0 deletions cmd/entrypoint/spire_disable.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//go:build disable_spire

/*
Copyright 2025 The Tekton Authors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
"context"
"flag"
"log"
"os"

"github.com/tektoncd/pipeline/pkg/result"
)

var (
enableSpire = flag.Bool("enable_spire", false, "If specified by configmap, this enables spire signing and verification")
)

// EntrypointerAPIClient interface maps to the spire entrypointer API to interact with spire
type EntrypointerAPIClient interface {
Close() error
// Sign returns the signature material to be put in the RunResult to append to the output results
Sign(ctx context.Context, results []result.RunResult) ([]result.RunResult, error)
}

func initializeSpireAPI() EntrypointerAPIClient {
if enableSpire != nil && *enableSpire {
log.Fatal("Error: SPIRE is disabled in this build, but enableSpire was set to true. Please recompile with SPIRE support.")
os.Exit(1)
}
return nil
}
15 changes: 15 additions & 0 deletions docs/developers/fips.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
## Introduction
FIPS compliance requires compiling the project with a Go FIPS-compliant compiler (e.g., golang-fips) and using dynamic linking.

This approach works for most binaries in tektoncd/pipeline, except for the entrypoint, which must be statically compiled to ensure it runs in any environment, regardless of library locations or versions. To mark a statically compiled binary as FIPS compliant, we must eliminate cryptographic symbols (crypto/*, golang.org/x/crypto, etc.).

To achieve this, we need compile-time options to disable TLS, SPIRE, and any network-related functionality.

This document provides instructions on compiling the entrypoint command to ensure FIPS compliance.

## Disable SPIRE during Build
To disable SPIRE during the build process, use the following command

```shell
CGO_ENABLED=0 go build -tags disable_spire -o bin/entrypoint ./cmd/entrypoint
```
6 changes: 6 additions & 0 deletions docs/spire.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ When a TaskRun is created:
1. The entrypointer receives an x509 SVID, containing the x509 certificate and associated private key.
1. The entrypointer signs the results of the TaskRun and emits the signatures and x509 certificate to the TaskRun results for later verification.

## Enable SPIRE during Build
Users can enable SPIRE support in Tekton Pipelines during the build process by using the following build tag:
```shell
CGO_ENABLED=0 go build -tags "!disable_spire" -o bin/entrypoint ./cmd/entrypoint
```

## Enabling TaskRun result attestations

To enable TaskRun attestations:
Expand Down
18 changes: 8 additions & 10 deletions pkg/entrypoint/entrypointer.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ import (
"github.com/tektoncd/pipeline/pkg/internal/resultref"
"github.com/tektoncd/pipeline/pkg/pod"
"github.com/tektoncd/pipeline/pkg/result"
"github.com/tektoncd/pipeline/pkg/spire"
"github.com/tektoncd/pipeline/pkg/termination"

"github.com/google/cel-go/cel"
Expand All @@ -53,8 +52,9 @@ const (
)

const (
breakpointExitSuffix = ".breakpointexit"
breakpointBeforeStepSuffix = ".beforestepexit"
breakpointExitSuffix = ".breakpointexit"
breakpointBeforeStepSuffix = ".beforestepexit"
ResultExtractionMethodTerminationMessage = "termination-message"
)

// DebugBeforeStepError is an error means mark before step breakpoint failure
Expand Down Expand Up @@ -147,7 +147,7 @@ type Entrypointer struct {
// StepMetadataDir is the directory for a step where the step related metadata can be stored
StepMetadataDir string
// SpireWorkloadAPI connects to spire and does obtains SVID based on taskrun
SpireWorkloadAPI spire.EntrypointerAPIClient
SpireWorkloadAPI EntrypointerAPIClient
// ResultsDirectory is the directory to find results, defaults to pipeline.DefaultResultPath
ResultsDirectory string
// ResultExtractionMethod is the method using which the controller extracts the results from the task pod.
Expand Down Expand Up @@ -444,13 +444,11 @@ func (e Entrypointer) readResultsFromDisk(ctx context.Context, resultDir string,
})
}

if e.SpireWorkloadAPI != nil {
signed, err := e.SpireWorkloadAPI.Sign(ctx, output)
if err != nil {
return err
}
output = append(output, signed...)
signed, err := signResults(ctx, e.SpireWorkloadAPI, output)
if err != nil {
return err
}
output = append(output, signed...)

// push output to termination path
if e.ResultExtractionMethod == config.ResultExtractionMethodTerminationMessage && len(output) != 0 {
Expand Down
38 changes: 38 additions & 0 deletions pkg/entrypoint/spire.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//go:build !disable_spire

/*
Copyright 2025 The Tekton Authors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package entrypoint

import (
"context"

"github.com/tektoncd/pipeline/pkg/result"
"github.com/tektoncd/pipeline/pkg/spire"
)

// EntrypointerAPIClient defines the interface for SPIRE operations
type EntrypointerAPIClient interface {
spire.EntrypointerAPIClient
}

func signResults(ctx context.Context, api EntrypointerAPIClient, results []result.RunResult) ([]result.RunResult, error) {
if api == nil {
return nil, nil
}
return api.Sign(ctx, results)
}
34 changes: 34 additions & 0 deletions pkg/entrypoint/spire_disabled.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//go:build disable_spire

/*
Copyright 2025 The Tekton Authors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package entrypoint

import (
"context"

"github.com/tektoncd/pipeline/pkg/result"
)

// EntrypointerAPIClient defines the interface for SPIRE operations
type EntrypointerAPIClient interface {
Sign(ctx context.Context, results []result.RunResult) ([]result.RunResult, error)
}

func signResults(ctx context.Context, api EntrypointerAPIClient, results []result.RunResult) ([]result.RunResult, error) {
return nil, nil
}
Loading