github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/creds/secretsmanager/manager.go (about)

     1  package secretsmanager
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  
     7  	"code.cloudfoundry.org/lager"
     8  	"github.com/aws/aws-sdk-go/aws"
     9  	"github.com/aws/aws-sdk-go/aws/credentials"
    10  	"github.com/aws/aws-sdk-go/aws/session"
    11  	"github.com/aws/aws-sdk-go/service/secretsmanager"
    12  	"github.com/pf-qiu/concourse/v6/atc/creds"
    13  )
    14  
    15  const DefaultPipelineSecretTemplate = "/concourse/{{.Team}}/{{.Pipeline}}/{{.Secret}}"
    16  const DefaultTeamSecretTemplate = "/concourse/{{.Team}}/{{.Secret}}"
    17  
    18  type Manager struct {
    19  	AwsAccessKeyID         string `long:"access-key" description:"AWS Access key ID"`
    20  	AwsSecretAccessKey     string `long:"secret-key" description:"AWS Secret Access Key"`
    21  	AwsSessionToken        string `long:"session-token" description:"AWS Session Token"`
    22  	AwsRegion              string `long:"region" description:"AWS region to send requests to"`
    23  	PipelineSecretTemplate string `long:"pipeline-secret-template" description:"AWS Secrets Manager secret identifier template used for pipeline specific parameter" default:"/concourse/{{.Team}}/{{.Pipeline}}/{{.Secret}}"`
    24  	TeamSecretTemplate     string `long:"team-secret-template" description:"AWS Secrets Manager secret identifier  template used for team specific parameter" default:"/concourse/{{.Team}}/{{.Secret}}"`
    25  	SecretManager          *SecretsManager
    26  }
    27  
    28  func (manager *Manager) Init(log lager.Logger) error {
    29  	config := &aws.Config{Region: &manager.AwsRegion}
    30  	if manager.AwsAccessKeyID != "" {
    31  		config.Credentials = credentials.NewStaticCredentials(manager.AwsAccessKeyID, manager.AwsSecretAccessKey, manager.AwsSessionToken)
    32  	}
    33  
    34  	sess, err := session.NewSession(config)
    35  	if err != nil {
    36  		log.Error("create-aws-session", err)
    37  		return err
    38  	}
    39  
    40  	manager.SecretManager = &SecretsManager{
    41  		log: log,
    42  		api: secretsmanager.New(sess),
    43  	}
    44  	return nil
    45  }
    46  
    47  func (manager *Manager) Health() (*creds.HealthResponse, error) {
    48  	health := &creds.HealthResponse{
    49  		Method: "GetSecretValue",
    50  	}
    51  
    52  	_, _, _, err := manager.SecretManager.getSecretById("__concourse-health-check")
    53  	if err != nil {
    54  		health.Error = err.Error()
    55  		return health, nil
    56  	}
    57  
    58  	health.Response = map[string]string{
    59  		"status": "UP",
    60  	}
    61  
    62  	return health, nil
    63  }
    64  
    65  func (manager *Manager) MarshalJSON() ([]byte, error) {
    66  	health, err := manager.Health()
    67  	if err != nil {
    68  		return nil, err
    69  	}
    70  
    71  	return json.Marshal(&map[string]interface{}{
    72  		"aws_region":               manager.AwsRegion,
    73  		"pipeline_secret_template": manager.PipelineSecretTemplate,
    74  		"team_secret_template":     manager.TeamSecretTemplate,
    75  		"health":                   health,
    76  	})
    77  }
    78  
    79  func (manager *Manager) IsConfigured() bool {
    80  	return manager.AwsRegion != ""
    81  }
    82  
    83  func (manager *Manager) Validate() error {
    84  	if _, err := creds.BuildSecretTemplate("pipeline-secret-template", manager.PipelineSecretTemplate); err != nil {
    85  		return err
    86  	}
    87  	if _, err := creds.BuildSecretTemplate("team-secret-template", manager.TeamSecretTemplate); err != nil {
    88  		return err
    89  	}
    90  
    91  	// All of the AWS credential variables may be empty since credentials may be obtained via environemnt variables
    92  	// or other means. However, if one of them is provided, then all of them (except session token) must be provided.
    93  	if manager.AwsAccessKeyID == "" && manager.AwsSecretAccessKey == "" && manager.AwsSessionToken == "" {
    94  		return nil
    95  	}
    96  
    97  	if manager.AwsAccessKeyID == "" {
    98  		return errors.New("must provide aws access key id")
    99  	}
   100  
   101  	if manager.AwsSecretAccessKey == "" {
   102  		return errors.New("must provide aws secret access key")
   103  	}
   104  
   105  	return nil
   106  }
   107  
   108  func (manager *Manager) NewSecretsFactory(log lager.Logger) (creds.SecretsFactory, error) {
   109  	config := &aws.Config{Region: &manager.AwsRegion}
   110  	if manager.AwsAccessKeyID != "" {
   111  		config.Credentials = credentials.NewStaticCredentials(manager.AwsAccessKeyID, manager.AwsSecretAccessKey, manager.AwsSessionToken)
   112  	}
   113  
   114  	sess, err := session.NewSession(config)
   115  	if err != nil {
   116  		log.Error("create-aws-session", err)
   117  		return nil, err
   118  	}
   119  
   120  	pipelineSecretTemplate, err := creds.BuildSecretTemplate("pipeline-secret-template", manager.PipelineSecretTemplate)
   121  	if err != nil {
   122  		return nil, err
   123  	}
   124  
   125  	teamSecretTemplate, err := creds.BuildSecretTemplate("team-secret-template", manager.TeamSecretTemplate)
   126  	if err != nil {
   127  		return nil, err
   128  	}
   129  
   130  	return NewSecretsManagerFactory(log, sess, []*creds.SecretTemplate{pipelineSecretTemplate, teamSecretTemplate}), nil
   131  }
   132  
   133  func (manager Manager) Close(logger lager.Logger) {
   134  	// TODO - to implement
   135  }