Skip to content

Commit

Permalink
Draft elasticContainerRegistry;
Browse files Browse the repository at this point in the history
  • Loading branch information
ycliuhw committed Sep 22, 2021
1 parent 09454fb commit 6fcba0b
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 8 deletions.
3 changes: 3 additions & 0 deletions docker/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ type ImageRepoDetails struct {

// ServerAddress is the auth server address.
ServerAddress string `json:"serveraddress,omitempty" yaml:"serveraddress,omitempty"`

// Region is the cloud region.
Region string `json:"region,omitempty" yaml:"region,omitempty"`
}

// AuthEqual compares if the provided one equals to current repository detail.
Expand Down
8 changes: 4 additions & 4 deletions docker/registry/internal/acr.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,16 @@ func (c *azureContainerRegistry) Match() bool {
return strings.Contains(c.repoDetails.ServerAddress, "azurecr.io")
}

func getUserNameFromAuth(auth string) (string, error) {
func unpackAuthToken(auth string) (string, string, error) {
content, err := base64.StdEncoding.DecodeString(auth)
if err != nil {
return "", errors.Annotate(err, "doing base64 decode on the auth token")
}
parts := strings.Split(string(content), ":")
if len(parts) < 1 {
if len(parts) < 2 {
return "", errors.NotValidf("registry auth token")
}
return parts[0], nil
return parts[0], parts[1], nil
}

func azureContainerRegistryTransport(
Expand All @@ -48,7 +48,7 @@ func azureContainerRegistryTransport(
username := repoDetails.Username
if username == "" {
var err error
username, err = getUserNameFromAuth(repoDetails.Auth)
username, _, err = unpackAuthToken(repoDetails.Auth)
if err != nil {
return nil, errors.Trace(err)
}
Expand Down
99 changes: 96 additions & 3 deletions docker/registry/internal/ecr.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,59 @@
package internal

import (
"fmt"
"net/http"
"strings"
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/client"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ecr"
"github.com/aws/aws-sdk-go/service/ecr/ecriface"
"github.com/juju/errors"

"github.com/juju/juju/docker"
)

type awsLogger struct {
session *session.Session
}

func (l awsLogger) Log(args ...interface{}) {
logger.Tracef("awsLogger %p: %s", l.session, fmt.Sprint(args...))
}

func getDefaultRetryer() client.DefaultRetryer {
return client.DefaultRetryer{
NumMaxRetries: 10,
MinRetryDelay: time.Second,
MinThrottleDelay: time.Second,
MaxRetryDelay: time.Minute,
MaxThrottleDelay: time.Minute,
}
}

func getECRClient(accessKeyID, secretAccessKey, region string) (ecriface.ECRAPI, error) {
config := &aws.Config{
Retryer: getDefaultRetryer(),
Region: aws.String(region),
Credentials: credentials.NewStaticCredentialsFromCreds(credentials.Value{
AccessKeyID: accessKeyID,
SecretAccessKey: secretAccessKey,
}),
}
s := session.Must(session.NewSession())
// Enable request and response logging, but only if TRACE is enabled (as
// they're probably fairly expensive to produce).
if logger.IsTraceEnabled() {
config.Logger = awsLogger{s}
config.LogLevel = aws.LogLevel(aws.LogDebug | aws.LogDebugWithRequestErrors | aws.LogDebugWithRequestRetries)
}
return ecr.New(s, config), nil
}

type elasticContainerRegistry struct {
*baseClient
}
Expand All @@ -23,9 +68,57 @@ func newElasticContainerRegistry(repoDetails docker.ImageRepoDetails, transport

// Match checks if the repository details matches current provider format.
func (c *elasticContainerRegistry) Match() bool {
return strings.Contains(c.repoDetails.ServerAddress, "ecr.aws")
return strings.Contains(c.repoDetails.ServerAddress, "amazonaws.com")
}

func getTokenForElasticContainerRegistry(repoDetails *docker.ImageRepoDetails) (token string, err error) {
if repoDetails.Region == "" {
return "", errors.NewNotValid(nil, "region is required")
}
if (repoDetails.Username == "" || repoDetails.Password == "") && repoDetails.Auth != "" {
if repoDetails.Username, repoDetails.Password, err = unpackAuthToken(repoDetails.Auth); err != nil {
return "", errors.Annotatef(err, "unpacking auth token for %q", repoDetails.Repository)
}
}
c, err := getECRClient(repoDetails.Username, repoDetails.Password, repoDetails.Region)
if err != nil {
return "", errors.Trace(err)
}
result, err := c.GetAuthorizationToken(&ecr.GetAuthorizationTokenInput{})
if err != nil {
return "", errors.Trace(err)
}
if len(result.AuthorizationData) > 0 {
token = aws.StringValue(result.AuthorizationData[0].AuthorizationToken)
}
if token == "" {
return "", errors.NotFoundf("authorization token for %q", repoDetails.Repository)
}
return token, nil
}

func elasticContainerRegistryTransport(transport http.RoundTripper, repoDetails *docker.ImageRepoDetails,
) (http.RoundTripper, error) {
if !repoDetails.TokenAuthConfig.Empty() {
return nil, errors.New("elastic container registry only supports username and password")
}
if repoDetails.BasicAuthConfig.Empty() {
return nil, errors.NewNotValid(nil, "empty credential for elastic container registry")
}
token, err := getTokenForElasticContainerRegistry(repoDetails)
if err != nil {
return nil, errors.Trace(err)
}
return newBasicTransport(transport, "AWS", token, ""), nil
return transport, nil
}

func (c *elasticContainerRegistry) WrapTransport(...TransportWrapper) error {
return errors.NotSupportedf("AWS elastic container registry")
func (c *elasticContainerRegistry) WrapTransport(...TransportWrapper) (err error) {
if c.client.Transport, err = mergeTransportWrappers(
c.client.Transport, c.repoDetails,
newPrivateOnlyTransport, elasticContainerRegistryTransport, wrapErrorTransport,
); err != nil {
return errors.Trace(err)
}
return nil
}
2 changes: 1 addition & 1 deletion docker/registry/internal/gcr.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func validateGoogleContainerRegistryCredential(auth docker.BasicAuthConfig) (err
}
username := auth.Username
if auth.Auth != "" {
username, err = getUserNameFromAuth(auth.Auth)
username, _, err = unpackAuthToken(auth.Auth)
if err != nil {
return errors.Annotate(err, "getting username from the google container registry auth token")
}
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ require (
github.com/EvilSuperstars/go-cidrman v0.0.0-20170211231153-4e5a4a63d9b7
github.com/altoros/gosigma v0.0.0-20150408145232-31228935eec6
github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878
github.com/aws/aws-sdk-go v1.40.46
github.com/aws/aws-sdk-go-v2 v1.6.0
github.com/aws/aws-sdk-go-v2/config v1.3.0
github.com/aws/aws-sdk-go-v2/credentials v1.2.1
Expand Down
3 changes: 3 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878 h1:EFSB7Zo9Eg91v7
github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQhVx52RsWOnlkpikZr01T/yAVN2gn0861vByNg=
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/aws/aws-sdk-go v1.40.46 h1:2O4qZ1ROLry/cYkHo14G0p8cnLKB5feIFXY7xWgq1n8=
github.com/aws/aws-sdk-go v1.40.46/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
github.com/aws/aws-sdk-go-v2 v1.6.0 h1:r20hdhm8wZmKkClREfacXrKfX0Y7/s0aOoeraFbf/sY=
github.com/aws/aws-sdk-go-v2 v1.6.0/go.mod h1:tI4KhsR5VkzlUa2DZAdwx7wCAYGwkZZ1H31PYrBFx1w=
github.com/aws/aws-sdk-go-v2/config v1.3.0 h1:0JAnp0WcsgKilFLiZEScUTKIvTKa2LkicadZADza+u0=
Expand Down Expand Up @@ -919,6 +921,7 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d h1:20cMwl2fHAzkJMEA+8J4JgqBQcQGzbisXo31MIeenXI=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
Expand Down

0 comments on commit 6fcba0b

Please sign in to comment.