Skip to content

Commit

Permalink
Merge pull request #153 from nicholasSUSE/slsa-charts-bypass
Browse files Browse the repository at this point in the history
Slsa charts bypass
  • Loading branch information
nicholasSUSE authored Nov 19, 2024
2 parents 41d67c0 + c31aa1d commit cafb872
Show file tree
Hide file tree
Showing 3 changed files with 185 additions and 7 deletions.
18 changes: 17 additions & 1 deletion pkg/path/path.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,41 +6,54 @@ const (

// RepositoryHelmIndexFile is the file on your Staging/Live branch that contains your Helm repository index
RepositoryHelmIndexFile = "index.yaml"

// RepositoryPackagesDir is a directory on your Staging branch that contains the files necessary to generate your package
RepositoryPackagesDir = "packages"

// RepositoryAssetsDir is a directory on your Staging/Live branch that contains chart archives for each version of your package
RepositoryAssetsDir = "assets"

// RepositoryChartsDir is a directory on your Staging/Live branch that contains unarchived charts for each version of your package
RepositoryChartsDir = "charts"

// PackageOptionsFile is the name of a file that contains information about how to prepare your package
// The expected structure of this file is one that can be marshalled into a PackageOptions struct
PackageOptionsFile = "package.yaml"

// PackageTemplatesDir is a directory containing templates used as additional chart options
PackageTemplatesDir = "templates"

// GeneratedChangesDir is a directory that contains GeneratedChanges
GeneratedChangesDir = "generated-changes"

// GeneratedChangesAdditionalChartDir is a directory that contains additionalCharts
GeneratedChangesAdditionalChartDir = "additional-charts"

// GeneratedChangesDependenciesDir is a directory that contains dependencies within GeneratedChangesDir
GeneratedChangesDependenciesDir = "dependencies"

// GeneratedChangesExcludeDir is a directory that contains excludes within GeneratedChangesDir
GeneratedChangesExcludeDir = "exclude"

// GeneratedChangesOverlayDir is a directory that contains overlays within GeneratedChangesDir
GeneratedChangesOverlayDir = "overlay"

// GeneratedChangesPatchDir is a directory that contains patches within GeneratedChangesDir
GeneratedChangesPatchDir = "patch"

// DependencyOptionsFile is a file that contains information about how to prepare your dependency
// The expected structure of this file is one that can be marshalled into a ChartOptions struct
DependencyOptionsFile = "dependency.yaml"

// ChartCRDDir represents the directory that we expect to contain CRDs within the chart
ChartCRDDir = "crds"

// ChartExtraFileDir represents the directory that contains non-YAML files
ChartExtraFileDir = "files"

// ChartCRDTgzFilename represents the filename of the crd's tgz file
ChartCRDTgzFilename = "crd-manifest.tgz"

// ChartValidateInstallCRDFile is the path to the file pushed to upstream that validates the existence of CRDs in the chart
ChartValidateInstallCRDFile = "templates/validate-install-crd.yaml"

Expand All @@ -50,12 +63,15 @@ const (
// RepositoryLogosDir is a directory on your Staging/Live branch that contains the files with the logos of each chart
RepositoryLogosDir = "assets/logos"

// RepositoryStAte file is a file to hold the current status of the released and developed assets versions
// RepositoryStateFile is a file to hold the current status of the released and developed assets versions
RepositoryStateFile = "state.json"

// RepositoryReleaseYaml is the file on your Staging/Live branch that contains the release information
RepositoryReleaseYaml = "release.yaml"

// VersionRulesFile is the file that contains the version rules for the current branch on charts-build-scripts
VersionRulesFile = "version_rules.json"

// SlsaYamlFile is the file that contains the list of images already synced and signed for SLSA.
SlsaYamlFile = "slsa.yaml"
)
56 changes: 50 additions & 6 deletions pkg/regsync/generateconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,14 @@ import (
"sort"
"strings"

"github.com/rancher/charts-build-scripts/pkg/path"
"golang.org/x/exp/slices"
"gopkg.in/yaml.v2"
)

// ReadSlsaYamlFunc is a function type that reads the slsa.yaml file and returns a list of images.
type ReadSlsaYamlFunc func() ([]string, error)

// chartsToIgnoreTags and systemChartsToIgnoreTags defines the charts and system charts in which a specified
// image tag should be ignored.
var chartsToIgnoreTags = map[string]string{
Expand All @@ -26,18 +30,17 @@ var chartsToIgnoreTags = map[string]string{
func GenerateConfigFile() error {
imageTagMap := make(map[string][]string)

err := walkAssetsFolder(imageTagMap)
if err != nil {
if err := walkAssetsFolder(imageTagMap); err != nil {
return err
}

// Create the regsync config file
err = createRegSyncConfigFile(imageTagMap)
if err != nil {
// Remove the images that are already signed from the imageTagMap
if err := removeSlsaImages(imageTagMap, readSlsaYaml); err != nil {
return err
}

return nil
// Create the regsync config file
return createRegSyncConfigFile(imageTagMap)
}

// walkAssetsFolder walks over the assets folder, untars files, stores the values.yaml content
Expand Down Expand Up @@ -217,3 +220,44 @@ func walkMap(inputMap interface{}, callback func(map[interface{}]interface{})) {
}
}
}

// removeSlsaImages removes the images that are already signed from the imageTagMap.
func removeSlsaImages(imageTagMap map[string][]string, readSlsaYaml ReadSlsaYamlFunc) error {
// Get the list of images that should not be synced with the registry.
// These images are defined in the slsa.yaml file.
// We will remove these images from the imageTagMap.
slsaImgs, err := readSlsaYaml()
if err != nil {
return err
}

// The images will not be synced because they are already:
// - Signed
// - Synced with the registry
if slsaImgs != nil {
for _, img := range slsaImgs {
delete(imageTagMap, img)
}
}
return nil
}

func readSlsaYaml() ([]string, error) {
var slsaImgs []string

file, err := os.Open(path.SlsaYamlFile)
if err != nil {
return nil, err // backward version compatibility
}
defer file.Close()

decoder := yaml.NewDecoder(file)
if err := decoder.Decode(&slsaImgs); err != nil {
if err == io.EOF {
return slsaImgs, nil // Handle EOF error gracefully
}
return nil, err
}

return slsaImgs, nil
}
118 changes: 118 additions & 0 deletions pkg/regsync/generateconfig_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package regsync

import (
"testing"

"github.com/stretchr/testify/require"
)

func Test_SlsaYaml(t *testing.T) {

type input struct {
imageTagMap map[string][]string
readSlsaYamlMock func() ([]string, error)
}

type expected struct {
err error
imageTagMap map[string][]string
}

type test struct {
name string
input input
expected expected
}

tests := []test{
{
name: "#1",
input: input{
imageTagMap: map[string][]string{
"image1": {"tag1"},
"image2": {"tag2"},
"image3": {"tag3"},
},
readSlsaYamlMock: func() ([]string, error) {
return []string{"image1"}, nil
},
},
expected: expected{
err: nil,
imageTagMap: map[string][]string{
"image2": {"tag2"},
"image3": {"tag3"},
},
},
},
{
name: "#2",
input: input{
imageTagMap: map[string][]string{
"image1": {"tag1", "tag2"},
"image2": {"tag2"},
"image3": {"tag3", "tag4"},
},
readSlsaYamlMock: func() ([]string, error) {
return []string{"image1", "image2"}, nil
},
},
expected: expected{
err: nil,
imageTagMap: map[string][]string{
"image3": {"tag3", "tag4"},
},
},
},
{
name: "#3",
input: input{
imageTagMap: map[string][]string{
"image1": {"tag1", "tag2"},
},
readSlsaYamlMock: func() ([]string, error) {
return []string{"image1", "image2"}, nil
},
},
expected: expected{
err: nil,
imageTagMap: map[string][]string{},
},
},
{
name: "#4",
input: input{
imageTagMap: map[string][]string{},
readSlsaYamlMock: func() ([]string, error) {
return []string{"image1", "image2"}, nil
},
},
expected: expected{
err: nil,
imageTagMap: map[string][]string{},
},
},
{
name: "#5",
input: input{
imageTagMap: map[string][]string{},
readSlsaYamlMock: func() ([]string, error) {
return []string{}, nil
},
},
expected: expected{
err: nil,
imageTagMap: map[string][]string{},
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := removeSlsaImages(tt.input.imageTagMap, tt.input.readSlsaYamlMock)
require.NoError(t, err)
require.Equal(t, tt.expected.imageTagMap, tt.input.imageTagMap)

})
}
}

0 comments on commit cafb872

Please sign in to comment.