From 5ccb34378c4dac386f0e6df369d33fbedcf65316 Mon Sep 17 00:00:00 2001 From: Constantino Antunes Date: Fri, 17 Sep 2021 17:58:38 +0100 Subject: [PATCH 01/21] AST-3450: add base permission validation --- go.mod | 2 +- go.sum | 143 +------------------------------ internal/process.go | 48 +++++++++++ internal/process_test.go | 65 ++++++++++++++ internal/sast-client.go | 2 +- internal/sliceutils/main.go | 19 ++++ internal/sliceutils/main_test.go | 9 ++ 7 files changed, 145 insertions(+), 143 deletions(-) create mode 100644 internal/process_test.go diff --git a/go.mod b/go.mod index 379544f..0e7476e 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.16 require ( github.com/checkmarxDev/ast-observability-library v1.1.0 - github.com/pkg/errors v0.9.1 // indirect + github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/rs/zerolog v1.25.0 github.com/spf13/cobra v1.2.1 github.com/stretchr/testify v1.7.0 diff --git a/go.sum b/go.sum index 07a9aa7..35a5f28 100644 --- a/go.sum +++ b/go.sum @@ -17,103 +17,70 @@ cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKP 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 h1:at8Tk2zUz63cLPR0JPWm5vp77pEZmzxEQBEfRKn1VV8= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= 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= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0 h1:PQcPefKFdaIzjQFbiyOgAqyx8q5djaE7x9Sqe712DPA= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0 h1:/May9ojXjRkPBNVrq+oWLqmWCkr4OU5uRY29bu0mRyQ= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/firestore v1.1.0 h1:9x7Bx0A9R5/M9jibeJeZWqjeVEIxYW9fZYqB9a70/bY= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= 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 h1:ukjixP1wl0LpnZ6LWtZJ0mX5tBmjp1f8Sqer8Z2OMUU= cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= 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 h1:STgFzyU5/8miMl0//zKh2aQeTyeaUH3WN9bSUiJ09bA= 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 h1:VpgP7xuJadIUuKccphEpTJnWhS2jkQyMt6Y7pJCD7fY= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/antihax/optional v1.0.0 h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e h1:QEF07wC0T1rKkctt1RINW/+RMTVmiwxETico2l3gxJA= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 h1:BUAU3CGlLvorLI26FmByPp2eC2qla6E1Tw+scpcg/to= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bketelsen/crypt v0.0.4 h1:w/jqZtC9YD4DS/Vp9GhWfWcCpuAL58oTnLoI8vE9YHU= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= -github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/checkmarxDev/ast-observability-library v1.1.0 h1:PSu+crqOhj6M2fgovGGSSd2whAuKBZkkI81mkQpmiEY= github.com/checkmarxDev/ast-observability-library v1.1.0/go.mod h1:es+kjxYDaFOFJIG3ADVx3pi8BUwZwLxBJMV5Qn/88/M= -github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 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 h1:cqQfy1jclcSy/FwLjemeg3SR1yaINm74aQyupQ0Bl8M= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -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= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= 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 h1:QyzYnTnPE15SQyUeqU6qLbWxMkwyAyu+vGksa0b7j00= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1 h1:QbL/5oDUmRBzO9/Z7Seo6zf912W/a6Sr4Eu0G/3Jho0= 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 h1:WtGNWLvXpe6ZudgnXrq0barxBImvnnJoMEhXAzcbM0I= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 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 h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= @@ -122,7 +89,6 @@ 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 h1:jlYHihg//f7RRwuPfptm04yp4s7O6Kw8EZiVYIGcH0g= github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= 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= @@ -140,10 +106,8 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw 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/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 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= @@ -155,14 +119,10 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ 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 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= 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 h1:wCKgOCHuUEVfsaQLpPSJb7VdYCdTVZQAuOdYm1yc/60= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= 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= @@ -174,158 +134,95 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf 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 h1:zIaiqGYDQwa4HVx5wGRTXbx38Pqxjemn4BP98wpzpXo= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/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 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hashicorp/consul/api v1.1.0 h1:BNQPM9ytxj6jbjjdRPioQ94T6YXriSopn0i8COv6SRA= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/sdk v0.1.1 h1:LnuDWGNsoajlhGyHJvuWW6FVqRl8JOTPqS6CPTsYjhY= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-rootcerts v1.0.0 h1:Rqb66Oo1X/eSV1x66xbDccZjhJigjg0+e82kpwzSwCI= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-sockaddr v1.0.0 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sLo0ICXs= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-syslog v1.0.0 h1:KaodqZuhUoZereWVIYmpUgZysurB1kBLX2j0MwMrUAE= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go.net v0.0.1 h1:sNCoNyDEvN1xa+X0baata4RdcpKwcMS6DH+xwfqPgjw= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0 h1:WhIgCr5a7AaVH6jPUwjtRuuE7/RDufnUvzIr48smyxs= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3 h1:EmmoJme1matNzb+hMpDuR/0sbJSUisxyqBGG676r31M= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2 h1:YZ7UKsJv+hKjqGVUUbtE3HNj79Eln2oQ75tniF6iPt0= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 h1:mV02weKRL81bEnm8A0HT1/CAelMQDBuQIfLw8n+d6xI= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 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 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/kisielk/errcheck v1.5.0 h1:e8esj/e4R+SAOwFwN+n3zr0nYeCyeweozKfO23MvHzY= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= -github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-isatty v0.0.3 h1:ns/ykhmWi7G9O+8a448SecJU3nSMBXJfqQkl0upE1jI= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/miekg/dns v1.0.14 h1:9jZdLNd/P4+SfEJ0TNyxYpsK8N4GtfylBLqtbYN1sbA= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/mitchellh/cli v1.0.0 h1:iGBIsUe3+HZ/AD/Vd7DErOt5sU9fa8Uj7A2s1aggv1Y= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/gox v0.4.0 h1:lfGJxY7ToLJQjHHwi0EX6uYBdK78egf954SQl13PQJc= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0 h1:C+X3KsSTLFVBr/tK1eYN/vs4rJcvsiLU338UhYPJWeY= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c h1:Lgl0gzECD8GnQ5QCWA8o6BtfL6mDH5rQgM4/fX3avOs= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.10.1 h1:VasscCm72135zRysgrJDKsntdmPN+OuU3+nnHYA9wyc= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1 h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi2s= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.3.0 h1:RR9dF3JtopPvtkroDZuVD7qquD0bnHlKSqaQhgwt8yk= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= -github.com/rs/xid v1.3.0 h1:6NjYksEUlhurdVehpc7S7dk6DAmcKv8V9gG0FsVN2U4= github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.23.0/go.mod h1:6c7hFfxPOy7TacJc4Fcdi24/J0NKYGzjG8FWRI916Qo= github.com/rs/zerolog v1.25.0 h1:Rj7XygbUHKUlDPcVdoLyR91fJBsduXj5fRxyqIQj/II= github.com/rs/zerolog v1.25.0/go.mod h1:7KHcEGe0QZPOm2IE4Kpb5rTh6n1h2hIgS5OOnu1rUaI= -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/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f h1:UFr9zpz4xgTnIE5yIMtWAMngCdZ9p/+q6lTbgelo80M= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/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/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw= github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= -github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.8.1 h1:Kq1fyeebqsBfbjZj4EL7gj2IO0mMaiyjYUWcUsl2O44= github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= -github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -334,19 +231,14 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 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/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= 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 h1:dPmz1Snjq0kmkz159iL7S6WzdahUTHnHB5M56WFVifs= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -go.etcd.io/etcd/api/v3 v3.5.0 h1:GsV3S+OfZEOCNXdtNkBSR7kgLobAa/SO6tCxRa0GAYw= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/client/pkg/v3 v3.5.0 h1:2aQv6F436YnN7I4VbI8PPYrBhu+SmrTaADcf8Mi/6PU= go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/v2 v2.305.0 h1:ftQ0nOOHMcbMS3KIaDQ0g5Qcd6bhaBrQT6b89DfwLTs= go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= @@ -354,13 +246,9 @@ 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 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -368,7 +256,6 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -379,10 +266,8 @@ golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u0 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 h1:QE6XYQK6naiK1EPAe1g/ILLxN5RBoH5xkJk3CqlMI/Y= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/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= @@ -395,10 +280,8 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu 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 h1:4+4C/Iv2U4fMZBiMCc98MG1In4gJY5YRhtpDNeDeHWs= 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= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= @@ -408,7 +291,6 @@ 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 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 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= @@ -445,7 +327,6 @@ golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v 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 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -458,7 +339,6 @@ golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ 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-20210402161424-2e8d93401602 h1:0Ja1LBD+yisY6RWM/BH7TJVXWsSjs2VwBSmvSX4HdBc= golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 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= @@ -470,7 +350,6 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -512,9 +391,7 @@ golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -522,11 +399,9 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 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 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -579,12 +454,10 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f 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.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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= @@ -607,7 +480,6 @@ google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34q 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.44.0 h1:URs6qR1lAxDsqWITsQXI4ZkGiYJ5dHtRNiCpfs2OeKA= google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -615,7 +487,6 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 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/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -657,7 +528,6 @@ google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6D 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-20210602131652-f16073e35f0c h1:wtujag7C+4D6KMoulW9YauvK2lgdvCMS260jsqqBXr0= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -678,7 +548,6 @@ google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA5 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.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -691,19 +560,15 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= 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= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= @@ -714,11 +579,7 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 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 h1:UoveltGrhghAA7ePc+e+QYDHXrBps2PqFZiHkGR/xK8= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -rsc.io/binaryregexp v0.2.0 h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0 h1:9JKUTTIUgS6kzR9mK1YuGKv6Nl+DijDNIc0ghT58FaY= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/internal/process.go b/internal/process.go index b4a9a7c..6db2f27 100644 --- a/internal/process.go +++ b/internal/process.go @@ -9,6 +9,8 @@ import ( "strings" "time" + "github.com/dgrijalva/jwt-go" + "github.com/checkmarxDev/ast-sast-export/internal/sliceutils" "github.com/rs/zerolog/log" @@ -23,6 +25,11 @@ const ( reportType = "XML" scansFileName = "%d.xml" + + useOdataPermission = "use-odata" + generateScanReportPermission = "generate-scan-report" + manageAuthProviderPermission = "manage-authentication-providers" + manageRolesPermission = "manage-roles" ) type ReportConsumeOutput struct { @@ -68,6 +75,28 @@ func RunExport(args *Args) { Str("exportOptions", args.Export). Msgf("parsed export options") + // validate permissions + jwtClaims := jwt.MapClaims{} + _, _, jwtErr := new(jwt.Parser).ParseUnverified(client.Token.AccessToken, jwtClaims) + if jwtErr != nil { + log.Debug(). + Err(jwtErr). + Msg("permissions validation failed to parse jwt token") + panic(fmt.Errorf("permissions error - could not decode access token")) + } + availablePermissions := jwtClaims["sast-permissions"].([]interface{}) + requiredPermissions := sliceutils.ConvertStringToInterface(getPermissionsFromExportOptions(selectedExportOptions)) + missingPermissionsCount := 0 + for _, requiredPermission := range requiredPermissions { + if !sliceutils.Contains(requiredPermission, availablePermissions) { + missingPermissionsCount++ + log.Error().Msgf("missing permission: %s", requiredPermission) + } + } + if missingPermissionsCount > 0 { + panic(fmt.Errorf("please add missing permissions to your SAST user")) + } + // start export log.Info().Msg("collecting data from SAST") @@ -451,3 +480,22 @@ func retryGetReport(client *SASTClient, totalAttempts, reportID, projectID int, } return nil } + +func getPermissionsFromExportOptions(exportOptions []string) []string { + var output []string + + usersPermissions := []string{manageAuthProviderPermission, manageRolesPermission} + teamsPermissions := []string{manageAuthProviderPermission} + resultsPermissions := []string{useOdataPermission, generateScanReportPermission} + + for _, exportOption := range exportOptions { + if exportOption == usersExportOption { + output = append(output, usersPermissions...) + } else if exportOption == teamsExportOption { + output = append(output, teamsPermissions...) + } else if exportOption == resultsExportOption { + output = append(output, resultsPermissions...) + } + } + return sliceutils.ConvertInterfaceToString(sliceutils.Unique(sliceutils.ConvertStringToInterface(output))) +} diff --git a/internal/process_test.go b/internal/process_test.go new file mode 100644 index 0000000..bbd0279 --- /dev/null +++ b/internal/process_test.go @@ -0,0 +1,65 @@ +package internal + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestGetPermissionsFromExportOptions(t *testing.T) { + t.Run("users case", func(t *testing.T) { + exportOptions := []string{usersExportOption} + result := getPermissionsFromExportOptions(exportOptions) + + expected := []string{manageAuthProviderPermission, manageRolesPermission} + assert.ElementsMatch(t, expected, result) + }) + + t.Run("teams case", func(t *testing.T) { + exportOptions := []string{teamsExportOption} + result := getPermissionsFromExportOptions(exportOptions) + + expected := []string{manageAuthProviderPermission} + assert.ElementsMatch(t, expected, result) + }) + + t.Run("results case", func(t *testing.T) { + exportOptions := []string{resultsExportOption} + result := getPermissionsFromExportOptions(exportOptions) + + expected := []string{useOdataPermission, generateScanReportPermission} + assert.ElementsMatch(t, expected, result) + }) + + t.Run("users+teams case", func(t *testing.T) { + exportOptions := []string{usersExportOption, teamsExportOption} + result := getPermissionsFromExportOptions(exportOptions) + + expected := []string{manageAuthProviderPermission, manageRolesPermission} + assert.ElementsMatch(t, expected, result) + }) + + t.Run("users+results case", func(t *testing.T) { + exportOptions := []string{usersExportOption, resultsExportOption} + result := getPermissionsFromExportOptions(exportOptions) + + expected := []string{manageAuthProviderPermission, manageRolesPermission, useOdataPermission, generateScanReportPermission} + assert.ElementsMatch(t, expected, result) + }) + + t.Run("results+users case", func(t *testing.T) { + exportOptions := []string{resultsExportOption, usersExportOption} + result := getPermissionsFromExportOptions(exportOptions) + + expected := []string{manageAuthProviderPermission, manageRolesPermission, useOdataPermission, generateScanReportPermission} + assert.ElementsMatch(t, expected, result) + }) + + t.Run("results+teams case", func(t *testing.T) { + exportOptions := []string{teamsExportOption, resultsExportOption} + result := getPermissionsFromExportOptions(exportOptions) + + expected := []string{manageAuthProviderPermission, useOdataPermission, generateScanReportPermission} + assert.ElementsMatch(t, expected, result) + }) +} diff --git a/internal/sast-client.go b/internal/sast-client.go index 2236d71..46bc1be 100644 --- a/internal/sast-client.go +++ b/internal/sast-client.go @@ -100,7 +100,7 @@ func (c *SASTClient) Authenticate(username, password string) error { unmarshalErr := json.Unmarshal(responseBody, c.Token) if unmarshalErr != nil { logger.Debug(). - Err(ioErr). + Err(unmarshalErr). Str("responseBody", string(responseBody)). Msg("authenticate ok failed to unmarshal response") return fmt.Errorf("authentication error - could not decode response") diff --git a/internal/sliceutils/main.go b/internal/sliceutils/main.go index 960f7a8..8d879f0 100644 --- a/internal/sliceutils/main.go +++ b/internal/sliceutils/main.go @@ -9,6 +9,17 @@ func Contains(needle interface{}, data []interface{}) bool { return false } +func Unique(data []interface{}) []interface{} { + var out []interface{} + for _, v := range data { + if Contains(v, out) { + continue + } + out = append(out, v) + } + return out +} + func ConvertStringToInterface(data []string) []interface{} { out := make([]interface{}, len(data)) for i, v := range data { @@ -16,3 +27,11 @@ func ConvertStringToInterface(data []string) []interface{} { } return out } + +func ConvertInterfaceToString(data []interface{}) []string { + out := make([]string, len(data)) + for i, v := range data { + out[i] = v.(string) + } + return out +} diff --git a/internal/sliceutils/main_test.go b/internal/sliceutils/main_test.go index 40248d7..6388337 100644 --- a/internal/sliceutils/main_test.go +++ b/internal/sliceutils/main_test.go @@ -12,3 +12,12 @@ func TestContains(t *testing.T) { assert.False(t, Contains("foo", heap)) assert.True(t, Contains("bar", heap)) } + +func TestUnique(t *testing.T) { + heap := []interface{}{"a", "b", "c", "c", "d", "e", "f", "f", "g"} + + result := Unique(heap) + + expected := []interface{}{"a", "b", "c", "d", "e", "f", "g"} + assert.Equal(t, expected, result) +} From 2dfbfd8f30893bb6c629f850fb9e5d7616b297bf Mon Sep 17 00:00:00 2001 From: Constantino Antunes Date: Mon, 20 Sep 2021 09:59:17 +0100 Subject: [PATCH 02/21] AST-3450: create function for parsing permissions from claims --- internal/process.go | 21 ++++++++++++++++++++- internal/process_test.go | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/internal/process.go b/internal/process.go index 6db2f27..56f2438 100644 --- a/internal/process.go +++ b/internal/process.go @@ -84,7 +84,10 @@ func RunExport(args *Args) { Msg("permissions validation failed to parse jwt token") panic(fmt.Errorf("permissions error - could not decode access token")) } - availablePermissions := jwtClaims["sast-permissions"].([]interface{}) + availablePermissions, permissionErr := getPermissionsFromJwtClaims(jwtClaims) + if permissionErr != nil { + panic(fmt.Errorf("permissions error - could not parse available permissions")) + } requiredPermissions := sliceutils.ConvertStringToInterface(getPermissionsFromExportOptions(selectedExportOptions)) missingPermissionsCount := 0 for _, requiredPermission := range requiredPermissions { @@ -499,3 +502,19 @@ func getPermissionsFromExportOptions(exportOptions []string) []string { } return sliceutils.ConvertInterfaceToString(sliceutils.Unique(sliceutils.ConvertStringToInterface(output))) } + +func getPermissionsFromJwtClaims(claims jwt.MapClaims) ([]interface{}, error) { + sastPermissions, exists := claims["sast-permissions"] + if !exists { + return make([]interface{}, 0), nil + } + multiplePermissions, ok := sastPermissions.([]interface{}) + if ok { + return multiplePermissions, nil + } + singlePermission, ok := sastPermissions.(interface{}) + if ok { + return []interface{}{singlePermission}, nil + } + return make([]interface{}, 0), fmt.Errorf("could not parse permissions") +} diff --git a/internal/process_test.go b/internal/process_test.go index bbd0279..df0978d 100644 --- a/internal/process_test.go +++ b/internal/process_test.go @@ -3,6 +3,8 @@ package internal import ( "testing" + "github.com/dgrijalva/jwt-go" + "github.com/stretchr/testify/assert" ) @@ -63,3 +65,35 @@ func TestGetPermissionsFromExportOptions(t *testing.T) { assert.ElementsMatch(t, expected, result) }) } + +func TestGetPermissionsFromJwtClaims(t *testing.T) { + t.Run("claims without permission", func(t *testing.T) { + claims := jwt.MapClaims{"test": "test"} + + result, err := getPermissionsFromJwtClaims(claims) + + expected := make([]interface{}, 0) + assert.NoError(t, err) + assert.ElementsMatch(t, expected, result) + }) + + t.Run("claims with one permission", func(t *testing.T) { + claims := jwt.MapClaims{"test": "test", "sast-permissions": "use-odata"} + + result, err := getPermissionsFromJwtClaims(claims) + + expected := []interface{}{"use-odata"} + assert.NoError(t, err) + assert.ElementsMatch(t, expected, result) + }) + + t.Run("claims with more than one permission", func(t *testing.T) { + claims := jwt.MapClaims{"test": "test", "sast-permissions": []interface{}{"use-odata", "generate-scan-report"}} + + result, err := getPermissionsFromJwtClaims(claims) + + expected := []interface{}{"use-odata", "generate-scan-report"} + assert.NoError(t, err) + assert.ElementsMatch(t, expected, result) + }) +} From dbe1460c3919fb5f328d3355db47610f4a1dc93d Mon Sep 17 00:00:00 2001 From: Constantino Antunes Date: Mon, 20 Sep 2021 10:14:13 +0100 Subject: [PATCH 03/21] AST-3450: refactor get permissions from export options --- internal/process.go | 6 +++--- internal/process_test.go | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/internal/process.go b/internal/process.go index 56f2438..940bcf0 100644 --- a/internal/process.go +++ b/internal/process.go @@ -88,7 +88,7 @@ func RunExport(args *Args) { if permissionErr != nil { panic(fmt.Errorf("permissions error - could not parse available permissions")) } - requiredPermissions := sliceutils.ConvertStringToInterface(getPermissionsFromExportOptions(selectedExportOptions)) + requiredPermissions := getPermissionsFromExportOptions(selectedExportOptions) missingPermissionsCount := 0 for _, requiredPermission := range requiredPermissions { if !sliceutils.Contains(requiredPermission, availablePermissions) { @@ -484,7 +484,7 @@ func retryGetReport(client *SASTClient, totalAttempts, reportID, projectID int, return nil } -func getPermissionsFromExportOptions(exportOptions []string) []string { +func getPermissionsFromExportOptions(exportOptions []string) []interface{} { var output []string usersPermissions := []string{manageAuthProviderPermission, manageRolesPermission} @@ -500,7 +500,7 @@ func getPermissionsFromExportOptions(exportOptions []string) []string { output = append(output, resultsPermissions...) } } - return sliceutils.ConvertInterfaceToString(sliceutils.Unique(sliceutils.ConvertStringToInterface(output))) + return sliceutils.Unique(sliceutils.ConvertStringToInterface(output)) } func getPermissionsFromJwtClaims(claims jwt.MapClaims) ([]interface{}, error) { diff --git a/internal/process_test.go b/internal/process_test.go index df0978d..8cb778e 100644 --- a/internal/process_test.go +++ b/internal/process_test.go @@ -13,7 +13,7 @@ func TestGetPermissionsFromExportOptions(t *testing.T) { exportOptions := []string{usersExportOption} result := getPermissionsFromExportOptions(exportOptions) - expected := []string{manageAuthProviderPermission, manageRolesPermission} + expected := []interface{}{manageAuthProviderPermission, manageRolesPermission} assert.ElementsMatch(t, expected, result) }) @@ -21,7 +21,7 @@ func TestGetPermissionsFromExportOptions(t *testing.T) { exportOptions := []string{teamsExportOption} result := getPermissionsFromExportOptions(exportOptions) - expected := []string{manageAuthProviderPermission} + expected := []interface{}{manageAuthProviderPermission} assert.ElementsMatch(t, expected, result) }) @@ -29,7 +29,7 @@ func TestGetPermissionsFromExportOptions(t *testing.T) { exportOptions := []string{resultsExportOption} result := getPermissionsFromExportOptions(exportOptions) - expected := []string{useOdataPermission, generateScanReportPermission} + expected := []interface{}{useOdataPermission, generateScanReportPermission} assert.ElementsMatch(t, expected, result) }) @@ -37,7 +37,7 @@ func TestGetPermissionsFromExportOptions(t *testing.T) { exportOptions := []string{usersExportOption, teamsExportOption} result := getPermissionsFromExportOptions(exportOptions) - expected := []string{manageAuthProviderPermission, manageRolesPermission} + expected := []interface{}{manageAuthProviderPermission, manageRolesPermission} assert.ElementsMatch(t, expected, result) }) @@ -45,7 +45,7 @@ func TestGetPermissionsFromExportOptions(t *testing.T) { exportOptions := []string{usersExportOption, resultsExportOption} result := getPermissionsFromExportOptions(exportOptions) - expected := []string{manageAuthProviderPermission, manageRolesPermission, useOdataPermission, generateScanReportPermission} + expected := []interface{}{manageAuthProviderPermission, manageRolesPermission, useOdataPermission, generateScanReportPermission} assert.ElementsMatch(t, expected, result) }) @@ -53,7 +53,7 @@ func TestGetPermissionsFromExportOptions(t *testing.T) { exportOptions := []string{resultsExportOption, usersExportOption} result := getPermissionsFromExportOptions(exportOptions) - expected := []string{manageAuthProviderPermission, manageRolesPermission, useOdataPermission, generateScanReportPermission} + expected := []interface{}{manageAuthProviderPermission, manageRolesPermission, useOdataPermission, generateScanReportPermission} assert.ElementsMatch(t, expected, result) }) @@ -61,7 +61,7 @@ func TestGetPermissionsFromExportOptions(t *testing.T) { exportOptions := []string{teamsExportOption, resultsExportOption} result := getPermissionsFromExportOptions(exportOptions) - expected := []string{manageAuthProviderPermission, useOdataPermission, generateScanReportPermission} + expected := []interface{}{manageAuthProviderPermission, useOdataPermission, generateScanReportPermission} assert.ElementsMatch(t, expected, result) }) } From f3590544bd278edc28f3ab7b9a883c7ed1ec73d1 Mon Sep 17 00:00:00 2001 From: Constantino Antunes Date: Mon, 20 Sep 2021 11:12:23 +0100 Subject: [PATCH 04/21] AST-3450: parse access control permissions --- internal/process.go | 15 ++++++++++----- internal/process_test.go | 12 +++++++----- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/internal/process.go b/internal/process.go index 940bcf0..5de84fd 100644 --- a/internal/process.go +++ b/internal/process.go @@ -84,10 +84,15 @@ func RunExport(args *Args) { Msg("permissions validation failed to parse jwt token") panic(fmt.Errorf("permissions error - could not decode access token")) } - availablePermissions, permissionErr := getPermissionsFromJwtClaims(jwtClaims) - if permissionErr != nil { - panic(fmt.Errorf("permissions error - could not parse available permissions")) + sastPermissions, sastPermissionErr := getPermissionsFromJwtClaim(jwtClaims, "sast-permissions") + if sastPermissionErr != nil { + panic(fmt.Errorf("permissions error - could not parse SAST permissions")) } + accessControlPermissions, accessControlPermissionErr := getPermissionsFromJwtClaim(jwtClaims, "access-control-permissions") + if accessControlPermissionErr != nil { + panic(fmt.Errorf("permissions error - could not parse Access Control permissions")) + } + availablePermissions := append(sastPermissions, accessControlPermissions...) requiredPermissions := getPermissionsFromExportOptions(selectedExportOptions) missingPermissionsCount := 0 for _, requiredPermission := range requiredPermissions { @@ -503,8 +508,8 @@ func getPermissionsFromExportOptions(exportOptions []string) []interface{} { return sliceutils.Unique(sliceutils.ConvertStringToInterface(output)) } -func getPermissionsFromJwtClaims(claims jwt.MapClaims) ([]interface{}, error) { - sastPermissions, exists := claims["sast-permissions"] +func getPermissionsFromJwtClaim(claims jwt.MapClaims, key string) ([]interface{}, error) { + sastPermissions, exists := claims[key] if !exists { return make([]interface{}, 0), nil } diff --git a/internal/process_test.go b/internal/process_test.go index 8cb778e..b3af53c 100644 --- a/internal/process_test.go +++ b/internal/process_test.go @@ -67,10 +67,12 @@ func TestGetPermissionsFromExportOptions(t *testing.T) { } func TestGetPermissionsFromJwtClaims(t *testing.T) { + key := "permissions" + t.Run("claims without permission", func(t *testing.T) { claims := jwt.MapClaims{"test": "test"} - result, err := getPermissionsFromJwtClaims(claims) + result, err := getPermissionsFromJwtClaim(claims, key) expected := make([]interface{}, 0) assert.NoError(t, err) @@ -78,9 +80,9 @@ func TestGetPermissionsFromJwtClaims(t *testing.T) { }) t.Run("claims with one permission", func(t *testing.T) { - claims := jwt.MapClaims{"test": "test", "sast-permissions": "use-odata"} + claims := jwt.MapClaims{"test": "test", "permissions": "use-odata"} - result, err := getPermissionsFromJwtClaims(claims) + result, err := getPermissionsFromJwtClaim(claims, key) expected := []interface{}{"use-odata"} assert.NoError(t, err) @@ -88,9 +90,9 @@ func TestGetPermissionsFromJwtClaims(t *testing.T) { }) t.Run("claims with more than one permission", func(t *testing.T) { - claims := jwt.MapClaims{"test": "test", "sast-permissions": []interface{}{"use-odata", "generate-scan-report"}} + claims := jwt.MapClaims{"test": "test", "permissions": []interface{}{"use-odata", "generate-scan-report"}} - result, err := getPermissionsFromJwtClaims(claims) + result, err := getPermissionsFromJwtClaim(claims, key) expected := []interface{}{"use-odata", "generate-scan-report"} assert.NoError(t, err) From a85df47c11304dad4ae2345e9d75b0a37c5dce97 Mon Sep 17 00:00:00 2001 From: Constantino Antunes Date: Mon, 20 Sep 2021 11:31:49 +0100 Subject: [PATCH 05/21] AST-3450: refactor permissions --- internal/export/export.go | 7 ++ internal/permissions/permissions.go | 51 +++++++++++ internal/permissions/permissions_test.go | 103 +++++++++++++++++++++++ internal/process.go | 74 ++++------------ 4 files changed, 176 insertions(+), 59 deletions(-) create mode 100644 internal/export/export.go create mode 100644 internal/permissions/permissions.go create mode 100644 internal/permissions/permissions_test.go diff --git a/internal/export/export.go b/internal/export/export.go new file mode 100644 index 0000000..8f167b8 --- /dev/null +++ b/internal/export/export.go @@ -0,0 +1,7 @@ +package export + +const ( + UsersOption = "users" + TeamsOption = "teams" + ResultsOption = "results" +) diff --git a/internal/permissions/permissions.go b/internal/permissions/permissions.go new file mode 100644 index 0000000..830c980 --- /dev/null +++ b/internal/permissions/permissions.go @@ -0,0 +1,51 @@ +package permissions + +import ( + "fmt" + + "github.com/checkmarxDev/ast-sast-export/internal/export" + "github.com/checkmarxDev/ast-sast-export/internal/sliceutils" + "github.com/dgrijalva/jwt-go" +) + +const ( + useOdataPermission = "use-odata" + generateScanReportPermission = "generate-scan-report" + manageAuthProviderPermission = "manage-authentication-providers" + manageRolesPermission = "manage-roles" +) + +func GetFromExportOptions(exportOptions []string) []interface{} { + var output []string + + usersPermissions := []string{manageAuthProviderPermission, manageRolesPermission} + teamsPermissions := []string{manageAuthProviderPermission} + resultsPermissions := []string{useOdataPermission, generateScanReportPermission} + + for _, exportOption := range exportOptions { + if exportOption == export.UsersOption { + output = append(output, usersPermissions...) + } else if exportOption == export.TeamsOption { + output = append(output, teamsPermissions...) + } else if exportOption == export.ResultsOption { + output = append(output, resultsPermissions...) + } + } + return sliceutils.Unique(sliceutils.ConvertStringToInterface(output)) +} + +func GetFromJwtClaim(claims jwt.MapClaims, key string) ([]interface{}, error) { + sastPermissions, exists := claims[key] + if !exists { + return make([]interface{}, 0), nil + } + multiplePermissions, ok := sastPermissions.([]interface{}) + if ok { + return multiplePermissions, nil + } + singlePermission, ok := sastPermissions.(interface{}) + if ok { + return []interface{}{singlePermission}, nil + } + return make([]interface{}, 0), fmt.Errorf("could not parse permissions") +} diff --git a/internal/permissions/permissions_test.go b/internal/permissions/permissions_test.go new file mode 100644 index 0000000..0a066b2 --- /dev/null +++ b/internal/permissions/permissions_test.go @@ -0,0 +1,103 @@ +package permissions + +import ( + "testing" + + "github.com/checkmarxDev/ast-sast-export/internal/export" + + "github.com/dgrijalva/jwt-go" + + "github.com/stretchr/testify/assert" +) + +func TestGetFromExportOptions(t *testing.T) { + t.Run("users case", func(t *testing.T) { + exportOptions := []string{export.UsersOption} + result := GetFromExportOptions(exportOptions) + + expected := []interface{}{manageAuthProviderPermission, manageRolesPermission} + assert.ElementsMatch(t, expected, result) + }) + + t.Run("teams case", func(t *testing.T) { + exportOptions := []string{export.TeamsOption} + result := GetFromExportOptions(exportOptions) + + expected := []interface{}{manageAuthProviderPermission} + assert.ElementsMatch(t, expected, result) + }) + + t.Run("results case", func(t *testing.T) { + exportOptions := []string{export.ResultsOption} + result := GetFromExportOptions(exportOptions) + + expected := []interface{}{useOdataPermission, generateScanReportPermission} + assert.ElementsMatch(t, expected, result) + }) + + t.Run("users+teams case", func(t *testing.T) { + exportOptions := []string{export.UsersOption, export.TeamsOption} + result := GetFromExportOptions(exportOptions) + + expected := []interface{}{manageAuthProviderPermission, manageRolesPermission} + assert.ElementsMatch(t, expected, result) + }) + + t.Run("users+results case", func(t *testing.T) { + exportOptions := []string{export.UsersOption, export.ResultsOption} + result := GetFromExportOptions(exportOptions) + + expected := []interface{}{manageAuthProviderPermission, manageRolesPermission, useOdataPermission, generateScanReportPermission} + assert.ElementsMatch(t, expected, result) + }) + + t.Run("results+users case", func(t *testing.T) { + exportOptions := []string{export.ResultsOption, export.UsersOption} + result := GetFromExportOptions(exportOptions) + + expected := []interface{}{manageAuthProviderPermission, manageRolesPermission, useOdataPermission, generateScanReportPermission} + assert.ElementsMatch(t, expected, result) + }) + + t.Run("results+teams case", func(t *testing.T) { + exportOptions := []string{export.TeamsOption, export.ResultsOption} + result := GetFromExportOptions(exportOptions) + + expected := []interface{}{manageAuthProviderPermission, useOdataPermission, generateScanReportPermission} + assert.ElementsMatch(t, expected, result) + }) +} + +func TestGetFromJwtClaims(t *testing.T) { + key := "permissions" + + t.Run("claims without permission", func(t *testing.T) { + claims := jwt.MapClaims{"test": "test"} + + result, err := GetFromJwtClaim(claims, key) + + expected := make([]interface{}, 0) + assert.NoError(t, err) + assert.ElementsMatch(t, expected, result) + }) + + t.Run("claims with one permission", func(t *testing.T) { + claims := jwt.MapClaims{"test": "test", "permissions": "use-odata"} + + result, err := GetFromJwtClaim(claims, key) + + expected := []interface{}{"use-odata"} + assert.NoError(t, err) + assert.ElementsMatch(t, expected, result) + }) + + t.Run("claims with more than one permission", func(t *testing.T) { + claims := jwt.MapClaims{"test": "test", "permissions": []interface{}{"use-odata", "generate-scan-report"}} + + result, err := GetFromJwtClaim(claims, key) + + expected := []interface{}{"use-odata", "generate-scan-report"} + assert.NoError(t, err) + assert.ElementsMatch(t, expected, result) + }) +} diff --git a/internal/process.go b/internal/process.go index 5de84fd..b15487c 100644 --- a/internal/process.go +++ b/internal/process.go @@ -9,27 +9,18 @@ import ( "strings" "time" - "github.com/dgrijalva/jwt-go" - + "github.com/checkmarxDev/ast-sast-export/internal/export" + "github.com/checkmarxDev/ast-sast-export/internal/permissions" "github.com/checkmarxDev/ast-sast-export/internal/sliceutils" - + "github.com/dgrijalva/jwt-go" "github.com/rs/zerolog/log" ) const ( createdStatus = "Created" - usersExportOption = "users" - teamsExportOption = "teams" - resultsExportOption = "results" - reportType = "XML" scansFileName = "%d.xml" - - useOdataPermission = "use-odata" - generateScanReportPermission = "generate-scan-report" - manageAuthProviderPermission = "manage-authentication-providers" - manageRolesPermission = "manage-roles" ) type ReportConsumeOutput struct { @@ -67,7 +58,7 @@ func RunExport(args *Args) { if args.Export != "" { selectedExportOptions = strings.Split(args.Export, ",") } else { - selectedExportOptions = []string{usersExportOption, resultsExportOption, teamsExportOption} + selectedExportOptions = []string{export.UsersOption, export.ResultsOption, export.TeamsOption} } args.Export = strings.Join(selectedExportOptions, ",") @@ -84,16 +75,16 @@ func RunExport(args *Args) { Msg("permissions validation failed to parse jwt token") panic(fmt.Errorf("permissions error - could not decode access token")) } - sastPermissions, sastPermissionErr := getPermissionsFromJwtClaim(jwtClaims, "sast-permissions") + sastPermissions, sastPermissionErr := permissions.GetFromJwtClaim(jwtClaims, "sast-permissions") if sastPermissionErr != nil { panic(fmt.Errorf("permissions error - could not parse SAST permissions")) } - accessControlPermissions, accessControlPermissionErr := getPermissionsFromJwtClaim(jwtClaims, "access-control-permissions") + accessControlPermissions, accessControlPermissionErr := permissions.GetFromJwtClaim(jwtClaims, "access-control-permissions") if accessControlPermissionErr != nil { panic(fmt.Errorf("permissions error - could not parse Access Control permissions")) } availablePermissions := append(sastPermissions, accessControlPermissions...) - requiredPermissions := getPermissionsFromExportOptions(selectedExportOptions) + requiredPermissions := permissions.GetFromExportOptions(selectedExportOptions) missingPermissionsCount := 0 for _, requiredPermission := range requiredPermissions { if !sliceutils.Contains(requiredPermission, availablePermissions) { @@ -123,23 +114,23 @@ func RunExport(args *Args) { }(&exportValues) } - availableExportOptions := []string{usersExportOption, teamsExportOption, resultsExportOption} + availableExportOptions := []string{export.UsersOption, export.TeamsOption, export.ResultsOption} for _, exportOption := range availableExportOptions { if sliceutils.Contains(exportOption, sliceutils.ConvertStringToInterface(selectedExportOptions)) { log.Info().Msgf("collecting %s", exportOption) switch exportOption { - case usersExportOption: + case export.UsersOption: if err = fetchUsersData(client); err != nil { log.Error().Err(err) panic(err) } - case teamsExportOption: + case export.TeamsOption: if err = fetchTeamsData(client); err != nil { log.Error().Err(err) panic(err) } - case resultsExportOption: + case export.ResultsOption: if err = fetchResultsData(client, args); err != nil { log.Error().Err(err) panic(err) @@ -160,7 +151,7 @@ func RunExport(args *Args) { func ExportResultsToFile(args *Args, exportValues *Export) (*string, error) { - if strings.Contains(args.Export, usersExportOption) { + if strings.Contains(args.Export, export.UsersOption) { if exportErr := exportValues.AddFile(UsersFileName, usersData); exportErr != nil { return nil, exportErr } @@ -178,7 +169,7 @@ func ExportResultsToFile(args *Args, exportValues *Export) (*string, error) { } } - if strings.Contains(args.Export, resultsExportOption) { + if strings.Contains(args.Export, export.ResultsOption) { for _, res := range exportData { if exportErr := exportValues.AddFile(res.FileName, res.Data); exportErr != nil { return nil, exportErr @@ -186,7 +177,7 @@ func ExportResultsToFile(args *Args, exportValues *Export) (*string, error) { } } - if strings.Contains(args.Export, teamsExportOption) { + if strings.Contains(args.Export, export.TeamsOption) { if exportErr := exportValues.AddFile(TeamsFileName, teamsData); exportErr != nil { return nil, exportErr } @@ -200,7 +191,7 @@ func ExportResultsToFile(args *Args, exportValues *Export) (*string, error) { } } - if strings.Contains(args.Export, usersExportOption) || strings.Contains(args.Export, teamsExportOption) { + if strings.Contains(args.Export, export.UsersOption) || strings.Contains(args.Export, export.TeamsOption) { if exportErr := exportValues.AddFile(LdapServersFileName, ldapServersData); exportErr != nil { return nil, exportErr } @@ -488,38 +479,3 @@ func retryGetReport(client *SASTClient, totalAttempts, reportID, projectID int, } return nil } - -func getPermissionsFromExportOptions(exportOptions []string) []interface{} { - var output []string - - usersPermissions := []string{manageAuthProviderPermission, manageRolesPermission} - teamsPermissions := []string{manageAuthProviderPermission} - resultsPermissions := []string{useOdataPermission, generateScanReportPermission} - - for _, exportOption := range exportOptions { - if exportOption == usersExportOption { - output = append(output, usersPermissions...) - } else if exportOption == teamsExportOption { - output = append(output, teamsPermissions...) - } else if exportOption == resultsExportOption { - output = append(output, resultsPermissions...) - } - } - return sliceutils.Unique(sliceutils.ConvertStringToInterface(output)) -} - -func getPermissionsFromJwtClaim(claims jwt.MapClaims, key string) ([]interface{}, error) { - sastPermissions, exists := claims[key] - if !exists { - return make([]interface{}, 0), nil - } - multiplePermissions, ok := sastPermissions.([]interface{}) - if ok { - return multiplePermissions, nil - } - singlePermission, ok := sastPermissions.(interface{}) - if ok { - return []interface{}{singlePermission}, nil - } - return make([]interface{}, 0), fmt.Errorf("could not parse permissions") -} From 9f0a340dabb3da938bacdf6cb64c7184c94a99b0 Mon Sep 17 00:00:00 2001 From: Constantino Antunes Date: Mon, 20 Sep 2021 11:32:07 +0100 Subject: [PATCH 06/21] AST-3450: remove unnecessary file --- internal/process_test.go | 101 --------------------------------------- 1 file changed, 101 deletions(-) delete mode 100644 internal/process_test.go diff --git a/internal/process_test.go b/internal/process_test.go deleted file mode 100644 index b3af53c..0000000 --- a/internal/process_test.go +++ /dev/null @@ -1,101 +0,0 @@ -package internal - -import ( - "testing" - - "github.com/dgrijalva/jwt-go" - - "github.com/stretchr/testify/assert" -) - -func TestGetPermissionsFromExportOptions(t *testing.T) { - t.Run("users case", func(t *testing.T) { - exportOptions := []string{usersExportOption} - result := getPermissionsFromExportOptions(exportOptions) - - expected := []interface{}{manageAuthProviderPermission, manageRolesPermission} - assert.ElementsMatch(t, expected, result) - }) - - t.Run("teams case", func(t *testing.T) { - exportOptions := []string{teamsExportOption} - result := getPermissionsFromExportOptions(exportOptions) - - expected := []interface{}{manageAuthProviderPermission} - assert.ElementsMatch(t, expected, result) - }) - - t.Run("results case", func(t *testing.T) { - exportOptions := []string{resultsExportOption} - result := getPermissionsFromExportOptions(exportOptions) - - expected := []interface{}{useOdataPermission, generateScanReportPermission} - assert.ElementsMatch(t, expected, result) - }) - - t.Run("users+teams case", func(t *testing.T) { - exportOptions := []string{usersExportOption, teamsExportOption} - result := getPermissionsFromExportOptions(exportOptions) - - expected := []interface{}{manageAuthProviderPermission, manageRolesPermission} - assert.ElementsMatch(t, expected, result) - }) - - t.Run("users+results case", func(t *testing.T) { - exportOptions := []string{usersExportOption, resultsExportOption} - result := getPermissionsFromExportOptions(exportOptions) - - expected := []interface{}{manageAuthProviderPermission, manageRolesPermission, useOdataPermission, generateScanReportPermission} - assert.ElementsMatch(t, expected, result) - }) - - t.Run("results+users case", func(t *testing.T) { - exportOptions := []string{resultsExportOption, usersExportOption} - result := getPermissionsFromExportOptions(exportOptions) - - expected := []interface{}{manageAuthProviderPermission, manageRolesPermission, useOdataPermission, generateScanReportPermission} - assert.ElementsMatch(t, expected, result) - }) - - t.Run("results+teams case", func(t *testing.T) { - exportOptions := []string{teamsExportOption, resultsExportOption} - result := getPermissionsFromExportOptions(exportOptions) - - expected := []interface{}{manageAuthProviderPermission, useOdataPermission, generateScanReportPermission} - assert.ElementsMatch(t, expected, result) - }) -} - -func TestGetPermissionsFromJwtClaims(t *testing.T) { - key := "permissions" - - t.Run("claims without permission", func(t *testing.T) { - claims := jwt.MapClaims{"test": "test"} - - result, err := getPermissionsFromJwtClaim(claims, key) - - expected := make([]interface{}, 0) - assert.NoError(t, err) - assert.ElementsMatch(t, expected, result) - }) - - t.Run("claims with one permission", func(t *testing.T) { - claims := jwt.MapClaims{"test": "test", "permissions": "use-odata"} - - result, err := getPermissionsFromJwtClaim(claims, key) - - expected := []interface{}{"use-odata"} - assert.NoError(t, err) - assert.ElementsMatch(t, expected, result) - }) - - t.Run("claims with more than one permission", func(t *testing.T) { - claims := jwt.MapClaims{"test": "test", "permissions": []interface{}{"use-odata", "generate-scan-report"}} - - result, err := getPermissionsFromJwtClaim(claims, key) - - expected := []interface{}{"use-odata", "generate-scan-report"} - assert.NoError(t, err) - assert.ElementsMatch(t, expected, result) - }) -} From 0d6f84030e6a3ee3717dc3ab0236c1f52bf49f4e Mon Sep 17 00:00:00 2001 From: Constantino Antunes Date: Mon, 20 Sep 2021 11:32:50 +0100 Subject: [PATCH 07/21] AST-3450: refactor sliceutils --- internal/sliceutils/{main.go => sliceutils.go} | 0 internal/sliceutils/{main_test.go => sliceutils_test.go} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename internal/sliceutils/{main.go => sliceutils.go} (100%) rename internal/sliceutils/{main_test.go => sliceutils_test.go} (100%) diff --git a/internal/sliceutils/main.go b/internal/sliceutils/sliceutils.go similarity index 100% rename from internal/sliceutils/main.go rename to internal/sliceutils/sliceutils.go diff --git a/internal/sliceutils/main_test.go b/internal/sliceutils/sliceutils_test.go similarity index 100% rename from internal/sliceutils/main_test.go rename to internal/sliceutils/sliceutils_test.go From a97cab1d038b3132655d8dea3f0dfd8a4eb4de41 Mon Sep 17 00:00:00 2001 From: Constantino Antunes Date: Mon, 20 Sep 2021 11:37:52 +0100 Subject: [PATCH 08/21] AST-3450: document process and refactor export options --- internal/export/export.go | 4 ++++ internal/process.go | 14 ++++++-------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/internal/export/export.go b/internal/export/export.go index 8f167b8..20f849b 100644 --- a/internal/export/export.go +++ b/internal/export/export.go @@ -5,3 +5,7 @@ const ( TeamsOption = "teams" ResultsOption = "results" ) + +func GetOptions() []string { + return []string{UsersOption, TeamsOption, ResultsOption} +} diff --git a/internal/process.go b/internal/process.go index b15487c..53bec69 100644 --- a/internal/process.go +++ b/internal/process.go @@ -42,13 +42,14 @@ func RunExport(args *Args) { Int("consumers", consumerCount). Msg("starting export") - // create api client and authenticate + // create api client client, err := NewSASTClient(args.URL, &http.Client{}) if err != nil { log.Error().Err(err) panic(err) } + // authenticate log.Info().Msg("connecting to SAST") if authErr := client.Authenticate(args.Username, args.Password); authErr != nil { log.Error().Err(authErr) @@ -58,7 +59,7 @@ func RunExport(args *Args) { if args.Export != "" { selectedExportOptions = strings.Split(args.Export, ",") } else { - selectedExportOptions = []string{export.UsersOption, export.ResultsOption, export.TeamsOption} + selectedExportOptions = export.GetOptions() } args.Export = strings.Join(selectedExportOptions, ",") @@ -96,9 +97,8 @@ func RunExport(args *Args) { panic(fmt.Errorf("please add missing permissions to your SAST user")) } - // start export + // collect export data log.Info().Msg("collecting data from SAST") - exportValues, exportCreateErr := CreateExport(args.ProductName) if exportCreateErr != nil { log.Error().Err(exportCreateErr) @@ -114,9 +114,7 @@ func RunExport(args *Args) { }(&exportValues) } - availableExportOptions := []string{export.UsersOption, export.TeamsOption, export.ResultsOption} - - for _, exportOption := range availableExportOptions { + for _, exportOption := range export.GetOptions() { if sliceutils.Contains(exportOption, sliceutils.ConvertStringToInterface(selectedExportOptions)) { log.Info().Msgf("collecting %s", exportOption) switch exportOption { @@ -139,8 +137,8 @@ func RunExport(args *Args) { } } + // export data to file log.Info().Msg("exporting collected data") - exportFileName, exportErr := ExportResultsToFile(args, &exportValues) if exportErr != nil { log.Error().Err(exportErr).Msg("error exporting collected data") From 6e1c98e58f9c59a501938deac12110c6ff9ef896 Mon Sep 17 00:00:00 2001 From: Constantino Antunes Date: Mon, 20 Sep 2021 12:05:09 +0100 Subject: [PATCH 09/21] AST-3450: refactor and add unit tests --- internal/process.go | 63 ++++++++++++++++++---------- internal/process_test.go | 91 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+), 23 deletions(-) create mode 100644 internal/process_test.go diff --git a/internal/process.go b/internal/process.go index 53bec69..4cad89f 100644 --- a/internal/process.go +++ b/internal/process.go @@ -31,7 +31,6 @@ type ReportConsumeOutput struct { func RunExport(args *Args) { isDebug = args.Debug - var selectedExportOptions []string consumerCount := GetNumCPU() log.Debug(). @@ -42,6 +41,9 @@ func RunExport(args *Args) { Int("consumers", consumerCount). Msg("starting export") + selectedExportOptions := getSelectedExportOptions(args.Export, export.GetOptions()) + args.Export = strings.Join(selectedExportOptions, ",") + // create api client client, err := NewSASTClient(args.URL, &http.Client{}) if err != nil { @@ -56,13 +58,6 @@ func RunExport(args *Args) { panic(authErr) } - if args.Export != "" { - selectedExportOptions = strings.Split(args.Export, ",") - } else { - selectedExportOptions = export.GetOptions() - } - args.Export = strings.Join(selectedExportOptions, ",") - log.Debug(). Str("exportOptions", args.Export). Msgf("parsed export options") @@ -76,24 +71,16 @@ func RunExport(args *Args) { Msg("permissions validation failed to parse jwt token") panic(fmt.Errorf("permissions error - could not decode access token")) } - sastPermissions, sastPermissionErr := permissions.GetFromJwtClaim(jwtClaims, "sast-permissions") - if sastPermissionErr != nil { - panic(fmt.Errorf("permissions error - could not parse SAST permissions")) - } - accessControlPermissions, accessControlPermissionErr := permissions.GetFromJwtClaim(jwtClaims, "access-control-permissions") - if accessControlPermissionErr != nil { - panic(fmt.Errorf("permissions error - could not parse Access Control permissions")) + availablePermissions, availablePermissionsErr := getAvailablePermissions(jwtClaims) + if availablePermissionsErr != nil { + panic(fmt.Errorf("permissions error - %s", availablePermissionsErr.Error())) } - availablePermissions := append(sastPermissions, accessControlPermissions...) requiredPermissions := permissions.GetFromExportOptions(selectedExportOptions) - missingPermissionsCount := 0 - for _, requiredPermission := range requiredPermissions { - if !sliceutils.Contains(requiredPermission, availablePermissions) { - missingPermissionsCount++ - log.Error().Msgf("missing permission: %s", requiredPermission) + missingPermissions := getMissingPermissions(requiredPermissions, availablePermissions) + if len(missingPermissions) > 0 { + for _, permission := range missingPermissions { + log.Error().Msgf("missing permission: %s", permission) } - } - if missingPermissionsCount > 0 { panic(fmt.Errorf("please add missing permissions to your SAST user")) } @@ -477,3 +464,33 @@ func retryGetReport(client *SASTClient, totalAttempts, reportID, projectID int, } return nil } + +func getMissingPermissions(requiredPermissions, availablePermissions []interface{}) []interface{} { + output := make([]interface{}, 0) + for _, requiredPermission := range requiredPermissions { + if !sliceutils.Contains(requiredPermission, availablePermissions) { + output = append(output, requiredPermission) + } + } + return output +} + +func getAvailablePermissions(jwtClaims jwt.MapClaims) ([]interface{}, error) { + sastPermissions, sastPermissionErr := permissions.GetFromJwtClaim(jwtClaims, "sast-permissions") + if sastPermissionErr != nil { + return nil, fmt.Errorf("could not parse SAST permissions") + } + accessControlPermissions, accessControlPermissionErr := permissions.GetFromJwtClaim(jwtClaims, "access-control-permissions") + if accessControlPermissionErr != nil { + return nil, fmt.Errorf("could not parse Access Control permissions") + } + availablePermissions := append(sastPermissions, accessControlPermissions...) + return availablePermissions, nil +} + +func getSelectedExportOptions(selected string, defaultValue []string) []string { + if selected != "" { + return strings.Split(selected, ",") + } + return defaultValue +} diff --git a/internal/process_test.go b/internal/process_test.go new file mode 100644 index 0000000..add9f98 --- /dev/null +++ b/internal/process_test.go @@ -0,0 +1,91 @@ +package internal + +import ( + "testing" + + "github.com/dgrijalva/jwt-go" + "github.com/stretchr/testify/assert" +) + +func TestGetMissingPermissions(t *testing.T) { + t.Run("empty lists return empty list", func(t *testing.T) { + requiredPermissions := make([]interface{}, 0) + availablePermissions := make([]interface{}, 0) + + result := getMissingPermissions(requiredPermissions, availablePermissions) + + expected := make([]interface{}, 0) + assert.ElementsMatch(t, expected, result) + }) + + t.Run("empty required return empty list", func(t *testing.T) { + requiredPermissions := make([]interface{}, 0) + availablePermissions := []interface{}{"a", "b", "c"} + + result := getMissingPermissions(requiredPermissions, availablePermissions) + + expected := make([]interface{}, 0) + assert.ElementsMatch(t, expected, result) + }) + + t.Run("more available than required return empty list", func(t *testing.T) { + requiredPermissions := []interface{}{"a", "b"} + availablePermissions := []interface{}{"a", "b", "c"} + + result := getMissingPermissions(requiredPermissions, availablePermissions) + + expected := make([]interface{}, 0) + assert.ElementsMatch(t, expected, result) + }) + + t.Run("missing one returns one item", func(t *testing.T) { + requiredPermissions := []interface{}{"a", "b", "c"} + availablePermissions := []interface{}{"a", "b"} + + result := getMissingPermissions(requiredPermissions, availablePermissions) + + expected := []interface{}{"c"} + assert.ElementsMatch(t, expected, result) + }) + + t.Run("missing many returns many items", func(t *testing.T) { + requiredPermissions := []interface{}{"a", "b", "c", "d", "e", "f"} + availablePermissions := []interface{}{"a", "b", "d", "f"} + + result := getMissingPermissions(requiredPermissions, availablePermissions) + + expected := []interface{}{"c", "e"} + assert.ElementsMatch(t, expected, result) + }) +} + +func TestGetAvailablePermissions(t *testing.T) { + claims := jwt.MapClaims{ + "sast-permissions": []interface{}{"a", "b"}, + "access-control-permissions": []interface{}{"c", "d"}, + } + + result, err := getAvailablePermissions(claims) + + expected := []interface{}{"a", "b", "c", "d"} + assert.NoError(t, err) + assert.ElementsMatch(t, expected, result) +} + +func TestGetSelectedExportOptions(t *testing.T) { + defaultOptions := []string{"a", "b", "c"} + + t.Run("empty falls back to default", func(t *testing.T) { + result := getSelectedExportOptions("", defaultOptions) + + expected := defaultOptions + assert.ElementsMatch(t, expected, result) + }) + + t.Run("non-empty returns selected", func(t *testing.T) { + result := getSelectedExportOptions("a,b", defaultOptions) + + expected := []string{"a", "b"} + assert.ElementsMatch(t, expected, result) + }) +} From eb583fa86a11e753b1de13b85619079f5580e0b5 Mon Sep 17 00:00:00 2001 From: Constantino Antunes Date: Mon, 20 Sep 2021 12:16:40 +0100 Subject: [PATCH 10/21] AST-3450: reduce size of RunExports function --- internal/process.go | 92 +++++++++++++++++++++++++-------------------- 1 file changed, 52 insertions(+), 40 deletions(-) diff --git a/internal/process.go b/internal/process.go index 4cad89f..033e9fc 100644 --- a/internal/process.go +++ b/internal/process.go @@ -63,25 +63,9 @@ func RunExport(args *Args) { Msgf("parsed export options") // validate permissions - jwtClaims := jwt.MapClaims{} - _, _, jwtErr := new(jwt.Parser).ParseUnverified(client.Token.AccessToken, jwtClaims) - if jwtErr != nil { - log.Debug(). - Err(jwtErr). - Msg("permissions validation failed to parse jwt token") - panic(fmt.Errorf("permissions error - could not decode access token")) - } - availablePermissions, availablePermissionsErr := getAvailablePermissions(jwtClaims) - if availablePermissionsErr != nil { - panic(fmt.Errorf("permissions error - %s", availablePermissionsErr.Error())) - } - requiredPermissions := permissions.GetFromExportOptions(selectedExportOptions) - missingPermissions := getMissingPermissions(requiredPermissions, availablePermissions) - if len(missingPermissions) > 0 { - for _, permission := range missingPermissions { - log.Error().Msgf("missing permission: %s", permission) - } - panic(fmt.Errorf("please add missing permissions to your SAST user")) + permissionsValidateErr := validatePermissions(client, selectedExportOptions) + if permissionsValidateErr != nil { + panic(fmt.Errorf("permissions error - %s", permissionsValidateErr.Error())) } // collect export data @@ -101,27 +85,10 @@ func RunExport(args *Args) { }(&exportValues) } - for _, exportOption := range export.GetOptions() { - if sliceutils.Contains(exportOption, sliceutils.ConvertStringToInterface(selectedExportOptions)) { - log.Info().Msgf("collecting %s", exportOption) - switch exportOption { - case export.UsersOption: - if err = fetchUsersData(client); err != nil { - log.Error().Err(err) - panic(err) - } - case export.TeamsOption: - if err = fetchTeamsData(client); err != nil { - log.Error().Err(err) - panic(err) - } - case export.ResultsOption: - if err = fetchResultsData(client, args); err != nil { - log.Error().Err(err) - panic(err) - } - } - } + fetchErr := fetchSelectedData(client, args, selectedExportOptions) + if fetchErr != nil { + log.Error().Err(err) + panic(fmt.Errorf("fetch error - %s", err.Error())) } // export data to file @@ -198,6 +165,51 @@ func ExportResultsToFile(args *Args, exportValues *Export) (*string, error) { return &exportFileName, exportErr } +func validatePermissions(client *SASTClient, selectedExportOptions []string) error { + jwtClaims := jwt.MapClaims{} + _, _, jwtErr := new(jwt.Parser).ParseUnverified(client.Token.AccessToken, jwtClaims) + if jwtErr != nil { + return jwtErr + } + availablePermissions, availablePermissionsErr := getAvailablePermissions(jwtClaims) + if availablePermissionsErr != nil { + return availablePermissionsErr + } + requiredPermissions := permissions.GetFromExportOptions(selectedExportOptions) + missingPermissions := getMissingPermissions(requiredPermissions, availablePermissions) + if len(missingPermissions) > 0 { + for _, permission := range missingPermissions { + log.Warn().Msgf("missing permission %s", permission) + } + return fmt.Errorf("please add missing permissions to your SAST user") + } + return nil +} + +func fetchSelectedData(client *SASTClient, args *Args, selectedExportOptions []string) error { + options := sliceutils.ConvertStringToInterface(selectedExportOptions) + for _, exportOption := range export.GetOptions() { + if sliceutils.Contains(exportOption, options) { + log.Info().Msgf("collecting %s", exportOption) + switch exportOption { + case export.UsersOption: + if err := fetchUsersData(client); err != nil { + return err + } + case export.TeamsOption: + if err := fetchTeamsData(client); err != nil { + return err + } + case export.ResultsOption: + if err := fetchResultsData(client, args); err != nil { + return err + } + } + } + } + return nil +} + func fetchUsersData(c *SASTClient) error { var err error usersData, err = c.GetUsers() From b614c8d3de0c0dc0eef066bbdac7cedc74362442 Mon Sep 17 00:00:00 2001 From: Constantino Antunes Date: Mon, 20 Sep 2021 13:58:41 +0100 Subject: [PATCH 11/21] AST-3450: update AOL --- go.mod | 2 +- go.sum | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 0351d24..80cbc87 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/checkmarxDev/ast-sast-export go 1.16 require ( - github.com/checkmarxDev/ast-observability-library v1.2.0 + github.com/checkmarxDev/ast-observability-library v1.2.1 github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/rs/zerolog v1.25.0 github.com/spf13/cobra v1.2.1 diff --git a/go.sum b/go.sum index 54f1639..fbaea47 100644 --- a/go.sum +++ b/go.sum @@ -46,8 +46,8 @@ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/checkmarxDev/ast-observability-library v1.2.0 h1:G2uE9mBQEJOSdSCV74SRO02/0qioAJ6ZukgHANYjJ1Y= -github.com/checkmarxDev/ast-observability-library v1.2.0/go.mod h1:es+kjxYDaFOFJIG3ADVx3pi8BUwZwLxBJMV5Qn/88/M= +github.com/checkmarxDev/ast-observability-library v1.2.1 h1:td6VoYhr2jYoiVMNDViTtuD3qItWPI+fzxtfHQ8CNOg= +github.com/checkmarxDev/ast-observability-library v1.2.1/go.mod h1:9AlqHrGF1TD4ileeF5w7y8irxeGH+YB8AOC9YwV8CBM= 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= @@ -61,6 +61,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsr github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= 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= @@ -202,9 +204,7 @@ github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndr github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.23.0/go.mod h1:6c7hFfxPOy7TacJc4Fcdi24/J0NKYGzjG8FWRI916Qo= github.com/rs/zerolog v1.25.0 h1:Rj7XygbUHKUlDPcVdoLyR91fJBsduXj5fRxyqIQj/II= github.com/rs/zerolog v1.25.0/go.mod h1:7KHcEGe0QZPOm2IE4Kpb5rTh6n1h2hIgS5OOnu1rUaI= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= From 7444a5ae0b4cf4e3061cc92de2c66a17f435645e Mon Sep 17 00:00:00 2001 From: Constantino Antunes Date: Mon, 20 Sep 2021 14:31:26 +0100 Subject: [PATCH 12/21] AST-3450: refactor export arg --- cmd/args.go | 2 +- cmd/root.go | 9 +++------ internal/models.go | 2 +- internal/process.go | 41 +++++++++++++--------------------------- internal/process_test.go | 18 ------------------ 5 files changed, 18 insertions(+), 54 deletions(-) diff --git a/cmd/args.go b/cmd/args.go index 0323b13..5214602 100644 --- a/cmd/args.go +++ b/cmd/args.go @@ -25,7 +25,7 @@ func GetArgs(cmd *cobra.Command, productName string) internal.Args { if err != nil { panic(err) } - args.Export, err = cmd.Flags().GetString(exportArg) + args.Export, err = cmd.Flags().GetStringSlice(exportArg) if err != nil { panic(err) } diff --git a/cmd/root.go b/cmd/root.go index 1d5afc9..4eccf7d 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -2,14 +2,14 @@ package cmd import ( "fmt" - "os" - "github.com/checkmarxDev/ast-observability-library/pkg/aol" "github.com/checkmarxDev/ast-sast-export/internal" + "github.com/checkmarxDev/ast-sast-export/internal/export" "github.com/checkmarxDev/ast-sast-export/internal/logging" "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/spf13/cobra" + "os" ) const ( @@ -96,7 +96,7 @@ func init() { rootCmd.Flags().StringP(userArg, "", "", "SAST admin username") rootCmd.Flags().StringP(passArg, "", "", "SAST admin password") rootCmd.Flags().StringP(urlArg, "", "", "SAST url") - rootCmd.Flags().StringP(exportArg, "", "", "SAST [optional] export options --export users,results,teams, all if nothing defined") + rootCmd.Flags().StringSliceP(exportArg, "", export.GetOptions(), "SAST export options") rootCmd.Flags().IntP(resultsProjectActiveSinceArg, "", resultsProjectActiveSinceDefaultValue, resultsProjectActiveSinceUsage) rootCmd.Flags().Bool(debugArg, false, "Activate debug mode") rootCmd.Flags().BoolP(verboseArg, "v", false, "Enable verbose logging to console") @@ -110,9 +110,6 @@ func init() { if err := rootCmd.MarkFlagRequired(urlArg); err != nil { panic(err) } - if err := rootCmd.MarkFlagCustom(exportArg, "users,results,teams"); err != nil { - panic(err) - } if err := rootCmd.MarkFlagCustom(resultsProjectActiveSinceArg, resultsProjectActiveSinceUsage); err != nil { panic(err) } diff --git a/internal/models.go b/internal/models.go index 918ee19..5ebd688 100644 --- a/internal/models.go +++ b/internal/models.go @@ -8,9 +8,9 @@ type Args struct { URL, Username, Password, - Export, OutputPath, ProductName string + Export []string ResultsProjectActiveSince int Debug bool } diff --git a/internal/process.go b/internal/process.go index 5f8a00c..2be2ea3 100644 --- a/internal/process.go +++ b/internal/process.go @@ -6,7 +6,6 @@ import ( "fmt" "net/http" "os/exec" - "strings" "time" "github.com/checkmarxDev/ast-sast-export/internal/export" @@ -37,15 +36,12 @@ func RunExport(args *Args) { log.Debug(). Str("url", args.URL). - Str("export", args.Export). + Str("export", fmt.Sprintf("%v", args.Export)). Int("resultsProjectActiveSince", args.ResultsProjectActiveSince). Bool("debug", args.Debug). Int("consumers", consumerCount). Msg("starting export") - selectedExportOptions := getSelectedExportOptions(args.Export, export.GetOptions()) - args.Export = strings.Join(selectedExportOptions, ",") - // create api client client, err := NewSASTClient(args.URL, &http.Client{}) if err != nil { @@ -60,12 +56,8 @@ func RunExport(args *Args) { panic(authErr) } - log.Debug(). - Str("exportOptions", args.Export). - Msgf("parsed export options") - // validate permissions - permissionsValidateErr := validatePermissions(client, selectedExportOptions) + permissionsValidateErr := validatePermissions(client, args.Export) if permissionsValidateErr != nil { panic(fmt.Errorf("permissions error - %s", permissionsValidateErr.Error())) } @@ -87,7 +79,7 @@ func RunExport(args *Args) { }(&exportValues) } - fetchErr := fetchSelectedData(client, args, selectedExportOptions) + fetchErr := fetchSelectedData(client, args) if fetchErr != nil { log.Error().Err(err) panic(fmt.Errorf("fetch error - %s", err.Error())) @@ -104,8 +96,8 @@ func RunExport(args *Args) { } func ExportResultsToFile(args *Args, exportValues *Export) (*string, error) { - - if strings.Contains(args.Export, export.UsersOption) { + exportOptions := sliceutils.ConvertStringToInterface(args.Export) + if sliceutils.Contains(export.UsersOption, exportOptions) { if exportErr := exportValues.AddFile(UsersFileName, usersData); exportErr != nil { return nil, exportErr } @@ -123,7 +115,7 @@ func ExportResultsToFile(args *Args, exportValues *Export) (*string, error) { } } - if strings.Contains(args.Export, export.ResultsOption) { + if sliceutils.Contains(export.ResultsOption, exportOptions) { for _, res := range exportData { if exportErr := exportValues.AddFile(res.FileName, res.Data); exportErr != nil { return nil, exportErr @@ -131,7 +123,7 @@ func ExportResultsToFile(args *Args, exportValues *Export) (*string, error) { } } - if strings.Contains(args.Export, export.TeamsOption) { + if sliceutils.Contains(export.TeamsOption, exportOptions) { if exportErr := exportValues.AddFile(TeamsFileName, teamsData); exportErr != nil { return nil, exportErr } @@ -145,7 +137,7 @@ func ExportResultsToFile(args *Args, exportValues *Export) (*string, error) { } } - if strings.Contains(args.Export, export.UsersOption) || strings.Contains(args.Export, export.TeamsOption) { + if sliceutils.Contains(export.UsersOption, exportOptions) || sliceutils.Contains(export.TeamsOption, exportOptions) { if exportErr := exportValues.AddFile(LdapServersFileName, ldapServersData); exportErr != nil { return nil, exportErr } @@ -188,8 +180,8 @@ func validatePermissions(client *SASTClient, selectedExportOptions []string) err return nil } -func fetchSelectedData(client *SASTClient, args *Args, selectedExportOptions []string) error { - options := sliceutils.ConvertStringToInterface(selectedExportOptions) +func fetchSelectedData(client *SASTClient, args *Args) error { + options := sliceutils.ConvertStringToInterface(args.Export) for _, exportOption := range export.GetOptions() { if sliceutils.Contains(exportOption, options) { log.Info().Msgf("collecting %s", exportOption) @@ -203,7 +195,7 @@ func fetchSelectedData(client *SASTClient, args *Args, selectedExportOptions []s return err } case export.ResultsOption: - if err := fetchResultsData(client, args); err != nil { + if err := fetchResultsData(client, args.ResultsProjectActiveSince); err != nil { return err } } @@ -266,11 +258,11 @@ func fetchTeamsData(client *SASTClient) error { return nil } -func fetchResultsData(client *SASTClient, args *Args) (err error) { +func fetchResultsData(client *SASTClient, resultsProjectActiveSince int) (err error) { consumerCount := GetNumCPU() reportJobs := make(chan ReportJob) - fromDate := GetDateFromDays(args.ResultsProjectActiveSince, time.Now()) + fromDate := GetDateFromDays(resultsProjectActiveSince, time.Now()) // collect last triaged scan by project var lastTriagedScansByProject []TriagedScan @@ -528,10 +520,3 @@ func getAvailablePermissions(jwtClaims jwt.MapClaims) ([]interface{}, error) { availablePermissions := append(sastPermissions, accessControlPermissions...) return availablePermissions, nil } - -func getSelectedExportOptions(selected string, defaultValue []string) []string { - if selected != "" { - return strings.Split(selected, ",") - } - return defaultValue -} diff --git a/internal/process_test.go b/internal/process_test.go index add9f98..44fbc32 100644 --- a/internal/process_test.go +++ b/internal/process_test.go @@ -71,21 +71,3 @@ func TestGetAvailablePermissions(t *testing.T) { assert.NoError(t, err) assert.ElementsMatch(t, expected, result) } - -func TestGetSelectedExportOptions(t *testing.T) { - defaultOptions := []string{"a", "b", "c"} - - t.Run("empty falls back to default", func(t *testing.T) { - result := getSelectedExportOptions("", defaultOptions) - - expected := defaultOptions - assert.ElementsMatch(t, expected, result) - }) - - t.Run("non-empty returns selected", func(t *testing.T) { - result := getSelectedExportOptions("a,b", defaultOptions) - - expected := []string{"a", "b"} - assert.ElementsMatch(t, expected, result) - }) -} From 770bd47e8c29aba41933d855945bf5a0f79f210c Mon Sep 17 00:00:00 2001 From: Constantino Antunes Date: Mon, 20 Sep 2021 14:37:59 +0100 Subject: [PATCH 13/21] AST-3450: revise help text --- cmd/root.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 4eccf7d..2527e26 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -1,7 +1,8 @@ package cmd import ( - "fmt" + "os" + "github.com/checkmarxDev/ast-observability-library/pkg/aol" "github.com/checkmarxDev/ast-sast-export/internal" "github.com/checkmarxDev/ast-sast-export/internal/export" @@ -9,7 +10,6 @@ import ( "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/spf13/cobra" - "os" ) const ( @@ -90,11 +90,10 @@ func Execute() { //nolint:gochecknoinits func init() { - resultsProjectActiveSinceUsage := fmt.Sprintf( - "SAST [optional] custom results project active since (days) - %d if nothing defined", resultsProjectActiveSinceDefaultValue) + resultsProjectActiveSinceUsage := "Include only results from projects active in the last N days" - rootCmd.Flags().StringP(userArg, "", "", "SAST admin username") - rootCmd.Flags().StringP(passArg, "", "", "SAST admin password") + rootCmd.Flags().StringP(userArg, "", "", "SAST username") + rootCmd.Flags().StringP(passArg, "", "", "SAST password") rootCmd.Flags().StringP(urlArg, "", "", "SAST url") rootCmd.Flags().StringSliceP(exportArg, "", export.GetOptions(), "SAST export options") rootCmd.Flags().IntP(resultsProjectActiveSinceArg, "", resultsProjectActiveSinceDefaultValue, resultsProjectActiveSinceUsage) From 5c522de8c16e5a2e55abb92e37a33d70a424b9c9 Mon Sep 17 00:00:00 2001 From: Constantino Antunes Date: Mon, 20 Sep 2021 14:43:54 +0100 Subject: [PATCH 14/21] AST-3450: revise help text --- cmd/root.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 2527e26..f8bab7a 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -90,15 +90,15 @@ func Execute() { //nolint:gochecknoinits func init() { - resultsProjectActiveSinceUsage := "Include only results from projects active in the last N days" + resultsProjectActiveSinceUsage := "include only results from projects active in the last N days" rootCmd.Flags().StringP(userArg, "", "", "SAST username") rootCmd.Flags().StringP(passArg, "", "", "SAST password") rootCmd.Flags().StringP(urlArg, "", "", "SAST url") rootCmd.Flags().StringSliceP(exportArg, "", export.GetOptions(), "SAST export options") rootCmd.Flags().IntP(resultsProjectActiveSinceArg, "", resultsProjectActiveSinceDefaultValue, resultsProjectActiveSinceUsage) - rootCmd.Flags().Bool(debugArg, false, "Activate debug mode") - rootCmd.Flags().BoolP(verboseArg, "v", false, "Enable verbose logging to console") + rootCmd.Flags().Bool(debugArg, false, "activate debug mode") + rootCmd.Flags().BoolP(verboseArg, "v", false, "enable verbose logging to console") if err := rootCmd.MarkFlagRequired(userArg); err != nil { panic(err) From be362a48b27c53d37620aea05e865fddfdbe1abd Mon Sep 17 00:00:00 2001 From: Constantino Antunes Date: Mon, 20 Sep 2021 15:50:45 +0100 Subject: [PATCH 15/21] AST-3450: move isDebug flag --- internal/process.go | 2 ++ internal/sast-client.go | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/process.go b/internal/process.go index 2be2ea3..c775fb1 100644 --- a/internal/process.go +++ b/internal/process.go @@ -24,6 +24,8 @@ const ( triagedScansPageLimit = 1000 ) +var isDebug bool + type ReportConsumeOutput struct { Err error ProjectID int diff --git a/internal/sast-client.go b/internal/sast-client.go index 11fd3ee..ba5d679 100644 --- a/internal/sast-client.go +++ b/internal/sast-client.go @@ -41,8 +41,6 @@ const ( LastTriagedFilters = "Date gt %s and Comment ne null" ) -var isDebug bool - type HTTPAdapter interface { Do(req *http.Request) (*http.Response, error) } From 36ccfc166078d5f8713e8ebe52f2a078c74d2bb6 Mon Sep 17 00:00:00 2001 From: Constantino Antunes Date: Mon, 20 Sep 2021 15:54:52 +0100 Subject: [PATCH 16/21] AST-3450: remove isDebug global var --- internal/process.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/internal/process.go b/internal/process.go index c775fb1..d6d149f 100644 --- a/internal/process.go +++ b/internal/process.go @@ -24,8 +24,6 @@ const ( triagedScansPageLimit = 1000 ) -var isDebug bool - type ReportConsumeOutput struct { Err error ProjectID int @@ -33,7 +31,6 @@ type ReportConsumeOutput struct { } func RunExport(args *Args) { - isDebug = args.Debug consumerCount := GetNumCPU() log.Debug(). @@ -72,7 +69,7 @@ func RunExport(args *Args) { panic(exportCreateErr) } - if !isDebug { + if !args.Debug { defer func(exportValues *Export) { cleanErr := exportValues.Clean() if cleanErr != nil { @@ -149,7 +146,7 @@ func ExportResultsToFile(args *Args, exportValues *Export) (*string, error) { } // create export package - if isDebug { + if args.Debug { exec.Command(`explorer`, `/select,`, exportValues.TmpDir).Run() return &exportValues.TmpDir, nil } From 4a1e7ee7d02fb9df23c923e92066ff057fd895dc Mon Sep 17 00:00:00 2001 From: Constantino Antunes Date: Mon, 20 Sep 2021 15:55:50 +0100 Subject: [PATCH 17/21] AST-3450: move process globals to process module --- internal/process.go | 13 +++++++++++++ internal/sast-client.go | 13 ------------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/internal/process.go b/internal/process.go index d6d149f..9b04a3f 100644 --- a/internal/process.go +++ b/internal/process.go @@ -24,6 +24,19 @@ const ( triagedScansPageLimit = 1000 ) +var ( + exportData []ExportData + usersData, + rolesData, + ldapRolesData, + samlRolesData, + teamsData, + samlTeamsData, + ldapTeamsData, + samlIDpsData, + ldapServersData []byte +) + type ReportConsumeOutput struct { Err error ProjectID int diff --git a/internal/sast-client.go b/internal/sast-client.go index ba5d679..e62a395 100644 --- a/internal/sast-client.go +++ b/internal/sast-client.go @@ -10,19 +10,6 @@ import ( "github.com/rs/zerolog/log" ) -var ( - exportData []ExportData - usersData, - rolesData, - ldapRolesData, - samlRolesData, - teamsData, - samlTeamsData, - ldapTeamsData, - samlIDpsData, - ldapServersData []byte -) - const ( UsersEndpoint = "/CxRestAPI/auth/Users" TeamsEndpoint = "/CxRestAPI/auth/Teams" From 46dd911feebf4168c2ac1b6fca22377e6eb44412 Mon Sep 17 00:00:00 2001 From: Constantino Antunes Date: Tue, 21 Sep 2021 12:13:13 +0100 Subject: [PATCH 18/21] AST-3450: add api version in request headers --- internal/requests.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/internal/requests.go b/internal/requests.go index 85488a4..f4ce701 100644 --- a/internal/requests.go +++ b/internal/requests.go @@ -12,8 +12,8 @@ const ( Accept = "Accept" ContentType = "Content-Type" Authorization = "Authorization" - JSONContentType = "application/json" - FormUrlEncodedContentType = "application/x-www-form-urlencoded" + JSONContentType = "application/json;v=1.0" + FormURLEncodedContentType = "application/x-www-form-urlencoded" ) func CreateAccessTokenRequest(baseURL, username, password string) (*http.Request, error) { @@ -29,13 +29,13 @@ func CreateAccessTokenRequest(baseURL, username, password string) (*http.Request if err != nil { return nil, err } - req.Header.Add(ContentType, FormUrlEncodedContentType) - req.Header.Add(Accept, FormUrlEncodedContentType) + req.Header.Add(ContentType, FormURLEncodedContentType) + req.Header.Add(Accept, FormURLEncodedContentType) return req, nil } -func CreateRequest(httpMethod, url string, requestBody io.Reader, token *AccessToken) (*http.Request, error) { - resp, err := http.NewRequest(httpMethod, url, requestBody) +func CreateRequest(httpMethod, requestURL string, requestBody io.Reader, token *AccessToken) (*http.Request, error) { + resp, err := http.NewRequest(httpMethod, requestURL, requestBody) if err != nil { return nil, err } From 3c23f2cecf899a1aa15efe434840a47a4544ebdd Mon Sep 17 00:00:00 2001 From: Constantino Antunes Date: Tue, 21 Sep 2021 16:05:40 +0100 Subject: [PATCH 19/21] AST-3450: add permission description --- internal/permissions/permissions.go | 15 +++++++++++++++ internal/process.go | 7 ++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/internal/permissions/permissions.go b/internal/permissions/permissions.go index 830c980..feeff22 100644 --- a/internal/permissions/permissions.go +++ b/internal/permissions/permissions.go @@ -15,6 +15,13 @@ const ( manageRolesPermission = "manage-roles" ) +var permissionDescription = map[interface{}]string{ + useOdataPermission: "Sast > API > Use Odata", + generateScanReportPermission: "Sast > Reports > Generate Scan Report", + manageAuthProviderPermission: "Access Control > General > Manage Authentication Providers", + manageRolesPermission: "Access Control > General > Manage Roles", +} + func GetFromExportOptions(exportOptions []string) []interface{} { var output []string @@ -49,3 +56,11 @@ func GetFromJwtClaim(claims jwt.MapClaims, key string) ([]interface{}, error) { } return make([]interface{}, 0), fmt.Errorf("could not parse permissions") } + +func GetDescription(permission interface{}) (string, error) { + description, ok := permissionDescription[permission] + if !ok { + return "", fmt.Errorf("unknown permission %s", permission) + } + return description, nil +} diff --git a/internal/process.go b/internal/process.go index 9b04a3f..6b82810 100644 --- a/internal/process.go +++ b/internal/process.go @@ -185,7 +185,12 @@ func validatePermissions(client *SASTClient, selectedExportOptions []string) err missingPermissions := getMissingPermissions(requiredPermissions, availablePermissions) if len(missingPermissions) > 0 { for _, permission := range missingPermissions { - log.Warn().Msgf("missing permission %s", permission) + description, descriptionErr := permissions.GetDescription(permission) + if descriptionErr != nil { + description = permission.(string) + log.Debug().Err(descriptionErr).Msg("could not get permission description") + } + log.Warn().Msgf("missing permission %s", description) } return fmt.Errorf("please add missing permissions to your SAST user") } From 73ef37f88bee727ad0b8cba424f02a7c3fca55e0 Mon Sep 17 00:00:00 2001 From: Constantino Antunes Date: Tue, 21 Sep 2021 16:23:02 +0100 Subject: [PATCH 20/21] AST-3450: move permission functions to respective package --- internal/permissions/permissions.go | 30 ++++++++-- internal/permissions/permissions_test.go | 72 ++++++++++++++++++++++- internal/process.go | 40 +++---------- internal/process_test.go | 73 ------------------------ 4 files changed, 104 insertions(+), 111 deletions(-) delete mode 100644 internal/process_test.go diff --git a/internal/permissions/permissions.go b/internal/permissions/permissions.go index feeff22..cb9829f 100644 --- a/internal/permissions/permissions.go +++ b/internal/permissions/permissions.go @@ -41,16 +41,28 @@ func GetFromExportOptions(exportOptions []string) []interface{} { return sliceutils.Unique(sliceutils.ConvertStringToInterface(output)) } -func GetFromJwtClaim(claims jwt.MapClaims, key string) ([]interface{}, error) { - sastPermissions, exists := claims[key] +func GetFromJwtClaims(jwtClaims jwt.MapClaims, keys []string) ([]interface{}, error) { + permissions := make([]interface{}, 0) + for _, key := range keys { + claimPermissions, permissionErr := getFromJwtClaim(jwtClaims, key) + if permissionErr != nil { + return nil, fmt.Errorf("could not parse %s permissions", key) + } + permissions = append(permissions, claimPermissions...) + } + return permissions, nil +} + +func getFromJwtClaim(claims jwt.MapClaims, key string) ([]interface{}, error) { + claimValue, exists := claims[key] if !exists { return make([]interface{}, 0), nil } - multiplePermissions, ok := sastPermissions.([]interface{}) + multiplePermissions, ok := claimValue.([]interface{}) if ok { return multiplePermissions, nil } - singlePermission, ok := sastPermissions.(interface{}) + singlePermission, ok := claimValue.(interface{}) if ok { return []interface{}{singlePermission}, nil } @@ -64,3 +76,13 @@ func GetDescription(permission interface{}) (string, error) { } return description, nil } + +func GetMissing(required, available []interface{}) []interface{} { + missing := make([]interface{}, 0) + for _, requiredPermission := range required { + if !sliceutils.Contains(requiredPermission, available) { + missing = append(missing, requiredPermission) + } + } + return missing +} diff --git a/internal/permissions/permissions_test.go b/internal/permissions/permissions_test.go index 0a066b2..43e26ee 100644 --- a/internal/permissions/permissions_test.go +++ b/internal/permissions/permissions_test.go @@ -68,13 +68,27 @@ func TestGetFromExportOptions(t *testing.T) { }) } +func TestGetAllFromJwtClaims(t *testing.T) { + claims := jwt.MapClaims{ + "aaa": []interface{}{"a", "b"}, + "bbb": []interface{}{"c", "d"}, + "ccc": []interface{}{"e", "f"}, + } + + result, err := GetFromJwtClaims(claims, []string{"aaa", "bbb"}) + + expected := []interface{}{"a", "b", "c", "d"} + assert.NoError(t, err) + assert.ElementsMatch(t, expected, result) +} + func TestGetFromJwtClaims(t *testing.T) { key := "permissions" t.Run("claims without permission", func(t *testing.T) { claims := jwt.MapClaims{"test": "test"} - result, err := GetFromJwtClaim(claims, key) + result, err := getFromJwtClaim(claims, key) expected := make([]interface{}, 0) assert.NoError(t, err) @@ -84,7 +98,7 @@ func TestGetFromJwtClaims(t *testing.T) { t.Run("claims with one permission", func(t *testing.T) { claims := jwt.MapClaims{"test": "test", "permissions": "use-odata"} - result, err := GetFromJwtClaim(claims, key) + result, err := getFromJwtClaim(claims, key) expected := []interface{}{"use-odata"} assert.NoError(t, err) @@ -94,10 +108,62 @@ func TestGetFromJwtClaims(t *testing.T) { t.Run("claims with more than one permission", func(t *testing.T) { claims := jwt.MapClaims{"test": "test", "permissions": []interface{}{"use-odata", "generate-scan-report"}} - result, err := GetFromJwtClaim(claims, key) + result, err := getFromJwtClaim(claims, key) expected := []interface{}{"use-odata", "generate-scan-report"} assert.NoError(t, err) assert.ElementsMatch(t, expected, result) }) } + +func TestGetMissing(t *testing.T) { + t.Run("empty lists return empty list", func(t *testing.T) { + required := make([]interface{}, 0) + available := make([]interface{}, 0) + + result := GetMissing(required, available) + + expected := make([]interface{}, 0) + assert.ElementsMatch(t, expected, result) + }) + + t.Run("empty required return empty list", func(t *testing.T) { + required := make([]interface{}, 0) + available := []interface{}{"a", "b", "c"} + + result := GetMissing(required, available) + + expected := make([]interface{}, 0) + assert.ElementsMatch(t, expected, result) + }) + + t.Run("more available than required return empty list", func(t *testing.T) { + required := []interface{}{"a", "b"} + available := []interface{}{"a", "b", "c"} + + result := GetMissing(required, available) + + expected := make([]interface{}, 0) + assert.ElementsMatch(t, expected, result) + }) + + t.Run("missing one returns one item", func(t *testing.T) { + required := []interface{}{"a", "b", "c"} + available := []interface{}{"a", "b"} + + result := GetMissing(required, available) + + expected := []interface{}{"c"} + assert.ElementsMatch(t, expected, result) + }) + + t.Run("missing many returns many items", func(t *testing.T) { + required := []interface{}{"a", "b", "c", "d", "e", "f"} + available := []interface{}{"a", "b", "d", "f"} + + result := GetMissing(required, available) + + expected := []interface{}{"c", "e"} + assert.ElementsMatch(t, expected, result) + }) +} diff --git a/internal/process.go b/internal/process.go index 6b82810..c06e73b 100644 --- a/internal/process.go +++ b/internal/process.go @@ -177,14 +177,15 @@ func validatePermissions(client *SASTClient, selectedExportOptions []string) err if jwtErr != nil { return jwtErr } - availablePermissions, availablePermissionsErr := getAvailablePermissions(jwtClaims) - if availablePermissionsErr != nil { - return availablePermissionsErr - } - requiredPermissions := permissions.GetFromExportOptions(selectedExportOptions) - missingPermissions := getMissingPermissions(requiredPermissions, availablePermissions) - if len(missingPermissions) > 0 { - for _, permission := range missingPermissions { + claimKeys := []string{"sast-permissions", "access-control-permissions"} + available, availableErr := permissions.GetFromJwtClaims(jwtClaims, claimKeys) + if availableErr != nil { + return availableErr + } + required := permissions.GetFromExportOptions(selectedExportOptions) + missing := permissions.GetMissing(required, available) + if len(missing) > 0 { + for _, permission := range missing { description, descriptionErr := permissions.GetDescription(permission) if descriptionErr != nil { description = permission.(string) @@ -514,26 +515,3 @@ func retryGetReport(client *SASTClient, totalAttempts, reportID, projectID int, } return nil } - -func getMissingPermissions(requiredPermissions, availablePermissions []interface{}) []interface{} { - output := make([]interface{}, 0) - for _, requiredPermission := range requiredPermissions { - if !sliceutils.Contains(requiredPermission, availablePermissions) { - output = append(output, requiredPermission) - } - } - return output -} - -func getAvailablePermissions(jwtClaims jwt.MapClaims) ([]interface{}, error) { - sastPermissions, sastPermissionErr := permissions.GetFromJwtClaim(jwtClaims, "sast-permissions") - if sastPermissionErr != nil { - return nil, fmt.Errorf("could not parse SAST permissions") - } - accessControlPermissions, accessControlPermissionErr := permissions.GetFromJwtClaim(jwtClaims, "access-control-permissions") - if accessControlPermissionErr != nil { - return nil, fmt.Errorf("could not parse Access Control permissions") - } - availablePermissions := append(sastPermissions, accessControlPermissions...) - return availablePermissions, nil -} diff --git a/internal/process_test.go b/internal/process_test.go deleted file mode 100644 index 44fbc32..0000000 --- a/internal/process_test.go +++ /dev/null @@ -1,73 +0,0 @@ -package internal - -import ( - "testing" - - "github.com/dgrijalva/jwt-go" - "github.com/stretchr/testify/assert" -) - -func TestGetMissingPermissions(t *testing.T) { - t.Run("empty lists return empty list", func(t *testing.T) { - requiredPermissions := make([]interface{}, 0) - availablePermissions := make([]interface{}, 0) - - result := getMissingPermissions(requiredPermissions, availablePermissions) - - expected := make([]interface{}, 0) - assert.ElementsMatch(t, expected, result) - }) - - t.Run("empty required return empty list", func(t *testing.T) { - requiredPermissions := make([]interface{}, 0) - availablePermissions := []interface{}{"a", "b", "c"} - - result := getMissingPermissions(requiredPermissions, availablePermissions) - - expected := make([]interface{}, 0) - assert.ElementsMatch(t, expected, result) - }) - - t.Run("more available than required return empty list", func(t *testing.T) { - requiredPermissions := []interface{}{"a", "b"} - availablePermissions := []interface{}{"a", "b", "c"} - - result := getMissingPermissions(requiredPermissions, availablePermissions) - - expected := make([]interface{}, 0) - assert.ElementsMatch(t, expected, result) - }) - - t.Run("missing one returns one item", func(t *testing.T) { - requiredPermissions := []interface{}{"a", "b", "c"} - availablePermissions := []interface{}{"a", "b"} - - result := getMissingPermissions(requiredPermissions, availablePermissions) - - expected := []interface{}{"c"} - assert.ElementsMatch(t, expected, result) - }) - - t.Run("missing many returns many items", func(t *testing.T) { - requiredPermissions := []interface{}{"a", "b", "c", "d", "e", "f"} - availablePermissions := []interface{}{"a", "b", "d", "f"} - - result := getMissingPermissions(requiredPermissions, availablePermissions) - - expected := []interface{}{"c", "e"} - assert.ElementsMatch(t, expected, result) - }) -} - -func TestGetAvailablePermissions(t *testing.T) { - claims := jwt.MapClaims{ - "sast-permissions": []interface{}{"a", "b"}, - "access-control-permissions": []interface{}{"c", "d"}, - } - - result, err := getAvailablePermissions(claims) - - expected := []interface{}{"a", "b", "c", "d"} - assert.NoError(t, err) - assert.ElementsMatch(t, expected, result) -} From 2f4095a90cbb1164fa6928e2405e5a74cbbdde1d Mon Sep 17 00:00:00 2001 From: Constantino Antunes Date: Tue, 21 Sep 2021 16:27:46 +0100 Subject: [PATCH 21/21] AST-3450: change permission validation warn to error --- internal/process.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/process.go b/internal/process.go index c06e73b..c4be8a6 100644 --- a/internal/process.go +++ b/internal/process.go @@ -191,7 +191,7 @@ func validatePermissions(client *SASTClient, selectedExportOptions []string) err description = permission.(string) log.Debug().Err(descriptionErr).Msg("could not get permission description") } - log.Warn().Msgf("missing permission %s", description) + log.Error().Msgf("missing permission %s", description) } return fmt.Errorf("please add missing permissions to your SAST user") }