//NewEcsImageCreator creates an instance of the EcsImageCreator from the docker environment variables, and returns the instance func NewEcsImageCreator(repo string, region string) (ImageCreator, error) { // awsClient := ecr.New(session.New(), &aws.Config{Region: aws.String(region)}) //only try to pull a single repository as a test describeRequest := &ecr.DescribeRepositoriesInput{ MaxResults: aws.Int64(1), } _, err := awsClient.DescribeRepositories(describeRequest) if err != nil { return nil, err } localDocker, err := NewLocalImageCreator(repo) if err != nil { return nil, err } return &EcsImageCreator{ awsClient: awsClient, dockerCreator: localDocker, }, nil }
func ExampleECR_BatchGetImage() { sess, err := session.NewSession() if err != nil { fmt.Println("failed to create session,", err) return } svc := ecr.New(sess) params := &ecr.BatchGetImageInput{ ImageIds: []*ecr.ImageIdentifier{ // Required { // Required ImageDigest: aws.String("ImageDigest"), ImageTag: aws.String("ImageTag"), }, // More values... }, RepositoryName: aws.String("RepositoryName"), // Required RegistryId: aws.String("RegistryId"), } resp, err := svc.BatchGetImage(params) if err != nil { // Print the error, cast err to awserr.Error to get the Code and // Message from an error. fmt.Println(err.Error()) return } // Pretty-print the response data. fmt.Println(resp) }
func ExampleECR_PutImage() { sess, err := session.NewSession() if err != nil { fmt.Println("failed to create session,", err) return } svc := ecr.New(sess) params := &ecr.PutImageInput{ ImageManifest: aws.String("ImageManifest"), // Required RepositoryName: aws.String("RepositoryName"), // Required RegistryId: aws.String("RegistryId"), } resp, err := svc.PutImage(params) if err != nil { // Print the error, cast err to awserr.Error to get the Code and // Message from an error. fmt.Println(err.Error()) return } // Pretty-print the response data. fmt.Println(resp) }
func ExampleECR_BatchCheckLayerAvailability() { sess, err := session.NewSession() if err != nil { fmt.Println("failed to create session,", err) return } svc := ecr.New(sess) params := &ecr.BatchCheckLayerAvailabilityInput{ LayerDigests: []*string{ // Required aws.String("BatchedOperationLayerDigest"), // Required // More values... }, RepositoryName: aws.String("RepositoryName"), // Required RegistryId: aws.String("RegistryId"), } resp, err := svc.BatchCheckLayerAvailability(params) if err != nil { // Print the error, cast err to awserr.Error to get the Code and // Message from an error. fmt.Println(err.Error()) return } // Pretty-print the response data. fmt.Println(resp) }
func ExampleECR_DescribeRepositories() { sess, err := session.NewSession() if err != nil { fmt.Println("failed to create session,", err) return } svc := ecr.New(sess) params := &ecr.DescribeRepositoriesInput{ MaxResults: aws.Int64(1), NextToken: aws.String("NextToken"), RegistryId: aws.String("RegistryId"), RepositoryNames: []*string{ aws.String("RepositoryName"), // Required // More values... }, } resp, err := svc.DescribeRepositories(params) if err != nil { // Print the error, cast err to awserr.Error to get the Code and // Message from an error. fmt.Println(err.Error()) return } // Pretty-print the response data. fmt.Println(resp) }
func ExampleECR_SetRepositoryPolicy() { sess, err := session.NewSession() if err != nil { fmt.Println("failed to create session,", err) return } svc := ecr.New(sess) params := &ecr.SetRepositoryPolicyInput{ PolicyText: aws.String("RepositoryPolicyText"), // Required RepositoryName: aws.String("RepositoryName"), // Required Force: aws.Bool(true), RegistryId: aws.String("RegistryId"), } resp, err := svc.SetRepositoryPolicy(params) if err != nil { // Print the error, cast err to awserr.Error to get the Code and // Message from an error. fmt.Println(err.Error()) return } // Pretty-print the response data. fmt.Println(resp) }
func ExampleECR_GetAuthorizationToken() { sess, err := session.NewSession() if err != nil { fmt.Println("failed to create session,", err) return } svc := ecr.New(sess) params := &ecr.GetAuthorizationTokenInput{ RegistryIds: []*string{ aws.String("RegistryId"), // Required // More values... }, } resp, err := svc.GetAuthorizationToken(params) if err != nil { // Print the error, cast err to awserr.Error to get the Code and // Message from an error. fmt.Println(err.Error()) return } // Pretty-print the response data. fmt.Println(resp) }
func ExampleECR_ListImages() { sess, err := session.NewSession() if err != nil { fmt.Println("failed to create session,", err) return } svc := ecr.New(sess) params := &ecr.ListImagesInput{ RepositoryName: aws.String("RepositoryName"), // Required Filter: &ecr.ListImagesFilter{ TagStatus: aws.String("TagStatus"), }, MaxResults: aws.Int64(1), NextToken: aws.String("NextToken"), RegistryId: aws.String("RegistryId"), } resp, err := svc.ListImages(params) if err != nil { // Print the error, cast err to awserr.Error to get the Code and // Message from an error. fmt.Println(err.Error()) return } // Pretty-print the response data. fmt.Println(resp) }
func ExampleECR_UploadLayerPart() { sess, err := session.NewSession() if err != nil { fmt.Println("failed to create session,", err) return } svc := ecr.New(sess) params := &ecr.UploadLayerPartInput{ LayerPartBlob: []byte("PAYLOAD"), // Required PartFirstByte: aws.Int64(1), // Required PartLastByte: aws.Int64(1), // Required RepositoryName: aws.String("RepositoryName"), // Required UploadId: aws.String("UploadId"), // Required RegistryId: aws.String("RegistryId"), } resp, err := svc.UploadLayerPart(params) if err != nil { // Print the error, cast err to awserr.Error to get the Code and // Message from an error. fmt.Println(err.Error()) return } // Pretty-print the response data. fmt.Println(resp) }
func newAuthProvider(c *cli.Context) (dockerauth.AuthProvider, error) { awsSession := newConfigProvider(c) provider := dockerauth.NewMultiAuthProvider() provider.AddProvider(dockerauth.NewECRAuthProvider(func(region string) dockerauth.ECR { return ecr.New(awsSession, &aws.Config{Region: aws.String(region)}) })) if dockerConfigPath := c.String(FlagDockerAuth); dockerConfigPath != "" { dockerConfigFile, err := os.Open(dockerConfigPath) if err != nil { return nil, err } defer dockerConfigFile.Close() dockerConfigProvider, err := dockerauth.NewDockerConfigAuthProvider(dockerConfigFile) if err != nil { return nil, err } provider.AddProvider(dockerConfigProvider) } return provider, nil }
func (defaultClientFactory DefaultClientFactory) NewClient(region string) Client { awsSession := session.New() return &defaultClient{ ecrClient: ecr.New(awsSession, &aws.Config{Region: aws.String(region)}), credentialCache: defaultClientFactory.buildCredentialsCache(awsSession, region), } }
func DockerLogin(ac docker.AuthConfiguration) (string, error) { if ac.Email == "" { ac.Email = "*****@*****.**" } // if ECR URL, try Username and Password as IAM keys to get auth token if match := regexpECR.FindStringSubmatch(ac.ServerAddress); len(match) > 1 { ECR := ecr.New(session.New(), &aws.Config{ Credentials: credentials.NewStaticCredentials(ac.Username, ac.Password, ""), Region: aws.String(match[2]), }) res, err := ECR.GetAuthorizationToken(&ecr.GetAuthorizationTokenInput{ RegistryIds: []*string{aws.String(match[1])}, }) if err != nil { return "", err } if len(res.AuthorizationData) < 1 { return "", fmt.Errorf("no authorization data") } endpoint := *res.AuthorizationData[0].ProxyEndpoint data, err := base64.StdEncoding.DecodeString(*res.AuthorizationData[0].AuthorizationToken) if err != nil { return "", err } parts := strings.SplitN(string(data), ":", 2) ac.Password = parts[1] ac.ServerAddress = endpoint[8:] ac.Username = parts[0] } args := []string{"login", "-e", ac.Email, "-u", ac.Username, "-p", ac.Password, ac.ServerAddress} out, err := exec.Command("docker", args...).CombinedOutput() // log args with password masked args[6] = "*****" cmd := fmt.Sprintf("docker %s", strings.Trim(fmt.Sprint(args), "[]")) if err != nil { fmt.Printf("ns=kernel cn=docker at=DockerLogin state=error step=exec.Command cmd=%q out=%q err=%q\n", cmd, out, err) } else { fmt.Printf("ns=kernel cn=docker at=DockerLogin state=success step=exec.Command cmd=%q\n", cmd) } return ac.ServerAddress, err }
// GetECRAuth requests AWS ECR API to get docker.AuthConfiguration token func GetECRAuth(registry, region string) (result docker.AuthConfiguration, err error) { _ecrAuthCache.mu.Lock() defer _ecrAuthCache.mu.Unlock() if token, ok := _ecrAuthCache.tokens[registry]; ok { return token, nil } defer func() { _ecrAuthCache.tokens[registry] = result }() cfg := &aws.Config{ Region: aws.String(region), } if log.StandardLogger().Level >= log.DebugLevel { cfg.LogLevel = aws.LogLevel(aws.LogDebugWithRequestErrors) } split := strings.Split(registry, ".") svc := ecr.New(session.New(), cfg) params := &ecr.GetAuthorizationTokenInput{ RegistryIds: []*string{aws.String(split[0])}, } res, err := svc.GetAuthorizationToken(params) if err != nil { return result, err } if len(res.AuthorizationData) == 0 { return result, nil } data, err := base64.StdEncoding.DecodeString(*res.AuthorizationData[0].AuthorizationToken) if err != nil { return result, err } userpass := strings.Split(string(data), ":") if len(userpass) != 2 { return result, fmt.Errorf("Cannot parse token got from ECR: %s", string(data)) } result = docker.AuthConfiguration{ Username: userpass[0], Password: userpass[1], ServerAddress: *res.AuthorizationData[0].ProxyEndpoint, } return }
// CreateImageRepo create a repository for the image on amazon's ECR(EC2 Container Repository) // if it doesn't exist as repository needs to be present before pushing and image into it. func CreateImageRepo(reponame string, params map[string]string) error { var ( accessKey string secretKey string regionName string ok bool ) accessKey, ok = params["accesskey"] if !ok { accessKey = "" } secretKey, ok = params["secretkey"] if !ok { secretKey = "" } regionName, ok = params["region"] if !ok || fmt.Sprint(regionName) == "" { return fmt.Errorf("No region parameter provided") } region := fmt.Sprint(regionName) creds := credentials.NewChainCredentials([]credentials.Provider{ &credentials.StaticProvider{ Value: credentials.Value{ AccessKeyID: accessKey, SecretAccessKey: secretKey, }, }, &credentials.EnvProvider{}, &credentials.SharedCredentialsProvider{}, &ec2rolecreds.EC2RoleProvider{Client: ec2metadata.New(session.New())}, }) awsConfig := aws.NewConfig() awsConfig.WithCredentials(creds) awsConfig.WithRegion(region) svc := ecr.New(session.New(awsConfig)) repoInput := &ecr.CreateRepositoryInput{ RepositoryName: aws.String(reponame), } _, err := svc.CreateRepository(repoInput) if err != nil { if s3Err, ok := err.(awserr.Error); ok && s3Err.Code() == "RepositoryAlreadyExistsException" { return nil } return err } return nil }
func ExampleECR_CreateRepository() { svc := ecr.New(session.New()) params := &ecr.CreateRepositoryInput{ RepositoryName: aws.String("RepositoryName"), // Required } resp, err := svc.CreateRepository(params) if err != nil { // Print the error, cast err to awserr.Error to get the Code and // Message from an error. fmt.Println(err.Error()) return } // Pretty-print the response data. fmt.Println(resp) }
// Enabled implements DockerConfigProvider.Enabled for the AWS token-based implementation. // For now, it gets activated only if AWS was chosen as the cloud provider. // TODO: figure how to enable it manually for deployments that are not on AWS but still // use ECR somehow? func (p *ecrProvider) Enabled() bool { if p.region == "" { glog.Errorf("Called ecrProvider.Enabled() with no region set") return false } getter := &ecrTokenGetter{svc: ecr.New(session.New(&aws.Config{ Credentials: nil, Region: &p.region, }))} getter.svc.Handlers.Sign.PushFrontNamed(request.NamedHandler{ Name: "k8s/logger", Fn: awsHandlerLogger, }) p.getter = getter return true }
func ExampleECR_InitiateLayerUpload() { svc := ecr.New(session.New()) params := &ecr.InitiateLayerUploadInput{ RepositoryName: aws.String("RepositoryName"), // Required RegistryId: aws.String("RegistryId"), } resp, err := svc.InitiateLayerUpload(params) if err != nil { // Print the error, cast err to awserr.Error to get the Code and // Message from an error. fmt.Println(err.Error()) return } // Pretty-print the response data. fmt.Println(resp) }
func ExampleECR_GetDownloadUrlForLayer() { svc := ecr.New(session.New()) params := &ecr.GetDownloadUrlForLayerInput{ LayerDigest: aws.String("LayerDigest"), // Required RepositoryName: aws.String("RepositoryName"), // Required RegistryId: aws.String("RegistryId"), } resp, err := svc.GetDownloadUrlForLayer(params) if err != nil { // Print the error, cast err to awserr.Error to get the Code and // Message from an error. fmt.Println(err.Error()) return } // Pretty-print the response data. fmt.Println(resp) }
// Get a login token for Amazon AWS ECR. Returns username and password // or an error. func (c *AwsAccessConfig) EcrGetLogin(ecrUrl string) (string, string, error) { exp := regexp.MustCompile("(?:http://|https://|)([0-9]*)\\.dkr\\.ecr\\.(.*)\\.amazonaws\\.com.*") splitUrl := exp.FindStringSubmatch(ecrUrl) accountId := splitUrl[1] region := splitUrl[2] log.Println(fmt.Sprintf("Getting ECR token for account: %s in %s..", accountId, region)) awsConfig, err := c.config(region) if err != nil { return "", "", err } session, err := session.NewSession(awsConfig) if err != nil { return "", "", fmt.Errorf("failed to create session: %s", err) } service := ecr.New(session) params := &ecr.GetAuthorizationTokenInput{ RegistryIds: []*string{ aws.String(accountId), }, } resp, err := service.GetAuthorizationToken(params) if err != nil { return "", "", fmt.Errorf(err.Error()) } auth, err := base64.StdEncoding.DecodeString(*resp.AuthorizationData[0].AuthorizationToken) if err != nil { return "", "", fmt.Errorf("Error decoding ECR AuthorizationToken: %s", err) } authParts := strings.SplitN(string(auth), ":", 2) log.Printf("Successfully got login for ECR: %s", ecrUrl) return authParts[0], authParts[1], nil }
func ExampleECR_ListImages() { svc := ecr.New(session.New()) params := &ecr.ListImagesInput{ RepositoryName: aws.String("RepositoryName"), // Required MaxResults: aws.Int64(1), NextToken: aws.String("NextToken"), RegistryId: aws.String("RegistryId"), } resp, err := svc.ListImages(params) if err != nil { // Print the error, cast err to awserr.Error to get the Code and // Message from an error. fmt.Println(err.Error()) return } // Pretty-print the response data. fmt.Println(resp) }
func newAuthProvider(c *cli.Context) (dockerauth.AuthProvider, error) { provider := dockerauth.NewMultiAuthProvider() provider.AddProvider(dockerauth.NewECRAuthProvider(ecr.New(newConfigProvider(c)))) if dockerConfigPath := c.String(FlagDockerAuth); dockerConfigPath != "" { dockerConfigFile, err := os.Open(dockerConfigPath) if err != nil { return nil, err } defer dockerConfigFile.Close() dockerConfigProvider, err := dockerauth.NewDockerConfigAuthProvider(dockerConfigFile) if err != nil { return nil, err } provider.AddProvider(dockerConfigProvider) } return provider, nil }
func (p *AWSProvider) authECR(host, access, secret string) (string, string, error) { config := p.config() if access != "" { config.Credentials = credentials.NewStaticCredentials(access, secret, "") } e := ecr.New(session.New(), config) if !regexpECRHost.MatchString(host) { return "", "", fmt.Errorf("invalid ECR hostname") } registry := regexpECRHost.FindStringSubmatch(host) res, err := e.GetAuthorizationToken(&ecr.GetAuthorizationTokenInput{ RegistryIds: []*string{aws.String(registry[1])}, }) if err != nil { return "", "", err } if len(res.AuthorizationData) != 1 { return "", "", fmt.Errorf("no authorization data") } token, err := base64.StdEncoding.DecodeString(*res.AuthorizationData[0].AuthorizationToken) if err != nil { return "", "", err } parts := strings.SplitN(string(token), ":", 2) if len(parts) != 2 { return "", "", fmt.Errorf("invalid auth data") } return parts[0], parts[1], nil }
func imageTagExists(repositoryName, tag, awsRegion, awsRegistryID string) (bool, error) { // Default to only look for tagged images awsTagStatus := "TAGGED" sess, err := session.NewSession() if err != nil { fmt.Println("failed to create session,", err) return false, err } svc := ecr.New(sess, &aws.Config{Region: aws.String(awsRegion)}) // Get images params := &ecr.ListImagesInput{ RepositoryName: aws.String(repositoryName), // Required Filter: &ecr.ListImagesFilter{ TagStatus: aws.String(awsTagStatus), }, RegistryId: aws.String(awsRegistryID), } resp, err := svc.ListImages(params) if err != nil { // Print the error, cast err to awserr.Error to get the Code and // Message from an error. fmt.Println(err.Error()) return false, err } for _, image := range resp.ImageIds { if image.ImageTag != nil && *image.ImageTag == tag { return true, nil } } return false, nil }
// Enabled implements DockerConfigProvider.Enabled for the AWS token-based implementation. // For now, it gets activated only if AWS was chosen as the cloud provider. // TODO: figure how to enable it manually for deployments that are not on AWS but still // use ECR somehow? func (p *ecrProvider) Enabled() bool { provider, err := cloudprovider.GetCloudProvider(aws_cloud.ProviderName, nil) if err != nil { glog.Errorf("while initializing AWS cloud provider %v", err) return false } if provider == nil { return false } zones, ok := provider.Zones() if !ok { glog.Errorf("couldn't get Zones() interface") return false } zone, err := zones.GetZone() if err != nil { glog.Errorf("while getting zone %v", err) return false } if zone.Region == "" { glog.Errorf("Region information is empty") return false } getter := &ecrTokenGetter{svc: ecr.New(session.New(&aws.Config{ Credentials: nil, Region: &zone.Region, }))} getter.svc.Handlers.Sign.PushFrontNamed(request.NamedHandler{ Name: "k8s/logger", Fn: awsHandlerLogger, }) p.getter = getter return true }
func ExampleECR_CompleteLayerUpload() { svc := ecr.New(session.New()) params := &ecr.CompleteLayerUploadInput{ LayerDigests: []*string{ // Required aws.String("LayerDigest"), // Required // More values... }, RepositoryName: aws.String("RepositoryName"), // Required UploadId: aws.String("UploadId"), // Required RegistryId: aws.String("RegistryId"), } resp, err := svc.CompleteLayerUpload(params) if err != nil { // Print the error, cast err to awserr.Error to get the Code and // Message from an error. fmt.Println(err.Error()) return } // Pretty-print the response data. fmt.Println(resp) }
// Client configures and returns a fully initialized AWSClient func (c *Config) Client() (interface{}, error) { // Get the auth and region. This can fail if keys/regions were not // specified and we're attempting to use the environment. var errs []error log.Println("[INFO] Building AWS region structure") err := c.ValidateRegion() if err != nil { errs = append(errs, err) } var client AWSClient if len(errs) == 0 { // store AWS region in client struct, for region specific operations such as // bucket storage in S3 client.region = c.Region log.Println("[INFO] Building AWS auth structure") creds := GetCredentials(c.AccessKey, c.SecretKey, c.Token, c.Profile, c.CredsFilename) // Call Get to check for credential provider. If nothing found, we'll get an // error, and we can present it nicely to the user cp, err := creds.Get() if err != nil { if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "NoCredentialProviders" { errs = append(errs, fmt.Errorf(`No valid credential sources found for AWS Provider. Please see https://terraform.io/docs/providers/aws/index.html for more information on providing credentials for the AWS Provider`)) } else { errs = append(errs, fmt.Errorf("Error loading credentials for AWS Provider: %s", err)) } return nil, &multierror.Error{Errors: errs} } log.Printf("[INFO] AWS Auth provider used: %q", cp.ProviderName) awsConfig := &aws.Config{ Credentials: creds, Region: aws.String(c.Region), MaxRetries: aws.Int(c.MaxRetries), HTTPClient: cleanhttp.DefaultClient(), } if logging.IsDebugOrHigher() { awsConfig.LogLevel = aws.LogLevel(aws.LogDebugWithHTTPBody) awsConfig.Logger = awsLogger{} } if c.Insecure { transport := awsConfig.HTTPClient.Transport.(*http.Transport) transport.TLSClientConfig = &tls.Config{ InsecureSkipVerify: true, } } // Set up base session sess := session.New(awsConfig) sess.Handlers.Build.PushFrontNamed(addTerraformVersionToUserAgent) // Some services exist only in us-east-1, e.g. because they manage // resources that can span across multiple regions, or because // signature format v4 requires region to be us-east-1 for global // endpoints: // http://docs.aws.amazon.com/general/latest/gr/sigv4_changes.html usEast1Sess := sess.Copy(&aws.Config{Region: aws.String("us-east-1")}) // Some services have user-configurable endpoints awsEc2Sess := sess.Copy(&aws.Config{Endpoint: aws.String(c.Ec2Endpoint)}) awsElbSess := sess.Copy(&aws.Config{Endpoint: aws.String(c.ElbEndpoint)}) awsIamSess := sess.Copy(&aws.Config{Endpoint: aws.String(c.IamEndpoint)}) dynamoSess := sess.Copy(&aws.Config{Endpoint: aws.String(c.DynamoDBEndpoint)}) kinesisSess := sess.Copy(&aws.Config{Endpoint: aws.String(c.KinesisEndpoint)}) // These two services need to be set up early so we can check on AccountID client.iamconn = iam.New(awsIamSess) client.stsconn = sts.New(sess) err = c.ValidateCredentials(client.stsconn) if err != nil { errs = append(errs, err) return nil, &multierror.Error{Errors: errs} } accountId, err := GetAccountId(client.iamconn, client.stsconn, cp.ProviderName) if err == nil { client.accountid = accountId } authErr := c.ValidateAccountId(client.accountid) if authErr != nil { errs = append(errs, authErr) } client.apigateway = apigateway.New(sess) client.autoscalingconn = autoscaling.New(sess) client.cfconn = cloudformation.New(sess) client.cloudfrontconn = cloudfront.New(sess) client.cloudtrailconn = cloudtrail.New(sess) client.cloudwatchconn = cloudwatch.New(sess) client.cloudwatcheventsconn = cloudwatchevents.New(sess) client.cloudwatchlogsconn = cloudwatchlogs.New(sess) client.codecommitconn = codecommit.New(usEast1Sess) client.codedeployconn = codedeploy.New(sess) client.dsconn = directoryservice.New(sess) client.dynamodbconn = dynamodb.New(dynamoSess) client.ec2conn = ec2.New(awsEc2Sess) client.ecrconn = ecr.New(sess) client.ecsconn = ecs.New(sess) client.efsconn = efs.New(sess) client.elasticacheconn = elasticache.New(sess) client.elasticbeanstalkconn = elasticbeanstalk.New(sess) client.elastictranscoderconn = elastictranscoder.New(sess) client.elbconn = elb.New(awsElbSess) client.emrconn = emr.New(sess) client.esconn = elasticsearch.New(sess) client.firehoseconn = firehose.New(sess) client.glacierconn = glacier.New(sess) client.kinesisconn = kinesis.New(kinesisSess) client.kmsconn = kms.New(sess) client.lambdaconn = lambda.New(sess) client.opsworksconn = opsworks.New(usEast1Sess) client.r53conn = route53.New(usEast1Sess) client.rdsconn = rds.New(sess) client.redshiftconn = redshift.New(sess) client.simpledbconn = simpledb.New(sess) client.s3conn = s3.New(sess) client.sesConn = ses.New(sess) client.snsconn = sns.New(sess) client.sqsconn = sqs.New(sess) } if len(errs) > 0 { return nil, &multierror.Error{Errors: errs} } return &client, nil }
// Client configures and returns a fully initialized AWSClient func (c *Config) Client() (interface{}, error) { var client AWSClient // Get the auth and region. This can fail if keys/regions were not // specified and we're attempting to use the environment. var errs []error log.Println("[INFO] Building AWS region structure") err := c.ValidateRegion() if err != nil { errs = append(errs, err) } if len(errs) == 0 { // store AWS region in client struct, for region specific operations such as // bucket storage in S3 client.region = c.Region log.Println("[INFO] Building AWS auth structure") creds := getCreds(c.AccessKey, c.SecretKey, c.Token) // Call Get to check for credential provider. If nothing found, we'll get an // error, and we can present it nicely to the user _, err = creds.Get() if err != nil { errs = append(errs, fmt.Errorf("Error loading credentials for AWS Provider: %s", err)) return nil, &multierror.Error{Errors: errs} } awsConfig := &aws.Config{ Credentials: creds, Region: aws.String(c.Region), MaxRetries: aws.Int(c.MaxRetries), HTTPClient: cleanhttp.DefaultClient(), } log.Println("[INFO] Initializing IAM Connection") sess := session.New(awsConfig) client.iamconn = iam.New(sess) err = c.ValidateCredentials(client.iamconn) if err != nil { errs = append(errs, err) } // Some services exist only in us-east-1, e.g. because they manage // resources that can span across multiple regions, or because // signature format v4 requires region to be us-east-1 for global // endpoints: // http://docs.aws.amazon.com/general/latest/gr/sigv4_changes.html usEast1AwsConfig := &aws.Config{ Credentials: creds, Region: aws.String("us-east-1"), MaxRetries: aws.Int(c.MaxRetries), HTTPClient: cleanhttp.DefaultClient(), } usEast1Sess := session.New(usEast1AwsConfig) awsDynamoDBConfig := *awsConfig awsDynamoDBConfig.Endpoint = aws.String(c.DynamoDBEndpoint) log.Println("[INFO] Initializing DynamoDB connection") dynamoSess := session.New(&awsDynamoDBConfig) client.dynamodbconn = dynamodb.New(dynamoSess) log.Println("[INFO] Initializing ELB connection") client.elbconn = elb.New(sess) log.Println("[INFO] Initializing S3 connection") client.s3conn = s3.New(sess) log.Println("[INFO] Initializing SQS connection") client.sqsconn = sqs.New(sess) log.Println("[INFO] Initializing SNS connection") client.snsconn = sns.New(sess) log.Println("[INFO] Initializing RDS Connection") client.rdsconn = rds.New(sess) awsKinesisConfig := *awsConfig awsKinesisConfig.Endpoint = aws.String(c.KinesisEndpoint) log.Println("[INFO] Initializing Kinesis Connection") kinesisSess := session.New(&awsKinesisConfig) client.kinesisconn = kinesis.New(kinesisSess) authErr := c.ValidateAccountId(client.iamconn) if authErr != nil { errs = append(errs, authErr) } log.Println("[INFO] Initializing Kinesis Firehose Connection") client.firehoseconn = firehose.New(sess) log.Println("[INFO] Initializing AutoScaling connection") client.autoscalingconn = autoscaling.New(sess) log.Println("[INFO] Initializing EC2 Connection") client.ec2conn = ec2.New(sess) log.Println("[INFO] Initializing ECR Connection") client.ecrconn = ecr.New(sess) log.Println("[INFO] Initializing ECS Connection") client.ecsconn = ecs.New(sess) log.Println("[INFO] Initializing EFS Connection") client.efsconn = efs.New(sess) log.Println("[INFO] Initializing ElasticSearch Connection") client.esconn = elasticsearch.New(sess) log.Println("[INFO] Initializing Route 53 connection") client.r53conn = route53.New(usEast1Sess) log.Println("[INFO] Initializing Elasticache Connection") client.elasticacheconn = elasticache.New(sess) log.Println("[INFO] Initializing Lambda Connection") client.lambdaconn = lambda.New(sess) log.Println("[INFO] Initializing Cloudformation Connection") client.cfconn = cloudformation.New(sess) log.Println("[INFO] Initializing CloudWatch SDK connection") client.cloudwatchconn = cloudwatch.New(sess) log.Println("[INFO] Initializing CloudTrail connection") client.cloudtrailconn = cloudtrail.New(sess) log.Println("[INFO] Initializing CloudWatch Logs connection") client.cloudwatchlogsconn = cloudwatchlogs.New(sess) log.Println("[INFO] Initializing OpsWorks Connection") client.opsworksconn = opsworks.New(usEast1Sess) log.Println("[INFO] Initializing Directory Service connection") client.dsconn = directoryservice.New(sess) log.Println("[INFO] Initializing Glacier connection") client.glacierconn = glacier.New(sess) log.Println("[INFO] Initializing CodeDeploy Connection") client.codedeployconn = codedeploy.New(sess) log.Println("[INFO] Initializing CodeCommit SDK connection") client.codecommitconn = codecommit.New(usEast1Sess) log.Println("[INFO] Initializing Redshift SDK connection") client.redshiftconn = redshift.New(sess) } if len(errs) > 0 { return nil, &multierror.Error{Errors: errs} } return &client, nil }
// Client configures and returns a fully initialized AWSClient func (c *Config) Client() (interface{}, error) { // Get the auth and region. This can fail if keys/regions were not // specified and we're attempting to use the environment. log.Println("[INFO] Building AWS region structure") err := c.ValidateRegion() if err != nil { return nil, err } var client AWSClient // store AWS region in client struct, for region specific operations such as // bucket storage in S3 client.region = c.Region log.Println("[INFO] Building AWS auth structure") creds, err := GetCredentials(c) if err != nil { return nil, err } // Call Get to check for credential provider. If nothing found, we'll get an // error, and we can present it nicely to the user cp, err := creds.Get() if err != nil { if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "NoCredentialProviders" { return nil, errors.New(`No valid credential sources found for AWS Provider. Please see https://terraform.io/docs/providers/aws/index.html for more information on providing credentials for the AWS Provider`) } return nil, fmt.Errorf("Error loading credentials for AWS Provider: %s", err) } log.Printf("[INFO] AWS Auth provider used: %q", cp.ProviderName) awsConfig := &aws.Config{ Credentials: creds, Region: aws.String(c.Region), MaxRetries: aws.Int(c.MaxRetries), HTTPClient: cleanhttp.DefaultClient(), S3ForcePathStyle: aws.Bool(c.S3ForcePathStyle), } if logging.IsDebugOrHigher() { awsConfig.LogLevel = aws.LogLevel(aws.LogDebugWithHTTPBody) awsConfig.Logger = awsLogger{} } if c.Insecure { transport := awsConfig.HTTPClient.Transport.(*http.Transport) transport.TLSClientConfig = &tls.Config{ InsecureSkipVerify: true, } } // Set up base session sess, err := session.NewSession(awsConfig) if err != nil { return nil, errwrap.Wrapf("Error creating AWS session: {{err}}", err) } // Removes the SDK Version handler, so we only have the provider User-Agent // Ex: "User-Agent: APN/1.0 HashiCorp/1.0 Terraform/0.7.9-dev" sess.Handlers.Build.Remove(request.NamedHandler{Name: "core.SDKVersionUserAgentHandler"}) sess.Handlers.Build.PushFrontNamed(addTerraformVersionToUserAgent) if extraDebug := os.Getenv("TERRAFORM_AWS_AUTHFAILURE_DEBUG"); extraDebug != "" { sess.Handlers.UnmarshalError.PushFrontNamed(debugAuthFailure) } // Some services exist only in us-east-1, e.g. because they manage // resources that can span across multiple regions, or because // signature format v4 requires region to be us-east-1 for global // endpoints: // http://docs.aws.amazon.com/general/latest/gr/sigv4_changes.html usEast1Sess := sess.Copy(&aws.Config{Region: aws.String("us-east-1")}) // Some services have user-configurable endpoints awsEc2Sess := sess.Copy(&aws.Config{Endpoint: aws.String(c.Ec2Endpoint)}) awsElbSess := sess.Copy(&aws.Config{Endpoint: aws.String(c.ElbEndpoint)}) awsIamSess := sess.Copy(&aws.Config{Endpoint: aws.String(c.IamEndpoint)}) awsS3Sess := sess.Copy(&aws.Config{Endpoint: aws.String(c.S3Endpoint)}) dynamoSess := sess.Copy(&aws.Config{Endpoint: aws.String(c.DynamoDBEndpoint)}) kinesisSess := sess.Copy(&aws.Config{Endpoint: aws.String(c.KinesisEndpoint)}) // These two services need to be set up early so we can check on AccountID client.iamconn = iam.New(awsIamSess) client.stsconn = sts.New(sess) if !c.SkipCredsValidation { err = c.ValidateCredentials(client.stsconn) if err != nil { return nil, err } } if !c.SkipRequestingAccountId { partition, accountId, err := GetAccountInfo(client.iamconn, client.stsconn, cp.ProviderName) if err == nil { client.partition = partition client.accountid = accountId } } authErr := c.ValidateAccountId(client.accountid) if authErr != nil { return nil, authErr } client.acmconn = acm.New(sess) client.apigateway = apigateway.New(sess) client.appautoscalingconn = applicationautoscaling.New(sess) client.autoscalingconn = autoscaling.New(sess) client.cfconn = cloudformation.New(sess) client.cloudfrontconn = cloudfront.New(sess) client.cloudtrailconn = cloudtrail.New(sess) client.cloudwatchconn = cloudwatch.New(sess) client.cloudwatcheventsconn = cloudwatchevents.New(sess) client.cloudwatchlogsconn = cloudwatchlogs.New(sess) client.codecommitconn = codecommit.New(usEast1Sess) client.codedeployconn = codedeploy.New(sess) client.dsconn = directoryservice.New(sess) client.dynamodbconn = dynamodb.New(dynamoSess) client.ec2conn = ec2.New(awsEc2Sess) client.ecrconn = ecr.New(sess) client.ecsconn = ecs.New(sess) client.efsconn = efs.New(sess) client.elasticacheconn = elasticache.New(sess) client.elasticbeanstalkconn = elasticbeanstalk.New(sess) client.elastictranscoderconn = elastictranscoder.New(sess) client.elbconn = elb.New(awsElbSess) client.elbv2conn = elbv2.New(awsElbSess) client.emrconn = emr.New(sess) client.esconn = elasticsearch.New(sess) client.firehoseconn = firehose.New(sess) client.glacierconn = glacier.New(sess) client.kinesisconn = kinesis.New(kinesisSess) client.kmsconn = kms.New(sess) client.lambdaconn = lambda.New(sess) client.lightsailconn = lightsail.New(usEast1Sess) client.opsworksconn = opsworks.New(usEast1Sess) client.r53conn = route53.New(usEast1Sess) client.rdsconn = rds.New(sess) client.redshiftconn = redshift.New(sess) client.simpledbconn = simpledb.New(sess) client.s3conn = s3.New(awsS3Sess) client.sesConn = ses.New(sess) client.snsconn = sns.New(sess) client.sqsconn = sqs.New(sess) client.ssmconn = ssm.New(sess) client.wafconn = waf.New(sess) return &client, nil }
// PushDockerImageToECR pushes a local Docker image to an ECR repository func PushDockerImageToECR(localImageTag string, ecrRepoName string, awsSession *session.Session, logger *logrus.Logger) (string, error) { stsSvc := sts.New(awsSession) ecrSvc := ecr.New(awsSession) // 1. Get the caller identity s.t. we can get the ECR URL which includes the // account name stsIdentityOutput, stsIdentityErr := stsSvc.GetCallerIdentity(&sts.GetCallerIdentityInput{}) if nil != stsIdentityErr { return "", stsIdentityErr } // 2. Create the URL to which we're going to do the push localImageTagParts := strings.Split(localImageTag, ":") ecrTagValue := fmt.Sprintf("%s.dkr.ecr.%s.amazonaws.com/%s:%s", *stsIdentityOutput.Account, *awsSession.Config.Region, ecrRepoName, localImageTagParts[len(localImageTagParts)-1]) // 3. Tag the local image with the ECR tag dockerTagCmd := exec.Command("docker", "tag", localImageTag, ecrTagValue) dockerTagCmdErr := runOSCommand(dockerTagCmd, logger) if nil != dockerTagCmdErr { return "", dockerTagCmdErr } // 4. Push the image - if that fails attempt to reauthorize with the docker // client and try again var pushError error dockerPushCmd := exec.Command("docker", "push", ecrTagValue) pushError = runOSCommand(dockerPushCmd, logger) if nil != pushError { logger.WithFields(logrus.Fields{ "Error": pushError, }).Info("ECR push failed - reauthorizing") ecrAuthTokenResult, ecrAuthTokenResultErr := ecrSvc.GetAuthorizationToken(&ecr.GetAuthorizationTokenInput{}) if nil != ecrAuthTokenResultErr { pushError = ecrAuthTokenResultErr } else { authData := ecrAuthTokenResult.AuthorizationData[0] authToken, authTokenErr := base64.StdEncoding.DecodeString(*authData.AuthorizationToken) if nil != authTokenErr { pushError = authTokenErr } else { authTokenString := string(authToken) authTokenParts := strings.Split(authTokenString, ":") dockerURL := fmt.Sprintf("https://%s.dkr.ecr.%s.amazonaws.com", *stsIdentityOutput.Account, *awsSession.Config.Region) dockerLoginCmd := exec.Command("docker", "login", "-u", authTokenParts[0], "-p", authTokenParts[1], "-e", "none", dockerURL) dockerLoginCmdErr := runOSCommand(dockerLoginCmd, logger) if nil != dockerLoginCmdErr { pushError = dockerLoginCmdErr } else { // Try it again... dockerRetryPushCmd := exec.Command("docker", "push", ecrTagValue) dockerRetryPushCmdErr := runOSCommand(dockerRetryPushCmd, logger) pushError = dockerRetryPushCmdErr } } } } return ecrTagValue, pushError }
func DockerLogin(ac docker.AuthConfiguration) (string, error) { log := Logger.At("DockerLogin").Start() if ac.Email == "" { ac.Email = "*****@*****.**" } // if ECR URL, try Username and Password as IAM keys to get auth token if match := regexpECR.FindStringSubmatch(ac.ServerAddress); len(match) > 1 { ECR := ecr.New(session.New(), &aws.Config{ Credentials: credentials.NewStaticCredentials(ac.Username, ac.Password, ""), Region: aws.String(match[2]), }) res, err := ECR.GetAuthorizationToken(&ecr.GetAuthorizationTokenInput{ RegistryIds: []*string{aws.String(match[1])}, }) if err != nil { return "", err } if len(res.AuthorizationData) < 1 { return "", fmt.Errorf("no authorization data") } endpoint := *res.AuthorizationData[0].ProxyEndpoint data, err := base64.StdEncoding.DecodeString(*res.AuthorizationData[0].AuthorizationToken) if err != nil { return "", err } parts := strings.SplitN(string(data), ":", 2) ac.Password = parts[1] ac.ServerAddress = endpoint[8:] ac.Username = parts[0] } log = log.Namespace("host=%q user=%q", ac.ServerAddress, ac.Username) args := []string{"login", "-e", ac.Email, "-u", ac.Username, "-p", ac.Password, ac.ServerAddress} if _, err := exec.Command("docker", args...).CombinedOutput(); err != nil { log.Error(err) return "", err } log.Success() return ac.ServerAddress, nil }