diff --git a/cmd/root.go b/cmd/root.go index ee21bdc1..c9c92845 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -56,6 +56,7 @@ func init() { withDefault("gitlab")) stringFlag(flags, "vcs-token", "VCS API token.") stringFlag(flags, "argocd-api-token", "ArgoCD API token.") + stringFlag(flags, "argocd-api-path-prefix", "ArgoCD API Path Prefix.") stringFlag(flags, "argocd-api-server-addr", "ArgoCD API Server Address.", newStringOpts().withDefault("argocd-server")) boolFlag(flags, "argocd-api-insecure", "Enable to use insecure connections to the ArgoCD API server.") stringFlag(flags, "kubernetes-config", "Path to your kubernetes config file, used to monitor applications.") @@ -73,6 +74,8 @@ func init() { withDefault([]string{"./schemas"})) boolFlag(flags, "enable-conftest", "Set to true to enable conftest policy checking of manifests.") + boolFlag(flags, "ecr-login-enabled", "Enable Aws Ecr login and helm dependency build for chart dependencies that are hosted on Aws private Ecr repositories.") + stringFlag(flags, "aws-ecr-host", "The Aws ecr host. i.e: .dkr.ecr..amazonaws.com.") stringSliceFlag(flags, "policies-location", "Sets rego policy locations to be used for every check request. Can be common path inside the repos being checked or git urls in either git or http(s) format.", newStringSliceOpts(). withDefault([]string{"./policies"})) diff --git a/docs/usage.md b/docs/usage.md index d95acd28..f27d5a54 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -37,8 +37,11 @@ The full list of supported environment variables is described below: |Env Var|Description|Default Value| |-----------|-------------|------| |`KUBECHECKS_ARGOCD_API_INSECURE`|Enable to use insecure connections to the ArgoCD API server.|`false`| +|`KUBECHECKS_ARGOCD_API_PATH_PREFIX`|ArgoCD API Path Prefix.|| |`KUBECHECKS_ARGOCD_API_SERVER_ADDR`|ArgoCD API Server Address.|`argocd-server`| |`KUBECHECKS_ARGOCD_API_TOKEN`|ArgoCD API token.|| +|`KUBECHECKS_AWS_ECR_HOST`|The Aws ecr host. i.e: .dkr.ecr..amazonaws.com.|| +|`KUBECHECKS_ECR_LOGIN_ENABLED`|Enable Aws Ecr login and helm dependency build for chart dependencies that are hosted on Aws private Ecr repositories.|`false`| |`KUBECHECKS_ENABLE_CONFTEST`|Set to true to enable conftest policy checking of manifests.|`false`| |`KUBECHECKS_ENABLE_KUBECONFORM`|Enable kubeconform checks.|`true`| |`KUBECHECKS_ENABLE_PREUPGRADE`|Enable preupgrade checks.|`true`| diff --git a/go.mod b/go.mod index 370c3aeb..9592dfe2 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,8 @@ toolchain go1.21.6 require ( github.com/argoproj/argo-cd/v2 v2.10.5 github.com/argoproj/gitops-engine v0.7.1-0.20240122213038-792124280fcc + github.com/aws/aws-sdk-go-v2/config v1.25.12 + github.com/aws/aws-sdk-go-v2/service/ecr v1.27.4 github.com/cenkalti/backoff/v4 v4.2.1 github.com/creasty/defaults v1.7.0 github.com/docker/docker v26.0.0+incompatible @@ -79,6 +81,18 @@ require ( github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect github.com/argoproj/pkg v0.13.7-0.20230627120311-a4dd357b057e // indirect github.com/aws/aws-sdk-go v1.50.8 // indirect + github.com/aws/aws-sdk-go-v2 v1.26.1 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.16.16 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.11 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.7.1 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.10 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.18.7 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.7 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.26.7 // indirect + github.com/aws/smithy-go v1.20.2 // indirect github.com/basgys/goxml2json v1.1.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect diff --git a/go.sum b/go.sum index 28153828..f2ac04e2 100644 --- a/go.sum +++ b/go.sum @@ -258,6 +258,34 @@ github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX github.com/aws/aws-sdk-go v1.44.290/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/aws/aws-sdk-go v1.50.8 h1:gY0WoOW+/Wz6XmYSgDH9ge3wnAevYDSQWPxxJvqAkP4= github.com/aws/aws-sdk-go v1.50.8/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= +github.com/aws/aws-sdk-go-v2 v1.26.1 h1:5554eUqIYVWpU0YmeeYZ0wU64H2VLBs8TlhRB2L+EkA= +github.com/aws/aws-sdk-go-v2 v1.26.1/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM= +github.com/aws/aws-sdk-go-v2/config v1.25.12 h1:mF4cMuNh/2G+d19nWnm1vJ/ak0qK6SbqF0KtSX9pxu0= +github.com/aws/aws-sdk-go-v2/config v1.25.12/go.mod h1:lOvvqtZP9p29GIjOTuA/76HiVk0c/s8qRcFRq2+E2uc= +github.com/aws/aws-sdk-go-v2/credentials v1.16.16 h1:8q6Rliyv0aUFAVtzaldUEcS+T5gbadPbWdV1WcAddK8= +github.com/aws/aws-sdk-go-v2/credentials v1.16.16/go.mod h1:UHVZrdUsv63hPXFo1H7c5fEneoVo9UXiz36QG1GEPi0= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.11 h1:c5I5iH+DZcH3xOIMlz3/tCKJDaHFwYEmxvlh2fAcFo8= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.11/go.mod h1:cRrYDYAMUohBJUtUnOhydaMHtiK/1NZ0Otc9lIb6O0Y= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 h1:aw39xVGeRWlWx9EzGVnhOR4yOjQDHPQ6o6NmBlscyQg= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5/go.mod h1:FSaRudD0dXiMPK2UjknVwwTYyZMRsHv3TtkabsZih5I= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 h1:PG1F3OD1szkuQPzDw3CIQsRIrtTlUC3lP84taWzHlq0= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5/go.mod h1:jU1li6RFryMz+so64PpKtudI+QzbKoIEivqdf6LNpOc= +github.com/aws/aws-sdk-go-v2/internal/ini v1.7.1 h1:uR9lXYjdPX0xY+NhvaJ4dD8rpSRz5VY81ccIIoNG+lw= +github.com/aws/aws-sdk-go-v2/internal/ini v1.7.1/go.mod h1:6fQQgfuGmw8Al/3M2IgIllycxV7ZW7WCdVSqfBeUiCY= +github.com/aws/aws-sdk-go-v2/service/ecr v1.27.4 h1:Qr9W21mzWT3RhfYn9iAux7CeRIdbnTAqmiOlASqQgZI= +github.com/aws/aws-sdk-go-v2/service/ecr v1.27.4/go.mod h1:if7ybzzjOmDB8pat9FE35AHTY6ZxlYSy3YviSmFZv8c= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4 h1:/b31bi3YVNlkzkBrm9LfpaKoaYZUxIAj4sHfOTmLfqw= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4/go.mod h1:2aGXHFmbInwgP9ZfpmdIfOELL79zhdNYNmReK8qDfdQ= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.10 h1:DBYTXwIGQSGs9w4jKm60F5dmCQ3EEruxdc0MFh+3EY4= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.10/go.mod h1:wohMUQiFdzo0NtxbBg0mSRGZ4vL3n0dKjLTINdcIino= +github.com/aws/aws-sdk-go-v2/service/sso v1.18.7 h1:eajuO3nykDPdYicLlP3AGgOyVN3MOlFmZv7WGTuJPow= +github.com/aws/aws-sdk-go-v2/service/sso v1.18.7/go.mod h1:+mJNDdF+qiUlNKNC3fxn74WWNN+sOiGOEImje+3ScPM= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.7 h1:QPMJf+Jw8E1l7zqhZmMlFw6w1NmfkfiSK8mS4zOx3BA= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.7/go.mod h1:ykf3COxYI0UJmxcfcxcVuz7b6uADi1FkiUz6Eb7AgM8= +github.com/aws/aws-sdk-go-v2/service/sts v1.26.7 h1:NzO4Vrau795RkUdSHKEwiR01FaGzGOH1EETJ+5QHnm0= +github.com/aws/aws-sdk-go-v2/service/sts v1.26.7/go.mod h1:6h2YuIoxaMSCFf5fi1EgZAwdfkGMgDY+DVfa61uLe4U= +github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q= +github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= github.com/basgys/goxml2json v1.1.0 h1:4ln5i4rseYfXNd86lGEB+Vi652IsIXIvggKM/BhUKVw= github.com/basgys/goxml2json v1.1.0/go.mod h1:wH7a5Np/Q4QoECFIU8zTQlZwZkrilY0itPfecMw41Dw= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= diff --git a/localdev/kubechecks/values.yaml b/localdev/kubechecks/values.yaml index 84b9bf7b..6fd89df5 100644 --- a/localdev/kubechecks/values.yaml +++ b/localdev/kubechecks/values.yaml @@ -28,7 +28,7 @@ deployment: reloader.stakater.com/auto: "true" image: - pullPolicy: Never + pullPolicy: Always name: "kubechecks" tag: "" diff --git a/pkg/argo_client/manifests.go b/pkg/argo_client/manifests.go index 3ecd69a5..033b4298 100644 --- a/pkg/argo_client/manifests.go +++ b/pkg/argo_client/manifests.go @@ -1,8 +1,14 @@ package argo_client import ( + "bytes" "context" + "encoding/base64" "fmt" + "os" + "os/exec" + "strconv" + "strings" "time" "github.com/argoproj/argo-cd/v2/pkg/apiclient/cluster" @@ -10,6 +16,7 @@ import ( argoappv1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" repoapiclient "github.com/argoproj/argo-cd/v2/reposerver/apiclient" "github.com/argoproj/argo-cd/v2/reposerver/repository" + "github.com/argoproj/argo-cd/v2/util/git" "github.com/ghodss/yaml" "github.com/pkg/errors" @@ -17,8 +24,61 @@ import ( "k8s.io/apimachinery/pkg/api/resource" "github.com/zapier/kubechecks/telemetry" + + "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/service/ecr" ) +// Retrieve token for authentication against ECR registries. +func getToken(aws_ecr_host string) (string, error) { + os.Setenv("AWS_SDK_LOAD_CONFIG", "1") + var region = strings.SplitN(string(aws_ecr_host), ".", 6) + cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRegion(region[3])) + if err != nil { + return "", err + } + + svc := ecr.NewFromConfig(cfg) + token, err := svc.GetAuthorizationToken(context.TODO(), &ecr.GetAuthorizationTokenInput{}) + if err != nil { + return "", err + } + + authData := token.AuthorizationData[0].AuthorizationToken + data, err := base64.StdEncoding.DecodeString(*authData) + if err != nil { + return "", err + } + + parts := strings.SplitN(string(data), ":", 2) + + return parts[1], nil +} + +func helmLogin(tempRepoDir string, changedAppFilePath string) error { + + var aws_ecr_host = os.Getenv("AWS_ECR_HOST") + var currToken = "" + if token, err := getToken(aws_ecr_host); err != nil { + fmt.Println(err) + } else { + currToken = token + } + + cmd := exec.Command("bash", "-c", "echo "+currToken+" | helm registry login --username AWS --password-stdin "+aws_ecr_host+"; helm dependency build") + cmd.Dir = tempRepoDir + "/" + changedAppFilePath + var outb, errb bytes.Buffer + cmd.Stdout = &outb + cmd.Stderr = &errb + err := cmd.Run() + if err != nil { + log.Fatal() + } + + fmt.Println("out:", outb.String(), "err:", errb.String()) + return nil +} + func GetManifestsLocal(ctx context.Context, argoClient *ArgoClient, name, tempRepoDir, changedAppFilePath string, app argoappv1.Application) ([]string, error) { var err error @@ -59,6 +119,16 @@ func GetManifestsLocal(ctx context.Context, argoClient *ArgoClient, name, tempRe source := app.Spec.GetSource() + s := os.Getenv("ECR_LOGIN_ENABLED") + ecr_login_enabled, err := strconv.ParseBool(s) + if err != nil { + log.Fatal() + } + + if ecr_login_enabled { + helmLogin(tempRepoDir, changedAppFilePath) + } + log.Debug().Str("name", name).Msg("generating diff for application...") res, err := repository.GenerateManifests(ctx, fmt.Sprintf("%s/%s", tempRepoDir, changedAppFilePath), tempRepoDir, source.TargetRevision, &repoapiclient.ManifestRequest{ Repo: &argoappv1.Repository{Repo: source.RepoURL}, diff --git a/pkg/config/config.go b/pkg/config/config.go index 235a409f..9d5561e1 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -31,6 +31,10 @@ type ServerConfig struct { VcsToken string `mapstructure:"vcs-token"` VcsType string `mapstructure:"vcs-type"` + // Ecr + EcrLoginEnabled bool `mapstructure:"ecr-login-enabled"` + AwsEcrHost string `mapstructure:"aws-ecr-host"` + // webhooks EnsureWebhooks bool `mapstructure:"ensure-webhooks"` WebhookSecret string `mapstructure:"webhook-secret"` @@ -96,6 +100,10 @@ func NewWithViper(v *viper.Viper) (ServerConfig, error) { log.Info().Msgf("Webhook URL Base: %s", cfg.WebhookUrlBase) log.Info().Msgf("Webhook URL Prefix: %s", cfg.UrlPrefix) log.Info().Msgf("VCS Type: %s", cfg.VcsType) + if cfg.EcrLoginEnabled { + log.Info().Msgf("Aws Ecr Login Enabled") + log.Info().Msgf("Aws Ecr Host: %s", cfg.AwsEcrHost) + } return cfg, nil } diff --git a/pkg/git/repo.go b/pkg/git/repo.go index 05652154..65cd3a94 100644 --- a/pkg/git/repo.go +++ b/pkg/git/repo.go @@ -217,7 +217,7 @@ func SetCredentials(cfg config.ServerConfig, vcsClient vcs.Client) error { return errors.Wrap(err, "unable to set git credentials") } - cmd = execCommand(cfg, "git", "config", "--global", "credential.helper", "store") + cmd = execCommand(cfg, "git", "config", "--global", "credential.helper", "store", "--add") err = cmd.Run() if err != nil { return errors.Wrap(err, "unable to set git credential usage")