mirror of
https://github.com/rancher/rke.git
synced 2025-04-27 19:25:44 +00:00
99 lines
3.1 KiB
Go
99 lines
3.1 KiB
Go
package util
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"fmt"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/sirupsen/logrus"
|
|
|
|
"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"
|
|
v3 "github.com/rancher/rke/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 *v3.ECRCredentialPlugin, pr string) (authConfig types.AuthConfig, err error) {
|
|
if plugin == nil {
|
|
err = fmt.Errorf("ECRCredentialPlugin: ECRCredentialPlugin called with nil plugin data")
|
|
return authConfig, err
|
|
}
|
|
|
|
logrus.Tracef("ECRCredentialPlugin: ECRCredentialPlugin called with plugin [%v] and pr [%s]", plugin, pr)
|
|
|
|
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]),
|
|
}
|
|
|
|
logrus.Debugf("ECRCredentialPlugin: Setting Region to [%s]", matches[3])
|
|
var sess *session.Session
|
|
|
|
// Use predefined keys and override env lookup if keys are present //
|
|
if plugin.AwsAccessKeyID != "" && plugin.AwsSecretAccessKey != "" {
|
|
// if session token doesn't exist just pass empty string
|
|
config.Credentials = credentials.NewStaticCredentials(plugin.AwsAccessKeyID, plugin.AwsSecretAccessKey, plugin.AwsSessionToken)
|
|
sess, err = session.NewSession(config)
|
|
} else {
|
|
logrus.Debug("ECRCredentialPlugin: aws_access_key_id and aws_secret_access_key keys not in plugin, using IAM role or env variables")
|
|
sess, err = session.NewSessionWithOptions(session.Options{
|
|
Config: *config,
|
|
SharedConfigState: session.SharedConfigEnable,
|
|
})
|
|
}
|
|
|
|
if err != nil {
|
|
logrus.Trace("ECRCredentialPlugin: Error found while constructing auth session, returning authConfig")
|
|
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
|
|
}
|