Skip to content

Commit 41e4cdf

Browse files
SECURESIGN 12 | Enable Podman build for TUF server image
Signed-off-by: greg pereira <grpereir@redhat.com>
1 parent 1372537 commit 41e4cdf

File tree

3 files changed

+169
-90
lines changed

3 files changed

+169
-90
lines changed

cmd/tuf/server/main.go

+104-90
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ package main
1717
import (
1818
"bytes"
1919
"flag"
20-
"fmt"
2120
"net/http"
2221
"os"
2322
"path/filepath"
2423
"strings"
2524

26-
"github.com/sigstore/scaffolding/pkg/certs"
25+
"github.com/sigstore/scaffolding/pkg/build"
2726
"github.com/sigstore/scaffolding/pkg/repo"
2827
"github.com/sigstore/scaffolding/pkg/secret"
28+
"github.com/sigstore/scaffolding/pkg/tuf"
2929
"k8s.io/client-go/kubernetes"
3030
"k8s.io/client-go/rest"
3131
"knative.dev/pkg/logging"
@@ -43,104 +43,118 @@ var (
4343

4444
func main() {
4545
flag.Parse()
46-
47-
ns := os.Getenv("NAMESPACE")
48-
if ns == "" {
49-
panic("env variable NAMESPACE must be set")
50-
}
5146
ctx := signals.NewContext()
5247

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

56-
config, err := rest.InClusterConfig()
57-
if err != nil {
58-
logging.FromContext(ctx).Panicf("Failed to get InClusterConfig: %v", err)
59-
}
60-
clientset, err := kubernetes.NewForConfig(config)
61-
if err != nil {
62-
logging.FromContext(ctx).Panicf("Failed to get clientset: %v", err)
63-
}
51+
buildEnv := build.GetBuildMethod()
52+
if buildEnv == "kubernetes" {
53+
ns := os.Getenv("NAMESPACE")
54+
if ns == "" {
55+
panic("env variable NAMESPACE must be set")
56+
}
6457

65-
tufFiles, err := os.ReadDir(*dir)
66-
if err != nil {
67-
logging.FromContext(ctx).Fatalf("failed to read dir %s: %v", *dir, err)
68-
}
69-
trimDir := strings.TrimSuffix(*dir, "/")
70-
files := map[string][]byte{}
71-
for _, file := range tufFiles {
72-
if !file.IsDir() {
73-
logging.FromContext(ctx).Infof("Got file %s", file.Name())
74-
// Kubernetes adds some extra files here that are prefixed with
75-
// .., for example '..data' so skip those.
76-
if strings.HasPrefix(file.Name(), "..") {
77-
logging.FromContext(ctx).Infof("Skipping .. file %s", file.Name())
78-
continue
79-
}
80-
fileName := fmt.Sprintf("%s/%s", trimDir, file.Name())
81-
fileBytes, err := os.ReadFile(fileName)
82-
if err != nil {
83-
logging.FromContext(ctx).Fatalf("failed to read file %s/%s: %v", fileName, err)
84-
}
85-
// If it's a TSA file, we need to split it into multiple TUF
86-
// targets.
87-
if strings.Contains(file.Name(), "tsa") {
88-
logging.FromContext(ctx).Infof("Splitting TSA certchain into individual certs")
89-
90-
certFiles, err := certs.SplitCertChain(fileBytes, "tsa")
91-
if err != nil {
92-
logging.FromContext(ctx).Fatalf("failed to parse %s/%s: %v", fileName, err)
93-
}
94-
for k, v := range certFiles {
95-
logging.FromContext(ctx).Infof("Got tsa cert file %s", k)
96-
files[k] = v
97-
}
98-
} else {
99-
files[file.Name()] = fileBytes
100-
}
58+
config, err := rest.InClusterConfig()
59+
if err != nil {
60+
logging.FromContext(ctx).Panicf("Failed to get InClusterConfig: %v", err)
61+
}
62+
clientset, err := kubernetes.NewForConfig(config)
63+
if err != nil {
64+
logging.FromContext(ctx).Panicf("Failed to get clientset: %v", err)
10165
}
102-
}
10366

104-
// Create a new TUF root with the listed artifacts.
105-
local, dir, err := repo.CreateRepo(ctx, files)
106-
if err != nil {
107-
logging.FromContext(ctx).Panicf("Failed to create repo: %v", err)
108-
}
109-
meta, err := local.GetMeta()
110-
if err != nil {
111-
logging.FromContext(ctx).Panicf("Getting meta: %v", err)
112-
}
113-
rootJSON, ok := meta["root.json"]
114-
if !ok {
115-
logging.FromContext(ctx).Panicf("Getting root: %v", err)
116-
}
67+
tufFiles, err := os.ReadDir(*dir)
68+
if err != nil {
69+
logging.FromContext(ctx).Fatalf("failed to read dir %s: %v", *dir, err)
70+
}
71+
trimDir := strings.TrimSuffix(*dir, "/")
72+
files := map[string][]byte{}
73+
files = tuf.ProcessTufFiles(ctx, tufFiles, trimDir)
11774

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

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

131-
nsSecret := clientset.CoreV1().Secrets(ns)
132-
if err := secret.ReconcileSecret(ctx, *secretName, ns, data, nsSecret); err != nil {
133-
logging.FromContext(ctx).Panicf("Failed to reconcile secret %s/%s: %v", ns, *secretName, err)
134-
}
135-
// Serve the TUF repository.
136-
logging.FromContext(ctx).Infof("tuf repository was created in: %s", dir)
137-
serveDir := filepath.Join(dir, "repository")
138-
logging.FromContext(ctx).Infof("tuf repository was created in: %s serving tuf root at %s", dir, serveDir)
139-
fs := http.FileServer(http.Dir(serveDir))
140-
http.Handle("/", fs)
141-
142-
/* #nosec G114 */
143-
if err := http.ListenAndServe(":8080", nil); err != nil {
144-
panic(err)
89+
data := make(map[string][]byte)
90+
data["root"] = rootJSON
91+
92+
// Then compress the root directory and put it into a secret
93+
// Secrets have 1MiB and the repository as tested goes to about ~3k, so no
94+
// worries here.
95+
var compressed bytes.Buffer
96+
if err := repo.CompressFS(os.DirFS(dir), &compressed, map[string]bool{"keys": true, "staged": true}); err != nil {
97+
logging.FromContext(ctx).Fatalf("Failed to compress the repo: %v", err)
98+
}
99+
data["repository"] = compressed.Bytes()
100+
101+
nsSecret := clientset.CoreV1().Secrets(ns)
102+
if err := secret.ReconcileSecret(ctx, *secretName, ns, data, nsSecret); err != nil {
103+
logging.FromContext(ctx).Panicf("Failed to reconcile secret %s/%s: %v", ns, *secretName, err)
104+
}
105+
// Serve the TUF repository.
106+
logging.FromContext(ctx).Infof("tuf repository was created in: %s", dir)
107+
serveDir := filepath.Join(dir, "repository")
108+
logging.FromContext(ctx).Infof("tuf repository was created in: %s serving tuf root at %s", dir, serveDir)
109+
fs := http.FileServer(http.Dir(serveDir))
110+
http.Handle("/", fs)
111+
112+
/* #nosec G114 */
113+
if err := http.ListenAndServe(":8080", nil); err != nil {
114+
panic(err)
115+
}
116+
} else if buildEnv == "container" {
117+
tufFiles, err := os.ReadDir(*dir)
118+
if err != nil {
119+
logging.FromContext(ctx).Fatalf("failed to read dir %s: %v", *dir, err)
120+
}
121+
trimDir := strings.TrimSuffix(*dir, "/")
122+
files := map[string][]byte{}
123+
124+
files = tuf.ProcessTufFiles(ctx, tufFiles, trimDir)
125+
local, dir, err := repo.CreateRepo(ctx, files)
126+
if err != nil {
127+
logging.FromContext(ctx).Panicf("Failed to create repo: %v", err)
128+
}
129+
meta, err := local.GetMeta()
130+
if err != nil {
131+
logging.FromContext(ctx).Panicf("Getting meta: %v", err)
132+
}
133+
rootJSON, ok := meta["root.json"]
134+
if !ok {
135+
logging.FromContext(ctx).Panicf("Getting root: %v", err)
136+
}
137+
138+
data := make(map[string][]byte)
139+
data["root"] = rootJSON
140+
141+
// compressing the root directory and serving it from the filesystem.
142+
143+
var compressed bytes.Buffer
144+
if err := repo.CompressFS(os.DirFS(dir), &compressed, map[string]bool{"keys": true, "staged": true}); err != nil {
145+
logging.FromContext(ctx).Fatalf("Failed to compress the repo: %v", err)
146+
}
147+
data["repository"] = compressed.Bytes()
148+
149+
logging.FromContext(ctx).Infof("tuf repository was created in: %s", dir)
150+
serveDir := filepath.Join(dir, "repository")
151+
logging.FromContext(ctx).Infof("tuf repository was created in: %s serving tuf root at %s", dir, serveDir)
152+
fs := http.FileServer(http.Dir(serveDir))
153+
http.Handle("/", fs)
154+
155+
/* #nosec G114 */
156+
if err := http.ListenAndServe(":8080", nil); err != nil {
157+
panic(err)
158+
}
145159
}
146160
}

pkg/build/build.go

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package build
2+
3+
import (
4+
"os"
5+
)
6+
7+
func GetBuildMethod() string {
8+
kubernetesServiceHost := os.Getenv("KUBERNETES_SERVICE_HOST")
9+
kubernetesServicePort := os.Getenv("KUBERNETES_SERVICE_PORT")
10+
if kubernetesServiceHost == "" && kubernetesServicePort == "" {
11+
return "container"
12+
} else {
13+
return "kubernetes"
14+
}
15+
}

pkg/tuf/tuf.go

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package tuf
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"io/fs"
7+
"os"
8+
"strings"
9+
10+
"github.com/sigstore/scaffolding/pkg/certs"
11+
"knative.dev/pkg/logging"
12+
)
13+
14+
func ProcessTufFiles(ctx context.Context, tufFiles []fs.DirEntry, dir string) map[string][]byte {
15+
trimDir := strings.TrimSuffix(dir, "/")
16+
files := map[string][]byte{}
17+
for _, file := range tufFiles {
18+
if !file.IsDir() {
19+
logging.FromContext(ctx).Infof("Got file %s", file.Name())
20+
// Kubernetes adds some extra files here that are prefixed with
21+
// .., for example '..data' so skip those.
22+
if strings.HasPrefix(file.Name(), "..") {
23+
logging.FromContext(ctx).Infof("Skipping .. file %s", file.Name())
24+
continue
25+
}
26+
fileName := fmt.Sprintf("%s/%s", trimDir, file.Name())
27+
fileBytes, err := os.ReadFile(fileName)
28+
if err != nil {
29+
logging.FromContext(ctx).Fatalf("failed to read file %s/%s: %v", fileName, err)
30+
}
31+
// If it's a TSA file, we need to split it into multiple TUF
32+
// targets.
33+
if strings.Contains(file.Name(), "tsa") {
34+
logging.FromContext(ctx).Infof("Splitting TSA certchain into individual certs")
35+
36+
certFiles, err := certs.SplitCertChain(fileBytes, "tsa")
37+
if err != nil {
38+
logging.FromContext(ctx).Fatalf("failed to parse %s/%s: %v", fileName, err)
39+
}
40+
for k, v := range certFiles {
41+
logging.FromContext(ctx).Infof("Got tsa cert file %s", k)
42+
files[k] = v
43+
}
44+
} else {
45+
files[file.Name()] = fileBytes
46+
}
47+
}
48+
}
49+
return files
50+
}

0 commit comments

Comments
 (0)