mirror of
https://github.com/ultravioletrs/cocos.git
synced 2026-06-23 04:10:25 +00:00
d5badba547
CI / lint (push) Has been cancelled
CI / test (agent) (push) Has been cancelled
CI / test (cli) (push) Has been cancelled
CI / test (cmd) (push) Has been cancelled
CI / test (internal) (push) Has been cancelled
CI / test (manager, true) (push) Has been cancelled
CI / test (pkg) (push) Has been cancelled
CI / upload-coverage (push) Has been cancelled
* feat: Implement per-resource KBS configuration, allowing algorithms and datasets to specify individual KBS URLs. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * refactor: Encapsulate CLI error handling and CVM certificate paths within the CLI struct, and add algorithm type to agent's algorithm structure. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * style: Remove blank lines and fix indentation in CLI commands. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * refactor: Update downloadAndDecryptGenericResource to accept KBS URL as a parameter and adjust related tests Signed-off-by: Sammy Oina <sammyoina@gmail.com> * refactor: group CLI configuration into structured types and simplify skopeo decryption key handling Signed-off-by: Sammy Oina <sammyoina@gmail.com> --------- Signed-off-by: Sammy Oina <sammyoina@gmail.com>
135 lines
4.1 KiB
Go
135 lines
4.1 KiB
Go
// Copyright (c) Ultraviolet
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package oci
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
)
|
|
|
|
const (
|
|
// OCICryptKeyproviderConfig is the environment variable for ocicrypt config.
|
|
OCICryptKeyproviderConfig = "OCICRYPT_KEYPROVIDER_CONFIG"
|
|
|
|
// DefaultOCICryptConfig is the default path to ocicrypt config.
|
|
DefaultOCICryptConfig = "/etc/ocicrypt_keyprovider.conf"
|
|
|
|
// DecryptionKeyProvider is the decryption key provider for CoCo.
|
|
DecryptionKeyProvider = "provider:attestation-agent:cc_kbc::null"
|
|
)
|
|
|
|
// SkopeoClient wraps skopeo command-line operations.
|
|
type SkopeoClient struct {
|
|
skopeoPath string
|
|
workDir string
|
|
}
|
|
|
|
// NewSkopeoClient creates a new Skopeo client.
|
|
func NewSkopeoClient(workDir string) (*SkopeoClient, error) {
|
|
// Find skopeo binary
|
|
skopeoPath, err := exec.LookPath("skopeo")
|
|
if err != nil {
|
|
return nil, fmt.Errorf("skopeo not found in PATH: %w", err)
|
|
}
|
|
|
|
// Ensure work directory exists
|
|
if err := os.MkdirAll(workDir, 0o755); err != nil {
|
|
return nil, fmt.Errorf("failed to create work directory: %w", err)
|
|
}
|
|
|
|
return &SkopeoClient{
|
|
skopeoPath: skopeoPath,
|
|
workDir: workDir,
|
|
}, nil
|
|
}
|
|
|
|
// PullAndDecrypt pulls an OCI image and decrypts it if encrypted.
|
|
func (s *SkopeoClient) PullAndDecrypt(ctx context.Context, source ResourceSource, destDir string) error {
|
|
// Ensure destination directory exists
|
|
if err := os.MkdirAll(destDir, 0o755); err != nil {
|
|
return fmt.Errorf("failed to create destination directory: %w", err)
|
|
}
|
|
|
|
args := []string{"copy"}
|
|
|
|
// Add decryption key if image is encrypted.
|
|
// The KBS URL is configured at the CoCo Keyprovider service level
|
|
// (via kernel cmdline agent.aa_kbc_params), not via ocicrypt's --decryption-key flag.
|
|
if source.Encrypted {
|
|
args = append(args, "--decryption-key", DecryptionKeyProvider)
|
|
}
|
|
|
|
// Add insecure policy for testing (TODO: use proper policy in production)
|
|
args = append(args, "--insecure-policy", "--src-tls-verify=false", "--dest-tls-verify=false")
|
|
|
|
// Source and destination
|
|
args = append(args, source.URI, "oci:"+destDir)
|
|
|
|
cmd := exec.CommandContext(ctx, s.skopeoPath, args...)
|
|
|
|
// Set OCICRYPT environment
|
|
cmd.Env = append(os.Environ(),
|
|
OCICryptKeyproviderConfig+"="+DefaultOCICryptConfig)
|
|
|
|
// Set working directory
|
|
cmd.Dir = s.workDir
|
|
|
|
// Capture output
|
|
// Debug: Print full command
|
|
fmt.Printf("executing skopeo command: %s %v\n", s.skopeoPath, args)
|
|
fmt.Printf("skopeo environment: %s\n", OCICryptKeyproviderConfig+"="+DefaultOCICryptConfig)
|
|
|
|
output, err := cmd.CombinedOutput()
|
|
if err != nil {
|
|
return fmt.Errorf("skopeo copy failed: %w\nOutput: %s", err, string(output))
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Inspect inspects an OCI image and returns basic manifest information.
|
|
func (s *SkopeoClient) Inspect(ctx context.Context, imageRef string) (*ImageManifest, error) {
|
|
args := []string{"inspect", "--insecure-policy", "--tls-verify=false", imageRef}
|
|
|
|
cmd := exec.CommandContext(ctx, s.skopeoPath, args...)
|
|
cmd.Env = append(os.Environ(),
|
|
OCICryptKeyproviderConfig+"="+DefaultOCICryptConfig)
|
|
|
|
output, err := cmd.CombinedOutput()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("skopeo inspect failed: %w\nOutput: %s", err, string(output))
|
|
}
|
|
|
|
// For now, return basic info
|
|
// nolint:godox // TODO: Parse JSON output for detailed manifest info
|
|
return &ImageManifest{
|
|
Reference: imageRef,
|
|
}, nil
|
|
}
|
|
|
|
// ToDockerArchive converts an OCI directory to a Docker archive tarball.
|
|
func (s *SkopeoClient) ToDockerArchive(ctx context.Context, ociDir, destFile string) error {
|
|
args := []string{"copy", "--insecure-policy", "--src-tls-verify=false", "--dest-tls-verify=false", "oci:" + ociDir, "docker-archive:" + destFile}
|
|
|
|
cmd := exec.CommandContext(ctx, s.skopeoPath, args...)
|
|
cmd.Env = append(os.Environ(),
|
|
OCICryptKeyproviderConfig+"="+DefaultOCICryptConfig)
|
|
cmd.Dir = s.workDir
|
|
|
|
output, err := cmd.CombinedOutput()
|
|
if err != nil {
|
|
return fmt.Errorf("skopeo copy to docker-archive failed: %w\nOutput: %s", err, string(output))
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetLocalImagePath returns the path to a local OCI image directory.
|
|
func (s *SkopeoClient) GetLocalImagePath(name string) string {
|
|
return filepath.Join(s.workDir, name)
|
|
}
|