diff --git a/go.mod b/go.mod index b76ebc2ad..5243dd0c4 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/fatih/structs v1.1.0 github.com/favadi/protoc-go-inject-tag v1.3.0 github.com/godbus/dbus/v5 v5.0.6 // indirect - github.com/golang-migrate/migrate/v4 v4.14.1 + github.com/golang-migrate/migrate/v4 v4.15.1 github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe github.com/golang/protobuf v1.5.2 github.com/google/go-cmp v0.5.7 @@ -28,7 +28,7 @@ require ( github.com/hashicorp/go-bexpr v0.1.10 github.com/hashicorp/go-cleanhttp v0.5.2 github.com/hashicorp/go-hclog v1.1.0 - github.com/hashicorp/go-kms-wrapping/v2 v2.0.4 + github.com/hashicorp/go-kms-wrapping/v2 v2.0.5-0.20220321175502-0989a9b6deb1 github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/go-retryablehttp v0.7.0 github.com/hashicorp/go-rootcerts v1.0.2 @@ -83,7 +83,7 @@ require ( nhooyr.io/websocket v1.8.7 ) -require github.com/hashicorp/go-dbw v0.0.0-20211215222256-2ff0d37184ff // this is a branch and should be updated before merging +require github.com/hashicorp/go-dbw v0.0.0-20220412153211-c470aec9369f // this is a branch and should be updated before merging require ( github.com/prometheus/client_golang v1.12.1 @@ -93,12 +93,13 @@ require ( require ( github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/AlecAivazis/survey/v2 v2.2.9 // indirect - github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect + github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect + github.com/DATA-DOG/go-sqlmock v1.5.0 // indirect github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver v1.5.0 // indirect github.com/Masterminds/semver/v3 v3.1.1 // indirect github.com/Masterminds/sprig v2.22.0+incompatible // indirect - github.com/Microsoft/go-winio v0.4.16 // indirect + github.com/Microsoft/go-winio v0.5.0 // indirect github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect github.com/alessio/shellescape v1.4.1 // indirect github.com/apex/log v1.9.0 // indirect @@ -108,14 +109,13 @@ require ( github.com/cenkalti/backoff/v3 v3.0.0 // indirect github.com/cenkalti/backoff/v4 v4.1.0 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect - github.com/containerd/continuity v0.0.0-20200709052629-daa8e1ccc0bc // indirect + github.com/containerd/continuity v0.1.0 // indirect github.com/coreos/go-oidc/v3 v3.0.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect github.com/danieljoos/wincred v1.1.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/dhui/dktest v0.3.4 // indirect github.com/docker/cli v20.10.7+incompatible // indirect - github.com/docker/docker v20.10.7+incompatible // indirect + github.com/docker/docker v20.10.9+incompatible // indirect github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.4.0 // indirect github.com/dvsekhvalnov/jose2go v1.5.0 // indirect @@ -126,6 +126,7 @@ require ( github.com/google/uuid v1.3.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect + github.com/hashicorp/go-kms-wrapping/extras/kms/v2 v2.0.0-20220512190651-85bdcdd684e6 // indirect github.com/hashicorp/go-kms-wrapping/plugin/v2 v2.0.2 // indirect github.com/hashicorp/go-plugin v1.4.3 // indirect github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.1 // indirect @@ -147,30 +148,31 @@ require ( github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.3 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect - github.com/klauspost/compress v1.13.5 // indirect + github.com/klauspost/compress v1.13.6 // indirect github.com/lib/pq v1.10.2 // indirect github.com/mattn/go-isatty v0.0.14 // indirect github.com/mattn/go-sqlite3 v2.0.1+incompatible // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-testing-interface v1.0.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect - github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 // indirect + github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect github.com/mtibben/percent v0.2.1 // indirect github.com/oklog/run v1.0.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.0.1 // indirect - github.com/opencontainers/runc v1.0.0-rc9 // indirect + github.com/opencontainers/runc v1.0.2 // indirect github.com/pierrec/lz4 v2.5.2+incompatible // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/procfs v0.7.3 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect github.com/rogpeppe/go-internal v1.8.1 // indirect github.com/russross/blackfriday/v2 v2.0.1 // indirect github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect - github.com/sirupsen/logrus v1.7.0 // indirect + github.com/sirupsen/logrus v1.8.1 // indirect github.com/urfave/cli/v2 v2.3.0 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect @@ -188,6 +190,14 @@ require ( gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect gorm.io/driver/sqlite v1.2.4 // indirect - gotest.tools/v3 v3.0.3 // indirect + modernc.org/cc/v3 v3.32.4 // indirect + modernc.org/ccgo/v3 v3.9.2 // indirect + modernc.org/libc v1.9.5 // indirect + modernc.org/mathutil v1.2.2 // indirect + modernc.org/memory v1.0.4 // indirect + modernc.org/opt v0.1.1 // indirect + modernc.org/sqlite v1.10.6 // indirect + modernc.org/strutil v1.1.0 // indirect + modernc.org/token v1.0.0 // indirect sigs.k8s.io/yaml v1.3.0 // indirect ) diff --git a/go.sum b/go.sum index a2b2f40f2..71314f498 100644 --- a/go.sum +++ b/go.sum @@ -13,9 +13,16 @@ cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bP cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.63.0/go.mod h1:GmezbQc7T2snqkEXWfZ0sy0VfkB/ivI2DdtJL2DEmlg= -cloud.google.com/go v0.64.0/go.mod h1:xfORb36jGvE+6EexW71nMEtL025s3x6xvuYUKM4JLv4= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= +cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= +cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= +cloud.google.com/go v0.88.0/go.mod h1:dnKwfYbP9hQhefiUvpbcAyoGSHUrOxR20JVElLiUvEY= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -28,22 +35,42 @@ cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2k cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/spanner v1.9.0/go.mod h1:xvlEn0NZ5v1iJPYsBnUVRDNvccDxsBTEi16pJRKQVws= +cloud.google.com/go/spanner v1.24.0/go.mod h1:EZI0yH1D/PrXK0XH9Ba5LGXTXWeqZv0ClOD/19a0Z58= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= github.com/AlecAivazis/survey/v2 v2.2.9 h1:LWvJtUswz/W9/zVVXELrmlvdwWcKE60ZAw0FWV9vssk= github.com/AlecAivazis/survey/v2 v2.2.9/go.mod h1:9DYvHgXtiXm6nCn+jXnOXLKbH+Yo9u8fAS/SduGdoPk= -github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= +github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k= +github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-storage-blob-go v0.14.0/go.mod h1:SMqIBi+SuiQH32bvyjngEewEeXoPfKMgWlBDaYf6fck= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= +github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= +github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= +github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= +github.com/Azure/go-autorest/autorest/adal v0.9.14/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= +github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= +github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/ClickHouse/clickhouse-go v1.3.12/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI= +github.com/ClickHouse/clickhouse-go v1.4.3/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI= +github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= +github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= @@ -55,14 +82,36 @@ github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030I github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60= github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= +github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= -github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= +github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.5.0 h1:Elr9Wn+sGKPlkaBvwu4mTrxtmOp3F3yV9qhaHbXGjwU= +github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= +github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= +github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= +github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8= +github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= +github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= +github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= +github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= +github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= +github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= +github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= +github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -71,22 +120,54 @@ github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk5 github.com/alessio/shellescape v1.4.1 h1:V7yhSDDn8LP4lc4jS8pFkt0zCnzVJlG5JXy9BVKJUX0= github.com/alessio/shellescape v1.4.1/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30= github.com/alexbrainman/sspi v0.0.0-20180613141037-e580b900e9f5/go.mod h1:976q2ETgjT2snVCf2ZaBnyBbVoPERGjUz+0sofzEfro= +github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/apache/arrow/go/arrow v0.0.0-20200601151325-b2287a20f230/go.mod h1:QNYViu/X0HXDHw7m3KXzWSVXIbfUvJqBFe6Gj8/pYA0= +github.com/apache/arrow/go/arrow v0.0.0-20210818145353-234c94e4ce64/go.mod h1:2qMFB56yOP3KzkB3PbYZ4AlUFg3a88F67TIx5lB/WwY= +github.com/apache/arrow/go/arrow v0.0.0-20211013220434-5962184e7a30/go.mod h1:Q7yQnSMnLvcXlZ8RV+jwz/6y1rQTqbX6C82SndT52Zs= github.com/apex/log v1.9.0 h1:FHtw/xuaM8AgmvDDTI9fiwoAL25Sq2cxojnZICUU8l0= github.com/apex/log v1.9.0/go.mod h1:m82fZlWIuiWzWP04XCTXmnX0xRkYYbCdYn8jbJeLBEA= github.com/apex/logs v1.0.0/go.mod h1:XzxuLZ5myVHDy9SAmYpamKKRNApGj54PfYLcFrXqDwo= github.com/aphistic/golf v0.0.0-20180712155816-02c07f170c5a/go.mod h1:3NqKYiepwy8kCu4PNA+aP7WUV72eXWJeP9/r3/K9aLE= github.com/aphistic/sweet v0.2.0/go.mod h1:fWDlIh/isSE9n6EPsRmC0det+whmX6dJid3stzu0Xys= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-metrics v0.3.9 h1:O2sNqxBdvq8Eq5xmzljcYzAORli6RWCvEym4cJf9m18= github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= 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/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go-v2 v1.8.0/go.mod h1:xEFuWz+3TYdlPRuo+CqATbeDWIWyaT5uAPwPaWtgse0= +github.com/aws/aws-sdk-go-v2 v1.9.2/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4= +github.com/aws/aws-sdk-go-v2/config v1.6.0/go.mod h1:TNtBVmka80lRPk5+S9ZqVfFszOQAGJJ9KbT3EM3CHNU= +github.com/aws/aws-sdk-go-v2/config v1.8.3/go.mod h1:4AEiLtAb8kLs7vgw2ZV3p2VZ1+hBavOc84hqxVNpCyw= +github.com/aws/aws-sdk-go-v2/credentials v1.3.2/go.mod h1:PACKuTJdt6AlXvEq8rFI4eDmoqDFC5DpVKQbWysaDgM= +github.com/aws/aws-sdk-go-v2/credentials v1.4.3/go.mod h1:FNNC6nQZQUuyhq5aE5c7ata8o9e4ECGmS4lAXC7o1mQ= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.4.0/go.mod h1:Mj/U8OpDbcVcoctrYwA2bak8k/HFPdcLzI/vaiXMwuM= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.6.0/go.mod h1:gqlclDEZp4aqJOancXK6TN24aKhT0W0Ae9MHk3wzTMM= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.4.0/go.mod h1:eHwXu2+uE/T6gpnYWwBwqoeqRf9IXyCcolyOWDRAErQ= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.5.4/go.mod h1:Ex7XQmbFmgFHrjUX6TN3mApKW5Hglyga+F7wZHTtYhA= +github.com/aws/aws-sdk-go-v2/internal/ini v1.2.0/go.mod h1:Q5jATQc+f1MfZp3PDMhn6ry18hGvE0i8yvbXoKbnZaE= +github.com/aws/aws-sdk-go-v2/internal/ini v1.2.4/go.mod h1:ZcBrrI3zBKlhGFNYWvju0I3TR93I7YIgAfy82Fh4lcQ= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.2.2/go.mod h1:EASdTcM1lGhUe1/p4gkojHwlGJkeoRjjr1sRCzup3Is= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.3.0/go.mod h1:v8ygadNyATSm6elwJ/4gzJwcFhri9RqS8skgHKiwXPU= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.2.2/go.mod h1:NXmNI41bdEsJMrD0v9rUvbGCB5GwdBEpKvUvIY3vTFg= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.3.2/go.mod h1:72HRZDLMtmVQiLG2tLfQcaWLCssELvGl+Zf2WVxMmR8= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.5.2/go.mod h1:QuL2Ym8BkrLmN4lUofXYq6000/i5jPjosCNK//t6gak= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.7.2/go.mod h1:np7TMuJNT83O0oDOSF8i4dF3dvGqA6hPYYo6YYkzgRA= +github.com/aws/aws-sdk-go-v2/service/s3 v1.12.0/go.mod h1:6J++A5xpo7QDsIeSqPK4UHqMSyPOCopa+zKtqAMhqVQ= +github.com/aws/aws-sdk-go-v2/service/s3 v1.16.1/go.mod h1:CQe/KvWV1AqRc65KqeJjrLzr5X2ijnFTTVzJW0VBRCI= +github.com/aws/aws-sdk-go-v2/service/sso v1.3.2/go.mod h1:J21I6kF+d/6XHVk7kp/cx9YVD2TMD2TbLwtRGVcinXo= +github.com/aws/aws-sdk-go-v2/service/sso v1.4.2/go.mod h1:NBvT9R1MEF+Ud6ApJKM0G+IkPchKS7p7c2YPKwHmBOk= +github.com/aws/aws-sdk-go-v2/service/sts v1.6.1/go.mod h1:hLZ/AnkIKHLuPGjEiyghNEdvJ2PP0MgOxcmv9EBJ4xs= +github.com/aws/aws-sdk-go-v2/service/sts v1.7.2/go.mod h1:8EzeIqfWt2wWT4rJVu3f21TfrhJ8AEMzVybRNSb/b4g= +github.com/aws/smithy-go v1.7.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= +github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= +github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -94,45 +175,158 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k= +github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= +github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/bkaradzic/go-lz4 v1.0.0/go.mod h1:0YdlkowM3VswSROI7qDxhRvJ3sLhlFrRRwjwegp5jy4= +github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= +github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= +github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= +github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= +github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= +github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c= github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= github.com/cenkalti/backoff/v4 v4.0.2/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg= github.com/cenkalti/backoff/v4 v4.1.0 h1:c8LkOFQTzuO0WBM/ae5HdGQuZPfPxp7lqBRwQRm4fSc= github.com/cenkalti/backoff/v4 v4.1.0/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= +github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg= +github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc= +github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= +github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= +github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= -github.com/cockroachdb/cockroach-go v0.0.0-20190925194419-606b3d062051/go.mod h1:XGLbWH/ujMcbPbhZq52Nv6UrCghb1yGn//133kEsvDk= -github.com/containerd/containerd v1.4.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/cockroachdb/cockroach-go/v2 v2.1.1/go.mod h1:7NtUnP6eK+l6k483WSYNrq3Kb23bWV10IRV1TyeSpwM= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= +github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU= +github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= +github.com/containerd/aufs v1.0.0/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= +github.com/containerd/btrfs v0.0.0-20201111183144-404b9149801e/go.mod h1:jg2QkJcsabfHugurUvvPhS3E08Oxiuh5W/g1ybB4e0E= +github.com/containerd/btrfs v0.0.0-20210316141732-918d888fb676/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= +github.com/containerd/btrfs v1.0.0/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= +github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI= +github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= +github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM= +github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= +github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= +github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= +github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU= +github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= +github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= +github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= +github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= +github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= +github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.1-0.20191213020239-082f7e3aed57/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.3 h1:ijQT13JedHSHrQGWFcGEwzcNKrAGIiZ+jSD5QQG07SY= github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7V960Tmcumvqn8Mc+pCYQ= +github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU= +github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI= +github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s= +github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g= +github.com/containerd/containerd v1.5.7 h1:rQyoYtj4KddB3bxG6SAqd4+08gePNyJjRqvOIfV3rkM= +github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c= +github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20200413184840-d3ef23f19fbb/go.mod h1:Dq467ZllaHgAtVp4p1xUQWBrFXR9s/wyoTpG8zOJGkY= -github.com/containerd/continuity v0.0.0-20200709052629-daa8e1ccc0bc h1:lDK/G7OlwUnJW3O6nv/8M89bMupV6FuLK6FXmC3ueWc= -github.com/containerd/continuity v0.0.0-20200709052629-daa8e1ccc0bc/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= +github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= +github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= +github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ= +github.com/containerd/continuity v0.1.0 h1:UFRRY5JemiAhPZrr/uE0n8fMTLcZsUvySPr1+D7pgr8= +github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= +github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= +github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= +github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= +github.com/containerd/fifo v0.0.0-20201026212402-0724c46b320c/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= +github.com/containerd/fifo v0.0.0-20210316144830-115abcc95a1d/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= +github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= +github.com/containerd/go-cni v1.0.1/go.mod h1:+vUpYxKvAF72G9i1WoDOiPGRtQpqsNW/ZHtSlv++smU= +github.com/containerd/go-cni v1.0.2/go.mod h1:nrNABBHzu0ZwCug9Ije8hL2xBCYh/pjfMb1aZGrrohk= +github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= +github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= +github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328/go.mod h1:PpyHrqVs8FTi9vpyHwPwiNEGaACDxT/N/pLcvMSRA9g= +github.com/containerd/go-runc v0.0.0-20201020171139-16b287bc67d0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= +github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= +github.com/containerd/imgcrypt v1.0.1/go.mod h1:mdd8cEPW7TPgNG4FpuP3sGBiQ7Yi/zak9TYCG3juvb0= +github.com/containerd/imgcrypt v1.0.4-0.20210301171431-0ae5c75f59ba/go.mod h1:6TNsg0ctmizkrOgXRNQjAPFWpMYRWuiB6dSF4Pfa5SA= +github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow= +github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms= +github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c= +github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= +github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= +github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= +github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= +github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8= +github.com/containerd/ttrpc v1.0.1/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= +github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= +github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= +github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk= +github.com/containerd/typeurl v1.0.1/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg= +github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s= +github.com/containerd/zfs v0.0.0-20200918131355-0a33824f23a2/go.mod h1:8IgZOBdv8fAgXddBT4dBXJPtxyRsejFIpXoklgxgEjw= +github.com/containerd/zfs v0.0.0-20210301145711-11e8f1707f62/go.mod h1:A9zfAbMlQwE+/is6hi0Xw8ktpL+6glmqZYtevJgaB8Y= +github.com/containerd/zfs v0.0.0-20210315114300-dde8f0fda960/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= +github.com/containerd/zfs v0.0.0-20210324211415-d5c4544f0433/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= +github.com/containerd/zfs v1.0.0/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= +github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM= +github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8= +github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc= +github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgUV4GP9qXPfu4= +github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= +github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= +github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-oidc/v3 v3.0.0 h1:/mAA0XMgYJw2Uqm7WKGCsKnjitE/+A0FFbOmiRJm7LQ= github.com/coreos/go-oidc/v3 v3.0.0/go.mod h1:rEJ/idjfUyfkBit1eI1fvyr+64/g9dcKpAm8MJMesvo= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= +github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= @@ -140,7 +334,12 @@ github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7Do 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.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= github.com/cznic/mathutil v0.0.0-20180504122225-ca4c9f2c1369/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM= +github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ= +github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s= +github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8= +github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I= github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7hqDjlFjiygg= github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= @@ -148,36 +347,55 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs 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/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= -github.com/denisenkom/go-mssqldb v0.0.0-20200620013148-b91950f658ec h1:NfhRXXFDPxcF5Cwo06DzeIaE7uuJtAUhsDwH3LNsjos= -github.com/denisenkom/go-mssqldb v0.0.0-20200620013148-b91950f658ec/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= +github.com/denisenkom/go-mssqldb v0.10.0 h1:QykgLZBorFE95+gO3u9esLd0BmbvpWp0/waNNZfHBM8= +github.com/denisenkom/go-mssqldb v0.10.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= +github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= +github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dhui/dktest v0.3.3/go.mod h1:EML9sP4sqJELHn4jV7B0TY8oF6077nk83/tz7M56jcQ= -github.com/dhui/dktest v0.3.4 h1:VbUEcaSP+U2/yUr9d2JhSThXYEnDlGabRSHe2rIE46E= -github.com/dhui/dktest v0.3.4/go.mod h1:4m4n6lmXlmVfESth7mzdcv8nBI5mOb5UROPqjM02csU= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dhui/dktest v0.3.7 h1:jWjWgHAPDAdqgUr7lAsB3bqB2DKWC3OaA+isfekjRew= +github.com/dhui/dktest v0.3.7/go.mod h1:nYMOkafiA07WchSwKnKFUSbGMb2hMm5DrCGiXYG6gwM= +github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/docker/cli v20.10.7+incompatible h1:pv/3NqibQKphWZiAskMzdz8w0PRbtTaEB+f6NwdU7Is= github.com/docker/cli v20.10.7+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= +github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v17.12.0-ce-rc1.0.20200618181300-9dc6525e6118+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v17.12.0-ce-rc1.0.20210128214336-420b1d36250f+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -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 v20.10.9+incompatible h1:JlsVnETOjM2RLQa0Cc1XCIspUdXW3Zenq9P54uXBm6k= +github.com/docker/docker v20.10.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-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= +github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= +github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= +github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= +github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dvsekhvalnov/jose2go v1.5.0 h1:3j8ya4Z4kMCwT5nXIKFSV84YS+HdqSSO0VsTQxaLAeM= github.com/dvsekhvalnov/jose2go v1.5.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= +github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.5.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= @@ -188,28 +406,54 @@ github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/favadi/protoc-go-inject-tag v1.3.0 h1:JPrmsmc/uBShG85uY5xGZIa5WJ0IaNZn6LZhQR9tIQE= github.com/favadi/protoc-go-inject-tag v1.3.0/go.mod h1:SSkUBgfqw2IJ2p7NPNKWk0Idwxt/qIt2LQgFPUgRGtc= +github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/form3tech-oss/jwt-go v3.2.5+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/frankban/quicktest v1.10.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y= +github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/frankban/quicktest v1.13.0/go.mod h1:qLE0fzW0VuyUAJgPU19zByoIr0HtCHN/r/VLSOOIySU= github.com/frankban/quicktest v1.14.2 h1:SPb1KFFmM+ybpEjPUhCCkZOM5xlovT5UbrMvWnXyBns= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsouza/fake-gcs-server v1.17.0/go.mod h1:D1rTE4YCyHFNa99oyJJ5HyclvN/0uQR+pM/VdlL83bw= +github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= +github.com/gabriel-vasile/mimetype v1.3.1/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmxRtOJlERCzSmRvr8= +github.com/gabriel-vasile/mimetype v1.4.0/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmxRtOJlERCzSmRvr8= +github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= +github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= +github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= +github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= +github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= +github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U= github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc= github.com/go-ldap/ldap/v3 v3.1.10/go.mod h1:5Zun81jBTabRaI8lzN7E1JjyEl1g6zI6u9pd8luAK4Q= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= +github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= +github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= +github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= +github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= @@ -226,30 +470,67 @@ github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr6 github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= 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/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= +github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= +github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg= +github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= +github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= +github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs= +github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= +github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= +github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk= +github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28= +github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo= +github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk= +github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw= +github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360= +github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg= +github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE= github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM= +github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8= +github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= +github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= +github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= +github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= +github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= +github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= +github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= -github.com/gocql/gocql v0.0.0-20190301043612-f6df8288f9b4/go.mod h1:4Fw1eo5iaEhDUs8XyuhSVCVy52Jq3L+/3GJgYkwc+/0= +github.com/gocql/gocql v0.0.0-20210515062232-b7ef815b4556/go.mod h1:DL0ekTmBSTdlNF25Orwt/JMzqIq3EJ4MVa/J/uK64OY= +github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= +github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= +github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= +github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.6 h1:mkgN1ofwASrYnJ5W6U/BxG15eXXXjirgZc7CLqkcaro= github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= +github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-migrate/migrate/v4 v4.14.1 h1:qmRd/rNGjM1r3Ve5gHd5ZplytrD02UcItYNxJ3iUHHE= -github.com/golang-migrate/migrate/v4 v4.14.1/go.mod h1:l7Ks0Au6fYHuUIxUhQ0rcVX1uLlJg54C/VvW7tvxSz0= +github.com/golang-migrate/migrate/v4 v4.15.1 h1:Sakl3Nm6+wQKq0Q62tpFMi5a503bgGhceo2icrgQ9vM= +github.com/golang-migrate/migrate/v4 v4.15.1/go.mod h1:/CrBenUbcDqsW29jGTR/XFqCfVi/Y6mHXlooCcSOJMQ= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -260,6 +541,8 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.0.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -276,15 +559,17 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= 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/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/flatbuffers v1.11.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/flatbuffers v2.0.0+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -292,15 +577,21 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 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.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= +github.com/google/go-github/v35 v35.2.0/go.mod h1:s0515YVTI+IMrDoy9Y4pHt9ShGpzHvHO8rZ7L7acgvs= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -308,26 +599,46 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210715191844-86eeefc3e471/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 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/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= -github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= -github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.10.0 h1:ESEyqQqXXFIcImj/BE8oKEX37Zsuceb2cZI+EL/zNCY= github.com/grpc-ecosystem/grpc-gateway/v2 v2.10.0/go.mod h1:XnLCLFp3tjoZJszVKjfpyAK6J8sYIcQXWQxmqLWF21I= @@ -338,6 +649,7 @@ github.com/hashicorp/dawdle v0.4.0 h1:nAE+aCoAmVulgCPPPrp6oGOykjPhxEe4VUNms/mTKe github.com/hashicorp/dawdle v0.4.0/go.mod h1:gOBY8rFXpW4Rw39up1FIacw/1pG/fO779LfchCY3KUw= github.com/hashicorp/dbassert v0.0.0-20210708202608-ecf920cf1ed8 h1:/3iubtqEdLgdXB6ue+WAKvbcpn313jjL5mQvU5ByymE= github.com/hashicorp/dbassert v0.0.0-20210708202608-ecf920cf1ed8/go.mod h1:+B5eZq7vXqN4Gxkgjm4ub1bwG6OTcYzFL0r+bMvWorg= +github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 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= @@ -351,8 +663,10 @@ github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= 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-dbw v0.0.0-20211215222256-2ff0d37184ff h1:jUa73mulKrSJaWD5AVpsvhWgoCCQy5NeGJdZrXggga8= -github.com/hashicorp/go-dbw v0.0.0-20211215222256-2ff0d37184ff/go.mod h1:oh0okaxgqjJMPBSav3mSYPmyEbW7bVWQvRvkwJaQiIg= +github.com/hashicorp/go-dbw v0.0.0-20220409193558-ba55a31040a1 h1:G3tzu6oK/wVrw9ioQvZ1iRAEDQAOEaxBVumy5sF8xRM= +github.com/hashicorp/go-dbw v0.0.0-20220409193558-ba55a31040a1/go.mod h1:w9gD0GS/RPaf1BQ//LmdWfQpW8SFwamwL1hmtzQ58p0= +github.com/hashicorp/go-dbw v0.0.0-20220412153211-c470aec9369f h1:W9IOXASfpDhDY/msdD15bc92IhRVehphYcbVyxYxUUk= +github.com/hashicorp/go-dbw v0.0.0-20220412153211-c470aec9369f/go.mod h1:w9gD0GS/RPaf1BQ//LmdWfQpW8SFwamwL1hmtzQ58p0= github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI= github.com/hashicorp/go-hclog v0.8.0/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= @@ -365,10 +679,13 @@ github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjh github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-kms-wrapping/entropy v0.1.0/go.mod h1:d1g9WGtAunDNpek8jUIEJnBlbgKS1N2Q61QkHiZyR1g= +github.com/hashicorp/go-kms-wrapping/extras/kms/v2 v2.0.0-20220512190651-85bdcdd684e6 h1:3BknAN8P8326GPQac8e3iM132lwtwkO/3OilBU67S1I= +github.com/hashicorp/go-kms-wrapping/extras/kms/v2 v2.0.0-20220512190651-85bdcdd684e6/go.mod h1:TzFKcCsMKyMwFiMfH2MfO8SXqsFQLxzR7Z8JZiGzpK4= github.com/hashicorp/go-kms-wrapping/plugin/v2 v2.0.2 h1:it114Kjpk79JVh6AfxFMP5oi1gb+RPzcSLiG3zF/J0w= github.com/hashicorp/go-kms-wrapping/plugin/v2 v2.0.2/go.mod h1:b9mq0bG5xJ10ZcTEQJLZ22O9y71hIt2MGTLqROA/SAM= -github.com/hashicorp/go-kms-wrapping/v2 v2.0.4 h1:7BSAm60AqJom/TRb73wmaCzwco9A+Qolr/wCi0PORmY= -github.com/hashicorp/go-kms-wrapping/v2 v2.0.4/go.mod h1:sDQAfwJGv25uGPZA04x87ERglCG6avnRcBT9wYoMII8= +github.com/hashicorp/go-kms-wrapping/v2 v2.0.5-0.20220321175502-0989a9b6deb1 h1:UFHzbA/voyzrVfxvm83LW6Hq2gd43F0mgchFnqrinjA= +github.com/hashicorp/go-kms-wrapping/v2 v2.0.5-0.20220321175502-0989a9b6deb1/go.mod h1:sDQAfwJGv25uGPZA04x87ERglCG6avnRcBT9wYoMII8= +github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= @@ -441,10 +758,15 @@ github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= @@ -452,13 +774,16 @@ github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgO github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= -github.com/jackc/pgconn v1.3.2/go.mod h1:LvCquS3HbBKwgl7KbX9KyqEIumJAbm1UMcTvGaIf3bM= +github.com/jackc/pgconn v1.4.0/go.mod h1:Y2O3ZDF0q4mMacyWV3AstPJpeHXWGEetiFttmq5lahk= +github.com/jackc/pgconn v1.5.0/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= +github.com/jackc/pgconn v1.5.1-0.20200601181101-fa742c524853/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= github.com/jackc/pgconn v1.10.0/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= github.com/jackc/pgconn v1.10.1 h1:DzdIHIjG1AxGwoEEqS+mGsURyjt4enSmqzACXvVzOT8= github.com/jackc/pgconn v1.10.1/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= +github.com/jackc/pgerrcode v0.0.0-20201024163028-a0d42d470451/go.mod h1:a/s9Lp5W7n/DD0VrVoyJ00FbP2ytTPDVOivvn2bMlds= github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= @@ -474,14 +799,20 @@ github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvW github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.0.7/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgproto3/v2 v2.2.0 h1:r7JypeP2D3onoQTCxWdTpCtJ4D+qpKr0TxvoyMhZ5ns= github.com/jackc/pgproto3/v2 v2.2.0/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= +github.com/jackc/pgtype v1.2.0/go.mod h1:5m2OfMh1wTK7x+Fk952IDmI4nw3nPrvtQdM0ZT4WpC0= +github.com/jackc/pgtype v1.3.1-0.20200510190516-8cd94a14c75a/go.mod h1:vaogEUkALtxZMCH411K+tKzNpwzCKU+AnPzBKZ+I+Po= +github.com/jackc/pgtype v1.3.1-0.20200606141011-f6355165a91c/go.mod h1:cvk9Bgu/VzJ9/lxTO5R5sf80p0DiucVtN7ZxvaC4GmQ= +github.com/jackc/pgtype v1.6.2/go.mod h1:JCULISAZBFGrHaOXIIFiyfzW5VY0GRitRr8NeJsrdig= github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= github.com/jackc/pgtype v1.8.1/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= github.com/jackc/pgtype v1.9.0 h1:/SH1RxEtltvJgsDqp3TbiTFApD3mey3iygpuEGeuBXk= @@ -489,12 +820,18 @@ github.com/jackc/pgtype v1.9.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76I github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= +github.com/jackc/pgx/v4 v4.5.0/go.mod h1:EpAKPLdnTorwmPUUsqrPxy5fphV18j9q3wrfRXgo+kA= +github.com/jackc/pgx/v4 v4.6.1-0.20200510190926-94ba730bb1e9/go.mod h1:t3/cdRQl6fOLDxqtlyhe9UWgfIi9R8+8v8GKV5TRA/o= +github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904/go.mod h1:ZDaNWkt9sW1JMiNn0kdYBaLelIhw7Pg4qd+Vk6tw7Hg= +github.com/jackc/pgx/v4 v4.10.1/go.mod h1:QlrWebbs3kqEZPHCTGyxecvzG6tvIsYu+A5b1raylkA= github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= github.com/jackc/pgx/v4 v4.13.0/go.mod h1:9P4X524sErlaxj0XSGZk7s+LD0eOyu1ZDUrrpznYDF0= github.com/jackc/pgx/v4 v4.14.0 h1:TgdrmgnM7VY72EuSQzBbBd4JA1RLqJolrw9nQVZABVc= github.com/jackc/pgx/v4 v4.14.0/go.mod h1:jT3ibf/A0ZVCp89rtCIN0zCJxcE74ypROmHEZYsG/j8= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.2.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs= @@ -517,14 +854,23 @@ github.com/jinzhu/gorm v1.9.12/go.mod h1:vhTjlKSJUTWNtcbQtrMBFCxy7eXTzeCAzfL5fBZ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.3 h1:PlHq1bSCSZL9K0wUhbm2pGLoTWs2GwVhsP6emvGV/ZI= github.com/jinzhu/now v1.1.3/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= +github.com/jmoiron/sqlx v1.3.1/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ= +github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7/go.mod h1:2iMrUgbbvHEiQClaW2NsSzMyGHqN+rDFqY705q49KG0= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -532,19 +878,30 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= github.com/k0kubun/pp v2.3.0+incompatible/go.mod h1:GWse8YhT0p8pT4ir3ZgBbfZild3tgzSScAn6HmfYukg= github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= +github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= +github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.13.5 h1:9O69jUPDcsT9fEm74W92rZL9FQY7rCdaXVneq+yyzl4= -github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.13.1/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -556,6 +913,7 @@ 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/pty v1.1.4/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/pty v1.1.8 h1:AkaSdXYQOWeaO3neb8EM634ahkXXe3jYbVh/F9lq+GI= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= @@ -569,11 +927,20 @@ github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.6.0/go.mod h1:4vXEAYvW1fRQ2/FhZ78H73A60MHw1geSm145z2mdY1g= github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= +github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= github.com/markbates/pkger v0.15.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI= +github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= +github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= @@ -583,24 +950,32 @@ github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-ieproxy v0.0.1/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/gNWuh88E= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= -github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v2.0.1+incompatible h1:xQ15muvnzGBHpIpdrNi1DA5x0+TcBZzsIDwmw9uTHzw= github.com/mattn/go-sqlite3 v2.0.1+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= -github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= +github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/cli v1.1.2 h1:PvH+lL2B7IQ101xQL63Of8yFS2y+aDlsFcsqNc+u/Kw= github.com/mitchellh/cli v1.1.2/go.mod h1:6iaV0fGdElS6dPBx0EApTxHrcWvmJphyh2n8YBLPPZ4= @@ -620,13 +995,20 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.2 h1:6h7AQ0yhTcIsmFmnAwQls75jp2Gzs4iB8W7pjMO+rqo= github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 h1:rzf0wL0CHVc8CEsgyygG0Mn9CNCCPZqOPaz8RiiHYQk= +github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= +github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= +github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= +github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= +github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= +github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 h1:dcztxKSvZ4Id8iPpHERQBbIJfabdt4wUm5qy3wOL2Zc= +github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -634,49 +1016,92 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 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/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= +github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mutecomm/go-sqlcipher/v4 v4.4.0/go.mod h1:PyN04SaWalavxRGH9E8ZftG6Ju7rsPrGmQRjrEaVpiY= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/nakagami/firebirdsql v0.0.0-20190310045651-3c02a58cfed8/go.mod h1:86wM1zFnC6/uDBfZGNwB65O+pR2OFi5q/YQaEUid1qA= +github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= github.com/neo4j/neo4j-go-driver v1.8.1-0.20200803113522-b626aa943eba/go.mod h1:ncO5VaFWh0Nrt+4KT4mOZboaczBZcLuHrG+/sUeP8gI= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/oligot/go-mod-upgrade v0.6.1 h1:AZnCiEAOxOMxpKZWjFWFNm/i6QjZVBozuKjuB8EzRCk= github.com/oligot/go-mod-upgrade v0.6.1/go.mod h1:5Gyau3jUXqXrGhYxGkGqrxxgR90Lzd1yt/9YQp9sn1w= +github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= +github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= +github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v1.0.0-rc1.0.20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= 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.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/runc v1.0.0-rc9 h1:/k06BMULKF5hidyoZymkoDCzdJzltZpz/UU4LguQVtc= +github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0= +github.com/opencontainers/runc v1.0.2 h1:opHZMaswlyxz1OuGpBE53Dwe4/xF7EZTY0A2L/FpCOg= +github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= +github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= +github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= +github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= +github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/ory/dockertest/v3 v3.6.0/go.mod h1:4ZOpj8qBUmh8fcBSVzkH2bws2s91JdGvHUqan4GHEuQ= github.com/ory/dockertest/v3 v3.7.0 h1:Bijzonc69Ont3OU0a3TWKJ1Rzlh3TsDXP1JrTAkSmsM= github.com/ory/dockertest/v3 v3.7.0/go.mod h1:PvCCgnP7AfBZeVrzwiUTjZx/IUXlGLC1zQlUQrLIlUE= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= +github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= +github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4 v2.5.2+incompatible h1:WCjObylUIOlKy/+7Abdn34TLIkXiA4UWUMhxq9m9ZXI= github.com/pierrec/lz4 v2.5.2+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pierrec/lz4/v4 v4.1.8/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pires/go-proxyproto v0.6.1 h1:EBupykFmo22SDjv4fQVQd2J9NOoLPmyZA/15ldOGkPw= github.com/pires/go-proxyproto v0.6.1/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY= -github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA= +github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -689,34 +1114,55 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= 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/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= +github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/remyoudompheng/bigfft v0.0.0-20190728182440-6a916e37a237/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.6.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= @@ -727,36 +1173,58 @@ github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OK github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= 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.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= +github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= +github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM= +github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/gunit v1.0.0/go.mod h1:qwPWnhz6pn0NnRBP++URONOVyNkPyr4SauJk4cUOwJs= -github.com/snowflakedb/glog v0.0.0-20180824191149-f5055e6f21ce/go.mod h1:EB/w24pR5VKI60ecFnKqXzxX3dOorz1rnVicQTQrGM0= -github.com/snowflakedb/gosnowflake v1.3.5/go.mod h1:13Ky+lxzIm3VqNDZJdyvu9MCGy+WgRdYFdXp96UcLZU= +github.com/snowflakedb/gosnowflake v1.6.3/go.mod h1:6hLajn6yxuJ4xUHZegMekpq9rnQbGJ7TMwXjgTmA6lg= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= +github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.3.0 h1:NGXK3lHquSN08v5vWalVI/L8XU9hdzE/G6xsrze47As= -github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -766,7 +1234,11 @@ github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= +github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tj/assert v0.0.0-20171129193455-018094318fb0/go.mod h1:mZ9/Rh9oLWpLLDRpvE+3b7gP/C2YyLFYxNmcLnPTMe0= github.com/tj/assert v0.0.3 h1:Df/BlaZ20mq6kuai7f5z2TvPFiwC3xaWJSDQNiIS3Rk= github.com/tj/assert v0.0.3/go.mod h1:Ne6X72Q+TB1AteidzQncjw9PabbMp4PBMZ1k+vd1Pvk= @@ -774,39 +1246,70 @@ github.com/tj/go-buffer v1.1.0/go.mod h1:iyiJpfFcR2B9sXu7KvjbT9fpM4mOelRSDTbntVj github.com/tj/go-elastic v0.0.0-20171221160941-36157cbbebc2/go.mod h1:WjeM0Oo1eNAjXGDx2yma7uG2XoyRZTq1uv3M/o7imD0= github.com/tj/go-kinesis v0.0.0-20171128231115-08b17f58cb1b/go.mod h1:/yhzCV0xPfx6jb1bBgRFjl5lytqVqZXEaeqWP8lTEao= github.com/tj/go-spin v1.1.0/go.mod h1:Mg1mzmePZm4dva8Qz60H2lHwmJ2loum4VIrLgVnKwh4= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= +github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= +github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= +github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= +github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= +github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= +github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= +github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= +github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= github.com/xanzy/go-gitlab v0.15.0/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVThkpGiXrs= -github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= -github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= +github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= +github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= +github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= 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= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xo/dburl v0.9.0 h1:ME8QfRqZz/YDwf+VVEe9sq4wgEZCAOdYcUTeuAf+wQQ= github.com/xo/dburl v0.9.0/go.mod h1:7Uupe87dIDxNrbKFRrpw6bAf2l3/rqU42iwlpq1nyjY= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yhat/scrape v0.0.0-20161128144610-24b7890b0945/go.mod h1:4vRFPPNYllgCacoj+0FoKOjTW68rUhEfqPLiEJaK2w8= +github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= +github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= +github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= github.com/zalando/go-keyring v0.2.1 h1:MBRN/Z8H4U5wEKXiD67YbDAr5cj/DOStmSga70/2qKc= github.com/zalando/go-keyring v0.2.1/go.mod h1:g63M2PPn0w5vjmEbwAX3ib5I+41zdm4esSETOn9Y6Dw= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE= -go.mongodb.org/mongo-driver v1.1.0/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= +go.mongodb.org/mongo-driver v1.7.0/go.mod h1:Q4oFMbo1+MSNqICAdYMlC/zSTrwCogR4R8NzkI+yfU8= +go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -826,41 +1329,61 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200117160349-530e935923ad/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 h1:tkVvjkPTB7pnW3jnid7kNyAMPVWllTNOf/qKDze4p9o= golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -871,7 +1394,9 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -881,6 +1406,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -888,8 +1415,10 @@ golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181108082009-03003ca0c849/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190225153610-fe579d43d832/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -897,13 +1426,18 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191003171128-d98b1b443823/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191112182307-2180aed22343/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -918,16 +1452,24 @@ golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201029221708-28c70e62bb1d/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211013171255-e13a2654a71e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -937,13 +1479,21 @@ golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a h1:qfl7ob3DIEs3Ml9oLuPwY2N04gymzAW04WsUQHIClgM= golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190412183630-56d357773e84/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-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -957,6 +1507,7 @@ golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -964,28 +1515,47 @@ golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190530182044-ad28b68e88f1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191112214154-59a1497f0cea/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200121082415-34d275377bf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -996,23 +1566,48 @@ golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200828194041-157a740278f4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201029080932-201ba4db2418/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210818153620-00dd8d7831e7/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f h1:rlezHXNlxYWvBCzNses9Dlc7nGFaNMJeqLolcmQSSZY= @@ -1032,30 +1627,41 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1086,13 +1692,21 @@ golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200806022845-90696ccdc692/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200814230902-9882f1d1823d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200817023811-d00afeaade8f/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200818005847-188abfa75333/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210101214203-2dba1e4ea05c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1102,6 +1716,13 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= +gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0= +gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= +gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY= +google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -1118,6 +1739,15 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= +google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= +google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= +google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= google.golang.org/appengine v1.0.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1128,6 +1758,7 @@ google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCID google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -1135,6 +1766,7 @@ google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= @@ -1143,6 +1775,7 @@ google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200117163144-32f20d992d24/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= @@ -1160,21 +1793,43 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200806141610-86f49bd18e98/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200815001618-f69a88009b70/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200911024640-645f7a48b24f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201030142918-24207fddd1c3/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210207032614-bba0dbe2a9ea/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto v0.0.0-20210630183607-d20f26d13c79/go.mod h1:yiaVoXHpRzHGyxV3o4DktVWY4mSUErTKaeEOq6C3t3U= +google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210721163202-f1cecdd8b78a/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210726143408-b02e89920bf0/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20211013025323-ce878158c4d4/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220317150908-0efb43f6373e h1:fNKDNuUyC4WH+inqDMpfXDdfvwfYILbsX+oskGZ8hxg= google.golang.org/genproto v0.0.0-20220317150908-0efb43f6373e/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= +google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= @@ -1183,10 +1838,18 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= google.golang.org/grpc v1.45.0 h1:NEpgUqV3Z+ZjkqMsxMg11IaDrXY4RY6CQukSGK0uI1M= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= @@ -1210,10 +1873,13 @@ gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/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= -gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/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/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= @@ -1225,9 +1891,14 @@ gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eR gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mNfM5bm88whjWx4= gopkg.in/jcmturner/gokrb5.v7 v7.5.0/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM= gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8= +gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1242,10 +1913,13 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/driver/postgres v1.0.8/go.mod h1:4eOzrI1MUfm6ObJU/UcmbXyiHSs8jSwH95G5P5dxcAg= gorm.io/driver/postgres v1.2.2 h1:Ka9W6feOU+rPM9m007eYLMD4QoZuYGBnQ3Jp0faGSwg= gorm.io/driver/postgres v1.2.2/go.mod h1:Ik3tK+a3FMp8ORZl29v4b3M0RsgXsaeMXh9s9eVMXco= gorm.io/driver/sqlite v1.2.4 h1:jx16ESo1WzNjgBJNSbhEDoMKJnlhkU8BuBR2C0GC7D8= gorm.io/driver/sqlite v1.2.4/go.mod h1:n8/CTEIEmo7lKrehQI4pd+rz6O514tMkBeCAR5UTXLs= +gorm.io/gorm v1.20.12/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw= +gorm.io/gorm v1.21.4/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw= gorm.io/gorm v1.22.2/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= gorm.io/gorm v1.22.3 h1:/JS6z+GStEQvJNW3t1FTwJwG/gZ+A7crFdRqtvG5ehA= gorm.io/gorm v1.22.3/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= @@ -1260,17 +1934,65 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= +k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ= +k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8= +k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= +k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= +k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc= +k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= +k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM= +k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q= +k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y= +k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k= +k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0= +k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk= +k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI= +k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM= +k8s.io/cri-api v0.17.3/go.mod h1:X1sbHmuXhwaHs9xxYffLqJogVsnI+f6cPRcgPel7ywM= +k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= +k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= +k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc= +k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= +k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= +k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= +k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= modernc.org/b v1.0.0/go.mod h1:uZWcZfRj1BpYzfN9JTerzlNUnnPsV9O2ZA8JsRcubNg= +modernc.org/cc/v3 v3.32.4 h1:1ScT6MCQRWwvwVdERhGPsPq0f55J1/pFEOCiqM7zc78= +modernc.org/cc/v3 v3.32.4/go.mod h1:0R6jl1aZlIl2avnYfbfHBS1QB6/f+16mihBObaBC878= +modernc.org/ccgo/v3 v3.9.2 h1:mOLFgduk60HFuPmxSix3AluTEh7zhozkby+e1VDo/ro= +modernc.org/ccgo/v3 v3.9.2/go.mod h1:gnJpy6NIVqkETT+L5zPsQFj7L2kkhfPMzOghRNv/CFo= modernc.org/db v1.0.0/go.mod h1:kYD/cO29L/29RM0hXYl4i3+Q5VojL31kTUVpVJDw0s8= modernc.org/file v1.0.0/go.mod h1:uqEokAEn1u6e+J45e54dsEA/pw4o7zLrA2GwyntZzjw= modernc.org/fileutil v1.0.0/go.mod h1:JHsWpkrk/CnVV1H/eGlFf85BEpfkrp56ro8nojIq9Q8= modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= +modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= modernc.org/internal v1.0.0/go.mod h1:VUD/+JAkhCpvkUitlEOnhpVxCgsBI90oTzSCRcqQVSM= +modernc.org/libc v1.7.13-0.20210308123627-12f642a52bb8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w= +modernc.org/libc v1.9.5 h1:zv111ldxmP7DJ5mOIqzRbza7ZDl3kh4ncKfASB2jIYY= +modernc.org/libc v1.9.5/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w= modernc.org/lldb v1.0.0/go.mod h1:jcRvJGWfCGodDZz8BPwiKMJxGJngQ/5DrRapkQnLob8= modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= +modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.2.2 h1:+yFk8hBprV+4c0U9GjFtL+dV3N8hOJ8JCituQcMShFY= +modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/memory v1.0.4 h1:utMBrFcpnQDdNsmM6asmyH/FM9TqLPS7XF7otpJmrwM= +modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc= +modernc.org/opt v0.1.1 h1:/0RX92k9vwVeDXj+Xn23DKp2VJubL7k8qNffND6qn3A= +modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/ql v1.0.0/go.mod h1:xGVyrLIatPcO2C1JvI/Co8c0sr6y91HKFNy4pt9JXEY= modernc.org/sortutil v1.1.0/go.mod h1:ZyL98OQHJgH9IEfN71VsamvJgrtRX9Dj2gX+vH86L1k= +modernc.org/sqlite v1.10.6 h1:iNDTQbULcm0IJAqrzCm2JcCqxaKRS94rJ5/clBMRmc8= +modernc.org/sqlite v1.10.6/go.mod h1:Z9FEjUtZP4qFEg6/SiADg9XCER7aYy9a/j7Pg9P7CPs= +modernc.org/strutil v1.1.0 h1:+1/yCzZxY2pZwwrsbH+4T7BQMoLQ9QiBshRC9eicYsc= modernc.org/strutil v1.1.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= +modernc.org/tcl v1.5.2/go.mod h1:pmJYOLgpiys3oI4AeAafkcUfE+TKKilminxNyU/+Zlo= +modernc.org/token v1.0.0 h1:a0jaWiNMDhDUtqOj09wvjWWAqd3q7WpBulmL9H2egsk= +modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +modernc.org/z v1.0.1-0.20210308123920-1f282aa71362/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA= +modernc.org/z v1.0.1/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA= modernc.org/zappy v1.0.0/go.mod h1:hHe+oGahLVII/aTTyWK/b53VDHMAGCBYYeZ9sn83HC4= mvdan.cc/gofumpt v0.1.1/go.mod h1:yXG1r1WqZVKWbVRtBWKWX9+CxGYfA51nSomhM0woR48= mvdan.cc/gofumpt v0.3.1 h1:avhhrOmv0IuvQVK7fvwV91oFSGAk5/6Po8GXTzICeu8= @@ -1278,7 +2000,14 @@ mvdan.cc/gofumpt v0.3.1/go.mod h1:w3ymliuxvzVx8DAutBnVyDqYb1Niy/yCJt/lk821YCE= nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= +sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/internal/cmd/base/dev.go b/internal/cmd/base/dev.go index cf692f343..3e83670dd 100644 --- a/internal/cmd/base/dev.go +++ b/internal/cmd/base/dev.go @@ -328,11 +328,7 @@ func (b *Server) CreateDevOidcAuthMethod(ctx context.Context) error { func (b *Server) createInitialOidcAuthMethod(ctx context.Context) (*oidc.AuthMethod, error) { rw := db.New(b.Database) - kmsRepo, err := kms.NewRepository(rw, rw) - if err != nil { - return nil, fmt.Errorf("error creating kms repository: %w", err) - } - kmsCache, err := kms.NewKms(kmsRepo) + kmsCache, err := kms.New(ctx, rw, rw) if err != nil { return nil, fmt.Errorf("error creating kms cache: %w", err) } diff --git a/internal/cmd/base/initial_resources.go b/internal/cmd/base/initial_resources.go index 3f2560429..e32f27611 100644 --- a/internal/cmd/base/initial_resources.go +++ b/internal/cmd/base/initial_resources.go @@ -22,11 +22,7 @@ import ( func (b *Server) CreateInitialLoginRole(ctx context.Context) (*iam.Role, error) { rw := db.New(b.Database) - kmsRepo, err := kms.NewRepository(rw, rw) - if err != nil { - return nil, fmt.Errorf("error creating kms repository: %w", err) - } - kmsCache, err := kms.NewKms(kmsRepo) + kmsCache, err := kms.New(ctx, rw, rw) if err != nil { return nil, fmt.Errorf("error creating kms cache: %w", err) } @@ -80,11 +76,7 @@ func (b *Server) CreateInitialLoginRole(ctx context.Context) (*iam.Role, error) func (b *Server) CreateInitialPasswordAuthMethod(ctx context.Context) (*password.AuthMethod, *iam.User, error) { rw := db.New(b.Database) - kmsRepo, err := kms.NewRepository(rw, rw) - if err != nil { - return nil, nil, fmt.Errorf("error creating kms repository: %w", err) - } - kmsCache, err := kms.NewKms(kmsRepo) + kmsCache, err := kms.New(ctx, rw, rw) if err != nil { return nil, nil, fmt.Errorf("error creating kms cache: %w", err) } @@ -279,11 +271,7 @@ func (b *Server) CreateInitialPasswordAuthMethod(ctx context.Context) (*password func (b *Server) CreateInitialScopes(ctx context.Context) (*iam.Scope, *iam.Scope, error) { rw := db.New(b.Database) - kmsRepo, err := kms.NewRepository(rw, rw) - if err != nil { - return nil, nil, fmt.Errorf("error creating kms repository: %w", err) - } - kmsCache, err := kms.NewKms(kmsRepo) + kmsCache, err := kms.New(ctx, rw, rw) if err != nil { return nil, nil, fmt.Errorf("error creating kms cache: %w", err) } @@ -362,11 +350,7 @@ func (b *Server) CreateInitialScopes(ctx context.Context) (*iam.Scope, *iam.Scop func (b *Server) CreateInitialHostResources(ctx context.Context) (*static.HostCatalog, *static.HostSet, *static.Host, error) { rw := db.New(b.Database) - kmsRepo, err := kms.NewRepository(rw, rw) - if err != nil { - return nil, nil, nil, fmt.Errorf("error creating kms repository: %w", err) - } - kmsCache, err := kms.NewKms(kmsRepo) + kmsCache, err := kms.New(ctx, rw, rw) if err != nil { return nil, nil, nil, fmt.Errorf("error creating kms cache: %w", err) } @@ -473,11 +457,7 @@ func (b *Server) CreateInitialHostResources(ctx context.Context) (*static.HostCa func (b *Server) CreateInitialTarget(ctx context.Context) (target.Target, error) { rw := db.New(b.Database) - kmsRepo, err := kms.NewRepository(rw, rw) - if err != nil { - return nil, fmt.Errorf("error creating kms repository: %w", err) - } - kmsCache, err := kms.NewKms(kmsRepo) + kmsCache, err := kms.New(ctx, rw, rw) if err != nil { return nil, fmt.Errorf("error creating kms cache: %w", err) } @@ -608,11 +588,7 @@ func (b *Server) RegisterHostPlugin(ctx context.Context, name string, plg plgpb. } rw := db.New(b.Database) - kmsRepo, err := kms.NewRepository(rw, rw) - if err != nil { - return nil, fmt.Errorf("error creating kms repository: %w", err) - } - kmsCache, err := kms.NewKms(kmsRepo) + kmsCache, err := kms.New(ctx, rw, rw) if err != nil { return nil, fmt.Errorf("error creating kms cache: %w", err) } diff --git a/internal/cmd/base/servers.go b/internal/cmd/base/servers.go index 2b0f4c0d6..92a314ba6 100644 --- a/internal/cmd/base/servers.go +++ b/internal/cmd/base/servers.go @@ -649,11 +649,7 @@ func (b *Server) ConnectToDatabase(ctx context.Context, dialect string) error { func (b *Server) CreateGlobalKmsKeys(ctx context.Context) error { rw := db.New(b.Database) - kmsRepo, err := kms.NewRepository(rw, rw) - if err != nil { - return fmt.Errorf("error creating kms repository: %w", err) - } - kmsCache, err := kms.NewKms(kmsRepo) + kmsCache, err := kms.New(ctx, rw, rw) if err != nil { return fmt.Errorf("error creating kms cache: %w", err) } @@ -674,8 +670,7 @@ func (b *Server) CreateGlobalKmsKeys(ctx context.Context) error { } }() - _, err = kms.CreateKeysTx(cancelCtx, rw, rw, b.RootKms, b.SecureRandomReader, scope.Global.String()) - if err != nil { + if err = kmsCache.CreateKeys(cancelCtx, scope.Global.String(), kms.WithRandomReader(b.SecureRandomReader)); err != nil { return fmt.Errorf("error creating global scope kms keys: %w", err) } diff --git a/internal/cmd/commands/server/server.go b/internal/cmd/commands/server/server.go index 1b28e2fbf..f91291b9f 100644 --- a/internal/cmd/commands/server/server.go +++ b/internal/cmd/commands/server/server.go @@ -23,7 +23,6 @@ import ( "github.com/hashicorp/boundary/internal/errors" "github.com/hashicorp/boundary/internal/kms" "github.com/hashicorp/boundary/internal/observability/event" - "github.com/hashicorp/boundary/internal/types/scope" kms_plugin_assets "github.com/hashicorp/boundary/plugins/kms" "github.com/hashicorp/boundary/sdk/wrapper" "github.com/hashicorp/go-hclog" @@ -788,18 +787,13 @@ func (c *Command) verifyKmsSetup() error { const op = "server.(Command).verifyKmsExists" rw := db.New(c.Database) - kmsRepo, err := kms.NewRepository(rw, rw) + ctx := context.Background() + kmsCache, err := kms.New(ctx, rw, rw) if err != nil { - return fmt.Errorf("error creating kms repository: %w", err) + return fmt.Errorf("error creating kms: %w", err) } - rks, err := kmsRepo.ListRootKeys(c.Context, kms.WithLimit(1)) - if err != nil { + if err := kmsCache.VerifyGlobalRoot(ctx); err != nil { return err } - for _, rk := range rks { - if rk.GetScopeId() == scope.Global.String() { - return nil - } - } - return errors.NewDeprecated(errors.MigrationIntegrity, op, "can't find global scoped root key") + return nil } diff --git a/internal/daemon/controller/auth/auth.go b/internal/daemon/controller/auth/auth.go index 54b729644..91c122bd1 100644 --- a/internal/daemon/controller/auth/auth.go +++ b/internal/daemon/controller/auth/auth.go @@ -396,7 +396,7 @@ func (v *verifier) decryptToken(ctx context.Context) { v.requestInfo.TokenFormat = uint32(AuthTokenTypeUnknown) return } - wrapper := v.kms.GetExternalWrappers().Recovery() + wrapper := v.kms.GetExternalWrappers(ctx).Recovery() if wrapper == nil { event.WriteError(ctx, op, stderrors.New("no recovery KMS is available")) v.requestInfo.TokenFormat = uint32(AuthTokenTypeUnknown) diff --git a/internal/daemon/controller/controller.go b/internal/daemon/controller/controller.go index c028e1c84..c89386c92 100644 --- a/internal/daemon/controller/controller.go +++ b/internal/daemon/controller/controller.go @@ -204,11 +204,7 @@ func New(ctx context.Context, conf *Config) (*Controller, error) { // Set up repo stuff dbase := db.New(c.conf.Database) - kmsRepo, err := kms.NewRepository(dbase, dbase) - if err != nil { - return nil, fmt.Errorf("error creating kms repository: %w", err) - } - c.kms, err = kms.NewKms(kmsRepo) + c.kms, err = kms.New(ctx, dbase, dbase) if err != nil { return nil, fmt.Errorf("error creating kms cache: %w", err) } diff --git a/internal/daemon/controller/controller_test.go b/internal/daemon/controller/controller_test.go index 20c732fda..160886595 100644 --- a/internal/daemon/controller/controller_test.go +++ b/internal/daemon/controller/controller_test.go @@ -5,7 +5,6 @@ import ( "testing" "github.com/hashicorp/boundary/internal/cmd/base" - "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/iam" "github.com/hashicorp/boundary/internal/kms" "github.com/hashicorp/boundary/internal/types/scope" @@ -51,8 +50,8 @@ func TestController_New(t *testing.T) { verifyFn() // this tests a scenario where there is NOT an audit DEK - db.TestDeleteWhere(t, conf.Server.Database, func() interface{} { i := kms.AllocAuditKey(); return &i }(), "1=1") - db.TestDeleteWhere(t, conf.Server.Database, func() interface{} { i := kms.AllocOidcKey(); return &i }(), "1=1") + kms.TestKmsDeleteKeyPurpose(t, conf.Database, kms.KeyPurposeAudit) + kms.TestKmsDeleteKeyPurpose(t, conf.Database, kms.KeyPurposeOidc) // re-init an empty cache and assert that the DEKs are not there. kmsCache := kms.TestKms(t, conf.Server.Database, conf.RootKms) diff --git a/internal/daemon/controller/handlers/sessions/session_list_benchmarks_test.go b/internal/daemon/controller/handlers/sessions/session_list_benchmarks_test.go index 010e088c9..73401dae3 100644 --- a/internal/daemon/controller/handlers/sessions/session_list_benchmarks_test.go +++ b/internal/daemon/controller/handlers/sessions/session_list_benchmarks_test.go @@ -74,9 +74,7 @@ func BenchmarkSessionList(b *testing.B) { ctx := context.Background() conn, _ := db.TestSetup(b, "postgres", db.WithTemplate(template.name)) rw := db.New(conn) - kmsRepo, err := kms.NewRepository(rw, rw) - require.NoError(b, err) - kmsThing, err := kms.NewKms(kmsRepo) + kmsThing, err := kms.New(ctx, rw, rw) require.NoError(b, err) wrap, err := dbtest.GetBoundaryBenchmarksRootKeyWrapper(ctx) require.NoError(b, err) diff --git a/internal/db/read_writer.go b/internal/db/read_writer.go index 49d77c733..cc3d2bde1 100644 --- a/internal/db/read_writer.go +++ b/internal/db/read_writer.go @@ -208,6 +208,11 @@ func New(underlying *DB) *Db { return &Db{underlying: underlying} } +// UnderlyingDB returns the underlying *dbw.DB +func (rw *Db) UnderlyingDB() *dbw.DB { + return rw.underlying.wrapped +} + // Exec will execute the sql with the values as parameters. The int returned // is the number of rows affected by the sql. WithDebug is supported. func (rw *Db) Exec(ctx context.Context, sql string, values []interface{}, opt ...Option) (int, error) { diff --git a/internal/db/schema/migrations/oss/postgres/30/01_kms_domain_types.up.sql b/internal/db/schema/migrations/oss/postgres/30/01_kms_domain_types.up.sql new file mode 100644 index 000000000..bc55a9169 --- /dev/null +++ b/internal/db/schema/migrations/oss/postgres/30/01_kms_domain_types.up.sql @@ -0,0 +1,103 @@ +begin; + +-- make the required schema changes to adopt +-- github.com/hashicorp/go-kms-wrapping/extras/kms/v2 +-- this migration is from: +-- https://github.com/hashicorp/go-kms-wrapping/blob/main/extras/kms/migrations/postgres/01_domain_types.up.sql + +create domain kms_private_id as text +not null +check( + length(trim(value)) > 0 +); +comment on domain kms_private_id is + 'standard column for private id'; + +create domain kms_scope_id as text +check( + length(trim(value)) > 0 +); +comment on domain kms_scope_id is +'standard column for scope id'; + +create domain kms_timestamp as + timestamp with time zone + default current_timestamp; +comment on domain kms_timestamp is +'Standard timestamp for all create_time and update_time columns'; + +create domain kms_version as bigint + default 1 + not null + check( + value > 0 + ); +comment on domain kms_version is +'standard column for row version'; + +-- kms_immutable_columns() will make the column names immutable which are passed as +-- parameters when the trigger is created. It raises error code 23601 which is a +-- class 23 integrity constraint violation: immutable column +create function kms_immutable_columns() + returns trigger +as $$ +declare + col_name text; + new_value text; + old_value text; +begin + foreach col_name in array tg_argv loop + execute format('SELECT $1.%I', col_name) into new_value using new; + execute format('SELECT $1.%I', col_name) into old_value using old; + if new_value is distinct from old_value then + raise exception 'immutable column: %.%', tg_table_name, col_name using + errcode = '23601', + schema = tg_table_schema, + table = tg_table_name, + column = col_name; + end if; + end loop; + return new; +end; +$$ language plpgsql; + +comment on function + kms_immutable_columns() +is + 'function used in before update triggers to make columns immutable'; + + +create function kms_default_create_time() + returns trigger +as $$ +begin + if new.create_time is distinct from now() then + new.create_time = now(); + end if; + return new; +end; +$$ language plpgsql; +comment on function + kms_default_create_time() +is + 'function used to properly set create_time columns'; + +create function + kms_update_time_column() + returns trigger +as $$ +begin + if row(new.*) is distinct from row(old.*) then + new.update_time = now(); + return new; + else + return old; + end if; +end; +$$ language plpgsql; +comment on function + kms_update_time_column() +is + 'function used in before update triggers to properly set update_time columns'; + +commit; \ No newline at end of file diff --git a/internal/db/schema/migrations/oss/postgres/30/02_kms_version.up.sql b/internal/db/schema/migrations/oss/postgres/30/02_kms_version.up.sql new file mode 100644 index 000000000..9eecc2b7f --- /dev/null +++ b/internal/db/schema/migrations/oss/postgres/30/02_kms_version.up.sql @@ -0,0 +1,40 @@ +begin; + +-- make the required schema changes to adopt +-- github.com/hashicorp/go-kms-wrapping/extras/kms/v2 +-- this migration is from: +-- https://github.com/hashicorp/go-kms-wrapping/blob/main/extras/kms/migrations/postgres/02_version.up.sql + +create table kms_schema_version( + version text not null, + create_time kms_timestamp, + update_time kms_timestamp +); +comment on table kms_schema_version is + 'kms_schema_version contains the kms schema version'; + +-- this index ensures that there will only ever be one row in the +-- table. see: +-- https://www.postgresql.org/docs/current/indexes-expressional.html +create unique index kms_schema_version_one_row +ON kms_schema_version((version is not null)); + + -- define the immutable fields for kms_root_key (all of them) +create trigger kms_immutable_columns +before +update on kms_schema_version + for each row execute procedure kms_immutable_columns('create_time'); + +create trigger kms_default_create_time_column +before +insert on kms_schema_version + for each row execute procedure kms_default_create_time(); + +create trigger kms_update_time_column +before +update on kms_schema_version + for each row execute procedure kms_update_time_column(); + +insert into kms_schema_version(version) values('v0.0.1'); + +commit; \ No newline at end of file diff --git a/internal/db/schema/migrations/oss/postgres/30/03_kms_keys.up.sql b/internal/db/schema/migrations/oss/postgres/30/03_kms_keys.up.sql new file mode 100644 index 000000000..9ff06933c --- /dev/null +++ b/internal/db/schema/migrations/oss/postgres/30/03_kms_keys.up.sql @@ -0,0 +1,37 @@ +begin; + +-- make the required schema changes to adopt +-- github.com/hashicorp/go-kms-wrapping/extras/kms/v2 +-- this migration is from: +-- https://github.com/hashicorp/go-kms-wrapping/blob/main/extras/kms/migrations/postgres/03_keys.up.sql + +-- we need to replace the existing function and there are existing tables that +-- depend on it.. so let's just create/replace it + +-- kms_version_column() will increment the version column whenever row data +-- is inserted and should only be used in an before insert trigger. This +-- function will overwrite any explicit values to the version column. +create or replace function kms_version_column() + returns trigger +as $$ +declare + _key_id text; + _max bigint; +begin + execute format('SELECT $1.%I', tg_argv[0]) into _key_id using new; + execute format('select max(version) + 1 from %I where %I = $1', tg_relid::regclass, tg_argv[0]) using _key_id into _max; + if _max is null then + _max = 1; + end if; + new.version = _max; + return new; +end; +$$ language plpgsql; + +comment on function + kms_version_column() +is + 'function used in before insert triggers to properly set version columns for kms_* tables with a version column'; + + +commit; \ No newline at end of file diff --git a/internal/db/schema/migrations/oss/postgres/30/04_kms_keys.up.sql b/internal/db/schema/migrations/oss/postgres/30/04_kms_keys.up.sql new file mode 100644 index 000000000..c5643d401 --- /dev/null +++ b/internal/db/schema/migrations/oss/postgres/30/04_kms_keys.up.sql @@ -0,0 +1,281 @@ +begin; + +-- make the required schema changes to adopt +-- github.com/hashicorp/go-kms-wrapping/extras/kms/v2 +-- this migration is from: +-- https://github.com/hashicorp/go-kms-wrapping/blob/main/extras/kms/migrations/postgres/04_keys.up.sql + + +alter table kms_root_key rename to kms_deprecated_root_key; +alter table kms_root_key_version rename to kms_deprecated_root_key_version; + +create table kms_root_key ( + private_id kms_private_id primary key, + scope_id kms_scope_id not null unique -- there can only be one root key for a scope. + references iam_scope(public_id) + on delete cascade + on update cascade, + create_time kms_timestamp +); +comment on table kms_root_key is + 'kms_root_key defines a root key for a scope'; + +-- define the immutable fields for kms_root_key (all of them) +create trigger kms_immutable_columns +before +update on kms_root_key + for each row execute procedure kms_immutable_columns('private_id', 'scope_id', 'create_time'); + +-- not adding the kms_default_create_time_column trigger until after we've +-- converted the data (we don't want the timestamp to change) + +create table kms_root_key_version ( + private_id kms_private_id primary key, + root_key_id kms_private_id not null + constraint kms_root_key_fkey + references kms_root_key(private_id) + on delete cascade + on update cascade, + version kms_version, + key bytea not null + constraint not_empty_key + check ( + length(key) > 0 + ), + create_time kms_timestamp, + constraint kms_root_key_version_root_key_id_version_uq + unique(root_key_id, version) +); +comment on table kms_root_key_version is + 'kms_root_key_version contains versions of a kms_root_key'; + + -- define the immutable fields for kms_root_key_version (all of them) +create trigger kms_immutable_columns +before +update on kms_root_key_version + for each row execute procedure kms_immutable_columns('private_id', 'root_key_id', 'version', 'key', 'create_time'); + +-- not adding the kms_default_create_time_column or kms_version_column triggers +-- until after we've converted the data (we don't want the timestamp or versions +-- to change) + +create table kms_data_key ( + private_id kms_private_id primary key, + root_key_id kms_private_id not null + constraint kms_root_key_fkey + references kms_root_key(private_id) + on delete cascade + on update cascade, + purpose text not null + constraint not_start_end_whitespace_purpose + check (length(trim(purpose)) = length(purpose)), + create_time kms_timestamp, + constraint kms_data_key_root_key_id_purpose_uq + unique (root_key_id, purpose) -- there can only be one dek for a specific purpose per root key +); +comment on table kms_data_key is + 'kms_data_key contains deks (data keys) for specific purposes'; + + -- define the immutable fields for kms_data_key (all of them) +create trigger kms_immutable_columns +before +update on kms_data_key + for each row execute procedure kms_immutable_columns('private_id', 'root_key_id', 'purpose', 'create_time'); + +-- not adding the kms_default_create_time_column trigger until after we've +-- converted the data (we don't want the timestamp to change) + +create table kms_data_key_version ( + private_id kms_private_id primary key, + data_key_id kms_private_id not null + constraint kms_data_key_fkey + references kms_data_key(private_id) + on delete cascade + on update cascade, + root_key_version_id kms_private_id not null + constraint kms_root_key_version_fkey + references kms_root_key_version(private_id) + on delete cascade + on update cascade, + version kms_version, + key bytea not null + constraint not_empty_key + check ( + length(key) > 0 + ), + create_time kms_timestamp, + constraint kms_data_key_version_data_key_id_version_uq + unique(data_key_id, version) +); +comment on table kms_data_key is + 'kms_data_key_version contains versions of a kms_data_key (dek aka data keys)'; + + -- define the immutable fields for kms_data_key_version (all of them) +create trigger kms_immutable_columns +before +update on kms_data_key_version + for each row execute procedure immutable_columns('private_id', 'data_key_id', 'root_key_version_id', 'version', 'key', 'create_time'); + +-- not adding the kms_default_create_time_column or kms_version_column triggers +-- until after we've converted the data (we don't want the timestamp or versions +-- to change) + +-- ############################################################################ +-- Next: we will convert all the existing KEKs/DEKs into the new schema model +-- before adding triggers for create_time, and version +-- this is important, especially for the version column! + +-- convert KEK tables +insert into kms_root_key (private_id, scope_id, create_time) +select private_id, scope_id, create_time +from kms_deprecated_root_key; + +insert into kms_root_key_version (private_id, root_key_id, version, key, create_time) +select private_id, root_key_id, version, key, create_time +from kms_deprecated_root_key_version; + +-- convert database DEK tables +insert into kms_data_key (private_id, root_key_id, purpose, create_time) +select private_id, root_key_id, 'database', create_time +from kms_database_key; + +insert into kms_data_key_version (private_id, data_key_id, root_key_version_id, version, key, create_time) +select private_id, database_key_id, root_key_version_id, version, key, create_time +from kms_database_key_version; + +-- convert oplog DEK tables +insert into kms_data_key (private_id, root_key_id, purpose, create_time) +select private_id, root_key_id, 'oplog', create_time +from kms_oplog_key; + +insert into kms_data_key_version (private_id, data_key_id, root_key_version_id, version, key, create_time) +select private_id, oplog_key_id, root_key_version_id, version, key, create_time +from kms_oplog_key_version; + +-- convert the audit DEK tables +insert into kms_data_key (private_id, root_key_id, purpose, create_time) +select private_id, root_key_id, 'audit', create_time +from kms_audit_key; + +insert into kms_data_key_version (private_id, data_key_id, root_key_version_id, version, key, create_time) +select private_id, audit_key_id, root_key_version_id, version, key, create_time +from kms_audit_key_version; + +-- convert the oidc DEK tables +insert into kms_data_key (private_id, root_key_id, purpose, create_time) +select private_id, root_key_id, 'oidc', create_time +from kms_oidc_key; + +insert into kms_data_key_version (private_id, data_key_id, root_key_version_id, version, key, create_time) +select private_id, oidc_key_id, root_key_version_id, version, key, create_time +from kms_oidc_key_version; + +-- convert the token DEK tables +insert into kms_data_key (private_id, root_key_id, purpose, create_time) +select private_id, root_key_id, 'tokens', create_time +from kms_token_key; + +insert into kms_data_key_version (private_id, data_key_id, root_key_version_id, version, key, create_time) +select private_id, token_key_id, root_key_version_id, version, key, create_time +from kms_token_key_version; + +-- convert the session DEK tables +insert into kms_data_key (private_id, root_key_id, purpose, create_time) +select private_id, root_key_id, 'sessions', create_time +from kms_session_key; + +insert into kms_data_key_version (private_id, data_key_id, root_key_version_id, version, key, create_time) +select private_id, session_key_id, root_key_version_id, version, key, create_time +from kms_session_key_version; + +-- ############################################################################ +-- post conversion, we add the required triggers +create trigger kms_default_create_time_column +before +insert on kms_root_key + for each row execute procedure kms_default_create_time(); + +create trigger kms_default_create_time_column +before +insert on kms_root_key_version + for each row execute procedure kms_default_create_time(); + +create trigger kms_version_column +before insert on kms_root_key_version + for each row execute procedure kms_version_column('root_key_id'); + +create trigger default_create_time_column +before +insert on kms_data_key + for each row execute procedure kms_default_create_time(); + +create trigger default_create_time +before +insert on kms_data_key_version + for each row execute procedure kms_default_create_time(); + +create trigger kms_version_column +before insert on kms_data_key_version + for each row execute procedure kms_version_column('data_key_id'); + +-- Next: we will convert all the existing DEKs FKs to the new model +alter table credential_vault_token drop constraint kms_database_key_version_fkey; +alter table credential_vault_token +add constraint kms_data_key_version_fkey + foreign key(key_id) + references kms_data_key_version (private_id) + on delete restrict + on update cascade; + +alter table credential_vault_client_certificate drop constraint kms_database_key_version_fkey; +alter table credential_vault_client_certificate +add constraint kms_data_key_version_fkey + foreign key(key_id) + references kms_data_key_version (private_id) + on delete restrict + on update cascade; + +alter table auth_oidc_method drop constraint kms_database_key_version_fkey; +alter table auth_oidc_method +add constraint kms_data_key_version_fkey + foreign key(key_id) + references kms_data_key_version (private_id) + on delete restrict + on update cascade; + +alter table host_plugin_catalog_secret drop constraint kms_database_key_version_fkey; +alter table host_plugin_catalog_secret +add constraint kms_data_key_version_fkey + foreign key(key_id) + references kms_data_key_version (private_id) + on delete restrict + on update cascade; + +alter table session_credential drop constraint kms_database_key_version_fkey; +alter table session_credential +add constraint kms_data_key_version_fkey + foreign key(key_id) + references kms_data_key_version (private_id) + on delete restrict + on update cascade; + +-- rename tables so we know that they won't be used by mistake +alter table kms_database_key_version rename to kms_deprecated_database_key_version; +alter table kms_database_key rename to kms_deprecated_database_key; + +alter table kms_oplog_key_version rename to kms_deprecated_oplog_key_version; +alter table kms_oplog_key rename to kms_deprecated_oplog_key; + +alter table kms_audit_key_version rename to kms_deprecated_audit_key_version; +alter table kms_audit_key rename to kms_audit_database_key; + +alter table kms_oidc_key_version rename to kms_deprecated_oidc_key_version; +alter table kms_oidc_key rename to kms_deprecated_oidc_key; + +alter table kms_session_key_version rename to kms_deprecated_session_key_version; +alter table kms_session_key rename to kms_deprecated_session_key; + +alter table kms_token_key_version rename to kms_deprecated_token_key_version; +alter table kms_token_key rename to kms_deprecated_token_key; + +commit; \ No newline at end of file diff --git a/internal/db/schema/migrations/oss/postgres_18_01_test.go b/internal/db/schema/migrations/oss/postgres_18_01_test.go deleted file mode 100644 index 7b65ab84a..000000000 --- a/internal/db/schema/migrations/oss/postgres_18_01_test.go +++ /dev/null @@ -1,162 +0,0 @@ -package oss_test - -import ( - "context" - "testing" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/db/common" - "github.com/hashicorp/boundary/internal/db/schema" - "github.com/hashicorp/boundary/internal/kms" - "github.com/hashicorp/boundary/internal/servers" - "github.com/hashicorp/boundary/testing/dbtest" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestMigrations_Nonce(t *testing.T) { - const ( - priorMigration = 16005 - currentMigration = 18001 - ) - - t.Parallel() - assert, require := assert.New(t), require.New(t) - ctx := context.Background() - dialect := dbtest.Postgres - - c, u, _, err := dbtest.StartUsingTemplate(dialect, dbtest.WithTemplate(dbtest.Template1)) - require.NoError(err) - t.Cleanup(func() { - require.NoError(c()) - }) - d, err := common.SqlOpen(dialect, u) - require.NoError(err) - - // migration to the prior migration (before the one we want to test) - m, err := schema.NewManager(ctx, schema.Dialect(dialect), d, schema.WithEditions( - schema.TestCreatePartialEditions(schema.Dialect(dialect), schema.PartialEditions{"oss": priorMigration}), - )) - require.NoError(err) - - require.NoError(m.ApplyMigrations(ctx)) - state, err := m.CurrentState(ctx) - require.NoError(err) - want := &schema.State{ - Initialized: true, - Editions: []schema.EditionState{ - { - Name: "oss", - BinarySchemaVersion: priorMigration, - DatabaseSchemaVersion: priorMigration, - DatabaseSchemaState: schema.Equal, - }, - }, - } - require.Equal(want, state) - - // get a connection - dbType, err := db.StringToDbType(dialect) - require.NoError(err) - conn, err := db.Open(dbType, u) - require.NoError(err) - rw := db.New(conn) - - // okay, now we can seed the database with test data and validate existing - // functionality. At the end of this we will have two values in the table - // with no purpose. - { - // Create an old version of the struct - type RecoveryNonce struct { - Nonce string - } - - require.NoError(rw.CreateItems(ctx, []interface{}{ - &RecoveryNonce{Nonce: "abcd"}, - &RecoveryNonce{Nonce: "dcba"}, - })) - - var results []*RecoveryNonce - require.NoError(rw.SearchWhere(ctx, &results, "", nil)) - require.Len(results, 2) - } - - // now we're ready for the migration we want to test. - m, err = schema.NewManager(ctx, schema.Dialect(dialect), d, schema.WithEditions( - schema.TestCreatePartialEditions(schema.Dialect(dialect), schema.PartialEditions{"oss": currentMigration}), - )) - require.NoError(err) - - require.NoError(m.ApplyMigrations(ctx)) - state, err = m.CurrentState(ctx) - require.NoError(err) - want = &schema.State{ - Initialized: true, - Editions: []schema.EditionState{ - { - Name: "oss", - BinarySchemaVersion: currentMigration, - DatabaseSchemaVersion: currentMigration, - DatabaseSchemaState: schema.Equal, - }, - }, - } - require.Equal(want, state) - - // now we have migrated and we will validate functionality; we'll do this - // via the repo - { - wrapper := db.TestWrapper(t) - kmsCache := kms.TestKms(t, conn, wrapper) - rw := db.New(conn) - repo, err := servers.NewRepository(rw, rw, kmsCache) - require.NoError(err) - require.NotNil(repo) - - // First list and validate that the upgrade adjusted purpose correctly - results, err := repo.ListNonces(ctx, servers.NoncePurposeRecovery) - require.NoError(err) - assert.Len(results, 2) - for _, n := range results { - assert.Equal(servers.NoncePurposeRecovery, n.Purpose) - } - - // Test the constraint, first via the repo, then directly - const badPurpose = "foobar" - err = repo.AddNonce(ctx, "xyz", badPurpose) - require.Error(err) - assert.Contains(err.Error(), "unknown nonce purpose") - - // Check that null errors - require.Error(rw.CreateItems(ctx, []interface{}{ - &servers.Nonce{Nonce: "dcba"}, - })) - // Check that bad purpose errors - require.Error(rw.CreateItems(ctx, []interface{}{ - &servers.Nonce{Nonce: "dcba", Purpose: badPurpose}, - })) - - // Add some valid values, ensure that we can then list for both purposes - // and get different values - require.NoError(repo.AddNonce(ctx, "wxyz", servers.NoncePurposeWorkerAuth)) - require.NoError(repo.AddNonce(ctx, "zyxw", servers.NoncePurposeWorkerAuth)) - results, err = repo.ListNonces(ctx, servers.NoncePurposeRecovery) - require.NoError(err) - assert.Len(results, 2) - for _, n := range results { - assert.Equal(servers.NoncePurposeRecovery, n.Purpose) - } - results, err = repo.ListNonces(ctx, servers.NoncePurposeWorkerAuth) - require.NoError(err) - assert.Len(results, 2) - for _, n := range results { - assert.Equal(servers.NoncePurposeWorkerAuth, n.Purpose) - } - - // Last: add the same nonce, ensure we error - require.NoError(repo.AddNonce(ctx, "double", servers.NoncePurposeWorkerAuth)) - err = repo.AddNonce(ctx, "double", servers.NoncePurposeWorkerAuth) - require.Error(err) - require.Contains(err.Error(), "duplicate key value") - } -} diff --git a/internal/db/schema/migrations/oss/postgres_24_01_test.go b/internal/db/schema/migrations/oss/postgres_24_01_test.go deleted file mode 100644 index bb1893d4b..000000000 --- a/internal/db/schema/migrations/oss/postgres_24_01_test.go +++ /dev/null @@ -1,166 +0,0 @@ -package oss_test - -import ( - "context" - "testing" - - "github.com/hashicorp/boundary/internal/authtoken" - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/db/common" - "github.com/hashicorp/boundary/internal/db/schema" - "github.com/hashicorp/boundary/internal/host/static" - "github.com/hashicorp/boundary/internal/iam" - "github.com/hashicorp/boundary/internal/kms" - "github.com/hashicorp/boundary/internal/session" - "github.com/hashicorp/boundary/internal/target" - "github.com/hashicorp/boundary/internal/target/tcp" - "github.com/hashicorp/boundary/testing/dbtest" - "github.com/stretchr/testify/require" -) - -func TestMigrations_SessionState(t *testing.T) { - t.Parallel() - require := require.New(t) - - const ( - priorMigration = 21002 - currentMigration = 24001 - ) - dialect := dbtest.Postgres - ctx := context.Background() - - c, u, _, err := dbtest.StartUsingTemplate(dialect, dbtest.WithTemplate(dbtest.Template1)) - require.NoError(err) - t.Cleanup(func() { - require.NoError(c()) - }) - d, err := common.SqlOpen(dialect, u) - require.NoError(err) - - // migration to the prior migration (before the one we want to test) - m, err := schema.NewManager(ctx, schema.Dialect(dialect), d, schema.WithEditions( - schema.TestCreatePartialEditions(schema.Dialect(dialect), schema.PartialEditions{"oss": priorMigration}), - )) - require.NoError(err) - - require.NoError(m.ApplyMigrations(ctx)) - state, err := m.CurrentState(ctx) - require.NoError(err) - want := &schema.State{ - Initialized: true, - Editions: []schema.EditionState{ - { - Name: "oss", - BinarySchemaVersion: priorMigration, - DatabaseSchemaVersion: priorMigration, - DatabaseSchemaState: schema.Equal, - }, - }, - } - require.Equal(want, state) - - // Seed the database with test data - dbType, err := db.StringToDbType(dialect) - require.NoError(err) - - conn, err := db.Open(dbType, u) - require.NoError(err) - - rw := db.New(conn) - wrapper := db.TestWrapper(t) - - org, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NotNil(prj) - - hc := static.TestCatalogs(t, conn, prj.GetPublicId(), 1)[0] - hs := static.TestSets(t, conn, hc.GetPublicId(), 1)[0] - h := static.TestHosts(t, conn, hc.GetPublicId(), 1)[0] - static.TestSetMembers(t, conn, hs.GetPublicId(), []*static.Host{h}) - - tar := tcp.TestTarget(ctx, t, conn, prj.GetPublicId(), "test", target.WithHostSources([]string{hs.GetPublicId()})) - - kmsCache := kms.TestKms(t, conn, wrapper) - - { - at := authtoken.TestAuthToken(t, conn, kmsCache, org.GetPublicId()) - uId := at.GetIamUserId() - - sess := session.TestSession(t, conn, wrapper, session.ComposedOf{ - UserId: uId, - HostId: h.GetPublicId(), - TargetId: tar.GetPublicId(), - HostSetId: hs.GetPublicId(), - AuthTokenId: at.GetPublicId(), - ScopeId: prj.GetPublicId(), - Endpoint: "tcp://127.0.0.1:22", - ConnectionLimit: -1, - }) - - session.TestConnection(t, conn, sess.PublicId, "127.0.0.1", 22, - "127.0.0.2", 23, "127.0.0.1") - } - - // now we're ready for the migration we want to test. - m, err = schema.NewManager(ctx, schema.Dialect(dialect), d, schema.WithEditions( - schema.TestCreatePartialEditions(schema.Dialect(dialect), schema.PartialEditions{"oss": currentMigration}), - )) - require.NoError(err) - - require.NoError(m.ApplyMigrations(ctx)) - state, err = m.CurrentState(ctx) - require.NoError(err) - want = &schema.State{ - Initialized: true, - Editions: []schema.EditionState{ - { - Name: "oss", - BinarySchemaVersion: currentMigration, - DatabaseSchemaVersion: currentMigration, - DatabaseSchemaState: schema.Equal, - }, - }, - } - require.Equal(want, state) - - sessionRepo, err := session.NewRepository(rw, rw, kmsCache) - connectionRepo, err := session.NewConnectionRepository(ctx, rw, rw, kmsCache) - require.NoError(err) - - // Ensure session is cancelled - repoSessions, err := sessionRepo.ListSessions(ctx) - require.NoError(err) - var sessionTermReason []string - var repoSessionId string - for i := 0; i < len(repoSessions); i++ { - s := repoSessions[i] - repoSessionId = s.PublicId - sessionTermReason = append(sessionTermReason, s.TerminationReason) - } - require.Equal([]string{"canceled"}, sessionTermReason) - - // Ensure connection is also cancelled - connections, err := connectionRepo.ListConnectionsBySessionId(ctx, repoSessionId) - require.NoError(err) - - var connTermReason []string - for i := 0; i < len(connections); i++ { - c := connections[i] - connTermReason = append(connTermReason, c.ClosedReason) - } - require.Equal([]string{"canceled"}, connTermReason) - - // Validate new table contents - rows, err := d.QueryContext(ctx, "select * from session_valid_state") - require.NoError(err) - - var validStates []string - for rows.Next() { - var a, b string - require.NoError(rows.Scan(&a, &b)) - validStates = append(validStates, []string{a, b}...) - } - require.Equal([]string{ - "pending", "pending", "pending", "active", "pending", "terminated", - "pending", "canceling", "active", "canceling", "active", "terminated", "canceling", "terminated", - }, validStates) -} diff --git a/internal/db/schema/migrations/oss/postgres_28_02_test.go b/internal/db/schema/migrations/oss/postgres_28_02_test.go deleted file mode 100644 index d10967cd7..000000000 --- a/internal/db/schema/migrations/oss/postgres_28_02_test.go +++ /dev/null @@ -1,151 +0,0 @@ -package oss_test - -import ( - "context" - "testing" - - "github.com/hashicorp/boundary/internal/authtoken" - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/db/common" - "github.com/hashicorp/boundary/internal/db/schema" - "github.com/hashicorp/boundary/internal/host/static" - "github.com/hashicorp/boundary/internal/iam" - "github.com/hashicorp/boundary/internal/kms" - "github.com/hashicorp/boundary/internal/session" - "github.com/hashicorp/boundary/internal/target" - "github.com/hashicorp/boundary/internal/target/tcp" - "github.com/hashicorp/boundary/internal/types/resource" - "github.com/hashicorp/boundary/testing/dbtest" - "github.com/stretchr/testify/require" -) - -func TestMigrations_SessionStateTrigger(t *testing.T) { - t.Parallel() - require := require.New(t) - - const ( - priorMigration = 27002 - currentMigration = 28002 - ) - dialect := dbtest.Postgres - ctx := context.Background() - - c, u, _, err := dbtest.StartUsingTemplate(dialect, dbtest.WithTemplate(dbtest.Template1)) - require.NoError(err) - t.Cleanup(func() { - require.NoError(c()) - }) - d, err := common.SqlOpen(dialect, u) - require.NoError(err) - - // migration to the prior migration (before the one we want to test) - m, err := schema.NewManager(ctx, schema.Dialect(dialect), d, schema.WithEditions( - schema.TestCreatePartialEditions(schema.Dialect(dialect), schema.PartialEditions{"oss": priorMigration}), - )) - require.NoError(err) - - require.NoError(m.ApplyMigrations(ctx)) - state, err := m.CurrentState(ctx) - require.NoError(err) - want := &schema.State{ - Initialized: true, - Editions: []schema.EditionState{ - { - Name: "oss", - BinarySchemaVersion: priorMigration, - DatabaseSchemaVersion: priorMigration, - DatabaseSchemaState: schema.Equal, - }, - }, - } - require.Equal(want, state) - - // Seed the database with test data - dbType, err := db.StringToDbType(dialect) - require.NoError(err) - - conn, err := db.Open(dbType, u) - require.NoError(err) - - rw := db.New(conn) - wrapper := db.TestWrapper(t) - - org, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NotNil(prj) - - hc := static.TestCatalogs(t, conn, prj.GetPublicId(), 1)[0] - hs := static.TestSets(t, conn, hc.GetPublicId(), 1)[0] - h := static.TestHosts(t, conn, hc.GetPublicId(), 1)[0] - static.TestSetMembers(t, conn, hs.GetPublicId(), []*static.Host{h}) - tar := tcp.TestTarget(ctx, t, conn, prj.GetPublicId(), "test", target.WithHostSources([]string{hs.GetPublicId()})) - kmsCache := kms.TestKms(t, conn, wrapper) - - serverId := "worker" - tofu := session.TestTofu(t) - session.TestWorker(t, conn, wrapper, session.WithServerId(serverId)) - at := authtoken.TestAuthToken(t, conn, kmsCache, org.GetPublicId()) - uId := at.GetIamUserId() - sess := session.TestSession(t, conn, wrapper, session.ComposedOf{ - UserId: uId, - HostId: h.GetPublicId(), - TargetId: tar.GetPublicId(), - HostSetId: hs.GetPublicId(), - AuthTokenId: at.GetPublicId(), - ScopeId: prj.GetPublicId(), - Endpoint: "tcp://127.0.0.1:22", - ConnectionLimit: 1, - }) - - sessionRepo, err := session.NewRepository(rw, rw, kmsCache) - require.NoError(err) - - // Make and transition a valid session through pending, active, canceling, and terminated - // Unfortunately, could not recreate an invalid session P-A-T-C using the session repo - _, _, err = sessionRepo.ActivateSession(ctx, sess.PublicId, sess.Version, serverId, resource.Worker.String(), tofu) - require.NoError(err) - connection := session.TestConnection(t, conn, sess.PublicId, "127.0.0.1", 22, - "127.0.0.2", 23, "127.0.0.1") - session.TestConnectionState(t, conn, connection.PublicId, session.StatusConnected) - session.TestConnectionState(t, conn, connection.PublicId, session.StatusClosed) - _, err = sessionRepo.CancelSession(ctx, sess.PublicId, sess.Version+1) - require.NoError(err) - sessionRepo.TerminateCompletedSessions(ctx) - - repoSessions, err := sessionRepo.ListSessions(ctx) - require.NoError(err) - var numStates int - for _, s := range repoSessions { - numStates = len(s.States) - } - require.Equal(4, numStates) - - // now we're ready for the migration we want to test. - m, err = schema.NewManager(ctx, schema.Dialect(dialect), d, schema.WithEditions( - schema.TestCreatePartialEditions(schema.Dialect(dialect), schema.PartialEditions{"oss": currentMigration}), - )) - require.NoError(err) - - require.NoError(m.ApplyMigrations(ctx)) - state, err = m.CurrentState(ctx) - require.NoError(err) - want = &schema.State{ - Initialized: true, - Editions: []schema.EditionState{ - { - Name: "oss", - BinarySchemaVersion: currentMigration, - DatabaseSchemaVersion: currentMigration, - DatabaseSchemaState: schema.Equal, - }, - }, - } - require.Equal(want, state) - - // Check that we haven't removed a state - repoSessions, err = sessionRepo.ListSessions(ctx) - require.NoError(err) - for _, s := range repoSessions { - numStates = len(s.States) - } - require.Equal(4, numStates) -} diff --git a/internal/db/schema/migrations/oss/postgres_29_01_test.go b/internal/db/schema/migrations/oss/postgres_29_01_test.go deleted file mode 100644 index 32206bc04..000000000 --- a/internal/db/schema/migrations/oss/postgres_29_01_test.go +++ /dev/null @@ -1,140 +0,0 @@ -package oss_test - -import ( - "context" - "testing" - - "github.com/hashicorp/boundary/internal/authtoken" - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/db/common" - "github.com/hashicorp/boundary/internal/db/schema" - "github.com/hashicorp/boundary/internal/host/static" - "github.com/hashicorp/boundary/internal/iam" - "github.com/hashicorp/boundary/internal/kms" - "github.com/hashicorp/boundary/internal/session" - "github.com/hashicorp/boundary/internal/target" - "github.com/hashicorp/boundary/internal/target/tcp" - "github.com/hashicorp/boundary/internal/types/resource" - "github.com/hashicorp/boundary/testing/dbtest" - "github.com/stretchr/testify/require" -) - -func TestMigrations_SessionFKeyDelete(t *testing.T) { - t.Parallel() - require := require.New(t) - - const ( - priorMigration = 28002 - currentMigration = 29001 - ) - dialect := dbtest.Postgres - ctx := context.Background() - - c, u, _, err := dbtest.StartUsingTemplate(dialect, dbtest.WithTemplate(dbtest.Template1)) - require.NoError(err) - t.Cleanup(func() { - require.NoError(c()) - }) - d, err := common.SqlOpen(dialect, u) - require.NoError(err) - - // migration to the prior migration (before the one we want to test) - m, err := schema.NewManager(ctx, schema.Dialect(dialect), d, schema.WithEditions( - schema.TestCreatePartialEditions(schema.Dialect(dialect), schema.PartialEditions{"oss": priorMigration}), - )) - require.NoError(err) - - require.NoError(m.ApplyMigrations(ctx)) - state, err := m.CurrentState(ctx) - require.NoError(err) - want := &schema.State{ - Initialized: true, - Editions: []schema.EditionState{ - { - Name: "oss", - BinarySchemaVersion: priorMigration, - DatabaseSchemaVersion: priorMigration, - DatabaseSchemaState: schema.Equal, - }, - }, - } - require.Equal(want, state) - - // Seed the database with test data - dbType, err := db.StringToDbType(dialect) - require.NoError(err) - - conn, err := db.Open(dbType, u) - require.NoError(err) - - rw := db.New(conn) - wrapper := db.TestWrapper(t) - - org, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - require.NotNil(prj) - - hc := static.TestCatalogs(t, conn, prj.GetPublicId(), 1)[0] - hs := static.TestSets(t, conn, hc.GetPublicId(), 1)[0] - h := static.TestHosts(t, conn, hc.GetPublicId(), 1)[0] - static.TestSetMembers(t, conn, hs.GetPublicId(), []*static.Host{h}) - tar := tcp.TestTarget(ctx, t, conn, prj.GetPublicId(), "test", target.WithHostSources([]string{hs.GetPublicId()})) - kmsCache := kms.TestKms(t, conn, wrapper) - targetRepo, err := target.NewRepository(rw, rw, kmsCache) - require.NoError(err) - - serverId := "worker" - tofu := session.TestTofu(t) - session.TestWorker(t, conn, wrapper, session.WithServerId(serverId)) - at := authtoken.TestAuthToken(t, conn, kmsCache, org.GetPublicId()) - uId := at.GetIamUserId() - sess := session.TestSession(t, conn, wrapper, session.ComposedOf{ - UserId: uId, - HostId: h.GetPublicId(), - TargetId: tar.GetPublicId(), - HostSetId: hs.GetPublicId(), - AuthTokenId: at.GetPublicId(), - ScopeId: prj.GetPublicId(), - Endpoint: "tcp://127.0.0.1:22", - ConnectionLimit: 1, - }) - - sessionRepo, err := session.NewRepository(rw, rw, kmsCache) - require.NoError(err) - - // Create and terminate session without canceling - _, _, err = sessionRepo.ActivateSession(ctx, sess.PublicId, sess.Version, serverId, resource.Worker.String(), tofu) - require.NoError(err) - session.TestState(t, conn, sess.PublicId, session.StatusTerminated) - - // Delete target; expect a session_state violation and failure to delete target - rows, err := targetRepo.DeleteTarget(ctx, tar.GetPublicId()) - require.Errorf(err, "target.(Repository).DeleteTarget: db.DoTx: target.(Repository).DeleteTarget: db.Delete: insert or update on table \"session_state\" violates foreign key constraint \"session_valid_state_enm_fkey\": integrity violation: error #1003") - require.Equal(0, rows) - - // now we're ready for the migration we want to test. - m, err = schema.NewManager(ctx, schema.Dialect(dialect), d, schema.WithEditions( - schema.TestCreatePartialEditions(schema.Dialect(dialect), schema.PartialEditions{"oss": currentMigration}), - )) - require.NoError(err) - - require.NoError(m.ApplyMigrations(ctx)) - state, err = m.CurrentState(ctx) - require.NoError(err) - want = &schema.State{ - Initialized: true, - Editions: []schema.EditionState{ - { - Name: "oss", - BinarySchemaVersion: currentMigration, - DatabaseSchemaVersion: currentMigration, - DatabaseSchemaState: schema.Equal, - }, - }, - } - require.Equal(want, state) - - // Try to delete target again, should succeed without error - rows, err = targetRepo.DeleteTarget(ctx, tar.GetPublicId()) - require.NoError(err) - require.Equal(1, rows) -} diff --git a/internal/db/schema/migrations/oss/postgres_30_01_test.go b/internal/db/schema/migrations/oss/postgres_30_01_test.go new file mode 100644 index 000000000..539ffd32e --- /dev/null +++ b/internal/db/schema/migrations/oss/postgres_30_01_test.go @@ -0,0 +1,587 @@ +package oss_test + +import ( + "context" + "fmt" + "testing" + "time" + + "github.com/hashicorp/boundary/internal/db" + "github.com/hashicorp/boundary/internal/db/common" + "github.com/hashicorp/boundary/internal/db/schema" + "github.com/hashicorp/boundary/internal/iam" + "github.com/hashicorp/boundary/testing/dbtest" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestMigrations_KMS_Refactor(t *testing.T) { + const ( + priorMigration = 28002 + currentMigration = 30004 + ) + + t.Parallel() + ctx := context.Background() + dialect := dbtest.Postgres + + c, u, _, err := dbtest.StartUsingTemplate(dialect, dbtest.WithTemplate(dbtest.Template1)) + require.NoError(t, err) + t.Cleanup(func() { + require.NoError(t, c()) + }) + d, err := common.SqlOpen(dialect, u) + require.NoError(t, err) + + // migration to the prior migration (before the one we want to test) + m, err := schema.NewManager(ctx, schema.Dialect(dialect), d, schema.WithEditions( + schema.TestCreatePartialEditions(schema.Dialect(dialect), schema.PartialEditions{"oss": priorMigration}), + )) + require.NoError(t, err) + + require.NoError(t, m.ApplyMigrations(ctx)) + state, err := m.CurrentState(ctx) + require.NoError(t, err) + want := &schema.State{ + Initialized: true, + Editions: []schema.EditionState{ + { + Name: "oss", + BinarySchemaVersion: priorMigration, + DatabaseSchemaVersion: priorMigration, + DatabaseSchemaState: schema.Equal, + }, + }, + } + require.Equal(t, want, state) + + // get a connection + dbType, err := db.StringToDbType(dialect) + require.NoError(t, err) + conn, err := db.Open(dbType, u) + require.NoError(t, err) + rw := db.New(conn) + + generateTestKeys(t, rw) + // load up the current KEKs and their versions + existingKeks := loadKeks(t, rw) + existingKeksVersions := loadKekVersions(t, rw) + + // load up the current DEKs and their versions + existingDeks := loadCurrentDeks(t, rw) + existingKeyVersions := loadCurrentDekVersions(t, rw) + + // now we're ready for the migration we want to test. + m, err = schema.NewManager(ctx, schema.Dialect(dialect), d, schema.WithEditions( + schema.TestCreatePartialEditions(schema.Dialect(dialect), schema.PartialEditions{"oss": currentMigration}), + )) + require.NoError(t, err) + + require.NoError(t, m.ApplyMigrations(ctx)) + state, err = m.CurrentState(ctx) + require.NoError(t, err) + want = &schema.State{ + Initialized: true, + Editions: []schema.EditionState{ + { + Name: "oss", + BinarySchemaVersion: currentMigration, + DatabaseSchemaVersion: currentMigration, + DatabaseSchemaState: schema.Equal, + }, + }, + } + require.Equal(t, want, state) + // Now read all the converted keys and see if we have transformed them correctly + { + // get a new connection + dbType, err := db.StringToDbType(dialect) + require.NoError(t, err) + conn, err := db.Open(dbType, u) + require.NoError(t, err) + rw := db.New(conn) + + newKeks := loadKeks(t, rw) + assert.ElementsMatch(t, newKeks, existingKeks) + + newKeksVersions := loadKekVersions(t, rw) + assert.ElementsMatch(t, newKeksVersions, existingKeksVersions) + + newDeks := loadNewDeks(t, rw) + assert.ElementsMatch(t, newDeks, existingDeks) + + newKeyVersions := loadNewDekVersions(t, rw) + assert.ElementsMatch(t, newKeyVersions, existingKeyVersions) + } +} + +// we can't use the new KMS bits since all the tables have changed, so we'll +// generate a bit of test data by hand +func generateTestKeys(t *testing.T, rw *db.Db) { + t.Helper() + require := require.New(t) + testCtx := context.Background() + + for i := 0; i < 10; i++ { + k := kek{ + PrivateId: testId(t, "rk"), + ScopeId: testScope(t, rw).PublicId, + } + require.NoError(rw.Create(testCtx, &k)) + + var kv kekVersion + for i := 0; i < 2; i++ { + kv = kekVersion{ + PrivateId: testId(t, "rkv"), + RootKeyId: k.PrivateId, + Version: 1 + uint32(i), + Key: []byte("test-key"), + } + require.NoError(rw.Create(testCtx, &kv)) + } + + { + dbk := kmsDatabaseKey{ + PrivateId: testId(t, "dk"), + RootKeyId: k.PrivateId, + } + require.NoError(rw.Create(testCtx, &dbk)) + dbkv := kmsDatabaseKeyVersion{ + PrivateId: testId(t, "dkv"), + DatabaseKeyId: dbk.PrivateId, + RootKeyVersionId: kv.PrivateId, + Key: []byte("test-key"), + Version: 1, + } + require.NoError(rw.Create(testCtx, &dbkv)) + } + { + ak := kmsAuditKey{ + PrivateId: testId(t, "ak"), + RootKeyId: k.PrivateId, + } + require.NoError(rw.Create(testCtx, &ak)) + akv := kmsAuditKeyVersion{ + PrivateId: testId(t, "dkv"), + AuditKeyId: ak.PrivateId, + RootKeyVersionId: kv.PrivateId, + Key: []byte("test-key"), + Version: 1, + } + require.NoError(rw.Create(testCtx, &akv)) + } + { + oidck := kmsOidcKey{ + PrivateId: testId(t, "oidck"), + RootKeyId: k.PrivateId, + } + require.NoError(rw.Create(testCtx, &oidck)) + oidckv := kmsOidcKeyVersion{ + PrivateId: testId(t, "dkv"), + OidcKeyId: oidck.PrivateId, + RootKeyVersionId: kv.PrivateId, + Key: []byte("test-key"), + Version: 1, + } + require.NoError(rw.Create(testCtx, &oidckv)) + } + { + opk := kmsOplogKey{ + PrivateId: testId(t, "opk"), + RootKeyId: k.PrivateId, + } + require.NoError(rw.Create(testCtx, &opk)) + opkv := kmsOplogKeyVersion{ + PrivateId: testId(t, "dkv"), + OplogKeyId: opk.PrivateId, + RootKeyVersionId: kv.PrivateId, + Key: []byte("test-key"), + Version: 1, + } + require.NoError(rw.Create(testCtx, &opkv)) + } + { + sk := kmsSessionKey{ + PrivateId: testId(t, "sk"), + RootKeyId: k.PrivateId, + } + require.NoError(rw.Create(testCtx, &sk)) + skv := kmsSessionKeyVersion{ + PrivateId: testId(t, "dkv"), + SessionKeyId: sk.PrivateId, + RootKeyVersionId: kv.PrivateId, + Key: []byte("test-key"), + Version: 1, + } + require.NoError(rw.Create(testCtx, &skv)) + } + { + tk := kmsTokenKey{ + PrivateId: testId(t, "tk"), + RootKeyId: k.PrivateId, + } + require.NoError(rw.Create(testCtx, &tk)) + tkv := kmsTokenKeyVersion{ + PrivateId: testId(t, "dkv"), + TokenKeyId: tk.PrivateId, + RootKeyVersionId: kv.PrivateId, + Key: []byte("test-key"), + Version: 1, + } + require.NoError(rw.Create(testCtx, &tkv)) + } + + } +} + +func loadKeks(t *testing.T, rw *db.Db) []kek { + t.Helper() + testCtx := context.Background() + rows, err := rw.Query(testCtx, `select private_id, scope_id, create_time from kms_root_key order by private_id`, nil) + require.NoError(t, err) + require.NoError(t, err) + var keks []kek + for rows.Next() { + var key kek + require.NoError(t, rw.ScanRows(context.Background(), rows, &key)) + keks = append(keks, key) + } + return keks +} + +func loadKekVersions(t *testing.T, rw *db.Db) []kekVersion { + t.Helper() + testCtx := context.Background() + rows, err := rw.Query(testCtx, `select private_id, root_key_id, version, key, create_time from kms_root_key_version order by private_id`, nil) + require.NoError(t, err) + require.NoError(t, err) + var kekVersions []kekVersion + for rows.Next() { + var v kekVersion + require.NoError(t, rw.ScanRows(context.Background(), rows, &v)) + kekVersions = append(kekVersions, v) + } + return kekVersions +} + +func loadNewDeks(t *testing.T, rw *db.Db) []dek { + t.Helper() + testCtx := context.Background() + rows, err := rw.Query(testCtx, `select private_id, root_key_id, create_time, purpose from kms_data_key order by private_id`, nil) + require.NoError(t, err) + require.NoError(t, err) + var deks []dek + for rows.Next() { + var key dek + require.NoError(t, rw.ScanRows(context.Background(), rows, &key)) + deks = append(deks, key) + } + return deks +} + +func loadCurrentDeks(t *testing.T, rw *db.Db) []dek { + t.Helper() + testCtx := context.Background() + var deks []dek + for _, purpose := range []string{"audit", "database", "oidc", "oplog", "sessions", "tokens"} { + var table string + switch purpose { + case "audit": + table = "kms_audit_key" + case "database": + table = "kms_database_key" + case "oidc": + table = "kms_oidc_key" + case "oplog": + table = "kms_oplog_key" + case "sessions": + table = "kms_session_key" + case "tokens": + table = "kms_token_key" + default: + t.Fatalf("not a supported dek %q", purpose) + } + sql := fmt.Sprintf(`select private_id, root_key_id, create_time, '%s' as purpose from %s order by private_id`, purpose, table) + rows, err := rw.Query(testCtx, sql, nil) + require.NoError(t, err) + require.NoError(t, err) + for rows.Next() { + var key dek + require.NoError(t, rw.ScanRows(context.Background(), rows, &key)) + deks = append(deks, key) + } + } + return deks +} + +func loadNewDekVersions(t *testing.T, rw *db.Db) []dekVersion { + t.Helper() + testCtx := context.Background() + rows, err := rw.Query(testCtx, `select private_id, data_key_id, root_key_version_id, version, key, create_time from kms_data_key_version order by private_id`, nil) + require.NoError(t, err) + require.NoError(t, err) + var dekVersions []dekVersion + for rows.Next() { + var v dekVersion + require.NoError(t, rw.ScanRows(context.Background(), rows, &v)) + dekVersions = append(dekVersions, v) + } + return dekVersions +} + +func loadCurrentDekVersions(t *testing.T, rw *db.Db) []dekVersion { + t.Helper() + testCtx := context.Background() + var dekVersions []dekVersion + for _, versionType := range []string{"audit", "database", "oidc", "oplog", "session", "token"} { + var table string + switch versionType { + case "audit": + table = "kms_audit_key_version" + case "database": + table = "kms_database_key_version" + case "oidc": + table = "kms_oidc_key_version" + case "oplog": + table = "kms_oplog_key_version" + case "session": + table = "kms_session_key_version" + case "token": + table = "kms_token_key_version" + } + sql := fmt.Sprintf(`select private_id, %s_key_id, root_key_version_id, key, version, create_time from %s order by private_id`, versionType, table) + rows, err := rw.Query(testCtx, sql, nil) + require.NoError(t, err) + require.NoError(t, err) + for rows.Next() { + result := map[string]interface{}{} + require.NoError(t, rw.ScanRows(context.Background(), rows, &result)) + var v dekVersion + switch versionType { + case "audit": + v = dekVersion{ + PrivateId: result["private_id"].(string), + DataKeyId: result["audit_key_id"].(string), + RootKeyVersionId: result["root_key_version_id"].(string), + Key: result["key"].([]byte), + Version: uint32(result["version"].(int64)), + CreateTime: result["create_time"].(time.Time), + } + case "database": + v = dekVersion{ + PrivateId: result["private_id"].(string), + DataKeyId: result["database_key_id"].(string), + RootKeyVersionId: result["root_key_version_id"].(string), + Key: result["key"].([]byte), + Version: uint32(result["version"].(int64)), + CreateTime: result["create_time"].(time.Time), + } + case "oidc": + v = dekVersion{ + PrivateId: result["private_id"].(string), + DataKeyId: result["oidc_key_id"].(string), + RootKeyVersionId: result["root_key_version_id"].(string), + Key: result["key"].([]byte), + Version: uint32(result["version"].(int64)), + CreateTime: result["create_time"].(time.Time), + } + case "oplog": + v = dekVersion{ + PrivateId: result["private_id"].(string), + DataKeyId: result["oplog_key_id"].(string), + RootKeyVersionId: result["root_key_version_id"].(string), + Key: result["key"].([]byte), + Version: uint32(result["version"].(int64)), + CreateTime: result["create_time"].(time.Time), + } + case "session": + v = dekVersion{ + PrivateId: result["private_id"].(string), + DataKeyId: result["session_key_id"].(string), + RootKeyVersionId: result["root_key_version_id"].(string), + Key: result["key"].([]byte), + Version: uint32(result["version"].(int64)), + CreateTime: result["create_time"].(time.Time), + } + case "token": + v = dekVersion{ + PrivateId: result["private_id"].(string), + DataKeyId: result["token_key_id"].(string), + RootKeyVersionId: result["root_key_version_id"].(string), + Key: result["key"].([]byte), + Version: uint32(result["version"].(int64)), + CreateTime: result["create_time"].(time.Time), + } + } + dekVersions = append(dekVersions, v) + } + } + return dekVersions +} + +func testId(t testing.TB, prefix string) string { + t.Helper() + id, err := db.NewPublicId(prefix) + require.NoError(t, err) + return id +} + +func testScope(t *testing.T, rw *db.Db) *iam.Scope { + t.Helper() + require := require.New(t) + testCtx := context.Background() + + s, err := iam.NewOrg() + require.NoError(err) + s.PublicId = testId(t, "o") + + require.NoError(rw.Create(testCtx, &s)) + return s +} + +type kek struct { + PrivateId string + ScopeId string + CreateTime time.Time +} + +func (*kek) TableName() string { return "kms_root_key" } + +type kekVersion struct { + PrivateId string + RootKeyId string + Version uint32 + Key []byte + CreateTime time.Time +} + +func (*kekVersion) TableName() string { return "kms_root_key_version" } + +type dek struct { + PrivateId string + RootKeyId string + CreateTime time.Time + Purpose string +} +type dekVersion struct { + PrivateId string + DataKeyId string + RootKeyVersionId string + Key []byte + Version uint32 + CreateTime time.Time +} + +type kmsDatabaseKey struct { + PrivateId string + RootKeyId string + CreateTime time.Time +} + +func (*kmsDatabaseKey) TableName() string { return "kms_database_key" } + +type kmsDatabaseKeyVersion struct { + PrivateId string + DatabaseKeyId string + RootKeyVersionId string + Key []byte + Version uint32 + CreateTime time.Time +} + +func (*kmsDatabaseKeyVersion) TableName() string { return "kms_database_key_version" } + +type kmsAuditKey struct { + PrivateId string + RootKeyId string + CreateTime time.Time +} + +func (*kmsAuditKey) TableName() string { return "kms_audit_key" } + +type kmsAuditKeyVersion struct { + PrivateId string + AuditKeyId string + RootKeyVersionId string + Key []byte + Version uint32 + CreateTime time.Time +} + +func (*kmsAuditKeyVersion) TableName() string { return "kms_audit_key_version" } + +type kmsOidcKey struct { + PrivateId string + RootKeyId string + CreateTime time.Time +} + +func (*kmsOidcKey) TableName() string { return "kms_oidc_key" } + +type kmsOidcKeyVersion struct { + PrivateId string + OidcKeyId string + RootKeyVersionId string + Key []byte + Version uint32 + CreateTime time.Time +} + +func (*kmsOidcKeyVersion) TableName() string { return "kms_oidc_key_version" } + +type kmsOplogKey struct { + PrivateId string + RootKeyId string + CreateTime time.Time +} + +func (*kmsOplogKey) TableName() string { return "kms_oplog_key" } + +type kmsOplogKeyVersion struct { + PrivateId string + OplogKeyId string + RootKeyVersionId string + Key []byte + Version uint32 + CreateTime time.Time +} + +func (*kmsOplogKeyVersion) TableName() string { return "kms_oplog_key_version" } + +type kmsSessionKey struct { + PrivateId string + RootKeyId string + CreateTime time.Time +} + +func (*kmsSessionKey) TableName() string { return "kms_session_key" } + +type kmsSessionKeyVersion struct { + PrivateId string + SessionKeyId string + RootKeyVersionId string + Key []byte + Version uint32 + CreateTime time.Time +} + +func (*kmsSessionKeyVersion) TableName() string { return "kms_session_key_version" } + +type kmsTokenKey struct { + PrivateId string + RootKeyId string + CreateTime time.Time +} + +func (*kmsTokenKey) TableName() string { return "kms_token_key" } + +type kmsTokenKeyVersion struct { + PrivateId string + TokenKeyId string + RootKeyVersionId string + Key []byte + Version uint32 + CreateTime time.Time +} + +func (*kmsTokenKeyVersion) TableName() string { return "kms_token_key_version" } diff --git a/internal/db/sqltest/initdb.d/03_widgets_persona.sql b/internal/db/sqltest/initdb.d/03_widgets_persona.sql index 8abbb0b49..c6aef2661 100644 --- a/internal/db/sqltest/initdb.d/03_widgets_persona.sql +++ b/internal/db/sqltest/initdb.d/03_widgets_persona.sql @@ -105,13 +105,13 @@ begin; values ('krkv___widget', 'krk___widget', 'krk___widget'::bytea); - insert into kms_database_key - (private_id, root_key_id) + insert into kms_data_key + (private_id, root_key_id, purpose) values - ('kdk____widget', 'krk___widget'); + ('kdk____widget', 'krk___widget', 'database'); - insert into kms_database_key_version - (private_id, database_key_id, root_key_version_id, key) + insert into kms_data_key_version + (private_id, data_key_id, root_key_version_id, key) values ('kdkv___widget', 'kdk____widget', 'krkv___widget', 'kdk____widget'::bytea); diff --git a/internal/iam/repository_scope.go b/internal/iam/repository_scope.go index 6db6c0256..103196700 100644 --- a/internal/iam/repository_scope.go +++ b/internal/iam/repository_scope.go @@ -31,7 +31,6 @@ func (r *Repository) CreateScope(ctx context.Context, s *Scope, userId string, o } var parentOplogWrapper wrapping.Wrapper - var externalWrappers *kms.ExternalWrappers var err error switch s.Type { case scope.Unknown.String(): @@ -47,7 +46,6 @@ func (r *Repository) CreateScope(ctx context.Context, s *Scope, userId string, o default: parentOplogWrapper, err = r.kms.GetWrapper(ctx, s.ParentId, kms.KeyPurposeOplog) } - externalWrappers = r.kms.GetExternalWrappers() } if err != nil { return nil, errors.New(ctx, errors.InvalidParameter, op, "unable to get oplog wrapper") @@ -174,17 +172,17 @@ func (r *Repository) CreateScope(ctx context.Context, s *Scope, userId string, o s := scopeRaw.(*Scope) - // Create the scope's keys - _, err = kms.CreateKeysTx(ctx, dbr, w, externalWrappers.Root(), reader, s.PublicId) + txnKms, err := kms.NewUsingReaderWriter(ctx, dbr, w) if err != nil { + return errors.Wrap(ctx, err, op, errors.WithMsg("error creating transaction's kms")) + } + if err := txnKms.AddExternalWrappers(ctx, kms.WithRootWrapper(r.kms.GetExternalWrappers(ctx).Root())); err != nil { + return errors.Wrap(ctx, err, op, errors.WithMsg("error adding external root wrapper to transaction's kms")) + } + if err := txnKms.CreateKeys(ctx, s.PublicId, kms.WithRandomReader(reader), kms.WithReaderWriter(dbr, w)); err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("error creating scope keys")) } - - kmsRepo, err := kms.NewRepository(dbr, w) - if err != nil { - return errors.Wrap(ctx, err, op, errors.WithMsg("error creating new kms repo")) - } - childOplogWrapper, err := r.kms.GetWrapper(ctx, s.PublicId, kms.KeyPurposeOplog, kms.WithRepository(kmsRepo)) + childOplogWrapper, err := txnKms.GetWrapper(ctx, s.PublicId, kms.KeyPurposeOplog) if err != nil { return errors.New(ctx, errors.InvalidParameter, op, "unable to get oplog wrapper") } diff --git a/internal/iam/repository_test.go b/internal/iam/repository_test.go index bb1b4d4a9..7b27a264d 100644 --- a/internal/iam/repository_test.go +++ b/internal/iam/repository_test.go @@ -160,8 +160,8 @@ func Test_Repository_delete(t *testing.T) { err = db.TestVerifyOplog(t, rw, s.PublicId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(5*time.Second)) require.NoError(err) }) - rk := kms.AllocRootKey() - db.TestDeleteWhere(t, conn, &rk, "1=1") + kms.TestKmsDeleteAllKeys(t, conn) + t.Run("nil-resource", func(t *testing.T) { assert, require := assert.New(t), require.New(t) diff --git a/internal/iam/testing.go b/internal/iam/testing.go index 81f9cb3be..e5e782863 100644 --- a/internal/iam/testing.go +++ b/internal/iam/testing.go @@ -24,7 +24,7 @@ func TestRepo(t testing.TB, conn *db.DB, rootWrapper wrapping.Wrapper, opt ...Op kmsCache := kms.TestKms(t, conn, rootWrapper) wrapper, err := kmsCache.GetWrapper(context.Background(), scope.Global.String(), kms.KeyPurposeOplog) if err != nil { - _, err = kms.CreateKeysTx(context.Background(), rw, rw, rootWrapper, rand.Reader, scope.Global.String()) + err = kmsCache.CreateKeys(context.Background(), scope.Global.String(), kms.WithRandomReader(rand.Reader)) require.NoError(err) wrapper, err = kmsCache.GetWrapper(context.Background(), scope.Global.String(), kms.KeyPurposeOplog) if err != nil { diff --git a/internal/kms/audit_key.go b/internal/kms/audit_key.go deleted file mode 100644 index 91bbb956d..000000000 --- a/internal/kms/audit_key.go +++ /dev/null @@ -1,82 +0,0 @@ -package kms - -import ( - "context" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/kms/store" - "google.golang.org/protobuf/proto" -) - -const ( - DefaultAuditKeyTableName = "kms_audit_key" -) - -type AuditKey struct { - *store.AuditKey - tableName string `gorm:"-"` -} - -// NewAuditKey creates a new in memory audit key. This key is used for crypto -// operations on audit entries. No options are currently supported. -func NewAuditKey(ctx context.Context, rootKeyId string, _ ...Option) (*AuditKey, error) { - const op = "kms.NewAuditKey" - if rootKeyId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing root key id") - } - k := &AuditKey{ - AuditKey: &store.AuditKey{ - RootKeyId: rootKeyId, - }, - } - return k, nil -} - -// AllocAuditKey will allocate a AuditKey -func AllocAuditKey() AuditKey { - return AuditKey{ - AuditKey: &store.AuditKey{}, - } -} - -// Clone creates a clone of the AuditKey -func (k *AuditKey) Clone() interface{} { - cp := proto.Clone(k.AuditKey) - return &AuditKey{ - AuditKey: cp.(*store.AuditKey), - } -} - -// VetForWrite implements db.VetForWrite() interface and validates the key -// before it's written. -func (k *AuditKey) VetForWrite(ctx context.Context, r db.Reader, opType db.OpType, opt ...db.Option) error { - const op = "kms.(AuditKey).VetForWrite" - if k.PrivateId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - switch opType { - case db.CreateOp: - if k.RootKeyId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "missing root key id") - } - case db.UpdateOp: - return errors.New(ctx, errors.InvalidParameter, op, "key is immutable") - } - return nil -} - -// TableName returns the tablename to override the default gorm table name -func (k *AuditKey) TableName() string { - if k.tableName != "" { - return k.tableName - } - return DefaultAuditKeyTableName -} - -// SetTableName sets the tablename and satisfies the ReplayableMessage -// interface. If the caller attempts to set the name to "" the name will be -// reset to the default name. -func (k *AuditKey) SetTableName(n string) { - k.tableName = n -} diff --git a/internal/kms/audit_key_test.go b/internal/kms/audit_key_test.go deleted file mode 100644 index 2037a4ae2..000000000 --- a/internal/kms/audit_key_test.go +++ /dev/null @@ -1,209 +0,0 @@ -package kms_test - -import ( - "context" - "testing" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/iam" - "github.com/hashicorp/boundary/internal/kms" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" -) - -// NOTE: there are no update tests since all the AuditKey attributes are -// immutable and those tests are covered by TestAuditKey_ImmutableFields - -func TestAuditKey_Create(t *testing.T) { - t.Parallel() - testCtx := context.Background() - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - - type args struct { - rootKeyId string - opt []kms.Option - } - tests := []struct { - name string - args args - want *kms.AuditKey - wantErr bool - wantIsErr errors.Code - create bool - wantCreateErr bool - }{ - { - name: "empty-rootKeyId", - args: args{}, - wantErr: true, - wantIsErr: errors.InvalidParameter, - }, - { - name: "valid", - args: args{ - rootKeyId: rk.PrivateId, - }, - want: func() *kms.AuditKey { - k := kms.AllocAuditKey() - k.RootKeyId = rk.PrivateId - return &k - }(), - create: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocAuditKey(); return &i }(), "1=1") - got, err := kms.NewAuditKey(testCtx, tt.args.rootKeyId, tt.args.opt...) - if tt.wantErr { - require.Error(err) - assert.True(errors.Match(errors.T(tt.wantIsErr), err)) - return - } - require.NoError(err) - assert.Equal(tt.want, got) - if tt.create { - id, err := db.NewPublicId(kms.AuditKeyPrefix) - require.NoError(err) - got.PrivateId = id - err = db.New(conn).Create(context.Background(), got) - if tt.wantCreateErr { - assert.Error(err) - return - } else { - assert.NoError(err) - } - } - }) - } -} - -func TestAuditKey_Delete(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - - rk := kms.TestRootKey(t, conn, org.PublicId) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocAuditKey(); return &i }(), "1=1") - - tests := []struct { - name string - key *kms.AuditKey - wantRowsDeleted int - wantErr bool - wantErrMsg string - }{ - { - name: "valid", - key: kms.TestAuditKey(t, conn, rk.PrivateId), - wantErr: false, - wantRowsDeleted: 1, - }, - { - name: "bad-id", - key: func() *kms.AuditKey { - k := kms.AllocAuditKey() - id, err := db.NewPublicId(kms.AuditKeyPrefix) - require.NoError(t, err) - k.PrivateId = id - k.RootKeyId = rk.PrivateId - return &k - }(), - wantErr: false, - wantRowsDeleted: 0, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - deleteKey := kms.AllocAuditKey() - deleteKey.PrivateId = tt.key.PrivateId - deletedRows, err := rw.Delete(context.Background(), &deleteKey) - if tt.wantErr { - require.Error(err) - return - } - require.NoError(err) - if tt.wantRowsDeleted == 0 { - assert.Equal(tt.wantRowsDeleted, deletedRows) - return - } - assert.Equal(tt.wantRowsDeleted, deletedRows) - foundKey := kms.AllocAuditKey() - foundKey.PrivateId = tt.key.PrivateId - err = rw.LookupById(context.Background(), &foundKey) - require.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestAuditKey_Clone(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - t.Run("valid", func(t *testing.T) { - assert := assert.New(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - - rk := kms.TestRootKey(t, conn, org.PublicId) - k := kms.TestAuditKey(t, conn, rk.PrivateId) - cp := k.Clone() - assert.True(proto.Equal(cp.(*kms.AuditKey).AuditKey, k.AuditKey)) - }) - t.Run("not-equal", func(t *testing.T) { - assert := assert.New(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - org2, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - rk2 := kms.TestRootKey(t, conn, org2.PublicId) - k := kms.TestAuditKey(t, conn, rk.PrivateId) - k2 := kms.TestAuditKey(t, conn, rk2.PrivateId) - - cp := k.Clone() - assert.True(!proto.Equal(cp.(*kms.AuditKey).AuditKey, k2.AuditKey)) - }) -} - -func TestAuditKey_SetTableName(t *testing.T) { - t.Parallel() - defaultTableName := kms.DefaultAuditKeyTableName - tests := []struct { - name string - setNameTo string - want string - }{ - { - name: "new-name", - setNameTo: "new-name", - want: "new-name", - }, - { - name: "reset to default", - setNameTo: "", - want: defaultTableName, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - def := kms.AllocAuditKey() - require.Equal(defaultTableName, def.TableName()) - s := kms.AllocAuditKey() - s.SetTableName(tt.setNameTo) - assert.Equal(tt.want, s.TableName()) - }) - } -} diff --git a/internal/kms/audit_key_version.go b/internal/kms/audit_key_version.go deleted file mode 100644 index cb5971e65..000000000 --- a/internal/kms/audit_key_version.go +++ /dev/null @@ -1,122 +0,0 @@ -package kms - -import ( - "context" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/kms/store" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" - "github.com/hashicorp/go-kms-wrapping/v2/extras/structwrapping" - "google.golang.org/protobuf/proto" -) - -const ( - DefaultAuditKeyVersionTableName = "kms_audit_key_version" -) - -type AuditKeyVersion struct { - *store.AuditKeyVersion - tableName string `gorm:"-"` -} - -// NewAuditKeyVersion creates a new in memory audit key version. This key is -// used for crypto operations on audit entries. No options are currently -// supported. -func NewAuditKeyVersion(ctx context.Context, auditKeyId string, key []byte, rootKeyVersionId string, _ ...Option) (*AuditKeyVersion, error) { - const op = "kms.NewAuditKeyVersion" - if auditKeyId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing audit key id") - } - if len(key) == 0 { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing key") - } - if rootKeyVersionId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing root key version id") - } - - k := &AuditKeyVersion{ - AuditKeyVersion: &store.AuditKeyVersion{ - AuditKeyId: auditKeyId, - RootKeyVersionId: rootKeyVersionId, - Key: key, - }, - } - return k, nil -} - -// AllocAuditKeyVersion allocates a AuditKeyVersion -func AllocAuditKeyVersion() AuditKeyVersion { - return AuditKeyVersion{ - AuditKeyVersion: &store.AuditKeyVersion{}, - } -} - -// Clone creates a clone of the AuditKeyVersion -func (k *AuditKeyVersion) Clone() interface{} { - cp := proto.Clone(k.AuditKeyVersion) - return &AuditKeyVersion{ - AuditKeyVersion: cp.(*store.AuditKeyVersion), - } -} - -// VetForWrite implements db.VetForWrite() interface and validates the audit key -// version before it's written. -func (k *AuditKeyVersion) VetForWrite(ctx context.Context, r db.Reader, opType db.OpType, opt ...db.Option) error { - const op = "kms.(AuditKeyVersion).VetForWrite" - if k.PrivateId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - switch opType { - case db.CreateOp: - if k.CtKey == nil { - return errors.New(ctx, errors.InvalidParameter, op, "missing key") - } - if k.AuditKeyId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "missing audit key id") - } - if k.RootKeyVersionId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "missing root key version id") - } - case db.UpdateOp: - return errors.New(ctx, errors.InvalidParameter, op, "key is immutable") - } - return nil -} - -// TableName returns the tablename to override the default gorm table name -func (k *AuditKeyVersion) TableName() string { - if k.tableName != "" { - return k.tableName - } - return DefaultAuditKeyVersionTableName -} - -// SetTableName sets the tablename and satisfies the ReplayableMessage -// interface. If the caller attempts to set the name to "" the name will be -// reset to the default name. -func (k *AuditKeyVersion) SetTableName(n string) { - k.tableName = n -} - -// Encrypt will encrypt the audit key version's key -func (k *AuditKeyVersion) Encrypt(ctx context.Context, cipher wrapping.Wrapper) error { - const op = "kms.(AuditKeyVersion).Encrypt" - // structwrapping doesn't support embedding, so we'll pass in the - // store.AuditKeyVersion directly - if err := structwrapping.WrapStruct(ctx, cipher, k.AuditKeyVersion, nil); err != nil { - return errors.Wrap(ctx, err, op, errors.WithCode(errors.Encrypt)) - } - return nil -} - -// Decrypt will decrypt the audit key version's key -func (k *AuditKeyVersion) Decrypt(ctx context.Context, cipher wrapping.Wrapper) error { - const op = "kms.(AuditKeyVersion).Decrypt" - // structwrapping doesn't support embedding, so we'll pass in the - // store.AuditKeyVersion directly - if err := structwrapping.UnwrapStruct(ctx, cipher, k.AuditKeyVersion, nil); err != nil { - return errors.Wrap(ctx, err, op, errors.WithCode(errors.Decrypt)) - } - return nil -} diff --git a/internal/kms/audit_key_version_test.go b/internal/kms/audit_key_version_test.go deleted file mode 100644 index 431f617d8..000000000 --- a/internal/kms/audit_key_version_test.go +++ /dev/null @@ -1,250 +0,0 @@ -package kms_test - -import ( - "context" - "testing" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/iam" - "github.com/hashicorp/boundary/internal/kms" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" -) - -// NOTE: there are no update tests since all the AuditKeyVersion attributes are -// immutable and those tests are covered by TestAuditKey_ImmutableFields - -func TestAuditKeyVersion_Create(t *testing.T) { - t.Parallel() - testCtx := context.Background() - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - rkv, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - - dk := kms.TestAuditKey(t, conn, rk.PrivateId) - - type args struct { - AuditKeyId string - key []byte - rootKeyVersionId string - opt []kms.Option - } - tests := []struct { - name string - args args - want *kms.AuditKeyVersion - wantErr bool - wantIsErr errors.Code - create bool - wantCreateErr bool - }{ - { - name: "empty-audit-id", - args: args{ - key: []byte("audit key"), - rootKeyVersionId: rkv.PrivateId, - }, - wantErr: true, - wantIsErr: errors.InvalidParameter, - }, - { - name: "empty-key", - args: args{ - AuditKeyId: dk.PrivateId, - rootKeyVersionId: rkv.PrivateId, - }, - wantErr: true, - wantIsErr: errors.InvalidParameter, - }, - { - name: "empty-root-key-version-id", - args: args{ - AuditKeyId: dk.PrivateId, - key: []byte("audit key"), - }, - wantErr: true, - wantIsErr: errors.InvalidParameter, - }, - { - name: "valid", - args: args{ - AuditKeyId: dk.PrivateId, - key: []byte("audit key"), - rootKeyVersionId: rkv.PrivateId, - }, - want: func() *kms.AuditKeyVersion { - k := kms.AllocAuditKeyVersion() - k.RootKeyVersionId = rkv.PrivateId - k.Key = []byte("audit key") - k.AuditKeyId = dk.PrivateId - return &k - }(), - create: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocAuditKeyVersion(); return &i }(), "1=1") - got, err := kms.NewAuditKeyVersion(testCtx, tt.args.AuditKeyId, tt.args.key, tt.args.rootKeyVersionId, tt.args.opt...) - if tt.wantErr { - require.Error(err) - assert.True(errors.Match(errors.T(tt.wantIsErr), err)) - return - } - require.NoError(err) - assert.Equal(tt.want, got) - if tt.create { - id, err := db.NewPublicId(kms.AuditKeyPrefix) - require.NoError(err) - got.PrivateId = id - err = got.Encrypt(context.Background(), rkvWrapper) - require.NoError(err) - err = db.New(conn).Create(context.Background(), got) - if tt.wantCreateErr { - assert.Error(err) - return - } else { - assert.NoError(err) - } - } - }) - } -} - -func TestAuditKeyVersion_Delete(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - dk := kms.TestAuditKey(t, conn, rk.PrivateId) - - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocAuditKeyVersion(); return &i }(), "1=1") - - tests := []struct { - name string - key *kms.AuditKeyVersion - wantRowsDeleted int - wantErr bool - wantErrMsg string - }{ - { - name: "valid", - key: kms.TestAuditKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("audit key")), - wantErr: false, - wantRowsDeleted: 1, - }, - { - name: "bad-id", - key: func() *kms.AuditKeyVersion { - k := kms.AllocAuditKeyVersion() - id, err := db.NewPublicId(kms.AuditKeyVersionPrefix) - require.NoError(t, err) - k.PrivateId = id - return &k - }(), - wantErr: false, - wantRowsDeleted: 0, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - deleteKey := kms.AllocAuditKeyVersion() - deleteKey.PrivateId = tt.key.PrivateId - deletedRows, err := rw.Delete(context.Background(), &deleteKey) - if tt.wantErr { - require.Error(err) - return - } - require.NoError(err) - if tt.wantRowsDeleted == 0 { - assert.Equal(tt.wantRowsDeleted, deletedRows) - return - } - assert.Equal(tt.wantRowsDeleted, deletedRows) - foundKey := kms.AllocAuditKeyVersion() - foundKey.PrivateId = tt.key.PrivateId - err = rw.LookupById(context.Background(), &foundKey) - require.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestAuditKeyVersion_Clone(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - t.Run("valid", func(t *testing.T) { - assert := assert.New(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - - k := kms.TestAuditKey(t, conn, rk.PrivateId) - kv := kms.TestAuditKeyVersion(t, conn, rkvWrapper, k.PrivateId, []byte("test db key")) - cp := kv.Clone() - assert.True(proto.Equal(cp.(*kms.AuditKeyVersion).AuditKeyVersion, kv.AuditKeyVersion)) - }) - t.Run("not-equal", func(t *testing.T) { - assert := assert.New(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - org2, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - rk2 := kms.TestRootKey(t, conn, org2.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - _, rkvWrapper2 := kms.TestRootKeyVersion(t, conn, wrapper, rk2.PrivateId) - - k := kms.TestAuditKey(t, conn, rk.PrivateId) - k2 := kms.TestAuditKey(t, conn, rk2.PrivateId) - kv := kms.TestAuditKeyVersion(t, conn, rkvWrapper, k.PrivateId, []byte("test db key")) - kv2 := kms.TestAuditKeyVersion(t, conn, rkvWrapper2, k2.PrivateId, []byte("test db key 2")) - - cp := kv.Clone() - assert.True(!proto.Equal(cp.(*kms.AuditKeyVersion).AuditKeyVersion, kv2.AuditKeyVersion)) - }) -} - -func TestAuditKeyVersion_SetTableName(t *testing.T) { - t.Parallel() - defaultTableName := kms.DefaultAuditKeyVersionTableName - tests := []struct { - name string - setNameTo string - want string - }{ - { - name: "new-name", - setNameTo: "new-name", - want: "new-name", - }, - { - name: "reset to default", - setNameTo: "", - want: defaultTableName, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - def := kms.AllocAuditKeyVersion() - require.Equal(defaultTableName, def.TableName()) - s := kms.AllocAuditKeyVersion() - s.SetTableName(tt.setNameTo) - assert.Equal(tt.want, s.TableName()) - }) - } -} diff --git a/internal/kms/const.go b/internal/kms/const.go index 54020a20d..a08fddf3d 100644 --- a/internal/kms/const.go +++ b/internal/kms/const.go @@ -24,6 +24,9 @@ const ( // KeyPurposeRecovery is used for recovery access KeyPurposeRecovery + // KeyPurposeWorkerAuth is used for worker auth + KeyPurposeWorkerAuth + // KeyPurposeTokens is used for token encryption KeyPurposeTokens @@ -36,6 +39,9 @@ const ( // KeyPurposeAudit is used for audit operations KeyPurposeAudit + + // KeyPurposeRootKey is used as the root key + KeyPurposeRootKey ) // String returns the key purpose cast as a string, just so it can be called as @@ -48,6 +54,8 @@ func (k KeyPurpose) String() string { return "oplog" case KeyPurposeRecovery: return "recovery" + case KeyPurposeWorkerAuth: + return "workerauth" case KeyPurposeTokens: return "tokens" case KeyPurposeSessions: @@ -56,67 +64,21 @@ func (k KeyPurpose) String() string { return "oidc" case KeyPurposeAudit: return "audit" - default: - return "unknown" - } -} - -// KeyType allows the kms repo to return a map[KeyType]Key which can be easily -// used without type casting. -type KeyType uint - -const ( - KeyTypeUnknown KeyType = iota - KeyTypeRootKey - KeyTypeRootKeyVersion - KeyTypeDatabaseKey - KeyTypeDatabaseKeyVersion - KeyTypeOplogKey - KeyTypeOplogKeyVersion - KeyTypeTokenKey - KeyTypeTokenKeyVersion - KeyTypeSessionKey - KeyTypeSessionKeyVersion - KeyTypeOidcKey - KeyTypeOidcKeyVersion - KeyTypeAuditKey - KeyTypeAuditKeyVersion -) - -// String returns the key type cast as a string, just so it can be called as -// a function instead of direct casting elsewhere, yw -func (k KeyType) String() string { - switch k { - case KeyTypeRootKey: + case KeyPurposeRootKey: return "rootKey" - case KeyTypeRootKeyVersion: - return "rootKeyVersion" - case KeyTypeDatabaseKey: - return "databaseKey" - case KeyTypeDatabaseKeyVersion: - return "databaseKeyVersion" - case KeyTypeOplogKey: - return "oplogKey" - case KeyTypeOplogKeyVersion: - return "oplogKeyVersion" - case KeyTypeTokenKey: - return "tokenKey" - case KeyTypeTokenKeyVersion: - return "tokenKeyVersion" - case KeyTypeSessionKey: - return "sessionKey" - case KeyTypeSessionKeyVersion: - return "sessionKeyVersion" - case KeyTypeOidcKey: - return "oidcKey" - case KeyTypeOidcKeyVersion: - return "oidcKeyVersion" - case KeyTypeAuditKey: - return "auditKey" - case KeyTypeAuditKeyVersion: - return "auditKeyVersion" - default: return "unknown" } } + +// ValidDekPurposes returns the current list of valid DEK key purposes +func ValidDekPurposes() []KeyPurpose { + return []KeyPurpose{ + KeyPurposeDatabase, + KeyPurposeOplog, + KeyPurposeTokens, + KeyPurposeSessions, + KeyPurposeOidc, + KeyPurposeAudit, + } +} diff --git a/internal/kms/database_key.go b/internal/kms/database_key.go deleted file mode 100644 index ae81f2674..000000000 --- a/internal/kms/database_key.go +++ /dev/null @@ -1,82 +0,0 @@ -package kms - -import ( - "context" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/kms/store" - "google.golang.org/protobuf/proto" -) - -const ( - DefaultDatabaseKeyTableName = "kms_database_key" -) - -type DatabaseKey struct { - *store.DatabaseKey - tableName string `gorm:"-"` -} - -// NewDatabaseKey creates a new in memory database key. No options -// are currently supported. -func NewDatabaseKey(rootKeyId string, _ ...Option) (*DatabaseKey, error) { - const op = "kms.NewDatabaseKey" - if rootKeyId == "" { - return nil, errors.NewDeprecated(errors.InvalidParameter, op, "missing root key id") - } - c := &DatabaseKey{ - DatabaseKey: &store.DatabaseKey{ - RootKeyId: rootKeyId, - }, - } - return c, nil -} - -// AllocDatabaseKey will allocate a DatabaseKey -func AllocDatabaseKey() DatabaseKey { - return DatabaseKey{ - DatabaseKey: &store.DatabaseKey{}, - } -} - -// Clone creates a clone of the DatabaseKey -func (k *DatabaseKey) Clone() interface{} { - cp := proto.Clone(k.DatabaseKey) - return &DatabaseKey{ - DatabaseKey: cp.(*store.DatabaseKey), - } -} - -// VetForWrite implements db.VetForWrite() interface and validates the key -// before it's written. -func (k *DatabaseKey) VetForWrite(ctx context.Context, r db.Reader, opType db.OpType, opt ...db.Option) error { - const op = "kms.(DatabaseKey).VetForWrite" - if k.PrivateId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - switch opType { - case db.CreateOp: - if k.RootKeyId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "missing root key id") - } - case db.UpdateOp: - return errors.New(ctx, errors.InvalidParameter, op, "key is immutable") - } - return nil -} - -// TableName returns the tablename to override the default gorm table name -func (k *DatabaseKey) TableName() string { - if k.tableName != "" { - return k.tableName - } - return DefaultDatabaseKeyTableName -} - -// SetTableName sets the tablename and satisfies the ReplayableMessage -// interface. If the caller attempts to set the name to "" the name will be -// reset to the default name. -func (k *DatabaseKey) SetTableName(n string) { - k.tableName = n -} diff --git a/internal/kms/database_key_test.go b/internal/kms/database_key_test.go deleted file mode 100644 index 340a562b7..000000000 --- a/internal/kms/database_key_test.go +++ /dev/null @@ -1,206 +0,0 @@ -package kms_test - -import ( - "context" - "testing" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/iam" - "github.com/hashicorp/boundary/internal/kms" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" -) - -// NOTE: there are no update tests since all the DatabaseKey attributes are -// immutable and those tests are covered by TestDatabaseKey_ImmutableFields - -func TestDatabaseKey_Create(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - - type args struct { - rootKeyId string - opt []kms.Option - } - tests := []struct { - name string - args args - want *kms.DatabaseKey - wantErr bool - wantIsErr errors.Code - create bool - wantCreateErr bool - }{ - { - name: "empty-rootKeyId", - args: args{}, - wantErr: true, - wantIsErr: errors.InvalidParameter, - }, - { - name: "valid", - args: args{ - rootKeyId: rk.PrivateId, - }, - want: func() *kms.DatabaseKey { - k := kms.AllocDatabaseKey() - k.RootKeyId = rk.PrivateId - return &k - }(), - create: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocDatabaseKey(); return &i }(), "1=1") - got, err := kms.NewDatabaseKey(tt.args.rootKeyId, tt.args.opt...) - if tt.wantErr { - require.Error(err) - assert.True(errors.Match(errors.T(tt.wantIsErr), err)) - return - } - require.NoError(err) - assert.Equal(tt.want, got) - if tt.create { - id, err := db.NewPublicId(kms.DatabaseKeyPrefix) - require.NoError(err) - got.PrivateId = id - err = db.New(conn).Create(context.Background(), got) - if tt.wantCreateErr { - assert.Error(err) - return - } else { - assert.NoError(err) - } - } - }) - } -} - -func TestDatabaseKey_Delete(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocDatabaseKey(); return &i }(), "1=1") - - tests := []struct { - name string - key *kms.DatabaseKey - wantRowsDeleted int - wantErr bool - wantErrMsg string - }{ - { - name: "valid", - key: kms.TestDatabaseKey(t, conn, rk.PrivateId), - wantErr: false, - wantRowsDeleted: 1, - }, - { - name: "bad-id", - key: func() *kms.DatabaseKey { - k := kms.AllocDatabaseKey() - id, err := db.NewPublicId(kms.DatabaseKeyPrefix) - require.NoError(t, err) - k.PrivateId = id - k.RootKeyId = rk.PrivateId - return &k - }(), - wantErr: false, - wantRowsDeleted: 0, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - deleteKey := kms.AllocDatabaseKey() - deleteKey.PrivateId = tt.key.PrivateId - deletedRows, err := rw.Delete(context.Background(), &deleteKey) - if tt.wantErr { - require.Error(err) - return - } - require.NoError(err) - if tt.wantRowsDeleted == 0 { - assert.Equal(tt.wantRowsDeleted, deletedRows) - return - } - assert.Equal(tt.wantRowsDeleted, deletedRows) - foundKey := kms.AllocDatabaseKey() - foundKey.PrivateId = tt.key.PrivateId - err = rw.LookupById(context.Background(), &foundKey) - require.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestDatabaseKey_Clone(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - t.Run("valid", func(t *testing.T) { - assert := assert.New(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - k := kms.TestDatabaseKey(t, conn, rk.PrivateId) - cp := k.Clone() - assert.True(proto.Equal(cp.(*kms.DatabaseKey).DatabaseKey, k.DatabaseKey)) - }) - t.Run("not-equal", func(t *testing.T) { - assert := assert.New(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - org2, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - rk2 := kms.TestRootKey(t, conn, org2.PublicId) - k := kms.TestDatabaseKey(t, conn, rk.PrivateId) - k2 := kms.TestDatabaseKey(t, conn, rk2.PrivateId) - - cp := k.Clone() - assert.True(!proto.Equal(cp.(*kms.DatabaseKey).DatabaseKey, k2.DatabaseKey)) - }) -} - -func TestDatabaseKey_SetTableName(t *testing.T) { - t.Parallel() - defaultTableName := kms.DefaultDatabaseKeyTableName - tests := []struct { - name string - setNameTo string - want string - }{ - { - name: "new-name", - setNameTo: "new-name", - want: "new-name", - }, - { - name: "reset to default", - setNameTo: "", - want: defaultTableName, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - def := kms.AllocDatabaseKey() - require.Equal(defaultTableName, def.TableName()) - s := kms.AllocDatabaseKey() - s.SetTableName(tt.setNameTo) - assert.Equal(tt.want, s.TableName()) - }) - } -} diff --git a/internal/kms/database_key_version.go b/internal/kms/database_key_version.go deleted file mode 100644 index d2787a706..000000000 --- a/internal/kms/database_key_version.go +++ /dev/null @@ -1,121 +0,0 @@ -package kms - -import ( - "context" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/kms/store" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" - "github.com/hashicorp/go-kms-wrapping/v2/extras/structwrapping" - "google.golang.org/protobuf/proto" -) - -const ( - DefaultDatabaseKeyVersionTableName = "kms_database_key_version" -) - -type DatabaseKeyVersion struct { - *store.DatabaseKeyVersion - tableName string `gorm:"-"` -} - -// NewDatabaseKeyVersion creates a new in memory database key version. No options are -// currently supported. -func NewDatabaseKeyVersion(databaseKeyId string, key []byte, rootKeyVersionId string, _ ...Option) (*DatabaseKeyVersion, error) { - const op = "kms.NewDatabaseKeyVersion" - if databaseKeyId == "" { - return nil, errors.NewDeprecated(errors.InvalidParameter, op, "missing database key id") - } - if len(key) == 0 { - return nil, errors.NewDeprecated(errors.InvalidParameter, op, "missing key") - } - if rootKeyVersionId == "" { - return nil, errors.NewDeprecated(errors.InvalidParameter, op, "missing root key version id") - } - - k := &DatabaseKeyVersion{ - DatabaseKeyVersion: &store.DatabaseKeyVersion{ - DatabaseKeyId: databaseKeyId, - RootKeyVersionId: rootKeyVersionId, - Key: key, - }, - } - return k, nil -} - -// AllocDatabaseKeyVersion allocates a DatabaseKeyVersion -func AllocDatabaseKeyVersion() DatabaseKeyVersion { - return DatabaseKeyVersion{ - DatabaseKeyVersion: &store.DatabaseKeyVersion{}, - } -} - -// Clone creates a clone of the DatabaseKeyVersion -func (k *DatabaseKeyVersion) Clone() interface{} { - cp := proto.Clone(k.DatabaseKeyVersion) - return &DatabaseKeyVersion{ - DatabaseKeyVersion: cp.(*store.DatabaseKeyVersion), - } -} - -// VetForWrite implements db.VetForWrite() interface and validates the database key -// version before it's written. -func (k *DatabaseKeyVersion) VetForWrite(ctx context.Context, r db.Reader, opType db.OpType, opt ...db.Option) error { - const op = "kms.(DatabaseKeyVersion).VetForWrite" - if k.PrivateId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - switch opType { - case db.CreateOp: - if k.CtKey == nil { - return errors.New(ctx, errors.InvalidParameter, op, "missing key") - } - if k.DatabaseKeyId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "missing database key id") - } - if k.RootKeyVersionId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "missing root key version id") - } - case db.UpdateOp: - return errors.New(ctx, errors.InvalidParameter, op, "key is immutable") - } - return nil -} - -// TableName returns the tablename to override the default gorm table name -func (k *DatabaseKeyVersion) TableName() string { - if k.tableName != "" { - return k.tableName - } - return DefaultDatabaseKeyVersionTableName -} - -// SetTableName sets the tablename and satisfies the ReplayableMessage -// interface. If the caller attempts to set the name to "" the name will be -// reset to the default name. -func (k *DatabaseKeyVersion) SetTableName(n string) { - k.tableName = n -} - -// Encrypt will encrypt the database key version's key -func (k *DatabaseKeyVersion) Encrypt(ctx context.Context, cipher wrapping.Wrapper) error { - const op = "kms.(DatabaseKeyVersion).Encrypt" - // structwrapping doesn't support embedding, so we'll pass in the - // store.DatabaseKeyVersion directly - if err := structwrapping.WrapStruct(ctx, cipher, k.DatabaseKeyVersion, nil); err != nil { - return errors.Wrap(ctx, err, op, errors.WithCode(errors.Encrypt)) - } - return nil -} - -// Decrypt will decrypt the database key version's key -func (k *DatabaseKeyVersion) Decrypt(ctx context.Context, cipher wrapping.Wrapper) error { - const op = "kms.(DatabaseKeyVersion).Decrypt" - // structwrapping doesn't support embedding, so we'll pass in the - // store.DatabaseKeyVersion directly - if err := structwrapping.UnwrapStruct(ctx, cipher, k.DatabaseKeyVersion, nil); err != nil { - return errors.Wrap(ctx, err, op, errors.WithCode(errors.Decrypt)) - } - return nil -} diff --git a/internal/kms/database_key_version_test.go b/internal/kms/database_key_version_test.go deleted file mode 100644 index a879b6997..000000000 --- a/internal/kms/database_key_version_test.go +++ /dev/null @@ -1,249 +0,0 @@ -package kms_test - -import ( - "context" - "testing" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/iam" - "github.com/hashicorp/boundary/internal/kms" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" -) - -// NOTE: there are no update tests since all the DatabaseKeyVersion attributes are -// immutable and those tests are covered by TestDatabaseKey_ImmutableFields - -func TestDatabaseKeyVersion_Create(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - rkv, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - - dk := kms.TestDatabaseKey(t, conn, rk.PrivateId) - - type args struct { - databaseKeyId string - key []byte - rootKeyVersionId string - opt []kms.Option - } - tests := []struct { - name string - args args - want *kms.DatabaseKeyVersion - wantErr bool - wantIsErr errors.Code - create bool - wantCreateErr bool - }{ - { - name: "empty-database-id", - args: args{ - key: []byte("database key"), - rootKeyVersionId: rkv.PrivateId, - }, - wantErr: true, - wantIsErr: errors.InvalidParameter, - }, - { - name: "empty-key", - args: args{ - databaseKeyId: dk.PrivateId, - rootKeyVersionId: rkv.PrivateId, - }, - wantErr: true, - wantIsErr: errors.InvalidParameter, - }, - { - name: "empty-root-key-version-id", - args: args{ - databaseKeyId: dk.PrivateId, - key: []byte("database key"), - }, - wantErr: true, - wantIsErr: errors.InvalidParameter, - }, - { - name: "valid", - args: args{ - databaseKeyId: dk.PrivateId, - key: []byte("database key"), - rootKeyVersionId: rkv.PrivateId, - }, - want: func() *kms.DatabaseKeyVersion { - k := kms.AllocDatabaseKeyVersion() - k.RootKeyVersionId = rkv.PrivateId - k.Key = []byte("database key") - k.DatabaseKeyId = dk.PrivateId - return &k - }(), - create: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocDatabaseKeyVersion(); return &i }(), "1=1") - got, err := kms.NewDatabaseKeyVersion(tt.args.databaseKeyId, tt.args.key, tt.args.rootKeyVersionId, tt.args.opt...) - if tt.wantErr { - require.Error(err) - assert.True(errors.Match(errors.T(tt.wantIsErr), err)) - return - } - require.NoError(err) - assert.Equal(tt.want, got) - if tt.create { - id, err := db.NewPublicId(kms.DatabaseKeyPrefix) - require.NoError(err) - got.PrivateId = id - err = got.Encrypt(context.Background(), rkvWrapper) - require.NoError(err) - err = db.New(conn).Create(context.Background(), got) - if tt.wantCreateErr { - assert.Error(err) - return - } else { - assert.NoError(err) - } - } - }) - } -} - -func TestDatabaseKeyVersion_Delete(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - dk := kms.TestDatabaseKey(t, conn, rk.PrivateId) - - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocDatabaseKeyVersion(); return &i }(), "1=1") - - tests := []struct { - name string - key *kms.DatabaseKeyVersion - wantRowsDeleted int - wantErr bool - wantErrMsg string - }{ - { - name: "valid", - key: kms.TestDatabaseKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("database key")), - wantErr: false, - wantRowsDeleted: 1, - }, - { - name: "bad-id", - key: func() *kms.DatabaseKeyVersion { - k := kms.AllocDatabaseKeyVersion() - id, err := db.NewPublicId(kms.DatabaseKeyVersionPrefix) - require.NoError(t, err) - k.PrivateId = id - return &k - }(), - wantErr: false, - wantRowsDeleted: 0, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - deleteKey := kms.AllocDatabaseKeyVersion() - deleteKey.PrivateId = tt.key.PrivateId - deletedRows, err := rw.Delete(context.Background(), &deleteKey) - if tt.wantErr { - require.Error(err) - return - } - require.NoError(err) - if tt.wantRowsDeleted == 0 { - assert.Equal(tt.wantRowsDeleted, deletedRows) - return - } - assert.Equal(tt.wantRowsDeleted, deletedRows) - foundKey := kms.AllocDatabaseKeyVersion() - foundKey.PrivateId = tt.key.PrivateId - err = rw.LookupById(context.Background(), &foundKey) - require.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestDatabaseKeyVersion_Clone(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - t.Run("valid", func(t *testing.T) { - assert := assert.New(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - - k := kms.TestDatabaseKey(t, conn, rk.PrivateId) - kv := kms.TestDatabaseKeyVersion(t, conn, rkvWrapper, k.PrivateId, []byte("test db key")) - cp := kv.Clone() - assert.True(proto.Equal(cp.(*kms.DatabaseKeyVersion).DatabaseKeyVersion, kv.DatabaseKeyVersion)) - }) - t.Run("not-equal", func(t *testing.T) { - assert := assert.New(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - org2, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - rk2 := kms.TestRootKey(t, conn, org2.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - _, rkvWrapper2 := kms.TestRootKeyVersion(t, conn, wrapper, rk2.PrivateId) - - k := kms.TestDatabaseKey(t, conn, rk.PrivateId) - k2 := kms.TestDatabaseKey(t, conn, rk2.PrivateId) - kv := kms.TestDatabaseKeyVersion(t, conn, rkvWrapper, k.PrivateId, []byte("test db key")) - kv2 := kms.TestDatabaseKeyVersion(t, conn, rkvWrapper2, k2.PrivateId, []byte("test db key 2")) - - cp := kv.Clone() - assert.True(!proto.Equal(cp.(*kms.DatabaseKeyVersion).DatabaseKeyVersion, kv2.DatabaseKeyVersion)) - }) -} - -func TestDatabaseKeyVersion_SetTableName(t *testing.T) { - t.Parallel() - defaultTableName := kms.DefaultDatabaseKeyVersionTableName - tests := []struct { - name string - setNameTo string - want string - }{ - { - name: "new-name", - setNameTo: "new-name", - want: "new-name", - }, - { - name: "reset to default", - setNameTo: "", - want: defaultTableName, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - def := kms.AllocDatabaseKeyVersion() - require.Equal(defaultTableName, def.TableName()) - s := kms.AllocDatabaseKeyVersion() - s.SetTableName(tt.setNameTo) - assert.Equal(tt.want, s.TableName()) - }) - } -} diff --git a/internal/kms/external_wrappers.go b/internal/kms/external_wrappers.go new file mode 100644 index 000000000..48507f12d --- /dev/null +++ b/internal/kms/external_wrappers.go @@ -0,0 +1,28 @@ +package kms + +import ( + wrapping "github.com/hashicorp/go-kms-wrapping/v2" +) + +// ExternalWrappers holds wrappers defined outside of Boundary, e.g. in its +// configuration file. +type ExternalWrappers struct { + root wrapping.Wrapper + workerAuth wrapping.Wrapper + recovery wrapping.Wrapper +} + +// Root returns the wrapper for root keys +func (e *ExternalWrappers) Root() wrapping.Wrapper { + return e.root +} + +// WorkerAuth returns the wrapper for worker authentication +func (e *ExternalWrappers) WorkerAuth() wrapping.Wrapper { + return e.workerAuth +} + +// Recovery returns the wrapper for recovery operations +func (e *ExternalWrappers) Recovery() wrapping.Wrapper { + return e.recovery +} diff --git a/internal/kms/external_wrappers_test.go b/internal/kms/external_wrappers_test.go new file mode 100644 index 000000000..be43c61a6 --- /dev/null +++ b/internal/kms/external_wrappers_test.go @@ -0,0 +1,46 @@ +package kms + +import ( + "context" + "fmt" + "testing" + + "github.com/hashicorp/boundary/internal/db" + wrapping "github.com/hashicorp/go-kms-wrapping/v2" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestExternalWrappers(t *testing.T) { + t.Parallel() + assert, require := assert.New(t), require.New(t) + + testCtx := context.Background() + conn, _ := db.TestSetup(t, "postgres") + rootWrapper := db.TestWrapper(t) + recoveryWrapper := db.TestWrapper(t) + workerAuthWrapper := db.TestWrapper(t) + + k := TestKms(t, conn, rootWrapper) + err := k.AddExternalWrappers(testCtx, WithRecoveryWrapper(recoveryWrapper), WithWorkerAuthWrapper(workerAuthWrapper)) + require.NoError(err) + + assert.Equal(rootWrapper, k.GetExternalWrappers(testCtx).Root()) + assert.Equal(recoveryWrapper, k.GetExternalWrappers(testCtx).Recovery()) + assert.Equal(workerAuthWrapper, k.GetExternalWrappers(testCtx).WorkerAuth()) + + err = k.AddExternalWrappers(testCtx, WithRootWrapper(&invalidWrapper{})) + assert.Error(err) + err = k.AddExternalWrappers(testCtx, WithRecoveryWrapper(&invalidWrapper{})) + assert.Error(err) + err = k.AddExternalWrappers(testCtx, WithWorkerAuthWrapper(&invalidWrapper{})) + assert.Error(err) +} + +type invalidWrapper struct { + wrapping.Wrapper +} + +func (w *invalidWrapper) KeyId(context.Context) (string, error) { + return "", fmt.Errorf("invalid-error") +} diff --git a/internal/kms/ids.go b/internal/kms/ids.go deleted file mode 100644 index d4c021ff0..000000000 --- a/internal/kms/ids.go +++ /dev/null @@ -1,151 +0,0 @@ -package kms - -import ( - "context" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" -) - -const ( - RootKeyPrefix = "krk" - RootKeyVersionPrefix = "krkv" - DatabaseKeyPrefix = "kdk" - DatabaseKeyVersionPrefix = "kdkv" - OplogKeyPrefix = "kopk" - OplogKeyVersionPrefix = "kopkv" - TokenKeyPrefix = "ktk" - TokenKeyVersionPrefix = "ktv" - SessionKeyPrefix = "ksk" - SessionKeyVersionPrefix = "kskv" - OidcKeyPrefix = "koidck" - OidcKeyVersionPrefix = "koidckv" - AuditKeyPrefix = "kak" - AuditKeyVersionPrefix = "kakv" -) - -func newRootKeyId() (string, error) { - const op = "kms.newRootKeyId" - id, err := db.NewPublicId(RootKeyPrefix) - if err != nil { - return "", errors.WrapDeprecated(err, op) - } - return id, nil -} - -func newRootKeyVersionId() (string, error) { - const op = "kms.newRootKeyVersionId" - id, err := db.NewPublicId(RootKeyVersionPrefix) - if err != nil { - return "", errors.WrapDeprecated(err, op) - } - return id, nil -} - -func newDatabaseKeyId() (string, error) { - const op = "kms.newDatabaseKeyId" - id, err := db.NewPublicId(DatabaseKeyPrefix) - if err != nil { - return "", errors.WrapDeprecated(err, op) - } - return id, nil -} - -func newDatabaseKeyVersionId() (string, error) { - const op = "kms.newDatabaseKeyVersionId" - id, err := db.NewPublicId(DatabaseKeyVersionPrefix) - if err != nil { - return "", errors.WrapDeprecated(err, op) - } - return id, nil -} - -func newOplogKeyId() (string, error) { - const op = "kms.newOplogKeyId" - id, err := db.NewPublicId(OplogKeyPrefix) - if err != nil { - return "", errors.WrapDeprecated(err, op) - } - return id, nil -} - -func newOplogKeyVersionId() (string, error) { - const op = "kms.newOplogKeyVersionId" - id, err := db.NewPublicId(OplogKeyVersionPrefix) - if err != nil { - return "", errors.WrapDeprecated(err, op) - } - return id, nil -} - -func newTokenKeyId() (string, error) { - const op = "kms.newTokenKeyId" - id, err := db.NewPublicId(TokenKeyPrefix) - if err != nil { - return "", errors.WrapDeprecated(err, op) - } - return id, nil -} - -func newTokenKeyVersionId() (string, error) { - const op = "kms.newTokenKeyVersionId" - id, err := db.NewPublicId(TokenKeyVersionPrefix) - if err != nil { - return "", errors.WrapDeprecated(err, op) - } - return id, nil -} - -func newSessionKeyId() (string, error) { - const op = "kms.newSessionKeyId" - id, err := db.NewPublicId(SessionKeyPrefix) - if err != nil { - return "", errors.WrapDeprecated(err, op) - } - return id, nil -} - -func newSessionKeyVersionId() (string, error) { - const op = "kms.newSessionKeyVersionId" - id, err := db.NewPublicId(SessionKeyVersionPrefix) - if err != nil { - return "", errors.WrapDeprecated(err, op) - } - return id, nil -} - -func newOidcKeyId() (string, error) { - const op = "kms.newOidcKeyId" - id, err := db.NewPublicId(OidcKeyPrefix) - if err != nil { - return "", errors.WrapDeprecated(err, op) - } - return id, nil -} - -func newOidcKeyVersionId() (string, error) { - const op = "kms.newOidcKeyVersionId" - id, err := db.NewPublicId(OidcKeyVersionPrefix) - if err != nil { - return "", errors.WrapDeprecated(err, op) - } - return id, nil -} - -func newAuditKeyId(ctx context.Context) (string, error) { - const op = "kms.newAuditKeyId" - id, err := db.NewPublicId(AuditKeyPrefix) - if err != nil { - return "", errors.Wrap(ctx, err, op) - } - return id, nil -} - -func newAuditKeyVersionId(ctx context.Context) (string, error) { - const op = "kms.newAuditKeyVersionId" - id, err := db.NewPublicId(AuditKeyVersionPrefix) - if err != nil { - return "", errors.Wrap(ctx, err, op) - } - return id, nil -} diff --git a/internal/kms/ids_test.go b/internal/kms/ids_test.go deleted file mode 100644 index 3cb2a3b51..000000000 --- a/internal/kms/ids_test.go +++ /dev/null @@ -1,84 +0,0 @@ -package kms - -import ( - "context" - "strings" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func Test_Ids(t *testing.T) { - t.Parallel() - t.Run("krk", func(t *testing.T) { - id, err := newRootKeyId() - require.NoError(t, err) - assert.True(t, strings.HasPrefix(id, RootKeyPrefix+"_")) - }) - t.Run("krkv", func(t *testing.T) { - id, err := newRootKeyVersionId() - require.NoError(t, err) - assert.True(t, strings.HasPrefix(id, RootKeyVersionPrefix+"_")) - }) - t.Run("kdk", func(t *testing.T) { - id, err := newDatabaseKeyId() - require.NoError(t, err) - assert.True(t, strings.HasPrefix(id, DatabaseKeyPrefix+"_")) - }) - t.Run("kdkv", func(t *testing.T) { - id, err := newDatabaseKeyVersionId() - require.NoError(t, err) - assert.True(t, strings.HasPrefix(id, DatabaseKeyVersionPrefix+"_")) - }) - t.Run("kopk", func(t *testing.T) { - id, err := newOplogKeyId() - require.NoError(t, err) - assert.True(t, strings.HasPrefix(id, OplogKeyPrefix+"_")) - }) - t.Run("kopkv", func(t *testing.T) { - id, err := newOplogKeyVersionId() - require.NoError(t, err) - assert.True(t, strings.HasPrefix(id, OplogKeyVersionPrefix+"_")) - }) - t.Run("ktk", func(t *testing.T) { - id, err := newTokenKeyId() - require.NoError(t, err) - assert.True(t, strings.HasPrefix(id, TokenKeyPrefix+"_")) - }) - t.Run("ktkv", func(t *testing.T) { - id, err := newTokenKeyVersionId() - require.NoError(t, err) - assert.True(t, strings.HasPrefix(id, TokenKeyVersionPrefix+"_")) - }) - t.Run("ksk", func(t *testing.T) { - id, err := newSessionKeyId() - require.NoError(t, err) - assert.True(t, strings.HasPrefix(id, SessionKeyPrefix+"_")) - }) - t.Run("kskv", func(t *testing.T) { - id, err := newSessionKeyVersionId() - require.NoError(t, err) - assert.True(t, strings.HasPrefix(id, SessionKeyVersionPrefix+"_")) - }) - t.Run("koidck", func(t *testing.T) { - id, err := newOidcKeyId() - require.NoError(t, err) - assert.True(t, strings.HasPrefix(id, OidcKeyPrefix+"_")) - }) - t.Run("koidckv", func(t *testing.T) { - id, err := newOidcKeyVersionId() - require.NoError(t, err) - assert.True(t, strings.HasPrefix(id, OidcKeyVersionPrefix+"_")) - }) - t.Run("kak", func(t *testing.T) { - id, err := newAuditKeyId(context.Background()) - require.NoError(t, err) - assert.True(t, strings.HasPrefix(id, AuditKeyPrefix+"_")) - }) - t.Run("kakv", func(t *testing.T) { - id, err := newAuditKeyVersionId(context.Background()) - require.NoError(t, err) - assert.True(t, strings.HasPrefix(id, AuditKeyVersionPrefix+"_")) - }) -} diff --git a/internal/kms/immutable_fields_test.go b/internal/kms/immutable_fields_test.go deleted file mode 100644 index cbba96bd5..000000000 --- a/internal/kms/immutable_fields_test.go +++ /dev/null @@ -1,1165 +0,0 @@ -package kms_test - -import ( - "context" - "testing" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/db/timestamp" - "github.com/hashicorp/boundary/internal/iam" - "github.com/hashicorp/boundary/internal/kms" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/timestamppb" -) - -func TestOplogKey_ImmutableFields(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - - ts := timestamp.Timestamp{Timestamp: ×tamppb.Timestamp{Seconds: 0, Nanos: 0}} - - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocOplogKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - new := kms.TestOplogKey(t, conn, rk.PrivateId) - - tests := []struct { - name string - update *kms.OplogKey - fieldMask []string - }{ - { - name: "private_id", - update: func() *kms.OplogKey { - k := new.Clone().(*kms.OplogKey) - k.PrivateId = "o_thisIsNotAValidId" - return k - }(), - fieldMask: []string{"PrivateId"}, - }, - { - name: "create time", - update: func() *kms.OplogKey { - k := new.Clone().(*kms.OplogKey) - k.CreateTime = &ts - return k - }(), - fieldMask: []string{"CreateTime"}, - }, - { - name: "root_key_id", - update: func() *kms.OplogKey { - k := new.Clone().(*kms.OplogKey) - k.RootKeyId = "o_thisIsNotAValidId" - return k - }(), - fieldMask: []string{"ScopeId"}, - }, - } - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - orig := new.Clone() - err := rw.LookupById(context.Background(), orig) - require.NoError(err) - - rowsUpdated, err := rw.Update(context.Background(), tt.update, tt.fieldMask, nil, db.WithSkipVetForWrite(true)) - require.Error(err) - assert.Equal(0, rowsUpdated) - - after := new.Clone() - err = rw.LookupById(context.Background(), after) - require.NoError(err) - - assert.True(proto.Equal(orig.(*kms.OplogKey), after.(*kms.OplogKey))) - }) - } -} - -func TestOplogKeyVersion_ImmutableFields(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - rw := db.New(conn) - - ts := timestamp.Timestamp{Timestamp: ×tamppb.Timestamp{Seconds: 0, Nanos: 0}} - - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - dk := kms.TestOplogKey(t, conn, rk.PrivateId) - new := kms.TestOplogKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("oplog key")) - - tests := []struct { - name string - update *kms.OplogKeyVersion - fieldMask []string - }{ - { - name: "private_id", - update: func() *kms.OplogKeyVersion { - k := new.Clone().(*kms.OplogKeyVersion) - k.PrivateId = "o_thisIsNotAValidId" - return k - }(), - fieldMask: []string{"PrivateId"}, - }, - { - name: "create time", - update: func() *kms.OplogKeyVersion { - k := new.Clone().(*kms.OplogKeyVersion) - k.CreateTime = &ts - return k - }(), - fieldMask: []string{"CreateTime"}, - }, - { - name: "oplog_key_id", - update: func() *kms.OplogKeyVersion { - k := new.Clone().(*kms.OplogKeyVersion) - k.OplogKeyId = "o_thisIsNotAValidId" - return k - }(), - fieldMask: []string{"RootKeyId"}, - }, - { - name: "root_key_version_id", - update: func() *kms.OplogKeyVersion { - k := new.Clone().(*kms.OplogKeyVersion) - k.RootKeyVersionId = "o_thisIsNotAValidId" - return k - }(), - fieldMask: []string{"RootKeyId"}, - }, - { - name: "version", - update: func() *kms.OplogKeyVersion { - k := new.Clone().(*kms.OplogKeyVersion) - k.Version = uint32(22) - return k - }(), - fieldMask: []string{"Version"}, - }, - { - name: "key", - update: func() *kms.OplogKeyVersion { - k := new.Clone().(*kms.OplogKeyVersion) - k.Key = []byte("updated key") - return k - }(), - fieldMask: []string{"CtKey"}, - }, - } - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - orig := new.Clone() - err := rw.LookupById(context.Background(), orig) - require.NoError(err) - - err = tt.update.Encrypt(context.Background(), wrapper) - require.NoError(err) - rowsUpdated, err := rw.Update(context.Background(), tt.update, tt.fieldMask, nil, db.WithSkipVetForWrite(true)) - require.Error(err) - assert.Equal(0, rowsUpdated) - - after := new.Clone() - err = rw.LookupById(context.Background(), after) - require.NoError(err) - - assert.True(proto.Equal(orig.(*kms.OplogKeyVersion), after.(*kms.OplogKeyVersion))) - }) - } -} - -func TestTokenKey_ImmutableFields(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - - ts := timestamp.Timestamp{Timestamp: ×tamppb.Timestamp{Seconds: 0, Nanos: 0}} - - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocTokenKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - new := kms.TestTokenKey(t, conn, rk.PrivateId) - - tests := []struct { - name string - update *kms.TokenKey - fieldMask []string - }{ - { - name: "private_id", - update: func() *kms.TokenKey { - k := new.Clone().(*kms.TokenKey) - k.PrivateId = "o_thisIsNotAValidId" - return k - }(), - fieldMask: []string{"PrivateId"}, - }, - { - name: "create time", - update: func() *kms.TokenKey { - k := new.Clone().(*kms.TokenKey) - k.CreateTime = &ts - return k - }(), - fieldMask: []string{"CreateTime"}, - }, - { - name: "root_key_id", - update: func() *kms.TokenKey { - k := new.Clone().(*kms.TokenKey) - k.RootKeyId = "o_thisIsNotAValidId" - return k - }(), - fieldMask: []string{"ScopeId"}, - }, - } - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - orig := new.Clone() - err := rw.LookupById(context.Background(), orig) - require.NoError(err) - - rowsUpdated, err := rw.Update(context.Background(), tt.update, tt.fieldMask, nil, db.WithSkipVetForWrite(true)) - require.Error(err) - assert.Equal(0, rowsUpdated) - - after := new.Clone() - err = rw.LookupById(context.Background(), after) - require.NoError(err) - - assert.True(proto.Equal(orig.(*kms.TokenKey), after.(*kms.TokenKey))) - }) - } -} - -func TestTokenKeyVersion_ImmutableFields(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - rw := db.New(conn) - - ts := timestamp.Timestamp{Timestamp: ×tamppb.Timestamp{Seconds: 0, Nanos: 0}} - - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - dk := kms.TestTokenKey(t, conn, rk.PrivateId) - new := kms.TestTokenKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("token key")) - - tests := []struct { - name string - update *kms.TokenKeyVersion - fieldMask []string - }{ - { - name: "private_id", - update: func() *kms.TokenKeyVersion { - k := new.Clone().(*kms.TokenKeyVersion) - k.PrivateId = "o_thisIsNotAValidId" - return k - }(), - fieldMask: []string{"PrivateId"}, - }, - { - name: "create time", - update: func() *kms.TokenKeyVersion { - k := new.Clone().(*kms.TokenKeyVersion) - k.CreateTime = &ts - return k - }(), - fieldMask: []string{"CreateTime"}, - }, - { - name: "token_key_id", - update: func() *kms.TokenKeyVersion { - k := new.Clone().(*kms.TokenKeyVersion) - k.TokenKeyId = "o_thisIsNotAValidId" - return k - }(), - fieldMask: []string{"RootKeyId"}, - }, - { - name: "root_key_version_id", - update: func() *kms.TokenKeyVersion { - k := new.Clone().(*kms.TokenKeyVersion) - k.RootKeyVersionId = "o_thisIsNotAValidId" - return k - }(), - fieldMask: []string{"RootKeyId"}, - }, - { - name: "version", - update: func() *kms.TokenKeyVersion { - k := new.Clone().(*kms.TokenKeyVersion) - k.Version = uint32(22) - return k - }(), - fieldMask: []string{"Version"}, - }, - { - name: "key", - update: func() *kms.TokenKeyVersion { - k := new.Clone().(*kms.TokenKeyVersion) - k.Key = []byte("updated key") - return k - }(), - fieldMask: []string{"CtKey"}, - }, - } - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - orig := new.Clone() - err := rw.LookupById(context.Background(), orig) - require.NoError(err) - - err = tt.update.Encrypt(context.Background(), wrapper) - require.NoError(err) - rowsUpdated, err := rw.Update(context.Background(), tt.update, tt.fieldMask, nil, db.WithSkipVetForWrite(true)) - require.Error(err) - assert.Equal(0, rowsUpdated) - - after := new.Clone() - err = rw.LookupById(context.Background(), after) - require.NoError(err) - - assert.True(proto.Equal(orig.(*kms.TokenKeyVersion), after.(*kms.TokenKeyVersion))) - }) - } -} - -func TestSessionKey_ImmutableFields(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - - ts := timestamp.Timestamp{Timestamp: ×tamppb.Timestamp{Seconds: 0, Nanos: 0}} - - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocSessionKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - new := kms.TestSessionKey(t, conn, rk.PrivateId) - - tests := []struct { - name string - update *kms.SessionKey - fieldMask []string - }{ - { - name: "private_id", - update: func() *kms.SessionKey { - k := new.Clone().(*kms.SessionKey) - k.PrivateId = "o_thisIsNotAValidId" - return k - }(), - fieldMask: []string{"PrivateId"}, - }, - { - name: "create time", - update: func() *kms.SessionKey { - k := new.Clone().(*kms.SessionKey) - k.CreateTime = &ts - return k - }(), - fieldMask: []string{"CreateTime"}, - }, - { - name: "root_key_id", - update: func() *kms.SessionKey { - k := new.Clone().(*kms.SessionKey) - k.RootKeyId = "o_thisIsNotAValidId" - return k - }(), - fieldMask: []string{"ScopeId"}, - }, - } - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - orig := new.Clone() - err := rw.LookupById(context.Background(), orig) - require.NoError(err) - - rowsUpdated, err := rw.Update(context.Background(), tt.update, tt.fieldMask, nil, db.WithSkipVetForWrite(true)) - require.Error(err) - assert.Equal(0, rowsUpdated) - - after := new.Clone() - err = rw.LookupById(context.Background(), after) - require.NoError(err) - - assert.True(proto.Equal(orig.(*kms.SessionKey), after.(*kms.SessionKey))) - }) - } -} - -func TestSessionKeyVersion_ImmutableFields(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - rw := db.New(conn) - - ts := timestamp.Timestamp{Timestamp: ×tamppb.Timestamp{Seconds: 0, Nanos: 0}} - - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - dk := kms.TestSessionKey(t, conn, rk.PrivateId) - new := kms.TestSessionKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("session key")) - - tests := []struct { - name string - update *kms.SessionKeyVersion - fieldMask []string - }{ - { - name: "private_id", - update: func() *kms.SessionKeyVersion { - k := new.Clone().(*kms.SessionKeyVersion) - k.PrivateId = "o_thisIsNotAValidId" - return k - }(), - fieldMask: []string{"PrivateId"}, - }, - { - name: "create time", - update: func() *kms.SessionKeyVersion { - k := new.Clone().(*kms.SessionKeyVersion) - k.CreateTime = &ts - return k - }(), - fieldMask: []string{"CreateTime"}, - }, - { - name: "Session_key_id", - update: func() *kms.SessionKeyVersion { - k := new.Clone().(*kms.SessionKeyVersion) - k.SessionKeyId = "o_thisIsNotAValidId" - return k - }(), - fieldMask: []string{"RootKeyId"}, - }, - { - name: "root_key_version_id", - update: func() *kms.SessionKeyVersion { - k := new.Clone().(*kms.SessionKeyVersion) - k.RootKeyVersionId = "o_thisIsNotAValidId" - return k - }(), - fieldMask: []string{"RootKeyId"}, - }, - { - name: "version", - update: func() *kms.SessionKeyVersion { - k := new.Clone().(*kms.SessionKeyVersion) - k.Version = uint32(22) - return k - }(), - fieldMask: []string{"Version"}, - }, - { - name: "key", - update: func() *kms.SessionKeyVersion { - k := new.Clone().(*kms.SessionKeyVersion) - k.Key = []byte("updated key") - return k - }(), - fieldMask: []string{"CtKey"}, - }, - } - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - orig := new.Clone() - err := rw.LookupById(context.Background(), orig) - require.NoError(err) - - err = tt.update.Encrypt(context.Background(), wrapper) - require.NoError(err) - rowsUpdated, err := rw.Update(context.Background(), tt.update, tt.fieldMask, nil, db.WithSkipVetForWrite(true)) - require.Error(err) - assert.Equal(0, rowsUpdated) - - after := new.Clone() - err = rw.LookupById(context.Background(), after) - require.NoError(err) - - assert.True(proto.Equal(orig.(*kms.SessionKeyVersion), after.(*kms.SessionKeyVersion))) - }) - } -} - -func TestRootKeyVersion_ImmutableFields(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - rw := db.New(conn) - - ts := timestamp.Timestamp{Timestamp: ×tamppb.Timestamp{Seconds: 0, Nanos: 0}} - - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKeyVersion(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - new, _ := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - - tests := []struct { - name string - update *kms.RootKeyVersion - fieldMask []string - }{ - { - name: "private_id", - update: func() *kms.RootKeyVersion { - k := new.Clone().(*kms.RootKeyVersion) - k.PrivateId = "o_thisIsNotAValidId" - return k - }(), - fieldMask: []string{"PrivateId"}, - }, - { - name: "create time", - update: func() *kms.RootKeyVersion { - k := new.Clone().(*kms.RootKeyVersion) - k.CreateTime = &ts - return k - }(), - fieldMask: []string{"CreateTime"}, - }, - { - name: "root_key_id", - update: func() *kms.RootKeyVersion { - k := new.Clone().(*kms.RootKeyVersion) - k.RootKeyId = "o_thisIsNotAValidId" - return k - }(), - fieldMask: []string{"RootKeyId"}, - }, - { - name: "version", - update: func() *kms.RootKeyVersion { - k := new.Clone().(*kms.RootKeyVersion) - k.Version = uint32(22) - return k - }(), - fieldMask: []string{"Version"}, - }, - { - name: "key", - update: func() *kms.RootKeyVersion { - k := new.Clone().(*kms.RootKeyVersion) - k.Key = []byte("updated key") - return k - }(), - fieldMask: []string{"CtKey"}, - }, - } - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - orig := new.Clone() - err := rw.LookupById(context.Background(), orig) - require.NoError(err) - - err = tt.update.Encrypt(context.Background(), wrapper) - require.NoError(err) - rowsUpdated, err := rw.Update(context.Background(), tt.update, tt.fieldMask, nil, db.WithSkipVetForWrite(true)) - require.Error(err) - assert.Equal(0, rowsUpdated) - - after := new.Clone() - err = rw.LookupById(context.Background(), after) - require.NoError(err) - - assert.True(proto.Equal(orig.(*kms.RootKeyVersion), after.(*kms.RootKeyVersion))) - }) - } -} - -func TestRootKey_ImmutableFields(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - - ts := timestamp.Timestamp{Timestamp: ×tamppb.Timestamp{Seconds: 0, Nanos: 0}} - - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - new := kms.TestRootKey(t, conn, org.PublicId) - - tests := []struct { - name string - update *kms.RootKey - fieldMask []string - }{ - { - name: "private_id", - update: func() *kms.RootKey { - k := new.Clone().(*kms.RootKey) - k.PrivateId = "o_thisIsNotAValidId" - return k - }(), - fieldMask: []string{"PrivateId"}, - }, - { - name: "create time", - update: func() *kms.RootKey { - k := new.Clone().(*kms.RootKey) - k.CreateTime = &ts - return k - }(), - fieldMask: []string{"CreateTime"}, - }, - { - name: "scope_id", - update: func() *kms.RootKey { - k := new.Clone().(*kms.RootKey) - k.ScopeId = "o_thisIsNotAValidId" - return k - }(), - fieldMask: []string{"ScopeId"}, - }, - } - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - orig := new.Clone() - err := rw.LookupById(context.Background(), orig) - require.NoError(err) - - rowsUpdated, err := rw.Update(context.Background(), tt.update, tt.fieldMask, nil, db.WithSkipVetForWrite(true)) - require.Error(err) - assert.Equal(0, rowsUpdated) - - after := new.Clone() - err = rw.LookupById(context.Background(), after) - require.NoError(err) - - assert.True(proto.Equal(orig.(*kms.RootKey), after.(*kms.RootKey))) - }) - } -} - -func TestDatabaseKey_ImmutableFields(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - - ts := timestamp.Timestamp{Timestamp: ×tamppb.Timestamp{Seconds: 0, Nanos: 0}} - - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocDatabaseKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - new := kms.TestDatabaseKey(t, conn, rk.PrivateId) - - tests := []struct { - name string - update *kms.DatabaseKey - fieldMask []string - }{ - { - name: "private_id", - update: func() *kms.DatabaseKey { - k := new.Clone().(*kms.DatabaseKey) - k.PrivateId = "o_thisIsNotAValidId" - return k - }(), - fieldMask: []string{"PrivateId"}, - }, - { - name: "create time", - update: func() *kms.DatabaseKey { - k := new.Clone().(*kms.DatabaseKey) - k.CreateTime = &ts - return k - }(), - fieldMask: []string{"CreateTime"}, - }, - { - name: "root_key_id", - update: func() *kms.DatabaseKey { - k := new.Clone().(*kms.DatabaseKey) - k.RootKeyId = "o_thisIsNotAValidId" - return k - }(), - fieldMask: []string{"ScopeId"}, - }, - } - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - orig := new.Clone() - err := rw.LookupById(context.Background(), orig) - require.NoError(err) - - rowsUpdated, err := rw.Update(context.Background(), tt.update, tt.fieldMask, nil, db.WithSkipVetForWrite(true)) - require.Error(err) - assert.Equal(0, rowsUpdated) - - after := new.Clone() - err = rw.LookupById(context.Background(), after) - require.NoError(err) - - assert.True(proto.Equal(orig.(*kms.DatabaseKey), after.(*kms.DatabaseKey))) - }) - } -} - -func TestDatabaseKeyVersion_ImmutableFields(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - rw := db.New(conn) - - ts := timestamp.Timestamp{Timestamp: ×tamppb.Timestamp{Seconds: 0, Nanos: 0}} - - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - dk := kms.TestDatabaseKey(t, conn, rk.PrivateId) - new := kms.TestDatabaseKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("database key")) - - tests := []struct { - name string - update *kms.DatabaseKeyVersion - fieldMask []string - }{ - { - name: "private_id", - update: func() *kms.DatabaseKeyVersion { - k := new.Clone().(*kms.DatabaseKeyVersion) - k.PrivateId = "o_thisIsNotAValidId" - return k - }(), - fieldMask: []string{"PrivateId"}, - }, - { - name: "create time", - update: func() *kms.DatabaseKeyVersion { - k := new.Clone().(*kms.DatabaseKeyVersion) - k.CreateTime = &ts - return k - }(), - fieldMask: []string{"CreateTime"}, - }, - { - name: "database_key_id", - update: func() *kms.DatabaseKeyVersion { - k := new.Clone().(*kms.DatabaseKeyVersion) - k.DatabaseKeyId = "o_thisIsNotAValidId" - return k - }(), - fieldMask: []string{"RootKeyId"}, - }, - { - name: "root_key_version_id", - update: func() *kms.DatabaseKeyVersion { - k := new.Clone().(*kms.DatabaseKeyVersion) - k.RootKeyVersionId = "o_thisIsNotAValidId" - return k - }(), - fieldMask: []string{"RootKeyId"}, - }, - { - name: "version", - update: func() *kms.DatabaseKeyVersion { - k := new.Clone().(*kms.DatabaseKeyVersion) - k.Version = uint32(22) - return k - }(), - fieldMask: []string{"Version"}, - }, - { - name: "key", - update: func() *kms.DatabaseKeyVersion { - k := new.Clone().(*kms.DatabaseKeyVersion) - k.Key = []byte("updated key") - return k - }(), - fieldMask: []string{"CtKey"}, - }, - } - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - orig := new.Clone() - err := rw.LookupById(context.Background(), orig) - require.NoError(err) - - err = tt.update.Encrypt(context.Background(), wrapper) - require.NoError(err) - rowsUpdated, err := rw.Update(context.Background(), tt.update, tt.fieldMask, nil, db.WithSkipVetForWrite(true)) - require.Error(err) - assert.Equal(0, rowsUpdated) - - after := new.Clone() - err = rw.LookupById(context.Background(), after) - require.NoError(err) - - assert.True(proto.Equal(orig.(*kms.DatabaseKeyVersion), after.(*kms.DatabaseKeyVersion))) - }) - } -} - -func TestOidcKey_ImmutableFields(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - - ts := timestamp.Timestamp{Timestamp: ×tamppb.Timestamp{Seconds: 0, Nanos: 0}} - - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocOidcKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - new := kms.TestOidcKey(t, conn, rk.PrivateId) - - tests := []struct { - name string - update *kms.OidcKey - fieldMask []string - }{ - { - name: "private_id", - update: func() *kms.OidcKey { - k := new.Clone().(*kms.OidcKey) - k.PrivateId = "o_thisIsNotAValidId" - return k - }(), - fieldMask: []string{"PrivateId"}, - }, - { - name: "create time", - update: func() *kms.OidcKey { - k := new.Clone().(*kms.OidcKey) - k.CreateTime = &ts - return k - }(), - fieldMask: []string{"CreateTime"}, - }, - { - name: "root_key_id", - update: func() *kms.OidcKey { - k := new.Clone().(*kms.OidcKey) - k.RootKeyId = "o_thisIsNotAValidId" - return k - }(), - fieldMask: []string{"ScopeId"}, - }, - } - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - orig := new.Clone() - err := rw.LookupById(context.Background(), orig) - require.NoError(err) - - rowsUpdated, err := rw.Update(context.Background(), tt.update, tt.fieldMask, nil, db.WithSkipVetForWrite(true)) - require.Error(err) - assert.Equal(0, rowsUpdated) - - after := new.Clone() - err = rw.LookupById(context.Background(), after) - require.NoError(err) - - assert.True(proto.Equal(orig.(*kms.OidcKey), after.(*kms.OidcKey))) - }) - } -} - -func TestOidcKeyVersion_ImmutableFields(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - rw := db.New(conn) - - ts := timestamp.Timestamp{Timestamp: ×tamppb.Timestamp{Seconds: 0, Nanos: 0}} - - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - dk := kms.TestOidcKey(t, conn, rk.PrivateId) - new := kms.TestOidcKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("oidc key")) - - tests := []struct { - name string - update *kms.OidcKeyVersion - fieldMask []string - }{ - { - name: "private_id", - update: func() *kms.OidcKeyVersion { - k := new.Clone().(*kms.OidcKeyVersion) - k.PrivateId = "o_thisIsNotAValidId" - return k - }(), - fieldMask: []string{"PrivateId"}, - }, - { - name: "create time", - update: func() *kms.OidcKeyVersion { - k := new.Clone().(*kms.OidcKeyVersion) - k.CreateTime = &ts - return k - }(), - fieldMask: []string{"CreateTime"}, - }, - { - name: "oidc_key_id", - update: func() *kms.OidcKeyVersion { - k := new.Clone().(*kms.OidcKeyVersion) - k.OidcKeyId = "o_thisIsNotAValidId" - return k - }(), - fieldMask: []string{"RootKeyId"}, - }, - { - name: "root_key_version_id", - update: func() *kms.OidcKeyVersion { - k := new.Clone().(*kms.OidcKeyVersion) - k.RootKeyVersionId = "o_thisIsNotAValidId" - return k - }(), - fieldMask: []string{"RootKeyId"}, - }, - { - name: "version", - update: func() *kms.OidcKeyVersion { - k := new.Clone().(*kms.OidcKeyVersion) - k.Version = uint32(22) - return k - }(), - fieldMask: []string{"Version"}, - }, - { - name: "key", - update: func() *kms.OidcKeyVersion { - k := new.Clone().(*kms.OidcKeyVersion) - k.Key = []byte("updated key") - return k - }(), - fieldMask: []string{"CtKey"}, - }, - } - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - orig := new.Clone() - err := rw.LookupById(context.Background(), orig) - require.NoError(err) - - err = tt.update.Encrypt(context.Background(), wrapper) - require.NoError(err) - rowsUpdated, err := rw.Update(context.Background(), tt.update, tt.fieldMask, nil, db.WithSkipVetForWrite(true)) - require.Error(err) - assert.Equal(0, rowsUpdated) - - after := new.Clone() - err = rw.LookupById(context.Background(), after) - require.NoError(err) - - assert.True(proto.Equal(orig.(*kms.OidcKeyVersion), after.(*kms.OidcKeyVersion))) - }) - } -} - -func TestAuditKey_ImmutableFields(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - - ts := timestamp.Timestamp{Timestamp: ×tamppb.Timestamp{Seconds: 0, Nanos: 0}} - - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocAuditKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - new := kms.TestAuditKey(t, conn, rk.PrivateId) - - tests := []struct { - name string - update *kms.AuditKey - fieldMask []string - }{ - { - name: "private_id", - update: func() *kms.AuditKey { - k := new.Clone().(*kms.AuditKey) - k.PrivateId = "o_thisIsNotAValidId" - return k - }(), - fieldMask: []string{"PrivateId"}, - }, - { - name: "create time", - update: func() *kms.AuditKey { - k := new.Clone().(*kms.AuditKey) - k.CreateTime = &ts - return k - }(), - fieldMask: []string{"CreateTime"}, - }, - { - name: "root_key_id", - update: func() *kms.AuditKey { - k := new.Clone().(*kms.AuditKey) - k.RootKeyId = "o_thisIsNotAValidId" - return k - }(), - fieldMask: []string{"ScopeId"}, - }, - } - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - orig := new.Clone() - err := rw.LookupById(context.Background(), orig) - require.NoError(err) - - rowsUpdated, err := rw.Update(context.Background(), tt.update, tt.fieldMask, nil, db.WithSkipVetForWrite(true)) - require.Error(err) - assert.Equal(0, rowsUpdated) - - after := new.Clone() - err = rw.LookupById(context.Background(), after) - require.NoError(err) - - assert.True(proto.Equal(orig.(*kms.AuditKey), after.(*kms.AuditKey))) - }) - } -} - -func TestAuditKeyVersion_ImmutableFields(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - rw := db.New(conn) - - ts := timestamp.Timestamp{Timestamp: ×tamppb.Timestamp{Seconds: 0, Nanos: 0}} - - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - dk := kms.TestAuditKey(t, conn, rk.PrivateId) - new := kms.TestAuditKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("audit key")) - - tests := []struct { - name string - update *kms.AuditKeyVersion - fieldMask []string - }{ - { - name: "private_id", - update: func() *kms.AuditKeyVersion { - k := new.Clone().(*kms.AuditKeyVersion) - k.PrivateId = "o_thisIsNotAValidId" - return k - }(), - fieldMask: []string{"PrivateId"}, - }, - { - name: "create time", - update: func() *kms.AuditKeyVersion { - k := new.Clone().(*kms.AuditKeyVersion) - k.CreateTime = &ts - return k - }(), - fieldMask: []string{"CreateTime"}, - }, - { - name: "audit_key_id", - update: func() *kms.AuditKeyVersion { - k := new.Clone().(*kms.AuditKeyVersion) - k.AuditKeyId = "o_thisIsNotAValidId" - return k - }(), - fieldMask: []string{"RootKeyId"}, - }, - { - name: "root_key_version_id", - update: func() *kms.AuditKeyVersion { - k := new.Clone().(*kms.AuditKeyVersion) - k.RootKeyVersionId = "o_thisIsNotAValidId" - return k - }(), - fieldMask: []string{"RootKeyId"}, - }, - { - name: "version", - update: func() *kms.AuditKeyVersion { - k := new.Clone().(*kms.AuditKeyVersion) - k.Version = uint32(22) - return k - }(), - fieldMask: []string{"Version"}, - }, - { - name: "key", - update: func() *kms.AuditKeyVersion { - k := new.Clone().(*kms.AuditKeyVersion) - k.Key = []byte("updated key") - return k - }(), - fieldMask: []string{"CtKey"}, - }, - } - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - orig := new.Clone() - err := rw.LookupById(context.Background(), orig) - require.NoError(err) - - err = tt.update.Encrypt(context.Background(), wrapper) - require.NoError(err) - rowsUpdated, err := rw.Update(context.Background(), tt.update, tt.fieldMask, nil, db.WithSkipVetForWrite(true)) - require.Error(err) - assert.Equal(0, rowsUpdated) - - after := new.Clone() - err = rw.LookupById(context.Background(), after) - require.NoError(err) - - assert.True(proto.Equal(orig.(*kms.AuditKeyVersion), after.(*kms.AuditKeyVersion))) - }) - } -} diff --git a/internal/kms/kms.go b/internal/kms/kms.go index dafa28663..701329b75 100644 --- a/internal/kms/kms.go +++ b/internal/kms/kms.go @@ -6,285 +6,150 @@ import ( "io" "reflect" "sync" + "time" "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/errors" "github.com/hashicorp/boundary/internal/types/scope" + "github.com/hashicorp/go-dbw" + wrappingKms "github.com/hashicorp/go-kms-wrapping/extras/kms/v2" wrapping "github.com/hashicorp/go-kms-wrapping/v2" - aead "github.com/hashicorp/go-kms-wrapping/v2/aead" - "github.com/hashicorp/go-kms-wrapping/v2/extras/multi" ) -// ExternalWrappers holds wrappers defined outside of Boundary, e.g. in its -// configuration file. -type ExternalWrappers struct { - m sync.RWMutex - root wrapping.Wrapper - workerAuth wrapping.Wrapper - recovery wrapping.Wrapper -} - -// Root returns the wrapper for root keys -func (e *ExternalWrappers) Root() wrapping.Wrapper { - e.m.RLock() - defer e.m.RUnlock() - return e.root -} - -// WorkerAuth returns the wrapper for worker authentication -func (e *ExternalWrappers) WorkerAuth() wrapping.Wrapper { - e.m.RLock() - defer e.m.RUnlock() - return e.workerAuth -} - -// Recovery returns the wrapper for recovery operations -func (e *ExternalWrappers) Recovery() wrapping.Wrapper { - e.m.RLock() - defer e.m.RUnlock() - return e.recovery -} - // Kms is a way to access wrappers for a given scope and purpose. Since keys can // never change, only be added or (eventually) removed, it opportunistically // caches, going to the database as needed. type Kms struct { - // scopePurposeCache holds a per-scope-purpose multiwrapper containing the - // current encrypting key and all previous key versions, for decryption - scopePurposeCache sync.Map - - externalScopeCache map[string]*ExternalWrappers - externalScopeCacheMutex sync.RWMutex - + underlying *wrappingKms.Kms + reader db.Reader derivedPurposeCache sync.Map - - repo *Repository } -// NewKms takes in a repo and returns a Kms. -func NewKms(repo *Repository, opt ...Option) (*Kms, error) { - const op = "kms.NewKms" - if repo == nil { - return nil, errors.NewDeprecated(errors.InvalidParameter, op, "missing underlying repo") +// New creates a Kms using the provided reader and writer. No options are +// currently supported. +func New(ctx context.Context, reader *db.Db, writer *db.Db, _ ...Option) (*Kms, error) { + const op = "kms.(Kms).New" + if isNil(reader) { + return nil, errors.New(ctx, errors.InvalidParameter, op, "missing reader") } + if isNil(writer) { + return nil, errors.New(ctx, errors.InvalidParameter, op, "missing writer") + } + purposes := stdNewKmsPurposes() + r := dbw.New(reader.UnderlyingDB()) + w := dbw.New(writer.UnderlyingDB()) + k, err := wrappingKms.New(r, w, purposes, wrappingKms.WithCache(true)) + if err != nil { + return nil, errors.Wrap(ctx, err, op, errors.WithMsg("error creating new in-memory kms")) + } return &Kms{ - externalScopeCache: make(map[string]*ExternalWrappers), - repo: repo, + underlying: k, + reader: reader, }, nil } -// GetScopePurposeCache is used in test functions for validation. Since the -// tests need to be in a different package to avoid circular dependencies, this -// is exported. -func (k *Kms) GetScopePurposeCache() *sync.Map { - return &k.scopePurposeCache +// NewUsingReaderWriter creates a Kms using the provided reader and writer. No +// options are currently supported. +func NewUsingReaderWriter(ctx context.Context, reader db.Reader, writer db.Writer, _ ...Option) (*Kms, error) { + const op = "kms.(Kms).New" + if isNil(reader) { + return nil, errors.New(ctx, errors.InvalidParameter, op, "missing reader") + } + if isNil(writer) { + return nil, errors.New(ctx, errors.InvalidParameter, op, "missing writer") + } + purposes := stdNewKmsPurposes() + + r, err := convertToRW(ctx, reader) + if err != nil { + return nil, errors.Wrap(ctx, err, op) + } + w, err := convertToRW(ctx, writer) + if err != nil { + return nil, errors.Wrap(ctx, err, op) + } + k, err := wrappingKms.New(r, w, purposes, wrappingKms.WithCache(true)) + if err != nil { + return nil, errors.Wrap(ctx, err, op, errors.WithMsg("error creating new in-memory kms")) + } + return &Kms{ + underlying: k, + reader: reader, + }, nil } -func (k *Kms) GetDerivedPurposeCache() *sync.Map { - return &k.derivedPurposeCache +func convertToRW(ctx context.Context, r interface{}) (*dbw.RW, error) { + const op = "kms.convertToDb" + d, ok := r.(*db.Db) + if !ok { + return nil, errors.New(ctx, errors.InvalidParameter, op, "unable to convert to db.DB") + } + return dbw.New(d.UnderlyingDB()), nil } // AddExternalWrappers allows setting the external keys. -// -// TODO: If we support more than one, e.g. for encrypting against many in case -// of a key loss, there will need to be some refactoring here to have the values -// being stored in the struct be a multiwrapper, but that's for a later project. func (k *Kms) AddExternalWrappers(ctx context.Context, opt ...Option) error { - const op = "kms.AddExternalWrappers" - k.externalScopeCacheMutex.Lock() - defer k.externalScopeCacheMutex.Unlock() - - ext := k.externalScopeCache[scope.Global.String()] - if ext == nil { - ext = &ExternalWrappers{} - } - ext.m.Lock() - defer ext.m.Unlock() + const op = "kms.(Kms).AddExternalWrappers" opts := getOpts(opt...) if opts.withRootWrapper != nil { - ext.root = opts.withRootWrapper - keyId, err := ext.root.KeyId(ctx) - if err != nil { - return errors.Wrap(ctx, err, op, errors.WithMsg("error reading root wrapper key ID")) - } - if keyId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "root wrapper has no key ID") + if err := k.underlying.AddExternalWrapper(ctx, wrappingKms.KeyPurpose(KeyPurposeRootKey.String()), opts.withRootWrapper); err != nil { + return errors.Wrap(ctx, err, op, errors.WithMsg("unable to add root wrapper")) } } if opts.withWorkerAuthWrapper != nil { - ext.workerAuth = opts.withWorkerAuthWrapper - keyId, err := ext.workerAuth.KeyId(ctx) - if err != nil { - return errors.Wrap(ctx, err, op, errors.WithMsg("error reading worker auth wrapper key ID")) - } - if keyId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "worker auth wrapper has no key ID") + if err := k.underlying.AddExternalWrapper(ctx, wrappingKms.KeyPurpose(KeyPurposeWorkerAuth.String()), opts.withWorkerAuthWrapper); err != nil { + return errors.Wrap(ctx, err, op, errors.WithMsg("unable to add worker auth wrapper")) } } if opts.withRecoveryWrapper != nil { - ext.recovery = opts.withRecoveryWrapper - keyId, err := ext.root.KeyId(ctx) - if err != nil { - return errors.Wrap(ctx, err, op, errors.WithMsg("error reading recovery wrapper key ID")) - } - if keyId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "recovery wrapper has no key ID") + if err := k.underlying.AddExternalWrapper(ctx, wrappingKms.KeyPurpose(KeyPurposeRecovery.String()), opts.withRecoveryWrapper); err != nil { + return errors.Wrap(ctx, err, op, errors.WithMsg("unable to add recovery wrapper")) } } - - k.externalScopeCache[scope.Global.String()] = ext return nil } -func (k *Kms) GetExternalWrappers() *ExternalWrappers { - k.externalScopeCacheMutex.RLock() - defer k.externalScopeCacheMutex.RUnlock() - - ext := k.externalScopeCache[scope.Global.String()] - ext.m.RLock() - defer ext.m.RUnlock() - - ret := &ExternalWrappers{ - root: ext.root, - workerAuth: ext.workerAuth, - recovery: ext.recovery, - } - return ret -} - // GetWrapper returns a wrapper for the given scope and purpose. When a keyId is // passed, it will ensure that the returning wrapper has that key ID in the -// multiwrapper. This is not necesary for encryption but should be supplied for +// multiwrapper. This is not necessary for encryption but should be supplied for // decryption. func (k *Kms) GetWrapper(ctx context.Context, scopeId string, purpose KeyPurpose, opt ...Option) (wrapping.Wrapper, error) { - const op = "kms.GetWrapper" + const op = "kms.(Kms).GetWrapper" if scopeId == "" { return nil, errors.New(ctx, errors.InvalidParameter, op, "missing scope id") } - - switch purpose { - case KeyPurposeOplog, KeyPurposeDatabase, KeyPurposeTokens, KeyPurposeSessions, KeyPurposeOidc, KeyPurposeAudit: - case KeyPurposeUnknown: - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing key purpose") - default: - return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("unsupported purpose %q", purpose)) + if purpose == KeyPurposeUnknown { + return nil, errors.New(ctx, errors.InvalidParameter, op, "missing purpose") } - opts := getOpts(opt...) - // Fast-path: we have a valid key at the scope/purpose. Verify the key with - // that ID is in the multiwrapper; if not, fall through to reload from the - // DB. - val, ok := k.scopePurposeCache.Load(scopeId + purpose.String()) - if ok { - wrapper := val.(*multi.PooledWrapper) - if opts.withKeyId == "" { - return wrapper, nil - } - if keyIdWrapper := wrapper.WrapperForKeyId(opts.withKeyId); keyIdWrapper != nil { - return keyIdWrapper, nil - } - // Fall through to refresh our multiwrapper for this scope/purpose from the DB - } - - // We don't have it cached, so we'll need to read from the database. Get the - // root for the scope as we'll need it to decrypt the value coming from the - // DB. We don't cache the roots as we expect that after a few calls the - // scope-purpose cache will catch everything in steady-state. - rootWrapper, rootKeyId, err := k.loadRoot(ctx, scopeId, opt...) + w, err := k.underlying.GetWrapper(ctx, scopeId, wrappingKms.KeyPurpose(purpose.String()), wrappingKms.WithKeyId(opts.withKeyId)) if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("error loading root key for scope %s", scopeId))) + return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to get wrapper")) } - if rootWrapper == nil { - return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("got nil root wrapper for scope %s", scopeId)) - } - - wrapper, err := k.loadDek(ctx, scopeId, purpose, rootWrapper, rootKeyId, opt...) - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("error loading %s for scope %s", purpose.String(), scopeId))) - } - k.scopePurposeCache.Store(scopeId+purpose.String(), wrapper) - - if opts.withKeyId != "" { - if keyIdWrapper := wrapper.WrapperForKeyId(opts.withKeyId); keyIdWrapper != nil { - return keyIdWrapper, nil - } - return nil, errors.New(ctx, errors.KeyNotFound, op, "unable to find specified key ID") - } - - return wrapper, nil + return w, err } -func (k *Kms) loadRoot(ctx context.Context, scopeId string, opt ...Option) (*multi.PooledWrapper, string, error) { - const op = "kms.loadRoot" - opts := getOpts(opt...) - repo := opts.withRepository - if repo == nil { - repo = k.repo +// GetExternalWrappers returns the Kms' ExternalWrappers +func (k *Kms) GetExternalWrappers(ctx context.Context) *ExternalWrappers { + const op = "kms.(Kms).GetExternalWrappers" + ret := &ExternalWrappers{} + if root, err := k.underlying.GetExternalRootWrapper(); err == nil { + ret.root = root } - rootKeys, err := repo.ListRootKeys(ctx) - if err != nil { - return nil, "", errors.Wrap(ctx, err, op) + if workerAuth, err := k.underlying.GetExternalWrapper(ctx, wrappingKms.KeyPurpose(KeyPurposeWorkerAuth.String())); err == nil { + ret.workerAuth = workerAuth } - var rootKeyId string - for _, k := range rootKeys { - if k.GetScopeId() == scopeId { - rootKeyId = k.GetPrivateId() - break - } - } - if rootKeyId == "" { - return nil, "", errors.New(ctx, errors.KeyNotFound, op, fmt.Sprintf("missing root key for scope %s", scopeId)) + if recovery, err := k.underlying.GetExternalWrapper(ctx, wrappingKms.KeyPurpose(KeyPurposeRecovery.String())); err == nil { + ret.recovery = recovery } + return ret +} - // Now: find the external KMS that can be used to decrypt the root values - // from the DB. - k.externalScopeCacheMutex.Lock() - externalWrappers := k.externalScopeCache[scope.Global.String()] - k.externalScopeCacheMutex.Unlock() - if externalWrappers == nil { - return nil, "", errors.New(ctx, errors.KeyNotFound, op, "could not find kms information at either the needed scope or global fallback") - } - - externalWrappers.m.RLock() - defer externalWrappers.m.RUnlock() - - if externalWrappers.root == nil { - return nil, "", errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("root key wrapper for scope %s is nil", scopeId)) - } - rootKeyVersions, err := repo.ListRootKeyVersions(ctx, externalWrappers.root, rootKeyId, WithOrderByVersion(db.DescendingOrderBy)) - if err != nil { - return nil, "", errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("error looking up root key versions for scope %s", scopeId))) - } - if len(rootKeyVersions) == 0 { - return nil, "", errors.New(ctx, errors.KeyNotFound, op, fmt.Sprintf("no root key versions found for scope %s", scopeId)) - } - - var pooled *multi.PooledWrapper - for i, key := range rootKeyVersions { - var err error - wrapper := aead.NewWrapper() - if _, err = wrapper.SetConfig(ctx, wrapping.WithKeyId(key.GetPrivateId())); err != nil { - return nil, "", errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("error setting config on aead root wrapper in scope %s", scopeId))) - } - if err = wrapper.SetAesGcmKeyBytes(key.GetKey()); err != nil { - return nil, "", errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("error setting key bytes on aead root wrapper in scope %s", scopeId))) - } - if i == 0 { - pooled, err = multi.NewPooledWrapper(ctx, wrapper) - if err != nil { - return nil, "", errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("error getting root pooled wrapper for key version 0 in scope %s", scopeId))) - } - } else { - _, err = pooled.AddWrapper(ctx, wrapper) - if err != nil { - return nil, "", errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("error adding pooled wrapper for key version %d in scope %s", i, scopeId))) - } - } - } - - return pooled, rootKeyId, nil +// GetDerivedPurposeCache returns the raw derived purpose cache +func (k *Kms) GetDerivedPurposeCache() *sync.Map { + return &k.derivedPurposeCache } // ReconcileKeys will reconcile the keys in the kms against known possible @@ -295,71 +160,108 @@ func (k *Kms) ReconcileKeys(ctx context.Context, randomReader io.Reader, opt ... if isNil(randomReader) { return errors.New(ctx, errors.InvalidParameter, op, "missing rand reader") } - // it's possible that the global audit key was created after this instance's // database was initialized... so check if the audit wrapper is available // for the global scope and if not, then add one to the global scope if _, err := k.GetWrapper(ctx, scope.Global.String(), KeyPurposeAudit); err != nil { - switch { - case errors.Match(errors.T(errors.KeyNotFound), err): - globalRootWrapper, _, err := k.loadRoot(ctx, scope.Global.String()) - if err != nil { - return errors.Wrap(ctx, err, op) - } - key, err := generateKey(ctx, randomReader) - if err != nil { - return errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("error generating random bytes for database key in scope %s", scope.Global.String()))) - } - if _, _, err := k.repo.CreateAuditKey(ctx, globalRootWrapper, key); err != nil { - return errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("error creating audit key in scope %s", scope.Global.String()))) - } - default: - errors.Wrap(ctx, err, op) + if err := k.underlying.ReconcileKeys( + ctx, + []string{scope.Global.String()}, + []wrappingKms.KeyPurpose{wrappingKms.KeyPurpose(KeyPurposeAudit.String())}, + wrappingKms.WithRandomReader(randomReader), + ); err != nil { + return errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("error creating audit key in scope %s", scope.Global.String()))) } } opts := getOpts(opt...) - for _, id := range opts.withScopeIds { - var scopeRootWrapper *multi.PooledWrapper - - for _, purpose := range []KeyPurpose{ + if len(opts.withScopeIds) > 0 { + if err := k.underlying.ReconcileKeys( + ctx, + opts.withScopeIds, // just add additional purposes as needed going forward to reconcile // new keys as they are added. - // - // NOTE: don't add an audit key here since it can only be created in - // the global scope. - KeyPurposeOidc, - } { - if _, err := k.GetWrapper(ctx, id, purpose); err != nil { - switch { - case errors.Match(errors.T(errors.KeyNotFound), err): - if scopeRootWrapper == nil { - if scopeRootWrapper, _, err = k.loadRoot(ctx, id); err != nil { - return errors.Wrap(ctx, err, op) - } - } - key, err := generateKey(ctx, randomReader) - if err != nil { - return errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("error generating random bytes for %q key in scope %q", purpose.String(), id))) - } - switch purpose { - case KeyPurposeOidc: - if _, _, err := k.repo.CreateOidcKey(ctx, scopeRootWrapper, key); err != nil { - return errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("error creating %q key in scope %s", purpose.String(), id))) - } - default: - return errors.New(ctx, errors.Internal, op, fmt.Sprintf("error creating %q key in scope %s since it's not a supported KeyPurpose", purpose.String(), id)) - } - default: - errors.Wrap(ctx, err, op) - } - } + []wrappingKms.KeyPurpose{wrappingKms.KeyPurpose(KeyPurposeOidc.String())}, + wrappingKms.WithRandomReader(randomReader), + ); err != nil { + return errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("error creating keys in scopes %s", opts.withScopeIds))) } } - return nil } +// CreateKeys creates the root key and DEKs returns a map of the new keys. +// Supports the WithRandomReader(...) and WithReaderWriter(...) options. +// When WithReaderWriter(...) is used the caller is responsible for managing the +// transaction which allows this capability to be shared with the iam repo when +// it's creating Scopes. +func (k *Kms) CreateKeys(ctx context.Context, scopeId string, opt ...Option) error { + const op = "kms.(Kms).CreateKeysTx" + if scopeId == "" { + return errors.New(ctx, errors.InvalidParameter, op, "missing scope id") + } + opts := getOpts(opt...) + kmsOpts := []wrappingKms.Option{wrappingKms.WithRandomReader(opts.withRandomReader)} + switch { + case !isNil(opts.withReader) && isNil(opts.withWriter): + return errors.New(ctx, errors.InvalidParameter, op, "missing writer") + case isNil(opts.withReader) && !isNil(opts.withWriter): + return errors.New(ctx, errors.InvalidParameter, op, "missing reader") + case !isNil(opts.withReader) && !isNil(opts.withWriter): + r, err := convertToRW(ctx, opts.withReader) + if err != nil { + return errors.Wrap(ctx, err, op, errors.WithMsg("unable to convert reader")) + } + w, err := convertToRW(ctx, opts.withWriter) + if err != nil { + return errors.Wrap(ctx, err, op, errors.WithMsg("unable to convert writer")) + } + kmsOpts = append(kmsOpts, wrappingKms.WithReaderWriter(r, w)) + } + purposes := make([]wrappingKms.KeyPurpose, 0, len(ValidDekPurposes())) + for _, p := range ValidDekPurposes() { + purposes = append(purposes, wrappingKms.KeyPurpose(p.String())) + } + if err := k.underlying.CreateKeys(ctx, scopeId, purposes, kmsOpts...); err != nil { + return errors.Wrap(ctx, err, op) + } + return nil +} + +// ClearCache will clear the kms's cache which is useful after a scope has been +// deleted. +func (k *Kms) ClearCache(ctx context.Context) error { + const op = "kms.(Kms).ClearCache" + if err := k.underlying.ClearCache(ctx); err != nil { + return errors.Wrap(ctx, err, op) + } + return nil +} + +// VerifyGlobalRoot will verify that the global root wrapper is reasonable. +func (k *Kms) VerifyGlobalRoot(ctx context.Context) error { + const op = "kms.(Kms).VerifyGlobalRoot" + var keys []*rootKey + if err := k.reader.SearchWhere(ctx, &keys, "1=1", nil, db.WithLimit(1), db.WithOrder("create_time asc")); err != nil { + return errors.Wrap(ctx, err, op) + } + for _, rk := range keys { + if rk.ScopeId == scope.Global.String() { + return nil + } + } + return errors.New(ctx, errors.MigrationIntegrity, op, "can't find global scoped root key") +} + +func stdNewKmsPurposes() []wrappingKms.KeyPurpose { + purposes := make([]wrappingKms.KeyPurpose, 0, len(ValidDekPurposes())) + for _, p := range ValidDekPurposes() { + purposes = append(purposes, wrappingKms.KeyPurpose(p.String())) + } + purposes = append(purposes, wrappingKms.KeyPurpose(KeyPurposeWorkerAuth.String()), wrappingKms.KeyPurpose(KeyPurposeRecovery.String())) + return purposes +} + func isNil(i interface{}) bool { if i == nil { return true @@ -371,111 +273,10 @@ func isNil(i interface{}) bool { return false } -// Dek is an interface wrapping dek types to allow a lot less switching in loadDek -type Dek interface { - GetRootKeyId() string - GetPrivateId() string +type rootKey struct { + PrivateId string `gorm:"primary_key"` + ScopeId string `gorm:"default:null"` + CreateTime time.Time `gorm:"default:current_timestamp"` } -// DekVersion is an interface wrapping versioned dek types to allow a lot less switching in loadDek -type DekVersion interface { - GetPrivateId() string - GetKey() []byte -} - -func (k *Kms) loadDek(ctx context.Context, scopeId string, purpose KeyPurpose, rootWrapper wrapping.Wrapper, rootKeyId string, opt ...Option) (*multi.PooledWrapper, error) { - const op = "kms.loadDek" - if rootWrapper == nil { - return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("nil root wrapper for scope %s", scopeId)) - } - if rootKeyId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("missing root key ID for scope %s", scopeId)) - } - - opts := getOpts(opt...) - repo := opts.withRepository - if repo == nil { - repo = k.repo - } - - var keys []Dek - var err error - switch purpose { - case KeyPurposeDatabase: - keys, err = repo.ListDatabaseKeys(ctx) - case KeyPurposeOplog: - keys, err = repo.ListOplogKeys(ctx) - case KeyPurposeTokens: - keys, err = repo.ListTokenKeys(ctx) - case KeyPurposeSessions: - keys, err = repo.ListSessionKeys(ctx) - case KeyPurposeOidc: - keys, err = repo.ListOidcKeys(ctx) - case KeyPurposeAudit: - keys, err = repo.ListAuditKeys(ctx) - default: - return nil, errors.New(ctx, errors.InvalidParameter, op, "unknown or invalid DEK purpose specified") - } - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg("error listing root keys")) - } - var keyId string - for _, k := range keys { - if k.GetRootKeyId() == rootKeyId { - keyId = k.GetPrivateId() - break - } - } - if keyId == "" { - return nil, errors.New(ctx, errors.KeyNotFound, op, fmt.Sprintf("error finding %s key for scope %s", purpose.String(), scopeId)) - } - - var keyVersions []DekVersion - switch purpose { - case KeyPurposeDatabase: - keyVersions, err = repo.ListDatabaseKeyVersions(ctx, rootWrapper, keyId, WithOrderByVersion(db.DescendingOrderBy)) - case KeyPurposeOplog: - keyVersions, err = repo.ListOplogKeyVersions(ctx, rootWrapper, keyId, WithOrderByVersion(db.DescendingOrderBy)) - case KeyPurposeTokens: - keyVersions, err = repo.ListTokenKeyVersions(ctx, rootWrapper, keyId, WithOrderByVersion(db.DescendingOrderBy)) - case KeyPurposeSessions: - keyVersions, err = repo.ListSessionKeyVersions(ctx, rootWrapper, keyId, WithOrderByVersion(db.DescendingOrderBy)) - case KeyPurposeOidc: - keyVersions, err = repo.ListOidcKeyVersions(ctx, rootWrapper, keyId, WithOrderByVersion(db.DescendingOrderBy)) - case KeyPurposeAudit: - keyVersions, err = repo.ListAuditKeyVersions(ctx, rootWrapper, keyId, WithOrderByVersion(db.DescendingOrderBy)) - default: - return nil, errors.New(ctx, errors.InvalidParameter, op, "unknown or invalid DEK purpose specified") - } - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("error looking up %s key versions for scope %s", purpose.String(), scopeId))) - } - if len(keyVersions) == 0 { - return nil, errors.New(ctx, errors.KeyNotFound, op, fmt.Sprintf("no %s key versions found for scope %s", purpose.String(), scopeId)) - } - - var pooled *multi.PooledWrapper - for i, keyVersion := range keyVersions { - var err error - wrapper := aead.NewWrapper() - if _, err = wrapper.SetConfig(ctx, wrapping.WithKeyId(keyVersion.GetPrivateId())); err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("error setting config on aead %s wrapper in scope %s", purpose.String(), scopeId))) - } - if err = wrapper.SetAesGcmKeyBytes(keyVersion.GetKey()); err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("error setting key bytes on aead %s wrapper in scope %s", purpose.String(), scopeId))) - } - if i == 0 { - pooled, err = multi.NewPooledWrapper(ctx, wrapper) - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("error getting %s pooled wrapper for key version 0 in scope %s", purpose.String(), scopeId))) - } - } else { - _, err = pooled.AddWrapper(ctx, wrapper) - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("error getting %s pooled wrapper for key version %d in scope %s", purpose.String(), i, scopeId))) - } - } - } - - return pooled, nil -} +func (*rootKey) TableName() string { return "kms_root_key" } diff --git a/internal/kms/kms_ext_test.go b/internal/kms/kms_ext_test.go index 7c8ece8be..8bf676411 100644 --- a/internal/kms/kms_ext_test.go +++ b/internal/kms/kms_ext_test.go @@ -26,55 +26,15 @@ func TestKms(t *testing.T) { t.Parallel() ctx := context.Background() conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) extWrapper := db.TestWrapper(t) - badExtWrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw) - require.NoError(t, err) kmsCache := kms.TestKms(t, conn, extWrapper) org, proj := iam.TestScopes(t, iam.TestRepo(t, conn, extWrapper)) - // Verify that the cache is empty, so we can show that by the end of the - // test sequence we did actually look up keys and store them in the cache - t.Run("verify cache empty", func(t *testing.T) { - var count int - kmsCache.GetScopePurposeCache().Range(func(key interface{}, value interface{}) bool { - count++ - return true - }) - assert.Equal(t, 0, count) - }) - // Verify that the root keys are all in the database and can be decrypted - // with the correct wrapper from the KMS object - t.Run("verify root keys", func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - rootKeys, err := repo.ListRootKeys(ctx) - require.NoError(err) - wrappers := kmsCache.GetExternalWrappers() - for _, key := range rootKeys { - kvs, err := repo.ListRootKeyVersions(ctx, wrappers.Root(), key.GetPrivateId()) - require.NoError(err) - assert.Len(kvs, 1) - assert.Len(kvs[0].GetKey(), 32) - } - }) - // Verify that the wrong wrapper causes decryption to fail - t.Run("bad external keys", func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - rootKeys, err := repo.ListRootKeys(ctx) - require.NoError(err) - for _, key := range rootKeys { - _, err := repo.ListRootKeyVersions(ctx, badExtWrapper, key.GetPrivateId()) - require.Error(err) - assert.True(strings.Contains(err.Error(), "message authentication failed"), err.Error()) - } - }) // This next sequence is run twice to ensure that calling for the keys twice // returns the same value each time and doesn't simply populate more keys // into the KMS object keyBytes := map[string]bool{} keyIds := map[string]bool{} - scopePurposeMap := map[string]interface{}{} for i := 1; i < 3; i++ { // This iterates through wrappers for all three scopes and four purposes, // ensuring that the key bytes and IDs are different for each of them, @@ -116,24 +76,6 @@ func TestKms(t *testing.T) { } } }) - // Verify that the cache has been populated with unique values. The - // second time we validate that the items we find when going through the - // cache a second time are the same as the first. If they were recreated - // the pointers would be different. - t.Run(fmt.Sprintf("verify cache populated x %d", i), func(t *testing.T) { - var count int - kmsCache.GetScopePurposeCache().Range(func(key interface{}, value interface{}) bool { - count++ - if i == 1 { - scopePurposeMap[key.(string)] = value - } else { - assert.Same(t, scopePurposeMap[key.(string)], value) - } - return true - }) - // four purposes x 3 scopes - assert.Equal(t, 12, count) - }) } } @@ -141,7 +83,6 @@ func TestKms_ReconcileKeys(t *testing.T) { t.Parallel() testCtx := context.Background() conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) org2, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) @@ -183,9 +124,10 @@ func TestKms_ReconcileKeys(t *testing.T) { kms: kms.TestKms(t, conn, wrapper), reader: rand.Reader, setup: func(k *kms.Kms) { - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocAuditKey(); return &i }(), "1=1") + kms.TestKmsDeleteKeyPurpose(t, conn, kms.KeyPurposeAudit) // make sure the kms is in the proper state for the unit test // before proceeding. + k.ClearCache(testCtx) _, err := k.GetWrapper(testCtx, scope.Global.String(), kms.KeyPurposeAudit) require.Error(t, err) }, @@ -200,14 +142,15 @@ func TestKms_ReconcileKeys(t *testing.T) { setup: func(k *kms.Kms) { // create initial keys for the test scope ids... for _, id := range []string{org.PublicId, org2.PublicId} { - _, err := kms.CreateKeysTx(context.Background(), rw, rw, wrapper, rand.Reader, id) + err := k.CreateKeys(testCtx, id) require.NoError(t, err) } - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocOidcKey(); return &i }(), "1=1") + kms.TestKmsDeleteKeyPurpose(t, conn, kms.KeyPurposeOidc) + // make sure the kms is in the proper state for the unit test // before proceeding. for _, id := range []string{org.PublicId, org2.PublicId} { - _, err := k.GetWrapper(testCtx, id, kms.KeyPurposeAudit) + _, err := k.GetWrapper(testCtx, id, kms.KeyPurposeOidc) require.Error(t, err) } }, @@ -218,10 +161,10 @@ func TestKms_ReconcileKeys(t *testing.T) { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) // start with no keys... - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") + kms.TestKmsDeleteAllKeys(t, conn) // create initial keys for the global scope... - _, err := kms.CreateKeysTx(context.Background(), rw, rw, wrapper, rand.Reader, scope.Global.String()) + err := tt.kms.CreateKeys(context.Background(), scope.Global.String()) require.NoError(err) if tt.setup != nil { @@ -252,3 +195,175 @@ func TestKms_ReconcileKeys(t *testing.T) { }) } } + +func TestKms_GetDerivedPurposeCache(t *testing.T) { + t.Parallel() + assert := assert.New(t) + + conn, _ := db.TestSetup(t, "postgres") + rootWrapper := db.TestWrapper(t) + kmsCache := kms.TestKms(t, conn, rootWrapper) + + derivedWrapper := db.TestWrapper(t) + kmsCache.GetDerivedPurposeCache().Store(1, derivedWrapper) + + v, ok := kmsCache.GetDerivedPurposeCache().Load(1) + assert.True(ok) + assert.Equal(derivedWrapper, v) +} + +func TestKms_VerifyGlobalRoot(t *testing.T) { + t.Parallel() + testCtx := context.Background() + assert, require := assert.New(t), require.New(t) + conn, _ := db.TestSetup(t, "postgres") + rootWrapper := db.TestWrapper(t) + kmsCache := kms.TestKms(t, conn, rootWrapper) + + assert.Error(kmsCache.VerifyGlobalRoot(testCtx)) + + require.NoError(kmsCache.CreateKeys(testCtx, "global")) + assert.NoError(kmsCache.VerifyGlobalRoot(testCtx)) +} + +func TestKms_GetWrapper(t *testing.T) { + t.Parallel() + testCtx := context.Background() + conn, _ := db.TestSetup(t, "postgres") + rootWrapper := db.TestWrapper(t) + kmsCache := kms.TestKms(t, conn, rootWrapper) + kmsCache.CreateKeys(testCtx, "global") + tests := []struct { + name string + kms *kms.Kms + purpose kms.KeyPurpose + scopeId string + opt []kms.Option + wantErr bool + wantErrMatch *errors.Template + wantErrContains string + }{ + { + name: "missing-purpose", + kms: kmsCache, + scopeId: "global", + wantErr: true, + wantErrMatch: errors.T(errors.InvalidParameter), + wantErrContains: "missing purpose", + }, + { + name: "missing-scope-id", + kms: kmsCache, + purpose: kms.KeyPurposeDatabase, + wantErr: true, + wantErrMatch: errors.T(errors.InvalidParameter), + wantErrContains: "missing scope id", + }, + { + name: "success", + kms: kmsCache, + purpose: kms.KeyPurposeDatabase, + scopeId: "global", + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + assert, require := assert.New(t), require.New(t) + got, err := tc.kms.GetWrapper(testCtx, tc.scopeId, tc.purpose, tc.opt...) + if tc.wantErr { + require.Error(err) + if tc.wantErrMatch != nil { + assert.Truef(errors.Match(tc.wantErrMatch, err), "expected %q and got err: %+v", tc.wantErrMatch.Code, err) + } + if tc.wantErrContains != "" { + assert.True(strings.Contains(err.Error(), tc.wantErrContains)) + } + return + } + require.NoError(err) + assert.NotNil(got) + }) + } +} + +func TestKms_CreateKeys(t *testing.T) { + t.Parallel() + testCtx := context.Background() + conn, _ := db.TestSetup(t, "postgres") + rootWrapper := db.TestWrapper(t) + kmsCache := kms.TestKms(t, conn, rootWrapper) + kmsCache.CreateKeys(testCtx, "global") + rw := db.New(conn) + + tests := []struct { + name string + kms *kms.Kms + scopeId string + opt []kms.Option + wantErr bool + wantErrMatch *errors.Template + wantErrContains string + }{ + { + name: "missing-scope-id", + kms: kmsCache, + wantErr: true, + wantErrMatch: errors.T(errors.InvalidParameter), + wantErrContains: "missing scope id", + }, + { + name: "invalid-scope", + kms: kmsCache, + scopeId: "o_1234567890", + wantErr: true, + wantErrContains: "violates foreign key constraint", + }, + { + name: "missing-writer-opt", + kms: kmsCache, + scopeId: "global", + opt: []kms.Option{kms.WithReaderWriter(rw, nil)}, + wantErr: true, + wantErrMatch: errors.T(errors.InvalidParameter), + wantErrContains: "missing writer", + }, + { + name: "missing-reader-opt", + kms: kmsCache, + scopeId: "global", + opt: []kms.Option{kms.WithReaderWriter(nil, rw)}, + wantErr: true, + wantErrMatch: errors.T(errors.InvalidParameter), + wantErrContains: "missing reader", + }, + { + name: "success", + kms: kmsCache, + scopeId: "global", + }, + { + name: "success-with-reader-writer", + kms: kmsCache, + opt: []kms.Option{kms.WithReaderWriter(rw, rw)}, + scopeId: "global", + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + assert, require := assert.New(t), require.New(t) + kms.TestKmsDeleteAllKeys(t, conn) + err := tc.kms.CreateKeys(testCtx, tc.scopeId, tc.opt...) + if tc.wantErr { + require.Error(err) + if tc.wantErrMatch != nil { + assert.Truef(errors.Match(tc.wantErrMatch, err), "expected %q and got err: %+v", tc.wantErrMatch.Code, err) + } + if tc.wantErrContains != "" { + assert.True(strings.Contains(err.Error(), tc.wantErrContains)) + } + return + } + require.NoError(err) + }) + } +} diff --git a/internal/kms/kms_test.go b/internal/kms/kms_test.go index 171ce3ff2..83eb47522 100644 --- a/internal/kms/kms_test.go +++ b/internal/kms/kms_test.go @@ -2,73 +2,175 @@ package kms import ( "context" - "crypto/rand" "testing" "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/types/scope" - "github.com/hashicorp/go-uuid" + "github.com/hashicorp/boundary/internal/errors" + "github.com/hashicorp/go-dbw" + wrappingKms "github.com/hashicorp/go-kms-wrapping/extras/kms/v2" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) -func TestKms_KeyId(t *testing.T) { +func Test_New(t *testing.T) { t.Parallel() - require := require.New(t) - ctx := context.Background() + testCtx := context.Background() conn, _ := db.TestSetup(t, "postgres") rw := db.New(conn) - extWrapper := db.TestWrapper(t) - repo, err := NewRepository(rw, rw) - require.NoError(err) - // Make the global scope base keys - _, err = CreateKeysTx(ctx, rw, rw, extWrapper, rand.Reader, scope.Global.String()) - require.NoError(err) + tests := []struct { + name string + r *db.Db + w *db.Db + want *Kms + wantErr bool + wantErrMatch *errors.Template + wantErrContains string + }{ + { + name: "nil-reader", + w: rw, + wantErr: true, + wantErrContains: "missing reader", + wantErrMatch: errors.T(errors.InvalidParameter), + }, + { + name: "nil-writer", + r: rw, + wantErr: true, + wantErrContains: "missing writer", + wantErrMatch: errors.T(errors.InvalidParameter), + }, + { + name: "success", + r: rw, + w: rw, + want: &Kms{ + reader: rw, + underlying: func() *wrappingKms.Kms { + purposes := make([]wrappingKms.KeyPurpose, 0, len(ValidDekPurposes())) + for _, p := range ValidDekPurposes() { + purposes = append(purposes, wrappingKms.KeyPurpose(p.String())) + } + purposes = append(purposes, wrappingKms.KeyPurpose(KeyPurposeWorkerAuth.String()), wrappingKms.KeyPurpose(KeyPurposeRecovery.String())) - // Get the global scope's root wrapper - kmsCache, err := NewKms(repo) - require.NoError(err) - require.NoError(kmsCache.AddExternalWrappers(ctx, WithRootWrapper(extWrapper))) - globalRootWrapper, _, err := kmsCache.loadRoot(ctx, scope.Global.String()) - require.NoError(err) + r := dbw.New(rw.UnderlyingDB()) + w := dbw.New(rw.UnderlyingDB()) + wrapped, err := wrappingKms.New(r, w, purposes, wrappingKms.WithCache(true)) + require.NoError(t, err) + return wrapped + }(), + }, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + assert, require := assert.New(t), require.New(t) - dks, err := repo.ListDatabaseKeys(ctx) - require.NoError(err) - require.Len(dks, 1) - - // Create another key version - newKeyBytes, err := uuid.GenerateRandomBytes(32) - require.NoError(err) - _, err = repo.CreateDatabaseKeyVersion(ctx, globalRootWrapper, dks[0].GetPrivateId(), newKeyBytes) - require.NoError(err) - - dkvs, err := repo.ListDatabaseKeyVersions(ctx, globalRootWrapper, dks[0].GetPrivateId()) - require.NoError(err) - require.Len(dkvs, 2) - - keyId1 := dkvs[0].GetPrivateId() - keyId2 := dkvs[1].GetPrivateId() - - // First test: just getting the key should return the latest - wrapper, err := kmsCache.GetWrapper(ctx, scope.Global.String(), KeyPurposeDatabase) - require.NoError(err) - tKeyId, err := wrapper.KeyId(context.Background()) - require.NoError(err) - require.Equal(keyId2, tKeyId) - - // Second: ask for each in turn - wrapper, err = kmsCache.GetWrapper(ctx, scope.Global.String(), KeyPurposeDatabase, WithKeyId(keyId1)) - require.NoError(err) - tKeyId, err = wrapper.KeyId(context.Background()) - require.NoError(err) - require.Equal(keyId1, tKeyId) - wrapper, err = kmsCache.GetWrapper(ctx, scope.Global.String(), KeyPurposeDatabase, WithKeyId(keyId2)) - require.NoError(err) - tKeyId, err = wrapper.KeyId(context.Background()) - require.NoError(err) - require.Equal(keyId2, tKeyId) - - // Last: verify something bogus finds nothing - _, err = kmsCache.GetWrapper(ctx, scope.Global.String(), KeyPurposeDatabase, WithKeyId("foo")) - require.Error(err) + got, err := New(testCtx, tc.r, tc.w) + if tc.wantErr { + require.Error(err) + if tc.wantErrMatch != nil { + assert.Truef(errors.Match(tc.wantErrMatch, err), "expected %q and got err: %+v", tc.wantErrMatch.Code, err) + } + if tc.wantErrContains != "" { + assert.Contains(err.Error(), tc.wantErrContains) + } + return + } + require.NoError(err) + assert.Equal(tc.want, got) + }) + } +} + +func Test_NewUsingReaderWriter(t *testing.T) { + t.Parallel() + testCtx := context.Background() + conn, _ := db.TestSetup(t, "postgres") + rw := db.New(conn) + + tests := []struct { + name string + r db.Reader + w db.Writer + want *Kms + wantErr bool + wantErrMatch *errors.Template + wantErrContains string + }{ + { + name: "nil-reader", + w: rw, + wantErr: true, + wantErrContains: "missing reader", + wantErrMatch: errors.T(errors.InvalidParameter), + }, + { + name: "nil-writer", + r: rw, + wantErr: true, + wantErrContains: "missing writer", + wantErrMatch: errors.T(errors.InvalidParameter), + }, + { + name: "invalid-reader", + r: &invalidReader{}, + w: rw, + wantErr: true, + wantErrContains: "unable to convert to db.DB", + wantErrMatch: errors.T(errors.InvalidParameter), + }, + { + name: "invalid-writer", + r: rw, + w: &invalidWriter{}, + wantErr: true, + wantErrContains: "unable to convert to db.DB", + wantErrMatch: errors.T(errors.InvalidParameter), + }, + { + name: "success", + r: rw, + w: rw, + want: &Kms{ + reader: rw, + underlying: func() *wrappingKms.Kms { + purposes := stdNewKmsPurposes() + r := dbw.New(rw.UnderlyingDB()) + w := dbw.New(rw.UnderlyingDB()) + wrapped, err := wrappingKms.New(r, w, purposes, wrappingKms.WithCache(true)) + require.NoError(t, err) + return wrapped + }(), + }, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + assert, require := assert.New(t), require.New(t) + + got, err := NewUsingReaderWriter(testCtx, tc.r, tc.w) + if tc.wantErr { + require.Error(err) + if tc.wantErrMatch != nil { + assert.Truef(errors.Match(tc.wantErrMatch, err), "expected %q and got err: %+v", tc.wantErrMatch.Code, err) + } + if tc.wantErrContains != "" { + assert.Contains(err.Error(), tc.wantErrContains) + } + return + } + require.NoError(err) + assert.Equal(tc.want, got) + }) + } +} + +type invalidReader struct { + db.Reader +} + +type invalidWriter struct { + db.Writer } diff --git a/internal/kms/oidc_key.go b/internal/kms/oidc_key.go deleted file mode 100644 index c3acff7ed..000000000 --- a/internal/kms/oidc_key.go +++ /dev/null @@ -1,83 +0,0 @@ -package kms - -import ( - "context" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/kms/store" - "google.golang.org/protobuf/proto" -) - -const ( - DefaultOidcKeyTableName = "kms_oidc_key" -) - -type OidcKey struct { - *store.OidcKey - tableName string `gorm:"-"` -} - -// NewOidcKey creates a new in memory oidc key. This key is used to encrypt -// oidc state before it's included in the oidc auth url. No options are -// currently supported. -func NewOidcKey(rootKeyId string, _ ...Option) (*OidcKey, error) { - const op = "kms.NewOidcKey" - if rootKeyId == "" { - return nil, errors.NewDeprecated(errors.InvalidParameter, op, "missing root key id") - } - c := &OidcKey{ - OidcKey: &store.OidcKey{ - RootKeyId: rootKeyId, - }, - } - return c, nil -} - -// AllocOidcKey will allocate a OidcKey -func AllocOidcKey() OidcKey { - return OidcKey{ - OidcKey: &store.OidcKey{}, - } -} - -// Clone creates a clone of the OidcKey -func (k *OidcKey) Clone() interface{} { - cp := proto.Clone(k.OidcKey) - return &OidcKey{ - OidcKey: cp.(*store.OidcKey), - } -} - -// VetForWrite implements db.VetForWrite() interface and validates the key -// before it's written. -func (k *OidcKey) VetForWrite(ctx context.Context, r db.Reader, opType db.OpType, opt ...db.Option) error { - const op = "kms.(OidcKey).VetForWrite" - if k.PrivateId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - switch opType { - case db.CreateOp: - if k.RootKeyId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "missing root key id") - } - case db.UpdateOp: - return errors.New(ctx, errors.InvalidParameter, op, "key is immutable") - } - return nil -} - -// TableName returns the tablename to override the default gorm table name -func (k *OidcKey) TableName() string { - if k.tableName != "" { - return k.tableName - } - return DefaultOidcKeyTableName -} - -// SetTableName sets the tablename and satisfies the ReplayableMessage -// interface. If the caller attempts to set the name to "" the name will be -// reset to the default name. -func (k *OidcKey) SetTableName(n string) { - k.tableName = n -} diff --git a/internal/kms/oidc_key_test.go b/internal/kms/oidc_key_test.go deleted file mode 100644 index 00430a9aa..000000000 --- a/internal/kms/oidc_key_test.go +++ /dev/null @@ -1,206 +0,0 @@ -package kms_test - -import ( - "context" - "testing" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/iam" - "github.com/hashicorp/boundary/internal/kms" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" -) - -// NOTE: there are no update tests since all the OidcKey attributes are -// immutable and those tests are covered by TestOidcKey_ImmutableFields - -func TestOidcKey_Create(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - - type args struct { - rootKeyId string - opt []kms.Option - } - tests := []struct { - name string - args args - want *kms.OidcKey - wantErr bool - wantIsErr errors.Code - create bool - wantCreateErr bool - }{ - { - name: "empty-rootKeyId", - args: args{}, - wantErr: true, - wantIsErr: errors.InvalidParameter, - }, - { - name: "valid", - args: args{ - rootKeyId: rk.PrivateId, - }, - want: func() *kms.OidcKey { - k := kms.AllocOidcKey() - k.RootKeyId = rk.PrivateId - return &k - }(), - create: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocOidcKey(); return &i }(), "1=1") - got, err := kms.NewOidcKey(tt.args.rootKeyId, tt.args.opt...) - if tt.wantErr { - require.Error(err) - assert.True(errors.Match(errors.T(tt.wantIsErr), err)) - return - } - require.NoError(err) - assert.Equal(tt.want, got) - if tt.create { - id, err := db.NewPublicId(kms.OidcKeyPrefix) - require.NoError(err) - got.PrivateId = id - err = db.New(conn).Create(context.Background(), got) - if tt.wantCreateErr { - assert.Error(err) - return - } else { - assert.NoError(err) - } - } - }) - } -} - -func TestOidcKey_Delete(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocOidcKey(); return &i }(), "1=1") - - tests := []struct { - name string - key *kms.OidcKey - wantRowsDeleted int - wantErr bool - wantErrMsg string - }{ - { - name: "valid", - key: kms.TestOidcKey(t, conn, rk.PrivateId), - wantErr: false, - wantRowsDeleted: 1, - }, - { - name: "bad-id", - key: func() *kms.OidcKey { - k := kms.AllocOidcKey() - id, err := db.NewPublicId(kms.OidcKeyPrefix) - require.NoError(t, err) - k.PrivateId = id - k.RootKeyId = rk.PrivateId - return &k - }(), - wantErr: false, - wantRowsDeleted: 0, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - deleteKey := kms.AllocOidcKey() - deleteKey.PrivateId = tt.key.PrivateId - deletedRows, err := rw.Delete(context.Background(), &deleteKey) - if tt.wantErr { - require.Error(err) - return - } - require.NoError(err) - if tt.wantRowsDeleted == 0 { - assert.Equal(tt.wantRowsDeleted, deletedRows) - return - } - assert.Equal(tt.wantRowsDeleted, deletedRows) - foundKey := kms.AllocOidcKey() - foundKey.PrivateId = tt.key.PrivateId - err = rw.LookupById(context.Background(), &foundKey) - require.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestOidcKey_Clone(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - t.Run("valid", func(t *testing.T) { - assert := assert.New(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - k := kms.TestOidcKey(t, conn, rk.PrivateId) - cp := k.Clone() - assert.True(proto.Equal(cp.(*kms.OidcKey).OidcKey, k.OidcKey)) - }) - t.Run("not-equal", func(t *testing.T) { - assert := assert.New(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - org2, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - rk2 := kms.TestRootKey(t, conn, org2.PublicId) - k := kms.TestOidcKey(t, conn, rk.PrivateId) - k2 := kms.TestOidcKey(t, conn, rk2.PrivateId) - - cp := k.Clone() - assert.True(!proto.Equal(cp.(*kms.OidcKey).OidcKey, k2.OidcKey)) - }) -} - -func TestOidcKey_SetTableName(t *testing.T) { - t.Parallel() - defaultTableName := kms.DefaultOidcKeyTableName - tests := []struct { - name string - setNameTo string - want string - }{ - { - name: "new-name", - setNameTo: "new-name", - want: "new-name", - }, - { - name: "reset to default", - setNameTo: "", - want: defaultTableName, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - def := kms.AllocOidcKey() - require.Equal(defaultTableName, def.TableName()) - s := kms.AllocOidcKey() - s.SetTableName(tt.setNameTo) - assert.Equal(tt.want, s.TableName()) - }) - } -} diff --git a/internal/kms/oidc_key_version.go b/internal/kms/oidc_key_version.go deleted file mode 100644 index f26be0281..000000000 --- a/internal/kms/oidc_key_version.go +++ /dev/null @@ -1,122 +0,0 @@ -package kms - -import ( - "context" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/kms/store" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" - "github.com/hashicorp/go-kms-wrapping/v2/extras/structwrapping" - "google.golang.org/protobuf/proto" -) - -const ( - DefaultOidcKeyVersionTableName = "kms_oidc_key_version" -) - -type OidcKeyVersion struct { - *store.OidcKeyVersion - tableName string `gorm:"-"` -} - -// NewOidcKeyVersion creates a new in memory oidc key version. This key is used -// to encrypt oidc state before it's included in the oidc auth url. No options -// are currently supported. -func NewOidcKeyVersion(oidcKeyId string, key []byte, rootKeyVersionId string, _ ...Option) (*OidcKeyVersion, error) { - const op = "kms.NewOidcKeyVersion" - if oidcKeyId == "" { - return nil, errors.NewDeprecated(errors.InvalidParameter, op, "missing oidc key id") - } - if len(key) == 0 { - return nil, errors.NewDeprecated(errors.InvalidParameter, op, "missing key") - } - if rootKeyVersionId == "" { - return nil, errors.NewDeprecated(errors.InvalidParameter, op, "missing root key version id") - } - - k := &OidcKeyVersion{ - OidcKeyVersion: &store.OidcKeyVersion{ - OidcKeyId: oidcKeyId, - RootKeyVersionId: rootKeyVersionId, - Key: key, - }, - } - return k, nil -} - -// AllocOidcKeyVersion allocates a OidcKeyVersion -func AllocOidcKeyVersion() OidcKeyVersion { - return OidcKeyVersion{ - OidcKeyVersion: &store.OidcKeyVersion{}, - } -} - -// Clone creates a clone of the OidcKeyVersion -func (k *OidcKeyVersion) Clone() interface{} { - cp := proto.Clone(k.OidcKeyVersion) - return &OidcKeyVersion{ - OidcKeyVersion: cp.(*store.OidcKeyVersion), - } -} - -// VetForWrite implements db.VetForWrite() interface and validates the oidc key -// version before it's written. -func (k *OidcKeyVersion) VetForWrite(ctx context.Context, r db.Reader, opType db.OpType, opt ...db.Option) error { - const op = "kms.(OidcKeyVersion).VetForWrite" - if k.PrivateId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - switch opType { - case db.CreateOp: - if k.CtKey == nil { - return errors.New(ctx, errors.InvalidParameter, op, "missing key") - } - if k.OidcKeyId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "missing oidc key id") - } - if k.RootKeyVersionId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "missing root key version id") - } - case db.UpdateOp: - return errors.New(ctx, errors.InvalidParameter, op, "key is immutable") - } - return nil -} - -// TableName returns the tablename to override the default gorm table name -func (k *OidcKeyVersion) TableName() string { - if k.tableName != "" { - return k.tableName - } - return DefaultOidcKeyVersionTableName -} - -// SetTableName sets the tablename and satisfies the ReplayableMessage -// interface. If the caller attempts to set the name to "" the name will be -// reset to the default name. -func (k *OidcKeyVersion) SetTableName(n string) { - k.tableName = n -} - -// Encrypt will encrypt the oidc key version's key -func (k *OidcKeyVersion) Encrypt(ctx context.Context, cipher wrapping.Wrapper) error { - const op = "kms.(OidcKeyVersion).Encrypt" - // structwrapping doesn't support embedding, so we'll pass in the - // store.OidcKeyVersion directly - if err := structwrapping.WrapStruct(ctx, cipher, k.OidcKeyVersion, nil); err != nil { - return errors.Wrap(ctx, err, op, errors.WithCode(errors.Encrypt)) - } - return nil -} - -// Decrypt will decrypt the oidc key version's key -func (k *OidcKeyVersion) Decrypt(ctx context.Context, cipher wrapping.Wrapper) error { - const op = "kms.(OidcKeyVersion).Decrypt" - // structwrapping doesn't support embedding, so we'll pass in the - // store.OidcKeyVersion directly - if err := structwrapping.UnwrapStruct(ctx, cipher, k.OidcKeyVersion, nil); err != nil { - return errors.Wrap(ctx, err, op, errors.WithCode(errors.Decrypt)) - } - return nil -} diff --git a/internal/kms/oidc_key_version_test.go b/internal/kms/oidc_key_version_test.go deleted file mode 100644 index 5fc6fd0d1..000000000 --- a/internal/kms/oidc_key_version_test.go +++ /dev/null @@ -1,249 +0,0 @@ -package kms_test - -import ( - "context" - "testing" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/iam" - "github.com/hashicorp/boundary/internal/kms" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" -) - -// NOTE: there are no update tests since all the OidcKeyVersion attributes are -// immutable and those tests are covered by TestOidcKey_ImmutableFields - -func TestOidcKeyVersion_Create(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - rkv, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - - dk := kms.TestOidcKey(t, conn, rk.PrivateId) - - type args struct { - OidcKeyId string - key []byte - rootKeyVersionId string - opt []kms.Option - } - tests := []struct { - name string - args args - want *kms.OidcKeyVersion - wantErr bool - wantIsErr errors.Code - create bool - wantCreateErr bool - }{ - { - name: "empty-oidc-id", - args: args{ - key: []byte("oidc key"), - rootKeyVersionId: rkv.PrivateId, - }, - wantErr: true, - wantIsErr: errors.InvalidParameter, - }, - { - name: "empty-key", - args: args{ - OidcKeyId: dk.PrivateId, - rootKeyVersionId: rkv.PrivateId, - }, - wantErr: true, - wantIsErr: errors.InvalidParameter, - }, - { - name: "empty-root-key-version-id", - args: args{ - OidcKeyId: dk.PrivateId, - key: []byte("oidc key"), - }, - wantErr: true, - wantIsErr: errors.InvalidParameter, - }, - { - name: "valid", - args: args{ - OidcKeyId: dk.PrivateId, - key: []byte("oidc key"), - rootKeyVersionId: rkv.PrivateId, - }, - want: func() *kms.OidcKeyVersion { - k := kms.AllocOidcKeyVersion() - k.RootKeyVersionId = rkv.PrivateId - k.Key = []byte("oidc key") - k.OidcKeyId = dk.PrivateId - return &k - }(), - create: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocOidcKeyVersion(); return &i }(), "1=1") - got, err := kms.NewOidcKeyVersion(tt.args.OidcKeyId, tt.args.key, tt.args.rootKeyVersionId, tt.args.opt...) - if tt.wantErr { - require.Error(err) - assert.True(errors.Match(errors.T(tt.wantIsErr), err)) - return - } - require.NoError(err) - assert.Equal(tt.want, got) - if tt.create { - id, err := db.NewPublicId(kms.OidcKeyPrefix) - require.NoError(err) - got.PrivateId = id - err = got.Encrypt(context.Background(), rkvWrapper) - require.NoError(err) - err = db.New(conn).Create(context.Background(), got) - if tt.wantCreateErr { - assert.Error(err) - return - } else { - assert.NoError(err) - } - } - }) - } -} - -func TestOidcKeyVersion_Delete(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - dk := kms.TestOidcKey(t, conn, rk.PrivateId) - - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocOidcKeyVersion(); return &i }(), "1=1") - - tests := []struct { - name string - key *kms.OidcKeyVersion - wantRowsDeleted int - wantErr bool - wantErrMsg string - }{ - { - name: "valid", - key: kms.TestOidcKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("oidc key")), - wantErr: false, - wantRowsDeleted: 1, - }, - { - name: "bad-id", - key: func() *kms.OidcKeyVersion { - k := kms.AllocOidcKeyVersion() - id, err := db.NewPublicId(kms.OidcKeyVersionPrefix) - require.NoError(t, err) - k.PrivateId = id - return &k - }(), - wantErr: false, - wantRowsDeleted: 0, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - deleteKey := kms.AllocOidcKeyVersion() - deleteKey.PrivateId = tt.key.PrivateId - deletedRows, err := rw.Delete(context.Background(), &deleteKey) - if tt.wantErr { - require.Error(err) - return - } - require.NoError(err) - if tt.wantRowsDeleted == 0 { - assert.Equal(tt.wantRowsDeleted, deletedRows) - return - } - assert.Equal(tt.wantRowsDeleted, deletedRows) - foundKey := kms.AllocOidcKeyVersion() - foundKey.PrivateId = tt.key.PrivateId - err = rw.LookupById(context.Background(), &foundKey) - require.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestOidcKeyVersion_Clone(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - t.Run("valid", func(t *testing.T) { - assert := assert.New(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - - k := kms.TestOidcKey(t, conn, rk.PrivateId) - kv := kms.TestOidcKeyVersion(t, conn, rkvWrapper, k.PrivateId, []byte("test db key")) - cp := kv.Clone() - assert.True(proto.Equal(cp.(*kms.OidcKeyVersion).OidcKeyVersion, kv.OidcKeyVersion)) - }) - t.Run("not-equal", func(t *testing.T) { - assert := assert.New(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - org2, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - rk2 := kms.TestRootKey(t, conn, org2.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - _, rkvWrapper2 := kms.TestRootKeyVersion(t, conn, wrapper, rk2.PrivateId) - - k := kms.TestOidcKey(t, conn, rk.PrivateId) - k2 := kms.TestOidcKey(t, conn, rk2.PrivateId) - kv := kms.TestOidcKeyVersion(t, conn, rkvWrapper, k.PrivateId, []byte("test db key")) - kv2 := kms.TestOidcKeyVersion(t, conn, rkvWrapper2, k2.PrivateId, []byte("test db key 2")) - - cp := kv.Clone() - assert.True(!proto.Equal(cp.(*kms.OidcKeyVersion).OidcKeyVersion, kv2.OidcKeyVersion)) - }) -} - -func TestOidcKeyVersion_SetTableName(t *testing.T) { - t.Parallel() - defaultTableName := kms.DefaultOidcKeyVersionTableName - tests := []struct { - name string - setNameTo string - want string - }{ - { - name: "new-name", - setNameTo: "new-name", - want: "new-name", - }, - { - name: "reset to default", - setNameTo: "", - want: defaultTableName, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - def := kms.AllocOidcKeyVersion() - require.Equal(defaultTableName, def.TableName()) - s := kms.AllocOidcKeyVersion() - s.SetTableName(tt.setNameTo) - assert.Equal(tt.want, s.TableName()) - }) - } -} diff --git a/internal/kms/oplog_key.go b/internal/kms/oplog_key.go deleted file mode 100644 index 6eb724aee..000000000 --- a/internal/kms/oplog_key.go +++ /dev/null @@ -1,79 +0,0 @@ -package kms - -import ( - "context" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/kms/store" - "google.golang.org/protobuf/proto" -) - -const ( - DefaultOplogKeyTableName = "kms_oplog_key" -) - -type OplogKey struct { - *store.OplogKey - tableName string `gorm:"-"` -} - -// NewOplogKey creates a new in memory key. No options -// are currently supported. -func NewOplogKey(rootKeyId string, _ ...Option) (*OplogKey, error) { - const op = "kms.NewOplogKey" - if rootKeyId == "" { - return nil, errors.NewDeprecated(errors.InvalidParameter, op, "missing root key id") - } - c := &OplogKey{ - OplogKey: &store.OplogKey{ - RootKeyId: rootKeyId, - }, - } - return c, nil -} - -// AllocOplogKey will allocate a key -func AllocOplogKey() OplogKey { - return OplogKey{ - OplogKey: &store.OplogKey{}, - } -} - -// Clone creates a clone of the key -func (k *OplogKey) Clone() interface{} { - cp := proto.Clone(k.OplogKey) - return &OplogKey{ - OplogKey: cp.(*store.OplogKey), - } -} - -// VetForWrite implements db.VetForWrite() interface and validates the key -// before it's written. -func (k *OplogKey) VetForWrite(ctx context.Context, _ db.Reader, opType db.OpType, _ ...db.Option) error { - const op = "kms.(OplogKey).VetForWrite" - if k.PrivateId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - if opType == db.CreateOp { - if k.RootKeyId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "missing root key id") - } - } - return nil -} - -// TableName returns the tablename to override the default gorm table name -func (k *OplogKey) TableName() string { - if k.tableName != "" { - return k.tableName - } - return DefaultOplogKeyTableName -} - -// SetTableName sets the tablename and satisfies the ReplayableMessage -// interface. If the caller attempts to set the name to "" the name will be -// reset to the default name. -func (k *OplogKey) SetTableName(n string) { - k.tableName = n -} diff --git a/internal/kms/oplog_key_test.go b/internal/kms/oplog_key_test.go deleted file mode 100644 index e1a1048e2..000000000 --- a/internal/kms/oplog_key_test.go +++ /dev/null @@ -1,206 +0,0 @@ -package kms_test - -import ( - "context" - "testing" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/iam" - "github.com/hashicorp/boundary/internal/kms" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" -) - -// NOTE: there are no update tests since all the OplogKey attributes are -// immutable and those tests are covered by TestOplogKey_ImmutableFields - -func TestOplogKey_Create(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - - type args struct { - rootKeyId string - opt []kms.Option - } - tests := []struct { - name string - args args - want *kms.OplogKey - wantErr bool - wantIsErr errors.Code - create bool - wantCreateErr bool - }{ - { - name: "empty-rootKeyId", - args: args{}, - wantErr: true, - wantIsErr: errors.InvalidParameter, - }, - { - name: "valid", - args: args{ - rootKeyId: rk.PrivateId, - }, - want: func() *kms.OplogKey { - k := kms.AllocOplogKey() - k.RootKeyId = rk.PrivateId - return &k - }(), - create: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocOplogKey(); return &i }(), "1=1") - got, err := kms.NewOplogKey(tt.args.rootKeyId, tt.args.opt...) - if tt.wantErr { - require.Error(err) - assert.True(errors.Match(errors.T(tt.wantIsErr), err)) - return - } - require.NoError(err) - assert.Equal(tt.want, got) - if tt.create { - id, err := db.NewPublicId(kms.OplogKeyPrefix) - require.NoError(err) - got.PrivateId = id - err = db.New(conn).Create(context.Background(), got) - if tt.wantCreateErr { - assert.Error(err) - return - } else { - assert.NoError(err) - } - } - }) - } -} - -func TestOplogKey_Delete(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocOplogKey(); return &i }(), "1=1") - - tests := []struct { - name string - key *kms.OplogKey - wantRowsDeleted int - wantErr bool - wantErrMsg string - }{ - { - name: "valid", - key: kms.TestOplogKey(t, conn, rk.PrivateId), - wantErr: false, - wantRowsDeleted: 1, - }, - { - name: "bad-id", - key: func() *kms.OplogKey { - k := kms.AllocOplogKey() - id, err := db.NewPublicId(kms.OplogKeyPrefix) - require.NoError(t, err) - k.PrivateId = id - k.RootKeyId = rk.PrivateId - return &k - }(), - wantErr: false, - wantRowsDeleted: 0, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - deleteKey := kms.AllocOplogKey() - deleteKey.PrivateId = tt.key.PrivateId - deletedRows, err := rw.Delete(context.Background(), &deleteKey) - if tt.wantErr { - require.Error(err) - return - } - require.NoError(err) - if tt.wantRowsDeleted == 0 { - assert.Equal(tt.wantRowsDeleted, deletedRows) - return - } - assert.Equal(tt.wantRowsDeleted, deletedRows) - foundKey := kms.AllocOplogKey() - foundKey.PrivateId = tt.key.PrivateId - err = rw.LookupById(context.Background(), &foundKey) - require.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestOplogKey_Clone(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - t.Run("valid", func(t *testing.T) { - assert := assert.New(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - k := kms.TestOplogKey(t, conn, rk.PrivateId) - cp := k.Clone() - assert.True(proto.Equal(cp.(*kms.OplogKey).OplogKey, k.OplogKey)) - }) - t.Run("not-equal", func(t *testing.T) { - assert := assert.New(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - org2, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - rk2 := kms.TestRootKey(t, conn, org2.PublicId) - k := kms.TestOplogKey(t, conn, rk.PrivateId) - k2 := kms.TestOplogKey(t, conn, rk2.PrivateId) - - cp := k.Clone() - assert.True(!proto.Equal(cp.(*kms.OplogKey).OplogKey, k2.OplogKey)) - }) -} - -func TestOplogKey_SetTableName(t *testing.T) { - t.Parallel() - defaultTableName := kms.DefaultOplogKeyTableName - tests := []struct { - name string - setNameTo string - want string - }{ - { - name: "new-name", - setNameTo: "new-name", - want: "new-name", - }, - { - name: "reset to default", - setNameTo: "", - want: defaultTableName, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - def := kms.AllocOplogKey() - require.Equal(defaultTableName, def.TableName()) - s := kms.AllocOplogKey() - s.SetTableName(tt.setNameTo) - assert.Equal(tt.want, s.TableName()) - }) - } -} diff --git a/internal/kms/oplog_key_version.go b/internal/kms/oplog_key_version.go deleted file mode 100644 index 42f905bb3..000000000 --- a/internal/kms/oplog_key_version.go +++ /dev/null @@ -1,118 +0,0 @@ -package kms - -import ( - "context" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/kms/store" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" - "github.com/hashicorp/go-kms-wrapping/v2/extras/structwrapping" - "google.golang.org/protobuf/proto" -) - -const ( - DefaultOplogKeyVersionTableName = "kms_oplog_key_version" -) - -type OplogKeyVersion struct { - *store.OplogKeyVersion - tableName string `gorm:"-"` -} - -// OplogKeyVersion creates a new in memory key version. No options are -// currently supported. -func NewOplogKeyVersion(oplogKeyId string, key []byte, rootKeyVersionId string, _ ...Option) (*OplogKeyVersion, error) { - const op = "kms.NewOplogKeyVersion" - if oplogKeyId == "" { - return nil, errors.NewDeprecated(errors.InvalidParameter, op, "missing oplog key id") - } - if len(key) == 0 { - return nil, errors.NewDeprecated(errors.InvalidParameter, op, "missing key") - } - if rootKeyVersionId == "" { - return nil, errors.NewDeprecated(errors.InvalidParameter, op, "missing root key version id") - } - - k := &OplogKeyVersion{ - OplogKeyVersion: &store.OplogKeyVersion{ - OplogKeyId: oplogKeyId, - RootKeyVersionId: rootKeyVersionId, - Key: key, - }, - } - return k, nil -} - -// AllocOplogKeyVersion allocates a key version -func AllocOplogKeyVersion() OplogKeyVersion { - return OplogKeyVersion{ - OplogKeyVersion: &store.OplogKeyVersion{}, - } -} - -// Clone creates a clone of the key version -func (k *OplogKeyVersion) Clone() interface{} { - cp := proto.Clone(k.OplogKeyVersion) - return &OplogKeyVersion{ - OplogKeyVersion: cp.(*store.OplogKeyVersion), - } -} - -// VetForWrite implements db.VetForWrite() interface and validates the key -// version before it's written. -func (k *OplogKeyVersion) VetForWrite(ctx context.Context, _ db.Reader, opType db.OpType, _ ...db.Option) error { - const op = "kms.(OplogKeyVersion).VetForWrite" - if k.PrivateId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - if opType == db.CreateOp { - if k.CtKey == nil { - return errors.New(ctx, errors.InvalidParameter, op, "missing key") - } - if k.OplogKeyId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "missing oplog key id") - } - if k.RootKeyVersionId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "missing root key version id") - } - } - return nil -} - -// TableName returns the tablename to override the default gorm table name -func (k *OplogKeyVersion) TableName() string { - if k.tableName != "" { - return k.tableName - } - return DefaultOplogKeyVersionTableName -} - -// SetTableName sets the tablename and satisfies the ReplayableMessage -// interface. If the caller attempts to set the name to "" the name will be -// reset to the default name. -func (k *OplogKeyVersion) SetTableName(n string) { - k.tableName = n -} - -// Encrypt will encrypt the key version's key -func (k *OplogKeyVersion) Encrypt(ctx context.Context, cipher wrapping.Wrapper) error { - const op = "kms.(OplogKeyVersion).Encrypt" - // structwrapping doesn't support embedding, so we'll pass in the - // store.OplogKeyVersion directly - if err := structwrapping.WrapStruct(ctx, cipher, k.OplogKeyVersion, nil); err != nil { - return errors.Wrap(ctx, err, op, errors.WithCode(errors.Encrypt)) - } - return nil -} - -// Decrypt will decrypt the key version's key -func (k *OplogKeyVersion) Decrypt(ctx context.Context, cipher wrapping.Wrapper) error { - const op = "kms.(OplogKeyVersion).Decrypt" - // structwrapping doesn't support embedding, so we'll pass in the - // store.OplogKeyVersion directly - if err := structwrapping.UnwrapStruct(ctx, cipher, k.OplogKeyVersion, nil); err != nil { - return errors.Wrap(ctx, err, op, errors.WithCode(errors.Decrypt)) - } - return nil -} diff --git a/internal/kms/oplog_key_version_test.go b/internal/kms/oplog_key_version_test.go deleted file mode 100644 index c4f413a3d..000000000 --- a/internal/kms/oplog_key_version_test.go +++ /dev/null @@ -1,249 +0,0 @@ -package kms_test - -import ( - "context" - "testing" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/iam" - "github.com/hashicorp/boundary/internal/kms" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" -) - -// NOTE: there are no update tests since all the OplogKeyVersion attributes are -// immutable and those tests are covered by TestOplogKey_ImmutableFields - -func TestOplogKeyVersion_Create(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - rkv, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - - dk := kms.TestOplogKey(t, conn, rk.PrivateId) - - type args struct { - oplogKeyId string - key []byte - rootKeyVersionId string - opt []kms.Option - } - tests := []struct { - name string - args args - want *kms.OplogKeyVersion - wantErr bool - wantIsErr errors.Code - create bool - wantCreateErr bool - }{ - { - name: "empty-id", - args: args{ - key: []byte("test key"), - rootKeyVersionId: rkv.PrivateId, - }, - wantErr: true, - wantIsErr: errors.InvalidParameter, - }, - { - name: "empty-key", - args: args{ - oplogKeyId: dk.PrivateId, - rootKeyVersionId: rkv.PrivateId, - }, - wantErr: true, - wantIsErr: errors.InvalidParameter, - }, - { - name: "empty-root-key-version-id", - args: args{ - oplogKeyId: dk.PrivateId, - key: []byte("test key"), - }, - wantErr: true, - wantIsErr: errors.InvalidParameter, - }, - { - name: "valid", - args: args{ - oplogKeyId: dk.PrivateId, - key: []byte("test key"), - rootKeyVersionId: rkv.PrivateId, - }, - want: func() *kms.OplogKeyVersion { - k := kms.AllocOplogKeyVersion() - k.RootKeyVersionId = rkv.PrivateId - k.Key = []byte("test key") - k.OplogKeyId = dk.PrivateId - return &k - }(), - create: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocOplogKeyVersion(); return &i }(), "1=1") - got, err := kms.NewOplogKeyVersion(tt.args.oplogKeyId, tt.args.key, tt.args.rootKeyVersionId, tt.args.opt...) - if tt.wantErr { - require.Error(err) - assert.True(errors.Match(errors.T(tt.wantIsErr), err)) - return - } - require.NoError(err) - assert.Equal(tt.want, got) - if tt.create { - id, err := db.NewPublicId(kms.OplogKeyPrefix) - require.NoError(err) - got.PrivateId = id - err = got.Encrypt(context.Background(), rkvWrapper) - require.NoError(err) - err = db.New(conn).Create(context.Background(), got) - if tt.wantCreateErr { - assert.Error(err) - return - } else { - assert.NoError(err) - } - } - }) - } -} - -func TestOplogKeyVersion_Delete(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - opk := kms.TestOplogKey(t, conn, rk.PrivateId) - - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocOplogKeyVersion(); return &i }(), "1=1") - - tests := []struct { - name string - key *kms.OplogKeyVersion - wantRowsDeleted int - wantErr bool - wantErrMsg string - }{ - { - name: "valid", - key: kms.TestOplogKeyVersion(t, conn, rkvWrapper, opk.PrivateId, []byte("test key")), - wantErr: false, - wantRowsDeleted: 1, - }, - { - name: "bad-id", - key: func() *kms.OplogKeyVersion { - k := kms.AllocOplogKeyVersion() - id, err := db.NewPublicId(kms.OplogKeyVersionPrefix) - require.NoError(t, err) - k.PrivateId = id - return &k - }(), - wantErr: false, - wantRowsDeleted: 0, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - deleteKey := kms.AllocOplogKeyVersion() - deleteKey.PrivateId = tt.key.PrivateId - deletedRows, err := rw.Delete(context.Background(), &deleteKey) - if tt.wantErr { - require.Error(err) - return - } - require.NoError(err) - if tt.wantRowsDeleted == 0 { - assert.Equal(tt.wantRowsDeleted, deletedRows) - return - } - assert.Equal(tt.wantRowsDeleted, deletedRows) - foundKey := kms.AllocOplogKeyVersion() - foundKey.PrivateId = tt.key.PrivateId - err = rw.LookupById(context.Background(), &foundKey) - require.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestOplogKeyVersion_Clone(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - t.Run("valid", func(t *testing.T) { - assert := assert.New(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - - k := kms.TestOplogKey(t, conn, rk.PrivateId) - kv := kms.TestOplogKeyVersion(t, conn, rkvWrapper, k.PrivateId, []byte("test key")) - cp := kv.Clone() - assert.True(proto.Equal(cp.(*kms.OplogKeyVersion).OplogKeyVersion, kv.OplogKeyVersion)) - }) - t.Run("not-equal", func(t *testing.T) { - assert := assert.New(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - org2, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - rk2 := kms.TestRootKey(t, conn, org2.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - _, rkvWrapper2 := kms.TestRootKeyVersion(t, conn, wrapper, rk2.PrivateId) - - k := kms.TestOplogKey(t, conn, rk.PrivateId) - k2 := kms.TestOplogKey(t, conn, rk2.PrivateId) - kv := kms.TestOplogKeyVersion(t, conn, rkvWrapper, k.PrivateId, []byte("test key")) - kv2 := kms.TestOplogKeyVersion(t, conn, rkvWrapper2, k2.PrivateId, []byte("test key 2")) - - cp := kv.Clone() - assert.True(!proto.Equal(cp.(*kms.OplogKeyVersion).OplogKeyVersion, kv2.OplogKeyVersion)) - }) -} - -func TestOplogKeyVersion_SetTableName(t *testing.T) { - t.Parallel() - defaultTableName := kms.DefaultOplogKeyVersionTableName - tests := []struct { - name string - setNameTo string - want string - }{ - { - name: "new-name", - setNameTo: "new-name", - want: "new-name", - }, - { - name: "reset to default", - setNameTo: "", - want: defaultTableName, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - def := kms.AllocOplogKeyVersion() - require.Equal(defaultTableName, def.TableName()) - s := kms.AllocOplogKeyVersion() - s.SetTableName(tt.setNameTo) - assert.Equal(tt.want, s.TableName()) - }) - } -} diff --git a/internal/kms/option_test.go b/internal/kms/option_test.go index c5e8e880c..2ed5562a6 100644 --- a/internal/kms/option_test.go +++ b/internal/kms/option_test.go @@ -35,4 +35,11 @@ func Test_GetOpts(t *testing.T) { testOpts.withOrderByVersion = db.DescendingOrderBy assert.Equal(opts, testOpts) }) + t.Run("WithKeyId", func(t *testing.T) { + assert := assert.New(t) + opts := getOpts(WithKeyId("100")) + testOpts := getDefaultOptions() + testOpts.withKeyId = "100" + assert.Equal(opts, testOpts) + }) } diff --git a/internal/kms/options.go b/internal/kms/options.go index 4473d2b4b..ab52ccaa1 100644 --- a/internal/kms/options.go +++ b/internal/kms/options.go @@ -1,6 +1,8 @@ package kms import ( + "io" + "github.com/hashicorp/boundary/internal/db" wrapping "github.com/hashicorp/go-kms-wrapping/v2" ) @@ -23,10 +25,12 @@ type options struct { withRootWrapper wrapping.Wrapper withWorkerAuthWrapper wrapping.Wrapper withRecoveryWrapper wrapping.Wrapper - withRepository *Repository withOrderByVersion db.OrderBy withKeyId string withScopeIds []string + withRandomReader io.Reader + withReader db.Reader + withWriter db.Writer } func getDefaultOptions() options { @@ -64,14 +68,6 @@ func WithRecoveryWrapper(w wrapping.Wrapper) Option { } } -// WithRepository sets a repository for a given wrapper lookup, useful if in the -// middle of a transaction where the reader/writer need to be specified -func WithRepository(repo *Repository) Option { - return func(o *options) { - o.withRepository = repo - } -} - // WithOrderByVersion provides an option to specify ordering by the // CreateTime field. func WithOrderByVersion(orderBy db.OrderBy) Option { @@ -95,3 +91,23 @@ func WithScopeIds(scopeId ...string) Option { o.withScopeIds = scopeId } } + +// WithRandomReader(...) option allows an optional random reader to be +// provided. By default the reader from crypto/rand will be used. +func WithRandomReader(randomReader io.Reader) Option { + return func(o *options) { + o.withRandomReader = randomReader + } +} + +// WithReaderWriter allows the caller to pass an inflight transaction to be used +// for all database operations. If WithReaderWriter(...) is used, then the +// caller is responsible for managing the transaction. The purpose of the +// WithReaderWriter(...) option is to allow the caller to create the scope and +// all of its keys in the same transaction. +func WithReaderWriter(r db.Reader, w db.Writer) Option { + return func(o *options) { + o.withReader = r + o.withWriter = w + } +} diff --git a/internal/kms/repository.go b/internal/kms/repository.go deleted file mode 100644 index 10c7ed7c3..000000000 --- a/internal/kms/repository.go +++ /dev/null @@ -1,200 +0,0 @@ -package kms - -import ( - "context" - "fmt" - "io" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/types/scope" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" - aead "github.com/hashicorp/go-kms-wrapping/v2/aead" - "github.com/hashicorp/go-uuid" -) - -// Repository is the iam database repository -type Repository struct { - reader db.Reader - writer db.Writer - // defaultLimit provides a default for limiting the number of results returned from the repo - defaultLimit int -} - -// NewRepository creates a new kms Repository. Supports the options: WithLimit -// which sets a default limit on results returned by repo operations. -func NewRepository(r db.Reader, w db.Writer, opt ...Option) (*Repository, error) { - const op = "kms.NewRepository" - if r == nil { - return nil, errors.NewDeprecated(errors.InvalidParameter, op, "nil reader") - } - if w == nil { - return nil, errors.NewDeprecated(errors.InvalidParameter, op, "nil writer") - } - opts := getOpts(opt...) - if opts.withLimit == 0 { - // zero signals the boundary defaults should be used. - opts.withLimit = db.DefaultLimit - } - return &Repository{ - reader: r, - writer: w, - defaultLimit: opts.withLimit, - }, nil -} - -// list will return a listing of resources and honor the WithLimit option or the -// repo defaultLimit -func (r *Repository) list(ctx context.Context, resources interface{}, where string, args []interface{}, opt ...Option) error { - opts := getOpts(opt...) - limit := r.defaultLimit - var dbOpts []db.Option - if opts.withLimit != 0 { - // non-zero signals an override of the default limit for the repo. - limit = opts.withLimit - } - dbOpts = append(dbOpts, db.WithLimit(limit)) - switch opts.withOrderByVersion { - case db.AscendingOrderBy: - dbOpts = append(dbOpts, db.WithOrder("version asc")) - case db.DescendingOrderBy: - dbOpts = append(dbOpts, db.WithOrder("version desc")) - } - - return r.reader.SearchWhere(ctx, resources, where, args, dbOpts...) -} - -// DefaultLimit returns the default limit for listing as set on the repo -func (r *Repository) DefaultLimit() int { - return r.defaultLimit -} - -// KeyIder defines a common interface for all keys returned from CreateKeysTx in -// a Keys map -type KeyIder interface { - GetPrivateId() string -} - -// Keys defines a return type for CreateKeysTx so the returned keys can be -// easily accessed via their KeyType -type Keys map[KeyType]KeyIder - -// CreateKeysTx creates the root key and DEKs returns a map of the new keys. -// This function encapsulates all the work required within a db.TxHandler and -// allows this capability to be shared with the iam repo. -func CreateKeysTx(ctx context.Context, dbReader db.Reader, dbWriter db.Writer, rootWrapper wrapping.Wrapper, randomReader io.Reader, scopeId string) (Keys, error) { - const op = "kms.CreateKeysTx" - if dbReader == nil { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing db reader") - } - if dbWriter == nil { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing db writer") - } - if rootWrapper == nil { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing root wrapper") - } - if randomReader == nil { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing random reader") - } - if scopeId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing scope id") - } - k, err := generateKey(ctx, randomReader) - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("error generating random bytes for root key in scope %s", scopeId))) - } - rootKey, rootKeyVersion, err := createRootKeyTx(ctx, dbWriter, rootWrapper, scopeId, k) - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("unable to create root key in scope %s", scopeId))) - } - - rkvWrapper := aead.NewWrapper() - if _, err := rkvWrapper.SetConfig(ctx, wrapping.WithKeyId(rootKeyVersion.GetPrivateId())); err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("error setting config on aead root wrapper in scope %s", scopeId))) - } - if err := rkvWrapper.SetAesGcmKeyBytes(rootKeyVersion.GetKey()); err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("error setting key bytes on aead root wrapper in scope %s", scopeId))) - } - - k, err = generateKey(ctx, randomReader) - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("error generating random bytes for database key in scope %s", scopeId))) - } - dbKey, dbKeyVersion, err := createDatabaseKeyTx(ctx, dbReader, dbWriter, rkvWrapper, k) - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("unable to create database key in scope %s", scopeId))) - } - - k, err = generateKey(ctx, randomReader) - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("error generating random bytes for oplog key in scope %s", scopeId))) - } - oplogKey, oplogKeyVersion, err := createOplogKeyTx(ctx, dbReader, dbWriter, rkvWrapper, k) - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("unable to create oplog key in scope %s", scopeId))) - } - - k, err = generateKey(ctx, randomReader) - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("error generating random bytes for session key in scope %s", scopeId))) - } - sessionKey, sessionKeyVersion, err := createSessionKeyTx(ctx, dbReader, dbWriter, rkvWrapper, k) - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("unable to create session key in scope %s", scopeId))) - } - - k, err = generateKey(ctx, randomReader) - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("error generating random bytes for token key in scope %s", scopeId))) - } - tokenKey, tokenKeyVersion, err := createTokenKeyTx(ctx, dbReader, dbWriter, rkvWrapper, k) - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("unable to create token key in scope %s", scopeId))) - } - - k, err = generateKey(ctx, randomReader) - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("error generating random bytes for oidc key in scope %s", scopeId))) - } - oidcKey, oidcKeyVersion, err := createOidcKeyTx(ctx, dbReader, dbWriter, rkvWrapper, k) - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("unable to create oidc key in scope %s", scopeId))) - } - keys := Keys{ - KeyTypeRootKey: rootKey, - KeyTypeRootKeyVersion: rootKeyVersion, - KeyTypeDatabaseKey: dbKey, - KeyTypeDatabaseKeyVersion: dbKeyVersion, - KeyTypeOplogKey: oplogKey, - KeyTypeOplogKeyVersion: oplogKeyVersion, - KeyTypeSessionKey: sessionKey, - KeyTypeSessionKeyVersion: sessionKeyVersion, - KeyTypeTokenKey: tokenKey, - KeyTypeTokenKeyVersion: tokenKeyVersion, - KeyTypeOidcKey: oidcKey, - KeyTypeOidcKeyVersion: oidcKeyVersion, - } - if scopeId == scope.Global.String() { - k, err = generateKey(ctx, randomReader) - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("error generating random bytes for oidc key in scope %s", scopeId))) - } - auditKey, auditKeyVersion, err := createAuditKeyTx(ctx, dbReader, dbWriter, rkvWrapper, k) - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("unable to create audit key in scope %s", scopeId))) - } - keys[KeyTypeAuditKey] = auditKey - keys[KeyTypeAuditKeyVersion] = auditKeyVersion - } - - return keys, nil -} - -func generateKey(ctx context.Context, randomReader io.Reader) ([]byte, error) { - const op = "kms.generateKey" - k, err := uuid.GenerateRandomBytesWithReader(32, randomReader) - if err != nil { - return nil, errors.Wrap(ctx, err, op) - } - return k, nil -} diff --git a/internal/kms/repository_audit_key.go b/internal/kms/repository_audit_key.go deleted file mode 100644 index 96e25b143..000000000 --- a/internal/kms/repository_audit_key.go +++ /dev/null @@ -1,163 +0,0 @@ -package kms - -import ( - "context" - "fmt" - "strings" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" -) - -// CreateAuditKey inserts into the repository and returns the new audit key and -// audit key version. There are no valid options at this time. -func (r *Repository) CreateAuditKey(ctx context.Context, rkvWrapper wrapping.Wrapper, key []byte, _ ...Option) (*AuditKey, *AuditKeyVersion, error) { - const op = "kms.(Repository).CreateAuditKey" - var returnedDk, returnedDv interface{} - _, err := r.writer.DoTx( - ctx, - db.StdRetryCnt, - db.ExpBackoff{}, - func(reader db.Reader, w db.Writer) error { - var err error - if returnedDk, returnedDv, err = createAuditKeyTx(ctx, reader, w, rkvWrapper, key); err != nil { - return errors.Wrap(ctx, err, op) - } - return nil - }, - ) - if err != nil { - return nil, nil, errors.Wrap(ctx, err, op) - } - return returnedDk.(*AuditKey), returnedDv.(*AuditKeyVersion), nil -} - -// createAuditKeyTx inserts into the db (via db.Writer) and returns the new audit key -// and audit key version. This function encapsulates all the work required within -// a db.TxHandler and allows this capability to be shared with the iam repo. -func createAuditKeyTx(ctx context.Context, r db.Reader, w db.Writer, rkvWrapper wrapping.Wrapper, key []byte) (*AuditKey, *AuditKeyVersion, error) { - const op = "kms.createAuditKeyTx" - if rkvWrapper == nil { - return nil, nil, errors.New(ctx, errors.InvalidParameter, op, "missing key wrapper") - } - if len(key) == 0 { - return nil, nil, errors.New(ctx, errors.InvalidParameter, op, "missing key") - } - rootKeyVersionId, err := rkvWrapper.KeyId(ctx) - if err != nil { - return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to lookup root key id")) - } - switch { - case !strings.HasPrefix(rootKeyVersionId, RootKeyVersionPrefix): - return nil, nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("root key version id %s doesn't start with prefix %s", rootKeyVersionId, RootKeyVersionPrefix)) - case rootKeyVersionId == "": - return nil, nil, errors.New(ctx, errors.InvalidParameter, op, "missing root key version id") - } - rv := AllocRootKeyVersion() - rv.PrivateId = rootKeyVersionId - err = r.LookupById(ctx, &rv) - if err != nil { - return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("unable to lookup root key version %s", rootKeyVersionId))) - } - - dk := AllocAuditKey() - dv := AllocAuditKeyVersion() - id, err := newAuditKeyId(ctx) - if err != nil { - return nil, nil, errors.Wrap(ctx, err, op) - } - dk.PrivateId = id - dk.RootKeyId = rv.RootKeyId - - id, err = newAuditKeyVersionId(ctx) - if err != nil { - return nil, nil, errors.Wrap(ctx, err, op) - } - dv.PrivateId = id - dv.AuditKeyId = dk.PrivateId - dv.RootKeyVersionId = rootKeyVersionId - dv.Key = key - if err := dv.Encrypt(ctx, rkvWrapper); err != nil { - return nil, nil, errors.Wrap(ctx, err, op) - } - - // no oplog entries for keys - if err := w.Create(ctx, &dk); err != nil { - return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg("keys create")) - } - // no oplog entries for key versions - if err := w.Create(ctx, &dv); err != nil { - return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg("key versions create")) - } - - return &dk, &dv, nil -} - -// LookupAuditKey will look up a key in the repository. If the key is not -// found, it will return nil, nil. -func (r *Repository) LookupAuditKey(ctx context.Context, privateId string, _ ...Option) (*AuditKey, error) { - const op = "kms.(Repository).LookupAuditKey" - if privateId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - k := AllocAuditKey() - k.PrivateId = privateId - if err := r.reader.LookupById(ctx, &k); err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - return &k, nil -} - -// DeleteAuditKey deletes the key for the provided id from the -// repository returning a count of the number of records deleted. All options -// are ignored. -func (r *Repository) DeleteAuditKey(ctx context.Context, privateId string, _ ...Option) (int, error) { - const op = "kms.(Repository).DeleteAuditKey" - if privateId == "" { - return db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - k := AllocAuditKey() - k.PrivateId = privateId - if err := r.reader.LookupById(ctx, &k); err != nil { - return db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - - var rowsDeleted int - _, err := r.writer.DoTx( - ctx, - db.StdRetryCnt, - db.ExpBackoff{}, - func(_ db.Reader, w db.Writer) (err error) { - dk := k.Clone() - // no oplog entries for root keys - rowsDeleted, err = w.Delete(ctx, dk) - if err != nil { - return errors.Wrap(ctx, err, op) - } - if rowsDeleted > 1 { - return errors.New(ctx, errors.MultipleRecords, op, "more than 1 resource would have been deleted") - } - return nil - }, - ) - if err != nil { - return db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - return rowsDeleted, nil -} - -// ListAuditKeys will list the keys. Supports the WithLimit option. -func (r *Repository) ListAuditKeys(ctx context.Context, opt ...Option) ([]Dek, error) { - const op = "kms.(Repository).ListAuditKeys" - var keys []*AuditKey - err := r.list(ctx, &keys, "1=1", nil, opt...) - if err != nil { - return nil, errors.Wrap(ctx, err, op) - } - deks := make([]Dek, 0, len(keys)) - for _, key := range keys { - deks = append(deks, key) - } - return deks, nil -} diff --git a/internal/kms/repository_audit_key_test.go b/internal/kms/repository_audit_key_test.go deleted file mode 100644 index d9255505b..000000000 --- a/internal/kms/repository_audit_key_test.go +++ /dev/null @@ -1,298 +0,0 @@ -package kms_test - -import ( - "context" - "testing" - "time" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/iam" - "github.com/hashicorp/boundary/internal/kms" - "github.com/hashicorp/boundary/internal/oplog" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" - "github.com/hashicorp/go-kms-wrapping/v2/aead" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" -) - -func TestRepository_CreateAuditKey(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - - type args struct { - scopeId string - key []byte - keyWrapper wrapping.Wrapper - opt []kms.Option - } - tests := []struct { - name string - args args - wantErr bool - wantIsError errors.Code - }{ - { - name: "valid-org", - args: args{ - scopeId: org.PublicId, - key: []byte("test key"), - keyWrapper: rkvWrapper, - }, - wantErr: false, - }, - { - name: "nil-key", - args: args{ - scopeId: org.PublicId, - keyWrapper: rkvWrapper, - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "empty-key", - args: args{ - scopeId: org.PublicId, - keyWrapper: rkvWrapper, - key: []byte(""), - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "nil-wrapper", - args: args{ - scopeId: org.PublicId, - key: []byte("test key"), - keyWrapper: nil, - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "not-rkv-wrapper", - args: args{ - scopeId: org.PublicId, - key: []byte("test key"), - keyWrapper: wrapper, - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "wrapper-missing-id", - args: args{ - scopeId: org.PublicId, - key: []byte("test key"), - keyWrapper: func() wrapping.Wrapper { - w := db.TestWrapper(t) - _, err = w.(*aead.Wrapper).SetConfig( - context.Background(), - wrapping.WithKeyId(""), - ) - require.NoError(t, err) - return w - }(), - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - dk, dv, err := repo.CreateAuditKey(context.Background(), tt.args.keyWrapper, tt.args.key, tt.args.opt...) - if tt.wantErr { - assert.Error(err) - assert.Nil(dk) - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - return - } - require.NoError(err) - assert.NotNil(dk.CreateTime) - foundKey, err := repo.LookupAuditKey(context.Background(), dk.PrivateId) - assert.NoError(err) - assert.True(proto.Equal(foundKey, dk)) - - // make sure there was no oplog written - err = db.TestVerifyOplog(t, rw, dk.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_CREATE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - - assert.NotNil(dv.CreateTime) - foundKeyVersion, err := repo.LookupAuditKeyVersion(context.Background(), tt.args.keyWrapper, dv.PrivateId) - assert.NoError(err) - assert.True(proto.Equal(foundKeyVersion, dv)) - - // make sure there was no oplog written - err = db.TestVerifyOplog(t, rw, dv.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_CREATE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestRepository_DeleteAuditKey(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - - type args struct { - key *kms.AuditKey - opt []kms.Option - } - tests := []struct { - name string - args args - wantRowsDeleted int - wantErr bool - wantIsError errors.Code - }{ - { - name: "valid", - args: args{ - key: kms.TestAuditKey(t, conn, rk.PrivateId), - }, - wantRowsDeleted: 1, - wantErr: false, - }, - { - name: "no-private-id", - args: args{ - key: func() *kms.AuditKey { - k := kms.AllocAuditKey() - return &k - }(), - }, - wantRowsDeleted: 0, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "not-found", - args: args{ - key: func() *kms.AuditKey { - id, err := db.NewPublicId(kms.RootKeyPrefix) - require.NoError(t, err) - k := kms.AllocAuditKey() - k.PrivateId = id - require.NoError(t, err) - return &k - }(), - }, - wantRowsDeleted: 0, - wantErr: true, - wantIsError: errors.RecordNotFound, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - deletedRows, err := repo.DeleteAuditKey(context.Background(), tt.args.key.PrivateId, tt.args.opt...) - if tt.wantErr { - require.Error(err) - assert.Equal(0, deletedRows) - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - // make sure there was no oplog written - err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - return - } - require.NoError(err) - assert.Equal(tt.wantRowsDeleted, deletedRows) - foundKey, err := repo.LookupAuditKey(context.Background(), tt.args.key.PrivateId) - assert.Error(err) - assert.Nil(foundKey) - assert.True(errors.IsNotFoundError(err)) - - // make sure there was no oplog written - err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestRepository_ListAuditKeys(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - const testLimit = 10 - rw := db.New(conn) - repo, err := kms.NewRepository(rw, rw, kms.WithLimit(testLimit)) - require.NoError(t, err) - wrapper := db.TestWrapper(t) - - type args struct { - opt []kms.Option - } - tests := []struct { - name string - createCnt int - args args - wantCnt int - wantErr bool - }{ - { - name: "no-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{ - opt: []kms.Option{kms.WithLimit(-1)}, - }, - wantCnt: repo.DefaultLimit() + 1, // org and project both have keys, plus global scope - wantErr: false, - }, - { - name: "default-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{}, - wantCnt: repo.DefaultLimit(), - wantErr: false, - }, - { - name: "custom-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{ - opt: []kms.Option{kms.WithLimit(3)}, - }, - wantCnt: 3, - wantErr: false, - }, - } - for _, tt := range tests { - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - for i := 0; i < tt.createCnt; i++ { - org, proj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "scope_id in(?)", "global", org.PublicId, proj.PublicId) - rk := kms.TestRootKey(t, conn, proj.PublicId) - kms.TestAuditKey(t, conn, rk.PrivateId) - require.NoError(err) - } - got, err := repo.ListAuditKeys(context.Background(), tt.args.opt...) - if tt.wantErr { - require.Error(err) - return - } - require.NoError(err) - assert.Equal(tt.wantCnt, len(got)) - }) - } -} diff --git a/internal/kms/repository_audit_key_version.go b/internal/kms/repository_audit_key_version.go deleted file mode 100644 index 1a474a930..000000000 --- a/internal/kms/repository_audit_key_version.go +++ /dev/null @@ -1,176 +0,0 @@ -package kms - -import ( - "context" - "fmt" - "strings" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" -) - -// CreateAuditKeyVersion inserts into the repository and returns the new key -// version with its PrivateId. There are no valid options at this time. -func (r *Repository) CreateAuditKeyVersion(ctx context.Context, rkvWrapper wrapping.Wrapper, auditKeyId string, key []byte, _ ...Option) (*AuditKeyVersion, error) { - const op = "kms.(Repository).CreateAuditKeyVersion" - if rkvWrapper == nil { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing root key version wrapper") - } - rootKeyVersionId, err := rkvWrapper.KeyId(ctx) - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to lookup root key version ID")) - } - switch { - case !strings.HasPrefix(rootKeyVersionId, RootKeyVersionPrefix): - return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("root key version id %s doesn't start with prefix %s", rootKeyVersionId, RootKeyVersionPrefix)) - case rootKeyVersionId == "": - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing root key version id") - } - if auditKeyId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing audit key id") - } - if len(key) == 0 { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing key") - } - kv := AllocAuditKeyVersion() - id, err := newAuditKeyVersionId(ctx) - if err != nil { - return nil, errors.Wrap(ctx, err, op) - } - kv.PrivateId = id - kv.RootKeyVersionId = rootKeyVersionId - kv.Key = key - kv.AuditKeyId = auditKeyId - if err := kv.Encrypt(ctx, rkvWrapper); err != nil { - return nil, errors.Wrap(ctx, err, op) - } - - var returnedKey interface{} - _, err = r.writer.DoTx( - ctx, - db.StdRetryCnt, - db.ExpBackoff{}, - func(_ db.Reader, w db.Writer) error { - returnedKey = kv.Clone() - // no oplog entries for root key version - if err := w.Create(ctx, returnedKey); err != nil { - return errors.Wrap(ctx, err, op) - } - return nil - }, - ) - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s audit key id", kv.AuditKeyId))) - } - return returnedKey.(*AuditKeyVersion), nil -} - -// LookupAuditKeyVersion will look up a key version in the repository. If -// the key version is not found, it will return nil, nil. -func (r *Repository) LookupAuditKeyVersion(ctx context.Context, keyWrapper wrapping.Wrapper, privateId string, _ ...Option) (*AuditKeyVersion, error) { - const op = "kms.(Repository).LookupAuditKeyVersion" - if privateId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - if keyWrapper == nil { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing key wrapper") - } - k := AllocAuditKeyVersion() - k.PrivateId = privateId - if err := r.reader.LookupById(ctx, &k); err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - if err := k.Decrypt(ctx, keyWrapper); err != nil { - return nil, errors.Wrap(ctx, err, op) - } - return &k, nil -} - -// DeleteAuditKeyVersion deletes the key version for the provided id from the -// repository returning a count of the number of records deleted. All options -// are ignored. -func (r *Repository) DeleteAuditKeyVersion(ctx context.Context, privateId string, _ ...Option) (int, error) { - const op = "kms.(Repository).DeleteAuditKeyVersion" - if privateId == "" { - return db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - k := AllocAuditKeyVersion() - k.PrivateId = privateId - if err := r.reader.LookupById(ctx, &k); err != nil { - return db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - - var rowsDeleted int - _, err := r.writer.DoTx( - ctx, - db.StdRetryCnt, - db.ExpBackoff{}, - func(_ db.Reader, w db.Writer) (err error) { - dk := k.Clone() - // no oplog entries for the key version - rowsDeleted, err = w.Delete(ctx, dk) - if err != nil { - return errors.Wrap(ctx, err, op) - } - if rowsDeleted > 1 { - return errors.New(ctx, errors.MultipleRecords, op, "more than 1 resource would have been deleted") - } - return nil - }, - ) - if err != nil { - return db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - return rowsDeleted, nil -} - -// LatestAuditKeyVersion searches for the key version with the highest -// version number. When no results are found, it returns nil with an -// errors.RecordNotFound error. -func (r *Repository) LatestAuditKeyVersion(ctx context.Context, rkvWrapper wrapping.Wrapper, AuditKeyId string, _ ...Option) (*AuditKeyVersion, error) { - const op = "kms.(Repository).LatestAuditKeyVersion" - if AuditKeyId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing audit key id") - } - if rkvWrapper == nil { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing root key version wrapper") - } - var foundKeys []*AuditKeyVersion - if err := r.reader.SearchWhere(ctx, &foundKeys, "audit_key_id = ?", []interface{}{AuditKeyId}, db.WithLimit(1), db.WithOrder("version desc")); err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", AuditKeyId))) - } - if len(foundKeys) == 0 { - return nil, errors.E(ctx, errors.WithCode(errors.RecordNotFound), errors.WithOp(op)) - } - if err := foundKeys[0].Decrypt(ctx, rkvWrapper); err != nil { - return nil, errors.Wrap(ctx, err, op) - } - return foundKeys[0], nil -} - -// ListAuditKeyVersions will lists versions of a key. Supports the WithLimit option. -func (r *Repository) ListAuditKeyVersions(ctx context.Context, rkvWrapper wrapping.Wrapper, AuditKeyId string, opt ...Option) ([]DekVersion, error) { - const op = "kms.(Repository).ListAuditKeyVersions" - if AuditKeyId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing audit key id") - } - if rkvWrapper == nil { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing root key version wrapper") - } - var versions []*AuditKeyVersion - err := r.list(ctx, &versions, "audit_key_id = ?", []interface{}{AuditKeyId}, opt...) - if err != nil { - return nil, errors.Wrap(ctx, err, op) - } - for i, k := range versions { - if err := k.Decrypt(ctx, rkvWrapper); err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("error decrypting key num %d", i))) - } - } - dekVersions := make([]DekVersion, 0, len(versions)) - for _, version := range versions { - dekVersions = append(dekVersions, version) - } - return dekVersions, nil -} diff --git a/internal/kms/repository_audit_key_version_test.go b/internal/kms/repository_audit_key_version_test.go deleted file mode 100644 index e87fa43b3..000000000 --- a/internal/kms/repository_audit_key_version_test.go +++ /dev/null @@ -1,367 +0,0 @@ -package kms_test - -import ( - "context" - "testing" - "time" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/iam" - "github.com/hashicorp/boundary/internal/kms" - "github.com/hashicorp/boundary/internal/oplog" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" -) - -func TestRepository_CreateAuditKeyVersion(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - dk := kms.TestAuditKey(t, conn, rk.PrivateId) - - type args struct { - key []byte - AuditKeyId string - keyWrapper wrapping.Wrapper - opt []kms.Option - } - tests := []struct { - name string - args args - wantErr bool - wantIsError errors.Code - }{ - { - name: "valid", - args: args{ - key: []byte("test key"), - keyWrapper: rkvWrapper, - AuditKeyId: dk.PrivateId, - }, - wantErr: false, - }, - { - name: "invalid-rkv-wrapper", - args: args{ - key: []byte("test key"), - keyWrapper: wrapper, - AuditKeyId: dk.PrivateId, - }, - wantErr: true, - }, - { - name: "empty-key", - args: args{ - key: nil, - keyWrapper: wrapper, - AuditKeyId: dk.PrivateId, - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "nil-wrapper", - args: args{ - key: []byte("test key"), - keyWrapper: nil, - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - k, err := repo.CreateAuditKeyVersion(context.Background(), tt.args.keyWrapper, tt.args.AuditKeyId, tt.args.key, tt.args.opt...) - if tt.wantErr { - assert.Error(err) - assert.Nil(k) - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - return - } - require.NoError(err) - assert.NotNil(k.CreateTime) - foundKey, err := repo.LookupAuditKeyVersion(context.Background(), tt.args.keyWrapper, k.PrivateId) - assert.NoError(err) - assert.True(proto.Equal(foundKey, k)) - - // make sure there was no oplog written - err = db.TestVerifyOplog(t, rw, k.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_CREATE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestRepository_DeleteAuditKeyVersion(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - dk := kms.TestAuditKey(t, conn, rk.PrivateId) - - type args struct { - key *kms.AuditKeyVersion - opt []kms.Option - } - tests := []struct { - name string - args args - wantRowsDeleted int - wantErr bool - wantIsError errors.Code - }{ - { - name: "valid", - args: args{ - key: kms.TestAuditKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("audit key")), - }, - wantRowsDeleted: 1, - wantErr: false, - }, - { - name: "no-private-id", - args: args{ - key: func() *kms.AuditKeyVersion { - k := kms.AllocAuditKeyVersion() - return &k - }(), - }, - wantRowsDeleted: 0, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "not-found", - args: args{ - key: func() *kms.AuditKeyVersion { - id, err := db.NewPublicId(kms.AuditKeyPrefix) - require.NoError(t, err) - k := kms.AllocAuditKeyVersion() - k.PrivateId = id - require.NoError(t, err) - return &k - }(), - }, - wantRowsDeleted: 0, - wantErr: true, - wantIsError: errors.RecordNotFound, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - deletedRows, err := repo.DeleteAuditKeyVersion(context.Background(), tt.args.key.PrivateId, tt.args.opt...) - if tt.wantErr { - require.Error(err) - assert.Equal(0, deletedRows) - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - return - } - require.NoError(err) - assert.Equal(tt.wantRowsDeleted, deletedRows) - foundKey, err := repo.LookupAuditKeyVersion(context.Background(), wrapper, tt.args.key.PrivateId) - assert.Error(err) - assert.Nil(foundKey) - assert.True(errors.IsNotFoundError(err)) - - // make sure there was no oplog written - err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestRepository_LatestAuditKeyVersion(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - dk := kms.TestAuditKey(t, conn, rk.PrivateId) - - tests := []struct { - name string - createCnt int - keyWrapper wrapping.Wrapper - wantVersion uint32 - wantErr bool - wantIsError errors.Code - }{ - { - name: "5", - createCnt: 5, - keyWrapper: rkvWrapper, - wantVersion: 5, - wantErr: false, - }, - { - name: "1", - createCnt: 1, - keyWrapper: rkvWrapper, - wantVersion: 1, - wantErr: false, - }, - { - name: "0", - createCnt: 0, - keyWrapper: rkvWrapper, - wantErr: true, - wantIsError: errors.RecordNotFound, - }, - { - name: "nil-wrapper", - createCnt: 5, - keyWrapper: nil, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocAuditKeyVersion(); return &i }(), "1=1") - testKeys := []*kms.AuditKeyVersion{} - for i := 0; i < tt.createCnt; i++ { - k := kms.TestAuditKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("test audit key")) - testKeys = append(testKeys, k) - } - assert.Equal(tt.createCnt, len(testKeys)) - got, err := repo.LatestAuditKeyVersion(context.Background(), tt.keyWrapper, dk.PrivateId) - if tt.wantErr { - require.Error(err) - assert.Nil(got) - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - return - } - require.NoError(err) - require.NotNil(got) - assert.Equal(tt.wantVersion, got.Version) - }) - } -} - -func TestRepository_ListAuditKeyVersions(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - const testLimit = 10 - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw, kms.WithLimit(testLimit)) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - dk := kms.TestAuditKey(t, conn, rk.PrivateId) - - type args struct { - AuditKeyId string - keyWrapper wrapping.Wrapper - opt []kms.Option - } - tests := []struct { - name string - createCnt int - args args - wantCnt int - wantErr bool - }{ - { - name: "no-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{ - AuditKeyId: dk.PrivateId, - keyWrapper: rkvWrapper, - opt: []kms.Option{kms.WithLimit(-1)}, - }, - wantCnt: repo.DefaultLimit() + 1, - wantErr: false, - }, - { - name: "default-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{ - keyWrapper: rkvWrapper, - AuditKeyId: dk.PrivateId, - }, - wantCnt: repo.DefaultLimit(), - wantErr: false, - }, - { - name: "custom-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{ - keyWrapper: rkvWrapper, - AuditKeyId: dk.PrivateId, - opt: []kms.Option{kms.WithLimit(3)}, - }, - wantCnt: 3, - wantErr: false, - }, - { - name: "bad-org", - createCnt: 1, - args: args{ - keyWrapper: rkvWrapper, - AuditKeyId: "bad-id", - }, - wantCnt: 0, - wantErr: false, - }, - { - name: "nil-wrapper", - createCnt: 1, - args: args{ - keyWrapper: nil, - AuditKeyId: dk.PrivateId, - }, - wantCnt: 0, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocAuditKeyVersion(); return &i }(), "1=1") - keyVersions := []*kms.AuditKeyVersion{} - for i := 0; i < tt.createCnt; i++ { - k := kms.TestAuditKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("audit key")) - keyVersions = append(keyVersions, k) - } - assert.Equal(tt.createCnt, len(keyVersions)) - got, err := repo.ListAuditKeyVersions(context.Background(), tt.args.keyWrapper, tt.args.AuditKeyId, tt.args.opt...) - if tt.wantErr { - require.Error(err) - return - } - require.NoError(err) - assert.Equal(tt.wantCnt, len(got)) - }) - } -} diff --git a/internal/kms/repository_database_key.go b/internal/kms/repository_database_key.go deleted file mode 100644 index 2bc58aaa6..000000000 --- a/internal/kms/repository_database_key.go +++ /dev/null @@ -1,163 +0,0 @@ -package kms - -import ( - "context" - "fmt" - "strings" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" -) - -// CreateDatabaseKey inserts into the repository and returns the new database key and -// database key version. There are no valid options at this time. -func (r *Repository) CreateDatabaseKey(ctx context.Context, rkvWrapper wrapping.Wrapper, key []byte, _ ...Option) (*DatabaseKey, *DatabaseKeyVersion, error) { - const op = "kms.(Repository).CreateDatabaseKey" - var returnedDk, returnedDv interface{} - _, err := r.writer.DoTx( - ctx, - db.StdRetryCnt, - db.ExpBackoff{}, - func(reader db.Reader, w db.Writer) error { - var err error - if returnedDk, returnedDv, err = createDatabaseKeyTx(ctx, reader, w, rkvWrapper, key); err != nil { - return errors.Wrap(ctx, err, op) - } - return nil - }, - ) - if err != nil { - return nil, nil, errors.Wrap(ctx, err, op) - } - return returnedDk.(*DatabaseKey), returnedDv.(*DatabaseKeyVersion), nil -} - -// createDatabaseKeyTx inserts into the db (via db.Writer) and returns the new database key -// and database key version. This function encapsulates all the work required within -// a db.TxHandler and allows this capability to be shared with the iam repo. -func createDatabaseKeyTx(ctx context.Context, r db.Reader, w db.Writer, rkvWrapper wrapping.Wrapper, key []byte) (*DatabaseKey, *DatabaseKeyVersion, error) { - const op = "kms.createDatabaseKeyTx" - if rkvWrapper == nil { - return nil, nil, errors.New(ctx, errors.InvalidParameter, op, "missing key wrapper") - } - if len(key) == 0 { - return nil, nil, errors.New(ctx, errors.InvalidParameter, op, "missing key") - } - rootKeyVersionId, err := rkvWrapper.KeyId(ctx) - if err != nil { - return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to lookup root key id")) - } - switch { - case !strings.HasPrefix(rootKeyVersionId, RootKeyVersionPrefix): - return nil, nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("root key version id %s doesn't start with prefix %s", rootKeyVersionId, RootKeyVersionPrefix)) - case rootKeyVersionId == "": - return nil, nil, errors.New(ctx, errors.InvalidParameter, op, "missing root key version id") - } - rv := AllocRootKeyVersion() - rv.PrivateId = rootKeyVersionId - err = r.LookupById(ctx, &rv) - if err != nil { - return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("unable to lookup root key version %s", rootKeyVersionId))) - } - - dk := AllocDatabaseKey() - dv := AllocDatabaseKeyVersion() - id, err := newDatabaseKeyId() - if err != nil { - return nil, nil, errors.Wrap(ctx, err, op) - } - dk.PrivateId = id - dk.RootKeyId = rv.RootKeyId - - id, err = newDatabaseKeyVersionId() - if err != nil { - return nil, nil, errors.Wrap(ctx, err, op) - } - dv.PrivateId = id - dv.DatabaseKeyId = dk.PrivateId - dv.RootKeyVersionId = rootKeyVersionId - dv.Key = key - if err := dv.Encrypt(ctx, rkvWrapper); err != nil { - return nil, nil, errors.Wrap(ctx, err, op) - } - - // no oplog entries for keys - if err := w.Create(ctx, &dk); err != nil { - return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg("keys create")) - } - // no oplog entries for key versions - if err := w.Create(ctx, &dv); err != nil { - return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg("key versions create")) - } - - return &dk, &dv, nil -} - -// LookupDatabaseKey will look up a key in the repository. If the key is not -// found, it will return nil, nil. -func (r *Repository) LookupDatabaseKey(ctx context.Context, privateId string, _ ...Option) (*DatabaseKey, error) { - const op = "kms.(Repository).LookupDatabaseKey" - if privateId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - k := AllocDatabaseKey() - k.PrivateId = privateId - if err := r.reader.LookupById(ctx, &k); err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - return &k, nil -} - -// DeleteDatabaseKey deletes the key for the provided id from the -// repository returning a count of the number of records deleted. All options -// are ignored. -func (r *Repository) DeleteDatabaseKey(ctx context.Context, privateId string, _ ...Option) (int, error) { - const op = "kms.(Repository).DeleteDatabaseKey" - if privateId == "" { - return db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - k := AllocDatabaseKey() - k.PrivateId = privateId - if err := r.reader.LookupById(ctx, &k); err != nil { - return db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - - var rowsDeleted int - _, err := r.writer.DoTx( - ctx, - db.StdRetryCnt, - db.ExpBackoff{}, - func(_ db.Reader, w db.Writer) (err error) { - dk := k.Clone() - // no oplog entries for root keys - rowsDeleted, err = w.Delete(ctx, dk) - if err != nil { - return errors.Wrap(ctx, err, op) - } - if rowsDeleted > 1 { - return errors.New(ctx, errors.MultipleRecords, op, "more than 1 resource would have been deleted") - } - return nil - }, - ) - if err != nil { - return db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - return rowsDeleted, nil -} - -// ListDatabaseKeys will list the keys. Supports the WithLimit option. -func (r *Repository) ListDatabaseKeys(ctx context.Context, opt ...Option) ([]Dek, error) { - const op = "kms.(Repository).ListDatabaseKeys" - var keys []*DatabaseKey - err := r.list(ctx, &keys, "1=1", nil, opt...) - if err != nil { - return nil, errors.Wrap(ctx, err, op) - } - deks := make([]Dek, 0, len(keys)) - for _, key := range keys { - deks = append(deks, key) - } - return deks, nil -} diff --git a/internal/kms/repository_database_key_test.go b/internal/kms/repository_database_key_test.go deleted file mode 100644 index 8b51c69fd..000000000 --- a/internal/kms/repository_database_key_test.go +++ /dev/null @@ -1,295 +0,0 @@ -package kms_test - -import ( - "context" - "testing" - "time" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/iam" - "github.com/hashicorp/boundary/internal/kms" - "github.com/hashicorp/boundary/internal/oplog" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" - aead "github.com/hashicorp/go-kms-wrapping/v2/aead" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" -) - -func TestRepository_CreateDatabaseKey(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - - type args struct { - scopeId string - key []byte - keyWrapper wrapping.Wrapper - opt []kms.Option - } - tests := []struct { - name string - args args - wantErr bool - wantIsError errors.Code - }{ - { - name: "valid-org", - args: args{ - scopeId: org.PublicId, - key: []byte("test key"), - keyWrapper: rkvWrapper, - }, - wantErr: false, - }, - { - name: "nil-key", - args: args{ - scopeId: org.PublicId, - keyWrapper: rkvWrapper, - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "empty-key", - args: args{ - scopeId: org.PublicId, - keyWrapper: rkvWrapper, - key: []byte(""), - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "nil-wrapper", - args: args{ - scopeId: org.PublicId, - key: []byte("test key"), - keyWrapper: nil, - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "not-rkv-wrapper", - args: args{ - scopeId: org.PublicId, - key: []byte("test key"), - keyWrapper: wrapper, - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "wrapper-missing-id", - args: args{ - scopeId: org.PublicId, - key: []byte("test key"), - keyWrapper: func() wrapping.Wrapper { - w := db.TestWrapper(t) - _, err = w.(*aead.Wrapper).SetConfig(context.Background()) - require.NoError(t, err) - return w - }(), - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - dk, dv, err := repo.CreateDatabaseKey(context.Background(), tt.args.keyWrapper, tt.args.key, tt.args.opt...) - if tt.wantErr { - assert.Error(err) - assert.Nil(dk) - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - return - } - require.NoError(err) - assert.NotNil(dk.CreateTime) - foundKey, err := repo.LookupDatabaseKey(context.Background(), dk.PrivateId) - assert.NoError(err) - assert.True(proto.Equal(foundKey, dk)) - - // make sure there was no oplog written - err = db.TestVerifyOplog(t, rw, dk.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_CREATE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - - assert.NotNil(dv.CreateTime) - foundKeyVersion, err := repo.LookupDatabaseKeyVersion(context.Background(), tt.args.keyWrapper, dv.PrivateId) - assert.NoError(err) - assert.True(proto.Equal(foundKeyVersion, dv)) - - // make sure there was no oplog written - err = db.TestVerifyOplog(t, rw, dv.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_CREATE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestRepository_DeleteDatabaseKey(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - - type args struct { - key *kms.DatabaseKey - opt []kms.Option - } - tests := []struct { - name string - args args - wantRowsDeleted int - wantErr bool - wantIsError errors.Code - }{ - { - name: "valid", - args: args{ - key: kms.TestDatabaseKey(t, conn, rk.PrivateId), - }, - wantRowsDeleted: 1, - wantErr: false, - }, - { - name: "no-private-id", - args: args{ - key: func() *kms.DatabaseKey { - k := kms.AllocDatabaseKey() - return &k - }(), - }, - wantRowsDeleted: 0, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "not-found", - args: args{ - key: func() *kms.DatabaseKey { - id, err := db.NewPublicId(kms.RootKeyPrefix) - require.NoError(t, err) - k := kms.AllocDatabaseKey() - k.PrivateId = id - require.NoError(t, err) - return &k - }(), - }, - wantRowsDeleted: 0, - wantErr: true, - wantIsError: errors.RecordNotFound, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - deletedRows, err := repo.DeleteDatabaseKey(context.Background(), tt.args.key.PrivateId, tt.args.opt...) - if tt.wantErr { - require.Error(err) - assert.Equal(0, deletedRows) - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - // make sure there was no oplog written - err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - return - } - require.NoError(err) - assert.Equal(tt.wantRowsDeleted, deletedRows) - foundKey, err := repo.LookupDatabaseKey(context.Background(), tt.args.key.PrivateId) - assert.Error(err) - assert.Nil(foundKey) - assert.True(errors.IsNotFoundError(err)) - - // make sure there was no oplog written - err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestRepository_ListDatabaseKeys(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - const testLimit = 10 - rw := db.New(conn) - repo, err := kms.NewRepository(rw, rw, kms.WithLimit(testLimit)) - require.NoError(t, err) - wrapper := db.TestWrapper(t) - - type args struct { - opt []kms.Option - } - tests := []struct { - name string - createCnt int - args args - wantCnt int - wantErr bool - }{ - { - name: "no-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{ - opt: []kms.Option{kms.WithLimit(-1)}, - }, - wantCnt: repo.DefaultLimit() + 1, // org and project both have keys, plus global scope - wantErr: false, - }, - { - name: "default-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{}, - wantCnt: repo.DefaultLimit(), - wantErr: false, - }, - { - name: "custom-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{ - opt: []kms.Option{kms.WithLimit(3)}, - }, - wantCnt: 3, - wantErr: false, - }, - } - for _, tt := range tests { - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - for i := 0; i < tt.createCnt; i++ { - org, proj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "scope_id in(?)", "global", org.PublicId, proj.PublicId) - rk := kms.TestRootKey(t, conn, proj.PublicId) - kms.TestDatabaseKey(t, conn, rk.PrivateId) - require.NoError(err) - } - got, err := repo.ListDatabaseKeys(context.Background(), tt.args.opt...) - if tt.wantErr { - require.Error(err) - return - } - require.NoError(err) - assert.Equal(tt.wantCnt, len(got)) - }) - } -} diff --git a/internal/kms/repository_database_key_version.go b/internal/kms/repository_database_key_version.go deleted file mode 100644 index 89bf0d90a..000000000 --- a/internal/kms/repository_database_key_version.go +++ /dev/null @@ -1,176 +0,0 @@ -package kms - -import ( - "context" - "fmt" - "strings" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" -) - -// CreateDatabaseKeyVersion inserts into the repository and returns the new key -// version with its PrivateId. There are no valid options at this time. -func (r *Repository) CreateDatabaseKeyVersion(ctx context.Context, rkvWrapper wrapping.Wrapper, databaseKeyId string, key []byte, _ ...Option) (*DatabaseKeyVersion, error) { - const op = "kms.(Repository).CreateDatabaseKeyVersion" - if rkvWrapper == nil { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing root key version wrapper") - } - rootKeyVersionId, err := rkvWrapper.KeyId(ctx) - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to get key id")) - } - switch { - case !strings.HasPrefix(rootKeyVersionId, RootKeyVersionPrefix): - return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("root key version id %s doesn't start with prefix %s", rootKeyVersionId, RootKeyVersionPrefix)) - case rootKeyVersionId == "": - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing root key version id") - } - if databaseKeyId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing database key id") - } - if len(key) == 0 { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing key") - } - kv := AllocDatabaseKeyVersion() - id, err := newDatabaseKeyVersionId() - if err != nil { - return nil, errors.Wrap(ctx, err, op) - } - kv.PrivateId = id - kv.RootKeyVersionId = rootKeyVersionId - kv.Key = key - kv.DatabaseKeyId = databaseKeyId - if err := kv.Encrypt(ctx, rkvWrapper); err != nil { - return nil, errors.Wrap(ctx, err, op) - } - - var returnedKey interface{} - _, err = r.writer.DoTx( - ctx, - db.StdRetryCnt, - db.ExpBackoff{}, - func(_ db.Reader, w db.Writer) error { - returnedKey = kv.Clone() - // no oplog entries for root key version - if err := w.Create(ctx, returnedKey); err != nil { - return errors.Wrap(ctx, err, op) - } - return nil - }, - ) - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s database key id", kv.DatabaseKeyId))) - } - return returnedKey.(*DatabaseKeyVersion), nil -} - -// LookupDatabaseKeyVersion will look up a key version in the repository. If -// the key version is not found, it will return nil, nil. -func (r *Repository) LookupDatabaseKeyVersion(ctx context.Context, keyWrapper wrapping.Wrapper, privateId string, _ ...Option) (*DatabaseKeyVersion, error) { - const op = "kms.(Repository).LookupDatabaseKeyVersion" - if privateId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - if keyWrapper == nil { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing key wrapper") - } - k := AllocDatabaseKeyVersion() - k.PrivateId = privateId - if err := r.reader.LookupById(ctx, &k); err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - if err := k.Decrypt(ctx, keyWrapper); err != nil { - return nil, errors.Wrap(ctx, err, op) - } - return &k, nil -} - -// DeleteDatabaseKeyVersion deletes the key version for the provided id from the -// repository returning a count of the number of records deleted. All options -// are ignored. -func (r *Repository) DeleteDatabaseKeyVersion(ctx context.Context, privateId string, _ ...Option) (int, error) { - const op = "kms.(Repository).DeleteDatabaseKeyVersion" - if privateId == "" { - return db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - k := AllocDatabaseKeyVersion() - k.PrivateId = privateId - if err := r.reader.LookupById(ctx, &k); err != nil { - return db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - - var rowsDeleted int - _, err := r.writer.DoTx( - ctx, - db.StdRetryCnt, - db.ExpBackoff{}, - func(_ db.Reader, w db.Writer) (err error) { - dk := k.Clone() - // no oplog entries for the key version - rowsDeleted, err = w.Delete(ctx, dk) - if err != nil { - return errors.Wrap(ctx, err, op) - } - if rowsDeleted > 1 { - return errors.New(ctx, errors.MultipleRecords, op, "more than 1 resource would have been deleted") - } - return nil - }, - ) - if err != nil { - return db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - return rowsDeleted, nil -} - -// LatestDatabaseKeyVersion searches for the key version with the highest -// version number. When no results are found, it returns nil with an -// errors.RecordNotFound error. -func (r *Repository) LatestDatabaseKeyVersion(ctx context.Context, rkvWrapper wrapping.Wrapper, databaseKeyId string, _ ...Option) (*DatabaseKeyVersion, error) { - const op = "kms.(Repository).LatestDatabaseKeyVersion" - if databaseKeyId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing database key id") - } - if rkvWrapper == nil { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing root key version wrapper") - } - var foundKeys []*DatabaseKeyVersion - if err := r.reader.SearchWhere(ctx, &foundKeys, "database_key_id = ?", []interface{}{databaseKeyId}, db.WithLimit(1), db.WithOrder("version desc")); err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", databaseKeyId))) - } - if len(foundKeys) == 0 { - return nil, errors.E(ctx, errors.WithCode(errors.RecordNotFound), errors.WithOp(op)) - } - if err := foundKeys[0].Decrypt(ctx, rkvWrapper); err != nil { - return nil, errors.Wrap(ctx, err, op) - } - return foundKeys[0], nil -} - -// ListDatabaseKeyVersions will lists versions of a key. Supports the WithLimit option. -func (r *Repository) ListDatabaseKeyVersions(ctx context.Context, rkvWrapper wrapping.Wrapper, databaseKeyId string, opt ...Option) ([]DekVersion, error) { - const op = "kms.(Repository).ListDatabaseKeyVersions" - if databaseKeyId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing database key id") - } - if rkvWrapper == nil { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing root key version wrapper") - } - var versions []*DatabaseKeyVersion - err := r.list(ctx, &versions, "database_key_id = ?", []interface{}{databaseKeyId}, opt...) - if err != nil { - return nil, errors.Wrap(ctx, err, op) - } - for i, k := range versions { - if err := k.Decrypt(ctx, rkvWrapper); err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("error decrypting key num %d", i))) - } - } - dekVersions := make([]DekVersion, 0, len(versions)) - for _, version := range versions { - dekVersions = append(dekVersions, version) - } - return dekVersions, nil -} diff --git a/internal/kms/repository_database_key_version_test.go b/internal/kms/repository_database_key_version_test.go deleted file mode 100644 index 50066fb37..000000000 --- a/internal/kms/repository_database_key_version_test.go +++ /dev/null @@ -1,367 +0,0 @@ -package kms_test - -import ( - "context" - "testing" - "time" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/iam" - "github.com/hashicorp/boundary/internal/kms" - "github.com/hashicorp/boundary/internal/oplog" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" -) - -func TestRepository_CreateDatabaseKeyVersion(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - dk := kms.TestDatabaseKey(t, conn, rk.PrivateId) - - type args struct { - key []byte - databaseKeyId string - keyWrapper wrapping.Wrapper - opt []kms.Option - } - tests := []struct { - name string - args args - wantErr bool - wantIsError errors.Code - }{ - { - name: "valid", - args: args{ - key: []byte("test key"), - keyWrapper: rkvWrapper, - databaseKeyId: dk.PrivateId, - }, - wantErr: false, - }, - { - name: "invalid-rkv-wrapper", - args: args{ - key: []byte("test key"), - keyWrapper: wrapper, - databaseKeyId: dk.PrivateId, - }, - wantErr: true, - }, - { - name: "empty-key", - args: args{ - key: nil, - keyWrapper: wrapper, - databaseKeyId: dk.PrivateId, - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "nil-wrapper", - args: args{ - key: []byte("test key"), - keyWrapper: nil, - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - k, err := repo.CreateDatabaseKeyVersion(context.Background(), tt.args.keyWrapper, tt.args.databaseKeyId, tt.args.key, tt.args.opt...) - if tt.wantErr { - assert.Error(err) - assert.Nil(k) - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - return - } - require.NoError(err) - assert.NotNil(k.CreateTime) - foundKey, err := repo.LookupDatabaseKeyVersion(context.Background(), tt.args.keyWrapper, k.PrivateId) - assert.NoError(err) - assert.True(proto.Equal(foundKey, k)) - - // make sure there was no oplog written - err = db.TestVerifyOplog(t, rw, k.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_CREATE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestRepository_DeleteDatabaseKeyVersion(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - dk := kms.TestDatabaseKey(t, conn, rk.PrivateId) - - type args struct { - key *kms.DatabaseKeyVersion - opt []kms.Option - } - tests := []struct { - name string - args args - wantRowsDeleted int - wantErr bool - wantIsError errors.Code - }{ - { - name: "valid", - args: args{ - key: kms.TestDatabaseKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("database key")), - }, - wantRowsDeleted: 1, - wantErr: false, - }, - { - name: "no-private-id", - args: args{ - key: func() *kms.DatabaseKeyVersion { - k := kms.AllocDatabaseKeyVersion() - return &k - }(), - }, - wantRowsDeleted: 0, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "not-found", - args: args{ - key: func() *kms.DatabaseKeyVersion { - id, err := db.NewPublicId(kms.DatabaseKeyPrefix) - require.NoError(t, err) - k := kms.AllocDatabaseKeyVersion() - k.PrivateId = id - require.NoError(t, err) - return &k - }(), - }, - wantRowsDeleted: 0, - wantErr: true, - wantIsError: errors.RecordNotFound, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - deletedRows, err := repo.DeleteDatabaseKeyVersion(context.Background(), tt.args.key.PrivateId, tt.args.opt...) - if tt.wantErr { - require.Error(err) - assert.Equal(0, deletedRows) - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - return - } - require.NoError(err) - assert.Equal(tt.wantRowsDeleted, deletedRows) - foundKey, err := repo.LookupDatabaseKeyVersion(context.Background(), wrapper, tt.args.key.PrivateId) - assert.Error(err) - assert.Nil(foundKey) - assert.True(errors.IsNotFoundError(err)) - - // make sure there was no oplog written - err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestRepository_LatestDatabaseKeyVersion(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - dk := kms.TestDatabaseKey(t, conn, rk.PrivateId) - - tests := []struct { - name string - createCnt int - keyWrapper wrapping.Wrapper - wantVersion uint32 - wantErr bool - wantIsError errors.Code - }{ - { - name: "5", - createCnt: 5, - keyWrapper: rkvWrapper, - wantVersion: 5, - wantErr: false, - }, - { - name: "1", - createCnt: 1, - keyWrapper: rkvWrapper, - wantVersion: 1, - wantErr: false, - }, - { - name: "0", - createCnt: 0, - keyWrapper: rkvWrapper, - wantErr: true, - wantIsError: errors.RecordNotFound, - }, - { - name: "nil-wrapper", - createCnt: 5, - keyWrapper: nil, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocDatabaseKeyVersion(); return &i }(), "1=1") - testKeys := []*kms.DatabaseKeyVersion{} - for i := 0; i < tt.createCnt; i++ { - k := kms.TestDatabaseKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("test database key")) - testKeys = append(testKeys, k) - } - assert.Equal(tt.createCnt, len(testKeys)) - got, err := repo.LatestDatabaseKeyVersion(context.Background(), tt.keyWrapper, dk.PrivateId) - if tt.wantErr { - require.Error(err) - assert.Nil(got) - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - return - } - require.NoError(err) - require.NotNil(got) - assert.Equal(tt.wantVersion, got.Version) - }) - } -} - -func TestRepository_ListDatabaseKeyVersions(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - const testLimit = 10 - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw, kms.WithLimit(testLimit)) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - dk := kms.TestDatabaseKey(t, conn, rk.PrivateId) - - type args struct { - databaseKeyId string - keyWrapper wrapping.Wrapper - opt []kms.Option - } - tests := []struct { - name string - createCnt int - args args - wantCnt int - wantErr bool - }{ - { - name: "no-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{ - databaseKeyId: dk.PrivateId, - keyWrapper: rkvWrapper, - opt: []kms.Option{kms.WithLimit(-1)}, - }, - wantCnt: repo.DefaultLimit() + 1, - wantErr: false, - }, - { - name: "default-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{ - keyWrapper: rkvWrapper, - databaseKeyId: dk.PrivateId, - }, - wantCnt: repo.DefaultLimit(), - wantErr: false, - }, - { - name: "custom-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{ - keyWrapper: rkvWrapper, - databaseKeyId: dk.PrivateId, - opt: []kms.Option{kms.WithLimit(3)}, - }, - wantCnt: 3, - wantErr: false, - }, - { - name: "bad-org", - createCnt: 1, - args: args{ - keyWrapper: rkvWrapper, - databaseKeyId: "bad-id", - }, - wantCnt: 0, - wantErr: false, - }, - { - name: "nil-wrapper", - createCnt: 1, - args: args{ - keyWrapper: nil, - databaseKeyId: dk.PrivateId, - }, - wantCnt: 0, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocDatabaseKeyVersion(); return &i }(), "1=1") - keyVersions := []*kms.DatabaseKeyVersion{} - for i := 0; i < tt.createCnt; i++ { - k := kms.TestDatabaseKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("database key")) - keyVersions = append(keyVersions, k) - } - assert.Equal(tt.createCnt, len(keyVersions)) - got, err := repo.ListDatabaseKeyVersions(context.Background(), tt.args.keyWrapper, tt.args.databaseKeyId, tt.args.opt...) - if tt.wantErr { - require.Error(err) - return - } - require.NoError(err) - assert.Equal(tt.wantCnt, len(got)) - }) - } -} diff --git a/internal/kms/repository_oidc_key.go b/internal/kms/repository_oidc_key.go deleted file mode 100644 index d3fe2d03e..000000000 --- a/internal/kms/repository_oidc_key.go +++ /dev/null @@ -1,162 +0,0 @@ -package kms - -import ( - "context" - "fmt" - "strings" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" -) - -// CreateOidcKey inserts into the repository and returns the new oidc key and -// oidc key version. There are no valid options at this time. -func (r *Repository) CreateOidcKey(ctx context.Context, rkvWrapper wrapping.Wrapper, key []byte, _ ...Option) (*OidcKey, *OidcKeyVersion, error) { - const op = "kms.(Repository).CreateOidcKey" - var returnedDk, returnedDv interface{} - _, err := r.writer.DoTx( - ctx, - db.StdRetryCnt, - db.ExpBackoff{}, - func(reader db.Reader, w db.Writer) error { - var err error - if returnedDk, returnedDv, err = createOidcKeyTx(ctx, reader, w, rkvWrapper, key); err != nil { - return errors.Wrap(ctx, err, op) - } - return nil - }, - ) - if err != nil { - return nil, nil, errors.Wrap(ctx, err, op) - } - return returnedDk.(*OidcKey), returnedDv.(*OidcKeyVersion), nil -} - -// createOidcKeyTx inserts into the db (via db.Writer) and returns the new oidc key -// and oidc key version. This function encapsulates all the work required within -// a db.TxHandler and allows this capability to be shared with the iam repo. -func createOidcKeyTx(ctx context.Context, r db.Reader, w db.Writer, rkvWrapper wrapping.Wrapper, key []byte) (*OidcKey, *OidcKeyVersion, error) { - const op = "kms.createOidcKeyTx" - if rkvWrapper == nil { - return nil, nil, errors.New(ctx, errors.InvalidParameter, op, "missing key wrapper") - } - if len(key) == 0 { - return nil, nil, errors.New(ctx, errors.InvalidParameter, op, "missing key") - } - rootKeyVersionId, err := rkvWrapper.KeyId(ctx) - if err != nil { - return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to lookup root key id")) - } - switch { - case !strings.HasPrefix(rootKeyVersionId, RootKeyVersionPrefix): - return nil, nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("root key version id %s doesn't start with prefix %s", rootKeyVersionId, RootKeyVersionPrefix)) - case rootKeyVersionId == "": - return nil, nil, errors.New(ctx, errors.InvalidParameter, op, "missing root key version id") - } - rv := AllocRootKeyVersion() - rv.PrivateId = rootKeyVersionId - if err := r.LookupById(ctx, &rv); err != nil { - return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("unable to lookup root key version %s", rootKeyVersionId))) - } - - dk := AllocOidcKey() - dv := AllocOidcKeyVersion() - id, err := newOidcKeyId() - if err != nil { - return nil, nil, errors.Wrap(ctx, err, op) - } - dk.PrivateId = id - dk.RootKeyId = rv.RootKeyId - - id, err = newOidcKeyVersionId() - if err != nil { - return nil, nil, errors.Wrap(ctx, err, op) - } - dv.PrivateId = id - dv.OidcKeyId = dk.PrivateId - dv.RootKeyVersionId = rootKeyVersionId - dv.Key = key - if err := dv.Encrypt(ctx, rkvWrapper); err != nil { - return nil, nil, errors.Wrap(ctx, err, op) - } - - // no oplog entries for keys - if err := w.Create(ctx, &dk); err != nil { - return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg("keys create")) - } - // no oplog entries for key versions - if err := w.Create(ctx, &dv); err != nil { - return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg("key versions create")) - } - - return &dk, &dv, nil -} - -// LookupOidcKey will look up a key in the repository. If the key is not -// found, it will return nil, nil. -func (r *Repository) LookupOidcKey(ctx context.Context, privateId string, _ ...Option) (*OidcKey, error) { - const op = "kms.(Repository).LookupOidcKey" - if privateId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - k := AllocOidcKey() - k.PrivateId = privateId - if err := r.reader.LookupById(ctx, &k); err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - return &k, nil -} - -// DeleteOidcKey deletes the key for the provided id from the -// repository returning a count of the number of records deleted. All options -// are ignored. -func (r *Repository) DeleteOidcKey(ctx context.Context, privateId string, _ ...Option) (int, error) { - const op = "kms.(Repository).DeleteOidcKey" - if privateId == "" { - return db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - k := AllocOidcKey() - k.PrivateId = privateId - if err := r.reader.LookupById(ctx, &k); err != nil { - return db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - - var rowsDeleted int - _, err := r.writer.DoTx( - ctx, - db.StdRetryCnt, - db.ExpBackoff{}, - func(_ db.Reader, w db.Writer) (err error) { - dk := k.Clone() - // no oplog entries for root keys - rowsDeleted, err = w.Delete(ctx, dk) - if err != nil { - return errors.Wrap(ctx, err, op) - } - if rowsDeleted > 1 { - return errors.New(ctx, errors.MultipleRecords, op, "more than 1 resource would have been deleted") - } - return nil - }, - ) - if err != nil { - return db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - return rowsDeleted, nil -} - -// ListOidcKeys will list the keys. Supports the WithLimit option. -func (r *Repository) ListOidcKeys(ctx context.Context, opt ...Option) ([]Dek, error) { - const op = "kms.(Repository).ListOidcKeys" - var keys []*OidcKey - err := r.list(ctx, &keys, "1=1", nil, opt...) - if err != nil { - return nil, errors.Wrap(ctx, err, op) - } - deks := make([]Dek, 0, len(keys)) - for _, key := range keys { - deks = append(deks, key) - } - return deks, nil -} diff --git a/internal/kms/repository_oidc_key_test.go b/internal/kms/repository_oidc_key_test.go deleted file mode 100644 index 56c402fdb..000000000 --- a/internal/kms/repository_oidc_key_test.go +++ /dev/null @@ -1,295 +0,0 @@ -package kms_test - -import ( - "context" - "testing" - "time" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/iam" - "github.com/hashicorp/boundary/internal/kms" - "github.com/hashicorp/boundary/internal/oplog" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" - aead "github.com/hashicorp/go-kms-wrapping/v2/aead" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" -) - -func TestRepository_CreateOidcKey(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - - type args struct { - scopeId string - key []byte - keyWrapper wrapping.Wrapper - opt []kms.Option - } - tests := []struct { - name string - args args - wantErr bool - wantIsError errors.Code - }{ - { - name: "valid-org", - args: args{ - scopeId: org.PublicId, - key: []byte("test key"), - keyWrapper: rkvWrapper, - }, - wantErr: false, - }, - { - name: "nil-key", - args: args{ - scopeId: org.PublicId, - keyWrapper: rkvWrapper, - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "empty-key", - args: args{ - scopeId: org.PublicId, - keyWrapper: rkvWrapper, - key: []byte(""), - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "nil-wrapper", - args: args{ - scopeId: org.PublicId, - key: []byte("test key"), - keyWrapper: nil, - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "not-rkv-wrapper", - args: args{ - scopeId: org.PublicId, - key: []byte("test key"), - keyWrapper: wrapper, - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "wrapper-missing-id", - args: args{ - scopeId: org.PublicId, - key: []byte("test key"), - keyWrapper: func() wrapping.Wrapper { - w := db.TestWrapper(t) - _, err = w.(*aead.Wrapper).SetConfig(context.Background()) - require.NoError(t, err) - return w - }(), - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - dk, dv, err := repo.CreateOidcKey(context.Background(), tt.args.keyWrapper, tt.args.key, tt.args.opt...) - if tt.wantErr { - assert.Error(err) - assert.Nil(dk) - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - return - } - require.NoError(err) - assert.NotNil(dk.CreateTime) - foundKey, err := repo.LookupOidcKey(context.Background(), dk.PrivateId) - assert.NoError(err) - assert.True(proto.Equal(foundKey, dk)) - - // make sure there was no oplog written - err = db.TestVerifyOplog(t, rw, dk.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_CREATE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - - assert.NotNil(dv.CreateTime) - foundKeyVersion, err := repo.LookupOidcKeyVersion(context.Background(), tt.args.keyWrapper, dv.PrivateId) - assert.NoError(err) - assert.True(proto.Equal(foundKeyVersion, dv)) - - // make sure there was no oplog written - err = db.TestVerifyOplog(t, rw, dv.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_CREATE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestRepository_DeleteOidcKey(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - - type args struct { - key *kms.OidcKey - opt []kms.Option - } - tests := []struct { - name string - args args - wantRowsDeleted int - wantErr bool - wantIsError errors.Code - }{ - { - name: "valid", - args: args{ - key: kms.TestOidcKey(t, conn, rk.PrivateId), - }, - wantRowsDeleted: 1, - wantErr: false, - }, - { - name: "no-private-id", - args: args{ - key: func() *kms.OidcKey { - k := kms.AllocOidcKey() - return &k - }(), - }, - wantRowsDeleted: 0, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "not-found", - args: args{ - key: func() *kms.OidcKey { - id, err := db.NewPublicId(kms.RootKeyPrefix) - require.NoError(t, err) - k := kms.AllocOidcKey() - k.PrivateId = id - require.NoError(t, err) - return &k - }(), - }, - wantRowsDeleted: 0, - wantErr: true, - wantIsError: errors.RecordNotFound, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - deletedRows, err := repo.DeleteOidcKey(context.Background(), tt.args.key.PrivateId, tt.args.opt...) - if tt.wantErr { - require.Error(err) - assert.Equal(0, deletedRows) - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - // make sure there was no oplog written - err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - return - } - require.NoError(err) - assert.Equal(tt.wantRowsDeleted, deletedRows) - foundKey, err := repo.LookupOidcKey(context.Background(), tt.args.key.PrivateId) - assert.Error(err) - assert.Nil(foundKey) - assert.True(errors.IsNotFoundError(err)) - - // make sure there was no oplog written - err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestRepository_ListOidcKeys(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - const testLimit = 10 - rw := db.New(conn) - repo, err := kms.NewRepository(rw, rw, kms.WithLimit(testLimit)) - require.NoError(t, err) - wrapper := db.TestWrapper(t) - - type args struct { - opt []kms.Option - } - tests := []struct { - name string - createCnt int - args args - wantCnt int - wantErr bool - }{ - { - name: "no-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{ - opt: []kms.Option{kms.WithLimit(-1)}, - }, - wantCnt: repo.DefaultLimit() + 1, // org and project both have keys, plus global scope - wantErr: false, - }, - { - name: "default-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{}, - wantCnt: repo.DefaultLimit(), - wantErr: false, - }, - { - name: "custom-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{ - opt: []kms.Option{kms.WithLimit(3)}, - }, - wantCnt: 3, - wantErr: false, - }, - } - for _, tt := range tests { - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - for i := 0; i < tt.createCnt; i++ { - org, proj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "scope_id in(?)", "global", org.PublicId, proj.PublicId) - rk := kms.TestRootKey(t, conn, proj.PublicId) - kms.TestOidcKey(t, conn, rk.PrivateId) - require.NoError(err) - } - got, err := repo.ListOidcKeys(context.Background(), tt.args.opt...) - if tt.wantErr { - require.Error(err) - return - } - require.NoError(err) - assert.Equal(tt.wantCnt, len(got)) - }) - } -} diff --git a/internal/kms/repository_oidc_key_version.go b/internal/kms/repository_oidc_key_version.go deleted file mode 100644 index 6237952d0..000000000 --- a/internal/kms/repository_oidc_key_version.go +++ /dev/null @@ -1,176 +0,0 @@ -package kms - -import ( - "context" - "fmt" - "strings" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" -) - -// CreateOidcKeyVersion inserts into the repository and returns the new key -// version with its PrivateId. There are no valid options at this time. -func (r *Repository) CreateOidcKeyVersion(ctx context.Context, rkvWrapper wrapping.Wrapper, oidcKeyId string, key []byte, _ ...Option) (*OidcKeyVersion, error) { - const op = "kms.(Repository).CreateOidcKeyVersion" - if rkvWrapper == nil { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing root key version wrapper") - } - rootKeyVersionId, err := rkvWrapper.KeyId(ctx) - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to fetch key id")) - } - switch { - case !strings.HasPrefix(rootKeyVersionId, RootKeyVersionPrefix): - return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("root key version id %s doesn't start with prefix %s", rootKeyVersionId, RootKeyVersionPrefix)) - case rootKeyVersionId == "": - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing root key version id") - } - if oidcKeyId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing oidc key id") - } - if len(key) == 0 { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing key") - } - kv := AllocOidcKeyVersion() - id, err := newOidcKeyVersionId() - if err != nil { - return nil, errors.Wrap(ctx, err, op) - } - kv.PrivateId = id - kv.RootKeyVersionId = rootKeyVersionId - kv.Key = key - kv.OidcKeyId = oidcKeyId - if err := kv.Encrypt(ctx, rkvWrapper); err != nil { - return nil, errors.Wrap(ctx, err, op) - } - - var returnedKey interface{} - _, err = r.writer.DoTx( - ctx, - db.StdRetryCnt, - db.ExpBackoff{}, - func(_ db.Reader, w db.Writer) error { - returnedKey = kv.Clone() - // no oplog entries for root key version - if err := w.Create(ctx, returnedKey); err != nil { - return errors.Wrap(ctx, err, op) - } - return nil - }, - ) - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s oidc key id", kv.OidcKeyId))) - } - return returnedKey.(*OidcKeyVersion), nil -} - -// LookupOidcKeyVersion will look up a key version in the repository. If -// the key version is not found, it will return nil, nil. -func (r *Repository) LookupOidcKeyVersion(ctx context.Context, keyWrapper wrapping.Wrapper, privateId string, _ ...Option) (*OidcKeyVersion, error) { - const op = "kms.(Repository).LookupOidcKeyVersion" - if privateId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - if keyWrapper == nil { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing key wrapper") - } - k := AllocOidcKeyVersion() - k.PrivateId = privateId - if err := r.reader.LookupById(ctx, &k); err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - if err := k.Decrypt(ctx, keyWrapper); err != nil { - return nil, errors.Wrap(ctx, err, op) - } - return &k, nil -} - -// DeleteOidcKeyVersion deletes the key version for the provided id from the -// repository returning a count of the number of records deleted. All options -// are ignored. -func (r *Repository) DeleteOidcKeyVersion(ctx context.Context, privateId string, _ ...Option) (int, error) { - const op = "kms.(Repository).DeleteOidcKeyVersion" - if privateId == "" { - return db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - k := AllocOidcKeyVersion() - k.PrivateId = privateId - if err := r.reader.LookupById(ctx, &k); err != nil { - return db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - - var rowsDeleted int - _, err := r.writer.DoTx( - ctx, - db.StdRetryCnt, - db.ExpBackoff{}, - func(_ db.Reader, w db.Writer) (err error) { - dk := k.Clone() - // no oplog entries for the key version - rowsDeleted, err = w.Delete(ctx, dk) - if err != nil { - return errors.Wrap(ctx, err, op) - } - if rowsDeleted > 1 { - return errors.New(ctx, errors.MultipleRecords, op, "more than 1 resource would have been deleted") - } - return nil - }, - ) - if err != nil { - return db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - return rowsDeleted, nil -} - -// LatestOidcKeyVersion searches for the key version with the highest -// version number. When no results are found, it returns nil with an -// errors.RecordNotFound error. -func (r *Repository) LatestOidcKeyVersion(ctx context.Context, rkvWrapper wrapping.Wrapper, OidcKeyId string, _ ...Option) (*OidcKeyVersion, error) { - const op = "kms.(Repository).LatestOidcKeyVersion" - if OidcKeyId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing oidc key id") - } - if rkvWrapper == nil { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing root key version wrapper") - } - var foundKeys []*OidcKeyVersion - if err := r.reader.SearchWhere(ctx, &foundKeys, "oidc_key_id = ?", []interface{}{OidcKeyId}, db.WithLimit(1), db.WithOrder("version desc")); err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", OidcKeyId))) - } - if len(foundKeys) == 0 { - return nil, errors.E(ctx, errors.WithCode(errors.RecordNotFound), errors.WithOp(op)) - } - if err := foundKeys[0].Decrypt(ctx, rkvWrapper); err != nil { - return nil, errors.Wrap(ctx, err, op) - } - return foundKeys[0], nil -} - -// ListOidcKeyVersions will lists versions of a key. Supports the WithLimit option. -func (r *Repository) ListOidcKeyVersions(ctx context.Context, rkvWrapper wrapping.Wrapper, OidcKeyId string, opt ...Option) ([]DekVersion, error) { - const op = "kms.(Repository).ListOidcKeyVersions" - if OidcKeyId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing oidc key id") - } - if rkvWrapper == nil { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing root key version wrapper") - } - var versions []*OidcKeyVersion - err := r.list(ctx, &versions, "oidc_key_id = ?", []interface{}{OidcKeyId}, opt...) - if err != nil { - return nil, errors.Wrap(ctx, err, op) - } - for i, k := range versions { - if err := k.Decrypt(ctx, rkvWrapper); err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("error decrypting key num %d", i))) - } - } - dekVersions := make([]DekVersion, 0, len(versions)) - for _, version := range versions { - dekVersions = append(dekVersions, version) - } - return dekVersions, nil -} diff --git a/internal/kms/repository_oidc_key_version_test.go b/internal/kms/repository_oidc_key_version_test.go deleted file mode 100644 index 47a51ccfc..000000000 --- a/internal/kms/repository_oidc_key_version_test.go +++ /dev/null @@ -1,367 +0,0 @@ -package kms_test - -import ( - "context" - "testing" - "time" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/iam" - "github.com/hashicorp/boundary/internal/kms" - "github.com/hashicorp/boundary/internal/oplog" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" -) - -func TestRepository_CreateOidcKeyVersion(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - dk := kms.TestOidcKey(t, conn, rk.PrivateId) - - type args struct { - key []byte - OidcKeyId string - keyWrapper wrapping.Wrapper - opt []kms.Option - } - tests := []struct { - name string - args args - wantErr bool - wantIsError errors.Code - }{ - { - name: "valid", - args: args{ - key: []byte("test key"), - keyWrapper: rkvWrapper, - OidcKeyId: dk.PrivateId, - }, - wantErr: false, - }, - { - name: "invalid-rkv-wrapper", - args: args{ - key: []byte("test key"), - keyWrapper: wrapper, - OidcKeyId: dk.PrivateId, - }, - wantErr: true, - }, - { - name: "empty-key", - args: args{ - key: nil, - keyWrapper: wrapper, - OidcKeyId: dk.PrivateId, - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "nil-wrapper", - args: args{ - key: []byte("test key"), - keyWrapper: nil, - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - k, err := repo.CreateOidcKeyVersion(context.Background(), tt.args.keyWrapper, tt.args.OidcKeyId, tt.args.key, tt.args.opt...) - if tt.wantErr { - assert.Error(err) - assert.Nil(k) - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - return - } - require.NoError(err) - assert.NotNil(k.CreateTime) - foundKey, err := repo.LookupOidcKeyVersion(context.Background(), tt.args.keyWrapper, k.PrivateId) - assert.NoError(err) - assert.True(proto.Equal(foundKey, k)) - - // make sure there was no oplog written - err = db.TestVerifyOplog(t, rw, k.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_CREATE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestRepository_DeleteOidcKeyVersion(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - dk := kms.TestOidcKey(t, conn, rk.PrivateId) - - type args struct { - key *kms.OidcKeyVersion - opt []kms.Option - } - tests := []struct { - name string - args args - wantRowsDeleted int - wantErr bool - wantIsError errors.Code - }{ - { - name: "valid", - args: args{ - key: kms.TestOidcKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("oidc key")), - }, - wantRowsDeleted: 1, - wantErr: false, - }, - { - name: "no-private-id", - args: args{ - key: func() *kms.OidcKeyVersion { - k := kms.AllocOidcKeyVersion() - return &k - }(), - }, - wantRowsDeleted: 0, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "not-found", - args: args{ - key: func() *kms.OidcKeyVersion { - id, err := db.NewPublicId(kms.OidcKeyPrefix) - require.NoError(t, err) - k := kms.AllocOidcKeyVersion() - k.PrivateId = id - require.NoError(t, err) - return &k - }(), - }, - wantRowsDeleted: 0, - wantErr: true, - wantIsError: errors.RecordNotFound, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - deletedRows, err := repo.DeleteOidcKeyVersion(context.Background(), tt.args.key.PrivateId, tt.args.opt...) - if tt.wantErr { - require.Error(err) - assert.Equal(0, deletedRows) - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - return - } - require.NoError(err) - assert.Equal(tt.wantRowsDeleted, deletedRows) - foundKey, err := repo.LookupOidcKeyVersion(context.Background(), wrapper, tt.args.key.PrivateId) - assert.Error(err) - assert.Nil(foundKey) - assert.True(errors.IsNotFoundError(err)) - - // make sure there was no oplog written - err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestRepository_LatestOidcKeyVersion(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - dk := kms.TestOidcKey(t, conn, rk.PrivateId) - - tests := []struct { - name string - createCnt int - keyWrapper wrapping.Wrapper - wantVersion uint32 - wantErr bool - wantIsError errors.Code - }{ - { - name: "5", - createCnt: 5, - keyWrapper: rkvWrapper, - wantVersion: 5, - wantErr: false, - }, - { - name: "1", - createCnt: 1, - keyWrapper: rkvWrapper, - wantVersion: 1, - wantErr: false, - }, - { - name: "0", - createCnt: 0, - keyWrapper: rkvWrapper, - wantErr: true, - wantIsError: errors.RecordNotFound, - }, - { - name: "nil-wrapper", - createCnt: 5, - keyWrapper: nil, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocOidcKeyVersion(); return &i }(), "1=1") - testKeys := []*kms.OidcKeyVersion{} - for i := 0; i < tt.createCnt; i++ { - k := kms.TestOidcKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("test oidc key")) - testKeys = append(testKeys, k) - } - assert.Equal(tt.createCnt, len(testKeys)) - got, err := repo.LatestOidcKeyVersion(context.Background(), tt.keyWrapper, dk.PrivateId) - if tt.wantErr { - require.Error(err) - assert.Nil(got) - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - return - } - require.NoError(err) - require.NotNil(got) - assert.Equal(tt.wantVersion, got.Version) - }) - } -} - -func TestRepository_ListOidcKeyVersions(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - const testLimit = 10 - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw, kms.WithLimit(testLimit)) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - dk := kms.TestOidcKey(t, conn, rk.PrivateId) - - type args struct { - OidcKeyId string - keyWrapper wrapping.Wrapper - opt []kms.Option - } - tests := []struct { - name string - createCnt int - args args - wantCnt int - wantErr bool - }{ - { - name: "no-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{ - OidcKeyId: dk.PrivateId, - keyWrapper: rkvWrapper, - opt: []kms.Option{kms.WithLimit(-1)}, - }, - wantCnt: repo.DefaultLimit() + 1, - wantErr: false, - }, - { - name: "default-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{ - keyWrapper: rkvWrapper, - OidcKeyId: dk.PrivateId, - }, - wantCnt: repo.DefaultLimit(), - wantErr: false, - }, - { - name: "custom-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{ - keyWrapper: rkvWrapper, - OidcKeyId: dk.PrivateId, - opt: []kms.Option{kms.WithLimit(3)}, - }, - wantCnt: 3, - wantErr: false, - }, - { - name: "bad-org", - createCnt: 1, - args: args{ - keyWrapper: rkvWrapper, - OidcKeyId: "bad-id", - }, - wantCnt: 0, - wantErr: false, - }, - { - name: "nil-wrapper", - createCnt: 1, - args: args{ - keyWrapper: nil, - OidcKeyId: dk.PrivateId, - }, - wantCnt: 0, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocOidcKeyVersion(); return &i }(), "1=1") - keyVersions := []*kms.OidcKeyVersion{} - for i := 0; i < tt.createCnt; i++ { - k := kms.TestOidcKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("oidc key")) - keyVersions = append(keyVersions, k) - } - assert.Equal(tt.createCnt, len(keyVersions)) - got, err := repo.ListOidcKeyVersions(context.Background(), tt.args.keyWrapper, tt.args.OidcKeyId, tt.args.opt...) - if tt.wantErr { - require.Error(err) - return - } - require.NoError(err) - assert.Equal(tt.wantCnt, len(got)) - }) - } -} diff --git a/internal/kms/repository_oplog_key.go b/internal/kms/repository_oplog_key.go deleted file mode 100644 index 0b0fc63a5..000000000 --- a/internal/kms/repository_oplog_key.go +++ /dev/null @@ -1,162 +0,0 @@ -package kms - -import ( - "context" - "fmt" - "strings" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" -) - -// CreateOplogKey inserts into the repository and returns the new key and the -// key version. There are no valid options at this time. -func (r *Repository) CreateOplogKey(ctx context.Context, rkvWrapper wrapping.Wrapper, key []byte, _ ...Option) (*OplogKey, *OplogKeyVersion, error) { - const op = "kms.(Repository).CreateOplogKey" - var returnedDk, returnedDv interface{} - _, err := r.writer.DoTx( - ctx, - db.StdRetryCnt, - db.ExpBackoff{}, - func(reader db.Reader, w db.Writer) error { - var err error - if returnedDk, returnedDv, err = createOplogKeyTx(ctx, reader, w, rkvWrapper, key); err != nil { - return errors.Wrap(ctx, err, op) - } - return nil - }, - ) - if err != nil { - return nil, nil, errors.Wrap(ctx, err, op) - } - return returnedDk.(*OplogKey), returnedDv.(*OplogKeyVersion), nil -} - -// createOplogKeyTx inserts into the db (via db.Writer) and returns the new key -// and the key version. This function encapsulates all the work required within -// a db.TxHandler and allows this capability to be shared with the iam repo. -func createOplogKeyTx(ctx context.Context, r db.Reader, w db.Writer, rkvWrapper wrapping.Wrapper, key []byte) (*OplogKey, *OplogKeyVersion, error) { - const op = "kms.createOplogKeyTx" - if rkvWrapper == nil { - return nil, nil, errors.New(ctx, errors.InvalidParameter, op, "missing key wrapper") - } - if len(key) == 0 { - return nil, nil, errors.New(ctx, errors.InvalidParameter, op, "missing key") - } - rootKeyVersionId, err := rkvWrapper.KeyId(ctx) - if err != nil { - return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to lookup root key id")) - } - switch { - case !strings.HasPrefix(rootKeyVersionId, RootKeyVersionPrefix): - return nil, nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("root key version id %s doesn't start with prefix %s", rootKeyVersionId, RootKeyVersionPrefix)) - case rootKeyVersionId == "": - return nil, nil, errors.New(ctx, errors.InvalidParameter, op, "missing root key version id") - } - rv := AllocRootKeyVersion() - rv.PrivateId = rootKeyVersionId - if err := r.LookupById(ctx, &rv); err != nil { - return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("unable to lookup root key version %s", rootKeyVersionId))) - } - - opk := AllocOplogKey() - opv := AllocOplogKeyVersion() - id, err := newOplogKeyId() - if err != nil { - return nil, nil, errors.Wrap(ctx, err, op) - } - opk.PrivateId = id - opk.RootKeyId = rv.RootKeyId - - id, err = newOplogKeyVersionId() - if err != nil { - return nil, nil, errors.Wrap(ctx, err, op) - } - opv.PrivateId = id - opv.OplogKeyId = opk.PrivateId - opv.RootKeyVersionId = rootKeyVersionId - opv.Key = key - if err := opv.Encrypt(ctx, rkvWrapper); err != nil { - return nil, nil, errors.Wrap(ctx, err, op) - } - - // no oplog entries for keys - if err := w.Create(ctx, &opk); err != nil { - return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg("key create")) - } - // no oplog entries for key versions - if err := w.Create(ctx, &opv); err != nil { - return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg("key versions create")) - } - - return &opk, &opv, nil -} - -// LookupOplogKey will look up a key in the repository. If the key is not -// found, it will return nil, nil. -func (r *Repository) LookupOplogKey(ctx context.Context, privateId string, _ ...Option) (*OplogKey, error) { - const op = "kms.(Repository).LookupOplogKey" - if privateId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - k := AllocOplogKey() - k.PrivateId = privateId - if err := r.reader.LookupById(ctx, &k); err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - return &k, nil -} - -// DeleteOplogKey deletes the key for the provided id from the -// repository returning a count of the number of records deleted. All options -// are ignored. -func (r *Repository) DeleteOplogKey(ctx context.Context, privateId string, _ ...Option) (int, error) { - const op = "kms.(Repository).DeleteOplogKey" - if privateId == "" { - return db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - k := AllocOplogKey() - k.PrivateId = privateId - if err := r.reader.LookupById(ctx, &k); err != nil { - return db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - - var rowsDeleted int - _, err := r.writer.DoTx( - ctx, - db.StdRetryCnt, - db.ExpBackoff{}, - func(_ db.Reader, w db.Writer) (err error) { - dk := k.Clone() - // no oplog entries for root keys - rowsDeleted, err = w.Delete(ctx, dk) - if err != nil { - return errors.Wrap(ctx, err, op) - } - if rowsDeleted > 1 { - return errors.New(ctx, errors.MultipleRecords, op, "more than 1 resource would have been deleted") - } - return nil - }, - ) - if err != nil { - return db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - return rowsDeleted, nil -} - -// ListOplogKeys will list the keys. Supports the WithLimit option. -func (r *Repository) ListOplogKeys(ctx context.Context, opt ...Option) ([]Dek, error) { - const op = "kms.(Repository).ListOplogKeys" - var keys []*OplogKey - err := r.list(ctx, &keys, "1=1", nil, opt...) - if err != nil { - return nil, errors.Wrap(ctx, err, op) - } - deks := make([]Dek, 0, len(keys)) - for _, key := range keys { - deks = append(deks, key) - } - return deks, nil -} diff --git a/internal/kms/repository_oplog_key_test.go b/internal/kms/repository_oplog_key_test.go deleted file mode 100644 index f897f1f4a..000000000 --- a/internal/kms/repository_oplog_key_test.go +++ /dev/null @@ -1,295 +0,0 @@ -package kms_test - -import ( - "context" - "testing" - "time" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/iam" - "github.com/hashicorp/boundary/internal/kms" - "github.com/hashicorp/boundary/internal/oplog" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" - aead "github.com/hashicorp/go-kms-wrapping/v2/aead" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" -) - -func TestRepository_CreateOplogKey(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - - type args struct { - scopeId string - key []byte - keyWrapper wrapping.Wrapper - opt []kms.Option - } - tests := []struct { - name string - args args - wantErr bool - wantIsError errors.Code - }{ - { - name: "valid-org", - args: args{ - scopeId: org.PublicId, - key: []byte("test key"), - keyWrapper: rkvWrapper, - }, - wantErr: false, - }, - { - name: "nil-key", - args: args{ - scopeId: org.PublicId, - keyWrapper: rkvWrapper, - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "empty-key", - args: args{ - scopeId: org.PublicId, - keyWrapper: rkvWrapper, - key: []byte(""), - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "nil-wrapper", - args: args{ - scopeId: org.PublicId, - key: []byte("test key"), - keyWrapper: nil, - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "not-rkv-wrapper", - args: args{ - scopeId: org.PublicId, - key: []byte("test key"), - keyWrapper: wrapper, - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "wrapper-missing-id", - args: args{ - scopeId: org.PublicId, - key: []byte("test key"), - keyWrapper: func() wrapping.Wrapper { - w := db.TestWrapper(t) - _, err = w.(*aead.Wrapper).SetConfig(context.Background()) - require.NoError(t, err) - return w - }(), - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - opk, opv, err := repo.CreateOplogKey(context.Background(), tt.args.keyWrapper, tt.args.key, tt.args.opt...) - if tt.wantErr { - assert.Error(err) - assert.Nil(opk) - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - return - } - require.NoError(err) - assert.NotNil(opk.CreateTime) - foundKey, err := repo.LookupOplogKey(context.Background(), opk.PrivateId) - assert.NoError(err) - assert.True(proto.Equal(foundKey, opk)) - - // make sure there was no oplog written - err = db.TestVerifyOplog(t, rw, opk.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_CREATE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - - assert.NotNil(opv.CreateTime) - foundKeyVersion, err := repo.LookupOplogKeyVersion(context.Background(), tt.args.keyWrapper, opv.PrivateId) - assert.NoError(err) - assert.True(proto.Equal(foundKeyVersion, opv)) - - // make sure there was no oplog written - err = db.TestVerifyOplog(t, rw, opv.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_CREATE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestRepository_DeleteOplogKey(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - - type args struct { - key *kms.OplogKey - opt []kms.Option - } - tests := []struct { - name string - args args - wantRowsDeleted int - wantErr bool - wantIsError errors.Code - }{ - { - name: "valid", - args: args{ - key: kms.TestOplogKey(t, conn, rk.PrivateId), - }, - wantRowsDeleted: 1, - wantErr: false, - }, - { - name: "no-private-id", - args: args{ - key: func() *kms.OplogKey { - k := kms.AllocOplogKey() - return &k - }(), - }, - wantRowsDeleted: 0, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "not-found", - args: args{ - key: func() *kms.OplogKey { - id, err := db.NewPublicId(kms.RootKeyPrefix) - require.NoError(t, err) - k := kms.AllocOplogKey() - k.PrivateId = id - require.NoError(t, err) - return &k - }(), - }, - wantRowsDeleted: 0, - wantErr: true, - wantIsError: errors.RecordNotFound, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - deletedRows, err := repo.DeleteOplogKey(context.Background(), tt.args.key.PrivateId, tt.args.opt...) - if tt.wantErr { - require.Error(err) - assert.Equal(0, deletedRows) - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - // make sure there was no oplog written - err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - return - } - require.NoError(err) - assert.Equal(tt.wantRowsDeleted, deletedRows) - foundKey, err := repo.LookupOplogKey(context.Background(), tt.args.key.PrivateId) - assert.Error(err) - assert.Nil(foundKey) - assert.True(errors.IsNotFoundError(err)) - - // make sure there was no oplog written - err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestRepository_ListOplogKeys(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - const testLimit = 10 - rw := db.New(conn) - repo, err := kms.NewRepository(rw, rw, kms.WithLimit(testLimit)) - require.NoError(t, err) - wrapper := db.TestWrapper(t) - - type args struct { - opt []kms.Option - } - tests := []struct { - name string - createCnt int - args args - wantCnt int - wantErr bool - }{ - { - name: "no-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{ - opt: []kms.Option{kms.WithLimit(-1)}, - }, - wantCnt: repo.DefaultLimit() + 1, // org and project both have keys, plus global scope - wantErr: false, - }, - { - name: "default-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{}, - wantCnt: repo.DefaultLimit(), - wantErr: false, - }, - { - name: "custom-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{ - opt: []kms.Option{kms.WithLimit(3)}, - }, - wantCnt: 3, - wantErr: false, - }, - } - for _, tt := range tests { - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - for i := 0; i < tt.createCnt; i++ { - org, proj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "scope_id in(?)", "global", org.PublicId, proj.PublicId) - rk := kms.TestRootKey(t, conn, proj.PublicId) - kms.TestOplogKey(t, conn, rk.PrivateId) - require.NoError(err) - } - got, err := repo.ListOplogKeys(context.Background(), tt.args.opt...) - if tt.wantErr { - require.Error(err) - return - } - require.NoError(err) - assert.Equal(tt.wantCnt, len(got)) - }) - } -} diff --git a/internal/kms/repository_oplog_key_version.go b/internal/kms/repository_oplog_key_version.go deleted file mode 100644 index d7db3e33b..000000000 --- a/internal/kms/repository_oplog_key_version.go +++ /dev/null @@ -1,176 +0,0 @@ -package kms - -import ( - "context" - "fmt" - "strings" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" -) - -// CreateOplogKeyVersion inserts into the repository and returns the new key -// version with its PrivateId. There are no valid options at this time. -func (r *Repository) CreateOplogKeyVersion(ctx context.Context, rkvWrapper wrapping.Wrapper, oplogKeyId string, key []byte, _ ...Option) (*OplogKeyVersion, error) { - const op = "kms.(Repository).CreateOplogKeyVersion" - if rkvWrapper == nil { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing root key version wrapper") - } - rootKeyVersionId, err := rkvWrapper.KeyId(ctx) - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to fetch key id")) - } - switch { - case !strings.HasPrefix(rootKeyVersionId, RootKeyVersionPrefix): - return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("root key version id %s doesn't start with prefix %s", rootKeyVersionId, RootKeyVersionPrefix)) - case rootKeyVersionId == "": - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing root key version id") - } - if oplogKeyId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing oplog key id") - } - if len(key) == 0 { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing key") - } - kv := AllocOplogKeyVersion() - id, err := newOplogKeyVersionId() - if err != nil { - return nil, errors.Wrap(ctx, err, op) - } - kv.PrivateId = id - kv.RootKeyVersionId = rootKeyVersionId - kv.Key = key - kv.OplogKeyId = oplogKeyId - if err := kv.Encrypt(ctx, rkvWrapper); err != nil { - return nil, errors.Wrap(ctx, err, op) - } - - var returnedKey interface{} - _, err = r.writer.DoTx( - ctx, - db.StdRetryCnt, - db.ExpBackoff{}, - func(_ db.Reader, w db.Writer) error { - returnedKey = kv.Clone() - // no oplog entries for root key version - if err := w.Create(ctx, returnedKey); err != nil { - return errors.Wrap(ctx, err, op) - } - return nil - }, - ) - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s oplog key id", kv.OplogKeyId))) - } - return returnedKey.(*OplogKeyVersion), nil -} - -// LookupOplogKeyVersion will look up a key version in the repository. If -// the key version is not found, it will return nil, nil. -func (r *Repository) LookupOplogKeyVersion(ctx context.Context, keyWrapper wrapping.Wrapper, privateId string, _ ...Option) (*OplogKeyVersion, error) { - const op = "kms.(Repository).LookupOplogKeyVersion" - if privateId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - if keyWrapper == nil { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing key wrapper") - } - k := AllocOplogKeyVersion() - k.PrivateId = privateId - if err := r.reader.LookupById(ctx, &k); err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - if err := k.Decrypt(ctx, keyWrapper); err != nil { - return nil, errors.Wrap(ctx, err, op) - } - return &k, nil -} - -// DeleteOplogKeyVersion deletes the key version for the provided id from the -// repository returning a count of the number of records deleted. All options -// are ignored. -func (r *Repository) DeleteOplogKeyVersion(ctx context.Context, privateId string, _ ...Option) (int, error) { - const op = "kms.(Repository).DeleteOplogKeyVersion" - if privateId == "" { - return db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - k := AllocOplogKeyVersion() - k.PrivateId = privateId - if err := r.reader.LookupById(ctx, &k); err != nil { - return db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - - var rowsDeleted int - _, err := r.writer.DoTx( - ctx, - db.StdRetryCnt, - db.ExpBackoff{}, - func(_ db.Reader, w db.Writer) (err error) { - dk := k.Clone() - // no oplog entries for the key version - rowsDeleted, err = w.Delete(ctx, dk) - if err != nil { - return errors.Wrap(ctx, err, op) - } - if rowsDeleted > 1 { - return errors.New(ctx, errors.MultipleRecords, op, "more than 1 resource would have been deleted") - } - return nil - }, - ) - if err != nil { - return db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - return rowsDeleted, nil -} - -// LatestOplogKeyVersion searches for the key version with the highest -// version number. When no results are found, it returns nil with an -// errors.RecordNotFound error. -func (r *Repository) LatestOplogKeyVersion(ctx context.Context, rkvWrapper wrapping.Wrapper, oplogKeyId string, _ ...Option) (*OplogKeyVersion, error) { - const op = "kms.(Repository).LatestOplogKeyVersion" - if oplogKeyId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing oplog key id") - } - if rkvWrapper == nil { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing root key version wrapper") - } - var foundKeys []*OplogKeyVersion - if err := r.reader.SearchWhere(ctx, &foundKeys, "oplog_key_id = ?", []interface{}{oplogKeyId}, db.WithLimit(1), db.WithOrder("version desc")); err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", oplogKeyId))) - } - if len(foundKeys) == 0 { - return nil, errors.E(ctx, errors.WithCode(errors.RecordNotFound), errors.WithOp(op)) - } - if err := foundKeys[0].Decrypt(ctx, rkvWrapper); err != nil { - return nil, errors.Wrap(ctx, err, op) - } - return foundKeys[0], nil -} - -// ListOplogKeyVersions will lists versions of a key. Supports the WithLimit option. -func (r *Repository) ListOplogKeyVersions(ctx context.Context, rkvWrapper wrapping.Wrapper, oplogKeyId string, opt ...Option) ([]DekVersion, error) { - const op = "kms.(Repository).ListOplogKeyVersions" - if oplogKeyId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing oplog key id") - } - if rkvWrapper == nil { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing root key version wrapper") - } - var versions []*OplogKeyVersion - err := r.list(ctx, &versions, "oplog_key_id = ?", []interface{}{oplogKeyId}, opt...) - if err != nil { - return nil, errors.Wrap(ctx, err, op) - } - for i, k := range versions { - if err := k.Decrypt(ctx, rkvWrapper); err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("error decrypting key num %d", i))) - } - } - dekVersions := make([]DekVersion, 0, len(versions)) - for _, version := range versions { - dekVersions = append(dekVersions, version) - } - return dekVersions, nil -} diff --git a/internal/kms/repository_oplog_key_version_test.go b/internal/kms/repository_oplog_key_version_test.go deleted file mode 100644 index 01f1002fb..000000000 --- a/internal/kms/repository_oplog_key_version_test.go +++ /dev/null @@ -1,367 +0,0 @@ -package kms_test - -import ( - "context" - "testing" - "time" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/iam" - "github.com/hashicorp/boundary/internal/kms" - "github.com/hashicorp/boundary/internal/oplog" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" -) - -func TestRepository_CreateOplogKeyVersion(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - dk := kms.TestOplogKey(t, conn, rk.PrivateId) - - type args struct { - key []byte - oplogKeyId string - keyWrapper wrapping.Wrapper - opt []kms.Option - } - tests := []struct { - name string - args args - wantErr bool - wantIsError errors.Code - }{ - { - name: "valid", - args: args{ - key: []byte("test key"), - keyWrapper: rkvWrapper, - oplogKeyId: dk.PrivateId, - }, - wantErr: false, - }, - { - name: "invalid-rkv-wrapper", - args: args{ - key: []byte("test key"), - keyWrapper: wrapper, - oplogKeyId: dk.PrivateId, - }, - wantErr: true, - }, - { - name: "empty-key", - args: args{ - key: nil, - keyWrapper: wrapper, - oplogKeyId: dk.PrivateId, - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "nil-wrapper", - args: args{ - key: []byte("test key"), - keyWrapper: nil, - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - k, err := repo.CreateOplogKeyVersion(context.Background(), tt.args.keyWrapper, tt.args.oplogKeyId, tt.args.key, tt.args.opt...) - if tt.wantErr { - assert.Error(err) - assert.Nil(k) - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - return - } - require.NoError(err) - assert.NotNil(k.CreateTime) - foundKey, err := repo.LookupOplogKeyVersion(context.Background(), tt.args.keyWrapper, k.PrivateId) - assert.NoError(err) - assert.True(proto.Equal(foundKey, k)) - - // make sure there was no oplog written - err = db.TestVerifyOplog(t, rw, k.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_CREATE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestRepository_DeleteOplogKeyVersion(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - dk := kms.TestOplogKey(t, conn, rk.PrivateId) - - type args struct { - key *kms.OplogKeyVersion - opt []kms.Option - } - tests := []struct { - name string - args args - wantRowsDeleted int - wantErr bool - wantIsError errors.Code - }{ - { - name: "valid", - args: args{ - key: kms.TestOplogKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("oplog key")), - }, - wantRowsDeleted: 1, - wantErr: false, - }, - { - name: "no-private-id", - args: args{ - key: func() *kms.OplogKeyVersion { - k := kms.AllocOplogKeyVersion() - return &k - }(), - }, - wantRowsDeleted: 0, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "not-found", - args: args{ - key: func() *kms.OplogKeyVersion { - id, err := db.NewPublicId(kms.OplogKeyPrefix) - require.NoError(t, err) - k := kms.AllocOplogKeyVersion() - k.PrivateId = id - require.NoError(t, err) - return &k - }(), - }, - wantRowsDeleted: 0, - wantErr: true, - wantIsError: errors.RecordNotFound, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - deletedRows, err := repo.DeleteOplogKeyVersion(context.Background(), tt.args.key.PrivateId, tt.args.opt...) - if tt.wantErr { - require.Error(err) - assert.Equal(0, deletedRows) - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - return - } - require.NoError(err) - assert.Equal(tt.wantRowsDeleted, deletedRows) - foundKey, err := repo.LookupOplogKeyVersion(context.Background(), wrapper, tt.args.key.PrivateId) - assert.Error(err) - assert.Nil(foundKey) - assert.True(errors.IsNotFoundError(err)) - - // make sure there was no oplog written - err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestRepository_LatestOplogKeyVersion(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - dk := kms.TestOplogKey(t, conn, rk.PrivateId) - - tests := []struct { - name string - createCnt int - keyWrapper wrapping.Wrapper - wantVersion uint32 - wantErr bool - wantIsError errors.Code - }{ - { - name: "5", - createCnt: 5, - keyWrapper: rkvWrapper, - wantVersion: 5, - wantErr: false, - }, - { - name: "1", - createCnt: 1, - keyWrapper: rkvWrapper, - wantVersion: 1, - wantErr: false, - }, - { - name: "0", - createCnt: 0, - keyWrapper: rkvWrapper, - wantErr: true, - wantIsError: errors.RecordNotFound, - }, - { - name: "nil-wrapper", - createCnt: 5, - keyWrapper: nil, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocOplogKeyVersion(); ; return &i }(), "1=1") - testKeys := []*kms.OplogKeyVersion{} - for i := 0; i < tt.createCnt; i++ { - k := kms.TestOplogKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("test oplog key")) - testKeys = append(testKeys, k) - } - assert.Equal(tt.createCnt, len(testKeys)) - got, err := repo.LatestOplogKeyVersion(context.Background(), tt.keyWrapper, dk.PrivateId) - if tt.wantErr { - require.Error(err) - assert.Nil(got) - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - return - } - require.NoError(err) - require.NotNil(got) - assert.Equal(tt.wantVersion, got.Version) - }) - } -} - -func TestRepository_ListOplogKeyVersions(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - const testLimit = 10 - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw, kms.WithLimit(testLimit)) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - dk := kms.TestOplogKey(t, conn, rk.PrivateId) - - type args struct { - oplogKeyId string - keyWrapper wrapping.Wrapper - opt []kms.Option - } - tests := []struct { - name string - createCnt int - args args - wantCnt int - wantErr bool - }{ - { - name: "no-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{ - oplogKeyId: dk.PrivateId, - keyWrapper: rkvWrapper, - opt: []kms.Option{kms.WithLimit(-1)}, - }, - wantCnt: repo.DefaultLimit() + 1, - wantErr: false, - }, - { - name: "default-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{ - keyWrapper: rkvWrapper, - oplogKeyId: dk.PrivateId, - }, - wantCnt: repo.DefaultLimit(), - wantErr: false, - }, - { - name: "custom-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{ - keyWrapper: rkvWrapper, - oplogKeyId: dk.PrivateId, - opt: []kms.Option{kms.WithLimit(3)}, - }, - wantCnt: 3, - wantErr: false, - }, - { - name: "bad-org", - createCnt: 1, - args: args{ - keyWrapper: rkvWrapper, - oplogKeyId: "bad-id", - }, - wantCnt: 0, - wantErr: false, - }, - { - name: "nil-wrapper", - createCnt: 1, - args: args{ - keyWrapper: nil, - oplogKeyId: dk.PrivateId, - }, - wantCnt: 0, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocOplogKeyVersion(); return &i }(), "1=1") - keyVersions := []*kms.OplogKeyVersion{} - for i := 0; i < tt.createCnt; i++ { - k := kms.TestOplogKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("oplog key")) - keyVersions = append(keyVersions, k) - } - assert.Equal(tt.createCnt, len(keyVersions)) - got, err := repo.ListOplogKeyVersions(context.Background(), tt.args.keyWrapper, tt.args.oplogKeyId, tt.args.opt...) - if tt.wantErr { - require.Error(err) - return - } - require.NoError(err) - assert.Equal(tt.wantCnt, len(got)) - }) - } -} diff --git a/internal/kms/repository_root_key.go b/internal/kms/repository_root_key.go deleted file mode 100644 index cf8844930..000000000 --- a/internal/kms/repository_root_key.go +++ /dev/null @@ -1,146 +0,0 @@ -package kms - -import ( - "context" - "fmt" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" -) - -// CreateRootKey inserts into the repository and returns the new root key and -// root key version. There are no valid options at this time. -func (r *Repository) CreateRootKey(ctx context.Context, keyWrapper wrapping.Wrapper, scopeId string, key []byte, _ ...Option) (*RootKey, *RootKeyVersion, error) { - const op = "kms.(Repository).CreateRootKey" - var returnedRk, returnedKv interface{} - _, err := r.writer.DoTx( - ctx, - db.StdRetryCnt, - db.ExpBackoff{}, - func(_ db.Reader, w db.Writer) error { - var err error - if returnedRk, returnedKv, err = createRootKeyTx(ctx, w, keyWrapper, scopeId, key); err != nil { - return errors.Wrap(ctx, err, op) - } - return nil - }, - ) - if err != nil { - return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", scopeId))) - } - return returnedRk.(*RootKey), returnedKv.(*RootKeyVersion), nil -} - -// createRootKeyTx inserts into the db (via db.Writer) and returns the new root key -// and root key version. This function encapsulates all the work required within -// a db.TxHandler and allows this capability to be shared with the iam repo. -func createRootKeyTx(ctx context.Context, w db.Writer, keyWrapper wrapping.Wrapper, scopeId string, key []byte) (*RootKey, *RootKeyVersion, error) { - const op = "kms.createRootKeyTx" - if scopeId == "" { - return nil, nil, errors.New(ctx, errors.InvalidParameter, op, "missing scope id") - } - if keyWrapper == nil { - return nil, nil, errors.New(ctx, errors.InvalidParameter, op, "missing key wrapper") - } - if len(key) == 0 { - return nil, nil, errors.New(ctx, errors.InvalidParameter, op, "missing key") - } - rk := AllocRootKey() - kv := AllocRootKeyVersion() - id, err := newRootKeyId() - if err != nil { - return nil, nil, errors.Wrap(ctx, err, op) - } - rk.PrivateId = id - rk.ScopeId = scopeId - - id, err = newRootKeyVersionId() - if err != nil { - return nil, nil, errors.Wrap(ctx, err, op) - } - kv.PrivateId = id - kv.RootKeyId = rk.PrivateId - kv.Key = key - if err := kv.Encrypt(ctx, keyWrapper); err != nil { - return nil, nil, errors.Wrap(ctx, err, op) - } - - // no oplog entries for root keys - if err := w.Create(ctx, &rk); err != nil { - return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg("root keys")) - } - // no oplog entries for root key versions - if err := w.Create(ctx, &kv); err != nil { - return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg("key versions")) - } - - return &rk, &kv, nil -} - -// LookupRootKey will look up a root key in the repository. If the key is not -// found, it will return nil, nil. -func (r *Repository) LookupRootKey(ctx context.Context, keyWrapper wrapping.Wrapper, privateId string, _ ...Option) (*RootKey, error) { - const op = "kms.(Repository).LookupRootKey" - if privateId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - if keyWrapper == nil { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing key wrapper") - } - k := AllocRootKey() - k.PrivateId = privateId - if err := r.reader.LookupById(ctx, &k); err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - return &k, nil -} - -// DeleteRootKey deletes the root key for the provided id from the -// repository returning a count of the number of records deleted. All options -// are ignored. -func (r *Repository) DeleteRootKey(ctx context.Context, privateId string, _ ...Option) (int, error) { - const op = "kms.(Repository).DeleteRootKey" - if privateId == "" { - return db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - k := AllocRootKey() - k.PrivateId = privateId - if err := r.reader.LookupById(ctx, &k); err != nil { - return db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - - var rowsDeleted int - _, err := r.writer.DoTx( - ctx, - db.StdRetryCnt, - db.ExpBackoff{}, - func(_ db.Reader, w db.Writer) (err error) { - dk := k.Clone() - // no oplog entries for root keys - rowsDeleted, err = w.Delete(ctx, dk) - if err != nil { - return errors.Wrap(ctx, err, op) - } - if rowsDeleted > 1 { - return errors.New(ctx, errors.MultipleRecords, op, "more than 1 resource would have been deleted") - } - return nil - }, - ) - if err != nil { - return db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - return rowsDeleted, nil -} - -// ListRootKeys will list the root keys. Supports the WithLimit option. -func (r *Repository) ListRootKeys(ctx context.Context, opt ...Option) ([]*RootKey, error) { - const op = "kms.(Repository).ListRootKeys" - var keys []*RootKey - err := r.list(ctx, &keys, "1=1", nil, opt...) - if err != nil { - return nil, errors.Wrap(ctx, err, op) - } - return keys, nil -} diff --git a/internal/kms/repository_root_key_test.go b/internal/kms/repository_root_key_test.go deleted file mode 100644 index 81571c703..000000000 --- a/internal/kms/repository_root_key_test.go +++ /dev/null @@ -1,270 +0,0 @@ -package kms_test - -import ( - "context" - "testing" - "time" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/iam" - "github.com/hashicorp/boundary/internal/kms" - "github.com/hashicorp/boundary/internal/oplog" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" -) - -func TestRepository_CreateRootKey(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - - type args struct { - scopeId string - key []byte - keyWrapper wrapping.Wrapper - opt []kms.Option - } - tests := []struct { - name string - args args - wantErr bool - wantIsError errors.Code - }{ - { - name: "valid-org", - args: args{ - scopeId: org.PublicId, - key: []byte("test key"), - keyWrapper: wrapper, - }, - wantErr: false, - }, - { - name: "valid-global", - args: args{ - scopeId: "global", - key: []byte("valid-global"), - keyWrapper: wrapper, - }, - wantErr: false, - }, - { - name: "invalid-scope", - args: args{ - scopeId: "o_notAValidScopeId", - key: []byte("invalid-scope"), - keyWrapper: wrapper, - }, - wantErr: true, - }, - { - name: "empty-scope", - args: args{ - key: []byte("empty-scope"), - keyWrapper: wrapper, - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "nil-wrapper", - args: args{ - scopeId: org.PublicId, - key: []byte("test key"), - keyWrapper: nil, - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - rk, kv, err := repo.CreateRootKey(context.Background(), tt.args.keyWrapper, tt.args.scopeId, tt.args.key, tt.args.opt...) - if tt.wantErr { - assert.Error(err) - assert.Nil(rk) - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - return - } - require.NoError(err) - assert.NotNil(rk.CreateTime) - foundKey, err := repo.LookupRootKey(context.Background(), tt.args.keyWrapper, rk.PrivateId) - assert.NoError(err) - assert.True(proto.Equal(foundKey, rk)) - - // make sure there was no oplog written - err = db.TestVerifyOplog(t, rw, rk.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_CREATE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - - assert.NotNil(kv.CreateTime) - foundKeyVersion, err := repo.LookupRootKeyVersion(context.Background(), tt.args.keyWrapper, kv.PrivateId) - assert.NoError(err) - assert.True(proto.Equal(foundKeyVersion, kv)) - - // make sure there was no oplog written - err = db.TestVerifyOplog(t, rw, kv.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_CREATE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestRepository_DeleteRootKey(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - - type args struct { - key *kms.RootKey - opt []kms.Option - } - tests := []struct { - name string - args args - wantRowsDeleted int - wantErr bool - wantIsError errors.Code - }{ - { - name: "valid", - args: args{ - key: kms.TestRootKey(t, conn, org.PublicId), - }, - wantRowsDeleted: 1, - wantErr: false, - }, - { - name: "no-private-id", - args: args{ - key: func() *kms.RootKey { - k := kms.AllocRootKey() - return &k - }(), - }, - wantRowsDeleted: 0, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "not-found", - args: args{ - key: func() *kms.RootKey { - id, err := db.NewPublicId(kms.RootKeyPrefix) - require.NoError(t, err) - k := kms.AllocRootKey() - k.PrivateId = id - require.NoError(t, err) - return &k - }(), - }, - wantRowsDeleted: 0, - wantErr: true, - wantIsError: errors.RecordNotFound, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - deletedRows, err := repo.DeleteRootKey(context.Background(), tt.args.key.PrivateId, tt.args.opt...) - if tt.wantErr { - require.Error(err) - assert.Equal(0, deletedRows) - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - // make sure there was no oplog written - err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - return - } - require.NoError(err) - assert.Equal(tt.wantRowsDeleted, deletedRows) - foundKey, err := repo.LookupRootKey(context.Background(), wrapper, tt.args.key.PrivateId) - assert.Error(err) - assert.Nil(foundKey) - assert.True(errors.IsNotFoundError(err)) - - // make sure there was no oplog written - err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestRepository_ListRootKeys(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - const testLimit = 10 - rw := db.New(conn) - repo, err := kms.NewRepository(rw, rw, kms.WithLimit(testLimit)) - require.NoError(t, err) - wrapper := db.TestWrapper(t) - - type args struct { - opt []kms.Option - } - tests := []struct { - name string - createCnt int - args args - wantCnt int - wantErr bool - }{ - { - name: "no-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{ - opt: []kms.Option{kms.WithLimit(-1)}, - }, - wantCnt: (repo.DefaultLimit()+1)*2 + 1, // org and project both have keys, plus global scope - wantErr: false, - }, - { - name: "default-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{}, - wantCnt: repo.DefaultLimit(), - wantErr: false, - }, - { - name: "custom-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{ - opt: []kms.Option{kms.WithLimit(3)}, - }, - wantCnt: 3, - wantErr: false, - }, - } - for _, tt := range tests { - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - for i := 0; i < tt.createCnt; i++ { - _, _ = iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - } - got, err := repo.ListRootKeys(context.Background(), tt.args.opt...) - if tt.wantErr { - require.Error(err) - return - } - require.NoError(err) - assert.Equal(tt.wantCnt, len(got)) - }) - } -} diff --git a/internal/kms/repository_root_key_version.go b/internal/kms/repository_root_key_version.go deleted file mode 100644 index 502ae1541..000000000 --- a/internal/kms/repository_root_key_version.go +++ /dev/null @@ -1,160 +0,0 @@ -package kms - -import ( - "context" - "fmt" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" -) - -// CreateRootKeyVersion inserts into the repository and returns the new root key -// version with its PrivateId. There are no valid options at this time. -func (r *Repository) CreateRootKeyVersion(ctx context.Context, keyWrapper wrapping.Wrapper, rootKeyId string, key []byte, _ ...Option) (*RootKeyVersion, error) { - const op = "kms.(Repository).CreateRootKeyVersion" - if rootKeyId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing root key id") - } - if keyWrapper == nil { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing key wrapper") - } - if len(key) == 0 { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing key") - } - kv := AllocRootKeyVersion() - id, err := newRootKeyVersionId() - if err != nil { - return nil, errors.Wrap(ctx, err, op) - } - kv.PrivateId = id - kv.RootKeyId = rootKeyId - kv.Key = key - if err := kv.Encrypt(ctx, keyWrapper); err != nil { - return nil, errors.Wrap(ctx, err, op) - } - - var returnedKey interface{} - _, err = r.writer.DoTx( - ctx, - db.StdRetryCnt, - db.ExpBackoff{}, - func(_ db.Reader, w db.Writer) error { - returnedKey = kv.Clone() - // no oplog entries for root key version - if err := w.Create(ctx, returnedKey); err != nil { - return errors.Wrap(ctx, err, op) - } - return nil - }, - ) - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s root key id", kv.RootKeyId))) - } - return returnedKey.(*RootKeyVersion), nil -} - -// LookupRootKeyVersion will look up a root key version in the repository. If -// the key version is not found, it will return nil, nil. -func (r *Repository) LookupRootKeyVersion(ctx context.Context, keyWrapper wrapping.Wrapper, privateId string, _ ...Option) (*RootKeyVersion, error) { - const op = "kms.(Repository).LookupRootKeyVersion" - if privateId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - if keyWrapper == nil { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing key wrapper") - } - k := AllocRootKeyVersion() - k.PrivateId = privateId - if err := r.reader.LookupById(ctx, &k); err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - if err := k.Decrypt(ctx, keyWrapper); err != nil { - return nil, errors.Wrap(ctx, err, op) - } - return &k, nil -} - -// DeleteRootKeyVersion deletes the root key version for the provided id from the -// repository returning a count of the number of records deleted. All options -// are ignored. -func (r *Repository) DeleteRootKeyVersion(ctx context.Context, privateId string, _ ...Option) (int, error) { - const op = "kms.(Repository).DeleteRootKeyVersion" - if privateId == "" { - return db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - k := AllocRootKeyVersion() - k.PrivateId = privateId - if err := r.reader.LookupById(ctx, &k); err != nil { - return db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - - var rowsDeleted int - _, err := r.writer.DoTx( - ctx, - db.StdRetryCnt, - db.ExpBackoff{}, - func(_ db.Reader, w db.Writer) (err error) { - dk := k.Clone() - // no oplog entries for root key version - rowsDeleted, err = w.Delete(ctx, dk) - if err != nil { - return errors.Wrap(ctx, err, op) - } - if rowsDeleted > 1 { - return errors.New(ctx, errors.MultipleRecords, op, "more than 1 resource would have been deleted") - } - return nil - }, - ) - if err != nil { - return db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - return rowsDeleted, nil -} - -// LatestRootKeyVersion searches for the root key version with the highest -// version number. When no results are found, it returns nil with an -// errors.RecordNotFound error. -func (r *Repository) LatestRootKeyVersion(ctx context.Context, keyWrapper wrapping.Wrapper, rootKeyId string, _ ...Option) (*RootKeyVersion, error) { - const op = "kms.(Repository).LatestRootKeyVersion" - if rootKeyId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing root key id") - } - if keyWrapper == nil { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing key wrapper") - } - var foundKeys []RootKeyVersion - if err := r.reader.SearchWhere(ctx, &foundKeys, "root_key_id = ?", []interface{}{rootKeyId}, db.WithLimit(1), db.WithOrder("version desc")); err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", rootKeyId))) - } - if len(foundKeys) == 0 { - return nil, errors.E(ctx, errors.WithCode(errors.RecordNotFound), errors.WithOp(op)) - } - if err := foundKeys[0].Decrypt(ctx, keyWrapper); err != nil { - return nil, errors.Wrap(ctx, err, op) - } - return &foundKeys[0], nil -} - -// ListRootKeyVersions in versions of a root key. Supports the WithLimit option. -func (r *Repository) ListRootKeyVersions(ctx context.Context, keyWrapper wrapping.Wrapper, rootKeyId string, opt ...Option) ([]*RootKeyVersion, error) { - const op = "kms.(Repository).ListRootKeyVersions" - if rootKeyId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing root key id") - } - if keyWrapper == nil { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing key wrapper") - } - var versions []*RootKeyVersion - err := r.list(ctx, &versions, "root_key_id = ?", []interface{}{rootKeyId}, opt...) - if err != nil { - return nil, errors.Wrap(ctx, err, op) - } - for i, k := range versions { - if err := k.Decrypt(ctx, keyWrapper); err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("error decrypting key num %d", i))) - } - } - return versions, nil -} diff --git a/internal/kms/repository_root_key_version_test.go b/internal/kms/repository_root_key_version_test.go deleted file mode 100644 index 0b47a4ac4..000000000 --- a/internal/kms/repository_root_key_version_test.go +++ /dev/null @@ -1,363 +0,0 @@ -package kms_test - -import ( - "context" - "testing" - "time" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/iam" - "github.com/hashicorp/boundary/internal/kms" - "github.com/hashicorp/boundary/internal/oplog" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" -) - -func TestRepository_CreateRootKeyVersion(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - - type args struct { - rootKeyId string - key []byte - keyWrapper wrapping.Wrapper - opt []kms.Option - } - tests := []struct { - name string - args args - wantErr bool - wantIsError errors.Code - }{ - { - name: "valid", - args: args{ - key: []byte("test key"), - rootKeyId: rk.PrivateId, - keyWrapper: wrapper, - }, - wantErr: false, - }, - { - name: "invalid-root-key", - args: args{ - key: []byte("test key"), - rootKeyId: "krk_thisIsNotValid", - keyWrapper: wrapper, - }, - wantErr: true, - }, - { - name: "empty-key", - args: args{ - key: nil, - rootKeyId: rk.PrivateId, - keyWrapper: wrapper, - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "nil-wrapper", - args: args{ - key: []byte("test key"), - rootKeyId: rk.PrivateId, - keyWrapper: nil, - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - k, err := repo.CreateRootKeyVersion(context.Background(), tt.args.keyWrapper, tt.args.rootKeyId, tt.args.key, tt.args.opt...) - if tt.wantErr { - assert.Error(err) - assert.Nil(k) - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - return - } - require.NoError(err) - assert.NotNil(k.CreateTime) - foundKey, err := repo.LookupRootKeyVersion(context.Background(), tt.args.keyWrapper, k.PrivateId) - assert.NoError(err) - assert.True(proto.Equal(foundKey, k)) - - // make sure there was no oplog written - err = db.TestVerifyOplog(t, rw, k.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_CREATE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestRepository_DeleteRootKeyVersion(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - - type args struct { - key *kms.RootKeyVersion - opt []kms.Option - } - tests := []struct { - name string - args args - wantRowsDeleted int - wantErr bool - wantIsError errors.Code - }{ - { - name: "valid", - args: args{ - key: func() *kms.RootKeyVersion { - k, _ := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - return k - }(), - }, - wantRowsDeleted: 1, - wantErr: false, - }, - { - name: "no-private-id", - args: args{ - key: func() *kms.RootKeyVersion { - k := kms.AllocRootKeyVersion() - return &k - }(), - }, - wantRowsDeleted: 0, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "not-found", - args: args{ - key: func() *kms.RootKeyVersion { - id, err := db.NewPublicId(kms.RootKeyPrefix) - require.NoError(t, err) - k := kms.AllocRootKeyVersion() - k.PrivateId = id - require.NoError(t, err) - return &k - }(), - }, - wantRowsDeleted: 0, - wantErr: true, - wantIsError: errors.RecordNotFound, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - deletedRows, err := repo.DeleteRootKeyVersion(context.Background(), tt.args.key.PrivateId, tt.args.opt...) - if tt.wantErr { - require.Error(err) - assert.Equal(0, deletedRows) - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - return - } - require.NoError(err) - assert.Equal(tt.wantRowsDeleted, deletedRows) - foundKey, err := repo.LookupRootKeyVersion(context.Background(), wrapper, tt.args.key.PrivateId) - assert.Error(err) - assert.Nil(foundKey) - assert.True(errors.IsNotFoundError(err)) - - // make sure there was no oplog written - err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestRepository_LatestRootKeyVersion(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - - tests := []struct { - name string - createCnt int - keyWrapper wrapping.Wrapper - wantVersion uint32 - wantErr bool - wantIsError errors.Code - }{ - { - name: "5", - createCnt: 5, - keyWrapper: wrapper, - wantVersion: 5, - wantErr: false, - }, - { - name: "1", - createCnt: 1, - keyWrapper: wrapper, - wantVersion: 1, - wantErr: false, - }, - { - name: "0", - createCnt: 0, - keyWrapper: wrapper, - wantErr: true, - wantIsError: errors.RecordNotFound, - }, - { - name: "nil-wrapper", - createCnt: 5, - keyWrapper: nil, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKeyVersion(); return &i }(), "1=1") - testKeys := []*kms.RootKeyVersion{} - for i := 0; i < tt.createCnt; i++ { - k, _ := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - testKeys = append(testKeys, k) - } - assert.Equal(tt.createCnt, len(testKeys)) - got, err := repo.LatestRootKeyVersion(context.Background(), tt.keyWrapper, rk.PrivateId) - if tt.wantErr { - require.Error(err) - assert.Nil(got) - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - return - } - require.NoError(err) - require.NotNil(got) - assert.Equal(tt.wantVersion, got.Version) - }) - } -} - -func TestRepository_ListRootKeyVersions(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - const testLimit = 10 - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw, kms.WithLimit(testLimit)) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - - type args struct { - rootKeyId string - keyWrapper wrapping.Wrapper - opt []kms.Option - } - tests := []struct { - name string - createCnt int - args args - wantCnt int - wantErr bool - }{ - { - name: "no-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{ - rootKeyId: rk.PrivateId, - keyWrapper: wrapper, - opt: []kms.Option{kms.WithLimit(-1)}, - }, - wantCnt: repo.DefaultLimit() + 1, - wantErr: false, - }, - { - name: "default-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{ - keyWrapper: wrapper, - rootKeyId: rk.PrivateId, - }, - wantCnt: repo.DefaultLimit(), - wantErr: false, - }, - { - name: "custom-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{ - keyWrapper: wrapper, - rootKeyId: rk.PrivateId, - opt: []kms.Option{kms.WithLimit(3)}, - }, - wantCnt: 3, - wantErr: false, - }, - { - name: "bad-org", - createCnt: 1, - args: args{ - keyWrapper: wrapper, - rootKeyId: "bad-id", - }, - wantCnt: 0, - wantErr: false, - }, - { - name: "nil-wrapper", - createCnt: 1, - args: args{ - keyWrapper: nil, - rootKeyId: rk.PrivateId, - }, - wantCnt: 0, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKeyVersion(); return &i }(), "1=1") - testRootKeyVersions := []*kms.RootKeyVersion{} - for i := 0; i < tt.createCnt; i++ { - k, _ := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - testRootKeyVersions = append(testRootKeyVersions, k) - } - assert.Equal(tt.createCnt, len(testRootKeyVersions)) - got, err := repo.ListRootKeyVersions(context.Background(), tt.args.keyWrapper, tt.args.rootKeyId, tt.args.opt...) - if tt.wantErr { - require.Error(err) - return - } - require.NoError(err) - assert.Equal(tt.wantCnt, len(got)) - }) - } -} diff --git a/internal/kms/repository_session_key.go b/internal/kms/repository_session_key.go deleted file mode 100644 index 24e0d548e..000000000 --- a/internal/kms/repository_session_key.go +++ /dev/null @@ -1,162 +0,0 @@ -package kms - -import ( - "context" - "fmt" - "strings" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" -) - -// CreateSessionKey inserts into the repository and returns the new key and the -// key version. There are no valid options at this time. -func (r *Repository) CreateSessionKey(ctx context.Context, rkvWrapper wrapping.Wrapper, key []byte, _ ...Option) (*SessionKey, *SessionKeyVersion, error) { - const op = "kms.(Repository).CreateSessionKey" - var returnedDk, returnedDv interface{} - _, err := r.writer.DoTx( - ctx, - db.StdRetryCnt, - db.ExpBackoff{}, - func(reader db.Reader, w db.Writer) error { - var err error - if returnedDk, returnedDv, err = createSessionKeyTx(ctx, reader, w, rkvWrapper, key); err != nil { - return errors.Wrap(ctx, err, op) - } - return nil - }, - ) - if err != nil { - return nil, nil, errors.Wrap(ctx, err, op) - } - return returnedDk.(*SessionKey), returnedDv.(*SessionKeyVersion), nil -} - -// createSessionKeyTx inserts into the db (via db.Writer) and returns the new key -// and the key version. This function encapsulates all the work required within -// a db.TxHandler and allows this capability to be shared with the iam repo. -func createSessionKeyTx(ctx context.Context, r db.Reader, w db.Writer, rkvWrapper wrapping.Wrapper, key []byte) (*SessionKey, *SessionKeyVersion, error) { - const op = "kms.createSessionKeyTx" - if rkvWrapper == nil { - return nil, nil, errors.New(ctx, errors.InvalidParameter, op, "missing key wrapper") - } - if len(key) == 0 { - return nil, nil, errors.New(ctx, errors.InvalidParameter, op, "missing key") - } - rootKeyVersionId, err := rkvWrapper.KeyId(ctx) - if err != nil { - return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to lookup root key id")) - } - switch { - case !strings.HasPrefix(rootKeyVersionId, RootKeyVersionPrefix): - return nil, nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("root key version id %s doesn't start with prefix %s", rootKeyVersionId, RootKeyVersionPrefix)) - case rootKeyVersionId == "": - return nil, nil, errors.New(ctx, errors.InvalidParameter, op, "missing root key version id") - } - rv := AllocRootKeyVersion() - rv.PrivateId = rootKeyVersionId - if err := r.LookupById(ctx, &rv); err != nil { - return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("unable to lookup root key version %s", rootKeyVersionId))) - } - - tk := AllocSessionKey() - tv := AllocSessionKeyVersion() - id, err := newSessionKeyId() - if err != nil { - return nil, nil, errors.Wrap(ctx, err, op) - } - tk.PrivateId = id - tk.RootKeyId = rv.RootKeyId - - id, err = newSessionKeyVersionId() - if err != nil { - return nil, nil, errors.Wrap(ctx, err, op) - } - tv.PrivateId = id - tv.SessionKeyId = tk.PrivateId - tv.RootKeyVersionId = rootKeyVersionId - tv.Key = key - if err := tv.Encrypt(ctx, rkvWrapper); err != nil { - return nil, nil, errors.Wrap(ctx, err, op) - } - - // no session entries for keys - if err := w.Create(ctx, &tk); err != nil { - return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg("keys create")) - } - // no session entries for key versions - if err := w.Create(ctx, &tv); err != nil { - return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg("key versions create")) - } - - return &tk, &tv, nil -} - -// LookupSessionKey will look up a key in the repository. If the key is not -// found, it will return nil, nil. -func (r *Repository) LookupSessionKey(ctx context.Context, privateId string, _ ...Option) (*SessionKey, error) { - const op = "kms.(Repository).LookupSessionKey" - if privateId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - k := AllocSessionKey() - k.PrivateId = privateId - if err := r.reader.LookupById(ctx, &k); err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - return &k, nil -} - -// DeleteSessionKey deletes the key for the provided id from the -// repository returning a count of the number of records deleted. All options -// are ignored. -func (r *Repository) DeleteSessionKey(ctx context.Context, privateId string, _ ...Option) (int, error) { - const op = "kms.(Repository).DeleteSessionKey" - if privateId == "" { - return db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - k := AllocSessionKey() - k.PrivateId = privateId - if err := r.reader.LookupById(ctx, &k); err != nil { - return db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - - var rowsDeleted int - _, err := r.writer.DoTx( - ctx, - db.StdRetryCnt, - db.ExpBackoff{}, - func(_ db.Reader, w db.Writer) (err error) { - dk := k.Clone() - // no session entries for root keys - rowsDeleted, err = w.Delete(ctx, dk) - if err != nil { - return errors.Wrap(ctx, err, op) - } - if rowsDeleted > 1 { - return errors.New(ctx, errors.MultipleRecords, op, "more than 1 resource would have been deleted") - } - return nil - }, - ) - if err != nil { - return db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - return rowsDeleted, nil -} - -// ListSessionKeys will list the keys. Supports the WithLimit option. -func (r *Repository) ListSessionKeys(ctx context.Context, opt ...Option) ([]Dek, error) { - const op = "kms.(Repository).ListSessionKeys" - var keys []*SessionKey - err := r.list(ctx, &keys, "1=1", nil, opt...) - if err != nil { - return nil, errors.Wrap(ctx, err, op) - } - deks := make([]Dek, 0, len(keys)) - for _, key := range keys { - deks = append(deks, key) - } - return deks, nil -} diff --git a/internal/kms/repository_session_key_test.go b/internal/kms/repository_session_key_test.go deleted file mode 100644 index 538ea883f..000000000 --- a/internal/kms/repository_session_key_test.go +++ /dev/null @@ -1,296 +0,0 @@ -package kms_test - -import ( - "context" - "testing" - "time" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/iam" - "github.com/hashicorp/boundary/internal/kms" - "github.com/hashicorp/boundary/internal/oplog" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" - aead "github.com/hashicorp/go-kms-wrapping/v2/aead" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" -) - -func TestRepository_CreateSessionKey(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - - type args struct { - scopeId string - key []byte - keyWrapper wrapping.Wrapper - opt []kms.Option - } - tests := []struct { - name string - args args - wantErr bool - wantIsError errors.Code - }{ - { - name: "valid-org", - args: args{ - scopeId: org.PublicId, - key: []byte("test key"), - keyWrapper: rkvWrapper, - }, - wantErr: false, - }, - { - name: "nil-key", - args: args{ - scopeId: org.PublicId, - keyWrapper: rkvWrapper, - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "empty-key", - args: args{ - scopeId: org.PublicId, - keyWrapper: rkvWrapper, - key: []byte(""), - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "nil-wrapper", - args: args{ - scopeId: org.PublicId, - key: []byte("test key"), - keyWrapper: nil, - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "not-rkv-wrapper", - args: args{ - scopeId: org.PublicId, - key: []byte("test key"), - keyWrapper: wrapper, - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "wrapper-missing-id", - args: args{ - scopeId: org.PublicId, - key: []byte("test key"), - keyWrapper: func() wrapping.Wrapper { - w := db.TestWrapper(t) - _, err = w.(*aead.Wrapper).SetConfig(context.Background()) - require.NoError(t, err) - return w - }(), - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - tk, tv, err := repo.CreateSessionKey(context.Background(), tt.args.keyWrapper, tt.args.key, tt.args.opt...) - if tt.wantErr { - assert.Error(err) - assert.Nil(tk) - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - return - } - require.NoError(err) - assert.NotNil(tk.CreateTime) - foundKey, err := repo.LookupSessionKey(context.Background(), tk.PrivateId) - assert.NoError(err) - assert.True(proto.Equal(foundKey, tk)) - - // make sure there was no session written - err = db.TestVerifyOplog(t, rw, tk.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_CREATE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - - assert.NotNil(tv.CreateTime) - foundKeyVersion, err := repo.LookupSessionKeyVersion(context.Background(), tt.args.keyWrapper, tv.PrivateId) - assert.NoError(err) - assert.True(proto.Equal(foundKeyVersion, tv)) - - // make sure there was no session written - err = db.TestVerifyOplog(t, rw, tv.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_CREATE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestRepository_DeleteSessionKey(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - - type args struct { - key *kms.SessionKey - opt []kms.Option - } - tests := []struct { - name string - args args - wantRowsDeleted int - wantErr bool - wantIsError errors.Code - }{ - { - name: "valid", - args: args{ - key: kms.TestSessionKey(t, conn, rk.PrivateId), - }, - wantRowsDeleted: 1, - wantErr: false, - }, - { - name: "no-private-id", - args: args{ - key: func() *kms.SessionKey { - k := kms.AllocSessionKey() - return &k - }(), - }, - wantRowsDeleted: 0, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "not-found", - args: args{ - key: func() *kms.SessionKey { - id, err := db.NewPublicId(kms.RootKeyPrefix) - require.NoError(t, err) - k := kms.AllocSessionKey() - k.PrivateId = id - require.NoError(t, err) - return &k - }(), - }, - wantRowsDeleted: 0, - wantErr: true, - wantIsError: errors.RecordNotFound, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - deletedRows, err := repo.DeleteSessionKey(context.Background(), tt.args.key.PrivateId, tt.args.opt...) - if tt.wantErr { - require.Error(err) - assert.Equal(0, deletedRows) - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - - // make sure there was no session written - err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - return - } - require.NoError(err) - assert.Equal(tt.wantRowsDeleted, deletedRows) - foundKey, err := repo.LookupSessionKey(context.Background(), tt.args.key.PrivateId) - assert.Error(err) - assert.Nil(foundKey) - assert.True(errors.IsNotFoundError(err)) - - // make sure there was no session written - err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestRepository_ListSessionKeys(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - const testLimit = 10 - rw := db.New(conn) - repo, err := kms.NewRepository(rw, rw, kms.WithLimit(testLimit)) - require.NoError(t, err) - wrapper := db.TestWrapper(t) - - type args struct { - opt []kms.Option - } - tests := []struct { - name string - createCnt int - args args - wantCnt int - wantErr bool - }{ - { - name: "no-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{ - opt: []kms.Option{kms.WithLimit(-1)}, - }, - wantCnt: repo.DefaultLimit() + 1, // org and project both have keys, plus global scope - wantErr: false, - }, - { - name: "default-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{}, - wantCnt: repo.DefaultLimit(), - wantErr: false, - }, - { - name: "custom-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{ - opt: []kms.Option{kms.WithLimit(3)}, - }, - wantCnt: 3, - wantErr: false, - }, - } - for _, tt := range tests { - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - for i := 0; i < tt.createCnt; i++ { - org, proj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "scope_id in(?)", "global", org.PublicId, proj.PublicId) - rk := kms.TestRootKey(t, conn, proj.PublicId) - kms.TestSessionKey(t, conn, rk.PrivateId) - require.NoError(err) - } - got, err := repo.ListSessionKeys(context.Background(), tt.args.opt...) - if tt.wantErr { - require.Error(err) - return - } - require.NoError(err) - assert.Equal(tt.wantCnt, len(got)) - }) - } -} diff --git a/internal/kms/repository_session_key_version.go b/internal/kms/repository_session_key_version.go deleted file mode 100644 index 89874e4d6..000000000 --- a/internal/kms/repository_session_key_version.go +++ /dev/null @@ -1,176 +0,0 @@ -package kms - -import ( - "context" - "fmt" - "strings" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" -) - -// CreateSessionKeyVersion inserts into the repository and returns the new key -// version with its PrivateId. There are no valid options at this time. -func (r *Repository) CreateSessionKeyVersion(ctx context.Context, rkvWrapper wrapping.Wrapper, sessionKeyId string, key []byte, _ ...Option) (*SessionKeyVersion, error) { - const op = "kms.(Repository).CreateSessionKeyVersion" - if rkvWrapper == nil { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing root key version wrapper") - } - rootKeyVersionId, err := rkvWrapper.KeyId(ctx) - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to fetch key id")) - } - switch { - case !strings.HasPrefix(rootKeyVersionId, RootKeyVersionPrefix): - return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("root key version id %s doesn't start with prefix %s", rootKeyVersionId, RootKeyVersionPrefix)) - case rootKeyVersionId == "": - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing root key version id") - } - if sessionKeyId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing session key id") - } - if len(key) == 0 { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing key") - } - kv := AllocSessionKeyVersion() - id, err := newSessionKeyVersionId() - if err != nil { - return nil, errors.Wrap(ctx, err, op) - } - kv.PrivateId = id - kv.RootKeyVersionId = rootKeyVersionId - kv.Key = key - kv.SessionKeyId = sessionKeyId - if err := kv.Encrypt(ctx, rkvWrapper); err != nil { - return nil, errors.Wrap(ctx, err, op) - } - - var returnedKey interface{} - _, err = r.writer.DoTx( - ctx, - db.StdRetryCnt, - db.ExpBackoff{}, - func(_ db.Reader, w db.Writer) error { - returnedKey = kv.Clone() - // no session entries for root key version - if err := w.Create(ctx, returnedKey); err != nil { - return errors.Wrap(ctx, err, op) - } - return nil - }, - ) - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s session key id", kv.SessionKeyId))) - } - return returnedKey.(*SessionKeyVersion), nil -} - -// LookupSessionKeyVersion will look up a key version in the repository. If -// the key version is not found, it will return nil, nil. -func (r *Repository) LookupSessionKeyVersion(ctx context.Context, keyWrapper wrapping.Wrapper, privateId string, _ ...Option) (*SessionKeyVersion, error) { - const op = "kms.(Repository).LookupSessionKeyVersion" - if privateId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - if keyWrapper == nil { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing key wrapper") - } - k := AllocSessionKeyVersion() - k.PrivateId = privateId - if err := r.reader.LookupById(ctx, &k); err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - if err := k.Decrypt(ctx, keyWrapper); err != nil { - return nil, errors.Wrap(ctx, err, op) - } - return &k, nil -} - -// DeleteSessionKeyVersion deletes the key version for the provided id from the -// repository returning a count of the number of records deleted. All options -// are ignored. -func (r *Repository) DeleteSessionKeyVersion(ctx context.Context, privateId string, _ ...Option) (int, error) { - const op = "kms.(Repository).DeleteSessionKeyVersion" - if privateId == "" { - return db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - k := AllocSessionKeyVersion() - k.PrivateId = privateId - if err := r.reader.LookupById(ctx, &k); err != nil { - return db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - - var rowsDeleted int - _, err := r.writer.DoTx( - ctx, - db.StdRetryCnt, - db.ExpBackoff{}, - func(_ db.Reader, w db.Writer) (err error) { - dk := k.Clone() - // no session entries for the key version - rowsDeleted, err = w.Delete(ctx, dk) - if err != nil { - return errors.Wrap(ctx, err, op) - } - if rowsDeleted > 1 { - return errors.New(ctx, errors.MultipleRecords, op, "more than 1 resource would have been deleted") - } - return nil - }, - ) - if err != nil { - return db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - return rowsDeleted, nil -} - -// LatestSessionKeyVersion searches for the key version with the highest -// version number. When no results are found, it returns nil with an -// errors.RecordNotFound error. -func (r *Repository) LatestSessionKeyVersion(ctx context.Context, rkvWrapper wrapping.Wrapper, sessionKeyId string, _ ...Option) (*SessionKeyVersion, error) { - const op = "kms.(Repository).LatestSessionKeyVersion" - if sessionKeyId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing session key id") - } - if rkvWrapper == nil { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing root key version wrapper") - } - var foundKeys []*SessionKeyVersion - if err := r.reader.SearchWhere(ctx, &foundKeys, "session_key_id = ?", []interface{}{sessionKeyId}, db.WithLimit(1), db.WithOrder("version desc")); err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", sessionKeyId))) - } - if len(foundKeys) == 0 { - return nil, errors.E(ctx, errors.WithCode(errors.RecordNotFound), errors.WithOp(op)) - } - if err := foundKeys[0].Decrypt(ctx, rkvWrapper); err != nil { - return nil, errors.Wrap(ctx, err, op) - } - return foundKeys[0], nil -} - -// ListSessionKeyVersions will lists versions of a key. Supports the WithLimit option. -func (r *Repository) ListSessionKeyVersions(ctx context.Context, rkvWrapper wrapping.Wrapper, sessionKeyId string, opt ...Option) ([]DekVersion, error) { - const op = "kms.(Repository).ListSessionKeyVersions" - if sessionKeyId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing session key id") - } - if rkvWrapper == nil { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing root key version wrapper") - } - var versions []*SessionKeyVersion - err := r.list(ctx, &versions, "session_key_id = ?", []interface{}{sessionKeyId}, opt...) - if err != nil { - return nil, errors.Wrap(ctx, err, op) - } - for i, k := range versions { - if err := k.Decrypt(ctx, rkvWrapper); err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("error decrypting key num %d", i))) - } - } - dekVersions := make([]DekVersion, 0, len(versions)) - for _, version := range versions { - dekVersions = append(dekVersions, version) - } - return dekVersions, nil -} diff --git a/internal/kms/repository_session_key_version_test.go b/internal/kms/repository_session_key_version_test.go deleted file mode 100644 index b64d466f9..000000000 --- a/internal/kms/repository_session_key_version_test.go +++ /dev/null @@ -1,367 +0,0 @@ -package kms_test - -import ( - "context" - "testing" - "time" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/iam" - "github.com/hashicorp/boundary/internal/kms" - "github.com/hashicorp/boundary/internal/oplog" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" -) - -func TestRepository_CreateSessionKeyVersion(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - sk := kms.TestSessionKey(t, conn, rk.PrivateId) - - type args struct { - key []byte - sessionKeyId string - keyWrapper wrapping.Wrapper - opt []kms.Option - } - tests := []struct { - name string - args args - wantErr bool - wantIsError errors.Code - }{ - { - name: "valid", - args: args{ - key: []byte("test key"), - keyWrapper: rkvWrapper, - sessionKeyId: sk.PrivateId, - }, - wantErr: false, - }, - { - name: "invalid-rkv-wrapper", - args: args{ - key: []byte("test key"), - keyWrapper: wrapper, - sessionKeyId: sk.PrivateId, - }, - wantErr: true, - }, - { - name: "empty-key", - args: args{ - key: nil, - keyWrapper: wrapper, - sessionKeyId: sk.PrivateId, - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "nil-wrapper", - args: args{ - key: []byte("test key"), - keyWrapper: nil, - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - k, err := repo.CreateSessionKeyVersion(context.Background(), tt.args.keyWrapper, tt.args.sessionKeyId, tt.args.key, tt.args.opt...) - if tt.wantErr { - assert.Error(err) - assert.Nil(k) - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - return - } - require.NoError(err) - assert.NotNil(k.CreateTime) - foundKey, err := repo.LookupSessionKeyVersion(context.Background(), tt.args.keyWrapper, k.PrivateId) - assert.NoError(err) - assert.True(proto.Equal(foundKey, k)) - - // make sure there was no oplog written - err = db.TestVerifyOplog(t, rw, k.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_CREATE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestRepository_DeleteSessionKeyVersion(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - sk := kms.TestSessionKey(t, conn, rk.PrivateId) - - type args struct { - key *kms.SessionKeyVersion - opt []kms.Option - } - tests := []struct { - name string - args args - wantRowsDeleted int - wantErr bool - wantIsError errors.Code - }{ - { - name: "valid", - args: args{ - key: kms.TestSessionKeyVersion(t, conn, rkvWrapper, sk.PrivateId, []byte("session key")), - }, - wantRowsDeleted: 1, - wantErr: false, - }, - { - name: "no-private-id", - args: args{ - key: func() *kms.SessionKeyVersion { - k := kms.AllocSessionKeyVersion() - return &k - }(), - }, - wantRowsDeleted: 0, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "not-found", - args: args{ - key: func() *kms.SessionKeyVersion { - id, err := db.NewPublicId(kms.SessionKeyPrefix) - require.NoError(t, err) - k := kms.AllocSessionKeyVersion() - k.PrivateId = id - require.NoError(t, err) - return &k - }(), - }, - wantRowsDeleted: 0, - wantErr: true, - wantIsError: errors.RecordNotFound, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - deletedRows, err := repo.DeleteSessionKeyVersion(context.Background(), tt.args.key.PrivateId, tt.args.opt...) - if tt.wantErr { - require.Error(err) - assert.Equal(0, deletedRows) - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - return - } - require.NoError(err) - assert.Equal(tt.wantRowsDeleted, deletedRows) - foundKey, err := repo.LookupSessionKeyVersion(context.Background(), wrapper, tt.args.key.PrivateId) - assert.Error(err) - assert.Nil(foundKey) - assert.True(errors.IsNotFoundError(err)) - - // make sure there was no oplog written - err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestRepository_LatestSessionKeyVersion(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - sk := kms.TestSessionKey(t, conn, rk.PrivateId) - - tests := []struct { - name string - createCnt int - keyWrapper wrapping.Wrapper - wantVersion uint32 - wantErr bool - wantIsError errors.Code - }{ - { - name: "5", - createCnt: 5, - keyWrapper: rkvWrapper, - wantVersion: 5, - wantErr: false, - }, - { - name: "1", - createCnt: 1, - keyWrapper: rkvWrapper, - wantVersion: 1, - wantErr: false, - }, - { - name: "0", - createCnt: 0, - keyWrapper: rkvWrapper, - wantErr: true, - wantIsError: errors.RecordNotFound, - }, - { - name: "nil-wrapper", - createCnt: 5, - keyWrapper: nil, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocSessionKeyVersion(); return &i }(), "1=1") - testKeys := []*kms.SessionKeyVersion{} - for i := 0; i < tt.createCnt; i++ { - k := kms.TestSessionKeyVersion(t, conn, rkvWrapper, sk.PrivateId, []byte("test key")) - testKeys = append(testKeys, k) - } - assert.Equal(tt.createCnt, len(testKeys)) - got, err := repo.LatestSessionKeyVersion(context.Background(), tt.keyWrapper, sk.PrivateId) - if tt.wantErr { - require.Error(err) - assert.Nil(got) - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - return - } - require.NoError(err) - require.NotNil(got) - assert.Equal(tt.wantVersion, got.Version) - }) - } -} - -func TestRepository_ListSessionKeyVersions(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - const testLimit = 10 - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw, kms.WithLimit(testLimit)) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - sk := kms.TestSessionKey(t, conn, rk.PrivateId) - - type args struct { - sessionKeyId string - keyWrapper wrapping.Wrapper - opt []kms.Option - } - tests := []struct { - name string - createCnt int - args args - wantCnt int - wantErr bool - }{ - { - name: "no-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{ - sessionKeyId: sk.PrivateId, - keyWrapper: rkvWrapper, - opt: []kms.Option{kms.WithLimit(-1)}, - }, - wantCnt: repo.DefaultLimit() + 1, - wantErr: false, - }, - { - name: "default-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{ - keyWrapper: rkvWrapper, - sessionKeyId: sk.PrivateId, - }, - wantCnt: repo.DefaultLimit(), - wantErr: false, - }, - { - name: "custom-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{ - keyWrapper: rkvWrapper, - sessionKeyId: sk.PrivateId, - opt: []kms.Option{kms.WithLimit(3)}, - }, - wantCnt: 3, - wantErr: false, - }, - { - name: "bad-org", - createCnt: 1, - args: args{ - keyWrapper: rkvWrapper, - sessionKeyId: "bad-id", - }, - wantCnt: 0, - wantErr: false, - }, - { - name: "nil-wrapper", - createCnt: 1, - args: args{ - keyWrapper: nil, - sessionKeyId: sk.PrivateId, - }, - wantCnt: 0, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocSessionKeyVersion(); return &i }(), "1=1") - keyVersions := []*kms.SessionKeyVersion{} - for i := 0; i < tt.createCnt; i++ { - k := kms.TestSessionKeyVersion(t, conn, rkvWrapper, sk.PrivateId, []byte("session key")) - keyVersions = append(keyVersions, k) - } - assert.Equal(tt.createCnt, len(keyVersions)) - got, err := repo.ListSessionKeyVersions(context.Background(), tt.args.keyWrapper, tt.args.sessionKeyId, tt.args.opt...) - if tt.wantErr { - require.Error(err) - return - } - require.NoError(err) - assert.Equal(tt.wantCnt, len(got)) - }) - } -} diff --git a/internal/kms/repository_test.go b/internal/kms/repository_test.go deleted file mode 100644 index 2a77e986b..000000000 --- a/internal/kms/repository_test.go +++ /dev/null @@ -1,288 +0,0 @@ -package kms_test - -import ( - "context" - "crypto/rand" - "io" - "testing" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/iam" - "github.com/hashicorp/boundary/internal/kms" - "github.com/hashicorp/boundary/internal/types/scope" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestNewRepository(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - type args struct { - r db.Reader - w db.Writer - } - tests := []struct { - name string - args args - want *kms.Repository - wantErr bool - wantErrString string - }{ - { - name: "valid", - args: args{ - r: rw, - w: rw, - }, - want: func() *kms.Repository { - ret, err := kms.NewRepository(rw, rw) - require.NoError(t, err) - return ret - }(), - wantErr: false, - }, - { - name: "nil-writer", - args: args{ - r: rw, - w: nil, - }, - want: nil, - wantErr: true, - wantErrString: "kms.NewRepository: nil writer: parameter violation: error #100", - }, - { - name: "nil-reader", - args: args{ - r: nil, - w: rw, - }, - want: nil, - wantErr: true, - wantErrString: "kms.NewRepository: nil reader: parameter violation: error #100", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - got, err := kms.NewRepository(tt.args.r, tt.args.w) - if tt.wantErr { - require.Error(err) - assert.Equal(tt.wantErrString, err.Error()) - return - } - require.NoError(err) - assert.Equal(tt.want, got) - }) - } -} - -func TestCreateKeysTx(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - - type args struct { - ctx context.Context - dbReader db.Reader - dbWriter db.Writer - rootWrapper wrapping.Wrapper - randomReader io.Reader - scopeId string - } - tests := []struct { - name string - args args - wantErr bool - wantErrIs errors.Code - }{ - { - name: "valid", - args: args{ - dbReader: rw, - dbWriter: rw, - rootWrapper: wrapper, - randomReader: rand.Reader, - scopeId: org.PublicId, - }, - }, - { - name: "valid-at-global", - args: args{ - dbReader: rw, - dbWriter: rw, - rootWrapper: wrapper, - randomReader: rand.Reader, - scopeId: scope.Global.String(), - }, - }, - { - name: "nil-reader", - args: args{ - dbReader: nil, - dbWriter: rw, - rootWrapper: wrapper, - randomReader: rand.Reader, - scopeId: org.PublicId, - }, - wantErr: true, - wantErrIs: errors.InvalidParameter, - }, - { - name: "nil-writer", - args: args{ - dbReader: rw, - dbWriter: nil, - rootWrapper: wrapper, - randomReader: rand.Reader, - scopeId: org.PublicId, - }, - wantErr: true, - wantErrIs: errors.InvalidParameter, - }, - { - name: "nil-wrapper", - args: args{ - dbReader: rw, - dbWriter: rw, - rootWrapper: nil, - randomReader: rand.Reader, - scopeId: org.PublicId, - }, - wantErr: true, - wantErrIs: errors.InvalidParameter, - }, - { - name: "empty-scope", - args: args{ - dbReader: rw, - dbWriter: rw, - rootWrapper: wrapper, - randomReader: rand.Reader, - scopeId: "", - }, - wantErr: true, - wantErrIs: errors.InvalidParameter, - }, - { - name: "bad-scope", - args: args{ - dbReader: rw, - dbWriter: rw, - rootWrapper: wrapper, - randomReader: rand.Reader, - scopeId: "o_thisIsAnInvalidScopeId", - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - keys, err := kms.CreateKeysTx(tt.args.ctx, tt.args.dbReader, tt.args.dbWriter, tt.args.rootWrapper, tt.args.randomReader, tt.args.scopeId) - if tt.wantErr { - require.Error(err) - assert.Truef(errors.Match(errors.T(tt.wantErrIs), err), "unexpected error: %s", err.Error()) - return - } - require.NoError(err) - rk := kms.AllocRootKey() - rk.PrivateId = keys[kms.KeyTypeRootKey].GetPrivateId() - err = rw.LookupById(context.Background(), &rk) - require.NoError(err) - assert.Equal(rk.ScopeId, tt.args.scopeId) - - rkv := kms.AllocRootKeyVersion() - rkv.PrivateId = keys[kms.KeyTypeRootKeyVersion].GetPrivateId() - err = rw.LookupById(context.Background(), &rkv) - require.NoError(err) - assert.Equal(rkv.RootKeyId, rk.PrivateId) - - dk := kms.AllocDatabaseKey() - dk.PrivateId = keys[kms.KeyTypeDatabaseKey].GetPrivateId() - err = rw.LookupById(context.Background(), &dk) - require.NoError(err) - assert.Equal(rk.PrivateId, dk.RootKeyId) - - dkv := kms.AllocDatabaseKeyVersion() - dkv.PrivateId = keys[kms.KeyTypeDatabaseKeyVersion].GetPrivateId() - err = rw.LookupById(context.Background(), &dkv) - require.NoError(err) - assert.Equal(dk.PrivateId, dkv.DatabaseKeyId) - assert.Equal(rkv.PrivateId, dkv.RootKeyVersionId) - - opk := kms.AllocOplogKey() - opk.PrivateId = keys[kms.KeyTypeOplogKey].GetPrivateId() - err = rw.LookupById(context.Background(), &opk) - require.NoError(err) - assert.Equal(rk.PrivateId, opk.RootKeyId) - - opkv := kms.AllocOplogKeyVersion() - opkv.PrivateId = keys[kms.KeyTypeOplogKeyVersion].GetPrivateId() - err = rw.LookupById(context.Background(), &opkv) - require.NoError(err) - assert.Equal(opk.PrivateId, opkv.OplogKeyId) - assert.Equal(rkv.PrivateId, opkv.RootKeyVersionId) - - sk := kms.AllocSessionKey() - sk.PrivateId = keys[kms.KeyTypeSessionKey].GetPrivateId() - err = rw.LookupById(context.Background(), &sk) - require.NoError(err) - assert.Equal(rk.PrivateId, sk.RootKeyId) - - skv := kms.AllocSessionKeyVersion() - skv.PrivateId = keys[kms.KeyTypeSessionKeyVersion].GetPrivateId() - err = rw.LookupById(context.Background(), &skv) - require.NoError(err) - assert.Equal(sk.PrivateId, skv.SessionKeyId) - assert.Equal(rkv.PrivateId, skv.RootKeyVersionId) - - tk := kms.AllocTokenKey() - tk.PrivateId = keys[kms.KeyTypeTokenKey].GetPrivateId() - err = rw.LookupById(context.Background(), &tk) - require.NoError(err) - assert.Equal(rk.PrivateId, tk.RootKeyId) - - tkv := kms.AllocTokenKeyVersion() - tkv.PrivateId = keys[kms.KeyTypeTokenKeyVersion].GetPrivateId() - err = rw.LookupById(context.Background(), &tkv) - require.NoError(err) - assert.Equal(tk.PrivateId, tkv.TokenKeyId) - assert.Equal(rkv.PrivateId, tkv.RootKeyVersionId) - - oidcK := kms.AllocOidcKey() - oidcK.PrivateId = keys[kms.KeyTypeOidcKey].GetPrivateId() - err = rw.LookupById(context.Background(), &oidcK) - require.NoError(err) - assert.Equal(rk.PrivateId, oidcK.RootKeyId) - - oidcKv := kms.AllocOidcKeyVersion() - oidcKv.PrivateId = keys[kms.KeyTypeOidcKeyVersion].GetPrivateId() - err = rw.LookupById(context.Background(), &oidcKv) - require.NoError(err) - assert.Equal(oidcK.PrivateId, oidcKv.OidcKeyId) - assert.Equal(rkv.PrivateId, oidcKv.RootKeyVersionId) - - if tt.args.scopeId == scope.Global.String() { - auditK := kms.AllocAuditKey() - auditK.PrivateId = keys[kms.KeyTypeAuditKey].GetPrivateId() - err = rw.LookupById(context.Background(), &auditK) - require.NoError(err) - assert.Equal(rk.PrivateId, auditK.RootKeyId) - - auditKv := kms.AllocAuditKeyVersion() - auditKv.PrivateId = keys[kms.KeyTypeAuditKeyVersion].GetPrivateId() - err = rw.LookupById(context.Background(), &auditKv) - require.NoError(err) - assert.Equal(auditK.PrivateId, auditKv.AuditKeyId) - assert.Equal(rkv.PrivateId, auditKv.RootKeyVersionId) - } - }) - } -} diff --git a/internal/kms/repository_token_key.go b/internal/kms/repository_token_key.go deleted file mode 100644 index 7d043ab4b..000000000 --- a/internal/kms/repository_token_key.go +++ /dev/null @@ -1,162 +0,0 @@ -package kms - -import ( - "context" - "fmt" - "strings" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" -) - -// CreateTokenKey inserts into the repository and returns the new key and the -// key version. There are no valid options at this time. -func (r *Repository) CreateTokenKey(ctx context.Context, rkvWrapper wrapping.Wrapper, key []byte, _ ...Option) (*TokenKey, *TokenKeyVersion, error) { - const op = "kms.(Repository).CreateTokenKey" - var returnedDk, returnedDv interface{} - _, err := r.writer.DoTx( - ctx, - db.StdRetryCnt, - db.ExpBackoff{}, - func(reader db.Reader, w db.Writer) error { - var err error - if returnedDk, returnedDv, err = createTokenKeyTx(ctx, reader, w, rkvWrapper, key); err != nil { - return errors.Wrap(ctx, err, op) - } - return nil - }, - ) - if err != nil { - return nil, nil, errors.Wrap(ctx, err, op) - } - return returnedDk.(*TokenKey), returnedDv.(*TokenKeyVersion), nil -} - -// createTokenKeyTx inserts into the db (via db.Writer) and returns the new key -// and the key version. This function encapsulates all the work required within -// a db.TxHandler and allows this capability to be shared with the iam repo. -func createTokenKeyTx(ctx context.Context, r db.Reader, w db.Writer, rkvWrapper wrapping.Wrapper, key []byte) (*TokenKey, *TokenKeyVersion, error) { - const op = "kms.createTokenKeyTx" - if rkvWrapper == nil { - return nil, nil, errors.New(ctx, errors.InvalidParameter, op, "missing key wrapper") - } - if len(key) == 0 { - return nil, nil, errors.New(ctx, errors.InvalidParameter, op, "missing key") - } - rootKeyVersionId, err := rkvWrapper.KeyId(ctx) - if err != nil { - return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to lookup root key id")) - } - switch { - case !strings.HasPrefix(rootKeyVersionId, RootKeyVersionPrefix): - return nil, nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("root key version id %s doesn't start with prefix %s", rootKeyVersionId, RootKeyVersionPrefix)) - case rootKeyVersionId == "": - return nil, nil, errors.New(ctx, errors.InvalidParameter, op, "missing root key version id") - } - rv := AllocRootKeyVersion() - rv.PrivateId = rootKeyVersionId - if err := r.LookupById(ctx, &rv); err != nil { - return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("unable to lookup root key version %s", rootKeyVersionId))) - } - - tk := AllocTokenKey() - tv := AllocTokenKeyVersion() - id, err := newTokenKeyId() - if err != nil { - return nil, nil, errors.Wrap(ctx, err, op) - } - tk.PrivateId = id - tk.RootKeyId = rv.RootKeyId - - id, err = newTokenKeyVersionId() - if err != nil { - return nil, nil, errors.Wrap(ctx, err, op) - } - tv.PrivateId = id - tv.TokenKeyId = tk.PrivateId - tv.RootKeyVersionId = rootKeyVersionId - tv.Key = key - if err := tv.Encrypt(ctx, rkvWrapper); err != nil { - return nil, nil, errors.Wrap(ctx, err, op) - } - - // no token entries for keys - if err := w.Create(ctx, &tk); err != nil { - return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg("keys create")) - } - // no token entries for key versions - if err := w.Create(ctx, &tv); err != nil { - return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg("key versions create")) - } - - return &tk, &tv, nil -} - -// LookupTokenKey will look up a key in the repository. If the key is not -// found, it will return nil, nil. -func (r *Repository) LookupTokenKey(ctx context.Context, privateId string, _ ...Option) (*TokenKey, error) { - const op = "kms.(Repository).LookupTokenKey" - if privateId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - k := AllocTokenKey() - k.PrivateId = privateId - if err := r.reader.LookupById(ctx, &k); err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - return &k, nil -} - -// DeleteTokenKey deletes the key for the provided id from the -// repository returning a count of the number of records deleted. All options -// are ignored. -func (r *Repository) DeleteTokenKey(ctx context.Context, privateId string, _ ...Option) (int, error) { - const op = "kms.(Repository).DeleteTokenKey" - if privateId == "" { - return db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - k := AllocTokenKey() - k.PrivateId = privateId - if err := r.reader.LookupById(ctx, &k); err != nil { - return db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - - var rowsDeleted int - _, err := r.writer.DoTx( - ctx, - db.StdRetryCnt, - db.ExpBackoff{}, - func(_ db.Reader, w db.Writer) (err error) { - dk := k.Clone() - // no token entries for root keys - rowsDeleted, err = w.Delete(ctx, dk) - if err != nil { - return errors.Wrap(ctx, err, op) - } - if rowsDeleted > 1 { - return errors.New(ctx, errors.MultipleRecords, op, "more than 1 resource would have been deleted") - } - return nil - }, - ) - if err != nil { - return db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - return rowsDeleted, nil -} - -// ListTokenKeys will list the keys. Supports the WithLimit option. -func (r *Repository) ListTokenKeys(ctx context.Context, opt ...Option) ([]Dek, error) { - const op = "kms.(Repository).ListTokenKeys" - var keys []*TokenKey - err := r.list(ctx, &keys, "1=1", nil, opt...) - if err != nil { - return nil, errors.Wrap(ctx, err, op) - } - deks := make([]Dek, 0, len(keys)) - for _, key := range keys { - deks = append(deks, key) - } - return deks, nil -} diff --git a/internal/kms/repository_token_key_test.go b/internal/kms/repository_token_key_test.go deleted file mode 100644 index 308fb4e4e..000000000 --- a/internal/kms/repository_token_key_test.go +++ /dev/null @@ -1,295 +0,0 @@ -package kms_test - -import ( - "context" - "testing" - "time" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/iam" - "github.com/hashicorp/boundary/internal/kms" - "github.com/hashicorp/boundary/internal/oplog" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" - aead "github.com/hashicorp/go-kms-wrapping/v2/aead" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" -) - -func TestRepository_CreateTokenKey(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - - type args struct { - scopeId string - key []byte - keyWrapper wrapping.Wrapper - opt []kms.Option - } - tests := []struct { - name string - args args - wantErr bool - wantIsError errors.Code - }{ - { - name: "valid-org", - args: args{ - scopeId: org.PublicId, - key: []byte("test key"), - keyWrapper: rkvWrapper, - }, - wantErr: false, - }, - { - name: "nil-key", - args: args{ - scopeId: org.PublicId, - keyWrapper: rkvWrapper, - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "empty-key", - args: args{ - scopeId: org.PublicId, - keyWrapper: rkvWrapper, - key: []byte(""), - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "nil-wrapper", - args: args{ - scopeId: org.PublicId, - key: []byte("test key"), - keyWrapper: nil, - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "not-rkv-wrapper", - args: args{ - scopeId: org.PublicId, - key: []byte("test key"), - keyWrapper: wrapper, - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "wrapper-missing-id", - args: args{ - scopeId: org.PublicId, - key: []byte("test key"), - keyWrapper: func() wrapping.Wrapper { - w := db.TestWrapper(t) - _, err = w.(*aead.Wrapper).SetConfig(context.Background()) - require.NoError(t, err) - return w - }(), - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - tk, tv, err := repo.CreateTokenKey(context.Background(), tt.args.keyWrapper, tt.args.key, tt.args.opt...) - if tt.wantErr { - assert.Error(err) - assert.Nil(tk) - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - return - } - require.NoError(err) - assert.NotNil(tk.CreateTime) - foundKey, err := repo.LookupTokenKey(context.Background(), tk.PrivateId) - assert.NoError(err) - assert.True(proto.Equal(foundKey, tk)) - - // make sure there was no token written - err = db.TestVerifyOplog(t, rw, tk.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_CREATE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - - assert.NotNil(tv.CreateTime) - foundKeyVersion, err := repo.LookupTokenKeyVersion(context.Background(), tt.args.keyWrapper, tv.PrivateId) - assert.NoError(err) - assert.True(proto.Equal(foundKeyVersion, tv)) - - // make sure there was no token written - err = db.TestVerifyOplog(t, rw, tv.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_CREATE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestRepository_DeleteTokenKey(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - - type args struct { - key *kms.TokenKey - opt []kms.Option - } - tests := []struct { - name string - args args - wantRowsDeleted int - wantErr bool - wantIsError errors.Code - }{ - { - name: "valid", - args: args{ - key: kms.TestTokenKey(t, conn, rk.PrivateId), - }, - wantRowsDeleted: 1, - wantErr: false, - }, - { - name: "no-private-id", - args: args{ - key: func() *kms.TokenKey { - k := kms.AllocTokenKey() - return &k - }(), - }, - wantRowsDeleted: 0, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "not-found", - args: args{ - key: func() *kms.TokenKey { - id, err := db.NewPublicId(kms.RootKeyPrefix) - require.NoError(t, err) - k := kms.AllocTokenKey() - k.PrivateId = id - require.NoError(t, err) - return &k - }(), - }, - wantRowsDeleted: 0, - wantErr: true, - wantIsError: errors.RecordNotFound, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - deletedRows, err := repo.DeleteTokenKey(context.Background(), tt.args.key.PrivateId, tt.args.opt...) - if tt.wantErr { - require.Error(err) - assert.Equal(0, deletedRows) - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - // make sure there was no token written - err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - return - } - require.NoError(err) - assert.Equal(tt.wantRowsDeleted, deletedRows) - foundKey, err := repo.LookupTokenKey(context.Background(), tt.args.key.PrivateId) - assert.Error(err) - assert.Nil(foundKey) - assert.True(errors.IsNotFoundError(err)) - - // make sure there was no token written - err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestRepository_ListTokenKeys(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - const testLimit = 10 - rw := db.New(conn) - repo, err := kms.NewRepository(rw, rw, kms.WithLimit(testLimit)) - require.NoError(t, err) - wrapper := db.TestWrapper(t) - - type args struct { - opt []kms.Option - } - tests := []struct { - name string - createCnt int - args args - wantCnt int - wantErr bool - }{ - { - name: "no-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{ - opt: []kms.Option{kms.WithLimit(-1)}, - }, - wantCnt: repo.DefaultLimit() + 1, // org and project both have keys, plus global scope - wantErr: false, - }, - { - name: "default-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{}, - wantCnt: repo.DefaultLimit(), - wantErr: false, - }, - { - name: "custom-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{ - opt: []kms.Option{kms.WithLimit(3)}, - }, - wantCnt: 3, - wantErr: false, - }, - } - for _, tt := range tests { - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - for i := 0; i < tt.createCnt; i++ { - org, proj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "scope_id in(?)", "global", org.PublicId, proj.PublicId) - rk := kms.TestRootKey(t, conn, proj.PublicId) - kms.TestTokenKey(t, conn, rk.PrivateId) - require.NoError(err) - } - got, err := repo.ListTokenKeys(context.Background(), tt.args.opt...) - if tt.wantErr { - require.Error(err) - return - } - require.NoError(err) - assert.Equal(tt.wantCnt, len(got)) - }) - } -} diff --git a/internal/kms/repository_token_key_version.go b/internal/kms/repository_token_key_version.go deleted file mode 100644 index 4c612bd5d..000000000 --- a/internal/kms/repository_token_key_version.go +++ /dev/null @@ -1,176 +0,0 @@ -package kms - -import ( - "context" - "fmt" - "strings" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" -) - -// CreateTokenKeyVersion inserts into the repository and returns the new key -// version with its PrivateId. There are no valid options at this time. -func (r *Repository) CreateTokenKeyVersion(ctx context.Context, rkvWrapper wrapping.Wrapper, tokenKeyId string, key []byte, _ ...Option) (*TokenKeyVersion, error) { - const op = "kms.(Repository).CreateTokenKeyVersion" - if rkvWrapper == nil { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing root key version wrapper") - } - rootKeyVersionId, err := rkvWrapper.KeyId(ctx) - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to fetch key id")) - } - switch { - case !strings.HasPrefix(rootKeyVersionId, RootKeyVersionPrefix): - return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("root key version id %s doesn't start with prefix %s", rootKeyVersionId, RootKeyVersionPrefix)) - case rootKeyVersionId == "": - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing root key version id") - } - if tokenKeyId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing token key id") - } - if len(key) == 0 { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing key") - } - kv := AllocTokenKeyVersion() - id, err := newTokenKeyVersionId() - if err != nil { - return nil, errors.Wrap(ctx, err, op) - } - kv.PrivateId = id - kv.RootKeyVersionId = rootKeyVersionId - kv.Key = key - kv.TokenKeyId = tokenKeyId - if err := kv.Encrypt(ctx, rkvWrapper); err != nil { - return nil, errors.Wrap(ctx, err, op) - } - - var returnedKey interface{} - _, err = r.writer.DoTx( - ctx, - db.StdRetryCnt, - db.ExpBackoff{}, - func(_ db.Reader, w db.Writer) error { - returnedKey = kv.Clone() - // no token entries for root key version - if err := w.Create(ctx, returnedKey); err != nil { - return errors.Wrap(ctx, err, op) - } - return nil - }, - ) - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s token key id", kv.TokenKeyId))) - } - return returnedKey.(*TokenKeyVersion), nil -} - -// LookupTokenKeyVersion will look up a key version in the repository. If -// the key version is not found, it will return nil, nil. -func (r *Repository) LookupTokenKeyVersion(ctx context.Context, keyWrapper wrapping.Wrapper, privateId string, _ ...Option) (*TokenKeyVersion, error) { - const op = "kms.(Repository).LookupTokenKeyVersion" - if privateId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - if keyWrapper == nil { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing key wrapper") - } - k := AllocTokenKeyVersion() - k.PrivateId = privateId - if err := r.reader.LookupById(ctx, &k); err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - if err := k.Decrypt(ctx, keyWrapper); err != nil { - return nil, errors.Wrap(ctx, err, op) - } - return &k, nil -} - -// DeleteTokenKeyVersion deletes the key version for the provided id from the -// repository returning a count of the number of records deleted. All options -// are ignored. -func (r *Repository) DeleteTokenKeyVersion(ctx context.Context, privateId string, _ ...Option) (int, error) { - const op = "kms.(Repository).DeleteTokenKeyVersion" - if privateId == "" { - return db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - k := AllocTokenKeyVersion() - k.PrivateId = privateId - if err := r.reader.LookupById(ctx, &k); err != nil { - return db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - - var rowsDeleted int - _, err := r.writer.DoTx( - ctx, - db.StdRetryCnt, - db.ExpBackoff{}, - func(_ db.Reader, w db.Writer) (err error) { - dk := k.Clone() - // no token entries for the key version - rowsDeleted, err = w.Delete(ctx, dk) - if err != nil { - return errors.Wrap(ctx, err, op) - } - if rowsDeleted > 1 { - return errors.New(ctx, errors.MultipleRecords, op, "more than 1 resource would have been deleted") - } - return nil - }, - ) - if err != nil { - return db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) - } - return rowsDeleted, nil -} - -// LatestTokenKeyVersion searches for the key version with the highest -// version number. When no results are found, it returns nil with an -// errors.RecordNotFound error. -func (r *Repository) LatestTokenKeyVersion(ctx context.Context, rkvWrapper wrapping.Wrapper, tokenKeyId string, _ ...Option) (*TokenKeyVersion, error) { - const op = "kms.(Repository).LatestTokenKeyVersion" - if tokenKeyId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing token key id") - } - if rkvWrapper == nil { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing root key version wrapper") - } - var foundKeys []*TokenKeyVersion - if err := r.reader.SearchWhere(ctx, &foundKeys, "token_key_id = ?", []interface{}{tokenKeyId}, db.WithLimit(1), db.WithOrder("version desc")); err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", tokenKeyId))) - } - if len(foundKeys) == 0 { - return nil, errors.E(ctx, errors.WithCode(errors.RecordNotFound), errors.WithOp(op)) - } - if err := foundKeys[0].Decrypt(ctx, rkvWrapper); err != nil { - return nil, errors.Wrap(ctx, err, op) - } - return foundKeys[0], nil -} - -// ListTokenKeyVersions will lists versions of a key. Supports the WithLimit option. -func (r *Repository) ListTokenKeyVersions(ctx context.Context, rkvWrapper wrapping.Wrapper, tokenKeyId string, opt ...Option) ([]DekVersion, error) { - const op = "kms.(Repository).ListTokenKeyVersions" - if tokenKeyId == "" { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing token key id") - } - if rkvWrapper == nil { - return nil, errors.New(ctx, errors.InvalidParameter, op, "missing root key version wrapper") - } - var versions []*TokenKeyVersion - err := r.list(ctx, &versions, "token_key_id = ?", []interface{}{tokenKeyId}, opt...) - if err != nil { - return nil, errors.Wrap(ctx, err, op) - } - for i, k := range versions { - if err := k.Decrypt(ctx, rkvWrapper); err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("error decrypting key num %d", i))) - } - } - dekVersions := make([]DekVersion, 0, len(versions)) - for _, version := range versions { - dekVersions = append(dekVersions, version) - } - return dekVersions, nil -} diff --git a/internal/kms/repository_token_key_version_test.go b/internal/kms/repository_token_key_version_test.go deleted file mode 100644 index 204e65279..000000000 --- a/internal/kms/repository_token_key_version_test.go +++ /dev/null @@ -1,367 +0,0 @@ -package kms_test - -import ( - "context" - "testing" - "time" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/iam" - "github.com/hashicorp/boundary/internal/kms" - "github.com/hashicorp/boundary/internal/oplog" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" -) - -func TestRepository_CreateTokenKeyVersion(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - dk := kms.TestTokenKey(t, conn, rk.PrivateId) - - type args struct { - key []byte - tokenKeyId string - keyWrapper wrapping.Wrapper - opt []kms.Option - } - tests := []struct { - name string - args args - wantErr bool - wantIsError errors.Code - }{ - { - name: "valid", - args: args{ - key: []byte("test key"), - keyWrapper: rkvWrapper, - tokenKeyId: dk.PrivateId, - }, - wantErr: false, - }, - { - name: "invalid-rkv-wrapper", - args: args{ - key: []byte("test key"), - keyWrapper: wrapper, - tokenKeyId: dk.PrivateId, - }, - wantErr: true, - }, - { - name: "empty-key", - args: args{ - key: nil, - keyWrapper: wrapper, - tokenKeyId: dk.PrivateId, - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "nil-wrapper", - args: args{ - key: []byte("test key"), - keyWrapper: nil, - }, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - k, err := repo.CreateTokenKeyVersion(context.Background(), tt.args.keyWrapper, tt.args.tokenKeyId, tt.args.key, tt.args.opt...) - if tt.wantErr { - assert.Error(err) - assert.Nil(k) - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - return - } - require.NoError(err) - assert.NotNil(k.CreateTime) - foundKey, err := repo.LookupTokenKeyVersion(context.Background(), tt.args.keyWrapper, k.PrivateId) - assert.NoError(err) - assert.True(proto.Equal(foundKey, k)) - - // make sure there was no oplog written - err = db.TestVerifyOplog(t, rw, k.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_CREATE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestRepository_DeleteTokenKeyVersion(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - dk := kms.TestTokenKey(t, conn, rk.PrivateId) - - type args struct { - key *kms.TokenKeyVersion - opt []kms.Option - } - tests := []struct { - name string - args args - wantRowsDeleted int - wantErr bool - wantIsError errors.Code - }{ - { - name: "valid", - args: args{ - key: kms.TestTokenKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("token key")), - }, - wantRowsDeleted: 1, - wantErr: false, - }, - { - name: "no-private-id", - args: args{ - key: func() *kms.TokenKeyVersion { - k := kms.AllocTokenKeyVersion() - return &k - }(), - }, - wantRowsDeleted: 0, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - { - name: "not-found", - args: args{ - key: func() *kms.TokenKeyVersion { - id, err := db.NewPublicId(kms.TokenKeyPrefix) - require.NoError(t, err) - k := kms.AllocTokenKeyVersion() - k.PrivateId = id - require.NoError(t, err) - return &k - }(), - }, - wantRowsDeleted: 0, - wantErr: true, - wantIsError: errors.RecordNotFound, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - deletedRows, err := repo.DeleteTokenKeyVersion(context.Background(), tt.args.key.PrivateId, tt.args.opt...) - if tt.wantErr { - require.Error(err) - assert.Equal(0, deletedRows) - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - return - } - require.NoError(err) - assert.Equal(tt.wantRowsDeleted, deletedRows) - foundKey, err := repo.LookupTokenKeyVersion(context.Background(), wrapper, tt.args.key.PrivateId) - assert.Error(err) - assert.Nil(foundKey) - assert.True(errors.IsNotFoundError(err)) - - // make sure there was no oplog written - err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) - assert.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestRepository_LatestTokenKeyVersion(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - dk := kms.TestTokenKey(t, conn, rk.PrivateId) - - tests := []struct { - name string - createCnt int - keyWrapper wrapping.Wrapper - wantVersion uint32 - wantErr bool - wantIsError errors.Code - }{ - { - name: "5", - createCnt: 5, - keyWrapper: rkvWrapper, - wantVersion: 5, - wantErr: false, - }, - { - name: "1", - createCnt: 1, - keyWrapper: rkvWrapper, - wantVersion: 1, - wantErr: false, - }, - { - name: "0", - createCnt: 0, - keyWrapper: rkvWrapper, - wantErr: true, - wantIsError: errors.RecordNotFound, - }, - { - name: "nil-wrapper", - createCnt: 5, - keyWrapper: nil, - wantErr: true, - wantIsError: errors.InvalidParameter, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocTokenKeyVersion(); return &i }(), "1=1") - testKeys := []*kms.TokenKeyVersion{} - for i := 0; i < tt.createCnt; i++ { - k := kms.TestTokenKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("test key")) - testKeys = append(testKeys, k) - } - assert.Equal(tt.createCnt, len(testKeys)) - got, err := repo.LatestTokenKeyVersion(context.Background(), tt.keyWrapper, dk.PrivateId) - if tt.wantErr { - require.Error(err) - assert.Nil(got) - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - return - } - require.NoError(err) - require.NotNil(got) - assert.Equal(tt.wantVersion, got.Version) - }) - } -} - -func TestRepository_ListTokenKeyVersions(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - const testLimit = 10 - rw := db.New(conn) - wrapper := db.TestWrapper(t) - repo, err := kms.NewRepository(rw, rw, kms.WithLimit(testLimit)) - require.NoError(t, err) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - dk := kms.TestTokenKey(t, conn, rk.PrivateId) - - type args struct { - tokenKeyId string - keyWrapper wrapping.Wrapper - opt []kms.Option - } - tests := []struct { - name string - createCnt int - args args - wantCnt int - wantErr bool - }{ - { - name: "no-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{ - tokenKeyId: dk.PrivateId, - keyWrapper: rkvWrapper, - opt: []kms.Option{kms.WithLimit(-1)}, - }, - wantCnt: repo.DefaultLimit() + 1, - wantErr: false, - }, - { - name: "default-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{ - keyWrapper: rkvWrapper, - tokenKeyId: dk.PrivateId, - }, - wantCnt: repo.DefaultLimit(), - wantErr: false, - }, - { - name: "custom-limit", - createCnt: repo.DefaultLimit() + 1, - args: args{ - keyWrapper: rkvWrapper, - tokenKeyId: dk.PrivateId, - opt: []kms.Option{kms.WithLimit(3)}, - }, - wantCnt: 3, - wantErr: false, - }, - { - name: "bad-org", - createCnt: 1, - args: args{ - keyWrapper: rkvWrapper, - tokenKeyId: "bad-id", - }, - wantCnt: 0, - wantErr: false, - }, - { - name: "nil-wrapper", - createCnt: 1, - args: args{ - keyWrapper: nil, - tokenKeyId: dk.PrivateId, - }, - wantCnt: 0, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocTokenKeyVersion(); return &i }(), "1=1") - keyVersions := []*kms.TokenKeyVersion{} - for i := 0; i < tt.createCnt; i++ { - k := kms.TestTokenKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("token key")) - keyVersions = append(keyVersions, k) - } - assert.Equal(tt.createCnt, len(keyVersions)) - got, err := repo.ListTokenKeyVersions(context.Background(), tt.args.keyWrapper, tt.args.tokenKeyId, tt.args.opt...) - if tt.wantErr { - require.Error(err) - return - } - require.NoError(err) - assert.Equal(tt.wantCnt, len(got)) - }) - } -} diff --git a/internal/kms/root_key.go b/internal/kms/root_key.go deleted file mode 100644 index f98049487..000000000 --- a/internal/kms/root_key.go +++ /dev/null @@ -1,84 +0,0 @@ -package kms - -import ( - "context" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/kms/store" - "google.golang.org/protobuf/proto" -) - -const ( - DefaultRootKeyTableName = "kms_root_key" -) - -type RootKey struct { - *store.RootKey - tableName string `gorm:"-"` -} - -// NewRootKey creates a new in memory root key. ScopeId must be -// for a global or org scope, but the scope type validation will be deferred -// until the in memory root key is written to the database. No options -// are currently supported. -func NewRootKey(scopeId string, _ ...Option) (*RootKey, error) { - const op = "kms.NewRootKey" - if scopeId == "" { - return nil, errors.NewDeprecated(errors.InvalidParameter, op, "missing scope id") - } - c := &RootKey{ - RootKey: &store.RootKey{ - ScopeId: scopeId, - }, - } - return c, nil -} - -// AllocRootKey will allocate a root key -func AllocRootKey() RootKey { - return RootKey{ - RootKey: &store.RootKey{}, - } -} - -// Clone creates a clone of the RootKey -func (k *RootKey) Clone() interface{} { - cp := proto.Clone(k.RootKey) - return &RootKey{ - RootKey: cp.(*store.RootKey), - } -} - -// VetForWrite implements db.VetForWrite() interface and validates the key -// before it's written. -func (k *RootKey) VetForWrite(ctx context.Context, _ db.Reader, opType db.OpType, _ ...db.Option) error { - const op = "kms.(RootKey).VetForWrite" - if k.PrivateId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - switch opType { - case db.CreateOp: - if k.ScopeId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "missing scope id") - } - case db.UpdateOp: - return errors.New(ctx, errors.InvalidParameter, op, "key is immutable") - } - return nil -} - -// TableName returns the tablename to override the default gorm table name -func (k *RootKey) TableName() string { - if k.tableName != "" { - return k.tableName - } - return DefaultRootKeyTableName -} - -// SetTableName sets the tablename and satisfies the ReplayableMessage -// interface. If the caller attempts to set the name to "" the name will be -// reset to the default name. -func (c *RootKey) SetTableName(n string) { - c.tableName = n -} diff --git a/internal/kms/root_key_test.go b/internal/kms/root_key_test.go deleted file mode 100644 index d364cd627..000000000 --- a/internal/kms/root_key_test.go +++ /dev/null @@ -1,210 +0,0 @@ -package kms_test - -import ( - "context" - "testing" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/iam" - "github.com/hashicorp/boundary/internal/kms" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" -) - -// NOTE: there are no update tests since all the RootKey attributes are -// immutable and those tests are covered by TestRootKey_ImmutableFields - -func TestRootKey_Create(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - type args struct { - scopeId string - opt []kms.Option - } - tests := []struct { - name string - args args - want *kms.RootKey - wantErr bool - wantIsErr errors.Code - create bool - wantCreateErr bool - }{ - { - name: "empty-scopeId", - args: args{}, - wantErr: true, - wantIsErr: errors.InvalidParameter, - }, - { - name: "valid-org-config", - args: args{ - scopeId: org.PublicId, - }, - want: func() *kms.RootKey { - k := kms.AllocRootKey() - k.ScopeId = org.PublicId - return &k - }(), - create: true, - }, - { - name: "valid-global-config", - args: args{ - scopeId: "global", - }, - want: func() *kms.RootKey { - k := kms.AllocRootKey() - k.ScopeId = "global" - return &k - }(), - create: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - got, err := kms.NewRootKey(tt.args.scopeId, tt.args.opt...) - if tt.wantErr { - require.Error(err) - assert.True(errors.Match(errors.T(tt.wantIsErr), err)) - return - } - require.NoError(err) - assert.Equal(tt.want, got) - if tt.create { - id, err := db.NewPublicId(kms.RootKeyPrefix) - require.NoError(err) - got.PrivateId = id - err = db.New(conn).Create(context.Background(), got) - if tt.wantCreateErr { - assert.Error(err) - return - } else { - assert.NoError(err) - } - } - }) - } -} - -func TestRootKey_Delete(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - - tests := []struct { - name string - key *kms.RootKey - wantRowsDeleted int - wantErr bool - wantErrMsg string - }{ - { - name: "valid", - key: kms.TestRootKey(t, conn, org.PublicId), - wantErr: false, - wantRowsDeleted: 1, - }, - { - name: "bad-id", - key: func() *kms.RootKey { - k := kms.AllocRootKey() - id, err := db.NewPublicId(kms.RootKeyPrefix) - require.NoError(t, err) - k.PrivateId = id - k.ScopeId = org.PublicId - return &k - }(), - wantErr: false, - wantRowsDeleted: 0, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - deleteKey := kms.AllocRootKey() - deleteKey.PrivateId = tt.key.PrivateId - deletedRows, err := rw.Delete(context.Background(), &deleteKey) - if tt.wantErr { - require.Error(err) - return - } - require.NoError(err) - if tt.wantRowsDeleted == 0 { - assert.Equal(tt.wantRowsDeleted, deletedRows) - return - } - assert.Equal(tt.wantRowsDeleted, deletedRows) - foundKey := kms.AllocRootKey() - foundKey.PrivateId = tt.key.PrivateId - err = rw.LookupById(context.Background(), &foundKey) - require.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestRootKey_Clone(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - t.Run("valid", func(t *testing.T) { - assert := assert.New(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - k := kms.TestRootKey(t, conn, org.PublicId) - cp := k.Clone() - assert.True(proto.Equal(cp.(*kms.RootKey).RootKey, k.RootKey)) - }) - t.Run("not-equal", func(t *testing.T) { - assert := assert.New(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - org2, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - k := kms.TestRootKey(t, conn, org.PublicId) - k2 := kms.TestRootKey(t, conn, org2.PublicId) - - cp := k.Clone() - assert.True(!proto.Equal(cp.(*kms.RootKey).RootKey, k2.RootKey)) - }) -} - -func TestRootKey_SetTableName(t *testing.T) { - t.Parallel() - defaultTableName := kms.DefaultRootKeyTableName - tests := []struct { - name string - setNameTo string - want string - }{ - { - name: "new-name", - setNameTo: "new-name", - want: "new-name", - }, - { - name: "reset to default", - setNameTo: "", - want: defaultTableName, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - def := kms.AllocRootKey() - require.Equal(defaultTableName, def.TableName()) - s := kms.AllocRootKey() - s.SetTableName(tt.setNameTo) - assert.Equal(tt.want, s.TableName()) - }) - } -} diff --git a/internal/kms/root_key_version.go b/internal/kms/root_key_version.go deleted file mode 100644 index a6cba9469..000000000 --- a/internal/kms/root_key_version.go +++ /dev/null @@ -1,114 +0,0 @@ -package kms - -import ( - "context" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/kms/store" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" - "github.com/hashicorp/go-kms-wrapping/v2/extras/structwrapping" - "google.golang.org/protobuf/proto" -) - -const ( - DefaultRootKeyVersionTableName = "kms_root_key_version" -) - -type RootKeyVersion struct { - *store.RootKeyVersion - tableName string `gorm:"-"` -} - -// NewRootKeyVersion creates a new in memory root key version. No options are -// currently supported. -func NewRootKeyVersion(rootKeyId string, key []byte, _ ...Option) (*RootKeyVersion, error) { - const op = "kms.NewRootKeyVersion" - if rootKeyId == "" { - return nil, errors.NewDeprecated(errors.InvalidParameter, op, "missing root key id") - } - if len(key) == 0 { - return nil, errors.NewDeprecated(errors.InvalidParameter, op, "missing key") - } - - k := &RootKeyVersion{ - RootKeyVersion: &store.RootKeyVersion{ - RootKeyId: rootKeyId, - Key: key, - }, - } - return k, nil -} - -// AllocRootKeyVersion allocates a RootKeyVersion -func AllocRootKeyVersion() RootKeyVersion { - return RootKeyVersion{ - RootKeyVersion: &store.RootKeyVersion{}, - } -} - -// Clone creates a clone of the RootKeyVersion -func (k *RootKeyVersion) Clone() interface{} { - cp := proto.Clone(k.RootKeyVersion) - return &RootKeyVersion{ - RootKeyVersion: cp.(*store.RootKeyVersion), - } -} - -// VetForWrite implements db.VetForWrite() interface and validates the root key -// version before it's written. -func (k *RootKeyVersion) VetForWrite(ctx context.Context, _ db.Reader, opType db.OpType, _ ...db.Option) error { - const op = "kms.(RootKeyVersion).VetForWrite" - if k.PrivateId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - switch opType { - case db.CreateOp: - if k.CtKey == nil { - return errors.New(ctx, errors.InvalidParameter, op, "missing key") - } - if k.RootKeyId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "missing root key id") - } - case db.UpdateOp: - return errors.New(ctx, errors.InvalidParameter, op, "key is immutable") - } - return nil -} - -// TableName returns the tablename to override the default gorm table name -func (k *RootKeyVersion) TableName() string { - if k.tableName != "" { - return k.tableName - } - return DefaultRootKeyVersionTableName -} - -// SetTableName sets the tablename and satisfies the ReplayableMessage -// interface. If the caller attempts to set the name to "" the name will be -// reset to the default name. -func (k *RootKeyVersion) SetTableName(n string) { - k.tableName = n -} - -// Encrypt will encrypt the root key version's key -func (k *RootKeyVersion) Encrypt(ctx context.Context, cipher wrapping.Wrapper) error { - const op = "kms.(RootKeyVersion).Encrypt" - // structwrapping doesn't support embedding, so we'll pass in the - // store.RootKey directly - if err := structwrapping.WrapStruct(ctx, cipher, k.RootKeyVersion, nil); err != nil { - return errors.Wrap(ctx, err, op, errors.WithCode(errors.Encrypt)) - } - return nil -} - -// Decrypt will decrypt the root key version's key -func (k *RootKeyVersion) Decrypt(ctx context.Context, cipher wrapping.Wrapper) error { - const op = "kms.(RootKeyVersion).Decrypt" - // structwrapping doesn't support embedding, so we'll pass in the - // store.RootKeyVersion directly - if err := structwrapping.UnwrapStruct(ctx, cipher, k.RootKeyVersion, nil); err != nil { - return errors.Wrap(ctx, err, op, errors.WithCode(errors.Decrypt)) - } - return nil -} diff --git a/internal/kms/root_key_version_test.go b/internal/kms/root_key_version_test.go deleted file mode 100644 index 36a2a6c1e..000000000 --- a/internal/kms/root_key_version_test.go +++ /dev/null @@ -1,219 +0,0 @@ -package kms_test - -import ( - "context" - "testing" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/iam" - "github.com/hashicorp/boundary/internal/kms" - "github.com/hashicorp/boundary/internal/kms/store" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" -) - -// NOTE: there are no update tests since all the RootKeyVersion attributes are -// immutable and those tests are covered by TestRootKeyVersion_ImmutableFields - -func TestRootKeyVersion_Create(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rootKey := kms.TestRootKey(t, conn, org.PublicId) - type args struct { - rootId string - key []byte - opt []kms.Option - } - tests := []struct { - name string - args args - want *kms.RootKeyVersion - wantErr bool - wantIsErr errors.Code - create bool - wantCreateErr bool - }{ - { - name: "empty-root-id", - args: args{ - key: []byte("test key"), - }, - wantErr: true, - wantIsErr: errors.InvalidParameter, - }, - { - name: "empty-key", - args: args{ - rootId: rootKey.PrivateId, - }, - wantErr: true, - wantIsErr: errors.InvalidParameter, - }, - { - name: "valid", - args: args{ - rootId: rootKey.PrivateId, - key: []byte("test key"), - }, - want: func() *kms.RootKeyVersion { - k := kms.AllocRootKeyVersion() - k.RootKeyId = rootKey.PrivateId - k.Key = []byte("test key") - return &k - }(), - create: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKeyVersion(); return &i }(), "1=1") - got, err := kms.NewRootKeyVersion(tt.args.rootId, tt.args.key, tt.args.opt...) - if tt.wantErr { - require.Error(err) - assert.True(errors.Match(errors.T(tt.wantIsErr), err)) - return - } - require.NoError(err) - assert.Equal(tt.want, got) - if tt.create { - id, err := db.NewPublicId(kms.RootKeyVersionPrefix) - require.NoError(err) - got.PrivateId = id - err = got.Encrypt(context.Background(), wrapper) - require.NoError(err) - err = db.New(conn).Create(context.Background(), got) - if tt.wantCreateErr { - assert.Error(err) - return - } else { - assert.NoError(err) - } - assert.Equal(uint32(1), got.Version) - } - }) - } -} - -func TestRootKeyVersion_Delete(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - rw := db.New(conn) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - - tests := []struct { - name string - key *kms.RootKeyVersion - wantRowsDeleted int - wantErr bool - wantErrMsg string - }{ - { - name: "valid", - key: func() *kms.RootKeyVersion { k, _ := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId); return k }(), - wantErr: false, - wantRowsDeleted: 1, - }, - { - name: "bad-id", - key: func() *kms.RootKeyVersion { - k := kms.AllocRootKeyVersion() - id, err := db.NewPublicId(kms.RootKeyVersionPrefix) - require.NoError(t, err) - k.PrivateId = id - return &k - }(), - wantErr: false, - wantRowsDeleted: 0, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - deleteKey := kms.AllocRootKeyVersion() - deleteKey.PrivateId = tt.key.PrivateId - deletedRows, err := rw.Delete(context.Background(), &deleteKey) - if tt.wantErr { - require.Error(err) - return - } - require.NoError(err) - if tt.wantRowsDeleted == 0 { - assert.Equal(tt.wantRowsDeleted, deletedRows) - return - } - assert.Equal(tt.wantRowsDeleted, deletedRows) - foundKey := kms.AllocRootKey() - foundKey.PrivateId = tt.key.PrivateId - err = rw.LookupById(context.Background(), &foundKey) - require.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestRootKeyVersion_Clone(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - t.Run("valid", func(t *testing.T) { - assert := assert.New(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - k, _ := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - cp := k.Clone() - assert.True(proto.Equal(cp.(*kms.RootKeyVersion).RootKeyVersion, k.RootKeyVersion)) - }) - t.Run("not-equal", func(t *testing.T) { - assert := assert.New(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - k, _ := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - k2, _ := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - cp := k.Clone() - assert.True(!proto.Equal(cp.(*kms.RootKeyVersion).RootKeyVersion, k2.RootKeyVersion)) - }) -} - -func TestRootKeyVersion_SetTableName(t *testing.T) { - t.Parallel() - defaultTableName := kms.DefaultRootKeyVersionTableName - tests := []struct { - name string - setNameTo string - want string - }{ - { - name: "new-name", - setNameTo: "new-name", - want: "new-name", - }, - { - name: "reset to default", - setNameTo: "", - want: defaultTableName, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - def := kms.AllocRootKeyVersion() - require.Equal(defaultTableName, def.TableName()) - s := &kms.RootKeyVersion{ - RootKeyVersion: &store.RootKeyVersion{}, - } - s.SetTableName(tt.setNameTo) - assert.Equal(tt.want, s.TableName()) - }) - } -} diff --git a/internal/kms/session_key.go b/internal/kms/session_key.go deleted file mode 100644 index 21105afe2..000000000 --- a/internal/kms/session_key.go +++ /dev/null @@ -1,79 +0,0 @@ -package kms - -import ( - "context" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/kms/store" - "google.golang.org/protobuf/proto" -) - -const ( - DefaultSessionKeyTableName = "kms_session_key" -) - -type SessionKey struct { - *store.SessionKey - tableName string `gorm:"-"` -} - -// NewSessionKey creates a new in memory key. No options -// are currently supported. -func NewSessionKey(rootKeyId string, _ ...Option) (*SessionKey, error) { - const op = "kms.NewSessionKey" - if rootKeyId == "" { - return nil, errors.NewDeprecated(errors.InvalidParameter, op, "missing root key id") - } - c := &SessionKey{ - SessionKey: &store.SessionKey{ - RootKeyId: rootKeyId, - }, - } - return c, nil -} - -// AllocSessionKey will allocate a key -func AllocSessionKey() SessionKey { - return SessionKey{ - SessionKey: &store.SessionKey{}, - } -} - -// Clone creates a clone of the key -func (k *SessionKey) Clone() interface{} { - cp := proto.Clone(k.SessionKey) - return &SessionKey{ - SessionKey: cp.(*store.SessionKey), - } -} - -// VetForWrite implements db.VetForWrite() interface and validates the key -// before it's written. -func (k *SessionKey) VetForWrite(ctx context.Context, _ db.Reader, opType db.OpType, _ ...db.Option) error { - const op = "kms.(SessionKey).VetForWrite" - if k.PrivateId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - if opType == db.CreateOp { - if k.RootKeyId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "missing root key id") - } - } - return nil -} - -// TableName returns the tablename to override the default gorm table name -func (k *SessionKey) TableName() string { - if k.tableName != "" { - return k.tableName - } - return DefaultSessionKeyTableName -} - -// SetTableName sets the tablename and satisfies the ReplayableMessage -// interface. If the caller attempts to set the name to "" the name will be -// reset to the default name. -func (k *SessionKey) SetTableName(n string) { - k.tableName = n -} diff --git a/internal/kms/session_key_test.go b/internal/kms/session_key_test.go deleted file mode 100644 index b5c5b8e95..000000000 --- a/internal/kms/session_key_test.go +++ /dev/null @@ -1,206 +0,0 @@ -package kms_test - -import ( - "context" - "testing" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/iam" - "github.com/hashicorp/boundary/internal/kms" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" -) - -// NOTE: there are no update tests since all the SessionKey attributes are -// immutable and those tests are covered by TestSessionKey_ImmutableFields - -func TestSessionKey_Create(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - - type args struct { - rootKeyId string - opt []kms.Option - } - tests := []struct { - name string - args args - want *kms.SessionKey - wantErr bool - wantIsErr errors.Code - create bool - wantCreateErr bool - }{ - { - name: "empty-rootKeyId", - args: args{}, - wantErr: true, - wantIsErr: errors.InvalidParameter, - }, - { - name: "valid", - args: args{ - rootKeyId: rk.PrivateId, - }, - want: func() *kms.SessionKey { - k := kms.AllocSessionKey() - k.RootKeyId = rk.PrivateId - return &k - }(), - create: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocSessionKey(); return &i }(), "1=1") - got, err := kms.NewSessionKey(tt.args.rootKeyId, tt.args.opt...) - if tt.wantErr { - require.Error(err) - assert.True(errors.Match(errors.T(tt.wantIsErr), err)) - return - } - require.NoError(err) - assert.Equal(tt.want, got) - if tt.create { - id, err := db.NewPublicId(kms.SessionKeyPrefix) - require.NoError(err) - got.PrivateId = id - err = db.New(conn).Create(context.Background(), got) - if tt.wantCreateErr { - assert.Error(err) - return - } else { - assert.NoError(err) - } - } - }) - } -} - -func TestSessionKey_Delete(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocSessionKey(); return &i }(), "1=1") - - tests := []struct { - name string - key *kms.SessionKey - wantRowsDeleted int - wantErr bool - wantErrMsg string - }{ - { - name: "valid", - key: kms.TestSessionKey(t, conn, rk.PrivateId), - wantErr: false, - wantRowsDeleted: 1, - }, - { - name: "bad-id", - key: func() *kms.SessionKey { - k := kms.AllocSessionKey() - id, err := db.NewPublicId(kms.SessionKeyPrefix) - require.NoError(t, err) - k.PrivateId = id - k.RootKeyId = rk.PrivateId - return &k - }(), - wantErr: false, - wantRowsDeleted: 0, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - deleteKey := kms.AllocSessionKey() - deleteKey.PrivateId = tt.key.PrivateId - deletedRows, err := rw.Delete(context.Background(), &deleteKey) - if tt.wantErr { - require.Error(err) - return - } - require.NoError(err) - if tt.wantRowsDeleted == 0 { - assert.Equal(tt.wantRowsDeleted, deletedRows) - return - } - assert.Equal(tt.wantRowsDeleted, deletedRows) - foundKey := kms.AllocSessionKey() - foundKey.PrivateId = tt.key.PrivateId - err = rw.LookupById(context.Background(), &foundKey) - require.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestSessionKey_Clone(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - t.Run("valid", func(t *testing.T) { - assert := assert.New(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - k := kms.TestSessionKey(t, conn, rk.PrivateId) - cp := k.Clone() - assert.True(proto.Equal(cp.(*kms.SessionKey).SessionKey, k.SessionKey)) - }) - t.Run("not-equal", func(t *testing.T) { - assert := assert.New(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - org2, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - rk2 := kms.TestRootKey(t, conn, org2.PublicId) - k := kms.TestSessionKey(t, conn, rk.PrivateId) - k2 := kms.TestSessionKey(t, conn, rk2.PrivateId) - - cp := k.Clone() - assert.True(!proto.Equal(cp.(*kms.SessionKey).SessionKey, k2.SessionKey)) - }) -} - -func TestSessionKey_SetTableName(t *testing.T) { - t.Parallel() - defaultTableName := kms.DefaultSessionKeyTableName - tests := []struct { - name string - setNameTo string - want string - }{ - { - name: "new-name", - setNameTo: "new-name", - want: "new-name", - }, - { - name: "reset to default", - setNameTo: "", - want: defaultTableName, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - def := kms.AllocSessionKey() - require.Equal(defaultTableName, def.TableName()) - s := kms.AllocSessionKey() - s.SetTableName(tt.setNameTo) - assert.Equal(tt.want, s.TableName()) - }) - } -} diff --git a/internal/kms/session_key_version.go b/internal/kms/session_key_version.go deleted file mode 100644 index 0ffd9c8d8..000000000 --- a/internal/kms/session_key_version.go +++ /dev/null @@ -1,118 +0,0 @@ -package kms - -import ( - "context" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/kms/store" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" - "github.com/hashicorp/go-kms-wrapping/v2/extras/structwrapping" - "google.golang.org/protobuf/proto" -) - -const ( - DefaultSessionKeyVersionTableName = "kms_session_key_version" -) - -type SessionKeyVersion struct { - *store.SessionKeyVersion - tableName string `gorm:"-"` -} - -// SessionKeyVersion creates a new in memory key version. No options are -// currently supported. -func NewSessionKeyVersion(sessionKeyId string, key []byte, rootKeyVersionId string, _ ...Option) (*SessionKeyVersion, error) { - const op = "kms.NewSessionKeyVersion" - if sessionKeyId == "" { - return nil, errors.NewDeprecated(errors.InvalidParameter, op, "missing session key id") - } - if len(key) == 0 { - return nil, errors.NewDeprecated(errors.InvalidParameter, op, "missing key") - } - if rootKeyVersionId == "" { - return nil, errors.NewDeprecated(errors.InvalidParameter, op, "missing root key version id") - } - - k := &SessionKeyVersion{ - SessionKeyVersion: &store.SessionKeyVersion{ - SessionKeyId: sessionKeyId, - RootKeyVersionId: rootKeyVersionId, - Key: key, - }, - } - return k, nil -} - -// AllocSessionKeyVersion allocates a key version -func AllocSessionKeyVersion() SessionKeyVersion { - return SessionKeyVersion{ - SessionKeyVersion: &store.SessionKeyVersion{}, - } -} - -// Clone creates a clone of the key version -func (k *SessionKeyVersion) Clone() interface{} { - cp := proto.Clone(k.SessionKeyVersion) - return &SessionKeyVersion{ - SessionKeyVersion: cp.(*store.SessionKeyVersion), - } -} - -// VetForWrite implements db.VetForWrite() interface and validates the key -// version before it's written. -func (k *SessionKeyVersion) VetForWrite(ctx context.Context, r db.Reader, opType db.OpType, opt ...db.Option) error { - const op = "kms.(SessionKeyVersion).VetForWrite" - if k.PrivateId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - if opType == db.CreateOp { - if k.CtKey == nil { - return errors.New(ctx, errors.InvalidParameter, op, "missing key") - } - if k.SessionKeyId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "missing session key id") - } - if k.RootKeyVersionId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "missing root key version id") - } - } - return nil -} - -// TableName returns the tablename to override the default gorm table name -func (k *SessionKeyVersion) TableName() string { - if k.tableName != "" { - return k.tableName - } - return DefaultSessionKeyVersionTableName -} - -// SetTableName sets the tablename and satisfies the ReplayableMessage -// interface. If the caller attempts to set the name to "" the name will be -// reset to the default name. -func (k *SessionKeyVersion) SetTableName(n string) { - k.tableName = n -} - -// Encrypt will encrypt the key version's key -func (k *SessionKeyVersion) Encrypt(ctx context.Context, cipher wrapping.Wrapper) error { - const op = "kms.(SessionKeyVersion).Encrypt" - // structwrapping doesn't support embedding, so we'll pass in the - // store.SessionKeyVersion directly - if err := structwrapping.WrapStruct(ctx, cipher, k.SessionKeyVersion, nil); err != nil { - return errors.Wrap(ctx, err, op, errors.WithCode(errors.Encrypt)) - } - return nil -} - -// Decrypt will decrypt the key version's key -func (k *SessionKeyVersion) Decrypt(ctx context.Context, cipher wrapping.Wrapper) error { - const op = "kms.(SessionKeyVersion).Decrypt" - // structwrapping doesn't support embedding, so we'll pass in the - // store.SessionKeyVersion directly - if err := structwrapping.UnwrapStruct(ctx, cipher, k.SessionKeyVersion, nil); err != nil { - return errors.Wrap(ctx, err, op, errors.WithCode(errors.Decrypt)) - } - return nil -} diff --git a/internal/kms/session_key_version_test.go b/internal/kms/session_key_version_test.go deleted file mode 100644 index df75baceb..000000000 --- a/internal/kms/session_key_version_test.go +++ /dev/null @@ -1,249 +0,0 @@ -package kms_test - -import ( - "context" - "testing" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/iam" - "github.com/hashicorp/boundary/internal/kms" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" -) - -// NOTE: there are no update tests since all the essionKeyVersion attributes are -// immutable and those tests are covered by TestSessionKey_ImmutableFields - -func TestSessionKeyVersion_Create(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - rkv, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - - dk := kms.TestSessionKey(t, conn, rk.PrivateId) - - type args struct { - sessionKeyId string - key []byte - rootKeyVersionId string - opt []kms.Option - } - tests := []struct { - name string - args args - want *kms.SessionKeyVersion - wantErr bool - wantIsErr errors.Code - create bool - wantCreateErr bool - }{ - { - name: "empty-id", - args: args{ - key: []byte("test key"), - rootKeyVersionId: rkv.PrivateId, - }, - wantErr: true, - wantIsErr: errors.InvalidParameter, - }, - { - name: "empty-key", - args: args{ - sessionKeyId: dk.PrivateId, - rootKeyVersionId: rkv.PrivateId, - }, - wantErr: true, - wantIsErr: errors.InvalidParameter, - }, - { - name: "empty-root-key-version-id", - args: args{ - sessionKeyId: dk.PrivateId, - key: []byte("test key"), - }, - wantErr: true, - wantIsErr: errors.InvalidParameter, - }, - { - name: "valid", - args: args{ - sessionKeyId: dk.PrivateId, - key: []byte("test key"), - rootKeyVersionId: rkv.PrivateId, - }, - want: func() *kms.SessionKeyVersion { - k := kms.AllocSessionKeyVersion() - k.RootKeyVersionId = rkv.PrivateId - k.Key = []byte("test key") - k.SessionKeyId = dk.PrivateId - return &k - }(), - create: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocSessionKeyVersion(); return &i }(), "1=1") - got, err := kms.NewSessionKeyVersion(tt.args.sessionKeyId, tt.args.key, tt.args.rootKeyVersionId, tt.args.opt...) - if tt.wantErr { - require.Error(err) - assert.True(errors.Match(errors.T(tt.wantIsErr), err)) - return - } - require.NoError(err) - assert.Equal(tt.want, got) - if tt.create { - id, err := db.NewPublicId(kms.SessionKeyPrefix) - require.NoError(err) - got.PrivateId = id - err = got.Encrypt(context.Background(), rkvWrapper) - require.NoError(err) - err = db.New(conn).Create(context.Background(), got) - if tt.wantCreateErr { - assert.Error(err) - return - } else { - assert.NoError(err) - } - } - }) - } -} - -func TestSessionKeyVersion_Delete(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - tk := kms.TestSessionKey(t, conn, rk.PrivateId) - - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocSessionKeyVersion(); return &i }(), "1=1") - - tests := []struct { - name string - key *kms.SessionKeyVersion - wantRowsDeleted int - wantErr bool - wantErrMsg string - }{ - { - name: "valid", - key: kms.TestSessionKeyVersion(t, conn, rkvWrapper, tk.PrivateId, []byte("test key")), - wantErr: false, - wantRowsDeleted: 1, - }, - { - name: "bad-id", - key: func() *kms.SessionKeyVersion { - k := kms.AllocSessionKeyVersion() - id, err := db.NewPublicId(kms.SessionKeyVersionPrefix) - require.NoError(t, err) - k.PrivateId = id - return &k - }(), - wantErr: false, - wantRowsDeleted: 0, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - deleteKey := kms.AllocSessionKeyVersion() - deleteKey.PrivateId = tt.key.PrivateId - deletedRows, err := rw.Delete(context.Background(), &deleteKey) - if tt.wantErr { - require.Error(err) - return - } - require.NoError(err) - if tt.wantRowsDeleted == 0 { - assert.Equal(tt.wantRowsDeleted, deletedRows) - return - } - assert.Equal(tt.wantRowsDeleted, deletedRows) - foundKey := kms.AllocSessionKeyVersion() - foundKey.PrivateId = tt.key.PrivateId - err = rw.LookupById(context.Background(), &foundKey) - require.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestSessionKeyVersion_Clone(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - t.Run("valid", func(t *testing.T) { - assert := assert.New(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - - k := kms.TestSessionKey(t, conn, rk.PrivateId) - kv := kms.TestSessionKeyVersion(t, conn, rkvWrapper, k.PrivateId, []byte("test key")) - cp := kv.Clone() - assert.True(proto.Equal(cp.(*kms.SessionKeyVersion).SessionKeyVersion, kv.SessionKeyVersion)) - }) - t.Run("not-equal", func(t *testing.T) { - assert := assert.New(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - org2, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - rk2 := kms.TestRootKey(t, conn, org2.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - _, rkvWrapper2 := kms.TestRootKeyVersion(t, conn, wrapper, rk2.PrivateId) - - k := kms.TestSessionKey(t, conn, rk.PrivateId) - k2 := kms.TestSessionKey(t, conn, rk2.PrivateId) - kv := kms.TestSessionKeyVersion(t, conn, rkvWrapper, k.PrivateId, []byte("test key")) - kv2 := kms.TestSessionKeyVersion(t, conn, rkvWrapper2, k2.PrivateId, []byte("test key 2")) - - cp := kv.Clone() - assert.True(!proto.Equal(cp.(*kms.SessionKeyVersion).SessionKeyVersion, kv2.SessionKeyVersion)) - }) -} - -func TestSessionKeyVersion_SetTableName(t *testing.T) { - t.Parallel() - defaultTableName := kms.DefaultSessionKeyVersionTableName - tests := []struct { - name string - setNameTo string - want string - }{ - { - name: "new-name", - setNameTo: "new-name", - want: "new-name", - }, - { - name: "reset to default", - setNameTo: "", - want: defaultTableName, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - def := kms.AllocSessionKeyVersion() - require.Equal(defaultTableName, def.TableName()) - s := kms.AllocSessionKeyVersion() - s.SetTableName(tt.setNameTo) - assert.Equal(tt.want, s.TableName()) - }) - } -} diff --git a/internal/kms/testing.go b/internal/kms/testing.go index aaf2e4ea2..1cab48eba 100644 --- a/internal/kms/testing.go +++ b/internal/kms/testing.go @@ -2,276 +2,38 @@ package kms import ( "context" + "fmt" "testing" "github.com/hashicorp/boundary/internal/db" wrapping "github.com/hashicorp/go-kms-wrapping/v2" - aead "github.com/hashicorp/go-kms-wrapping/v2/aead" "github.com/stretchr/testify/require" ) -func TestRootKey(t testing.TB, conn *db.DB, scopeId string) *RootKey { - t.Helper() - require := require.New(t) - db.TestDeleteWhere(t, conn, func() interface{} { i := AllocRootKey(); return &i }(), "scope_id = ?", scopeId) - rw := db.New(conn) - k, err := NewRootKey(scopeId) - require.NoError(err) - id, err := newRootKeyId() - require.NoError(err) - k.PrivateId = id - err = rw.Create(context.Background(), k) - require.NoError(err) - return k -} - -func TestRootKeyVersion(t testing.TB, conn *db.DB, wrapper wrapping.Wrapper, rootId string) (kv *RootKeyVersion, kvWrapper wrapping.Wrapper) { - t.Helper() - require := require.New(t) - rw := db.New(conn) - rootKeyVersionWrapper := db.TestWrapper(t) - key, err := rootKeyVersionWrapper.(*aead.Wrapper).KeyBytes(context.Background()) - require.NoError(err) - k, err := NewRootKeyVersion(rootId, key) - require.NoError(err) - id, err := newRootKeyVersionId() - require.NoError(err) - k.PrivateId = id - err = k.Encrypt(context.Background(), wrapper) - require.NoError(err) - err = rw.Create(context.Background(), k) - require.NoError(err) - _, err = rootKeyVersionWrapper.(*aead.Wrapper).SetConfig(context.Background(), wrapping.WithKeyId(k.GetPrivateId())) - require.NoError(err) - return k, rootKeyVersionWrapper -} - +// TestKms creates a kms for testing. func TestKms(t testing.TB, conn *db.DB, rootWrapper wrapping.Wrapper) *Kms { t.Helper() require := require.New(t) rw := db.New(conn) - kmsRepo, err := NewRepository(rw, rw) - require.NoError(err) - kms, err := NewKms(kmsRepo) + kms, err := New(context.Background(), rw, rw) require.NoError(err) err = kms.AddExternalWrappers(context.Background(), WithRootWrapper(rootWrapper)) require.NoError(err) + _, err = kms.underlying.GetExternalRootWrapper() + require.NoError(err) return kms } -func TestDatabaseKey(t testing.TB, conn *db.DB, rootKeyId string) *DatabaseKey { - t.Helper() - require := require.New(t) - rw := db.New(conn) - db.TestDeleteWhere(t, conn, func() interface{} { i := AllocDatabaseKey(); return &i }(), "root_key_id = ?", rootKeyId) - k, err := NewDatabaseKey(rootKeyId) - require.NoError(err) - id, err := newDatabaseKeyId() - require.NoError(err) - k.PrivateId = id - k.RootKeyId = rootKeyId - err = rw.Create(context.Background(), k) - require.NoError(err) - return k +// TestKmsDeleteKeyPurpose allows you to delete a KeyPurpose for testing. +func TestKmsDeleteKeyPurpose(t testing.TB, conn *db.DB, purpose KeyPurpose) { + db.TestDeleteWhere(t, conn, func() interface{} { i := dataKey{}; return &i }(), fmt.Sprintf("purpose='%s'", purpose.String())) } -func TestDatabaseKeyVersion(t testing.TB, conn *db.DB, rootKeyVersionWrapper wrapping.Wrapper, databaseKeyId string, key []byte) *DatabaseKeyVersion { - t.Helper() - require := require.New(t) - rw := db.New(conn) - rootKeyId, err := rootKeyVersionWrapper.KeyId(context.Background()) - require.NoError(err) - rootKeyVersionId := rootKeyId - require.NotEmpty(rootKeyVersionId) - k, err := NewDatabaseKeyVersion(databaseKeyId, key, rootKeyVersionId) - require.NoError(err) - id, err := newDatabaseKeyVersionId() - require.NoError(err) - k.PrivateId = id - err = k.Encrypt(context.Background(), rootKeyVersionWrapper) - require.NoError(err) - err = rw.Create(context.Background(), k) - require.NoError(err) - return k +// TestKmsDeleteAllKeys allows you to delete all the keys for testing. +func TestKmsDeleteAllKeys(t testing.TB, conn *db.DB) { + db.TestDeleteWhere(t, conn, func() interface{} { i := rootKey{}; return &i }(), "1=1") } -func TestOplogKey(t testing.TB, conn *db.DB, rootKeyId string) *OplogKey { - t.Helper() - require := require.New(t) - rw := db.New(conn) - db.TestDeleteWhere(t, conn, func() interface{} { i := AllocOplogKey(); return &i }(), "root_key_id = ?", rootKeyId) - k, err := NewOplogKey(rootKeyId) - require.NoError(err) - id, err := newOplogKeyId() - require.NoError(err) - k.PrivateId = id - k.RootKeyId = rootKeyId - err = rw.Create(context.Background(), k) - require.NoError(err) - return k -} +type dataKey struct{} -func TestOplogKeyVersion(t testing.TB, conn *db.DB, rootKeyVersionWrapper wrapping.Wrapper, oplogKeyId string, key []byte) *OplogKeyVersion { - t.Helper() - require := require.New(t) - rw := db.New(conn) - rootKeyId, err := rootKeyVersionWrapper.KeyId(context.Background()) - require.NoError(err) - rootKeyVersionId := rootKeyId - require.NotEmpty(rootKeyVersionId) - k, err := NewOplogKeyVersion(oplogKeyId, key, rootKeyVersionId) - require.NoError(err) - id, err := newOplogKeyVersionId() - require.NoError(err) - k.PrivateId = id - err = k.Encrypt(context.Background(), rootKeyVersionWrapper) - require.NoError(err) - err = rw.Create(context.Background(), k) - require.NoError(err) - return k -} - -func TestTokenKey(t testing.TB, conn *db.DB, rootKeyId string) *TokenKey { - t.Helper() - require := require.New(t) - db.TestDeleteWhere(t, conn, func() interface{} { i := AllocTokenKey(); return &i }(), "root_key_id = ?", rootKeyId) - rw := db.New(conn) - k, err := NewTokenKey(rootKeyId) - require.NoError(err) - id, err := newTokenKeyId() - require.NoError(err) - k.PrivateId = id - k.RootKeyId = rootKeyId - err = rw.Create(context.Background(), k) - require.NoError(err) - return k -} - -func TestTokenKeyVersion(t testing.TB, conn *db.DB, rootKeyVersionWrapper wrapping.Wrapper, tokenKeyId string, key []byte) *TokenKeyVersion { - t.Helper() - require := require.New(t) - rw := db.New(conn) - rootKeyId, err := rootKeyVersionWrapper.KeyId(context.Background()) - require.NoError(err) - rootKeyVersionId := rootKeyId - require.NotEmpty(rootKeyVersionId) - k, err := NewTokenKeyVersion(tokenKeyId, key, rootKeyVersionId) - require.NoError(err) - id, err := newTokenKeyVersionId() - require.NoError(err) - k.PrivateId = id - err = k.Encrypt(context.Background(), rootKeyVersionWrapper) - require.NoError(err) - err = rw.Create(context.Background(), k) - require.NoError(err) - return k -} - -func TestSessionKey(t testing.TB, conn *db.DB, rootKeyId string) *SessionKey { - t.Helper() - require := require.New(t) - db.TestDeleteWhere(t, conn, func() interface{} { i := AllocSessionKey(); return &i }(), "root_key_id = ?", rootKeyId) - rw := db.New(conn) - k, err := NewSessionKey(rootKeyId) - require.NoError(err) - id, err := newSessionKeyId() - require.NoError(err) - k.PrivateId = id - k.RootKeyId = rootKeyId - err = rw.Create(context.Background(), k) - require.NoError(err) - return k -} - -func TestSessionKeyVersion(t testing.TB, conn *db.DB, rootKeyVersionWrapper wrapping.Wrapper, sessionKeyId string, key []byte) *SessionKeyVersion { - t.Helper() - require := require.New(t) - rw := db.New(conn) - rootKeyId, err := rootKeyVersionWrapper.KeyId(context.Background()) - require.NoError(err) - rootKeyVersionId := rootKeyId - require.NotEmpty(rootKeyVersionId) - k, err := NewSessionKeyVersion(sessionKeyId, key, rootKeyVersionId) - require.NoError(err) - id, err := newSessionKeyVersionId() - require.NoError(err) - k.PrivateId = id - err = k.Encrypt(context.Background(), rootKeyVersionWrapper) - require.NoError(err) - err = rw.Create(context.Background(), k) - require.NoError(err) - return k -} - -func TestOidcKey(t testing.TB, conn *db.DB, rootKeyId string) *OidcKey { - t.Helper() - require := require.New(t) - db.TestDeleteWhere(t, conn, func() interface{} { i := AllocOidcKey(); return &i }(), "root_key_id = ?", rootKeyId) - rw := db.New(conn) - k, err := NewOidcKey(rootKeyId) - require.NoError(err) - id, err := newOidcKeyId() - require.NoError(err) - k.PrivateId = id - k.RootKeyId = rootKeyId - err = rw.Create(context.Background(), k) - require.NoError(err) - return k -} - -func TestOidcKeyVersion(t testing.TB, conn *db.DB, rootKeyVersionWrapper wrapping.Wrapper, oidcKeyId string, key []byte) *OidcKeyVersion { - t.Helper() - require := require.New(t) - rw := db.New(conn) - rootKeyId, err := rootKeyVersionWrapper.KeyId(context.Background()) - require.NoError(err) - rootKeyVersionId := rootKeyId - require.NotEmpty(rootKeyVersionId) - k, err := NewOidcKeyVersion(oidcKeyId, key, rootKeyVersionId) - require.NoError(err) - id, err := newOidcKeyVersionId() - require.NoError(err) - k.PrivateId = id - err = k.Encrypt(context.Background(), rootKeyVersionWrapper) - require.NoError(err) - err = rw.Create(context.Background(), k) - require.NoError(err) - return k -} - -func TestAuditKey(t testing.TB, conn *db.DB, rootKeyId string) *AuditKey { - t.Helper() - ctx := context.Background() - require := require.New(t) - db.TestDeleteWhere(t, conn, func() interface{} { i := AllocAuditKey(); return &i }(), "root_key_id = ?", rootKeyId) - rw := db.New(conn) - k, err := NewAuditKey(ctx, rootKeyId) - require.NoError(err) - id, err := newAuditKeyId(ctx) - require.NoError(err) - k.PrivateId = id - k.RootKeyId = rootKeyId - err = rw.Create(context.Background(), k) - require.NoError(err) - return k -} - -func TestAuditKeyVersion(t testing.TB, conn *db.DB, rootKeyVersionWrapper wrapping.Wrapper, auditKeyId string, key []byte) *AuditKeyVersion { - t.Helper() - ctx := context.Background() - require := require.New(t) - rw := db.New(conn) - rootKeyVersionId, err := rootKeyVersionWrapper.KeyId(ctx) - require.NoError(err) - require.NotEmpty(rootKeyVersionId) - k, err := NewAuditKeyVersion(ctx, auditKeyId, key, rootKeyVersionId) - require.NoError(err) - id, err := newAuditKeyVersionId(ctx) - require.NoError(err) - k.PrivateId = id - err = k.Encrypt(context.Background(), rootKeyVersionWrapper) - require.NoError(err) - err = rw.Create(context.Background(), k) - require.NoError(err) - return k -} +func (*dataKey) TableName() string { return "kms_data_key" } diff --git a/internal/kms/testing_test.go b/internal/kms/testing_test.go deleted file mode 100644 index 30ef305a2..000000000 --- a/internal/kms/testing_test.go +++ /dev/null @@ -1,150 +0,0 @@ -package kms_test - -import ( - "testing" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/iam" - "github.com/hashicorp/boundary/internal/kms" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func Test_TestRootKey(t *testing.T) { - assert, require := assert.New(t), require.New(t) - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - k := kms.TestRootKey(t, conn, org.PublicId) - require.NotNil(k) - assert.NotEmpty(k.PrivateId) -} - -func Test_TestRootKeyVersion(t *testing.T) { - assert, require := assert.New(t), require.New(t) - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - k, _ := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - require.NotNil(k) - assert.NotEmpty(k.PrivateId) -} - -func Test_TestDatabaseKey(t *testing.T) { - assert, require := assert.New(t), require.New(t) - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - k := kms.TestRootKey(t, conn, org.PublicId) - require.NotNil(k) - assert.NotEmpty(k.PrivateId) - - dk := kms.TestDatabaseKey(t, conn, k.PrivateId) - require.NotNil(dk) - assert.NotEmpty(dk.PrivateId) -} - -func Test_TestDatabaseKeyVersion(t *testing.T) { - require := require.New(t) - conn, _ := db.TestSetup(t, "postgres") - kmsWrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, kmsWrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rootKeyVersionWrapper := kms.TestRootKeyVersion(t, conn, kmsWrapper, rk.PrivateId) - dk := kms.TestDatabaseKey(t, conn, rk.PrivateId) - dv := kms.TestDatabaseKeyVersion(t, conn, rootKeyVersionWrapper, dk.PrivateId, []byte("test dek key")) - require.NotNil(dv) - require.NotEmpty(dv.PrivateId) -} - -func Test_TestOplogKey(t *testing.T) { - assert, require := assert.New(t), require.New(t) - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - k := kms.TestRootKey(t, conn, org.PublicId) - require.NotNil(k) - assert.NotEmpty(k.PrivateId) - - opk := kms.TestOplogKey(t, conn, k.PrivateId) - require.NotNil(opk) - assert.NotEmpty(opk.PrivateId) -} - -func Test_TestOplogKeyVersion(t *testing.T) { - require := require.New(t) - conn, _ := db.TestSetup(t, "postgres") - kmsWrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, kmsWrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rootKeyVersionWrapper := kms.TestRootKeyVersion(t, conn, kmsWrapper, rk.PrivateId) - opk := kms.TestOplogKey(t, conn, rk.PrivateId) - opv := kms.TestOplogKeyVersion(t, conn, rootKeyVersionWrapper, opk.PrivateId, []byte("test dek key")) - require.NotNil(opv) - require.NotEmpty(opv.PrivateId) -} - -func Test_TestTokenKey(t *testing.T) { - assert, require := assert.New(t), require.New(t) - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - k := kms.TestRootKey(t, conn, org.PublicId) - require.NotNil(k) - assert.NotEmpty(k.PrivateId) - - tk := kms.TestTokenKey(t, conn, k.PrivateId) - require.NotNil(tk) - assert.NotEmpty(tk.PrivateId) -} - -func Test_TestTokenKeyVersion(t *testing.T) { - require := require.New(t) - conn, _ := db.TestSetup(t, "postgres") - kmsWrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, kmsWrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rootKeyVersionWrapper := kms.TestRootKeyVersion(t, conn, kmsWrapper, rk.PrivateId) - tk := kms.TestTokenKey(t, conn, rk.PrivateId) - tv := kms.TestTokenKeyVersion(t, conn, rootKeyVersionWrapper, tk.PrivateId, []byte("test dek key")) - require.NotNil(tv) - require.NotEmpty(tv.PrivateId) -} - -func Test_TestSessionKey(t *testing.T) { - assert, require := assert.New(t), require.New(t) - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - k := kms.TestRootKey(t, conn, org.PublicId) - require.NotNil(k) - assert.NotEmpty(k.PrivateId) - - sk := kms.TestSessionKey(t, conn, k.PrivateId) - require.NotNil(sk) - assert.NotEmpty(sk.PrivateId) -} - -func Test_TestSessionKeyVersion(t *testing.T) { - require := require.New(t) - conn, _ := db.TestSetup(t, "postgres") - kmsWrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, kmsWrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rootKeyVersionWrapper := kms.TestRootKeyVersion(t, conn, kmsWrapper, rk.PrivateId) - sk := kms.TestSessionKey(t, conn, rk.PrivateId) - sv := kms.TestSessionKeyVersion(t, conn, rootKeyVersionWrapper, sk.PrivateId, []byte("test dek key")) - require.NotNil(sv) - require.NotEmpty(sv.PrivateId) -} diff --git a/internal/kms/token_key.go b/internal/kms/token_key.go deleted file mode 100644 index 63e61d63a..000000000 --- a/internal/kms/token_key.go +++ /dev/null @@ -1,79 +0,0 @@ -package kms - -import ( - "context" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/kms/store" - "google.golang.org/protobuf/proto" -) - -const ( - DefaultTokenKeyTableName = "kms_token_key" -) - -type TokenKey struct { - *store.TokenKey - tableName string `gorm:"-"` -} - -// NewTokenKey creates a new in memory key. No options -// are currently supported. -func NewTokenKey(rootKeyId string, _ ...Option) (*TokenKey, error) { - const op = "kms.NewTokenKey" - if rootKeyId == "" { - return nil, errors.NewDeprecated(errors.InvalidParameter, op, "missing root key id") - } - c := &TokenKey{ - TokenKey: &store.TokenKey{ - RootKeyId: rootKeyId, - }, - } - return c, nil -} - -// AllocTokenKey will allocate a key -func AllocTokenKey() TokenKey { - return TokenKey{ - TokenKey: &store.TokenKey{}, - } -} - -// Clone creates a clone of the key -func (k *TokenKey) Clone() interface{} { - cp := proto.Clone(k.TokenKey) - return &TokenKey{ - TokenKey: cp.(*store.TokenKey), - } -} - -// VetForWrite implements db.VetForWrite() interface and validates the key -// before it's written. -func (k *TokenKey) VetForWrite(ctx context.Context, _ db.Reader, opType db.OpType, _ ...db.Option) error { - const op = "kms.(TokenKey).VetForWrite" - if k.PrivateId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - if opType == db.CreateOp { - if k.RootKeyId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "missing root key id") - } - } - return nil -} - -// TableName returns the tablename to override the default gorm table name -func (k *TokenKey) TableName() string { - if k.tableName != "" { - return k.tableName - } - return DefaultTokenKeyTableName -} - -// SetTableName sets the tablename and satisfies the ReplayableMessage -// interface. If the caller attempts to set the name to "" the name will be -// reset to the default name. -func (k *TokenKey) SetTableName(n string) { - k.tableName = n -} diff --git a/internal/kms/token_key_test.go b/internal/kms/token_key_test.go deleted file mode 100644 index 9f1b8a4fa..000000000 --- a/internal/kms/token_key_test.go +++ /dev/null @@ -1,206 +0,0 @@ -package kms_test - -import ( - "context" - "testing" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/iam" - "github.com/hashicorp/boundary/internal/kms" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" -) - -// NOTE: there are no update tests since all the TokenKey attributes are -// immutable and those tests are covered by TestTokenKey_ImmutableFields - -func TestTokenKey_Create(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - - type args struct { - rootKeyId string - opt []kms.Option - } - tests := []struct { - name string - args args - want *kms.TokenKey - wantErr bool - wantIsErr errors.Code - create bool - wantCreateErr bool - }{ - { - name: "empty-rootKeyId", - args: args{}, - wantErr: true, - wantIsErr: errors.InvalidParameter, - }, - { - name: "valid", - args: args{ - rootKeyId: rk.PrivateId, - }, - want: func() *kms.TokenKey { - k := kms.AllocTokenKey() - k.RootKeyId = rk.PrivateId - return &k - }(), - create: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocTokenKey(); return &i }(), "1=1") - got, err := kms.NewTokenKey(tt.args.rootKeyId, tt.args.opt...) - if tt.wantErr { - require.Error(err) - assert.True(errors.Match(errors.T(tt.wantIsErr), err)) - return - } - require.NoError(err) - assert.Equal(tt.want, got) - if tt.create { - id, err := db.NewPublicId(kms.TokenKeyPrefix) - require.NoError(err) - got.PrivateId = id - err = db.New(conn).Create(context.Background(), got) - if tt.wantCreateErr { - assert.Error(err) - return - } else { - assert.NoError(err) - } - } - }) - } -} - -func TestTokenKey_Delete(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocTokenKey(); return &i }(), "1=1") - - tests := []struct { - name string - key *kms.TokenKey - wantRowsDeleted int - wantErr bool - wantErrMsg string - }{ - { - name: "valid", - key: kms.TestTokenKey(t, conn, rk.PrivateId), - wantErr: false, - wantRowsDeleted: 1, - }, - { - name: "bad-id", - key: func() *kms.TokenKey { - k := kms.AllocTokenKey() - id, err := db.NewPublicId(kms.TokenKeyPrefix) - require.NoError(t, err) - k.PrivateId = id - k.RootKeyId = rk.PrivateId - return &k - }(), - wantErr: false, - wantRowsDeleted: 0, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - deleteKey := kms.AllocTokenKey() - deleteKey.PrivateId = tt.key.PrivateId - deletedRows, err := rw.Delete(context.Background(), &deleteKey) - if tt.wantErr { - require.Error(err) - return - } - require.NoError(err) - if tt.wantRowsDeleted == 0 { - assert.Equal(tt.wantRowsDeleted, deletedRows) - return - } - assert.Equal(tt.wantRowsDeleted, deletedRows) - foundKey := kms.AllocTokenKey() - foundKey.PrivateId = tt.key.PrivateId - err = rw.LookupById(context.Background(), &foundKey) - require.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestTokenKey_Clone(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - t.Run("valid", func(t *testing.T) { - assert := assert.New(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - k := kms.TestTokenKey(t, conn, rk.PrivateId) - cp := k.Clone() - assert.True(proto.Equal(cp.(*kms.TokenKey).TokenKey, k.TokenKey)) - }) - t.Run("not-equal", func(t *testing.T) { - assert := assert.New(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - org2, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - rk2 := kms.TestRootKey(t, conn, org2.PublicId) - k := kms.TestTokenKey(t, conn, rk.PrivateId) - k2 := kms.TestTokenKey(t, conn, rk2.PrivateId) - - cp := k.Clone() - assert.True(!proto.Equal(cp.(*kms.TokenKey).TokenKey, k2.TokenKey)) - }) -} - -func TestTokenKey_SetTableName(t *testing.T) { - t.Parallel() - defaultTableName := kms.DefaultTokenKeyTableName - tests := []struct { - name string - setNameTo string - want string - }{ - { - name: "new-name", - setNameTo: "new-name", - want: "new-name", - }, - { - name: "reset to default", - setNameTo: "", - want: defaultTableName, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - def := kms.AllocTokenKey() - require.Equal(defaultTableName, def.TableName()) - s := kms.AllocTokenKey() - s.SetTableName(tt.setNameTo) - assert.Equal(tt.want, s.TableName()) - }) - } -} diff --git a/internal/kms/token_key_version.go b/internal/kms/token_key_version.go deleted file mode 100644 index efb406e57..000000000 --- a/internal/kms/token_key_version.go +++ /dev/null @@ -1,118 +0,0 @@ -package kms - -import ( - "context" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/kms/store" - wrapping "github.com/hashicorp/go-kms-wrapping/v2" - "github.com/hashicorp/go-kms-wrapping/v2/extras/structwrapping" - "google.golang.org/protobuf/proto" -) - -const ( - DefaultTokenKeyVersionTableName = "kms_token_key_version" -) - -type TokenKeyVersion struct { - *store.TokenKeyVersion - tableName string `gorm:"-"` -} - -// TokenKeyVersion creates a new in memory key version. No options are -// currently supported. -func NewTokenKeyVersion(tokenKeyId string, key []byte, rootKeyVersionId string, _ ...Option) (*TokenKeyVersion, error) { - const op = "kms.NewTokenKeyVersion" - if tokenKeyId == "" { - return nil, errors.NewDeprecated(errors.InvalidParameter, op, "missing token key id") - } - if len(key) == 0 { - return nil, errors.NewDeprecated(errors.InvalidParameter, op, "missing key") - } - if rootKeyVersionId == "" { - return nil, errors.NewDeprecated(errors.InvalidParameter, op, "missing root key version id") - } - - k := &TokenKeyVersion{ - TokenKeyVersion: &store.TokenKeyVersion{ - TokenKeyId: tokenKeyId, - RootKeyVersionId: rootKeyVersionId, - Key: key, - }, - } - return k, nil -} - -// AllocTokenKeyVersion allocates a key version -func AllocTokenKeyVersion() TokenKeyVersion { - return TokenKeyVersion{ - TokenKeyVersion: &store.TokenKeyVersion{}, - } -} - -// Clone creates a clone of the key version -func (k *TokenKeyVersion) Clone() interface{} { - cp := proto.Clone(k.TokenKeyVersion) - return &TokenKeyVersion{ - TokenKeyVersion: cp.(*store.TokenKeyVersion), - } -} - -// VetForWrite implements db.VetForWrite() interface and validates the key -// version before it's written. -func (k *TokenKeyVersion) VetForWrite(ctx context.Context, _r db.Reader, opType db.OpType, _ ...db.Option) error { - const op = "kms.(TokenKeyVersion).VetForWrite" - if k.PrivateId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "missing private id") - } - if opType == db.CreateOp { - if k.CtKey == nil { - return errors.New(ctx, errors.InvalidParameter, op, "missing key") - } - if k.TokenKeyId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "missing token key id") - } - if k.RootKeyVersionId == "" { - return errors.New(ctx, errors.InvalidParameter, op, "missing root key version id") - } - } - return nil -} - -// TableName returns the tablename to override the default gorm table name -func (k *TokenKeyVersion) TableName() string { - if k.tableName != "" { - return k.tableName - } - return DefaultTokenKeyVersionTableName -} - -// SetTableName sets the tablename and satisfies the ReplayableMessage -// interface. If the caller attempts to set the name to "" the name will be -// reset to the default name. -func (k *TokenKeyVersion) SetTableName(n string) { - k.tableName = n -} - -// Encrypt will encrypt the key version's key -func (k *TokenKeyVersion) Encrypt(ctx context.Context, cipher wrapping.Wrapper) error { - const op = "kms.(TokenKeyVersion).Encrypt" - // structwrapping doesn't support embedding, so we'll pass in the - // store.TokenKeyVersion directly - if err := structwrapping.WrapStruct(ctx, cipher, k.TokenKeyVersion, nil); err != nil { - return errors.Wrap(ctx, err, op, errors.WithCode(errors.Encrypt)) - } - return nil -} - -// Decrypt will decrypt the key version's key -func (k *TokenKeyVersion) Decrypt(ctx context.Context, cipher wrapping.Wrapper) error { - const op = "kms.(TokenKeyVersion).Decrypt" - // structwrapping doesn't support embedding, so we'll pass in the - // store.TokenKeyVersion directly - if err := structwrapping.UnwrapStruct(ctx, cipher, k.TokenKeyVersion, nil); err != nil { - return errors.Wrap(ctx, err, op, errors.WithCode(errors.Decrypt)) - } - return nil -} diff --git a/internal/kms/token_key_version_test.go b/internal/kms/token_key_version_test.go deleted file mode 100644 index 6e02ed71d..000000000 --- a/internal/kms/token_key_version_test.go +++ /dev/null @@ -1,249 +0,0 @@ -package kms_test - -import ( - "context" - "testing" - - "github.com/hashicorp/boundary/internal/db" - "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/iam" - "github.com/hashicorp/boundary/internal/kms" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" -) - -// NOTE: there are no update tests since all the TokenKeyVersion attributes are -// immutable and those tests are covered by TestTokenKey_ImmutableFields - -func TestTokenKeyVersion_Create(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - rkv, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - - dk := kms.TestTokenKey(t, conn, rk.PrivateId) - - type args struct { - tokenKeyId string - key []byte - rootKeyVersionId string - opt []kms.Option - } - tests := []struct { - name string - args args - want *kms.TokenKeyVersion - wantErr bool - wantIsErr errors.Code - create bool - wantCreateErr bool - }{ - { - name: "empty-id", - args: args{ - key: []byte("test key"), - rootKeyVersionId: rkv.PrivateId, - }, - wantErr: true, - wantIsErr: errors.InvalidParameter, - }, - { - name: "empty-key", - args: args{ - tokenKeyId: dk.PrivateId, - rootKeyVersionId: rkv.PrivateId, - }, - wantErr: true, - wantIsErr: errors.InvalidParameter, - }, - { - name: "empty-root-key-version-id", - args: args{ - tokenKeyId: dk.PrivateId, - key: []byte("test key"), - }, - wantErr: true, - wantIsErr: errors.InvalidParameter, - }, - { - name: "valid", - args: args{ - tokenKeyId: dk.PrivateId, - key: []byte("test key"), - rootKeyVersionId: rkv.PrivateId, - }, - want: func() *kms.TokenKeyVersion { - k := kms.AllocTokenKeyVersion() - k.RootKeyVersionId = rkv.PrivateId - k.Key = []byte("test key") - k.TokenKeyId = dk.PrivateId - return &k - }(), - create: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocTokenKeyVersion(); return &i }(), "1=1") - got, err := kms.NewTokenKeyVersion(tt.args.tokenKeyId, tt.args.key, tt.args.rootKeyVersionId, tt.args.opt...) - if tt.wantErr { - require.Error(err) - assert.True(errors.Match(errors.T(tt.wantIsErr), err)) - return - } - require.NoError(err) - assert.Equal(tt.want, got) - if tt.create { - id, err := db.NewPublicId(kms.TokenKeyPrefix) - require.NoError(err) - got.PrivateId = id - err = got.Encrypt(context.Background(), rkvWrapper) - require.NoError(err) - err = db.New(conn).Create(context.Background(), got) - if tt.wantCreateErr { - assert.Error(err) - return - } else { - assert.NoError(err) - } - } - }) - } -} - -func TestTokenKeyVersion_Delete(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - rw := db.New(conn) - wrapper := db.TestWrapper(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - tk := kms.TestTokenKey(t, conn, rk.PrivateId) - - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocTokenKeyVersion(); return &i }(), "1=1") - - tests := []struct { - name string - key *kms.TokenKeyVersion - wantRowsDeleted int - wantErr bool - wantErrMsg string - }{ - { - name: "valid", - key: kms.TestTokenKeyVersion(t, conn, rkvWrapper, tk.PrivateId, []byte("test key")), - wantErr: false, - wantRowsDeleted: 1, - }, - { - name: "bad-id", - key: func() *kms.TokenKeyVersion { - k := kms.AllocTokenKeyVersion() - id, err := db.NewPublicId(kms.TokenKeyVersionPrefix) - require.NoError(t, err) - k.PrivateId = id - return &k - }(), - wantErr: false, - wantRowsDeleted: 0, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - deleteKey := kms.AllocTokenKeyVersion() - deleteKey.PrivateId = tt.key.PrivateId - deletedRows, err := rw.Delete(context.Background(), &deleteKey) - if tt.wantErr { - require.Error(err) - return - } - require.NoError(err) - if tt.wantRowsDeleted == 0 { - assert.Equal(tt.wantRowsDeleted, deletedRows) - return - } - assert.Equal(tt.wantRowsDeleted, deletedRows) - foundKey := kms.AllocTokenKeyVersion() - foundKey.PrivateId = tt.key.PrivateId - err = rw.LookupById(context.Background(), &foundKey) - require.Error(err) - assert.True(errors.IsNotFoundError(err)) - }) - } -} - -func TestTokenKeyVersion_Clone(t *testing.T) { - t.Parallel() - conn, _ := db.TestSetup(t, "postgres") - wrapper := db.TestWrapper(t) - t.Run("valid", func(t *testing.T) { - assert := assert.New(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - - rk := kms.TestRootKey(t, conn, org.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - - k := kms.TestTokenKey(t, conn, rk.PrivateId) - kv := kms.TestTokenKeyVersion(t, conn, rkvWrapper, k.PrivateId, []byte("test key")) - cp := kv.Clone() - assert.True(proto.Equal(cp.(*kms.TokenKeyVersion).TokenKeyVersion, kv.TokenKeyVersion)) - }) - t.Run("not-equal", func(t *testing.T) { - assert := assert.New(t) - org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - org2, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) - db.TestDeleteWhere(t, conn, func() interface{} { i := kms.AllocRootKey(); return &i }(), "1=1") - rk := kms.TestRootKey(t, conn, org.PublicId) - rk2 := kms.TestRootKey(t, conn, org2.PublicId) - _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) - _, rkvWrapper2 := kms.TestRootKeyVersion(t, conn, wrapper, rk2.PrivateId) - - k := kms.TestTokenKey(t, conn, rk.PrivateId) - k2 := kms.TestTokenKey(t, conn, rk2.PrivateId) - kv := kms.TestTokenKeyVersion(t, conn, rkvWrapper, k.PrivateId, []byte("test key")) - kv2 := kms.TestTokenKeyVersion(t, conn, rkvWrapper2, k2.PrivateId, []byte("test key 2")) - - cp := kv.Clone() - assert.True(!proto.Equal(cp.(*kms.TokenKeyVersion).TokenKeyVersion, kv2.TokenKeyVersion)) - }) -} - -func TestTokenKeyVersion_SetTableName(t *testing.T) { - t.Parallel() - defaultTableName := kms.DefaultTokenKeyVersionTableName - tests := []struct { - name string - setNameTo string - want string - }{ - { - name: "new-name", - setNameTo: "new-name", - want: "new-name", - }, - { - name: "reset to default", - setNameTo: "", - want: defaultTableName, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert, require := assert.New(t), require.New(t) - def := kms.AllocTokenKeyVersion() - require.Equal(defaultTableName, def.TableName()) - s := kms.AllocTokenKeyVersion() - s.SetTableName(tt.setNameTo) - assert.Equal(tt.want, s.TableName()) - }) - } -} diff --git a/internal/servers/repository_test.go b/internal/servers/repository_test.go index 6e82aba46..e348f484b 100644 --- a/internal/servers/repository_test.go +++ b/internal/servers/repository_test.go @@ -31,6 +31,10 @@ func TestRecoveryNonces(t *testing.T) { }) defer tc.Shutdown() + externalWrappers := tc.Kms().GetExternalWrappers(context.Background()) + externalRecovery := externalWrappers.Recovery() + require.Equal(externalRecovery, wrapper) + client := tc.Client() repo := tc.ServersRepo() diff --git a/internal/session/repository_test.go b/internal/session/repository_test.go index 5326a1b3a..4a2ed7878 100644 --- a/internal/session/repository_test.go +++ b/internal/session/repository_test.go @@ -13,14 +13,18 @@ func TestNewRepository(t *testing.T) { t.Parallel() conn, _ := db.TestSetup(t, "postgres") rw := db.New(conn) + wrapper := db.TestWrapper(t) + testKms := kms.TestKms(t, conn, wrapper) + type args struct { r db.Reader w db.Writer + k *kms.Kms } tests := []struct { name string args args - want *kms.Repository + want *Repository wantErr bool wantErrString string }{ @@ -29,9 +33,10 @@ func TestNewRepository(t *testing.T) { args: args{ r: rw, w: rw, + k: testKms, }, - want: func() *kms.Repository { - ret, err := kms.NewRepository(rw, rw) + want: func() *Repository { + ret, err := NewRepository(rw, rw, testKms) require.NoError(t, err) return ret }(), @@ -45,7 +50,7 @@ func TestNewRepository(t *testing.T) { }, want: nil, wantErr: true, - wantErrString: "kms.NewRepository: nil writer: parameter violation: error #100", + wantErrString: "session.NewRepository: nil writer: parameter violation: error #100", }, { name: "nil-reader", @@ -55,13 +60,13 @@ func TestNewRepository(t *testing.T) { }, want: nil, wantErr: true, - wantErrString: "kms.NewRepository: nil reader: parameter violation: error #100", + wantErrString: "session.NewRepository: nil reader: parameter violation: error #100", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - got, err := kms.NewRepository(tt.args.r, tt.args.w) + got, err := NewRepository(tt.args.r, tt.args.w, tt.args.k) if tt.wantErr { require.Error(err) assert.Equal(tt.wantErrString, err.Error())