Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support private Aws Ecr helm repositories for chart dependencies #200

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
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
3 changes: 3 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.")
Expand All @@ -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: <account-id>.dkr.ecr.<region>.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"}))
Expand Down
3 changes: 3 additions & 0 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -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: <account-id>.dkr.ecr.<region>.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`|
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this, or is it enough to have KUBECHECKS_AWS_ECR_HOST be set to a non-empty string?

|`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`|
Expand Down
14 changes: 14 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
28 changes: 28 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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=
Expand Down
2 changes: 1 addition & 1 deletion localdev/kubechecks/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ deployment:
reloader.stakater.com/auto: "true"

image:
pullPolicy: Never
pullPolicy: Always
name: "kubechecks"
tag: ""

Expand Down
70 changes: 70 additions & 0 deletions pkg/argo_client/manifests.go
Original file line number Diff line number Diff line change
@@ -1,24 +1,84 @@
package argo_client

import (
"bytes"
"context"
"encoding/base64"
"fmt"
"os"
"os/exec"
"strconv"
"strings"
"time"

"github.com/argoproj/argo-cd/v2/pkg/apiclient/cluster"
"github.com/argoproj/argo-cd/v2/pkg/apiclient/settings"
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"
"github.com/rs/zerolog/log"
"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) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

more nitpicking:

Suggested change
func getToken(aws_ecr_host string) (string, error) {
func getToken(awsECRHost string) (string, error) {

os.Setenv("AWS_SDK_LOAD_CONFIG", "1")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we want to set this here, we'd rather allow the user to set this when running the application

var region = strings.SplitN(string(aws_ecr_host), ".", 6)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
var region = strings.SplitN(string(aws_ecr_host), ".", 6)
var region = strings.SplitN(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 {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

super nitpicky:

Suggested change
func helmLogin(tempRepoDir string, changedAppFilePath string) error {
func helmLogin(tempRepoDir, 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)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we'll want to return this error, as we won't want to login to the registry if we can't get a token

} 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

Expand Down Expand Up @@ -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 {
Comment on lines +122 to +128
Copy link
Collaborator

@djeebus djeebus Apr 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you modify the args to include something like cfg config.ServerConfig, then you can clean up some of this:

Suggested change
s := os.Getenv("ECR_LOGIN_ENABLED")
ecr_login_enabled, err := strconv.ParseBool(s)
if err != nil {
log.Fatal()
}
if ecr_login_enabled {
if cfg.EcrLoginEnabled {

You can pass it into the call to GetManifestsLocal in worker.go, roughly like 110, by passing w.ctr.Config

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},
Expand Down
8 changes: 8 additions & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
Expand Down Expand Up @@ -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
}
2 changes: 1 addition & 1 deletion pkg/git/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down