Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dac83e23b6 | ||
|
|
86d383c7dd | ||
|
|
5ba86d5b84 | ||
|
|
39f8f290fc | ||
|
|
fcfe267a3f | ||
|
|
f263eefbba |
No files matched your search
@@ -17,7 +17,7 @@ and then the given credential will be revoked. In this way, after rotation,
|
||||
only Boundary knows the client secret in use by this plugin. More information
|
||||
about AWS static credentials can be found [here](https://docs.aws.amazon.com/sdkref/latest/guide/feature-static-credentials.html).
|
||||
|
||||
Credential rotation can be turned off by setting the
|
||||
Credential rotation can be turned off by setting the
|
||||
`disable_credential_rotation` attribute to `true`.
|
||||
|
||||
### Assume Role Credentials
|
||||
@@ -48,7 +48,7 @@ The plugin fetches hosts through the
|
||||
[DescribeInstances](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeInstances.html)
|
||||
call.
|
||||
|
||||
[Getting Started](https://github.com/hashicorp/boundary-plugin-aws/plugin/service/host/README.md)
|
||||
[Getting Started](plugin/service/host/README.md)
|
||||
|
||||
## Storage Bucket
|
||||
|
||||
@@ -60,7 +60,7 @@ these storage bucket resources can in turn be associated to targets within
|
||||
Boundary.
|
||||
|
||||
At creation, update or deletion of a storage bucket of this type, configuration of the
|
||||
plugin is performed via the attribute/secret values passed to the create, update, or
|
||||
plugin is performed via the attribute/secret values passed to the create, update, or
|
||||
delete calls actions. The values passed in to the plugin here are the attributes set
|
||||
on on a storage bucket in boundary.
|
||||
|
||||
@@ -76,4 +76,4 @@ The plugin fetches metadata about the files through the
|
||||
[HeadObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html)
|
||||
call.
|
||||
|
||||
[Getting Started](https://github.com/hashicorp/boundary-plugin-aws/plugin/service/storage/README.md)
|
||||
[Getting Started](plugin/service/storage/README.md)
|
||||
@@ -1,6 +1,6 @@
|
||||
module github.com/hashicorp/boundary-plugin-aws
|
||||
|
||||
go 1.20
|
||||
go 1.21
|
||||
|
||||
require (
|
||||
github.com/aws/aws-sdk-go v1.44.80
|
||||
@@ -11,18 +11,16 @@ require (
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.21.2
|
||||
github.com/aws/smithy-go v1.14.1
|
||||
github.com/google/go-cmp v0.5.9
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/hashicorp/boundary/sdk v0.0.33
|
||||
github.com/hashicorp/go-secure-stdlib/awsutil v0.2.2
|
||||
github.com/google/uuid v1.3.1
|
||||
github.com/hashicorp/boundary/sdk v0.0.41-0.20231117205527-08045ddb050e
|
||||
github.com/hashicorp/go-secure-stdlib/awsutil/v2 v2.0.0
|
||||
github.com/hashicorp/terraform-json v0.14.0
|
||||
github.com/mitchellh/mapstructure v1.5.0
|
||||
github.com/stretchr/testify v1.8.4
|
||||
google.golang.org/grpc v1.53.0
|
||||
google.golang.org/protobuf v1.28.1
|
||||
google.golang.org/grpc v1.59.0
|
||||
google.golang.org/protobuf v1.31.0
|
||||
)
|
||||
|
||||
replace github.com/hashicorp/go-secure-stdlib/awsutil v0.2.2 => github.com/hashicorp/go-secure-stdlib/awsutilv2 v0.0.0-20230809054404-9029211590fd
|
||||
|
||||
require (
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.12 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/config v1.18.33 // indirect
|
||||
@@ -39,29 +37,29 @@ require (
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.13.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.2 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/fatih/color v1.14.1 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/fatih/color v1.15.0 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/eventlogger v0.1.2-0.20230428153751-cca445805f24 // indirect
|
||||
github.com/hashicorp/eventlogger/filters/encrypt v0.1.8-0.20230428153751-cca445805f24 // indirect
|
||||
github.com/hashicorp/eventlogger v0.2.6-0.20231025104552-802587e608f0 // indirect
|
||||
github.com/hashicorp/eventlogger/filters/encrypt v0.1.8-0.20231025104552-802587e608f0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-hclog v1.5.0 // indirect
|
||||
github.com/hashicorp/go-kms-wrapping/v2 v2.0.9 // indirect
|
||||
github.com/hashicorp/go-kms-wrapping/v2 v2.0.14 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-uuid v1.0.3 // indirect
|
||||
github.com/hashicorp/go-version v1.5.0 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.17 // indirect
|
||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/pointerstructure v1.2.1 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/zclconf/go-cty v1.10.0 // indirect
|
||||
golang.org/x/crypto v0.8.0 // indirect
|
||||
golang.org/x/net v0.9.0 // indirect
|
||||
golang.org/x/sys v0.7.0 // indirect
|
||||
golang.org/x/text v0.9.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488 // indirect
|
||||
golang.org/x/crypto v0.14.0 // indirect
|
||||
golang.org/x/net v0.17.0 // indirect
|
||||
golang.org/x/sys v0.13.0 // indirect
|
||||
golang.org/x/text v0.13.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
@@ -1,9 +1,13 @@
|
||||
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
|
||||
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
||||
github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g=
|
||||
github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
|
||||
github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA=
|
||||
github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM=
|
||||
github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk=
|
||||
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
|
||||
github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=
|
||||
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/aws/aws-sdk-go v1.44.80 h1:jEXGecSgPdvM5KnyDsSgFhZSm7WwaTp4h544Im4SfhI=
|
||||
github.com/aws/aws-sdk-go v1.44.80/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
|
||||
github.com/aws/aws-sdk-go-v2 v1.18.0/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw=
|
||||
@@ -52,80 +56,98 @@ github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J
|
||||
github.com/aws/smithy-go v1.14.1 h1:EFKMUmH/iHMqLiwoEDx2rRjRQpI1YCn5jTysoaDujFs=
|
||||
github.com/aws/smithy-go v1.14.1/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
|
||||
github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
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=
|
||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||
github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w=
|
||||
github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg=
|
||||
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
|
||||
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
|
||||
github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho=
|
||||
github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
|
||||
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.5.4/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/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/hashicorp/boundary/sdk v0.0.33 h1:kHaVZ3b9j1QvYlG+vhAgrbXh8/+Rq2qlUIs8fKMQH7k=
|
||||
github.com/hashicorp/boundary/sdk v0.0.33/go.mod h1:jn9j5mM8v2pOk8aLeJNIszdm7WBf4gRSP68iy8Iu5Q0=
|
||||
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
|
||||
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/hashicorp/boundary/sdk v0.0.41-0.20231117205527-08045ddb050e h1:PzZklmCjnaqQq9JdZRI9SVPSd9xo0iXLlmOHoQX68aM=
|
||||
github.com/hashicorp/boundary/sdk v0.0.41-0.20231117205527-08045ddb050e/go.mod h1:+XTDYf9YNeKIbGOPJwy7hlO2Le4zgzCtHCG/u+z4THI=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/eventlogger v0.1.2-0.20230428153751-cca445805f24 h1:vtCJgcxwDMFrpUgVMfjtwXY1YqvHbj8pNA7GsXYEoLg=
|
||||
github.com/hashicorp/eventlogger v0.1.2-0.20230428153751-cca445805f24/go.mod h1://CHt6/j+Q2lc0NlUB5af4aS2M0c0aVBg9/JfcpAyhM=
|
||||
github.com/hashicorp/eventlogger/filters/encrypt v0.1.8-0.20230428153751-cca445805f24 h1:mopKPTxSaVr24uSysyRwywTDs85L5b05qqZvEkWa0qc=
|
||||
github.com/hashicorp/eventlogger/filters/encrypt v0.1.8-0.20230428153751-cca445805f24/go.mod h1:EQPLoX6CONA9BSYUovTQBHfPGE91g7wOxv03sO29FzY=
|
||||
github.com/hashicorp/eventlogger v0.2.6-0.20231025104552-802587e608f0 h1:f9oX8/3zxiQrfrWnBeyjDm4S02GAU02OBtCRoZOUwlo=
|
||||
github.com/hashicorp/eventlogger v0.2.6-0.20231025104552-802587e608f0/go.mod h1://CHt6/j+Q2lc0NlUB5af4aS2M0c0aVBg9/JfcpAyhM=
|
||||
github.com/hashicorp/eventlogger/filters/encrypt v0.1.8-0.20231025104552-802587e608f0 h1:iAb287bq0TaWTnhDYuN/zVqdD2EwanQg9ncVelC60Xc=
|
||||
github.com/hashicorp/eventlogger/filters/encrypt v0.1.8-0.20231025104552-802587e608f0/go.mod h1:tMywUTIvdB/FXhwm6HMTt61C8/eODY6gitCHhXtyojg=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
|
||||
github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c=
|
||||
github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
|
||||
github.com/hashicorp/go-kms-wrapping/plugin/v2 v2.0.4 h1:8z+Zi0uLYXONkxwWb/D7O5t1IUucB6Ft3uvSOa950bM=
|
||||
github.com/hashicorp/go-kms-wrapping/v2 v2.0.9 h1:JpCvi97NMA+saNqO8ovQcGoRbBq6P5ZZlJqvOsW5ick=
|
||||
github.com/hashicorp/go-kms-wrapping/v2 v2.0.9/go.mod h1:NtMaPhqSlfQ72XWDD2g80o8HI8RKkowIB8/WZHMyPY4=
|
||||
github.com/hashicorp/go-kms-wrapping/plugin/v2 v2.0.5 h1:jrnDfQm2hCQ0/hEselgqzV4fK16gpZoY0OWGZpVPNHM=
|
||||
github.com/hashicorp/go-kms-wrapping/plugin/v2 v2.0.5/go.mod h1:psh1qKep5ukvuNobFY/hCybuudlkkACpmazOsCgX5Rg=
|
||||
github.com/hashicorp/go-kms-wrapping/v2 v2.0.14 h1:1ZuhfnZgRnLK8S0KovJkoTCRIQId5pv3sDR7pG5VQBw=
|
||||
github.com/hashicorp/go-kms-wrapping/v2 v2.0.14/go.mod h1:0dWtzl2ilqKpavgM3id/kFK9L3tjo6fS4OhbVPSYpnQ=
|
||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/hashicorp/go-plugin v1.4.9 h1:ESiK220/qE0aGxWdzKIvRH69iLiuN/PjoLTm69RoWtU=
|
||||
github.com/hashicorp/go-secure-stdlib/awsutilv2 v0.0.0-20230809054404-9029211590fd h1:46A3lfywoivyHBOXlXioGDSDo3UJj2aW2ncnSCSJ7bs=
|
||||
github.com/hashicorp/go-secure-stdlib/awsutilv2 v0.0.0-20230809054404-9029211590fd/go.mod h1:XnoCjGsUi+UKk0+0P5TIS2rGKdw7O9ehSJy+kIuffBY=
|
||||
github.com/hashicorp/go-plugin v1.5.2 h1:aWv8eimFqWlsEiMrYZdPYl+FdHaBJSN4AWwGWfT1G2Y=
|
||||
github.com/hashicorp/go-plugin v1.5.2/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4=
|
||||
github.com/hashicorp/go-secure-stdlib/awsutil/v2 v2.0.0 h1:ca5TSI4AgaOncPpyzLDtCGjVEtKukONpeM95vFxXCOQ=
|
||||
github.com/hashicorp/go-secure-stdlib/awsutil/v2 v2.0.0/go.mod h1:7CUvZtfTp2U0CYQCLzMtS2ngckjAZePSfwrE2aeDP1M=
|
||||
github.com/hashicorp/go-secure-stdlib/base62 v0.1.1/go.mod h1:EdWO6czbmthiwZ3/PUsDV+UD1D5IRU4ActiaWGwt0Yw=
|
||||
github.com/hashicorp/go-secure-stdlib/base62 v0.1.2 h1:ET4pqyjiGmY09R5y+rSd70J2w45CtbWDNvGqWp/R3Ng=
|
||||
github.com/hashicorp/go-secure-stdlib/configutil/v2 v2.0.9 h1:YZ01/aiARPneDUryzjiPGvr3pmjCSC+1WBZKI1P7I7k=
|
||||
github.com/hashicorp/go-secure-stdlib/listenerutil v0.1.6 h1:rOmnqOSUBn5opme1Kh9OXO8qWd0KztO+f02vvCwCc/w=
|
||||
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.7 h1:UpiO20jno/eV1eVZcxqWnUohyKRe1g8FPV/xH1s/2qs=
|
||||
github.com/hashicorp/go-secure-stdlib/pluginutil/v2 v2.0.4 h1:IU2iGcvthrJ53rPbQU6B4+iVs/cLPO89ti5dd2XEj3k=
|
||||
github.com/hashicorp/go-secure-stdlib/base62 v0.1.2/go.mod h1:EdWO6czbmthiwZ3/PUsDV+UD1D5IRU4ActiaWGwt0Yw=
|
||||
github.com/hashicorp/go-secure-stdlib/configutil/v2 v2.0.11 h1:uPW2Wn0YlmI9RGSkZpcIplnVRwJ7BCiGpk1vnF2TMw4=
|
||||
github.com/hashicorp/go-secure-stdlib/configutil/v2 v2.0.11/go.mod h1:uis9dCmOzXuOaRyXq+1Foh31kcvXKoWogjNnhfjHfW8=
|
||||
github.com/hashicorp/go-secure-stdlib/listenerutil v0.1.9 h1:0S0ctJ7Ra8O7ap+/3fZUnzJ3VzJyirWS/WnNCuOYtZY=
|
||||
github.com/hashicorp/go-secure-stdlib/listenerutil v0.1.9/go.mod h1:TNNdgtjLgVDbrgFcyCKrlAicIl3dZF94swJltyGUX2M=
|
||||
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.8 h1:iBt4Ew4XEGLfh6/bPk4rSYmuZJGizr6/x/AEizP0CQc=
|
||||
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.8/go.mod h1:aiJI+PIApBRQG7FZTEBx5GiiX+HbOHilUdNxUZi4eV0=
|
||||
github.com/hashicorp/go-secure-stdlib/pluginutil/v2 v2.0.6 h1:ZYv2XA+tEfFXIToR2jmBgVqQU9gERt0APbWqmUoNGnY=
|
||||
github.com/hashicorp/go-secure-stdlib/pluginutil/v2 v2.0.6/go.mod h1:ggFN8dlaLWS2R1gymBbCrvXM/bkZP7hEAa4seqDwhyg=
|
||||
github.com/hashicorp/go-secure-stdlib/reloadutil v0.1.1 h1:SMGUnbpAcat8rIKHkBPjfv81yC46a8eCNZ2hsR2l1EI=
|
||||
github.com/hashicorp/go-secure-stdlib/reloadutil v0.1.1/go.mod h1:Ch/bf00Qnx77MZd49JRgHYqHQjtEmTgGU2faufpVZb0=
|
||||
github.com/hashicorp/go-secure-stdlib/strutil v0.1.1/go.mod h1:gKOamz3EwoIoJq7mlMIRBpVTAUn8qPCrEclOKKWhD3U=
|
||||
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9CdjCtrXrXGuOpxEA7Ts=
|
||||
github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.2 h1:phcbL8urUzF/kxA/Oj6awENaRwfWsjP59GW7u2qlDyY=
|
||||
github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc=
|
||||
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4=
|
||||
github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.3 h1:xbrxd0U9XQW8qL1BAz2XrAjAF/P2vcqUTAues9c24B8=
|
||||
github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.3/go.mod h1:LWq2Sy8UoKKuK4lFuCNWSjJj57MhNNf2zzBWMtkAIX4=
|
||||
github.com/hashicorp/go-sockaddr v1.0.5 h1:dvk7TIXCZpmfOlM+9mlcrWmWjw/wlKT+VDq2wMvfPJU=
|
||||
github.com/hashicorp/go-sockaddr v1.0.5/go.mod h1:uoUUmtwU7n9Dv3O4SNLeFvg0SxQ3lyjsj6+CCykpaxI=
|
||||
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
|
||||
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-version v1.5.0 h1:O293SZ2Eg+AAYijkVK3jR786Am1bhDEh2GHT0tIVE5E=
|
||||
github.com/hashicorp/go-version v1.5.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hashicorp/terraform-json v0.14.0 h1:sh9iZ1Y8IFJLx+xQiKHGud6/TSUCM0N8e17dKDpqV7s=
|
||||
github.com/hashicorp/terraform-json v0.14.0/go.mod h1:5A9HIWPkk4e5aeeXIBbkcOvaZbIYnAIkEyqP2pNSckM=
|
||||
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
|
||||
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
|
||||
github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU=
|
||||
github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk=
|
||||
github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg=
|
||||
github.com/jefferai/isbadcipher v0.0.0-20190226160619-51d2077c035f h1:E87tDTVS5W65euzixn7clSzK66puSt1H4I5SC0EmHH4=
|
||||
github.com/jefferai/isbadcipher v0.0.0-20190226160619-51d2077c035f/go.mod h1:3J2qVK16Lq8V+wfiL2lPeDZ7UWMxk5LemerHa1p6N00=
|
||||
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/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
@@ -138,12 +160,14 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
|
||||
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mitchellh/cli v1.1.5 h1:OxRIeJXpAMztws/XHlN2vu6imG5Dpq+j61AzAX5fLng=
|
||||
github.com/mitchellh/cli v1.1.5/go.mod h1:v8+iFts2sPIKUV1ltktPXMCC8fumSKFItNcD2cLtRR4=
|
||||
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
|
||||
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
|
||||
github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU=
|
||||
github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8=
|
||||
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
@@ -152,17 +176,21 @@ github.com/mitchellh/pointerstructure v1.2.1/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8oh
|
||||
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
|
||||
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA=
|
||||
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo=
|
||||
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
|
||||
github.com/rogpeppe/go-internal v1.6.2 h1:aIihoIOHCiLZHxyoNQ+ABL4NKhFTgKLBdMLyEAh98m0=
|
||||
github.com/rogpeppe/go-internal v1.6.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=
|
||||
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
|
||||
github.com/sebdah/goldie v1.0.0/go.mod h1:jXP4hmWywNEwZzhMuv2ccnqTSFpuq8iyQhtQdkkZBH4=
|
||||
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
|
||||
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
|
||||
github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
@@ -178,16 +206,16 @@ github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q
|
||||
github.com/zclconf/go-cty v1.10.0 h1:mp9ZXQeIcN8kAwuqorjH+Q+njbJKjLrvB2yIh4q7U+0=
|
||||
github.com/zclconf/go-cty v1.10.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk=
|
||||
github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8=
|
||||
go.uber.org/goleak v1.0.0 h1:qsup4IcBdlmsnGfqyLl4Ntn3C2XCCuKAE7DwHpScyUo=
|
||||
go.uber.org/goleak v1.0.0/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
||||
go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA=
|
||||
go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ=
|
||||
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
|
||||
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
|
||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
@@ -199,8 +227,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
|
||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -215,41 +243,42 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
|
||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20210101214203-2dba1e4ea05c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488 h1:QQF+HdiI4iocoxUjjpLgvTYDHKm99C/VtTBFnfiCJos=
|
||||
google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488/go.mod h1:TvhZT5f700eVlTNwND1xoEZQeWTB2RY/65kplwl/bFA=
|
||||
google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc=
|
||||
google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b h1:ZlWIi1wSK56/8hn4QcBp/j9M7Gt3U/3hZw3mC7vDICo=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:swOH3j0KzcDDgGUWr+SNpyTen5YrXjS3eyPzFYKc6lc=
|
||||
google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk=
|
||||
google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"github.com/aws/aws-sdk-go/aws/endpoints"
|
||||
"github.com/hashicorp/boundary-plugin-aws/internal/errors"
|
||||
"github.com/hashicorp/boundary-plugin-aws/internal/values"
|
||||
awsutilv2 "github.com/hashicorp/go-secure-stdlib/awsutil"
|
||||
"github.com/hashicorp/go-secure-stdlib/awsutil/v2"
|
||||
"google.golang.org/protobuf/types/known/structpb"
|
||||
)
|
||||
|
||||
@@ -37,7 +37,7 @@ type CredentialAttributes struct {
|
||||
// GetCredentialsConfig parses values out of a protobuf struct secrets and returns a
|
||||
// CredentialsConfig used for configuring an AWS session. An error is returned if
|
||||
// any unrecognized fields are found in the protobuf struct input.
|
||||
func GetCredentialsConfig(secrets *structpb.Struct, attrs *CredentialAttributes, required bool) (*awsutilv2.CredentialsConfig, error) {
|
||||
func GetCredentialsConfig(secrets *structpb.Struct, attrs *CredentialAttributes, required bool) (*awsutil.CredentialsConfig, error) {
|
||||
// initialize secrets if it is nil
|
||||
// secrets can be nil because static credentials are optional
|
||||
if secrets == nil {
|
||||
@@ -55,10 +55,6 @@ func GetCredentialsConfig(secrets *structpb.Struct, attrs *CredentialAttributes,
|
||||
}
|
||||
delete(unknownFields, ConstAccessKeyId)
|
||||
|
||||
if accessKey != "" && GetCredentialType(accessKey) != Static {
|
||||
badFields[fmt.Sprintf("secrets.%s", ConstAccessKeyId)] = "requires long-term access key beginning with \"AKIA\" prefix"
|
||||
}
|
||||
|
||||
secretKey, err := values.GetStringValue(secrets, ConstSecretAccessKey, required)
|
||||
if err != nil {
|
||||
badFields[fmt.Sprintf("secrets.%s", ConstSecretAccessKey)] = err.Error()
|
||||
@@ -72,7 +68,7 @@ func GetCredentialsConfig(secrets *structpb.Struct, attrs *CredentialAttributes,
|
||||
badFields[fmt.Sprintf("secrets.%s", s)] = "unrecognized field"
|
||||
}
|
||||
|
||||
opts := []awsutilv2.Option{}
|
||||
opts := []awsutil.Option{}
|
||||
// logic for parsing the credential type
|
||||
// supported types:
|
||||
// - user static credential
|
||||
@@ -83,22 +79,25 @@ func GetCredentialsConfig(secrets *structpb.Struct, attrs *CredentialAttributes,
|
||||
case accessKey != "" && secretKey != "" && attrs.RoleArn != "":
|
||||
badFields[fmt.Sprintf("secrets.%s", ConstAccessKeyId)] = "conflicts with role_arn value"
|
||||
badFields[fmt.Sprintf("secrets.%s", ConstSecretAccessKey)] = "conflicts with role_arn value"
|
||||
badFields[fmt.Sprintf("secrets.%s", ConstRoleArn)] = "conflicts with access_key_id and secret_access_key values"
|
||||
badFields[fmt.Sprintf("attributes.%s", ConstRoleArn)] = "conflicts with access_key_id and secret_access_key values"
|
||||
// static credential is missing it's secret_access_key
|
||||
case accessKey != "" && secretKey == "":
|
||||
badFields[fmt.Sprintf("secrets.%s", ConstSecretAccessKey)] = "missing required value"
|
||||
// static credential is missing it's access_key_id
|
||||
case accessKey == "" && secretKey != "":
|
||||
badFields[fmt.Sprintf("secrets.%s", ConstAccessKeyId)] = "missing required value"
|
||||
// dynamic credentials and credential rotation is not supported
|
||||
case len(attrs.RoleArn) > 0 && !attrs.DisableCredentialRotation:
|
||||
badFields[fmt.Sprintf("attributes.%s", ConstDisableCredentialRotation)] = "disable_credential_rotation attribute is required when providing a role_arn"
|
||||
// add static credentials
|
||||
case accessKey != "" && secretKey != "":
|
||||
opts = append(opts,
|
||||
awsutilv2.WithAccessKey(accessKey),
|
||||
awsutilv2.WithSecretKey(secretKey),
|
||||
awsutil.WithAccessKey(accessKey),
|
||||
awsutil.WithSecretKey(secretKey),
|
||||
)
|
||||
// add dynamic credentials
|
||||
case attrs.RoleArn != "":
|
||||
opts = append(opts, awsutilv2.WithRoleArn(attrs.RoleArn))
|
||||
opts = append(opts, awsutil.WithRoleArn(attrs.RoleArn))
|
||||
}
|
||||
|
||||
if len(badFields) > 0 {
|
||||
@@ -106,19 +105,19 @@ func GetCredentialsConfig(secrets *structpb.Struct, attrs *CredentialAttributes,
|
||||
}
|
||||
|
||||
if attrs.Region != "" {
|
||||
opts = append(opts, awsutilv2.WithRegion(attrs.Region))
|
||||
opts = append(opts, awsutil.WithRegion(attrs.Region))
|
||||
}
|
||||
if attrs.RoleExternalId != "" {
|
||||
opts = append(opts, awsutilv2.WithRoleExternalId(attrs.RoleExternalId))
|
||||
opts = append(opts, awsutil.WithRoleExternalId(attrs.RoleExternalId))
|
||||
}
|
||||
if attrs.RoleSessionName != "" {
|
||||
opts = append(opts, awsutilv2.WithRoleSessionName(attrs.RoleSessionName))
|
||||
opts = append(opts, awsutil.WithRoleSessionName(attrs.RoleSessionName))
|
||||
}
|
||||
if len(attrs.RoleTags) != 0 {
|
||||
opts = append(opts, awsutilv2.WithRoleTags(attrs.RoleTags))
|
||||
opts = append(opts, awsutil.WithRoleTags(attrs.RoleTags))
|
||||
}
|
||||
|
||||
return awsutilv2.NewCredentialsConfig(opts...)
|
||||
return awsutil.NewCredentialsConfig(opts...)
|
||||
}
|
||||
|
||||
// GetCredentialAttributes parses values out of a protobuf struct input and returns a
|
||||
|
||||
@@ -6,7 +6,7 @@ package credential
|
||||
import (
|
||||
"testing"
|
||||
|
||||
awsutilv2 "github.com/hashicorp/go-secure-stdlib/awsutil"
|
||||
"github.com/hashicorp/go-secure-stdlib/awsutil/v2"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
@@ -114,7 +114,7 @@ func TestGetCredentialsConfig(t *testing.T) {
|
||||
secrets *structpb.Struct
|
||||
required bool
|
||||
attrs *CredentialAttributes
|
||||
expected *awsutilv2.CredentialsConfig
|
||||
expected *awsutil.CredentialsConfig
|
||||
expectedErrContains string
|
||||
}{
|
||||
{
|
||||
@@ -122,23 +122,10 @@ func TestGetCredentialsConfig(t *testing.T) {
|
||||
attrs: &CredentialAttributes{
|
||||
Region: "us-west-2",
|
||||
},
|
||||
expected: &awsutilv2.CredentialsConfig{
|
||||
expected: &awsutil.CredentialsConfig{
|
||||
Region: "us-west-2",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "with invalid static credentials",
|
||||
secrets: &structpb.Struct{
|
||||
Fields: map[string]*structpb.Value{
|
||||
ConstAccessKeyId: structpb.NewStringValue("ASIAfoobar"),
|
||||
ConstSecretAccessKey: structpb.NewStringValue("bazqux"),
|
||||
},
|
||||
},
|
||||
attrs: &CredentialAttributes{
|
||||
Region: "us-west-2",
|
||||
},
|
||||
expectedErrContains: `secrets.access_key_id: requires long-term access key beginning with "AKIA" prefix`,
|
||||
},
|
||||
{
|
||||
name: "with static credentials",
|
||||
secrets: &structpb.Struct{
|
||||
@@ -150,7 +137,7 @@ func TestGetCredentialsConfig(t *testing.T) {
|
||||
attrs: &CredentialAttributes{
|
||||
Region: "us-west-2",
|
||||
},
|
||||
expected: &awsutilv2.CredentialsConfig{
|
||||
expected: &awsutil.CredentialsConfig{
|
||||
AccessKey: "AKIAfoobar",
|
||||
SecretKey: "bazqux",
|
||||
Region: "us-west-2",
|
||||
@@ -209,7 +196,7 @@ func TestGetCredentialsConfig(t *testing.T) {
|
||||
attrs: &CredentialAttributes{
|
||||
Region: "us-west-2",
|
||||
},
|
||||
expected: &awsutilv2.CredentialsConfig{
|
||||
expected: &awsutil.CredentialsConfig{
|
||||
AccessKey: "AKIAfoobar",
|
||||
SecretKey: "bazqux",
|
||||
Region: "us-west-2",
|
||||
@@ -228,8 +215,9 @@ func TestGetCredentialsConfig(t *testing.T) {
|
||||
RoleTags: map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
DisableCredentialRotation: true,
|
||||
},
|
||||
expected: &awsutilv2.CredentialsConfig{
|
||||
expected: &awsutil.CredentialsConfig{
|
||||
Region: "us-west-2",
|
||||
RoleARN: "arn:aws:iam::123456789012:role/S3Access",
|
||||
RoleExternalId: "1234567890",
|
||||
@@ -256,7 +244,21 @@ func TestGetCredentialsConfig(t *testing.T) {
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
expectedErrContains: "secrets.access_key_id: conflicts with role_arn value, secrets.role_arn: conflicts with access_key_id and secret_access_key values, secrets.secret_access_key: conflicts with role_arn value",
|
||||
expectedErrContains: "attributes.role_arn: conflicts with access_key_id and secret_access_key values, secrets.access_key_id: conflicts with role_arn value, secrets.secret_access_key: conflicts with role_arn value",
|
||||
},
|
||||
{
|
||||
name: "with dynamic credentials and no disable credential rotation",
|
||||
secrets: &structpb.Struct{Fields: map[string]*structpb.Value{}},
|
||||
attrs: &CredentialAttributes{
|
||||
Region: "us-west-2",
|
||||
RoleArn: "arn:aws:iam::123456789012:role/S3Access",
|
||||
RoleExternalId: "1234567890",
|
||||
RoleSessionName: "test-session",
|
||||
RoleTags: map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
expectedErrContains: "attributes.disable_credential_rotation: disable_credential_rotation attribute is required when providing a role_arn",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -13,16 +13,30 @@ import (
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
iamTypes "github.com/aws/aws-sdk-go-v2/service/iam/types"
|
||||
"github.com/hashicorp/boundary-plugin-aws/internal/values"
|
||||
awsutilv2 "github.com/hashicorp/go-secure-stdlib/awsutil"
|
||||
"github.com/hashicorp/go-secure-stdlib/awsutil/v2"
|
||||
"google.golang.org/protobuf/types/known/structpb"
|
||||
)
|
||||
|
||||
type CredentialType int
|
||||
|
||||
const (
|
||||
Unknown CredentialType = iota
|
||||
Static
|
||||
Dynamic
|
||||
// StaticAWS denotes an Access Key Id that begins with "AKIA". These are
|
||||
// long-term access keys, provided by AWS, for an IAM user or an AWS account
|
||||
// root user.
|
||||
// https://docs.aws.amazon.com/IAM/latest/UserGuide/security-creds.html#sec-access-keys-and-secret-access-keys
|
||||
StaticAWS CredentialType = iota
|
||||
|
||||
// DynamicAWS denotes the presence of a RoleARN, or an Access Key Id that
|
||||
// begins with "ASIA". The latter are temporary credentials access keys that
|
||||
// are created using AWS STS operations.
|
||||
DynamicAWS
|
||||
|
||||
// StaticOther denotes the presence of an Access Key Id that does not follow
|
||||
// the AKIA/ASIA convention outlined by AWS.
|
||||
StaticOther
|
||||
|
||||
// Unknown is a catch-all for everything else.
|
||||
Unknown
|
||||
)
|
||||
|
||||
// rotationWaitTimeout controls the time we wait for credential rotation to
|
||||
@@ -35,18 +49,18 @@ type AwsCredentialPersistedStateOption func(s *AwsCredentialPersistedState) erro
|
||||
// AwsCredentialPersistedState is the persisted state for the AWS credential.
|
||||
type AwsCredentialPersistedState struct {
|
||||
// CredentialsConfig is the credential configuration for the AWS credential.
|
||||
CredentialsConfig *awsutilv2.CredentialsConfig
|
||||
CredentialsConfig *awsutil.CredentialsConfig
|
||||
// CredsLastRotatedTime is the last rotation of aws secrets for the AWS credential.
|
||||
CredsLastRotatedTime time.Time
|
||||
|
||||
// testOpts are options that should be used for testing only
|
||||
testOpts []awsutilv2.Option
|
||||
testOpts []awsutil.Option
|
||||
}
|
||||
|
||||
// WithStateTestOpts enables unit testing different edge cases
|
||||
// when using CredentialsConfig. This should never be used in
|
||||
// production code. This should only be used in unit tests.
|
||||
func WithStateTestOpts(opts []awsutilv2.Option) AwsCredentialPersistedStateOption {
|
||||
func WithStateTestOpts(opts []awsutil.Option) AwsCredentialPersistedStateOption {
|
||||
return func(s *AwsCredentialPersistedState) error {
|
||||
s.testOpts = opts
|
||||
return nil
|
||||
@@ -54,7 +68,7 @@ func WithStateTestOpts(opts []awsutilv2.Option) AwsCredentialPersistedStateOptio
|
||||
}
|
||||
|
||||
// WithCredentialsConfig sets the value for CredentialsConfig in the credential persisted state.
|
||||
func WithCredentialsConfig(x *awsutilv2.CredentialsConfig) AwsCredentialPersistedStateOption {
|
||||
func WithCredentialsConfig(x *awsutil.CredentialsConfig) AwsCredentialPersistedStateOption {
|
||||
return func(s *AwsCredentialPersistedState) error {
|
||||
if s.CredentialsConfig != nil {
|
||||
return errors.New("credentials config already set")
|
||||
@@ -112,11 +126,11 @@ func (s *AwsCredentialPersistedState) RotateCreds(ctx context.Context) error {
|
||||
if s.CredentialsConfig == nil {
|
||||
return errors.New("missing credentials config")
|
||||
}
|
||||
if GetCredentialType(s.CredentialsConfig.AccessKey) != Static {
|
||||
if GetCredentialType(s.CredentialsConfig) != StaticAWS {
|
||||
return errors.New("invalid credential type")
|
||||
}
|
||||
if err := s.CredentialsConfig.RotateKeys(ctx, append([]awsutilv2.Option{
|
||||
awsutilv2.WithValidityCheckTimeout(rotationWaitTimeout),
|
||||
if err := s.CredentialsConfig.RotateKeys(ctx, append([]awsutil.Option{
|
||||
awsutil.WithValidityCheckTimeout(rotationWaitTimeout),
|
||||
}, s.testOpts...)...); err != nil {
|
||||
return fmt.Errorf("error rotating credentials: %w", err)
|
||||
}
|
||||
@@ -127,20 +141,18 @@ func (s *AwsCredentialPersistedState) RotateCreds(ctx context.Context) error {
|
||||
// ReplaceCreds replaces the access key in the state with a new key.
|
||||
// If the existing key was rotated at any point in time, it is
|
||||
// deleted first, otherwise it's left alone.
|
||||
func (s *AwsCredentialPersistedState) ReplaceCreds(ctx context.Context, credentialsConfig *awsutilv2.CredentialsConfig) error {
|
||||
func (s *AwsCredentialPersistedState) ReplaceCreds(ctx context.Context, credentialsConfig *awsutil.CredentialsConfig) error {
|
||||
if credentialsConfig == nil {
|
||||
return errors.New("missing new credentials config")
|
||||
}
|
||||
if s.CredentialsConfig == nil {
|
||||
return errors.New("missing credentials config")
|
||||
}
|
||||
if GetCredentialType(s.CredentialsConfig.AccessKey) != Static {
|
||||
return errors.New("invalid credential type")
|
||||
}
|
||||
|
||||
// Delete old/existing credentials. This action is only possible for static credential types.
|
||||
// This is done with the same credentials to ensure that it has the proper permissions to do it.
|
||||
if !s.CredsLastRotatedTime.IsZero() {
|
||||
ct := GetCredentialType(s.CredentialsConfig)
|
||||
if !s.CredsLastRotatedTime.IsZero() && ct == StaticAWS {
|
||||
if err := s.DeleteCreds(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -159,7 +171,7 @@ func (s *AwsCredentialPersistedState) DeleteCreds(ctx context.Context) error {
|
||||
if s.CredentialsConfig == nil {
|
||||
return errors.New("missing credentials config")
|
||||
}
|
||||
if GetCredentialType(s.CredentialsConfig.AccessKey) != Static {
|
||||
if GetCredentialType(s.CredentialsConfig) != StaticAWS {
|
||||
return errors.New("invalid credential type")
|
||||
}
|
||||
|
||||
@@ -184,7 +196,13 @@ func (s *AwsCredentialPersistedState) DeleteCreds(ctx context.Context) error {
|
||||
|
||||
// GenerateCredentialChain returns a AWS configuration for the credentials in the state.
|
||||
func (s *AwsCredentialPersistedState) GenerateCredentialChain(ctx context.Context) (*aws.Config, error) {
|
||||
return s.CredentialsConfig.GenerateCredentialChain(ctx, s.testOpts...)
|
||||
// Default `WithSharedCredentials` is `true` - This disables the ability to
|
||||
// read credentials from environment variables because we set the default
|
||||
// profile options, so we need to set it to false (see
|
||||
// awsutil@v2.(*CredentialsConfig).generateAwsConfigOptions) for extra
|
||||
// details.
|
||||
opts := append(s.testOpts, awsutil.WithSharedCredentials(false))
|
||||
return s.CredentialsConfig.GenerateCredentialChain(ctx, opts...)
|
||||
}
|
||||
|
||||
// ToMap returns a map of the credentials stored in the persisted state.
|
||||
@@ -192,7 +210,15 @@ func (s *AwsCredentialPersistedState) GenerateCredentialChain(ctx context.Contex
|
||||
// return a map for long-term credentials with following keys:
|
||||
// access_key_id, secret_access_key & creds_last_rotated_time
|
||||
func (s *AwsCredentialPersistedState) ToMap() map[string]any {
|
||||
if HasDynamicCredentials(s.CredentialsConfig.AccessKey) {
|
||||
ct := GetCredentialType(s.CredentialsConfig)
|
||||
// Dynamic AWS credentials are temporary credentials that expire within an hour.
|
||||
// ToMap() returns an empty map here so that Boundary does not store temporary
|
||||
// credentials into the database.
|
||||
//
|
||||
// Uknown credentials are not aws compatiable secrets that may have been provided
|
||||
// for a non-aws s3 compatiable service. These credentials will not be returned
|
||||
// because the plugin does not know how to manage non-aws credentials.
|
||||
if ct == DynamicAWS || ct == Unknown {
|
||||
return map[string]any{}
|
||||
}
|
||||
return map[string]any{
|
||||
@@ -237,29 +263,29 @@ func AwsCredentialPersistedStateFromProto(secrets *structpb.Struct, attrs *Crede
|
||||
return nil, err
|
||||
}
|
||||
|
||||
awsOpts := append([]awsutilv2.Option{}, s.testOpts...)
|
||||
awsOpts := append([]awsutil.Option{}, s.testOpts...)
|
||||
if accessKeyId != "" && secretAccessKey != "" {
|
||||
awsOpts = append(awsOpts,
|
||||
awsutilv2.WithAccessKey(accessKeyId),
|
||||
awsutilv2.WithSecretKey(secretAccessKey),
|
||||
awsutil.WithAccessKey(accessKeyId),
|
||||
awsutil.WithSecretKey(secretAccessKey),
|
||||
)
|
||||
}
|
||||
if attrs.Region != "" {
|
||||
awsOpts = append(awsOpts, awsutilv2.WithRegion(attrs.Region))
|
||||
awsOpts = append(awsOpts, awsutil.WithRegion(attrs.Region))
|
||||
}
|
||||
if attrs.RoleArn != "" {
|
||||
awsOpts = append(awsOpts, awsutilv2.WithRoleArn(attrs.RoleArn))
|
||||
awsOpts = append(awsOpts, awsutil.WithRoleArn(attrs.RoleArn))
|
||||
}
|
||||
if attrs.RoleExternalId != "" {
|
||||
awsOpts = append(awsOpts, awsutilv2.WithRoleExternalId(attrs.RoleExternalId))
|
||||
awsOpts = append(awsOpts, awsutil.WithRoleExternalId(attrs.RoleExternalId))
|
||||
}
|
||||
if attrs.RoleSessionName != "" {
|
||||
awsOpts = append(awsOpts, awsutilv2.WithRoleSessionName(attrs.RoleSessionName))
|
||||
awsOpts = append(awsOpts, awsutil.WithRoleSessionName(attrs.RoleSessionName))
|
||||
}
|
||||
if len(attrs.RoleTags) != 0 {
|
||||
awsOpts = append(awsOpts, awsutilv2.WithRoleTags(attrs.RoleTags))
|
||||
awsOpts = append(awsOpts, awsutil.WithRoleTags(attrs.RoleTags))
|
||||
}
|
||||
credentialsConfig, err := awsutilv2.NewCredentialsConfig(awsOpts...)
|
||||
credentialsConfig, err := awsutil.NewCredentialsConfig(awsOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -269,29 +295,22 @@ func AwsCredentialPersistedStateFromProto(secrets *structpb.Struct, attrs *Crede
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// GetCredentialType returns the credential type based on the given AWS AccessKey.
|
||||
//
|
||||
// https://docs.aws.amazon.com/IAM/latest/UserGuide/security-creds.html#sec-access-keys-and-secret-access-keys
|
||||
// Access key IDs beginning with ASIA are temporary credentials access keys that you create using AWS STS operations.
|
||||
//
|
||||
// https://docs.aws.amazon.com/IAM/latest/UserGuide/security-creds.html#sec-access-keys-and-secret-access-keys
|
||||
// Access key IDs beginning with AKIA are long-term access keys for an IAM user or an AWS account root user.
|
||||
func GetCredentialType(accessKey string) CredentialType {
|
||||
if strings.HasPrefix(accessKey, "ASIA") {
|
||||
return Dynamic
|
||||
// GetCredentialType returns the credential type based on the given
|
||||
// AccessKey/RoleARN. See CredentialType definition for more information.
|
||||
func GetCredentialType(cc *awsutil.CredentialsConfig) CredentialType {
|
||||
if cc == nil {
|
||||
return Unknown
|
||||
}
|
||||
if strings.HasPrefix(accessKey, "AKIA") {
|
||||
return Static
|
||||
|
||||
if len(cc.RoleARN) > 0 || strings.HasPrefix(cc.AccessKey, "ASIA") {
|
||||
return DynamicAWS
|
||||
}
|
||||
if strings.HasPrefix(cc.AccessKey, "AKIA") {
|
||||
return StaticAWS
|
||||
}
|
||||
if len(cc.AccessKey) > 0 {
|
||||
return StaticOther
|
||||
}
|
||||
|
||||
return Unknown
|
||||
}
|
||||
|
||||
// HasDynamicCredentials returns true if the access key is a dynamic credential type.
|
||||
func HasDynamicCredentials(accessKey string) bool {
|
||||
return strings.HasPrefix(accessKey, "ASIA")
|
||||
}
|
||||
|
||||
// HasStaticCredentials returns true if the access key is a static credential type.
|
||||
func HasStaticCredentials(accessKey string) bool {
|
||||
return strings.HasPrefix(accessKey, "AKIA")
|
||||
}
|
||||
+123
-168
@@ -13,7 +13,7 @@ import (
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/service/iam"
|
||||
iamTypes "github.com/aws/aws-sdk-go-v2/service/iam/types"
|
||||
awsutilv2 "github.com/hashicorp/go-secure-stdlib/awsutil"
|
||||
"github.com/hashicorp/go-secure-stdlib/awsutil/v2"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/protobuf/types/known/structpb"
|
||||
)
|
||||
@@ -40,7 +40,7 @@ func TestNewAwsCredentialPersistedState(t *testing.T) {
|
||||
name: "with credentials config",
|
||||
opts: []AwsCredentialPersistedStateOption{
|
||||
WithCredentialsConfig(
|
||||
&awsutilv2.CredentialsConfig{
|
||||
&awsutil.CredentialsConfig{
|
||||
AccessKey: "foobar",
|
||||
SecretKey: "bazqux",
|
||||
Region: "us-west-2",
|
||||
@@ -48,7 +48,7 @@ func TestNewAwsCredentialPersistedState(t *testing.T) {
|
||||
),
|
||||
},
|
||||
expected: &AwsCredentialPersistedState{
|
||||
CredentialsConfig: &awsutilv2.CredentialsConfig{
|
||||
CredentialsConfig: &awsutil.CredentialsConfig{
|
||||
AccessKey: "foobar",
|
||||
SecretKey: "bazqux",
|
||||
Region: "us-west-2",
|
||||
@@ -67,8 +67,8 @@ func TestNewAwsCredentialPersistedState(t *testing.T) {
|
||||
{
|
||||
name: "double set credentials config",
|
||||
opts: []AwsCredentialPersistedStateOption{
|
||||
WithCredentialsConfig(&awsutilv2.CredentialsConfig{}),
|
||||
WithCredentialsConfig(&awsutilv2.CredentialsConfig{}),
|
||||
WithCredentialsConfig(&awsutil.CredentialsConfig{}),
|
||||
WithCredentialsConfig(&awsutil.CredentialsConfig{}),
|
||||
},
|
||||
expectedErr: "credentials config already set",
|
||||
},
|
||||
@@ -123,7 +123,7 @@ func TestAwsCredentialPersistedStateFromProto(t *testing.T) {
|
||||
Region: "us-west-2",
|
||||
},
|
||||
expected: &AwsCredentialPersistedState{
|
||||
CredentialsConfig: &awsutilv2.CredentialsConfig{
|
||||
CredentialsConfig: &awsutil.CredentialsConfig{
|
||||
Region: "us-west-2",
|
||||
},
|
||||
},
|
||||
@@ -135,7 +135,7 @@ func TestAwsCredentialPersistedStateFromProto(t *testing.T) {
|
||||
Region: "us-west-2",
|
||||
},
|
||||
expected: &AwsCredentialPersistedState{
|
||||
CredentialsConfig: &awsutilv2.CredentialsConfig{
|
||||
CredentialsConfig: &awsutil.CredentialsConfig{
|
||||
Region: "us-west-2",
|
||||
},
|
||||
},
|
||||
@@ -147,7 +147,7 @@ func TestAwsCredentialPersistedStateFromProto(t *testing.T) {
|
||||
Region: "us-west-2",
|
||||
},
|
||||
expected: &AwsCredentialPersistedState{
|
||||
CredentialsConfig: &awsutilv2.CredentialsConfig{
|
||||
CredentialsConfig: &awsutil.CredentialsConfig{
|
||||
Region: "us-west-2",
|
||||
},
|
||||
},
|
||||
@@ -164,7 +164,7 @@ func TestAwsCredentialPersistedStateFromProto(t *testing.T) {
|
||||
Region: "us-west-2",
|
||||
},
|
||||
expected: &AwsCredentialPersistedState{
|
||||
CredentialsConfig: &awsutilv2.CredentialsConfig{
|
||||
CredentialsConfig: &awsutil.CredentialsConfig{
|
||||
Region: "us-west-2",
|
||||
AccessKey: "foobar",
|
||||
SecretKey: "bazqux",
|
||||
@@ -217,7 +217,7 @@ func TestAwsCredentialPersistedStateFromProto(t *testing.T) {
|
||||
Region: "us-west-2",
|
||||
},
|
||||
expected: &AwsCredentialPersistedState{
|
||||
CredentialsConfig: &awsutilv2.CredentialsConfig{
|
||||
CredentialsConfig: &awsutil.CredentialsConfig{
|
||||
AccessKey: "foobar",
|
||||
SecretKey: "bazqux",
|
||||
Region: "us-west-2",
|
||||
@@ -244,7 +244,7 @@ func TestAwsCredentialPersistedStateFromProto(t *testing.T) {
|
||||
Region: "us-west-2",
|
||||
},
|
||||
expected: &AwsCredentialPersistedState{
|
||||
CredentialsConfig: &awsutilv2.CredentialsConfig{
|
||||
CredentialsConfig: &awsutil.CredentialsConfig{
|
||||
AccessKey: "foobar",
|
||||
SecretKey: "bazqux",
|
||||
Region: "us-west-2",
|
||||
@@ -264,7 +264,7 @@ func TestAwsCredentialPersistedStateFromProto(t *testing.T) {
|
||||
},
|
||||
},
|
||||
expected: &AwsCredentialPersistedState{
|
||||
CredentialsConfig: &awsutilv2.CredentialsConfig{
|
||||
CredentialsConfig: &awsutil.CredentialsConfig{
|
||||
Region: "us-west-2",
|
||||
RoleARN: "arn:aws:iam::123456789012:role/S3Access",
|
||||
RoleExternalId: "1234567890",
|
||||
@@ -294,7 +294,7 @@ func TestAwsCredentialPersistedStateFromProto(t *testing.T) {
|
||||
},
|
||||
},
|
||||
expected: &AwsCredentialPersistedState{
|
||||
CredentialsConfig: &awsutilv2.CredentialsConfig{
|
||||
CredentialsConfig: &awsutil.CredentialsConfig{
|
||||
AccessKey: "foobar",
|
||||
SecretKey: "bazqux",
|
||||
Region: "us-west-2",
|
||||
@@ -352,15 +352,15 @@ func TestAwsCatalogPersistedState_ValidateCreds(t *testing.T) {
|
||||
{
|
||||
name: "validation error",
|
||||
in: &AwsCredentialPersistedState{
|
||||
CredentialsConfig: &awsutilv2.CredentialsConfig{
|
||||
CredentialsConfig: &awsutil.CredentialsConfig{
|
||||
AccessKey: "foobar",
|
||||
SecretKey: "bazqux",
|
||||
Region: "us-west-2",
|
||||
},
|
||||
testOpts: []awsutilv2.Option{
|
||||
awsutilv2.WithSTSAPIFunc(
|
||||
awsutilv2.NewMockSTS(
|
||||
awsutilv2.WithGetCallerIdentityError(errors.New(testGetCallerIdentityErr)),
|
||||
testOpts: []awsutil.Option{
|
||||
awsutil.WithSTSAPIFunc(
|
||||
awsutil.NewMockSTS(
|
||||
awsutil.WithGetCallerIdentityError(errors.New(testGetCallerIdentityErr)),
|
||||
),
|
||||
),
|
||||
},
|
||||
@@ -370,12 +370,12 @@ func TestAwsCatalogPersistedState_ValidateCreds(t *testing.T) {
|
||||
{
|
||||
name: "good",
|
||||
in: &AwsCredentialPersistedState{
|
||||
CredentialsConfig: &awsutilv2.CredentialsConfig{
|
||||
CredentialsConfig: &awsutil.CredentialsConfig{
|
||||
AccessKey: "foobar",
|
||||
SecretKey: "bazqux",
|
||||
Region: "us-west-2",
|
||||
},
|
||||
testOpts: []awsutilv2.Option{awsutilv2.WithSTSAPIFunc(awsutilv2.NewMockSTS())},
|
||||
testOpts: []awsutil.Option{awsutil.WithSTSAPIFunc(awsutil.NewMockSTS())},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -399,7 +399,7 @@ func TestAwsCatalogPersistedState_RotateCreds(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
in *AwsCredentialPersistedState
|
||||
exepected *awsutilv2.CredentialsConfig
|
||||
exepected *awsutil.CredentialsConfig
|
||||
expectedNonZeroRotatedTime bool
|
||||
expectedErr string
|
||||
}{
|
||||
@@ -411,7 +411,7 @@ func TestAwsCatalogPersistedState_RotateCreds(t *testing.T) {
|
||||
{
|
||||
name: "cannot delete dynamic credential type",
|
||||
in: &AwsCredentialPersistedState{
|
||||
CredentialsConfig: &awsutilv2.CredentialsConfig{
|
||||
CredentialsConfig: &awsutil.CredentialsConfig{
|
||||
AccessKey: "ASIAfoobar",
|
||||
SecretKey: "bazqux",
|
||||
},
|
||||
@@ -422,7 +422,7 @@ func TestAwsCatalogPersistedState_RotateCreds(t *testing.T) {
|
||||
{
|
||||
name: "cannot delete unknown credential type",
|
||||
in: &AwsCredentialPersistedState{
|
||||
CredentialsConfig: &awsutilv2.CredentialsConfig{
|
||||
CredentialsConfig: &awsutil.CredentialsConfig{
|
||||
AccessKey: "DNEfoobar",
|
||||
SecretKey: "bazqux",
|
||||
},
|
||||
@@ -433,15 +433,15 @@ func TestAwsCatalogPersistedState_RotateCreds(t *testing.T) {
|
||||
{
|
||||
name: "rotation error",
|
||||
in: &AwsCredentialPersistedState{
|
||||
CredentialsConfig: &awsutilv2.CredentialsConfig{
|
||||
CredentialsConfig: &awsutil.CredentialsConfig{
|
||||
AccessKey: "AKIAfoobar",
|
||||
SecretKey: "bazqux",
|
||||
Region: "us-west-2",
|
||||
},
|
||||
testOpts: []awsutilv2.Option{
|
||||
awsutilv2.WithIAMAPIFunc(
|
||||
awsutilv2.NewMockIAM(
|
||||
awsutilv2.WithGetUserError(errors.New(testGetUserErr)),
|
||||
testOpts: []awsutil.Option{
|
||||
awsutil.WithIAMAPIFunc(
|
||||
awsutil.NewMockIAM(
|
||||
awsutil.WithGetUserError(errors.New(testGetUserErr)),
|
||||
),
|
||||
),
|
||||
},
|
||||
@@ -451,18 +451,18 @@ func TestAwsCatalogPersistedState_RotateCreds(t *testing.T) {
|
||||
{
|
||||
name: "good",
|
||||
in: &AwsCredentialPersistedState{
|
||||
CredentialsConfig: &awsutilv2.CredentialsConfig{
|
||||
CredentialsConfig: &awsutil.CredentialsConfig{
|
||||
AccessKey: "AKIAfoobar",
|
||||
SecretKey: "bazqux",
|
||||
Region: "us-west-2",
|
||||
},
|
||||
testOpts: []awsutilv2.Option{
|
||||
awsutilv2.WithSTSAPIFunc(
|
||||
awsutilv2.NewMockSTS(),
|
||||
testOpts: []awsutil.Option{
|
||||
awsutil.WithSTSAPIFunc(
|
||||
awsutil.NewMockSTS(),
|
||||
),
|
||||
awsutilv2.WithIAMAPIFunc(
|
||||
awsutilv2.NewMockIAM(
|
||||
awsutilv2.WithGetUserOutput(
|
||||
awsutil.WithIAMAPIFunc(
|
||||
awsutil.NewMockIAM(
|
||||
awsutil.WithGetUserOutput(
|
||||
&iam.GetUserOutput{
|
||||
User: &iamTypes.User{
|
||||
Arn: aws.String("arn:aws:iam::123456789012:user/JohnDoe"),
|
||||
@@ -471,7 +471,7 @@ func TestAwsCatalogPersistedState_RotateCreds(t *testing.T) {
|
||||
},
|
||||
},
|
||||
),
|
||||
awsutilv2.WithCreateAccessKeyOutput(
|
||||
awsutil.WithCreateAccessKeyOutput(
|
||||
&iam.CreateAccessKeyOutput{
|
||||
AccessKey: &iamTypes.AccessKey{
|
||||
AccessKeyId: aws.String("one"),
|
||||
@@ -484,7 +484,7 @@ func TestAwsCatalogPersistedState_RotateCreds(t *testing.T) {
|
||||
),
|
||||
},
|
||||
},
|
||||
exepected: &awsutilv2.CredentialsConfig{
|
||||
exepected: &awsutil.CredentialsConfig{
|
||||
AccessKey: "one",
|
||||
SecretKey: "two",
|
||||
Region: "us-west-2",
|
||||
@@ -517,8 +517,8 @@ func TestAwsCatalogPersistedState_ReplaceCreds(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
in *AwsCredentialPersistedState
|
||||
credentialConfig *awsutilv2.CredentialsConfig
|
||||
expected *awsutilv2.CredentialsConfig
|
||||
credentialConfig *awsutil.CredentialsConfig
|
||||
expected *awsutil.CredentialsConfig
|
||||
expectedDeleteCalled bool
|
||||
expectedErr string
|
||||
}{
|
||||
@@ -530,71 +530,47 @@ func TestAwsCatalogPersistedState_ReplaceCreds(t *testing.T) {
|
||||
{
|
||||
name: "missing credentials config",
|
||||
in: &AwsCredentialPersistedState{},
|
||||
credentialConfig: &awsutilv2.CredentialsConfig{},
|
||||
credentialConfig: &awsutil.CredentialsConfig{},
|
||||
expectedErr: "missing credentials config",
|
||||
},
|
||||
{
|
||||
name: "cannot delete dynamic credential type",
|
||||
in: &AwsCredentialPersistedState{
|
||||
CredentialsConfig: &awsutilv2.CredentialsConfig{
|
||||
AccessKey: "ASIAfoobar",
|
||||
SecretKey: "bazqux",
|
||||
},
|
||||
CredsLastRotatedTime: time.Now(),
|
||||
},
|
||||
credentialConfig: &awsutilv2.CredentialsConfig{},
|
||||
expectedErr: "invalid credential type",
|
||||
},
|
||||
{
|
||||
name: "cannot delete unknown credential type",
|
||||
in: &AwsCredentialPersistedState{
|
||||
CredentialsConfig: &awsutilv2.CredentialsConfig{
|
||||
AccessKey: "DNEfoobar",
|
||||
SecretKey: "bazqux",
|
||||
},
|
||||
CredsLastRotatedTime: time.Now(),
|
||||
},
|
||||
credentialConfig: &awsutilv2.CredentialsConfig{},
|
||||
expectedErr: "invalid credential type",
|
||||
},
|
||||
{
|
||||
name: "deletion error",
|
||||
in: &AwsCredentialPersistedState{
|
||||
CredentialsConfig: &awsutilv2.CredentialsConfig{
|
||||
CredentialsConfig: &awsutil.CredentialsConfig{
|
||||
AccessKey: "AKIAfoobar",
|
||||
SecretKey: "bazqux",
|
||||
},
|
||||
CredsLastRotatedTime: time.Now(),
|
||||
testOpts: []awsutilv2.Option{
|
||||
awsutilv2.WithIAMAPIFunc(
|
||||
awsutilv2.NewMockIAM(
|
||||
awsutilv2.WithDeleteAccessKeyError(errors.New(testDeleteAccessKeyErr)),
|
||||
testOpts: []awsutil.Option{
|
||||
awsutil.WithIAMAPIFunc(
|
||||
awsutil.NewMockIAM(
|
||||
awsutil.WithDeleteAccessKeyError(errors.New(testDeleteAccessKeyErr)),
|
||||
),
|
||||
),
|
||||
},
|
||||
},
|
||||
credentialConfig: &awsutilv2.CredentialsConfig{},
|
||||
credentialConfig: &awsutil.CredentialsConfig{},
|
||||
expectedErr: fmt.Sprintf("error deleting old access key: %s", testDeleteAccessKeyErr),
|
||||
},
|
||||
{
|
||||
name: "good with delete of old rotated",
|
||||
in: &AwsCredentialPersistedState{
|
||||
CredentialsConfig: &awsutilv2.CredentialsConfig{
|
||||
CredentialsConfig: &awsutil.CredentialsConfig{
|
||||
AccessKey: "AKIAfoobar",
|
||||
SecretKey: "bazqux",
|
||||
},
|
||||
CredsLastRotatedTime: time.Now(),
|
||||
testOpts: []awsutilv2.Option{
|
||||
awsutilv2.WithIAMAPIFunc(
|
||||
testOpts: []awsutil.Option{
|
||||
awsutil.WithIAMAPIFunc(
|
||||
newTestMockIAM(state),
|
||||
),
|
||||
},
|
||||
},
|
||||
credentialConfig: &awsutilv2.CredentialsConfig{
|
||||
credentialConfig: &awsutil.CredentialsConfig{
|
||||
AccessKey: "one",
|
||||
SecretKey: "two",
|
||||
},
|
||||
expected: &awsutilv2.CredentialsConfig{
|
||||
expected: &awsutil.CredentialsConfig{
|
||||
AccessKey: "one",
|
||||
SecretKey: "two",
|
||||
},
|
||||
@@ -603,21 +579,21 @@ func TestAwsCatalogPersistedState_ReplaceCreds(t *testing.T) {
|
||||
{
|
||||
name: "good without delete of old rotated",
|
||||
in: &AwsCredentialPersistedState{
|
||||
CredentialsConfig: &awsutilv2.CredentialsConfig{
|
||||
CredentialsConfig: &awsutil.CredentialsConfig{
|
||||
AccessKey: "AKIAfoobar",
|
||||
SecretKey: "bazqux",
|
||||
},
|
||||
testOpts: []awsutilv2.Option{
|
||||
awsutilv2.WithIAMAPIFunc(
|
||||
testOpts: []awsutil.Option{
|
||||
awsutil.WithIAMAPIFunc(
|
||||
newTestMockIAM(state),
|
||||
),
|
||||
},
|
||||
},
|
||||
credentialConfig: &awsutilv2.CredentialsConfig{
|
||||
credentialConfig: &awsutil.CredentialsConfig{
|
||||
AccessKey: "one",
|
||||
SecretKey: "two",
|
||||
},
|
||||
expected: &awsutilv2.CredentialsConfig{
|
||||
expected: &awsutil.CredentialsConfig{
|
||||
AccessKey: "one",
|
||||
SecretKey: "two",
|
||||
},
|
||||
@@ -659,7 +635,7 @@ func TestAwsCatalogPersistedState_DeleteCreds(t *testing.T) {
|
||||
{
|
||||
name: "cannot delete dynamic credential type",
|
||||
in: &AwsCredentialPersistedState{
|
||||
CredentialsConfig: &awsutilv2.CredentialsConfig{
|
||||
CredentialsConfig: &awsutil.CredentialsConfig{
|
||||
AccessKey: "ASIAfoobar",
|
||||
SecretKey: "bazqux",
|
||||
},
|
||||
@@ -670,7 +646,7 @@ func TestAwsCatalogPersistedState_DeleteCreds(t *testing.T) {
|
||||
{
|
||||
name: "cannot delete unknown credential type",
|
||||
in: &AwsCredentialPersistedState{
|
||||
CredentialsConfig: &awsutilv2.CredentialsConfig{
|
||||
CredentialsConfig: &awsutil.CredentialsConfig{
|
||||
AccessKey: "DNEfoobar",
|
||||
SecretKey: "bazqux",
|
||||
},
|
||||
@@ -681,14 +657,14 @@ func TestAwsCatalogPersistedState_DeleteCreds(t *testing.T) {
|
||||
{
|
||||
name: "deletion error",
|
||||
in: &AwsCredentialPersistedState{
|
||||
CredentialsConfig: &awsutilv2.CredentialsConfig{
|
||||
CredentialsConfig: &awsutil.CredentialsConfig{
|
||||
AccessKey: "AKIAfoobar",
|
||||
SecretKey: "bazqux",
|
||||
},
|
||||
testOpts: []awsutilv2.Option{
|
||||
awsutilv2.WithIAMAPIFunc(
|
||||
awsutilv2.NewMockIAM(
|
||||
awsutilv2.WithDeleteAccessKeyError(errors.New(testDeleteAccessKeyErr)),
|
||||
testOpts: []awsutil.Option{
|
||||
awsutil.WithIAMAPIFunc(
|
||||
awsutil.NewMockIAM(
|
||||
awsutil.WithDeleteAccessKeyError(errors.New(testDeleteAccessKeyErr)),
|
||||
),
|
||||
),
|
||||
},
|
||||
@@ -698,14 +674,14 @@ func TestAwsCatalogPersistedState_DeleteCreds(t *testing.T) {
|
||||
{
|
||||
name: "deletion error, but OK because key was just gone",
|
||||
in: &AwsCredentialPersistedState{
|
||||
CredentialsConfig: &awsutilv2.CredentialsConfig{
|
||||
CredentialsConfig: &awsutil.CredentialsConfig{
|
||||
AccessKey: "AKIAfoobar",
|
||||
SecretKey: "bazqux",
|
||||
},
|
||||
testOpts: []awsutilv2.Option{
|
||||
awsutilv2.WithIAMAPIFunc(
|
||||
awsutilv2.NewMockIAM(
|
||||
awsutilv2.WithDeleteAccessKeyError(
|
||||
testOpts: []awsutil.Option{
|
||||
awsutil.WithIAMAPIFunc(
|
||||
awsutil.NewMockIAM(
|
||||
awsutil.WithDeleteAccessKeyError(
|
||||
&iamTypes.NoSuchEntityException{},
|
||||
),
|
||||
),
|
||||
@@ -716,13 +692,13 @@ func TestAwsCatalogPersistedState_DeleteCreds(t *testing.T) {
|
||||
{
|
||||
name: "good",
|
||||
in: &AwsCredentialPersistedState{
|
||||
CredentialsConfig: &awsutilv2.CredentialsConfig{
|
||||
CredentialsConfig: &awsutil.CredentialsConfig{
|
||||
AccessKey: "AKIAfoobar",
|
||||
SecretKey: "bazqux",
|
||||
},
|
||||
testOpts: []awsutilv2.Option{
|
||||
awsutilv2.WithIAMAPIFunc(
|
||||
awsutilv2.NewMockIAM(),
|
||||
testOpts: []awsutil.Option{
|
||||
awsutil.WithIAMAPIFunc(
|
||||
awsutil.NewMockIAM(),
|
||||
),
|
||||
},
|
||||
},
|
||||
@@ -756,24 +732,24 @@ func TestAwsCatalogPersistedState_GenerateCredentialChain(t *testing.T) {
|
||||
{
|
||||
name: "error",
|
||||
in: &AwsCredentialPersistedState{
|
||||
CredentialsConfig: &awsutilv2.CredentialsConfig{
|
||||
CredentialsConfig: &awsutil.CredentialsConfig{
|
||||
AccessKey: "foobar",
|
||||
SecretKey: "bazqux",
|
||||
},
|
||||
testOpts: []awsutilv2.Option{awsutilv2.MockOptionErr(errors.New(testOptionErr))},
|
||||
testOpts: []awsutil.Option{awsutil.MockOptionErr(errors.New(testOptionErr))},
|
||||
},
|
||||
expectedErr: fmt.Sprintf("error reading options in GenerateCredentialChain: %s", testOptionErr),
|
||||
},
|
||||
{
|
||||
name: "static credentials",
|
||||
in: &AwsCredentialPersistedState{
|
||||
CredentialsConfig: &awsutilv2.CredentialsConfig{
|
||||
CredentialsConfig: &awsutil.CredentialsConfig{
|
||||
AccessKey: "AKIA_foobar",
|
||||
SecretKey: "bazqux",
|
||||
},
|
||||
testOpts: []awsutilv2.Option{
|
||||
awsutilv2.WithIAMAPIFunc(
|
||||
awsutilv2.NewMockIAM(),
|
||||
testOpts: []awsutil.Option{
|
||||
awsutil.WithIAMAPIFunc(
|
||||
awsutil.NewMockIAM(),
|
||||
),
|
||||
},
|
||||
},
|
||||
@@ -781,22 +757,22 @@ func TestAwsCatalogPersistedState_GenerateCredentialChain(t *testing.T) {
|
||||
{
|
||||
name: "assume role",
|
||||
in: &AwsCredentialPersistedState{
|
||||
CredentialsConfig: func() *awsutilv2.CredentialsConfig {
|
||||
config, err := awsutilv2.NewCredentialsConfig(
|
||||
awsutilv2.WithRegion("us-west-2"),
|
||||
awsutilv2.WithRoleArn("arn:aws:iam::123456789012:role/S3Access"),
|
||||
awsutilv2.WithRoleExternalId("1234567890"),
|
||||
awsutilv2.WithRoleSessionName("assume-role"),
|
||||
awsutilv2.WithRoleTags(map[string]string{
|
||||
CredentialsConfig: func() *awsutil.CredentialsConfig {
|
||||
config, err := awsutil.NewCredentialsConfig(
|
||||
awsutil.WithRegion("us-west-2"),
|
||||
awsutil.WithRoleArn("arn:aws:iam::123456789012:role/S3Access"),
|
||||
awsutil.WithRoleExternalId("1234567890"),
|
||||
awsutil.WithRoleSessionName("assume-role"),
|
||||
awsutil.WithRoleTags(map[string]string{
|
||||
"foo": "bar",
|
||||
}),
|
||||
)
|
||||
require.NoError(err)
|
||||
return config
|
||||
}(),
|
||||
testOpts: []awsutilv2.Option{
|
||||
awsutilv2.WithIAMAPIFunc(
|
||||
awsutilv2.NewMockIAM(),
|
||||
testOpts: []awsutil.Option{
|
||||
awsutil.WithIAMAPIFunc(
|
||||
awsutil.NewMockIAM(),
|
||||
),
|
||||
},
|
||||
},
|
||||
@@ -815,74 +791,53 @@ func TestAwsCatalogPersistedState_GenerateCredentialChain(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestHasStaticCredentials(t *testing.T) {
|
||||
require := require.New(t)
|
||||
cases := []struct {
|
||||
name string
|
||||
accessKey string
|
||||
expected bool
|
||||
func TestGetCredentialType(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
credConfig *awsutil.CredentialsConfig
|
||||
expectedCredType CredentialType
|
||||
}{
|
||||
{
|
||||
name: "dynamic credential",
|
||||
accessKey: "ASIAEXAMPLE",
|
||||
expected: false,
|
||||
name: "nil credential config",
|
||||
credConfig: nil,
|
||||
expectedCredType: Unknown,
|
||||
},
|
||||
{
|
||||
name: "static credential",
|
||||
accessKey: "AKIAEXAMPLE",
|
||||
expected: true,
|
||||
name: "empty credential config",
|
||||
credConfig: &awsutil.CredentialsConfig{},
|
||||
expectedCredType: Unknown,
|
||||
},
|
||||
{
|
||||
name: "other credential",
|
||||
accessKey: "EXAMPLE",
|
||||
expected: false,
|
||||
name: "static aws",
|
||||
credConfig: &awsutil.CredentialsConfig{AccessKey: "AKIAfoobar"},
|
||||
expectedCredType: StaticAWS,
|
||||
},
|
||||
{
|
||||
name: "empty",
|
||||
accessKey: "",
|
||||
expected: false,
|
||||
name: "static other",
|
||||
credConfig: &awsutil.CredentialsConfig{AccessKey: "cK3kNFa24foobar"},
|
||||
expectedCredType: StaticOther,
|
||||
},
|
||||
{
|
||||
name: "dynamic aws - role arn",
|
||||
credConfig: &awsutil.CredentialsConfig{RoleARN: "arn:aws:iam::123456789012:role/S3Access"},
|
||||
expectedCredType: DynamicAWS,
|
||||
},
|
||||
{
|
||||
name: "dynamic aws - access key",
|
||||
credConfig: &awsutil.CredentialsConfig{AccessKey: "ASIAfoobar"},
|
||||
expectedCredType: DynamicAWS,
|
||||
},
|
||||
{
|
||||
name: "dynamic aws - role arn and access key",
|
||||
credConfig: &awsutil.CredentialsConfig{AccessKey: "ASIAfoobar", RoleARN: "arn:aws:iam::123456789012:role/S3Access"},
|
||||
expectedCredType: DynamicAWS,
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
require.Equal(tc.expected, HasStaticCredentials(tc.accessKey))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHasDynamicCredentials(t *testing.T) {
|
||||
require := require.New(t)
|
||||
cases := []struct {
|
||||
name string
|
||||
accessKey string
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "dynamic credential",
|
||||
accessKey: "ASIAEXAMPLE",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "static credential",
|
||||
accessKey: "AKIAEXAMPLE",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "other credential",
|
||||
accessKey: "EXAMPLE",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "empty",
|
||||
accessKey: "",
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
require.Equal(tc.expected, HasDynamicCredentials(tc.accessKey))
|
||||
ct := GetCredentialType(tc.credConfig)
|
||||
require.Equal(t, tc.expectedCredType, ct)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/service/iam"
|
||||
awsutilv2 "github.com/hashicorp/go-secure-stdlib/awsutil"
|
||||
"github.com/hashicorp/go-secure-stdlib/awsutil/v2"
|
||||
"google.golang.org/protobuf/types/known/structpb"
|
||||
)
|
||||
|
||||
@@ -28,7 +28,7 @@ func (s *testMockIAMState) Reset() {
|
||||
}
|
||||
|
||||
type testMockIAM struct {
|
||||
awsutilv2.IAMClient
|
||||
awsutil.IAMClient
|
||||
|
||||
State *testMockIAMState
|
||||
}
|
||||
@@ -38,12 +38,12 @@ func (m *testMockIAM) DeleteAccessKey(ctx context.Context, input *iam.DeleteAcce
|
||||
return m.IAMClient.DeleteAccessKey(ctx, input, opts...)
|
||||
}
|
||||
|
||||
func newTestMockIAM(state *testMockIAMState, opts ...awsutilv2.MockIAMOption) awsutilv2.IAMAPIFunc {
|
||||
return func(awsConfig *aws.Config) (awsutilv2.IAMClient, error) {
|
||||
func newTestMockIAM(state *testMockIAMState, opts ...awsutil.MockIAMOption) awsutil.IAMAPIFunc {
|
||||
return func(awsConfig *aws.Config) (awsutil.IAMClient, error) {
|
||||
m := &testMockIAM{
|
||||
State: state,
|
||||
}
|
||||
f := awsutilv2.NewMockIAM(opts...)
|
||||
f := awsutil.NewMockIAM(opts...)
|
||||
var err error
|
||||
|
||||
m.IAMClient, err = f(awsConfig)
|
||||
|
||||
@@ -83,8 +83,7 @@ func (p *HostPlugin) OnCreateCatalog(ctx context.Context, req *pb.OnCreateCatalo
|
||||
return nil, status.Errorf(codes.InvalidArgument, "error setting up persisted state: %s", err)
|
||||
}
|
||||
|
||||
// Try to rotate static credentials
|
||||
if cred.HasStaticCredentials(credState.CredentialsConfig.AccessKey) {
|
||||
if cred.GetCredentialType(credState.CredentialsConfig) == cred.StaticAWS {
|
||||
if !catalogAttributes.DisableCredentialRotation {
|
||||
if err := credState.RotateCreds(ctx); err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "error during credential rotation: %s", err)
|
||||
@@ -160,7 +159,7 @@ func (p *HostPlugin) OnUpdateCatalog(ctx context.Context, req *pb.OnUpdateCatalo
|
||||
return nil, status.Errorf(codes.InvalidArgument, "error loading persisted state: %s", err)
|
||||
}
|
||||
|
||||
if cred.HasStaticCredentials(credState.CredentialsConfig.AccessKey) {
|
||||
if cred.GetCredentialType(credState.CredentialsConfig) == cred.StaticAWS {
|
||||
if catalogAttributes.DisableCredentialRotation && !updateSecrets {
|
||||
// This is a validate check to make sure that we aren't disabling
|
||||
// rotation for credentials currently being managed by rotation.
|
||||
@@ -244,7 +243,7 @@ func (p *HostPlugin) OnDeleteCatalog(ctx context.Context, req *pb.OnDeleteCatalo
|
||||
}
|
||||
|
||||
// try to delete static credentials
|
||||
if cred.HasStaticCredentials(credState.CredentialsConfig.AccessKey) {
|
||||
if cred.GetCredentialType(credState.CredentialsConfig) == cred.StaticAWS {
|
||||
if !credState.CredsLastRotatedTime.IsZero() {
|
||||
// Delete old/existing credentials. This is done with the same
|
||||
// credentials to ensure that it has the proper permissions to do
|
||||
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
"github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/hostcatalogs"
|
||||
"github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/hostsets"
|
||||
pb "github.com/hashicorp/boundary/sdk/pbs/plugin"
|
||||
awsutilv2 "github.com/hashicorp/go-secure-stdlib/awsutil"
|
||||
"github.com/hashicorp/go-secure-stdlib/awsutil/v2"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
@@ -145,10 +145,10 @@ func TestPluginOnCreateCatalogErr(t *testing.T) {
|
||||
},
|
||||
},
|
||||
credOpts: []credential.AwsCredentialPersistedStateOption{
|
||||
credential.WithStateTestOpts([]awsutilv2.Option{
|
||||
awsutilv2.WithIAMAPIFunc(
|
||||
awsutilv2.NewMockIAM(
|
||||
awsutilv2.WithGetUserError(errors.New(testGetUserErr)),
|
||||
credential.WithStateTestOpts([]awsutil.Option{
|
||||
awsutil.WithIAMAPIFunc(
|
||||
awsutil.NewMockIAM(
|
||||
awsutil.WithGetUserError(errors.New(testGetUserErr)),
|
||||
),
|
||||
),
|
||||
}),
|
||||
@@ -176,10 +176,10 @@ func TestPluginOnCreateCatalogErr(t *testing.T) {
|
||||
},
|
||||
},
|
||||
credOpts: []credential.AwsCredentialPersistedStateOption{
|
||||
credential.WithStateTestOpts([]awsutilv2.Option{
|
||||
awsutilv2.WithSTSAPIFunc(
|
||||
awsutilv2.NewMockSTS(
|
||||
awsutilv2.WithGetCallerIdentityError(errors.New(testGetCallerIdentityErr)),
|
||||
credential.WithStateTestOpts([]awsutil.Option{
|
||||
awsutil.WithSTSAPIFunc(
|
||||
awsutil.NewMockSTS(
|
||||
awsutil.WithGetCallerIdentityError(errors.New(testGetCallerIdentityErr)),
|
||||
),
|
||||
),
|
||||
}),
|
||||
@@ -370,10 +370,10 @@ func TestPluginOnUpdateCatalogErr(t *testing.T) {
|
||||
},
|
||||
},
|
||||
credOpts: []credential.AwsCredentialPersistedStateOption{
|
||||
credential.WithStateTestOpts([]awsutilv2.Option{
|
||||
awsutilv2.WithIAMAPIFunc(
|
||||
awsutilv2.NewMockIAM(
|
||||
awsutilv2.WithDeleteAccessKeyError(errors.New(testDeleteAccessKeyErr)),
|
||||
credential.WithStateTestOpts([]awsutil.Option{
|
||||
awsutil.WithIAMAPIFunc(
|
||||
awsutil.NewMockIAM(
|
||||
awsutil.WithDeleteAccessKeyError(errors.New(testDeleteAccessKeyErr)),
|
||||
),
|
||||
),
|
||||
}),
|
||||
@@ -403,10 +403,10 @@ func TestPluginOnUpdateCatalogErr(t *testing.T) {
|
||||
},
|
||||
},
|
||||
credOpts: []credential.AwsCredentialPersistedStateOption{
|
||||
credential.WithStateTestOpts([]awsutilv2.Option{
|
||||
awsutilv2.WithIAMAPIFunc(
|
||||
awsutilv2.NewMockIAM(
|
||||
awsutilv2.WithGetUserError(errors.New(testGetUserErr)),
|
||||
credential.WithStateTestOpts([]awsutil.Option{
|
||||
awsutil.WithIAMAPIFunc(
|
||||
awsutil.NewMockIAM(
|
||||
awsutil.WithGetUserError(errors.New(testGetUserErr)),
|
||||
),
|
||||
),
|
||||
}),
|
||||
@@ -493,10 +493,10 @@ func TestPluginOnDeleteCatalogErr(t *testing.T) {
|
||||
},
|
||||
},
|
||||
credOpts: []credential.AwsCredentialPersistedStateOption{
|
||||
credential.WithStateTestOpts([]awsutilv2.Option{
|
||||
awsutilv2.WithIAMAPIFunc(
|
||||
awsutilv2.NewMockIAM(
|
||||
awsutilv2.WithDeleteAccessKeyError(errors.New(testDeleteAccessKeyErr)),
|
||||
credential.WithStateTestOpts([]awsutil.Option{
|
||||
awsutil.WithIAMAPIFunc(
|
||||
awsutil.NewMockIAM(
|
||||
awsutil.WithDeleteAccessKeyError(errors.New(testDeleteAccessKeyErr)),
|
||||
),
|
||||
),
|
||||
}),
|
||||
@@ -729,8 +729,8 @@ func TestPluginOnCreateSetErr(t *testing.T) {
|
||||
},
|
||||
},
|
||||
credOpts: []credential.AwsCredentialPersistedStateOption{
|
||||
credential.WithStateTestOpts([]awsutilv2.Option{
|
||||
awsutilv2.MockOptionErr(errors.New(testOptionErr)),
|
||||
credential.WithStateTestOpts([]awsutil.Option{
|
||||
awsutil.MockOptionErr(errors.New(testOptionErr)),
|
||||
}),
|
||||
},
|
||||
expectedErrContains: fmt.Sprintf("error loading persisted state: error reading options in NewCredentialsConfig: %s", testOptionErr),
|
||||
@@ -1098,8 +1098,8 @@ func TestPluginOnUpdateSetErr(t *testing.T) {
|
||||
},
|
||||
},
|
||||
credOpts: []credential.AwsCredentialPersistedStateOption{
|
||||
credential.WithStateTestOpts([]awsutilv2.Option{
|
||||
awsutilv2.MockOptionErr(errors.New(testOptionErr)),
|
||||
credential.WithStateTestOpts([]awsutil.Option{
|
||||
awsutil.MockOptionErr(errors.New(testOptionErr)),
|
||||
}),
|
||||
},
|
||||
expectedErrContains: fmt.Sprintf("error loading persisted state: error reading options in NewCredentialsConfig: %s", testOptionErr),
|
||||
@@ -1458,8 +1458,8 @@ func TestPluginListHostsErr(t *testing.T) {
|
||||
},
|
||||
},
|
||||
credOpts: []credential.AwsCredentialPersistedStateOption{
|
||||
credential.WithStateTestOpts([]awsutilv2.Option{
|
||||
awsutilv2.MockOptionErr(errors.New(testOptionErr)),
|
||||
credential.WithStateTestOpts([]awsutil.Option{
|
||||
awsutil.MockOptionErr(errors.New(testOptionErr)),
|
||||
}),
|
||||
},
|
||||
expectedErrContains: fmt.Sprintf("error loading persisted state: error reading options in NewCredentialsConfig: %s", testOptionErr),
|
||||
|
||||
@@ -8,14 +8,14 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/boundary-plugin-aws/internal/credential"
|
||||
awsutilv2 "github.com/hashicorp/go-secure-stdlib/awsutil"
|
||||
"github.com/hashicorp/go-secure-stdlib/awsutil/v2"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestAwsCatalogPersistedStateEC2Client(t *testing.T) {
|
||||
require := require.New(t)
|
||||
cred, err := credential.NewAwsCredentialPersistedState(
|
||||
credential.WithCredentialsConfig(&awsutilv2.CredentialsConfig{
|
||||
credential.WithCredentialsConfig(&awsutil.CredentialsConfig{
|
||||
Region: "us-west-2",
|
||||
AccessKey: "foobar",
|
||||
SecretKey: "barfoo",
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/aws/retry"
|
||||
@@ -21,7 +22,6 @@ import (
|
||||
cred "github.com/hashicorp/boundary-plugin-aws/internal/credential"
|
||||
"github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/storagebuckets"
|
||||
pb "github.com/hashicorp/boundary/sdk/pbs/plugin"
|
||||
awsutilv2 "github.com/hashicorp/go-secure-stdlib/awsutil"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
@@ -40,10 +40,6 @@ type StoragePlugin struct {
|
||||
|
||||
// testStorageStateOpts are passed in to the stored state to control test behavior
|
||||
testStorageStateOpts []awsStoragePersistedStateOption
|
||||
|
||||
// testAwsUtilV2Opts are passed to awsutilv2 directly (currently used for
|
||||
// GenerateCredentialChain).
|
||||
testAwsUtilV2Opts []awsutilv2.Option
|
||||
}
|
||||
|
||||
// OnCreateStorageBucket is called when a storage bucket is created.
|
||||
@@ -81,17 +77,10 @@ func (p *StoragePlugin) OnCreateStorageBucket(ctx context.Context, req *pb.OnCre
|
||||
return nil, status.Errorf(codes.InvalidArgument, "error setting up persisted state: %s", err)
|
||||
}
|
||||
|
||||
// Try to rotate static credentials
|
||||
if cred.HasStaticCredentials(credState.CredentialsConfig.AccessKey) {
|
||||
if !storageAttributes.DisableCredentialRotation {
|
||||
if err := credState.RotateCreds(ctx); err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "error during credential rotation: %s", err)
|
||||
}
|
||||
} else {
|
||||
// Simply validate if we aren't rotating.
|
||||
if err := credState.ValidateCreds(ctx); err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "error during credential validation: %s", err)
|
||||
}
|
||||
// Try to rotate AWS static credentials
|
||||
if cred.GetCredentialType(credConfig) == cred.StaticAWS && !storageAttributes.DisableCredentialRotation {
|
||||
if err := credState.RotateCreds(ctx); err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "error during credential rotation: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,13 +150,38 @@ func (p *StoragePlugin) OnUpdateStorageBucket(ctx context.Context, req *pb.OnUpd
|
||||
return nil, status.Errorf(codes.InvalidArgument, "error loading persisted state: %s", err)
|
||||
}
|
||||
|
||||
// Verify the incoming credentials are valid and return any errors to the
|
||||
// user if they're not. Note this doesn't validate the credentials against
|
||||
// AWS - it only does logical validation on the fields.
|
||||
updatedCredentials, err := cred.GetCredentialsConfig(newBucket.GetSecrets(), newStorageAttributes.CredentialAttributes, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// We will be updating credentials when one of two changes occur:
|
||||
// 1. the new bucket has secrets for static credentials, in which case we need to delete the old static credentials
|
||||
// 2. the new bucket has a different roleARN value for dynamic credentials
|
||||
if newBucket.GetSecrets() != nil || newStorageAttributes.RoleArn != oldStorageAttributes.RoleArn {
|
||||
updatedCredentials, err := cred.GetCredentialsConfig(newBucket.GetSecrets(), newStorageAttributes.CredentialAttributes, false)
|
||||
// Ensure the incoming credentials are valid for interaction with the S3
|
||||
// Bucket before replacing them.
|
||||
newCredState, err := cred.NewAwsCredentialPersistedState(
|
||||
append([]cred.AwsCredentialPersistedStateOption{
|
||||
cred.WithCredentialsConfig(updatedCredentials),
|
||||
}, p.testCredStateOpts...)...,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, status.Errorf(codes.InvalidArgument, "error setting up new credential persisted state: %s", err)
|
||||
}
|
||||
newStorageState, err := newAwsStoragePersistedState(
|
||||
append([]awsStoragePersistedStateOption{
|
||||
withCredentials(newCredState),
|
||||
}, p.testStorageStateOpts...)...,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "error loading persisted state: %s", err)
|
||||
}
|
||||
if err := dryRunValidation(ctx, newStorageState, newStorageAttributes, newBucket); err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "failed to validate incoming credentials: %s", err)
|
||||
}
|
||||
|
||||
// Replace the existing credential state.
|
||||
@@ -179,19 +193,7 @@ func (p *StoragePlugin) OnUpdateStorageBucket(ctx context.Context, req *pb.OnUpd
|
||||
}
|
||||
}
|
||||
|
||||
awsCfg, err := credState.CredentialsConfig.GenerateCredentialChain(ctx, p.testAwsUtilV2Opts...)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "failed to generate aws credential chain: %s", err)
|
||||
}
|
||||
|
||||
awsCredentials, err := awsCfg.Credentials.Retrieve(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "failed to retrieve aws credentials: %s", err)
|
||||
}
|
||||
|
||||
credentialType := cred.GetCredentialType(awsCredentials.AccessKeyID)
|
||||
switch credentialType {
|
||||
case cred.Static:
|
||||
if cred.GetCredentialType(credState.CredentialsConfig) == cred.StaticAWS {
|
||||
// This is a validate check to make sure that we aren't disabling
|
||||
// rotation for credentials currently being managed by rotation.
|
||||
// This is not allowed.
|
||||
@@ -208,16 +210,8 @@ func (p *StoragePlugin) OnUpdateStorageBucket(ctx context.Context, req *pb.OnUpd
|
||||
return nil, status.Errorf(codes.InvalidArgument, "error during credential rotation: %s", err)
|
||||
}
|
||||
}
|
||||
case cred.Dynamic:
|
||||
// We cannot allow credential rotation for dynamic credentials
|
||||
if !newStorageAttributes.DisableCredentialRotation {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "cannot enable credential rotation for dynamic credential type")
|
||||
}
|
||||
case cred.Unknown:
|
||||
fallthrough
|
||||
default:
|
||||
return nil, status.Errorf(codes.InvalidArgument, "unknown credential type")
|
||||
}
|
||||
|
||||
storageState, err := newAwsStoragePersistedState(
|
||||
append([]awsStoragePersistedStateOption{
|
||||
withCredentials(credState),
|
||||
@@ -283,7 +277,7 @@ func (p *StoragePlugin) OnDeleteStorageBucket(ctx context.Context, req *pb.OnDel
|
||||
}
|
||||
|
||||
// try to delete static credentials
|
||||
if cred.HasStaticCredentials(credState.CredentialsConfig.AccessKey) {
|
||||
if cred.GetCredentialType(credState.CredentialsConfig) == cred.StaticAWS {
|
||||
if !credState.CredsLastRotatedTime.IsZero() {
|
||||
// Delete old/existing credentials. This is done with the same
|
||||
// credentials to ensure that it has the proper permissions to do
|
||||
@@ -629,6 +623,129 @@ func (p *StoragePlugin) PutObject(ctx context.Context, req *pb.PutObjectRequest)
|
||||
}, nil
|
||||
}
|
||||
|
||||
// DeleteObjects is used to delete one or many objects from an s3 bucket.
|
||||
func (p *StoragePlugin) DeleteObjects(ctx context.Context, req *pb.DeleteObjectsRequest) (*pb.DeleteObjectsResponse, error) {
|
||||
if req.GetKeyPrefix() == "" {
|
||||
return nil, status.Error(codes.InvalidArgument, "key prefix is required")
|
||||
}
|
||||
|
||||
bucket := req.GetBucket()
|
||||
if bucket == nil {
|
||||
return nil, status.Error(codes.InvalidArgument, "bucket is required")
|
||||
}
|
||||
|
||||
if bucket.GetBucketName() == "" {
|
||||
return nil, status.Error(codes.InvalidArgument, "bucketName is required")
|
||||
}
|
||||
|
||||
attrs := bucket.GetAttributes()
|
||||
if attrs == nil {
|
||||
return nil, status.Error(codes.InvalidArgument, "attributes is required")
|
||||
}
|
||||
|
||||
storageAttributes, err := getStorageAttributes(attrs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
credConfig, err := cred.GetCredentialsConfig(bucket.GetSecrets(), storageAttributes.CredentialAttributes, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Set up the creds in our persisted state.
|
||||
credState, err := cred.NewAwsCredentialPersistedState(
|
||||
append([]cred.AwsCredentialPersistedStateOption{
|
||||
cred.WithCredentialsConfig(credConfig),
|
||||
}, p.testCredStateOpts...)...,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "error setting up persisted state: %s", err)
|
||||
}
|
||||
|
||||
storageState, err := newAwsStoragePersistedState(
|
||||
append([]awsStoragePersistedStateOption{
|
||||
withCredentials(credState),
|
||||
}, p.testStorageStateOpts...)...,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "error setting up persisted state: %s", err)
|
||||
}
|
||||
|
||||
opts := []s3Option{}
|
||||
if storageAttributes.EndpointUrl != "" {
|
||||
opts = append(opts, WithEndpoint(storageAttributes.EndpointUrl))
|
||||
}
|
||||
client, err := storageState.S3Client(ctx, opts...)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "error getting S3 client: %s", err)
|
||||
}
|
||||
|
||||
prefix := path.Join(bucket.GetBucketPrefix(), req.GetKeyPrefix())
|
||||
if strings.HasSuffix(req.GetKeyPrefix(), "/") {
|
||||
// path.Join ends by "cleaning" the path, including removing a trailing slash, if
|
||||
// it exists. given that a slash is used to denote a folder, it is required here.
|
||||
prefix += "/"
|
||||
}
|
||||
|
||||
if !req.Recursive {
|
||||
_, err := client.DeleteObject(ctx, &s3.DeleteObjectInput{
|
||||
Bucket: aws.String(bucket.GetBucketName()),
|
||||
Key: aws.String(prefix),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, parseAWSErrCode("error deleting S3 object", err)
|
||||
}
|
||||
return &pb.DeleteObjectsResponse{
|
||||
ObjectsDeleted: uint32(1),
|
||||
}, nil
|
||||
}
|
||||
|
||||
const maxkeys = 1000
|
||||
|
||||
objects := []types.ObjectIdentifier{}
|
||||
var conToken *string
|
||||
truncated := true
|
||||
for truncated {
|
||||
res, err := client.ListObjectsV2(ctx, &s3.ListObjectsV2Input{
|
||||
Bucket: aws.String(bucket.GetBucketName()),
|
||||
Prefix: aws.String(prefix),
|
||||
MaxKeys: maxkeys,
|
||||
ContinuationToken: conToken,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, parseAWSErrCode("error iterating S3 bucket contents", err)
|
||||
}
|
||||
truncated = res.IsTruncated
|
||||
conToken = res.NextContinuationToken
|
||||
for _, o := range res.Contents {
|
||||
objects = append(objects, types.ObjectIdentifier{
|
||||
Key: o.Key,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
deleted := 0
|
||||
|
||||
for i := 0; i < len(objects); i += maxkeys {
|
||||
toDelete := objects[i:min(len(objects), i+maxkeys)] // min is required to avoid an out of bounds panic
|
||||
res, err := client.DeleteObjects(ctx, &s3.DeleteObjectsInput{
|
||||
Bucket: aws.String(bucket.GetBucketName()),
|
||||
Delete: &types.Delete{
|
||||
Objects: toDelete,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, parseAWSErrCode("error deleting S3 object(s)", err)
|
||||
}
|
||||
deleted += len(res.Deleted)
|
||||
}
|
||||
|
||||
return &pb.DeleteObjectsResponse{
|
||||
ObjectsDeleted: uint32(deleted),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// dryRunValidation validates that the IAM role policy attached to the given secrets of the
|
||||
// storage bucket has the minimum required permissions needed for this plugin to function
|
||||
// as expected. This function will create an object in the s3 bucket to validate it has
|
||||
@@ -679,13 +796,21 @@ func dryRunValidation(ctx context.Context, state *awsStoragePersistedState, attr
|
||||
return parseAWSErrCode("error failed to get head object", err)
|
||||
}
|
||||
|
||||
// attempt to delete the test object created for the dry run validation,
|
||||
// this step is allowed to fail because DeleteObject is not a required
|
||||
// operation for the plugin.
|
||||
client.DeleteObject(ctx, &s3.DeleteObjectInput{
|
||||
if res, err := client.ListObjectsV2(ctx, &s3.ListObjectsV2Input{
|
||||
Bucket: aws.String(bucket.GetBucketName()),
|
||||
Prefix: aws.String(objectKey),
|
||||
}); err != nil {
|
||||
return parseAWSErrCode("error failed to list objects", err)
|
||||
} else if res == nil || len(res.Contents) != 1 || *res.Contents[0].Key != objectKey {
|
||||
return status.Errorf(codes.InvalidArgument, "list response did not contain the expected key: %+v", res)
|
||||
}
|
||||
|
||||
if _, err := client.DeleteObject(ctx, &s3.DeleteObjectInput{
|
||||
Bucket: aws.String(bucket.GetBucketName()),
|
||||
Key: aws.String(objectKey),
|
||||
})
|
||||
}); err != nil {
|
||||
return parseAWSErrCode("error failed to delete object", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
+1300
-144
File diff suppressed because it is too large.
Load diff
@@ -25,6 +25,8 @@ type S3API interface {
|
||||
GetObject(ctx context.Context, params *s3.GetObjectInput, optFns ...func(*s3.Options)) (*s3.GetObjectOutput, error)
|
||||
HeadObject(ctx context.Context, params *s3.HeadObjectInput, optFns ...func(*s3.Options)) (*s3.HeadObjectOutput, error)
|
||||
PutObject(ctx context.Context, params *s3.PutObjectInput, optFns ...func(*s3.Options)) (*s3.PutObjectOutput, error)
|
||||
DeleteObjects(ctx context.Context, params *s3.DeleteObjectsInput, optFns ...func(*s3.Options)) (*s3.DeleteObjectsOutput, error)
|
||||
ListObjectsV2(ctx context.Context, params *s3.ListObjectsV2Input, optFns ...func(*s3.Options)) (*s3.ListObjectsV2Output, error)
|
||||
}
|
||||
|
||||
var customClient = &http.Client{
|
||||
|
||||
@@ -8,34 +8,34 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/boundary-plugin-aws/internal/credential"
|
||||
awsutilv2 "github.com/hashicorp/go-secure-stdlib/awsutil"
|
||||
"github.com/hashicorp/go-secure-stdlib/awsutil/v2"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestAwsStoragePersistedStateS3Client(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
creds *awsutilv2.CredentialsConfig
|
||||
creds *awsutil.CredentialsConfig
|
||||
opts []awsStoragePersistedStateOption
|
||||
awsOpts []awsutilv2.Option
|
||||
awsOpts []awsutil.Option
|
||||
s3Opts []s3Option
|
||||
expectedRegion string
|
||||
expectedEndpoint string
|
||||
}{
|
||||
{
|
||||
name: "static credentials",
|
||||
creds: func() *awsutilv2.CredentialsConfig {
|
||||
creds, err := awsutilv2.NewCredentialsConfig(
|
||||
awsutilv2.WithRegion("us-west-2"),
|
||||
awsutilv2.WithAccessKey("foobar"),
|
||||
awsutilv2.WithSecretKey("barfoo"),
|
||||
creds: func() *awsutil.CredentialsConfig {
|
||||
creds, err := awsutil.NewCredentialsConfig(
|
||||
awsutil.WithRegion("us-west-2"),
|
||||
awsutil.WithAccessKey("foobar"),
|
||||
awsutil.WithSecretKey("barfoo"),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
return creds
|
||||
}(),
|
||||
awsOpts: []awsutilv2.Option{
|
||||
awsutilv2.WithIAMAPIFunc(
|
||||
awsutilv2.NewMockIAM(),
|
||||
awsOpts: []awsutil.Option{
|
||||
awsutil.WithIAMAPIFunc(
|
||||
awsutil.NewMockIAM(),
|
||||
),
|
||||
},
|
||||
opts: []awsStoragePersistedStateOption{
|
||||
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
"github.com/hashicorp/boundary-plugin-aws/internal/credential"
|
||||
"github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/storagebuckets"
|
||||
pb "github.com/hashicorp/boundary/sdk/pbs/plugin"
|
||||
awsutilv2 "github.com/hashicorp/go-secure-stdlib/awsutil"
|
||||
"github.com/hashicorp/go-secure-stdlib/awsutil/v2"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/protobuf/types/known/structpb"
|
||||
@@ -31,6 +31,9 @@ const (
|
||||
testGetObjectErr = "test error for GetObject"
|
||||
testPutObjectErr = "test error for PutObject"
|
||||
testHeadObjectErr = "test error for HeadObject"
|
||||
testListObjectV2Err = "test error for ListObjectV2"
|
||||
testDeleteObjectErr = "test error for DeleteObject"
|
||||
testDeleteObjectsErr = "test error for DeleteObjects"
|
||||
)
|
||||
|
||||
// throttleErr is a mocked error used for testing the aws s3 client
|
||||
@@ -54,6 +57,14 @@ type testMockS3State struct {
|
||||
|
||||
HeadObjectCalled bool
|
||||
HeadObjectInputParams *s3.HeadObjectInput
|
||||
|
||||
ListObjectsV2Called bool
|
||||
ListObjectsV2InputParams *s3.ListObjectsV2Input
|
||||
|
||||
DeleteObjectCalled bool
|
||||
DeleteObjectInputParams *s3.DeleteObjectInput
|
||||
DeleteObjectsCalled bool
|
||||
DeleteObjectsInputParams *s3.DeleteObjectsInput
|
||||
}
|
||||
|
||||
func (s *testMockS3State) Reset() {
|
||||
@@ -64,6 +75,12 @@ func (s *testMockS3State) Reset() {
|
||||
s.PutObjectBody = nil
|
||||
s.HeadObjectCalled = false
|
||||
s.HeadObjectInputParams = nil
|
||||
s.ListObjectsV2Called = false
|
||||
s.ListObjectsV2InputParams = nil
|
||||
s.DeleteObjectCalled = false
|
||||
s.DeleteObjectInputParams = nil
|
||||
s.DeleteObjectsCalled = false
|
||||
s.DeleteObjectsInputParams = nil
|
||||
}
|
||||
|
||||
type testMockS3 struct {
|
||||
@@ -83,6 +100,18 @@ type testMockS3 struct {
|
||||
// mocked responses for headObject
|
||||
HeadObjectOutput *s3.HeadObjectOutput
|
||||
HeadObjectErr error
|
||||
|
||||
// mocked responses for ListObjectsV2 (needed for delete)
|
||||
ListObjectsV2Output *s3.ListObjectsV2Output
|
||||
ListObjectsV2Err error
|
||||
// sometimes we need to create a wildcard output
|
||||
ListObjectsV2OutputFunc func(*s3.ListObjectsV2Input) *s3.ListObjectsV2Output
|
||||
|
||||
// mocked responses for DeleteObject(s)
|
||||
DeleteObjectOutput *s3.DeleteObjectOutput
|
||||
DeleteObjectErr error
|
||||
DeleteObjectsOutput *s3.DeleteObjectsOutput
|
||||
DeleteObjectsErr error
|
||||
}
|
||||
|
||||
type testMockS3Option func(m *testMockS3) error
|
||||
@@ -129,6 +158,55 @@ func testMockS3WithHeadObjectError(e error) testMockS3Option {
|
||||
}
|
||||
}
|
||||
|
||||
func testMockS3WithListObjectsV2Output(o *s3.ListObjectsV2Output) testMockS3Option {
|
||||
return func(m *testMockS3) error {
|
||||
m.ListObjectsV2Output = o
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func testMockS3WithListObjectsV2Error(e error) testMockS3Option {
|
||||
return func(m *testMockS3) error {
|
||||
m.ListObjectsV2Err = e
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func testMockS3WithListObjectsV2OutputFunc(o func(*s3.ListObjectsV2Input) *s3.ListObjectsV2Output) testMockS3Option {
|
||||
return func(m *testMockS3) error {
|
||||
m.ListObjectsV2OutputFunc = o
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func testMockS3WithDeleteObjectOutput(o *s3.DeleteObjectOutput) testMockS3Option {
|
||||
return func(m *testMockS3) error {
|
||||
m.DeleteObjectOutput = o
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func testMockS3WithDeleteObjectError(e error) testMockS3Option {
|
||||
return func(m *testMockS3) error {
|
||||
m.DeleteObjectErr = e
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func testMockS3WithDeleteObjectsOutput(o *s3.DeleteObjectsOutput) testMockS3Option {
|
||||
return func(m *testMockS3) error {
|
||||
m.DeleteObjectsOutput = o
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func testMockS3WithDeleteObjectsError(e error) testMockS3Option {
|
||||
return func(m *testMockS3) error {
|
||||
m.DeleteObjectsErr = e
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func newTestMockS3(state *testMockS3State, opts ...testMockS3Option) s3APIFunc {
|
||||
return func(cfgs ...aws.Config) (S3API, error) {
|
||||
m := &testMockS3{
|
||||
@@ -146,9 +224,6 @@ func newTestMockS3(state *testMockS3State, opts ...testMockS3Option) s3APIFunc {
|
||||
if cfg.Region != "" {
|
||||
m.Region = cfg.Region
|
||||
}
|
||||
// if cfg. != nil {
|
||||
// m.Endpoint = cfg.EndpointResolverWithOptions
|
||||
// }
|
||||
}
|
||||
|
||||
return m, nil
|
||||
@@ -196,8 +271,47 @@ func (m *testMockS3) PutObject(ctx context.Context, params *s3.PutObjectInput, o
|
||||
return m.PutObjectOutput, nil
|
||||
}
|
||||
|
||||
func (m *testMockS3) ListObjectsV2(ctx context.Context, params *s3.ListObjectsV2Input, optFns ...func(*s3.Options)) (*s3.ListObjectsV2Output, error) {
|
||||
if m.State != nil {
|
||||
m.State.ListObjectsV2Called = true
|
||||
m.State.ListObjectsV2InputParams = params
|
||||
}
|
||||
|
||||
if m.ListObjectsV2Err != nil {
|
||||
return nil, m.ListObjectsV2Err
|
||||
}
|
||||
|
||||
if m.ListObjectsV2OutputFunc != nil {
|
||||
return m.ListObjectsV2OutputFunc(params), nil
|
||||
}
|
||||
|
||||
return m.ListObjectsV2Output, nil
|
||||
}
|
||||
|
||||
func (m *testMockS3) DeleteObject(ctx context.Context, params *s3.DeleteObjectInput, optFns ...func(*s3.Options)) (*s3.DeleteObjectOutput, error) {
|
||||
return &s3.DeleteObjectOutput{}, nil
|
||||
if m.State != nil {
|
||||
m.State.DeleteObjectCalled = true
|
||||
m.State.DeleteObjectInputParams = params
|
||||
}
|
||||
|
||||
if m.DeleteObjectErr != nil {
|
||||
return nil, m.DeleteObjectErr
|
||||
}
|
||||
|
||||
return m.DeleteObjectOutput, nil
|
||||
}
|
||||
|
||||
func (m *testMockS3) DeleteObjects(ctx context.Context, params *s3.DeleteObjectsInput, optFns ...func(*s3.Options)) (*s3.DeleteObjectsOutput, error) {
|
||||
if m.State != nil {
|
||||
m.State.DeleteObjectsCalled = true
|
||||
m.State.DeleteObjectsInputParams = params
|
||||
}
|
||||
|
||||
if m.DeleteObjectsErr != nil {
|
||||
return nil, m.DeleteObjectsErr
|
||||
}
|
||||
|
||||
return m.DeleteObjectsOutput, nil
|
||||
}
|
||||
|
||||
func (m *testMockS3) HeadObject(ctx context.Context, params *s3.HeadObjectInput, optFns ...func(*s3.Options)) (*s3.HeadObjectOutput, error) {
|
||||
@@ -287,10 +401,10 @@ func deepCopyPutObjectRequest(v *pb.PutObjectRequest) *pb.PutObjectRequest {
|
||||
|
||||
func validSTSMock() []credential.AwsCredentialPersistedStateOption {
|
||||
return []credential.AwsCredentialPersistedStateOption{
|
||||
credential.WithStateTestOpts([]awsutilv2.Option{
|
||||
awsutilv2.WithSTSAPIFunc(
|
||||
awsutilv2.NewMockSTS(
|
||||
awsutilv2.WithGetCallerIdentityOutput(&sts.GetCallerIdentityOutput{
|
||||
credential.WithStateTestOpts([]awsutil.Option{
|
||||
awsutil.WithSTSAPIFunc(
|
||||
awsutil.NewMockSTS(
|
||||
awsutil.WithGetCallerIdentityOutput(&sts.GetCallerIdentityOutput{
|
||||
Account: aws.String("0123456789"),
|
||||
Arn: aws.String("arn:aws:iam::0123456789:user/test"),
|
||||
UserId: aws.String("test"),
|
||||
|
||||
+7
-7
@@ -16,7 +16,7 @@ import (
|
||||
"github.com/aws/smithy-go"
|
||||
"github.com/hashicorp/boundary-plugin-aws/internal/credential"
|
||||
"github.com/hashicorp/boundary-plugin-aws/internal/values"
|
||||
awsutilv2 "github.com/hashicorp/go-secure-stdlib/awsutil"
|
||||
"github.com/hashicorp/go-secure-stdlib/awsutil/v2"
|
||||
tfjson "github.com/hashicorp/terraform-json"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/protobuf/types/known/structpb"
|
||||
@@ -280,9 +280,9 @@ func requireCredentialsInvalid(t *testing.T, accessKeyId, secretAccessKey string
|
||||
t.Helper()
|
||||
require := require.New(t)
|
||||
|
||||
c, err := awsutilv2.NewCredentialsConfig(
|
||||
awsutilv2.WithAccessKey(accessKeyId),
|
||||
awsutilv2.WithSecretKey(secretAccessKey),
|
||||
c, err := awsutil.NewCredentialsConfig(
|
||||
awsutil.WithAccessKey(accessKeyId),
|
||||
awsutil.WithSecretKey(secretAccessKey),
|
||||
)
|
||||
require.NoError(err)
|
||||
|
||||
@@ -317,9 +317,9 @@ func requireCredentialsValid(t *testing.T, accessKeyId, secretAccessKey string)
|
||||
t.Helper()
|
||||
require := require.New(t)
|
||||
|
||||
c, err := awsutilv2.NewCredentialsConfig(
|
||||
awsutilv2.WithAccessKey(accessKeyId),
|
||||
awsutilv2.WithSecretKey(secretAccessKey),
|
||||
c, err := awsutil.NewCredentialsConfig(
|
||||
awsutil.WithAccessKey(accessKeyId),
|
||||
awsutil.WithSecretKey(secretAccessKey),
|
||||
)
|
||||
require.NoError(err)
|
||||
_, err = c.GetCallerIdentity(context.Background())
|
||||
|
||||
Reference in new issue
Block a user