Skip to content
Closed
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
1 change: 1 addition & 0 deletions .github/workflows/e2e_manual.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ on:
- gpu
- imagepuller-auth
- imagestore
- insecure
- kds-pcs-downtime
- memdump
- multi-runtime-class
Expand Down
71 changes: 59 additions & 12 deletions cli/cmd/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ subcommands.`,
cmd.Flags().Bool("inject-image-store", false, "inject an ephemeral storage device to pull images onto instead of into memory")
cmd.Flags().Bool("insecure-enable-debug-shell-access", false, "enable the debug shell service in the pod CVM to get access from container to guest VM")
cmd.Flags().StringP("output", "o", "", "output file for generated YAML")
cmd.Flags().Bool("INSECURE", false, "allow generation for insecure (non-CC) runtimes (also requires the CONTRAST_ALLOW_INSECURE_RUNTIMES environment variable to be set)")
must(cmd.MarkFlagFilename("policy", "rego"))
must(cmd.MarkFlagFilename("settings", "json"))
must(cmd.MarkFlagFilename("manifest", "json"))
Expand Down Expand Up @@ -147,6 +148,10 @@ func runGenerate(cmd *cobra.Command, args []string) error {
usedPlatforms.Add(flags.referenceValuesPlatform)
}

if err := validateInsecurePlatforms(usedPlatforms, flags.allowInsecureRuntimes); err != nil {
return err
}

// generate a manifest by checking if a manifest exists and using that,
// or otherwise using a default.
var mnf *manifest.Manifest
Expand Down Expand Up @@ -284,17 +289,17 @@ func runGenerate(cmd *cobra.Command, args []string) error {
return nil
}

// mapCCWorkloads applies the given function to all workloads with the 'contrast-cc' runtime class.
// mapContrastWorkloads applies the given function to all workloads with the 'contrast-cc' or 'contrast-insecure' runtime class.
// The callback receives an apply configuration together with the file path and index the unstructured object has in the file map.
// Changes to the apply configuration are not applied to the original unstructured object.
func mapCCWorkloads(fileMap map[string][]*unstructured.Unstructured, f func(res any, path string, idx int) (any, error)) error {
func mapContrastWorkloads(fileMap map[string][]*unstructured.Unstructured, f func(res any, path string, idx int) (any, error)) error {
for path, resources := range fileMap {
for idx, r := range resources {
applyConfig, err := kuberesource.UnstructuredToApplyConfiguration(r)
if err != nil {
continue
}
if !isCCWorkload(applyConfig) {
if !isContrastWorkload(applyConfig) {
continue
}
changed, err := f(applyConfig, path, idx)
Expand All @@ -313,9 +318,9 @@ func mapCCWorkloads(fileMap map[string][]*unstructured.Unstructured, f func(res
return nil
}

func isCCWorkload(resource any) (ret bool) {
func isContrastWorkload(resource any) (ret bool) {
kuberesource.MapPodSpec(resource, func(spec *applycorev1.PodSpecApplyConfiguration) *applycorev1.PodSpecApplyConfiguration {
if spec != nil && spec.RuntimeClassName != nil && strings.HasPrefix(*spec.RuntimeClassName, "contrast-cc") {
if kuberesource.IsContrastPod(spec) {
ret = true
}
return spec
Expand All @@ -336,10 +341,20 @@ func isCoordinator(resource any) bool {
return false
}

func patchCoordinatorAllowInsecure(resource any) {
r, ok := resource.(*applyappsv1.StatefulSetApplyConfiguration)
if !ok || !isCoordinator(resource) {
return
}
if len(r.Spec.Template.Spec.Containers) > 0 {
r.Spec.Template.Spec.Containers[0].WithEnv(kuberesource.NewEnvVar("CONTRAST_ALLOW_INSECURE", "1"))
}
}

func runVerifiers(fileMap map[string][]*unstructured.Unstructured, verifiers []verifier.Verifier) error {
var findings error
for _, v := range verifiers {
_ = mapCCWorkloads(fileMap, func(res any, path string, idx int) (any, error) {
_ = mapContrastWorkloads(fileMap, func(res any, path string, idx int) (any, error) {
if err := v.Verify(res); err != nil {
findings = errors.Join(findings, fmt.Errorf("failed to verify resource %q in file %q: %w", fileMap[path][idx].GetName(), path, err))
}
Expand Down Expand Up @@ -406,7 +421,7 @@ func extractTargets(paths []string, configFile io.Writer, logger *slog.Logger) (
applyConfig, err := kuberesource.UnstructuredToApplyConfiguration(object)
if err != nil {
logger.Warn("Could not convert resource into ApplyConfiguration", "path", path, "err", err)
} else if isCCWorkload(applyConfig) {
} else if isContrastWorkload(applyConfig) {
containsCC = true
if isCoordinator(applyConfig) {
r, ok := applyConfig.(*applyappsv1.StatefulSetApplyConfiguration)
Expand All @@ -421,7 +436,7 @@ func extractTargets(paths []string, configFile io.Writer, logger *slog.Logger) (
}
}
if len(fileMap) == 0 {
return nil, "", fmt.Errorf("no .yml/.yaml files with 'contrast-cc' runtime found")
return nil, "", fmt.Errorf("no .yml/.yaml files with 'contrast-cc' or 'contrast-insecure' runtime found")
}

extraData, err := kuberesource.EncodeUnstructured(extraResources)
Expand Down Expand Up @@ -454,7 +469,7 @@ func generatePolicies(ctx context.Context, flags *generateFlags, fileMap map[str
}
}()

return mapCCWorkloads(fileMap, func(res any, path string, idx int) (any, error) {
return mapContrastWorkloads(fileMap, func(res any, path string, idx int) (any, error) {
initdataAnno, err := runner.Run(ctx, res, extraPath, logger)
if err != nil {
return nil, fmt.Errorf("failed to generate policy for %q in %q: %w", fileMap[path][idx].GetName(), path, err)
Expand Down Expand Up @@ -496,7 +511,7 @@ func patchTargets(fileMap map[string][]*unstructured.Unstructured, imageReplacem
return fmt.Errorf("parsing release image definitions %s: %w", ReleaseImageReplacements, err)
}
}
return mapCCWorkloads(fileMap, func(res any, _ string, _ int) (any, error) {
return mapContrastWorkloads(fileMap, func(res any, _ string, _ int) (any, error) {
if flags.insecureEnableDebugShell {
if _, err := kuberesource.AddDebugShell(res, kuberesource.DebugShell()); err != nil {
return nil, fmt.Errorf("injecting debug shell container: %w", err)
Expand All @@ -515,6 +530,9 @@ func patchTargets(fileMap map[string][]*unstructured.Unstructured, imageReplacem
if flags.injectImageStore {
kuberesource.AddImageStore([]any{res})
}
if flags.allowInsecureRuntimes {
patchCoordinatorAllowInsecure(res)
}

kuberesource.PatchImages([]any{res}, replacements)

Expand Down Expand Up @@ -556,6 +574,19 @@ func injectServiceMesh(resource any) error {
return nil
}

func validateInsecurePlatforms(usedPlatforms kuberesource.PlatformCollection, allowInsecure bool) error {
if !slices.ContainsFunc(usedPlatforms.Platforms(), platforms.IsInsecure) {
return nil
}
if !allowInsecure {
return fmt.Errorf("insecure runtime platforms detected but --INSECURE flag not set")
}
if os.Getenv("CONTRAST_ALLOW_INSECURE_RUNTIMES") == "" {
return fmt.Errorf("insecure runtime platforms detected but CONTRAST_ALLOW_INSECURE_RUNTIMES environment variable not set")
}
return nil
}

func validateOutputFile(outputFile string) error {
if outputFile == "" {
return nil
Expand Down Expand Up @@ -683,7 +714,17 @@ func patchRuntimeClassName(defaultRuntimeHandler string) func(*applycorev1.PodSp
if spec == nil || spec.RuntimeClassName == nil {
return spec, nil
}
if *spec.RuntimeClassName == "kata-cc-isolation" || *spec.RuntimeClassName == "contrast-cc" {
if *spec.RuntimeClassName == "kata-cc-isolation" || *spec.RuntimeClassName == "contrast-cc" || *spec.RuntimeClassName == "contrast-insecure" {
// Only allow the bare runtime class names if the default runtime handler is compatible.
// For example, `contrast-cc` should only resolve when `--reference-values` is set to a CC-enabled platform,
// and `contrast-insecure` should only resolve when `--reference-values` is set to an insecure platform.
if *spec.RuntimeClassName == "contrast-insecure" && !strings.HasPrefix(defaultRuntimeHandler, "contrast-insecure-") {
return nil, fmt.Errorf("bare 'contrast-insecure' runtime class requires --reference-values to be set to an insecure platform")
}
if (*spec.RuntimeClassName == "contrast-cc" || *spec.RuntimeClassName == "kata-cc-isolation") &&
strings.HasPrefix(defaultRuntimeHandler, "contrast-insecure-") {
return nil, fmt.Errorf("bare %q runtime class is incompatible with insecure --reference-values platform %q", *spec.RuntimeClassName, defaultRuntimeHandler)
}
spec.RuntimeClassName = &defaultRuntimeHandler
if kuberesource.PodSpecRequiresGPU(spec) {
platform, err := platforms.FromRuntimeClassString(*spec.RuntimeClassName)
Expand All @@ -698,7 +739,7 @@ func patchRuntimeClassName(defaultRuntimeHandler string) func(*applycorev1.PodSp
}
return spec, nil
}
if !strings.HasPrefix(*spec.RuntimeClassName, "contrast-cc-") {
if !kuberesource.IsContrastPod(spec) {
return spec, nil
}
overridePlatform, err := platforms.FromRuntimeClassString(*spec.RuntimeClassName)
Expand Down Expand Up @@ -870,6 +911,7 @@ type generateFlags struct {
skipServiceMesh bool
injectImageStore bool
insecureEnableDebugShell bool
allowInsecureRuntimes bool
outputFile string
}

Expand Down Expand Up @@ -967,6 +1009,10 @@ func parseGenerateFlags(cmd *cobra.Command) (*generateFlags, error) {
if err != nil {
return nil, err
}
allowInsecureRuntimes, err := cmd.Flags().GetBool("INSECURE")
if err != nil {
return nil, err
}
outputFile, err := cmd.Flags().GetString("output")
if err != nil {
return nil, err
Expand All @@ -992,6 +1038,7 @@ func parseGenerateFlags(cmd *cobra.Command) (*generateFlags, error) {
skipServiceMesh: skipServiceMesh,
injectImageStore: injectImageStore,
insecureEnableDebugShell: insecureEnableDebugShell,
allowInsecureRuntimes: allowInsecureRuntimes,
outputFile: outputFile,
}, nil
}
Expand Down
Loading
Loading