Skip to content

Commit

Permalink
Draft implementation for Issue anchore#7 with aws secret manager (anc…
Browse files Browse the repository at this point in the history
…hore#16)

* Draft the codes of read credential from aws secret manager

* Add more debug logs

* Resolve conflict

* Fix a typo

* Apply the factory pattern to load the credential

* fix import cycle

* cleanup import

* Fix typo

* Fix the credential factory usage

* Change the method name to LoadFromCredentialStore

* Enable reading credential from aws secret manager
  • Loading branch information
cafeliker authored Mar 21, 2020
1 parent 7ff4da9 commit 3428f85
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 3 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/anchore/harbor-scanner-adapter
go 1.12

require (
github.com/aws/aws-sdk-go v1.25.48
github.com/elazarl/goproxy v0.0.0-20190711103511-473e67f1d7d2 // indirect
github.com/elazarl/goproxy/ext v0.0.0-20191011121108-aa519ddbe484 // indirect
github.com/golang/groupcache v0.0.0-20191002201903-404acd9df4cc
Expand Down
12 changes: 9 additions & 3 deletions pkg/adapter/anchore/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,18 @@ import (
"crypto/tls"
"encoding/json"
"fmt"
"github.com/anchore/harbor-scanner-adapter/pkg/model/anchore"
"github.com/parnurzeal/gorequest"
log "github.com/sirupsen/logrus"
"math"
"net/url"
"path"
"sort"
"strconv"
"strings"
"time"

"github.com/anchore/harbor-scanner-adapter/pkg/adapter/anchore/credential"
"github.com/anchore/harbor-scanner-adapter/pkg/model/anchore"
"github.com/parnurzeal/gorequest"
log "github.com/sirupsen/logrus"
)

const (
Expand All @@ -38,6 +40,10 @@ type ClientConfig struct {
}

func getNewRequest(clientConfiguration *ClientConfig) *gorequest.SuperAgent {
passwordConfig := clientConfiguration.Password
credenitalLoader := credential.CreateCredentialLoader(passwordConfig)
clientConfiguration.Password = credenitalLoader.LoadFromCredentialStore(passwordConfig)

timeout := time.Duration(clientConfiguration.TimeoutSeconds) * time.Second
return gorequest.New().TLSClientConfig(&tls.Config{InsecureSkipVerify: clientConfiguration.TLSVerify}).SetBasicAuth(clientConfiguration.Username, clientConfiguration.Password).Timeout(timeout)
}
Expand Down
84 changes: 84 additions & 0 deletions pkg/adapter/anchore/credential/awsloader.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package credential

import (
"encoding/json"
"fmt"
"strings"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/secretsmanager"
log "github.com/sirupsen/logrus"
)

type AWSCredenitalLoader struct{}

func (c *AWSCredenitalLoader) LoadFromCredentialStore(passwordConfig string) string {
if strings.HasPrefix(passwordConfig, "aws:secretmanager") {
log.Debug("Start to load password from AWS Secret Manager")
value := getAWSSecret(passwordConfig)
if value != "" {
return value
}
}
return passwordConfig
}

func getAWSSecret(configValue string) string {
// The expected format is aws:secretmanager:<region>:<secret name>:<secret key>
fileds := strings.Split(configValue, ":")
region, name, key := fileds[2], fileds[3], fileds[4]

log.WithFields(log.Fields{"region": region, "name": name, "key": key}).Debug("pass in secret manager parameters")

//Create a Secrets Manager client
svc := secretsmanager.New(session.New(), &aws.Config{Region: aws.String(region)})
input := &secretsmanager.GetSecretValueInput{
SecretId: aws.String(name),
VersionStage: aws.String("AWSCURRENT"), // VersionStage defaults to AWSCURRENT if unspecified
}

result, err := svc.GetSecretValue(input)
if err != nil {
if aerr, ok := err.(awserr.Error); ok {
switch aerr.Code() {
case secretsmanager.ErrCodeDecryptionFailure:
// Secrets Manager can't decrypt the protected secret text using the provided KMS key.
fmt.Println(secretsmanager.ErrCodeDecryptionFailure, aerr.Error())

case secretsmanager.ErrCodeInternalServiceError:
// An error occurred on the server side.
fmt.Println(secretsmanager.ErrCodeInternalServiceError, aerr.Error())

case secretsmanager.ErrCodeInvalidParameterException:
// You provided an invalid value for a parameter.
fmt.Println(secretsmanager.ErrCodeInvalidParameterException, aerr.Error())

case secretsmanager.ErrCodeInvalidRequestException:
// You provided a parameter value that is not valid for the current state of the resource.
fmt.Println(secretsmanager.ErrCodeInvalidRequestException, aerr.Error())

case secretsmanager.ErrCodeResourceNotFoundException:
// We can't find the resource that you asked for.
fmt.Println(secretsmanager.ErrCodeResourceNotFoundException, aerr.Error())
}
} else {
// Print the error, cast err to awserr.Error to get the Code and
// Message from an error.
fmt.Println(err.Error())
}
} else {
// Decrypts secret using the associated KMS CMK.
var secretString string
if result.SecretString != nil {
secretString = *result.SecretString
// a map container to decode the JSON structure into
kmap := make(map[string]string)
json.Unmarshal([]byte(secretString), &kmap)
return kmap[key]
}
}

return ""
}
7 changes: 7 additions & 0 deletions pkg/adapter/anchore/credential/defaultloader.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package credential

type DefaultCredenitalLoader struct{}

func (c *DefaultCredenitalLoader) LoadFromCredentialStore(passwordConfig string) string {
return passwordConfig
}
16 changes: 16 additions & 0 deletions pkg/adapter/anchore/credential/factory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package credential

import (
"strings"
)

type CredentialLoader interface {
LoadFromCredentialStore(passwordConfig string) string
}

func CreateCredentialLoader(passwordConfig string) CredentialLoader {
if strings.HasPrefix(passwordConfig, "aws:secretmanager") {
return &AWSCredenitalLoader{}
}
return &DefaultCredenitalLoader{}
}

0 comments on commit 3428f85

Please sign in to comment.