1
0
mirror of https://github.com/rancher/rke.git synced 2025-04-28 11:36:27 +00:00
rke/util/ecr.go
2021-07-05 10:16:44 +10:00

90 lines
2.6 KiB
Go

package util
import (
"encoding/base64"
"fmt"
"regexp"
"strings"
"github.com/aws/aws-sdk-go/aws"
"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/docker/docker/api/types"
)
const proxyEndpointScheme = "https://"
var ecrPattern = regexp.MustCompile(`(^[a-zA-Z0-9][a-zA-Z0-9-_]*)\.dkr\.ecr(\-fips)?\.([a-zA-Z0-9][a-zA-Z0-9-_]*)\.amazonaws\.com(\.cn)?`)
// ECRCredentialPlugin is a wrapper to generate ECR token using the AWS Credentials
func ECRCredentialPlugin(plugin map[string]string, pr string) (authConfig types.AuthConfig, err error) {
if strings.HasPrefix(pr, proxyEndpointScheme) {
pr = strings.TrimPrefix(pr, proxyEndpointScheme)
}
matches := ecrPattern.FindStringSubmatch(pr)
if len(matches) == 0 {
return authConfig, fmt.Errorf("Not a valid ECR registry")
} else if len(matches) < 3 {
return authConfig, fmt.Errorf(pr + "is not a valid repository URI for Amazon Elastic Container Registry.")
}
config := &aws.Config{
Region: aws.String(matches[3]),
}
var sess *session.Session
awsAccessKeyID, accessKeyOK := plugin["aws_access_key_id"]
awsSecretAccessKey, secretKeyOK := plugin["aws_secret_access_key"]
// Use predefined keys and override env lookup if keys are present //
if accessKeyOK && secretKeyOK {
// if session token doesnt exist just pass empty string
awsSessionToken := plugin["aws_session_token"]
config.Credentials = credentials.NewStaticCredentials(awsAccessKeyID, awsSecretAccessKey, awsSessionToken)
sess, err = session.NewSession(config)
} else {
sess, err = session.NewSessionWithOptions(session.Options{
Config: *config,
SharedConfigState: session.SharedConfigEnable,
})
}
if err != nil {
return authConfig, err
}
ecrClient := ecr.New(sess)
result, err := ecrClient.GetAuthorizationToken(&ecr.GetAuthorizationTokenInput{})
if err != nil {
return authConfig, err
}
if len(result.AuthorizationData) == 0 {
return authConfig, fmt.Errorf("No authorization data returned")
}
authConfig, err = extractToken(*result.AuthorizationData[0].AuthorizationToken)
return authConfig, err
}
func extractToken(token string) (authConfig types.AuthConfig, err error) {
decodedToken, err := base64.StdEncoding.DecodeString(token)
if err != nil {
return authConfig, fmt.Errorf("Invalid token: %v", err)
}
parts := strings.SplitN(string(decodedToken), ":", 2)
if len(parts) < 2 {
return authConfig, fmt.Errorf("Invalid token: expected two parts, got %d", len(parts))
}
authConfig = types.AuthConfig{
Username: parts[0],
Password: parts[1],
}
return authConfig, nil
}