diff --git a/agent.go b/agent.go index 799e25909..ae3c2f1eb 100644 --- a/agent.go +++ b/agent.go @@ -6,6 +6,17 @@ import ( ) type ( + // AWSConfig is a configuration used to authenticate against AWS IAM Roles Anywhere + AWSConfig struct { + ClientCertPath string + ClientKeyPath string + ClientBundlePath string + RoleARN string + TrustAnchorARN string + ProfileARN string + Region string + } + // ClusterMember is the representation of an agent inside a cluster. ClusterMember struct { IPAddress string @@ -101,6 +112,13 @@ type ( SSLCACert string UpdateID int CertRetryInterval time.Duration + AWSClientCert string + AWSClientKey string + AWSClientBundle string + AWSRoleARN string + AWSTrustAnchorARN string + AWSProfileARN string + AWSRegion string } NomadConfig struct { @@ -237,7 +255,7 @@ type ( var ( // Version represents the version of the agent. - Version = "2.18.0" + Version = "2.17.0" ) const ( @@ -349,6 +367,10 @@ const ( KubernetesServiceHost = "KUBERNETES_SERVICE_HOST" // KubernetesServicePortHttps is the environment variable of the kubernetes API server https port KubernetesServicePortHttps = "KUBERNETES_SERVICE_PORT_HTTPS" + // DefaultAWSClientCertPath is the default path to the AWS client certificate file + DefaultAWSClientCertPath = "/certs/aws-client.crt" + // DefaultAWSClientKeyPath is the default path to the AWS client key file + DefaultAWSClientKeyPath = "/certs/aws-client.key" ) const ( diff --git a/cmd/agent/main.go b/cmd/agent/main.go index 95260db3b..040cf1861 100644 --- a/cmd/agent/main.go +++ b/cmd/agent/main.go @@ -330,6 +330,7 @@ func main() { DockerInfoService: dockerInfoService, ContainerPlatform: containerPlatform, } + edgeManager = edge.NewManager(edgeManagerParameters) edgeKey, err := edge.RetrieveEdgeKey(options.EdgeKey, clusterService, options.DataPath) @@ -377,7 +378,21 @@ func main() { if options.EdgeMode { config.Addr = advertiseAddr } - err = registry.StartRegistryServer(edgeManager) + + var awsConfig agent.AWSConfig + if os.IsValidAWSConfig(options) { + log.Info().Msg("AWS configuration detected") + awsConfig = agent.AWSConfig{ + ClientCertPath: options.AWSClientCert, + ClientKeyPath: options.AWSClientKey, + RoleARN: options.AWSRoleARN, + TrustAnchorARN: options.AWSTrustAnchorARN, + ProfileARN: options.AWSProfileARN, + Region: options.AWSRegion, + } + } + + err = registry.StartRegistryServer(edgeManager, &awsConfig) if err != nil { log.Fatal().Err(err).Msg("unable to start registry server") } diff --git a/edge/registry/aws.go b/edge/registry/aws.go new file mode 100644 index 000000000..776086909 --- /dev/null +++ b/edge/registry/aws.go @@ -0,0 +1,73 @@ +package registry + +import ( + "context" + + "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/credentials" + iamra "github.com/aws/rolesanywhere-credential-helper/aws_signing_helper" + "github.com/awslabs/amazon-ecr-credential-helper/ecr-login/api" + "github.com/portainer/agent" + "github.com/rs/zerolog/log" +) + +func doAWSIAMRolesAnywhereAuthAndGetECRCredentials(serverURL string, awsConfig *agent.AWSConfig) (*agent.RegistryCredentials, error) { + iamraCreds, err := authenticateAgainstIAMRA(awsConfig) + if err != nil { + return nil, err + } + + factory := api.DefaultClientFactory{} + + cfg, err := config.LoadDefaultConfig( + context.TODO(), + config.WithRegion(awsConfig.Region), + config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(iamraCreds.AccessKeyId, iamraCreds.SecretAccessKey, iamraCreds.SessionToken)), + ) + if err != nil { + log.Err(err).Msg("unable to build AWS client config") + return nil, err + } + + client := factory.NewClient(cfg) + + creds, err := client.GetCredentials(serverURL) + if err != nil { + // This might not be an ECR registry + // Therefore we deliberately not return an error here so that the upstream logic can fallback to other credential providers + log.Warn().Str("server_url", serverURL).Err(err).Msg("unable to retrieve credentials from server") + return nil, nil + } + + return &agent.RegistryCredentials{ + ServerURL: serverURL, + Username: creds.Username, + Secret: creds.Password, + }, nil +} + +func authenticateAgainstIAMRA(awsConfig *agent.AWSConfig) (*iamra.CredentialProcessOutput, error) { + credentialsOptions := iamra.CredentialsOpts{ + PrivateKeyId: awsConfig.ClientKeyPath, + CertificateId: awsConfig.ClientCertPath, + RoleArn: awsConfig.RoleARN, + ProfileArnStr: awsConfig.ProfileARN, + TrustAnchorArnStr: awsConfig.TrustAnchorARN, + SessionDuration: 3600, + NoVerifySSL: false, + WithProxy: false, + Debug: false, + } + + if awsConfig.ClientBundlePath != "" { + credentialsOptions.CertificateBundleId = awsConfig.ClientBundlePath + } + + credentialProcessOutput, err := iamra.GenerateCredentials(&credentialsOptions) + if err != nil { + log.Err(err).Msg("unable to authenticate against AWS IAM Roles Anywhere") + return nil, err + } + + return &credentialProcessOutput, nil +} diff --git a/edge/registry/server.go b/edge/registry/server.go index ceb7e121c..7b2ab573b 100644 --- a/edge/registry/server.go +++ b/edge/registry/server.go @@ -2,7 +2,6 @@ package registry import ( "errors" - "fmt" "net/http" "net/url" "strings" @@ -21,12 +20,14 @@ import ( type Handler struct { *mux.Router EdgeManager *edge.Manager + awsConfig *agent.AWSConfig } -func NewEdgeRegistryHandler(edgeManager *edge.Manager) *Handler { +func NewEdgeRegistryHandler(edgeManager *edge.Manager, awsConfig *agent.AWSConfig) *Handler { h := &Handler{ Router: mux.NewRouter(), EdgeManager: edgeManager, + awsConfig: awsConfig, } h.Handle("/lookup", httperror.LoggerHandler(h.LookupHandler)).Methods(http.MethodGet) @@ -47,6 +48,26 @@ func (handler *Handler) LookupHandler(rw http.ResponseWriter, r *http.Request) * return response.Empty(rw) } + // We could technically filter out non ECR registry URLs here and not apply this logic to all the registries + // The cost of going through this logic for all server/registries is to authenticate against IAM RA for each registry + // We could filter non ECR registries based on a URL pattern: https://docs.aws.amazon.com/AmazonECR/latest/userguide/Registries.html + // BUT, to keep support for DNS aliases with ECR registries (e.g. mapping a custom domain such as myregistry.portainer.io to an ECR registry) I've decided to avoid the filter + if handler.awsConfig != nil { + log.Info().Msg("using local AWS config for credential lookup") + + c, err := doAWSIAMRolesAnywhereAuthAndGetECRCredentials(serverUrl, handler.awsConfig) + if err != nil { + return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve credentials", err} + } + + // Only write credentials if credentials are found + // For non ECR registries, credentials will be set to nil + // Therefore we want to fallback to the default credential lookup + if c != nil { + return response.JSON(rw, c) + } + } + credentials := stackManager.GetEdgeRegistryCredentials() if len(credentials) > 0 { var key string @@ -75,32 +96,10 @@ func (handler *Handler) LookupHandler(rw http.ResponseWriter, r *http.Request) * return response.Empty(rw) } -func LookupCredentials(credentials []agent.RegistryCredentials, serverUrl string) (*agent.RegistryCredentials, error) { - u, err := url.Parse(serverUrl) - if err != nil { - return nil, err - } - - var key string - if strings.HasSuffix(u.Hostname(), ".docker.io") { - key = "docker.io" - } else { - key = u.Hostname() - } - - for _, c := range credentials { - if key == c.ServerURL { - return &c, nil - } - } - - return nil, fmt.Errorf("No credentials found for %s", serverUrl) -} - -func StartRegistryServer(edgeManager *edge.Manager) (err error) { +func StartRegistryServer(edgeManager *edge.Manager, awsConfig *agent.AWSConfig) (err error) { log.Info().Msg("starting registry credential server") - h := NewEdgeRegistryHandler(edgeManager) + h := NewEdgeRegistryHandler(edgeManager, awsConfig) server := &http.Server{ Addr: "127.0.0.1:9005", diff --git a/go.mod b/go.mod index 09d68bd4f..362fa3459 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,10 @@ go 1.18 require ( github.com/Microsoft/go-winio v0.5.1 github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d + github.com/aws/aws-sdk-go-v2/config v1.18.2 + github.com/aws/aws-sdk-go-v2/credentials v1.13.2 + github.com/aws/rolesanywhere-credential-helper v1.0.2 + github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20221118222346-4177265fa425 github.com/docker/distribution v2.8.1+incompatible github.com/docker/docker v20.10.16+incompatible github.com/gorilla/mux v1.8.0 @@ -39,6 +43,19 @@ require ( github.com/alecthomas/units v0.0.0-20210208195552-ff826a37aa15 // indirect github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878 // indirect github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 // indirect + github.com/aws/aws-sdk-go v1.44.57 // indirect + github.com/aws/aws-sdk-go-v2 v1.17.1 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.19 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.25 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.19 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.3.26 // indirect + github.com/aws/aws-sdk-go-v2/service/ecr v1.17.22 // indirect + github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.13.19 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.19 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.11.25 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.8 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.17.4 // indirect + github.com/aws/smithy-go v1.13.4 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.4.0 // indirect @@ -67,6 +84,7 @@ require ( github.com/hashicorp/go-uuid v1.0.2 // indirect github.com/hashicorp/memberlist v0.1.4 // indirect github.com/jaypipes/pcidb v1.0.0 // indirect + github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/jpillora/backoff v1.0.0 // indirect github.com/jpillora/sizestr v1.0.0 // indirect @@ -83,7 +101,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.0.2 // indirect github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect - github.com/sirupsen/logrus v1.8.1 // indirect + github.com/sirupsen/logrus v1.9.0 // indirect github.com/tidwall/gjson v1.14.0 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.0 // indirect diff --git a/go.sum b/go.sum index 1d06259fb..e11c41260 100644 --- a/go.sum +++ b/go.sum @@ -58,6 +58,40 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ= github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= +github.com/aws/aws-sdk-go v1.44.57 h1:Dx1QD+cA89LE0fVQWSov22tpnTa0znq2Feyaa/myVjg= +github.com/aws/aws-sdk-go v1.44.57/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= +github.com/aws/aws-sdk-go-v2 v1.17.1 h1:02c72fDJr87N8RAC2s3Qu0YuvMRZKNZJ9F+lAehCazk= +github.com/aws/aws-sdk-go-v2 v1.17.1/go.mod h1:JLnGeGONAyi2lWXI1p0PCIOIy333JMVK1U7Hf0aRFLw= +github.com/aws/aws-sdk-go-v2/config v1.18.2 h1:tRhTb3xMZsB0gW0sXWpqs9FeIP8iQp5SvnvwiPXzHwo= +github.com/aws/aws-sdk-go-v2/config v1.18.2/go.mod h1:9XVoZTdD8ICjrgI5ddb8j918q6lEZkFYpb7uohgvU6c= +github.com/aws/aws-sdk-go-v2/credentials v1.13.2 h1:F/v1w0XcFDZjL0bCdi9XWJenoPKjGbzljBhDKcryzEQ= +github.com/aws/aws-sdk-go-v2/credentials v1.13.2/go.mod h1:eAT5aj/WJ2UDIA0IVNFc2byQLeD89SDEi4cjzH/MKoQ= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.19 h1:E3PXZSI3F2bzyj6XxUXdTIfvp425HHhwKsFvmzBwHgs= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.19/go.mod h1:VihW95zQpeKQWVPGkwT+2+WJNQV8UXFfMTWdU6VErL8= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.25 h1:nBO/RFxeq/IS5G9Of+ZrgucRciie2qpLy++3UGZ+q2E= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.25/go.mod h1:Zb29PYkf42vVYQY6pvSyJCJcFHlPIiY+YKdPtwnvMkY= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.19 h1:oRHDrwCTVT8ZXi4sr9Ld+EXk7N/KGssOr2ygNeojEhw= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.19/go.mod h1:6Q0546uHDp421okhmmGfbxzq2hBqbXFNpi4k+Q1JnQA= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.26 h1:Mza+vlnZr+fPKFKRq/lKGVvM6B/8ZZmNdEopOwSQLms= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.26/go.mod h1:Y2OJ+P+MC1u1VKnavT+PshiEuGPyh/7DqxoDNij4/bg= +github.com/aws/aws-sdk-go-v2/service/ecr v1.17.22 h1:cC+NNTWWyV0DZF94k2Ugz6NFSdcBoo08oNdYtj9hg5g= +github.com/aws/aws-sdk-go-v2/service/ecr v1.17.22/go.mod h1:kEVGiy2tACP0cegVqx4MrjsgQMSgrtgRq1fSa+Ix6F0= +github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.13.19 h1:AwWP9a5n9a6kcgpTOfZ2/AeHKdq1Cb+HwgWQ1ADqiZM= +github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.13.19/go.mod h1:j3mVo8gEwXjgzf9PfORBnYUUQnnjkd4OY6y5JmubV94= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.19 h1:GE25AWCdNUPh9AOJzI9KIJnja7IwUc1WyUqz/JTyJ/I= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.19/go.mod h1:02CP6iuYP+IVnBX5HULVdSAku/85eHB2Y9EsFhrkEwU= +github.com/aws/aws-sdk-go-v2/service/sso v1.11.25 h1:GFZitO48N/7EsFDt8fMa5iYdmWqkUDDB3Eje6z3kbG0= +github.com/aws/aws-sdk-go-v2/service/sso v1.11.25/go.mod h1:IARHuzTXmj1C0KS35vboR0FeJ89OkEy1M9mWbK2ifCI= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.8 h1:jcw6kKZrtNfBPJkaHrscDOZoe5gvi9wjudnxvozYFJo= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.8/go.mod h1:er2JHN+kBY6FcMfcBBKNGCT3CarImmdFzishsqBmSRI= +github.com/aws/aws-sdk-go-v2/service/sts v1.17.4 h1:YNncBj5dVYd05i4ZQ+YicOotSXo0ufc9P8kTioi13EM= +github.com/aws/aws-sdk-go-v2/service/sts v1.17.4/go.mod h1:bXcN3koeVYiJcdDU89n3kCYILob7Y34AeLopUbZgLT4= +github.com/aws/rolesanywhere-credential-helper v1.0.2 h1:uE3ebUGDRPYRYG+G8SPzznQFDkvYMes3NIWvl0JGkDg= +github.com/aws/rolesanywhere-credential-helper v1.0.2/go.mod h1:QVGNxlDlYhjR0/ZUee7uGl0hNChWidNpe2+GD87Buqk= +github.com/aws/smithy-go v1.13.4 h1:/RN2z1txIJWeXeOkzX+Hk/4Uuvv7dWtCjbmVJcrskyk= +github.com/aws/smithy-go v1.13.4/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= +github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20221118222346-4177265fa425 h1:5+gCwtWMYJ3oIoWCxZ9uGexsoc5yICphWRTyp1A6pyQ= +github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20221118222346-4177265fa425/go.mod h1:exIdpgK6SlXjjeLFjSTUJxKUI+AGen47qo6n+mQs5xM= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -70,6 +104,7 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -77,6 +112,7 @@ github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6 github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v20.10.16+incompatible h1:2Db6ZR/+FUR3hqPMwnogOPHFn405crbpxvWzKovETOQ= github.com/docker/docker v20.10.16+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= @@ -162,6 +198,7 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -232,6 +269,10 @@ github.com/jaypipes/ghw v0.9.0/go.mod h1:dXMo19735vXOjpIBDyDYSp31sB2u4hrtRCMxInq github.com/jaypipes/pcidb v1.0.0 h1:vtZIfkiCUE42oYbJS0TAq9XSfSmcsgo9IdxSm9qzYU8= github.com/jaypipes/pcidb v1.0.0/go.mod h1:TnYUvqhPBzCKnH34KrIX22kAeEbDCSRJ9cqLRCuNDfk= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jpillora/ansi v1.0.2/go.mod h1:D2tT+6uzJvN1nBVQILYWkIdq7zG+b5gcFN5WI/VyjMY= @@ -332,20 +373,26 @@ github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFo github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/tidwall/gjson v1.14.0 h1:6aeJ0bzojgWLa82gDQHcx3S0Lr/O51I9bJ5nv6JFx5w= github.com/tidwall/gjson v1.14.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= @@ -508,9 +555,12 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= diff --git a/os/options.go b/os/options.go index dc0fe25a5..735070bd1 100644 --- a/os/options.go +++ b/os/options.go @@ -33,6 +33,13 @@ const ( EnvKeySSLKey = "MTLS_SSL_KEY" EnvKeySSLCACert = "MTLS_SSL_CA" EnvKeyCertRetryInterval = "MTLS_CERT_RETRY_INTERVAL" + EnvKeyAWSClientCert = "AWS_CLIENT_CERT" + EnvKeyAWSClientKey = "AWS_CLIENT_KEY" + EnvKeyAWSClientBundle = "AWS_CLIENT_BUNDLE" + EnvKeyAWSRoleARN = "AWS_ROLE_ARN" + EnvKeyAWSTrustAnchorARN = "AWS_TRUST_ANCHOR_ARN" + EnvKeyAWSProfileARN = "AWS_PROFILE_ARN" + EnvKeyAWSRegion = "AWS_REGION" EnvKeyUpdateID = "UPDATE_ID" ) @@ -73,8 +80,21 @@ var ( fSSLKey = kingpin.Flag("sslkey", "Path to the SSL key used to identify the agent to Portainer").Envar(EnvKeySSLKey).String() fSSLCACert = kingpin.Flag("sslcacert", "Path to the SSL CA certificate used to validate the Portainer server").Envar(EnvKeySSLCACert).String() fCertRetryInterval = kingpin.Flag("certificate-retry-interval", "Interval used to block initialization until the certificate is available").Envar(EnvKeyCertRetryInterval).Duration() + + // AWS IAM Roles Anywhere + ECR + fAWSClientCert = kingpin.Flag("aws-cert", "Path to the x509 certificate used to authenticate against IAM Roles Anywhere").Envar(EnvKeyAWSClientCert).Default(agent.DefaultAWSClientCertPath).String() + fAWSClientKey = kingpin.Flag("aws-key", "Path to the private key used to authenticate against IAM Roles Anywhere").Envar(EnvKeyAWSClientKey).Default(agent.DefaultAWSClientKeyPath).String() + fAWSClientBundle = kingpin.Flag("aws-bundle", "Path to the x509 intermediate certificate bundle used to authenticate against IAM Roles Anywhere").Envar(EnvKeyAWSClientBundle).String() + fAWSRoleARN = kingpin.Flag("aws-role-arn", "AWS IAM target role to assume (IAM Roles Anywhere authentication)").Envar(EnvKeyAWSRoleARN).String() + fAWSTrustAnchorARN = kingpin.Flag("aws-trust-anchor-arn", "AWS IAM Trust anchor used for authentication against IAM Roles Anyhwere").Envar(EnvKeyAWSTrustAnchorARN).String() + fAWSProfileARN = kingpin.Flag("aws-profile-arn", "AWS profile ARN used to pull policies from (IAM Roles Anywhere authentication)").Envar(EnvKeyAWSProfileARN).String() + fAWSRegion = kingpin.Flag("aws-region", "AWS region used when signing against IAM Roles Anyhwere").Envar(EnvKeyAWSRegion).String() ) +func IsValidAWSConfig(opts *agent.Options) bool { + return opts.AWSRoleARN != "" && opts.AWSTrustAnchorARN != "" && opts.AWSProfileARN != "" && opts.AWSRegion != "" +} + func (parser *EnvOptionParser) Options() (*agent.Options, error) { kingpin.Parse() @@ -105,5 +125,12 @@ func (parser *EnvOptionParser) Options() (*agent.Options, error) { SSLCACert: *fSSLCACert, UpdateID: *fUpdateID, CertRetryInterval: *fCertRetryInterval, + AWSClientCert: *fAWSClientCert, + AWSClientKey: *fAWSClientKey, + AWSClientBundle: *fAWSClientBundle, + AWSRoleARN: *fAWSRoleARN, + AWSTrustAnchorARN: *fAWSTrustAnchorARN, + AWSProfileARN: *fAWSProfileARN, + AWSRegion: *fAWSRegion, }, nil }