Skip to content

Commit

Permalink
feat: 🎸 adding helm repo password refresh
Browse files Browse the repository at this point in the history
useful for ECR OCI helm repositories which require credential refresh
after 12 hours

✅ Closes: #8097

Signed-off-by: Isaac Gaskin <isaac.gaskin@circle.com>
  • Loading branch information
igaskin committed Jan 3, 2023
1 parent 566d50f commit be1355d
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 1 deletion.
2 changes: 1 addition & 1 deletion docs/developer-guide/contributors-quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ and the [toolchain guide](toolchain-guide.md).

- Get current value of `GOPATH` env:
```shell
go env | grep path
go env | grep -i path
```
- Change directory into that path
```shell
Expand Down
50 changes: 50 additions & 0 deletions util/helm/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"crypto/tls"
"crypto/x509"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
Expand All @@ -18,6 +19,8 @@ import (
"time"

"github.com/argoproj/pkg/sync"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ecr"
log "github.com/sirupsen/logrus"
"gopkg.in/yaml.v2"

Expand All @@ -42,6 +45,8 @@ type Creds struct {
CertData []byte
KeyData []byte
InsecureSkipVerify bool
CredsExpire time.Duration
credsUpdatedAt time.Time
}

type indexCache interface {
Expand Down Expand Up @@ -164,6 +169,15 @@ func (c *nativeHelmChart) ExtractChart(chart string, version string, passCredent
defer func() { _ = os.RemoveAll(tempDest) }()

if c.enableOci {
// check if new ECR password needs to be generated
if IsECRHelmRepo(c.repoURL) && c.isExpiredCredentials() {
c.creds.Username = "AWS"
c.creds.Password, err = c.getECRAuthorizationToken()
if err != nil {
return "", nil, err
}
c.creds.credsUpdatedAt = time.Now()
}
if c.creds.Password != "" && c.creds.Username != "" {
_, err = helmCmd.RegistryLogin(c.repoURL, c.creds)
if err != nil {
Expand Down Expand Up @@ -213,6 +227,34 @@ func (c *nativeHelmChart) ExtractChart(chart string, version string, passCredent
}), nil
}

func (c *nativeHelmChart) getECRAuthorizationToken() (string, error) {
sess, err := session.NewSession()
if err != nil {
return "", fmt.Errorf("error creating new AWS session: %s", err)
}
ecrAPI := ecr.New(sess)
result, err := ecrAPI.GetAuthorizationToken(&ecr.GetAuthorizationTokenInput{})
if err != nil {
return "", err
}
token, err := base64.RawStdEncoding.DecodeString(result.String())
if err != nil {
return "", fmt.Errorf("unable generate ecr repo password: %v", err)
}
return string(token), nil

}

func (c *nativeHelmChart) isExpiredCredentials() bool {
if c.creds.credsUpdatedAt.IsZero() {
return true
}
if time.Since(c.creds.credsUpdatedAt) >= c.creds.CredsExpire {
return true
}
return false
}

func (c *nativeHelmChart) GetIndex(noCache bool) (*Index, error) {
indexLock.Lock(c.repoURL)
defer indexLock.Unlock(c.repoURL)
Expand Down Expand Up @@ -374,6 +416,14 @@ func IsHelmOciRepo(repoURL string) bool {
return err == nil && parsed.Host == ""
}

func IsECRHelmRepo(repoURL string) bool {
if repoURL == "" {
return false
}
parsed, err := url.Parse(repoURL)
return err == nil && strings.HasSuffix(parsed.Path, "amazonaws.com")
}

func getIndexURL(rawURL string) (string, error) {
indexFile := "index.yaml"
repoURL, err := url.Parse(rawURL)
Expand Down
5 changes: 5 additions & 0 deletions util/helm/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,11 @@ func TestIsHelmOciRepo(t *testing.T) {
assert.False(t, IsHelmOciRepo("https://demo.goharbor.io:8080"))
}

func TestIsECRHelmRepo(t *testing.T) {
assert.True(t, IsECRHelmRepo("account.dkr.ecr.eu-central-1.amazonaws.com"))
assert.False(t, IsECRHelmRepo("demo.goharbor.io"))
}

func TestGetIndexURL(t *testing.T) {
urlTemplate := `https://gitlab.com/projects/%s/packages/helm/stable`
t.Run("URL without escaped characters", func(t *testing.T) {
Expand Down

0 comments on commit be1355d

Please sign in to comment.