diff --git a/go.mod b/go.mod index 4e4e208f..6b443b7d 100644 --- a/go.mod +++ b/go.mod @@ -75,9 +75,7 @@ require ( github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/swag v0.22.3 // indirect - github.com/golang/protobuf v1.5.3 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/gorilla/schema v1.4.1 // indirect github.com/gorilla/securecookie v1.1.2 // indirect github.com/gorilla/websocket v1.5.3 // indirect github.com/huandu/xstrings v1.3.3 // indirect @@ -109,7 +107,6 @@ require ( github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/xtaci/smux v1.5.24 // indirect github.com/zitadel/logging v0.6.0 // indirect - github.com/zitadel/oidc/v2 v2.12.0 // indirect github.com/zitadel/oidc/v3 v3.26.0 // indirect github.com/zitadel/schema v1.3.0 // indirect go.opentelemetry.io/otel v1.28.0 // indirect @@ -119,9 +116,7 @@ require ( golang.org/x/crypto v0.25.0 // indirect golang.org/x/net v0.26.0 // indirect golang.org/x/oauth2 v0.21.0 // indirect - google.golang.org/appengine v1.6.7 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect - gopkg.in/square/go-jose.v2 v2.6.0 // indirect ) require ( diff --git a/go.sum b/go.sum index 71d13548..d1540271 100644 --- a/go.sum +++ b/go.sum @@ -56,6 +56,8 @@ github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiE github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/bmatcuk/doublestar/v4 v4.6.1 h1:FH9SifrbvJhnlQpztAx++wlkk70QBf0iBWDwNy7PA4I= +github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= github.com/briandowns/spinner v1.23.0 h1:alDF2guRWqa/FOZZYWjlMIx2L6H0wyewPxo/CH4Pt2A= github.com/briandowns/spinner v1.23.0/go.mod h1:rPG4gmXeN3wQV/TsAY4w8lPdIM6RX3yqeBQJSrbXjuE= github.com/catppuccin/go v0.2.0 h1:ktBeIrIP42b/8FGiScP9sgrWOss3lw0Z5SktRoithGA= @@ -82,12 +84,8 @@ github.com/charmbracelet/x/windows v0.1.2 h1:Iumiwq2G+BRmgoayww/qfcvof7W/3uLoelh github.com/charmbracelet/x/windows v0.1.2/go.mod h1:GLEO/l+lizvFDBPLIOk+49gdX49L9YWMB5t+DZd0jkQ= github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575 h1:kHaBemcxl8o/pQ5VM1c8PVE1PubbNx3mjUr09OqWGCs= github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575/go.mod h1:9d6lWj8KzO/fd/NrVaLscBKmPigpZpn5YawRPw+e3Yo= -github.com/common-fate/apikit v0.3.0 h1:7dkL0jnmJhNAR7bjMM6+8h9psRBY5D+EMY2BzCBcLG8= -github.com/common-fate/apikit v0.3.0/go.mod h1:5WXBU3NBnQ6ZuqQyazwL5Ou6yT7UpC8c3yK8F9mGh9k= github.com/common-fate/apikit v0.4.0 h1:d3ZYWg4CPBte6gIyiNM2MFuqn7Pg24RdYlB6Tz258dQ= github.com/common-fate/apikit v0.4.0/go.mod h1:5WXBU3NBnQ6ZuqQyazwL5Ou6yT7UpC8c3yK8F9mGh9k= -github.com/common-fate/awsconfigfile v0.9.0 h1:eP5UGdX/kUqubnp1OM+78n/ssuuu2xMjztUZMwR7xPI= -github.com/common-fate/awsconfigfile v0.9.0/go.mod h1:4g8kxy1vcf2hn6N5Zmaz+nfc7xQ66uWSb5dsm2ZCa6s= github.com/common-fate/awsconfigfile v0.10.0 h1:9W0JTeO0d3jNLw3Ps9U7IJwLYp4D9zcipq/sqNEWJOg= github.com/common-fate/awsconfigfile v0.10.0/go.mod h1:znstvN26aO+KUwmdjwZ+WcmitZ7heEJb5iFdCPokAO8= github.com/common-fate/cli v1.8.0 h1:T3I+NCMTyvIlZC8QK9qfmsZWj3eSDSZRPHQlM5KJ8Q4= @@ -102,8 +100,6 @@ github.com/common-fate/grab v1.3.0 h1:vGNBMfhAVAWtrLuH1stnhL4LsDb73drhegC/060q+O github.com/common-fate/grab v1.3.0/go.mod h1:6zH8GckZGFrOKfZzL4Y/2OTvxwFeL6cDtsztM0GGC2Y= github.com/common-fate/iso8601 v1.1.0 h1:nrej9shsK1aB4IyOAjZl68xGk8yDuUxVwQjoDzxSK2c= github.com/common-fate/iso8601 v1.1.0/go.mod h1:DU4mvUEkkWZUUSJq2aCuNqM1luSb0Pwyb2dLzXS+img= -github.com/common-fate/sdk v1.45.1 h1:3G8/Ct/l5uiDRGElExKn7kMxViHqq60R5tVQx1uSzio= -github.com/common-fate/sdk v1.45.1/go.mod h1:Y7yRweNikBpi/LRYPRx+wl/mlOx1VQ9xapglkGKEdcM= github.com/common-fate/sdk v1.55.0 h1:G5VcjFBp4VZ/Er+ekgfHhgFqMhpGSOd+KDid0JDxb6c= github.com/common-fate/sdk v1.55.0/go.mod h1:OrXhzB2Y1JSrKGHrb4qRmY+6MF2M3MFb+3edBnessXo= github.com/common-fate/session-manager-plugin v0.0.0-20240723053832-3d311db99016 h1:WObxQKT/BuR8HWKSGsJ6aQb/cdhvkenkb1KWXNyPWeE= @@ -151,15 +147,11 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U= github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= -github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk= -github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw= github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-jose/go-jose/v4 v4.0.2 h1:R3l3kkBds16bO7ZFAEEcofK0MkrAJt3jlJznWZG0nvk= github.com/go-jose/go-jose/v4 v4.0.2/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= -github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= @@ -182,29 +174,21 @@ github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGF github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= -github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/schema v1.4.1 h1:jUg5hUjCSDZpNGLuXQOgIWGdlgrIdYvgQ0wZtdK1M3E= -github.com/gorilla/schema v1.4.1/go.mod h1:Dg5SSm5PV60mhF2NFaTV1xuYYj8tV8NOPRo4FggUMnM= -github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= -github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= @@ -334,8 +318,8 @@ github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUc github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= -github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= -github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/cors v1.11.0 h1:0B9GE/r9Bc2UxRMMtymBkHTenPkHDv0CW4Y98GBY+po= +github.com/rs/cors v1.11.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/schollz/progressbar/v3 v3.13.1 h1:o8rySDYiQ59Mwzy2FELeHY5ZARXZTVJC7iHD6PEFUiE= @@ -386,22 +370,14 @@ github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/zitadel/logging v0.6.0 h1:t5Nnt//r+m2ZhhoTmoPX+c96pbMarqJvW1Vq6xFTank= github.com/zitadel/logging v0.6.0/go.mod h1:Y4CyAXHpl3Mig6JOszcV5Rqqsojj+3n7y2F591Mp/ow= -github.com/zitadel/oidc/v2 v2.12.0 h1:4aMTAy99/4pqNwrawEyJqhRb3yY3PtcDxnoDSryhpn4= -github.com/zitadel/oidc/v2 v2.12.0/go.mod h1:LrRav74IiThHGapQgCHZOUNtnqJG0tcZKHro/91rtLw= github.com/zitadel/oidc/v3 v3.26.0 h1:BG3OUK+JpuKz7YHJIyUxL5Sl2JV6ePkG42UP4Xv3J2w= github.com/zitadel/oidc/v3 v3.26.0/go.mod h1:Cx6AYPTJO5q2mjqF3jaknbKOUjpq1Xui0SYvVhkKuXU= github.com/zitadel/schema v1.3.0 h1:kQ9W9tvIwZICCKWcMvCEweXET1OcOyGEuFbHs4o5kg0= github.com/zitadel/schema v1.3.0/go.mod h1:NptN6mkBDFvERUCvZHlvWmmME+gmZ44xzwRXwhzsbtc= -go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= -go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= -go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= -go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= -go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= -go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= @@ -429,7 +405,6 @@ golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQz golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -437,12 +412,8 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220513224357-95641704303c/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= -golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ= -golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -500,8 +471,6 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -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/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= @@ -518,8 +487,6 @@ gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= -gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= -gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/internal/build/config.go b/internal/build/config.go index 03568370..4ab3371b 100644 --- a/internal/build/config.go +++ b/internal/build/config.go @@ -2,5 +2,6 @@ package build // these configs are overridden as part of the release build process. var ( - ConfigFolderName = ".dgranted" + ConfigFolderName = ".dgranted" + ChromeExtensionID = "cjjieeldgoohbkifkogalkmfpddeafcm" ) diff --git a/pkg/assume/entrypoint.go b/pkg/assume/entrypoint.go index 071dd1d0..59a5b34e 100644 --- a/pkg/assume/entrypoint.go +++ b/pkg/assume/entrypoint.go @@ -12,6 +12,7 @@ import ( "github.com/common-fate/granted/pkg/assumeprint" "github.com/common-fate/granted/pkg/autosync" "github.com/common-fate/granted/pkg/browser" + "github.com/common-fate/granted/pkg/chromemsg" "github.com/common-fate/granted/pkg/config" "github.com/common-fate/useragent" "github.com/urfave/cli/v2" @@ -119,6 +120,11 @@ func GetCliApp() *cli.App { return err } + err = chromemsg.ConfigureHost() + if err != nil { + clio.Debugf("error configuring Granted browser extension native messaging manifest: %s", err.Error()) + } + if !hasSetup { browserName, err := browser.HandleBrowserWizard(c) if err != nil { diff --git a/pkg/chromemsg/chromemsg.go b/pkg/chromemsg/chromemsg.go new file mode 100644 index 00000000..0a87da6e --- /dev/null +++ b/pkg/chromemsg/chromemsg.go @@ -0,0 +1,50 @@ +// Package chromemsg implements the Chrome native messaging protocol: +// https://developer.chrome.com/docs/extensions/develop/concepts/native-messaging +package chromemsg + +import ( + "encoding/binary" + "io" +) + +type Server struct { + Input io.Reader + Output io.Writer +} + +func (s *Server) Read(p []byte) (int, error) { + // From the Chrome developer docs: + // "Each message is serialized using JSON, UTF-8 encoded and is preceded with 32-bit message length in native byte order." + // we need to read the 32-bit message length value first. + var b [4]byte + _, err := io.ReadFull(s.Input, b[:]) + if err != nil { + return 0, err + } + + size := binary.LittleEndian.Uint32(b[:]) + r := io.LimitReader(s.Input, int64(size)) + + return r.Read(p) +} + +func (s *Server) Write(p []byte) (n int, err error) { + // From the Chrome developer docs: + // "Each message is serialized using JSON, UTF-8 encoded and is preceded with 32-bit message length in native byte order." + // we need to read the 32-bit message length value first. + + header := []byte{0, 0, 0, 0} // 32-bit + binary.LittleEndian.PutUint32(header, uint32(len(p))) + + n, err = s.Output.Write(header) + if err != nil { + return 0, err + } + + n2, err := s.Output.Write(p) + if err != nil { + return 0, err + } + + return n + n2, nil +} diff --git a/pkg/chromemsg/chromemsg_test.go b/pkg/chromemsg/chromemsg_test.go new file mode 100644 index 00000000..3ab096cb --- /dev/null +++ b/pkg/chromemsg/chromemsg_test.go @@ -0,0 +1,34 @@ +// Package chromemsg implements the Chrome native messaging protocol: +// https://developer.chrome.com/docs/extensions/develop/concepts/native-messaging +package chromemsg + +import ( + "io" + "testing" +) + +// TestServer_ReadWrite tests the protocol by creating a server where the output +// is connected to the input. We write to the output, and then try and read the +// same message back from the input. +func TestServer_ReadWrite(t *testing.T) { + r, w := io.Pipe() + + server := &Server{Input: r, Output: w} + + message := []byte("Hello, Chrome!") + + go func() { + if _, err := server.Write(message); err != nil { + t.Errorf("failed to write message: %v", err) + } + }() + + readBuffer := make([]byte, len(message)) + if _, err := server.Read(readBuffer); err != nil { + t.Errorf("failed to read message: %v", err) + } + + if string(readBuffer) != string(message) { + t.Errorf("expected %s, got %s", message, readBuffer) + } +} diff --git a/pkg/chromemsg/configure.go b/pkg/chromemsg/configure.go new file mode 100644 index 00000000..cb986e7d --- /dev/null +++ b/pkg/chromemsg/configure.go @@ -0,0 +1,89 @@ +//go:build !windows +// +build !windows + +package chromemsg + +import ( + "fmt" + "os" + "path/filepath" + "runtime" + + "github.com/common-fate/clio" +) + +// Configure writes native messaging host configuration to various well-known folders, +// including Google Chrome, Arc, Microsoft Edge, and Vivaldi. +// +// See: https://developer.chrome.com/docs/extensions/develop/concepts/native-messaging#native-messaging-host +// +// The resulting file looks like this: +// +// { +// "name": "io.commonfate.granted", +// "description": "Granted BrowserSupport", +// "path": "/usr/local/bin/granted", +// "type": "stdio", +// "allowed_origins": [ +// "chrome-extension://fcipjekpmlpmiikgdecbjbcpmenmceoh/" +// ] +// } +func ConfigureHost() error { + switch runtime.GOOS { + case "darwin": + return configureMacOS() + case "linux": + return configureLinux() + } + + return fmt.Errorf("unsupported platform: %s", runtime.GOOS) +} + +func configureMacOS() error { + appSupportFolder := filepath.Join(os.Getenv("HOME"), "Library", "Application Support") + browsers := []string{ + "Arc/User Data", + "Google/Chrome", + "Google/Chrome Beta", + "Google/Chrome Canary", + "Google/Chrome Dev", + "Chromium", + "Microsoft Edge", + "Microsoft Edge Beta", + "Microsoft Edge Canary", + "Microsoft Edge Dev", + "Vivaldi", + } + + for _, browser := range browsers { + browserPath := filepath.Join(appSupportFolder, browser, "NativeMessagingHosts") + if _, err := os.Stat(browserPath); os.IsNotExist(err) { + continue + } + + manifestPath := filepath.Join(browserPath, "io.commonfate.granted.json") + if err := writeManifest(manifestPath); err != nil { + return err + } + + clio.Debugf("wrote native messaging manifest: %s", manifestPath) + } + return nil +} + +func configureLinux() error { + browsers := []string{ + filepath.Join(os.Getenv("HOME"), ".config/google-chrome/NativeMessagingHosts"), + filepath.Join(os.Getenv("HOME"), ".config/chromium/NativeMessagingHosts"), + } + + for _, browserPath := range browsers { + if _, err := os.Stat(browserPath); err == nil { + manifestPath := filepath.Join(browserPath, "io.commonfate.granted.json") + if err := writeManifest(manifestPath); err != nil { + return err + } + } + } + return nil +} diff --git a/pkg/chromemsg/configure_windows.go b/pkg/chromemsg/configure_windows.go new file mode 100644 index 00000000..0e8a83a3 --- /dev/null +++ b/pkg/chromemsg/configure_windows.go @@ -0,0 +1,78 @@ +//go:build windows +// +build windows + +package chromemsg + +import ( + "path/filepath" + + "github.com/common-fate/granted/pkg/config" + "golang.org/x/sys/windows/registry" +) + +// Configure writes native messaging host configuration to various well-known folders, +// including Google Chrome, Arc, Microsoft Edge, and Vivaldi. +// +// See: https://developer.chrome.com/docs/extensions/develop/concepts/native-messaging#native-messaging-host +// +// The resulting file looks like this: +// +// { +// "name": "io.commonfate.granted", +// "description": "Granted BrowserSupport", +// "path": "/usr/local/bin/granted", +// "type": "stdio", +// "allowed_origins": [ +// "chrome-extension://fcipjekpmlpmiikgdecbjbcpmenmceoh/" +// ] +// } +func ConfigureHost() error { + return configureWindows() +} + +// configureWindows configures Windows registry entries pointing to the native messaging manifest file. +// +// From the Chrome developer documentation: +// +// "On Windows, the manifest file can be located anywhere in the file system. +// The application installer must create a registry key, either +// HKEY_LOCAL_MACHINE\SOFTWARE\Google\Chrome\NativeMessagingHosts\com.my_company.my_application +// or HKEY_CURRENT_USER\SOFTWARE\Google\Chrome\NativeMessagingHosts\com.my_company.my_application, +// and set the default value of that key to the full path to the manifest file. +func configureWindows() error { + + paths := []string{ + "Software\\Google\\Chrome\\NativeMessagingHosts", + "Software\\Chromium\\NativeMessagingHosts", + } + + grantedConfigFolder, err := config.GrantedConfigFolder() + if err != nil { + return err + } + + manifestPath := filepath.Join(grantedConfigFolder, "native-messaging-host-manifest.json") + err = writeManifest(manifestPath) + if err != nil { + return err + } + + for _, regPath := range paths { + key, err := registry.OpenKey(registry.CURRENT_USER, regPath, registry.QUERY_VALUE|registry.SET_VALUE) + if err != nil { + continue + } + defer key.Close() + + gkey, _, err := registry.CreateKey(key, "io.commonfate.granted", registry.QUERY_VALUE|registry.SET_VALUE) + if err != nil { + continue + } + defer gkey.Close() + + if err = gkey.SetStringValue("", manifestPath); err != nil { + return err + } + } + return nil +} diff --git a/pkg/chromemsg/write_manifest.go b/pkg/chromemsg/write_manifest.go new file mode 100644 index 00000000..d92c5d51 --- /dev/null +++ b/pkg/chromemsg/write_manifest.go @@ -0,0 +1,56 @@ +package chromemsg + +import ( + "encoding/json" + "fmt" + "os" + "path/filepath" + "runtime" + + "github.com/common-fate/granted/internal/build" +) + +type HostManifest struct { + Name string `json:"name"` + Description string `json:"description"` + Path string `json:"path"` + Type string `json:"type"` + AllowedOrigins []string `json:"allowed_origins"` +} + +func writeManifest(manifestPath string) error { + executablePath, err := os.Executable() + if err != nil { + return err + } + + executablePath, err = filepath.EvalSymlinks(executablePath) + if err != nil { + return err + } + + if runtime.GOOS == "windows" { + // on windows, the file needs to be 'granted.exe' rather than 'assumego.exe'. + parent := filepath.Dir(executablePath) + executablePath = filepath.Join(parent, build.GrantedBinaryName()+".exe") + } + + manifest := HostManifest{ + Name: "io.commonfate.granted", + Description: "Granted BrowserSupport", + Path: executablePath, + Type: "stdio", + AllowedOrigins: []string{ + fmt.Sprintf("chrome-extension://%s/", build.ChromeExtensionID), + }, + } + + file, err := os.Create(manifestPath) + if err != nil { + return err + } + defer file.Close() + + encoder := json.NewEncoder(file) + return encoder.Encode(manifest) +} diff --git a/pkg/granted/chrome_extension.go b/pkg/granted/chrome_extension.go new file mode 100644 index 00000000..fe949d8f --- /dev/null +++ b/pkg/granted/chrome_extension.go @@ -0,0 +1,75 @@ +package granted + +import ( + "encoding/json" + "fmt" + "net/url" + "os" + + "github.com/common-fate/granted/internal/build" + "github.com/common-fate/granted/pkg/chromemsg" + "github.com/common-fate/granted/pkg/securestorage" + "github.com/urfave/cli/v2" +) + +func HandleChromeExtensionCall(c *cli.Context) error { + arg := c.Args().First() + + // When called with a chrome extension, the first argument will be the extension ID, + // in a format like 'chrome-extension://fcipjekpmlpmiikgdecbjbcpmenmceoh'. + // + // We need to verify the extension ID matches our list of allowed Chrome extension IDs. + + u, err := url.Parse(arg) + if err != nil { + return fmt.Errorf("invalid Chrome Extension URL %q: %w", arg, err) + } + + if u.Host != build.ChromeExtensionID { + return fmt.Errorf("Chrome Extension ID %q did not match allowed ID %q", u.Host, build.ChromeExtensionID) + } + + // If we get here, the Granted CLI has been invoked from our browser extension. + // + // The browser extension native messaging protocol uses stdin and stdout to + // communicate with the Granted CLI. + // + // See: https://developer.chrome.com/docs/extensions/develop/concepts/native-messaging + s := chromemsg.Server{ + Input: os.Stdin, + Output: os.Stdout, + } + + var msg chromeMessage + + // Unmarshal the message received from the browser. + err = json.NewDecoder(&s).Decode(&msg) + if err != nil { + return err + } + + // Currently, the only valid message type is 'get_valid_user_codes'. + // In future, we may introduce additional message types. + if msg.Type != "get_valid_user_codes" { + return fmt.Errorf("invalid type field: %s", msg.Type) + } + + storage := securestorage.NewDeviceCodeSecureStorage() + codes, err := storage.GetValidUserCodes() + if err != nil { + return err + } + + err = json.NewEncoder(&s).Encode(codes) + if err != nil { + return err + } + + // ensure stdout is flushed. If this isn't called, the + // browser extension seems to have issues receiving data. + return os.Stdout.Sync() +} + +type chromeMessage struct { + Type string `json:"type"` +} diff --git a/pkg/granted/entrypoint.go b/pkg/granted/entrypoint.go index 496c2e6a..979915a6 100644 --- a/pkg/granted/entrypoint.go +++ b/pkg/granted/entrypoint.go @@ -4,11 +4,13 @@ import ( "fmt" "os" "path" + "strings" "github.com/common-fate/clio" "github.com/common-fate/clio/cliolog" "github.com/common-fate/glide-cli/cmd/command" "github.com/common-fate/granted/internal/build" + "github.com/common-fate/granted/pkg/chromemsg" "github.com/common-fate/granted/pkg/config" "github.com/common-fate/granted/pkg/granted/auth" "github.com/common-fate/granted/pkg/granted/doctor" @@ -64,6 +66,20 @@ func GetCliApp() *cli.App { &rds.Command, &CFCommand, }, + // Granted may be invoked via our browser extension, which uses the Native Messaging + // protocol to communicate with the Granted CLI. If invoked this way, the browser calls + // the CLI with the ID of the browser extension as the first argument. + Action: func(c *cli.Context) error { + arg := c.Args().First() + if strings.HasPrefix(arg, "chrome-extension://") { + // the CLI has been invoked from our browser extension + return HandleChromeExtensionCall(c) + } + + // Not invoked via the browser extension, so fall back to the default + // behaviour of showing the application help. + return cli.ShowAppHelp(c) + }, EnableBashCompletion: true, Before: func(c *cli.Context) error { if c.String("aws-config-file") != "" { @@ -92,6 +108,11 @@ func GetCliApp() *cli.App { // set the user agent c.Context = useragent.NewContext(c.Context, "granted", build.Version) + err = chromemsg.ConfigureHost() + if err != nil { + clio.Debugf("error configuring Granted browser extension native messaging manifest: %s", err.Error()) + } + return nil }, } diff --git a/pkg/idclogin/run.go b/pkg/idclogin/run.go index eedf6b8f..f3e6cd96 100644 --- a/pkg/idclogin/run.go +++ b/pkg/idclogin/run.go @@ -49,6 +49,16 @@ func Login(ctx context.Context, cfg aws.Config, startUrl string, scopes []string return nil, err } + // store the device code in the keychain, so that the Granted browser extension can read it. + s := securestorage.NewDeviceCodeSecureStorage() + err = s.StoreUserCode(securestorage.UserCode{ + Code: *deviceAuth.UserCode, + Expiry: time.Now().Add(time.Duration(deviceAuth.ExpiresIn) * time.Second), + }) + if err != nil { + clio.Errorf("Error storing user code in keychain: %s", err.Error()) + } + // trigger OIDC login. open browser to login. close tab once login is done. press enter to continue url := aws.ToString(deviceAuth.VerificationUriComplete) clio.Info("If the browser does not open automatically, please open this link: " + url) diff --git a/pkg/securestorage/idc_user_code_storage.go b/pkg/securestorage/idc_user_code_storage.go new file mode 100644 index 00000000..e815f609 --- /dev/null +++ b/pkg/securestorage/idc_user_code_storage.go @@ -0,0 +1,73 @@ +package securestorage + +import ( + "time" + + "github.com/99designs/keyring" + "github.com/common-fate/clio" +) + +type DeviceCodeSecureStorage struct { + SecureStorage SecureStorage +} + +type AllUserCodes struct { + Codes []UserCode `json:"codes"` +} + +// Prune stale user codes that have expired. +func (a *AllUserCodes) Prune(now time.Time) { + var valid []UserCode + for _, c := range a.Codes { + if c.Expiry.After(now) { + valid = append(valid, c) + } + } + + a.Codes = valid +} + +type UserCode struct { + Code string `json:"code"` + Expiry time.Time `json:"expiry"` +} + +func NewDeviceCodeSecureStorage() DeviceCodeSecureStorage { + return DeviceCodeSecureStorage{ + SecureStorage: SecureStorage{ + StorageSuffix: "aws-idc-user-codes", + }, + } +} + +func (i *DeviceCodeSecureStorage) GetValidUserCodes() (AllUserCodes, error) { + var u AllUserCodes + err := i.SecureStorage.Retrieve("codes", &u) + if err == keyring.ErrKeyNotFound { + return AllUserCodes{}, nil + } + + if err != nil { + return AllUserCodes{}, err + } + + u.Prune(time.Now()) + + clio.Debugw("retrieve user codes from keychain", "codes", u) + + return u, nil +} + +func (i *DeviceCodeSecureStorage) StoreUserCode(code UserCode) (err error) { + allCodes, err := i.GetValidUserCodes() + if err != nil { + clio.Debugf("storeusercode: error retrieving IDC user codes in keychain: %s", err.Error()) + } + + allCodes.Codes = append(allCodes.Codes, code) + + clio.Debugw("storing user codes in keychain", "codes", allCodes) + + err = i.SecureStorage.Store("codes", &allCodes) + return +}