Skip to content

Commit

Permalink
SECURESIGN 12 | Enable Podman build for TUF server image
Browse files Browse the repository at this point in the history
Signed-off-by: greg pereira <[email protected]>
  • Loading branch information
Gregory-Pereira committed Jan 3, 2024
1 parent 1372537 commit 41e4cdf
Show file tree
Hide file tree
Showing 3 changed files with 169 additions and 90 deletions.
194 changes: 104 additions & 90 deletions cmd/tuf/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ package main
import (
"bytes"
"flag"
"fmt"
"net/http"
"os"
"path/filepath"
"strings"

"github.com/sigstore/scaffolding/pkg/certs"
"github.com/sigstore/scaffolding/pkg/build"
"github.com/sigstore/scaffolding/pkg/repo"
"github.com/sigstore/scaffolding/pkg/secret"
"github.com/sigstore/scaffolding/pkg/tuf"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"knative.dev/pkg/logging"
Expand All @@ -43,104 +43,118 @@ var (

func main() {
flag.Parse()

ns := os.Getenv("NAMESPACE")
if ns == "" {
panic("env variable NAMESPACE must be set")
}
ctx := signals.NewContext()

versionInfo := version.GetVersionInfo()
logging.FromContext(ctx).Infof("running create_repo Version: %s GitCommit: %s BuildDate: %s", versionInfo.GitVersion, versionInfo.GitCommit, versionInfo.BuildDate)

config, err := rest.InClusterConfig()
if err != nil {
logging.FromContext(ctx).Panicf("Failed to get InClusterConfig: %v", err)
}
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
logging.FromContext(ctx).Panicf("Failed to get clientset: %v", err)
}
buildEnv := build.GetBuildMethod()
if buildEnv == "kubernetes" {
ns := os.Getenv("NAMESPACE")
if ns == "" {
panic("env variable NAMESPACE must be set")
}

tufFiles, err := os.ReadDir(*dir)
if err != nil {
logging.FromContext(ctx).Fatalf("failed to read dir %s: %v", *dir, err)
}
trimDir := strings.TrimSuffix(*dir, "/")
files := map[string][]byte{}
for _, file := range tufFiles {
if !file.IsDir() {
logging.FromContext(ctx).Infof("Got file %s", file.Name())
// Kubernetes adds some extra files here that are prefixed with
// .., for example '..data' so skip those.
if strings.HasPrefix(file.Name(), "..") {
logging.FromContext(ctx).Infof("Skipping .. file %s", file.Name())
continue
}
fileName := fmt.Sprintf("%s/%s", trimDir, file.Name())
fileBytes, err := os.ReadFile(fileName)
if err != nil {
logging.FromContext(ctx).Fatalf("failed to read file %s/%s: %v", fileName, err)
}
// If it's a TSA file, we need to split it into multiple TUF
// targets.
if strings.Contains(file.Name(), "tsa") {
logging.FromContext(ctx).Infof("Splitting TSA certchain into individual certs")

certFiles, err := certs.SplitCertChain(fileBytes, "tsa")
if err != nil {
logging.FromContext(ctx).Fatalf("failed to parse %s/%s: %v", fileName, err)
}
for k, v := range certFiles {
logging.FromContext(ctx).Infof("Got tsa cert file %s", k)
files[k] = v
}
} else {
files[file.Name()] = fileBytes
}
config, err := rest.InClusterConfig()
if err != nil {
logging.FromContext(ctx).Panicf("Failed to get InClusterConfig: %v", err)
}
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
logging.FromContext(ctx).Panicf("Failed to get clientset: %v", err)
}
}

// Create a new TUF root with the listed artifacts.
local, dir, err := repo.CreateRepo(ctx, files)
if err != nil {
logging.FromContext(ctx).Panicf("Failed to create repo: %v", err)
}
meta, err := local.GetMeta()
if err != nil {
logging.FromContext(ctx).Panicf("Getting meta: %v", err)
}
rootJSON, ok := meta["root.json"]
if !ok {
logging.FromContext(ctx).Panicf("Getting root: %v", err)
}
tufFiles, err := os.ReadDir(*dir)
if err != nil {
logging.FromContext(ctx).Fatalf("failed to read dir %s: %v", *dir, err)
}
trimDir := strings.TrimSuffix(*dir, "/")
files := map[string][]byte{}

Check failure on line 72 in cmd/tuf/server/main.go

View workflow job for this annotation

GitHub Actions / lint

ineffectual assignment to files (ineffassign)

Check failure on line 72 in cmd/tuf/server/main.go

View workflow job for this annotation

GitHub Actions / lint

SA4006: this value of `files` is never used (staticcheck)
files = tuf.ProcessTufFiles(ctx, tufFiles, trimDir)

// Add the initial 1.root.json to secrets.
data := make(map[string][]byte)
data["root"] = rootJSON
local, dir, err := repo.CreateRepo(ctx, files)
if err != nil {
logging.FromContext(ctx).Panicf("Failed to create repo: %v", err)
}

// Then compress the root directory and put it into a secret
// Secrets have 1MiB and the repository as tested goes to about ~3k, so no
// worries here.
var compressed bytes.Buffer
if err := repo.CompressFS(os.DirFS(dir), &compressed, map[string]bool{"keys": true, "staged": true}); err != nil {
logging.FromContext(ctx).Fatalf("Failed to compress the repo: %v", err)
}
data["repository"] = compressed.Bytes()
meta, err := local.GetMeta()
if err != nil {
logging.FromContext(ctx).Panicf("Getting meta: %v", err)
}
rootJSON, ok := meta["root.json"]
if !ok {
logging.FromContext(ctx).Panicf("Getting root: %v", err)
}

nsSecret := clientset.CoreV1().Secrets(ns)
if err := secret.ReconcileSecret(ctx, *secretName, ns, data, nsSecret); err != nil {
logging.FromContext(ctx).Panicf("Failed to reconcile secret %s/%s: %v", ns, *secretName, err)
}
// Serve the TUF repository.
logging.FromContext(ctx).Infof("tuf repository was created in: %s", dir)
serveDir := filepath.Join(dir, "repository")
logging.FromContext(ctx).Infof("tuf repository was created in: %s serving tuf root at %s", dir, serveDir)
fs := http.FileServer(http.Dir(serveDir))
http.Handle("/", fs)

/* #nosec G114 */
if err := http.ListenAndServe(":8080", nil); err != nil {
panic(err)
data := make(map[string][]byte)
data["root"] = rootJSON

// Then compress the root directory and put it into a secret
// Secrets have 1MiB and the repository as tested goes to about ~3k, so no
// worries here.
var compressed bytes.Buffer
if err := repo.CompressFS(os.DirFS(dir), &compressed, map[string]bool{"keys": true, "staged": true}); err != nil {
logging.FromContext(ctx).Fatalf("Failed to compress the repo: %v", err)
}
data["repository"] = compressed.Bytes()

nsSecret := clientset.CoreV1().Secrets(ns)
if err := secret.ReconcileSecret(ctx, *secretName, ns, data, nsSecret); err != nil {
logging.FromContext(ctx).Panicf("Failed to reconcile secret %s/%s: %v", ns, *secretName, err)
}
// Serve the TUF repository.
logging.FromContext(ctx).Infof("tuf repository was created in: %s", dir)
serveDir := filepath.Join(dir, "repository")
logging.FromContext(ctx).Infof("tuf repository was created in: %s serving tuf root at %s", dir, serveDir)
fs := http.FileServer(http.Dir(serveDir))
http.Handle("/", fs)

/* #nosec G114 */
if err := http.ListenAndServe(":8080", nil); err != nil {
panic(err)
}
} else if buildEnv == "container" {
tufFiles, err := os.ReadDir(*dir)
if err != nil {
logging.FromContext(ctx).Fatalf("failed to read dir %s: %v", *dir, err)
}
trimDir := strings.TrimSuffix(*dir, "/")
files := map[string][]byte{}

Check failure on line 122 in cmd/tuf/server/main.go

View workflow job for this annotation

GitHub Actions / lint

ineffectual assignment to files (ineffassign)

Check failure on line 122 in cmd/tuf/server/main.go

View workflow job for this annotation

GitHub Actions / lint

SA4006: this value of `files` is never used (staticcheck)

files = tuf.ProcessTufFiles(ctx, tufFiles, trimDir)
local, dir, err := repo.CreateRepo(ctx, files)
if err != nil {
logging.FromContext(ctx).Panicf("Failed to create repo: %v", err)
}
meta, err := local.GetMeta()
if err != nil {
logging.FromContext(ctx).Panicf("Getting meta: %v", err)
}
rootJSON, ok := meta["root.json"]
if !ok {
logging.FromContext(ctx).Panicf("Getting root: %v", err)
}

data := make(map[string][]byte)
data["root"] = rootJSON

// compressing the root directory and serving it from the filesystem.

var compressed bytes.Buffer
if err := repo.CompressFS(os.DirFS(dir), &compressed, map[string]bool{"keys": true, "staged": true}); err != nil {
logging.FromContext(ctx).Fatalf("Failed to compress the repo: %v", err)
}
data["repository"] = compressed.Bytes()

logging.FromContext(ctx).Infof("tuf repository was created in: %s", dir)
serveDir := filepath.Join(dir, "repository")
logging.FromContext(ctx).Infof("tuf repository was created in: %s serving tuf root at %s", dir, serveDir)
fs := http.FileServer(http.Dir(serveDir))
http.Handle("/", fs)

/* #nosec G114 */
if err := http.ListenAndServe(":8080", nil); err != nil {
panic(err)
}
}
}
15 changes: 15 additions & 0 deletions pkg/build/build.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package build

import (
"os"
)

func GetBuildMethod() string {
kubernetesServiceHost := os.Getenv("KUBERNETES_SERVICE_HOST")
kubernetesServicePort := os.Getenv("KUBERNETES_SERVICE_PORT")
if kubernetesServiceHost == "" && kubernetesServicePort == "" {
return "container"
} else {

Check warning on line 12 in pkg/build/build.go

View workflow job for this annotation

GitHub Actions / lint

indent-error-flow: if block ends with a return statement, so drop this else and outdent its block (revive)
return "kubernetes"
}
}
50 changes: 50 additions & 0 deletions pkg/tuf/tuf.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package tuf

import (
"context"
"fmt"
"io/fs"
"os"
"strings"

"github.com/sigstore/scaffolding/pkg/certs"
"knative.dev/pkg/logging"
)

func ProcessTufFiles(ctx context.Context, tufFiles []fs.DirEntry, dir string) map[string][]byte {
trimDir := strings.TrimSuffix(dir, "/")
files := map[string][]byte{}
for _, file := range tufFiles {
if !file.IsDir() {
logging.FromContext(ctx).Infof("Got file %s", file.Name())
// Kubernetes adds some extra files here that are prefixed with
// .., for example '..data' so skip those.
if strings.HasPrefix(file.Name(), "..") {
logging.FromContext(ctx).Infof("Skipping .. file %s", file.Name())
continue
}
fileName := fmt.Sprintf("%s/%s", trimDir, file.Name())
fileBytes, err := os.ReadFile(fileName)
if err != nil {
logging.FromContext(ctx).Fatalf("failed to read file %s/%s: %v", fileName, err)
}
// If it's a TSA file, we need to split it into multiple TUF
// targets.
if strings.Contains(file.Name(), "tsa") {
logging.FromContext(ctx).Infof("Splitting TSA certchain into individual certs")

certFiles, err := certs.SplitCertChain(fileBytes, "tsa")
if err != nil {
logging.FromContext(ctx).Fatalf("failed to parse %s/%s: %v", fileName, err)
}
for k, v := range certFiles {
logging.FromContext(ctx).Infof("Got tsa cert file %s", k)
files[k] = v
}
} else {
files[file.Name()] = fileBytes
}
}
}
return files
}

0 comments on commit 41e4cdf

Please sign in to comment.