From ed1a06d9d827ea1ef74f5faa83b14805213de99b Mon Sep 17 00:00:00 2001 From: Jordan Raub Date: Fri, 31 Jan 2025 12:42:35 -0800 Subject: [PATCH] certificate propagation throughout the build process --- Dockerfile | 6 +++ certificates/.gitignore | 1 + pkg/combustion/combustion.go | 2 +- pkg/combustion/rpm.go | 4 +- pkg/combustion/rpm_test.go | 6 +-- pkg/rpm/resolver/resolver.go | 38 +++++++++++++++++-- pkg/rpm/resolver/templates/Dockerfile.tpl | 2 + .../resolver/templates/rpm-resolution.sh.tpl | 2 + 8 files changed, 53 insertions(+), 8 deletions(-) create mode 100644 certificates/.gitignore diff --git a/Dockerfile b/Dockerfile index 7e6b0f22..d2c175d3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,9 @@ # ----- EIB Builder Image ----- FROM registry.suse.com/bci/golang:1.22-1.36.1 +COPY certificates/. /etc/pki/trust/anchors/ +RUN update-ca-certificates + # Dependency uses by line # 1. Podman Go library RUN zypper install -y \ @@ -20,6 +23,9 @@ RUN --mount=type=cache,id=gomod,target=/go/pkg/mod \ # ----- Deliverable Image ----- FROM opensuse/leap:15.6 +COPY certificates/. /etc/pki/trust/anchors/ +RUN update-ca-certificates + # Dependency uses by line # 1. ISO image building # 2. RAW image modification on x86_64 and aarch64 diff --git a/certificates/.gitignore b/certificates/.gitignore new file mode 100644 index 00000000..72e8ffc0 --- /dev/null +++ b/certificates/.gitignore @@ -0,0 +1 @@ +* diff --git a/pkg/combustion/combustion.go b/pkg/combustion/combustion.go index dcb2724a..a0f53df7 100644 --- a/pkg/combustion/combustion.go +++ b/pkg/combustion/combustion.go @@ -41,7 +41,7 @@ type kubernetesArtefactDownloader interface { } type rpmResolver interface { - Resolve(packages *image.Packages, localRPMConfig *image.LocalRPMConfig, outputDir string) (rpmDirPath string, pkgList []string, err error) + Resolve(packages *image.Packages, localRPMConfig *image.LocalRPMConfig, certsPath, outputDir string) (rpmDirPath string, pkgList []string, err error) } type rpmRepoCreator interface { diff --git a/pkg/combustion/rpm.go b/pkg/combustion/rpm.go index 9e37644b..62745267 100644 --- a/pkg/combustion/rpm.go +++ b/pkg/combustion/rpm.go @@ -59,8 +59,10 @@ func (c *Combustion) configureRPMs(ctx *image.Context) ([]string, error) { return nil, fmt.Errorf("creating rpm artefacts path: %w", err) } + certsPath := filepath.Join(ctx.ImageConfigDir, certsConfigDir) + log.Audit("Resolving package dependencies...") - repoPath, pkgsList, err := c.RPMResolver.Resolve(packages, localRPMConfig, artefactsPath) + repoPath, pkgsList, err := c.RPMResolver.Resolve(packages, localRPMConfig, certsPath, artefactsPath) if err != nil { log.AuditComponentFailed(rpmComponentName) return nil, fmt.Errorf("resolving rpm/package dependencies: %w", err) diff --git a/pkg/combustion/rpm_test.go b/pkg/combustion/rpm_test.go index 2ddcb1ae..b90793e5 100644 --- a/pkg/combustion/rpm_test.go +++ b/pkg/combustion/rpm_test.go @@ -14,12 +14,12 @@ import ( ) type mockRPMResolver struct { - resolveFunc func(packages *image.Packages, localRPMConfig *image.LocalRPMConfig, outputDir string) (rpmDir string, pkgList []string, err error) + resolveFunc func(packages *image.Packages, localRPMConfig *image.LocalRPMConfig, certsPath, outputDir string) (rpmDir string, pkgList []string, err error) } -func (m mockRPMResolver) Resolve(packages *image.Packages, localRPMConfig *image.LocalRPMConfig, outputDir string) (rpmDir string, pkgList []string, err error) { +func (m mockRPMResolver) Resolve(packages *image.Packages, localRPMConfig *image.LocalRPMConfig, certsPath, outputDir string) (rpmDir string, pkgList []string, err error) { if m.resolveFunc != nil { - return m.resolveFunc(packages, localRPMConfig, outputDir) + return m.resolveFunc(packages, localRPMConfig, certsPath, outputDir) } panic("not implemented") diff --git a/pkg/rpm/resolver/resolver.go b/pkg/rpm/resolver/resolver.go index edcbcf07..2fc7ef32 100644 --- a/pkg/rpm/resolver/resolver.go +++ b/pkg/rpm/resolver/resolver.go @@ -81,7 +81,7 @@ func New(workDir string, podman Podman, baseImageBuilder BaseResolverImageBuilde // - localRPMConfig - configuration for locally provided RPMs // // - outputDir - directory in which the resolver will create a directory containing the resolved rpms. -func (r *Resolver) Resolve(packages *image.Packages, localRPMConfig *image.LocalRPMConfig, outputDir string) (rpmDirPath string, pkgList []string, err error) { +func (r *Resolver) Resolve(packages *image.Packages, localRPMConfig *image.LocalRPMConfig, certsPath, outputDir string) (rpmDirPath string, pkgList []string, err error) { zap.L().Info("Resolving package dependencies...") revert, err := mount.DisableDefaultMounts(r.overrideMountsPath) @@ -98,7 +98,7 @@ func (r *Resolver) Resolve(packages *image.Packages, localRPMConfig *image.Local return "", nil, fmt.Errorf("building base resolver image: %w", err) } - if err = r.prepare(localRPMConfig, packages); err != nil { + if err = r.prepare(localRPMConfig, packages, certsPath); err != nil { return "", nil, fmt.Errorf("generating context for the resolver image: %w", err) } @@ -122,7 +122,7 @@ func (r *Resolver) Resolve(packages *image.Packages, localRPMConfig *image.Local return filepath.Join(outputDir, rpmRepoName), r.generatePKGInstallList(packages), nil } -func (r *Resolver) prepare(localRPMConfig *image.LocalRPMConfig, packages *image.Packages) error { +func (r *Resolver) prepare(localRPMConfig *image.LocalRPMConfig, packages *image.Packages, certsPath string) error { zap.L().Info("Preparing resolver image context...") buildContext := r.generateBuildContextPath() @@ -136,6 +136,10 @@ func (r *Resolver) prepare(localRPMConfig *image.LocalRPMConfig, packages *image } } + if err := r.prepareCertificates(certsPath); err != nil { + return fmt.Errorf("preparing certificates for resolver image build: %w", err) + } + if err := r.writeRPMResolutionScript(localRPMConfig, packages); err != nil { return fmt.Errorf("writing rpm resolution script: %w", err) } @@ -148,6 +152,29 @@ func (r *Resolver) prepare(localRPMConfig *image.LocalRPMConfig, packages *image return nil } +func (r *Resolver) prepareCertificates(certsPath string) error { + certsDest := r.generateCertificatePathInBuildContext() + + if err := os.MkdirAll(certsDest, os.ModePerm); err != nil { + return fmt.Errorf("creating certificates dir %s: %w", certsDest, err) + } + + if _, err := os.Stat(certsPath); os.IsNotExist(err) { + zap.S().Info("skipping certificates, no certificates provided") + return nil + } + + if err := fileio.CopyFiles(certsPath, certsDest, ".crt", false, &fileio.NonExecutablePerms); err != nil { + return fmt.Errorf("copying crt files to %s: %w", certsDest, err) + } + + if err := fileio.CopyFiles(certsPath, certsDest, ".pem", false, &fileio.NonExecutablePerms); err != nil { + return fmt.Errorf("copying pem files to %s: %w", certsDest, err) + } + + return nil +} + func (r *Resolver) prepareLocalRPMs(localRPMConfig *image.LocalRPMConfig) error { rpmDest := r.generateRPMPathInBuildContext() if err := fileio.CopyFiles(localRPMConfig.RPMPath, rpmDest, ".rpm", false, &fileio.NonExecutablePerms); err != nil { @@ -274,6 +301,11 @@ func (r *Resolver) generateBuildContextPath() string { return filepath.Join(r.dir, "resolver-image-build") } +// path to the certificates directory in the resolver build context, as seen in the EIB image +func (r *Resolver) generateCertificatePathInBuildContext() string { + return filepath.Join(r.generateBuildContextPath(), "certificates") +} + // path to the rpms directory in the resolver build context, as seen in the EIB image func (r *Resolver) generateRPMPathInBuildContext() string { return filepath.Join(r.generateBuildContextPath(), "rpms") diff --git a/pkg/rpm/resolver/templates/Dockerfile.tpl b/pkg/rpm/resolver/templates/Dockerfile.tpl index 0e70f4fe..665492c1 100644 --- a/pkg/rpm/resolver/templates/Dockerfile.tpl +++ b/pkg/rpm/resolver/templates/Dockerfile.tpl @@ -16,6 +16,8 @@ COPY {{ .FromGPGPath }} {{ .ToGPGPath }} {{ end -}} {{ end }} +COPY certificates/. /etc/pki/trust/anchors/ + RUN ./{{ .RPMResolutionScriptName }} CMD ["/bin/bash"] \ No newline at end of file diff --git a/pkg/rpm/resolver/templates/rpm-resolution.sh.tpl b/pkg/rpm/resolver/templates/rpm-resolution.sh.tpl index 5fdd8766..d5f2a4e1 100644 --- a/pkg/rpm/resolver/templates/rpm-resolution.sh.tpl +++ b/pkg/rpm/resolver/templates/rpm-resolution.sh.tpl @@ -12,6 +12,8 @@ set -euo pipefail # Arch - sets the architecture of the rpm packages to pull # EnableExtras - registers the SL-Micro-Extras repo for use in resolution +update-ca-certificates -v + {{ if ne .RegCode "" }} suseconnect -r {{ .RegCode }} {{ if $.EnableExtras -}}