Commit ea597e5b authored by Vasilis Katopodis's avatar Vasilis Katopodis
Browse files

fix: isolate OCI registry credentials from host Docker config

Fixes #10
parent bf72df1a
Loading
Loading
Loading
Loading
Loading
+0 −1
Changes for .gitignore: 0 added lines, 1 removed line.
Original line number Diff line number Diff line
tmp/
.air.toml
org.etsi.osl.hypo.core.pkg-manager.helm
GEMINI.md
CLAUDE.md
.claude/
bin/
+4 −0
Changes for Makefile: 4 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -24,6 +24,10 @@ fmt: ## Run gofmt against code.
vet: ## Run go vet against code.
	go vet ./...

.PHONY: tidy
tidy: ## Tidy go.mod/go.sum.
	go mod tidy

.PHONY: lint
lint: ## Run golangci-lint. Set LINT_ARGS to append flags (e.g. CI report output).
	$(GOLANGCI_LINT) run ./... --fast-only $(LINT_ARGS)
+0 −28
Changes for commons/general.go: 0 added lines, 28 removed lines.
Original line number Diff line number Diff line
@@ -13,7 +13,6 @@ import (
	"strings"
	"time"

	"github.com/distribution/reference"
	"helm.sh/helm/v3/pkg/registry"
	"labs.etsi.org/rep/osl/hypo/code/org.etsi.osl.hypo.core/pkg-manager.helm/internal/logging"
)
@@ -95,19 +94,6 @@ func CheckIfRepoIsPublic(ctx context.Context, log logging.Logger, serviceID stri
	}
}

func GetRegistryDomain(url string) (string, error) {
	url = strings.TrimSuffix(url, "/")
	// Parse the URL using the reference package
	parsed, err := reference.ParseNormalizedNamed(url)
	if err != nil {
		return "", fmt.Errorf("failed to parse URL: %v", err)
	}

	// Extract the domain part
	domain := reference.Domain(parsed)
	return domain, nil
}

// OCI prefix is correctly formatted and prevents issues where "oci://" could become "oci:/".
func FormatOCIChartReference(repositoryURL string, chartName string) string {
	repositoryURLWithoutScheme := strings.TrimPrefix(repositoryURL, fmt.Sprintf("%s://", registry.OCIScheme))
@@ -140,17 +126,3 @@ func ShortenUUIDString(uuidStr string) string {
	segments := strings.Split(uuidStr, "-")
	return segments[len(segments)-1]
}

// TODO: Migrate this logic to the Monitoring Service
//
// const defaultClusterNodeCount = 1
// func calculateResources(logger logging.Logger, manifests string) (int, error) {
// 	k8sResources, err := resources.Calculate(manifests)
// 	if err != nil {
// 		return 0, fmt.Errorf("resources calculation failed: %w", err)
// 	}
// 	logger.Debug("Calculated Total cpu: %.1f cores", k8sResources.CPU)
// 	logger.Debug("Calculated Total memory: %.1fM", k8sResources.Memory)

// 	return defaultClusterNodeCount, nil
// }
+1 −1
Changes for go.mod: 1 added line, 1 removed line.
Original line number Diff line number Diff line
@@ -5,7 +5,6 @@ go 1.25.0
require (
	github.com/Masterminds/semver v1.5.0
	github.com/arttor/helmify v0.4.13
	github.com/distribution/reference v0.6.0
	github.com/go-git/go-billy/v5 v5.5.0
	github.com/google/uuid v1.6.0
	github.com/joho/godotenv v1.5.1
@@ -53,6 +52,7 @@ require (
	github.com/containerd/platforms v0.2.1 // indirect
	github.com/cyphar/filepath-securejoin v0.2.5 // indirect
	github.com/deckarep/golang-set v1.8.0 // indirect
	github.com/distribution/reference v0.6.0 // indirect
	github.com/docker/cli v27.1.0+incompatible // indirect
	github.com/docker/docker v28.5.1+incompatible // indirect
	github.com/docker/docker-credential-helpers v0.8.2 // indirect
+16 −5
Changes for ops/helmParseHandler.go: 16 added lines, 5 removed lines.
Original line number Diff line number Diff line
@@ -312,44 +312,55 @@ func (op *Operator) processDockerComposeToHelm(ctx context.Context, serviceOrder

	serviceID := serviceOrder.ServiceID

	op.Logger.Debug("[ServiceID: %s] Executing Docker Compose -> Helm translation", serviceID)
	op.Logger.Debug("service_id=%s msg=\"Executing Docker Compose -> Helm translation.\"", serviceID)
	conversionResult, err := op.helmConverter.ConvertDockerComposeToHelmCharts(ctx, serviceOrder, credentials.Username, credentials.Password)
	if err != nil {
		return nil, fmt.Errorf("compose conversion failed: %w", err)
	}

	defer func() {
		op.Logger.Debug("service_id=%s msg=\"Cleaning up temporary export files.\"", serviceID)
		contextTag := fmt.Sprintf("service_id=%s", serviceID)
	defer commons.CleanupFiles(op.Logger, contextTag, conversionResult.ExportedFilesPath)
		commons.CleanupFiles(op.Logger, contextTag, conversionResult.ExportedFilesPath)
	}()

	return op.internalRegistryClient.PackageChartWithMetadata(ctx, defaultRepoName, serviceOrder.ServiceID, conversionResult.HelmChartsPath)
}

func (op *Operator) processOCIRegistry(ctx context.Context, registryURL, chartName, chartVersion string, credentials *registryapi.RepoCredentials) ([]byte, error) {
	op.Logger.Debug("component=oci_registry msg=\"processOCIRegistry called.\" registry_url=\"%s\" chart_name=\"%s\" chart_version=\"%s\" has_credentials=%v",
		registryURL, chartName, chartVersion, credentials != nil)

	dl, regClient, err := newTracedDownloader(ctx, op.Logger)
	if err != nil {
		return nil, err
	}

	formattedOCIChartReference := commons.FormatOCIChartReference(registryURL, chartName)
	registryURLWithoutScheme := strings.TrimPrefix(registryURL, fmt.Sprintf("%s://", registry.OCIScheme))

	if credentials != nil {
		dl.Options = append(dl.Options, getter.WithBasicAuth(credentials.Username, credentials.Password))
		registryDomain, _ := commons.GetRegistryDomain(registryURLWithoutScheme)
		registryDomain := commons.ExtractOCIDomain(registryURL)

		op.Logger.Debug("component=oci_registry msg=\"Logging in to OCI registry.\" domain=\"%s\" username=\"%s\"", registryDomain, credentials.Username)

		if err := regClient.Login(
			registryDomain,
			registry.LoginOptBasicAuth(credentials.Username, credentials.Password),
			registry.LoginOptInsecure(true)); err != nil {
		); err != nil {
			return nil, fmt.Errorf("OCI login failed: %w", err)
		}
	}

	op.Logger.Debug("component=oci_registry msg=\"Resolving chart version.\" ref=\"%s\" version=\"%s\"", formattedOCIChartReference, chartVersion)
	chartURL, err := dl.ResolveChartVersion(formattedOCIChartReference, chartVersion)
	if err != nil {
		return nil, fmt.Errorf("failed to resolve OCI version: %w", err)
	}

	chartReference := strings.TrimPrefix(chartURL.String(), fmt.Sprintf("%s://", registry.OCIScheme))

	op.Logger.Debug("component=oci_registry msg=\"Pulling chart.\" ref=\"%s\"", chartReference)
	chartData, err := regClient.Pull(chartReference)
	if err != nil {
		return nil, fmt.Errorf("failed to pull OCI helm chart: %w", err)
Loading