Compare commits

..
Author SHA1 Message Date
Hugo 7d2654e707 feat(storage): Improve error messages
Current `errorToStatus` is not displaying the underlying error if the
status code is 400. Additionally, we are sending the error into this
function twice: Once in the error message and again in the error itself.

This commit changes the way `errorToStatus` works by sending a message
indicating where the error occured and then the actual error as a
different argument. Additionally, it changes `errorToStatus` to always
print the input message and the error regardless of error type.
2024-10-01 15:13:57 +01:00
Hugo 759ac083ac feat(storage): Drop checksum headers
Some non-MinIO services that can use this plugin do not support
`x-amz-checksum-algorithm` and/or `x-amz-checksum-sha256`.

Important to note that if a SHA256 checksum still comes through in the
response, the existing code will verify that it matches what we have
locally.
2024-10-01 15:13:57 +01:00
dani dad21afc00 Large File Support (#21)
* disable multipart puts and add a large file test

* read random bytes rather than generate from string
2024-08-13 15:59:58 -04:00
daniandElim Tsiagbey 589e435ff1 Worker storage bucket credential state (#18)
* feat: parse minio errors and plugin permission

- Evaluate minio errors. If the error is a permission related error, convert the error to a `Permission` proto and attach it to the gRPC status
- Update `dryRun` method to join all errors before returning response. This ensures all the permissions are validated before returning

* refactor errorToStatus to return storage states

* update oncreate and validate errorcodes on failure

* update go.mod for new sdk version

* update tests to parse state instead of permissions

---------

Co-authored-by: Elim Tsiagbey <elim.tsiagbey@hashicorp.com>
2024-07-17 15:37:45 -04:00
Hugo caa6c4eda2 feat(storage): Make checksum verification optional
Some 3rd party services the MinIO SDK can connect
with do not return a checksum whenever a file is
uploaded. Before this change, this would lead to
an error, rendering it impossible to operate with
those 3rd party services. With this change, we'll
continue to verify checksums if they come through,
however we won't error out if they don't and the
PutObject call is successful.

Note: There are no new tests with this change as
this behaviour is not unit-testeable at the
moment. I suggest we could have end-to-end tests
for this.
2024-06-10 16:19:20 +01:00
dani 9299172dd1 move service account validation to only check for service account on credential rotation. should allow other S3-compatible providers (#16) 2024-05-15 11:45:47 -04:00
Danielle Miu 07cb85645b update all vulnerable packages 2024-04-11 22:41:40 -04:00
hashicorp-copywrite[bot] a0067502b9 [COMPLIANCE] Add Copyright and License Headers (#15)
Co-authored-by: hashicorp-copywrite[bot] <110428419+hashicorp-copywrite[bot]@users.noreply.github.com>
2024-04-09 11:17:43 -07:00
Hugo bde78ecccd docs(plugin): Add Credential Rotation attribute and explanation 2024-04-04 18:03:37 +01:00
Hugo eb0c2b4682 feat(plugin): Implement Credential Rotation 2024-04-04 18:03:37 +01:00
Hugo 0214399017 feat(plugin): Add credential rotation primitives 2024-04-04 18:03:37 +01:00
Hugo 2c2bd3429b feat(values): Add methods to get bool and time values from proto 2024-04-04 18:03:37 +01:00
dani 09cece64bc feat(plugin): implement DeleteObjects functionality along with associated automated tests (#14) 2024-04-04 12:19:10 -04:00
9 changed files with 912 additions and 368 deletions

No files matched your search

+14 -12
View File
@@ -1,17 +1,18 @@
module github.com/hashicorp/boundary-plugin-minio
go 1.21.5
go 1.22.2
require (
github.com/google/go-cmp v0.6.0
github.com/google/uuid v1.5.0
github.com/hashicorp/boundary/sdk v0.0.42
github.com/hashicorp/boundary/sdk v0.0.43-0.20240717182311-a20aae98794a
github.com/hashicorp/go-multierror v1.1.1
github.com/minio/madmin-go/v3 v3.0.48
github.com/minio/minio-go/v7 v7.0.67
github.com/ory/dockertest/v3 v3.10.0
github.com/stretchr/testify v1.8.4
google.golang.org/grpc v1.59.0
google.golang.org/protobuf v1.32.0
google.golang.org/grpc v1.61.0
google.golang.org/protobuf v1.33.0
)
require (
@@ -22,7 +23,7 @@ require (
github.com/containerd/continuity v0.3.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/docker/cli v20.10.17+incompatible // indirect
github.com/docker/docker v20.10.7+incompatible // indirect
github.com/docker/docker v24.0.9+incompatible // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.4.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
@@ -35,7 +36,6 @@ require (
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-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/imdario/mergo v0.3.13 // indirect
github.com/json-iterator/go v1.1.12 // indirect
@@ -54,7 +54,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.2 // indirect
github.com/opencontainers/runc v1.1.5 // indirect
github.com/opencontainers/runc v1.1.12 // indirect
github.com/philhofer/fwd v1.1.2 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
@@ -76,14 +76,16 @@ require (
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect
golang.org/x/crypto v0.17.0 // indirect
golang.org/x/crypto v0.22.0 // indirect
golang.org/x/mod v0.9.0 // indirect
golang.org/x/net v0.19.0 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/net v0.24.0 // indirect
golang.org/x/sync v0.5.0 // indirect
golang.org/x/sys v0.19.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/tools v0.7.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b // indirect
google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
+26 -54
View File
@@ -1,6 +1,5 @@
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
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=
@@ -17,24 +16,18 @@ github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQ
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E=
github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA=
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg=
github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM=
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
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/docker/cli v20.10.17+incompatible h1:eO2KS7ZFeov5UJeaDmIs1NFEDRf32PaqRpvoEkKBy5M=
github.com/docker/cli v20.10.17+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/docker v20.10.7+incompatible h1:Z6O9Nhsjv+ayUEeI1IojKbYcsGdgYSNqxe1s2MYzUhQ=
github.com/docker/docker v20.10.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v24.0.9+incompatible h1:HPGzNmwfLZWdxHqK9/II92pyi1EpYKsAqcl4G0Of9v0=
github.com/docker/docker v24.0.9+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
@@ -43,15 +36,12 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
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/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
@@ -73,8 +63,8 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaU
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hashicorp/boundary/sdk v0.0.42 h1:iRDdnM6/6q9qLtBP7/cpq/FWQGf69TFSsBQFxgGK8Jw=
github.com/hashicorp/boundary/sdk v0.0.42/go.mod h1:QJhm4rky2YMtk9DS5Rj8QJhDKB/6zQbVrm3R0QgdYmQ=
github.com/hashicorp/boundary/sdk v0.0.43-0.20240717182311-a20aae98794a h1:SwVze6sYE5o+J9qdcgj29auY1k6O8oSo9DC2+2Gb9rw=
github.com/hashicorp/boundary/sdk v0.0.43-0.20240717182311-a20aae98794a/go.mod h1:9iOT7kDM6mYcSkKxNuZlv8rP7U5BG1kXoevjLLL8lNQ=
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=
@@ -136,9 +126,8 @@ github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/4
github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
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.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
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=
@@ -175,7 +164,6 @@ github.com/mitchellh/pointerstructure v1.2.1 h1:ZhBBeX8tSlRpu/FFhXH4RC4OJzFlqsQh
github.com/mitchellh/pointerstructure v1.2.1/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=
github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 h1:rzf0wL0CHVc8CEsgyygG0Mn9CNCCPZqOPaz8RiiHYQk=
github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -183,17 +171,14 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
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/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/runc v1.1.5 h1:L44KXEpKmfWDcS02aeGm8QNTFXTo2D+8MYGDIJ/GDEs=
github.com/opencontainers/runc v1.1.5/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg=
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
github.com/opencontainers/runc v1.1.12 h1:BOIssBaW1La0/qbNZHXOOa71dZfZEQOzW7dqQf3phss=
github.com/opencontainers/runc v1.1.12/go.mod h1:S+lQwSfncpBha7XTy/5lBwWgm5+y5Ma/O44Ekby9FK8=
github.com/ory/dockertest/v3 v3.10.0 h1:4K3z2VMe8Woe++invjaTB7VRyQXQy5UY+loujO4aNE4=
github.com/ory/dockertest/v3 v3.10.0/go.mod h1:nr57ZbRWMqfsdGdFNLHz5jjNdDb7VVFnzAeW1n5N1Lg=
github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw=
@@ -222,12 +207,10 @@ github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjR
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
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/safchain/ethtool v0.3.0 h1:gimQJpsI6sc1yIqP/y8GYgiXn/NjgvpM0RNoWLVVmP0=
github.com/safchain/ethtool v0.3.0/go.mod h1:SA9BwrgyAqNo7M+uaL6IYbxpm5wk3L7Mm6ocLW+CJUs=
github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
github.com/secure-io/sio-go v0.3.1 h1:dNvY9awjabXTYGsTF1PiCySl9Ltofk9GA3VdWlo7rRc=
github.com/secure-io/sio-go v0.3.1/go.mod h1:+xbkjDzPjwh4Axd07pRKSNriS9SCiYksWnZqdnfpQxs=
github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4=
@@ -238,8 +221,6 @@ github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
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/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
@@ -248,7 +229,6 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
@@ -256,16 +236,12 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/tinylib/msgp v1.1.8 h1:FCXC1xanKO4I8plpHGH2P7koL/RzZs12l/+r7vakfm0=
github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw=
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
@@ -285,8 +261,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
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/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
@@ -302,36 +278,28 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/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-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/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-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -340,8 +308,9 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
@@ -368,15 +337,18 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
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/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/genproto v0.0.0-20240116215550-a9fa1716bcac h1:ZL/Teoy/ZGnzyrqK/Optxxp2pmVh+fmJ97slxSRyzUg=
google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:+Rvu7ElI+aLzyDQhpHMFMMltsD6m7nqpuWDd2CwJw3k=
google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe h1:0poefMBYvYbs7g5UkjS6HcxBPaTRAmznle9jnxYoAI8=
google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe h1:bQnxqljG/wqi4NTXu2+DJ3n7APcEA882QZ1JvhQAq9o=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s=
google.golang.org/grpc v1.61.0 h1:TOvOcuXn30kRao+gfcvsebNEa5iZIiLkisYEkf7R7o0=
google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs=
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.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
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/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+6
View File
@@ -13,6 +13,7 @@ boundary storage-buckets create \
-worker-filter '"minio-access" in "/tags/type"' \
-attr endpoint_url="https://my-minio-instance.dev/s3-api" \
-attr region=REGION \
-attr disable_credential_rotation=true \
-secret access_key_id='KEY' \
-secret secret_access_key='SECRET'
```
@@ -24,6 +25,11 @@ The following `attributes` are valid on a MinIO storage bucket resource:
- `endpoint_url` (string, required): Fully-qualified endpoint pointing to a
MinIO S3 API.
- `region` (string, optional): The region to configure the storage bucket for.
- `disable_credential_rotation` (bool, optional): Controls whether the plugin
will rotate the incoming credentials and manage a new MinIO service account.
If this attribute is set to `false`, or not provided, the plugin will rotate
the incoming credentials, using them to create a new MinIO service account,
then delete the incoming credentials.
### Secrets
+4 -4
View File
@@ -65,11 +65,11 @@ func (sa *StorageSecrets) AsMap() map[string]any {
// Clone returns a new StorageSecrets object with the same state as the incoming
// one.
func (ss *StorageSecrets) Clone() *StorageSecrets {
func (sec *StorageSecrets) Clone() *StorageSecrets {
return &StorageSecrets{
AccessKeyId: ss.AccessKeyId,
SecretAccessKey: ss.SecretAccessKey,
LastRotatedTime: ss.LastRotatedTime,
AccessKeyId: sec.AccessKeyId,
SecretAccessKey: sec.SecretAccessKey,
LastRotatedTime: sec.LastRotatedTime,
}
}
+5 -5
View File
@@ -333,9 +333,9 @@ func TestTestStorageSecretsClone(t *testing.T) {
LastRotatedTime: now,
}
ss := in.Clone()
require.Equal(t, in.AccessKeyId, ss.AccessKeyId)
require.Equal(t, in.AccessKeyId, ss.AccessKeyId)
require.Equal(t, in.LastRotatedTime, ss.LastRotatedTime)
require.NotSame(t, in, ss)
secCl := in.Clone()
require.Equal(t, in.AccessKeyId, secCl.AccessKeyId)
require.Equal(t, in.AccessKeyId, secCl.AccessKeyId)
require.Equal(t, in.LastRotatedTime, secCl.LastRotatedTime)
require.NotSame(t, in, secCl)
}
+259 -66
View File
@@ -19,6 +19,7 @@ import (
"github.com/google/uuid"
"github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/storagebuckets"
pb "github.com/hashicorp/boundary/sdk/pbs/plugin"
"github.com/hashicorp/go-multierror"
madmin "github.com/minio/madmin-go/v3"
"github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/credentials"
@@ -60,11 +61,6 @@ func (sp *StoragePlugin) OnCreateStorageBucket(ctx context.Context, req *pb.OnCr
return nil, err
}
err = ensureServiceAccount(ctx, sa, sec)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "failed to ensure service account: %v", err)
}
deleteOldCredsFn := func() error { return nil }
if !sa.DisableCredentialRotation {
newSec, fn, err := rotateCredentials(ctx, bucket.GetBucketName(), sa, sec)
@@ -84,9 +80,15 @@ func (sp *StoragePlugin) OnCreateStorageBucket(ctx context.Context, req *pb.OnCr
return nil, status.Errorf(codes.Unknown, "failed to create minio sdk client: %v", err)
}
err = dryRun(ctx, cl, bucket)
if err != nil {
return nil, status.Errorf(codes.Unknown, "failed to verify provided minio environment: %v", err)
p, dryRunErr := dryRun(ctx, cl, bucket)
if dryRunErr.Len() > 0 {
st := status.New(codes.InvalidArgument, fmt.Sprintf("failed to verify provided minio environment: %v", dryRunErr.Unwrap()))
st, err = st.WithDetails(&pb.StorageBucketCredentialState{State: p})
if err != nil {
st = status.New(codes.Unknown, fmt.Sprintf("failed to verify provided minio environment: %v", dryRunErr.Unwrap()))
}
return nil, st.Err()
}
persistedData, err := structpb.NewStruct(sec.AsMap())
@@ -178,22 +180,17 @@ func (sp *StoragePlugin) OnUpdateStorageBucket(ctx context.Context, req *pb.OnUp
return nil, err
}
err = ensureServiceAccount(ctx, nsa, newSec)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "failed to ensure service account: %s", err)
}
if !nsa.DisableCredentialRotation {
// We have new incoming credentials and we're also rotating,
// therefore we use incoming credentials to create a new service
// account, then delete the incoming credentials. The existing
// persisted credentials have already been scheduled for deletion
// above (if applicable), so we don't need to do it here.
ss, fn, err := rotateCredentials(ctx, newBucket.GetBucketName(), nsa, newSec)
rotatedSec, fn, err := rotateCredentials(ctx, newBucket.GetBucketName(), nsa, newSec)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "failed to rotate minio credentials: %v", err)
}
sec = ss
sec = rotatedSec
deleteRotatedCredsFn = fn
} else {
// We have new incoming credentials but we're not rotating. Set them
@@ -205,16 +202,8 @@ func (sp *StoragePlugin) OnUpdateStorageBucket(ctx context.Context, req *pb.OnUp
} else {
if osa.DisableCredentialRotation && !nsa.DisableCredentialRotation {
// Handle the case where the user enables credential rotation but
// provides no new credentials. In this case, we use the existing
// persisted credentials to generate a new service account. The
// persisted credentials are, by definition, not being managed by us
// (credential rotation was disabled beforehand), so don't schedule
// them for deletion.
ss, _, err := rotateCredentials(ctx, newBucket.GetBucketName(), nsa, sec)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "failed to rotate minio credentials: %v", err)
}
sec = ss
// provides no new credentials. This is an error.
return nil, status.Errorf(codes.InvalidArgument, "credential rotation enabled with no new credentials provided")
}
}
@@ -227,8 +216,16 @@ func (sp *StoragePlugin) OnUpdateStorageBucket(ctx context.Context, req *pb.OnUp
return nil, status.Errorf(codes.InvalidArgument, "failed to create minio sdk client: %s", err)
}
if err = dryRun(ctx, cl, newBucket); err != nil {
return nil, status.Errorf(codes.InvalidArgument, "failed to verify provided minio environment: %s", err)
if p, dryRunErr := dryRun(ctx, cl, newBucket); dryRunErr != nil {
if dryRunErr.Len() > 0 {
st := status.New(codes.InvalidArgument, fmt.Sprintf("failed to verify provided minio environment: %v", dryRunErr.Unwrap()))
st, err = st.WithDetails(&pb.StorageBucketCredentialState{State: p})
if err != nil {
st = status.New(codes.InvalidArgument, fmt.Sprintf("failed to verify provided minio environment: %v", dryRunErr.Unwrap()))
}
return nil, st.Err()
}
}
persisted, err := structpb.NewStruct(sec.AsMap())
@@ -300,9 +297,13 @@ func (sp *StoragePlugin) ValidatePermissions(ctx context.Context, req *pb.Valida
return nil, err
}
err = ensureServiceAccount(ctx, sa, sec)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "failed to ensure service account: %v", err)
if !sec.LastRotatedTime.IsZero() {
// since these are existing secrets, we only want to validate the
// service account if the credentials have been rotated previously
err = ensureServiceAccount(ctx, sa, sec)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "failed to ensure service account: %v", err)
}
}
cl, err := minio.New(sa.EndpointUrl, &minio.Options{
@@ -314,9 +315,15 @@ func (sp *StoragePlugin) ValidatePermissions(ctx context.Context, req *pb.Valida
return nil, status.Errorf(codes.Unknown, "failed to create minio sdk client: %v", err)
}
err = dryRun(ctx, cl, bucket)
if err != nil {
return nil, status.Errorf(codes.Unknown, "failed to verify provided minio environment: %v", err)
p, dryRunErr := dryRun(ctx, cl, bucket)
if dryRunErr.Unwrap() != nil {
st := status.New(codes.FailedPrecondition, fmt.Sprintf("failed to verify provided minio environment: %v", dryRunErr.Unwrap()))
st, err = st.WithDetails(&pb.StorageBucketCredentialState{State: p})
if err != nil {
st = status.New(codes.Unknown, fmt.Sprintf("failed to verify provided minio environment: %v", dryRunErr.Unwrap()))
}
return nil, st.Err()
}
return &pb.ValidatePermissionsResponse{}, nil
@@ -352,13 +359,13 @@ func (sp *StoragePlugin) HeadObject(ctx context.Context, req *pb.HeadObjectReque
Region: sa.Region,
})
if err != nil {
return nil, status.Errorf(codes.Unknown, "failed to create minio sdk client: %v", err)
return nil, errorToStatus(codes.Unknown, "failed to create minio sdk client", err, req).Err()
}
objKey := path.Join(bucket.GetBucketPrefix(), req.GetKey())
oi, err := cl.StatObject(ctx, bucket.GetBucketName(), objKey, minio.StatObjectOptions{})
if err != nil {
return nil, status.Errorf(codes.Unknown, "failed to stat object: %v", err)
return nil, errorToStatus(codes.Unknown, "failed to stat object", err, req).Err()
}
return &pb.HeadObjectResponse{
@@ -397,13 +404,13 @@ func (sp *StoragePlugin) GetObject(req *pb.GetObjectRequest, objServer pb.Storag
Region: sa.Region,
})
if err != nil {
return status.Errorf(codes.Unknown, "failed to create minio sdk client: %v", err)
return errorToStatus(codes.Unknown, "failed to create minio sdk client", err, req).Err()
}
objKey := path.Join(bucket.GetBucketPrefix(), req.GetKey())
obj, err := cl.GetObject(objServer.Context(), bucket.GetBucketName(), objKey, minio.GetObjectOptions{})
if err != nil {
return status.Errorf(codes.Unknown, "failed to get object: %v", err)
return errorToStatus(codes.Unknown, "failed to get object", err, req).Err()
}
defer obj.Close()
@@ -486,7 +493,7 @@ func (sp *StoragePlugin) PutObject(ctx context.Context, req *pb.PutObjectRequest
Region: sa.Region,
})
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to create minio sdk client: %v", err)
return nil, errorToStatus(codes.Internal, "failed to create minio sdk client", err, req).Err()
}
hash := sha256.New()
@@ -500,23 +507,23 @@ func (sp *StoragePlugin) PutObject(ctx context.Context, req *pb.PutObjectRequest
}
key := path.Join(bucket.GetBucketPrefix(), req.GetKey())
res, err := cl.PutObject(ctx, bucket.GetBucketName(), key, file, info.Size(), minio.PutObjectOptions{
UserMetadata: map[string]string{
"x-amz-checksum-algorithm": "SHA256",
"x-amz-checksum-sha256": checksum,
},
})
res, err := cl.PutObject(ctx, bucket.GetBucketName(), key, file, info.Size(), minio.PutObjectOptions{})
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to put object into minio: %v", err)
return nil, errorToStatus(codes.Internal, "failed to put object into minio", err, req).Err()
}
if res.ChecksumSHA256 == "" {
return nil, status.Error(codes.Internal, "missing checksum response from minio")
resChecksum := res.ChecksumSHA256
if resChecksum == "" {
// We were successful in putting the object but we didn't get a file
// SHA256 checksum from the server. Given that the call was successful,
// assume everything went ok and force the checksum to match so we can
// send it correctly back to Boundary.
resChecksum = checksum
}
if checksum != res.ChecksumSHA256 {
if checksum != resChecksum {
return nil, status.Error(codes.Internal, "mismatched checksum")
}
decodedChecksum, err := base64.StdEncoding.DecodeString(res.ChecksumSHA256)
decodedChecksum, err := base64.StdEncoding.DecodeString(resChecksum)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to decode checksum value from minio: %v", err)
}
@@ -556,7 +563,7 @@ func (sp *StoragePlugin) DeleteObjects(ctx context.Context, req *pb.DeleteObject
Region: sa.Region,
})
if err != nil {
return nil, status.Errorf(codes.Unknown, "failed to create minio sdk client: %v", err)
return nil, errorToStatus(codes.Unknown, "failed to create minio sdk client", err, req).Err()
}
prefix := path.Join(bucket.GetBucketPrefix(), req.GetKeyPrefix())
@@ -568,7 +575,7 @@ func (sp *StoragePlugin) DeleteObjects(ctx context.Context, req *pb.DeleteObject
if !req.Recursive {
if err := cl.RemoveObject(ctx, bucket.GetBucketName(), prefix, minio.RemoveObjectOptions{}); err != nil {
return nil, status.Errorf(codes.Unknown, "error deleting minio object: %v", err)
return nil, errorToStatus(codes.Unknown, "error deleting minio object", err, req).Err()
}
return &pb.DeleteObjectsResponse{
ObjectsDeleted: uint32(1),
@@ -581,8 +588,7 @@ func (sp *StoragePlugin) DeleteObjects(ctx context.Context, req *pb.DeleteObject
Recursive: true,
}) {
if obj.Err != nil {
// check if context cancelled ?
return nil, status.Errorf(codes.Unknown, "error iterating minio bucket contents: %v", err)
return nil, errorToStatus(codes.Unknown, "error iterating minio bucket contents", obj.Err, req).Err()
}
objects = append(objects, obj)
}
@@ -599,8 +605,7 @@ func (sp *StoragePlugin) DeleteObjects(ctx context.Context, req *pb.DeleteObject
removed := 0
for res := range cl.RemoveObjectsWithResult(ctx, bucket.GetBucketName(), emitter, minio.RemoveObjectsOptions{}) {
if res.Err != nil {
// check if context cancelled ?
return nil, status.Errorf(codes.Unknown, "error deleting minio object(s): %v", err)
return nil, errorToStatus(codes.Unknown, "error deleting minio object(s)", res.Err, req).Err()
}
removed++
}
@@ -610,37 +615,145 @@ func (sp *StoragePlugin) DeleteObjects(ctx context.Context, req *pb.DeleteObject
}, nil
}
func dryRun(ctx context.Context, cl *minio.Client, bucket *storagebuckets.StorageBucket) error {
objectKey := path.Join(bucket.GetBucketPrefix(), uuid.New().String())
// validateWritePermission checks if the plugin has write permission for an object.
func validateWritePermission(ctx context.Context, cl *minio.Client, bucket *storagebuckets.StorageBucket, objectKey string) (*pb.Permission, *multierror.Error) {
const op = "storage.validateWritePermission"
var combinedErrors *multierror.Error
if cl == nil {
err := fmt.Errorf("%s: minio client is nil", op)
return &pb.Permission{State: pb.StateType_STATE_TYPE_UNKNOWN, ErrorDetails: err.Error(), CheckedAt: timestamppb.Now()}, multierror.Append(combinedErrors, err)
}
if bucket == nil {
err := fmt.Errorf("%s: storage bucket is nil", op)
return &pb.Permission{State: pb.StateType_STATE_TYPE_UNKNOWN, ErrorDetails: err.Error(), CheckedAt: timestamppb.Now()}, multierror.Append(combinedErrors, err)
}
rd := bytes.NewReader([]byte("hashicorp boundary minio plugin access test"))
_, err := cl.PutObject(ctx, bucket.GetBucketName(), objectKey, rd, rd.Size(), minio.PutObjectOptions{})
if err != nil {
return fmt.Errorf("failed to put object at %q: %w", objectKey, err)
combinedErrors = multierror.Append(combinedErrors, fmt.Errorf("failed to put object at %q: %w", objectKey, err))
return errorToPermission(err), combinedErrors
}
_, err = cl.StatObject(ctx, bucket.GetBucketName(), objectKey, minio.StatObjectOptions{})
return &pb.Permission{State: pb.StateType_STATE_TYPE_OK, CheckedAt: timestamppb.Now()}, nil
}
// validateReadPermission checks if the plugin has read permission for an object.
func validateReadPermission(ctx context.Context, cl *minio.Client, bucket *storagebuckets.StorageBucket, objectKey string) (*pb.Permission, *multierror.Error) {
const op = "storage.validateReadPermission"
var combinedErrors *multierror.Error
if cl == nil {
err := fmt.Errorf("%s: minio client is nil", op)
return &pb.Permission{State: pb.StateType_STATE_TYPE_UNKNOWN, ErrorDetails: err.Error(), CheckedAt: timestamppb.Now()}, multierror.Append(combinedErrors, err)
}
if bucket == nil {
err := fmt.Errorf("%s: storage bucket is nil", op)
return &pb.Permission{State: pb.StateType_STATE_TYPE_UNKNOWN, ErrorDetails: err.Error(), CheckedAt: timestamppb.Now()}, multierror.Append(combinedErrors, err)
}
if objectKey == "" {
err := fmt.Errorf("%s: object key is empty", op)
return &pb.Permission{State: pb.StateType_STATE_TYPE_UNKNOWN, ErrorDetails: err.Error(), CheckedAt: timestamppb.Now()}, multierror.Append(combinedErrors, err)
}
permission := &pb.Permission{State: pb.StateType_STATE_TYPE_OK}
_, err := cl.StatObject(ctx, bucket.GetBucketName(), objectKey, minio.StatObjectOptions{})
if err != nil {
return fmt.Errorf("failed to stat object at %q: %w", objectKey, err)
permission = errorToPermission(err)
combinedErrors = multierror.Append(combinedErrors, fmt.Errorf("failed to stat object at %q: %w", objectKey, err))
}
_, err = cl.GetObject(ctx, bucket.GetBucketName(), objectKey, minio.GetObjectOptions{})
if err != nil {
return fmt.Errorf("failed to get object at %q: %w", objectKey, err)
p := errorToPermission(err)
if permission.GetState() == pb.StateType_STATE_TYPE_OK {
permission = p
} else {
if p != nil && p.GetErrorDetails() != "" {
permission.ErrorDetails = fmt.Sprintf("%s, %s", permission.GetErrorDetails(), p.GetErrorDetails())
}
}
combinedErrors = multierror.Append(combinedErrors, fmt.Errorf("failed to get object at %q: %w", objectKey, err))
}
oiCh := cl.ListObjects(ctx, bucket.GetBucketName(), minio.ListObjectsOptions{Recursive: true})
for oi := range oiCh {
if oi.Err != nil {
return fmt.Errorf("failed to list objects in bucket %q: %w", bucket.GetBucketName(), oi.Err)
if permission.GetState() == pb.StateType_STATE_TYPE_OK {
permission = errorToPermission(oi.Err)
} else {
p := errorToPermission(err)
if p != nil && p.GetErrorDetails() != "" {
permission.ErrorDetails = fmt.Sprintf("%s, %s", permission.GetErrorDetails(), p.GetErrorDetails())
}
}
combinedErrors = multierror.Append(fmt.Errorf("failed to list objects in bucket %q: %w", bucket.GetBucketName(), oi.Err))
}
}
err = cl.RemoveObject(ctx, bucket.GetBucketName(), objectKey, minio.RemoveObjectOptions{})
if err != nil {
return fmt.Errorf("failed to remove object at %q: %w", objectKey, err)
if combinedErrors != nil {
return permission, combinedErrors
}
return nil
permission.CheckedAt = timestamppb.Now()
return permission, nil
}
// validateDeletePermission checks if the plugin has delete permission for an object.
func validateDeletePermission(ctx context.Context, cl *minio.Client, bucket *storagebuckets.StorageBucket, objectKey string) (*pb.Permission, *multierror.Error) {
const op = "storage.validateDeletePermission"
var combinedErrors *multierror.Error
if cl == nil {
err := fmt.Errorf("%s: minio client is nil", op)
combinedErrors = multierror.Append(combinedErrors, err)
return &pb.Permission{State: pb.StateType_STATE_TYPE_UNKNOWN, ErrorDetails: err.Error(), CheckedAt: timestamppb.Now()}, combinedErrors
}
if bucket == nil {
err := fmt.Errorf("%s: storage bucket is nil", op)
combinedErrors = multierror.Append(combinedErrors, err)
return &pb.Permission{State: pb.StateType_STATE_TYPE_UNKNOWN, ErrorDetails: err.Error(), CheckedAt: timestamppb.Now()}, combinedErrors
}
if objectKey == "" {
err := fmt.Errorf("%s: object key is empty", op)
combinedErrors = multierror.Append(combinedErrors, err)
return &pb.Permission{State: pb.StateType_STATE_TYPE_UNKNOWN, ErrorDetails: err.Error(), CheckedAt: timestamppb.Now()}, combinedErrors
}
err := cl.RemoveObject(ctx, bucket.GetBucketName(), objectKey, minio.RemoveObjectOptions{})
if err != nil {
combinedErrors = multierror.Append(combinedErrors, fmt.Errorf("failed to remove object at %q: %w", objectKey, err))
return errorToPermission(err), combinedErrors
}
return &pb.Permission{State: pb.StateType_STATE_TYPE_OK, CheckedAt: timestamppb.Now()}, nil
}
func dryRun(ctx context.Context, cl *minio.Client, bucket *storagebuckets.StorageBucket) (*pb.Permissions, *multierror.Error) {
objectKey := path.Join(bucket.GetBucketPrefix(), uuid.New().String())
permissions := &pb.Permissions{
Write: &pb.Permission{State: pb.StateType_STATE_TYPE_UNKNOWN, CheckedAt: timestamppb.Now()},
Read: &pb.Permission{State: pb.StateType_STATE_TYPE_UNKNOWN, CheckedAt: timestamppb.Now()},
Delete: &pb.Permission{State: pb.StateType_STATE_TYPE_UNKNOWN, CheckedAt: timestamppb.Now()},
}
var combinedErrors *multierror.Error
writePermission, writeErr := validateWritePermission(ctx, cl, bucket, objectKey)
combinedErrors = multierror.Append(combinedErrors, writeErr)
permissions.Write = writePermission
readPermission, readErr := validateReadPermission(ctx, cl, bucket, objectKey)
combinedErrors = multierror.Append(combinedErrors, readErr)
permissions.Read = readPermission
deletePermission, deleteErr := validateDeletePermission(ctx, cl, bucket, objectKey)
combinedErrors = multierror.Append(combinedErrors, deleteErr)
permissions.Delete = deletePermission
return permissions, combinedErrors
}
func newMadminClient(sa *StorageAttributes, sec *StorageSecrets) (*madmin.AdminClient, error) {
@@ -665,3 +778,83 @@ func ensureServiceAccount(ctx context.Context, sa *StorageAttributes, sec *Stora
return nil
}
// errorToPermission converts a MinIO error to a plugin permission.
// errorToPermission only handles a subset of MinIO errors that have to do with
// permissions.
// If the MinIO error is not recognized, it returns a permission with an unknown state.
func errorToPermission(err error) *pb.Permission {
if err == nil {
return &pb.Permission{}
}
errResponse := minio.ToErrorResponse(err)
switch errResponse.Code {
// https://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html#ErrorCodeList
case "AccessDenied":
fallthrough
case "InvalidSecurity":
fallthrough
case "InvalidAccessKeyId":
fallthrough
case "NoSuchBucket":
return &pb.Permission{State: pb.StateType_STATE_TYPE_ERROR, ErrorDetails: errResponse.Error(), CheckedAt: timestamppb.Now()}
case "InvalidObjectState":
fallthrough
default:
return &pb.Permission{State: pb.StateType_STATE_TYPE_UNKNOWN, ErrorDetails: errResponse.Error(), CheckedAt: timestamppb.Now()}
}
}
// errorToStatus converts an error to a gRPC status with the plugin permission
// attached.
// If the permission error is not recognized, a gRPC status will be returned
// with an code and error message passed in.
func errorToStatus(code codes.Code, msg string, err error, req any) *status.Status {
if err == nil {
// If we see this status, it means this function was called with a nil
// err. This is odd and should probably be investigated.
return status.New(code, fmt.Sprintf("%s: no error from storage service provider", msg))
}
errResponse := minio.ToErrorResponse(err)
switch errResponse.Code {
// https://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html#ErrorCodeList
case "RequestTimeout":
return status.New(codes.DeadlineExceeded, fmt.Sprintf("%s: timeout exceeded when communicating with storage service provider", msg))
case "SlowDown":
return status.New(codes.Unavailable, fmt.Sprintf("%s: received a throttling response from storage service provider", msg))
case "BadDigest":
return status.New(codes.Aborted, fmt.Sprintf("%s: storage checksum mismatch", msg))
case "NoSuchBucket":
return status.New(codes.NotFound, fmt.Sprintf("%s: specified storage bucket does not exist", msg))
case "NoSuchKey":
return status.New(codes.NotFound, fmt.Sprintf("%s: specified object does not exist", msg))
}
if errResponse.StatusCode == 400 {
// catch-all for various different bad-request related errors
return status.New(codes.InvalidArgument, fmt.Sprintf("%s: received a bad request response from storage service provider: %v", msg, err))
}
// for all other errors, we can parse as permission state errors
permission := errorToPermission(err)
state := &pb.StorageBucketCredentialState{State: &pb.Permissions{}}
// we can use the request type to determine what kind of response we should return
switch req.(type) {
case pb.HeadObjectRequest, *pb.HeadObjectRequest:
state.State.Read = permission
case pb.GetObjectRequest, *pb.GetObjectRequest:
state.State.Read = permission
case pb.PutObjectRequest, *pb.PutObjectRequest:
state.State.Write = permission
case pb.DeleteObjectsRequest, *pb.DeleteObjectsRequest:
state.State.Delete = permission
}
st, err := status.New(code, fmt.Sprintf("%s: %s", msg, err)).WithDetails(state)
if err != nil {
st = status.New(code, fmt.Sprintf("%s: %s", msg, err))
}
return st
}
File diff suppressed because it is too large. Load diff
+5 -2
View File
@@ -1,3 +1,6 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package storage
import (
@@ -73,9 +76,9 @@ func rotateCredentials(ctx context.Context, bucketName string, sa *StorageAttrib
LastRotatedTime: time.Now(),
}
inCl, newCl := inSec.Clone(), newSec.Clone()
inCl := inSec.Clone()
return newSec, sync.OnceValue(func() error {
ac, err := newMadminClient(sa, newCl)
ac, err := newMadminClient(sa, inCl)
if err != nil {
return fmt.Errorf("failed to create minio admin client: %w", err)
}
+17 -14
View File
@@ -1,3 +1,6 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package storage
import (
@@ -21,13 +24,13 @@ func TestRotateCredentials(t *testing.T) {
tests := []struct {
name string
ss *StorageSecrets
inSec *StorageSecrets
expErrMsg string
credDelErr bool
}{
{
name: "notUsingServiceAccount",
ss: &StorageSecrets{
inSec: &StorageSecrets{
AccessKeyId: server.RootUsername,
SecretAccessKey: server.RootPassword,
},
@@ -35,7 +38,7 @@ func TestRotateCredentials(t *testing.T) {
},
{
name: "addServiceAccountFail",
ss: func() *StorageSecrets {
inSec: func() *StorageSecrets {
creds, err := server.AdminClient.AddServiceAccount(ctx, madmin.AddServiceAccountReq{
Policy: json.RawMessage(`
{
@@ -63,7 +66,7 @@ func TestRotateCredentials(t *testing.T) {
},
{
name: "credentialDeletionFail",
ss: func() *StorageSecrets {
inSec: func() *StorageSecrets {
creds, err := server.AdminClient.AddServiceAccount(ctx, madmin.AddServiceAccountReq{})
require.NoError(t, err)
@@ -76,7 +79,7 @@ func TestRotateCredentials(t *testing.T) {
},
{
name: "success",
ss: func() *StorageSecrets {
inSec: func() *StorageSecrets {
creds, err := server.AdminClient.AddServiceAccount(ctx, madmin.AddServiceAccountReq{})
require.NoError(t, err)
@@ -95,26 +98,26 @@ func TestRotateCredentials(t *testing.T) {
UseSSL: false,
}
ss, delFn, err := rotateCredentials(context.Background(), bucketName, sa, tt.ss)
outSec, delFn, err := rotateCredentials(context.Background(), bucketName, sa, tt.inSec)
if tt.expErrMsg != "" {
require.ErrorContains(t, err, tt.expErrMsg)
require.Nil(t, ss)
require.Nil(t, outSec)
require.Nil(t, delFn)
return
}
require.NoError(t, err)
require.NotNil(t, ss)
require.NotNil(t, outSec)
require.NotNil(t, delFn)
require.NotEqual(t, ss.AccessKeyId, tt.ss.AccessKeyId)
require.NotEqual(t, ss.SecretAccessKey, tt.ss.SecretAccessKey)
require.NotEmpty(t, ss.LastRotatedTime)
require.NotEqual(t, outSec.AccessKeyId, tt.inSec.AccessKeyId)
require.NotEqual(t, outSec.SecretAccessKey, tt.inSec.SecretAccessKey)
require.NotEmpty(t, outSec.LastRotatedTime)
// Ensure old creds still exist since the callback hasn't been
// called. We then make the delete call and finally assert that the
// credential was removed if there was no error when attempting to
// delete.
_, err = server.AdminClient.InfoServiceAccount(ctx, tt.ss.AccessKeyId)
_, err = server.AdminClient.InfoServiceAccount(ctx, tt.inSec.AccessKeyId)
require.NoError(t, err)
if tt.credDelErr {
@@ -122,7 +125,7 @@ func TestRotateCredentials(t *testing.T) {
require.ErrorContains(t, delFn(), "failed to delete minio service account")
require.ErrorContains(t, delFn(), "failed to delete minio service account") // 2nd call should return the same state (due to sync.Once).
_, err := server.AdminClient.InfoServiceAccount(ctx, tt.ss.AccessKeyId)
_, err := server.AdminClient.InfoServiceAccount(ctx, tt.inSec.AccessKeyId)
require.NoError(t, err)
return
} else {
@@ -130,7 +133,7 @@ func TestRotateCredentials(t *testing.T) {
require.NoError(t, delFn()) // 2nd call should return the same state (due to sync.Once).
}
_, err = server.AdminClient.InfoServiceAccount(ctx, tt.ss.AccessKeyId)
_, err = server.AdminClient.InfoServiceAccount(ctx, tt.inSec.AccessKeyId)
require.ErrorContains(t, err, "service account is not found")
})
}