diff --git a/integrations/event-handler/go.mod b/integrations/event-handler/go.mod
index 976c668647413..94527d82e944c 100644
--- a/integrations/event-handler/go.mod
+++ b/integrations/event-handler/go.mod
@@ -175,6 +175,7 @@ require (
github.com/googleapis/enterprise-certificate-proxy v0.3.5 // indirect
github.com/googleapis/gax-go/v2 v2.14.1 // indirect
github.com/gorilla/mux v1.8.1 // indirect
+ github.com/gorilla/securecookie v1.1.2 // indirect
github.com/gorilla/websocket v1.5.3 // indirect
github.com/gosuri/uitable v0.0.4 // indirect
github.com/gravitational/license v0.0.0-20240313232707-8312e719d624 // indirect
@@ -225,6 +226,7 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
+ github.com/muhlemmer/gu v0.3.1 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
github.com/okta/okta-sdk-golang/v2 v2.20.0 // indirect
@@ -269,6 +271,9 @@ require (
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
github.com/xlab/treeprint v1.2.0 // indirect
github.com/zeebo/errs v1.3.0 // indirect
+ github.com/zitadel/logging v0.6.2 // indirect
+ github.com/zitadel/oidc/v3 v3.38.1 // indirect
+ github.com/zitadel/schema v1.3.1 // indirect
github.com/zmap/zcrypto v0.0.0-20231219022726-a1f61fb1661c // indirect
github.com/zmap/zlint/v3 v3.6.0 // indirect
go.mongodb.org/mongo-driver v1.14.0 // indirect
diff --git a/integrations/event-handler/go.sum b/integrations/event-handler/go.sum
index ad0ac5fff29ed..180196a7ef53c 100644
--- a/integrations/event-handler/go.sum
+++ b/integrations/event-handler/go.sum
@@ -189,6 +189,8 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
+github.com/bmatcuk/doublestar/v4 v4.8.1 h1:54Bopc5c2cAvhLRAzqOGCYHYyhcDHsFF4wWIR5wKP38=
+github.com/bmatcuk/doublestar/v4 v4.8.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/boombuler/barcode v1.0.1 h1:NDBbPmhS+EqABEs5Kg3n/5ZNjy73Pz7SIV+KCeqyXcs=
github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
@@ -310,6 +312,9 @@ github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-asn1-ber/asn1-ber v1.5.5 h1:MNHlNMBDgEKD4TcKr36vQN68BA00aDfjIt3/bD50WnA=
github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
+github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec=
+github.com/go-chi/chi/v5 v5.2.1 h1:KOIHODQj58PmL80G2Eak4WdvUzjSJSm0vG72crDCqb8=
+github.com/go-chi/chi/v5 v5.2.1/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs=
@@ -438,6 +443,8 @@ github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyE
github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
+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.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
@@ -514,6 +521,8 @@ github.com/jackc/pgx/v5 v5.7.1 h1:x7SYsPBYDkHDksogeSmZZ5xzThcTgRz++I5E+ePFUcs=
github.com/jackc/pgx/v5 v5.7.1/go.mod h1:e7O26IywZZ+naJtWWos6i6fvWK+29etgITqrqHLfoZA=
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
+github.com/jeremija/gosubmit v0.2.8 h1:mmSITBz9JxVtu8eqbN+zmmwX7Ij2RidQxhcwRVI4wqA=
+github.com/jeremija/gosubmit v0.2.8/go.mod h1:Ui+HS073lCFREXBbdfrJzMB57OI/bdxTiLtrDHHhFPI=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
@@ -612,6 +621,10 @@ github.com/montanaflynn/stats v0.7.0 h1:r3y12KyNxj/Sb/iOE46ws+3mS1+MZca1wlHQFPsY
github.com/montanaflynn/stats v0.7.0/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
github.com/mreiferson/go-httpclient v0.0.0-20160630210159-31f0106b4474/go.mod h1:OQA4XLvDbMgS8P0CevmM4m9Q3Jq4phKUzcocxuGJ5m8=
github.com/mreiferson/go-httpclient v0.0.0-20201222173833-5e475fde3a4d/go.mod h1:OQA4XLvDbMgS8P0CevmM4m9Q3Jq4phKUzcocxuGJ5m8=
+github.com/muhlemmer/gu v0.3.1 h1:7EAqmFrW7n3hETvuAdmFmn4hS8W+z3LgKtrnow+YzNM=
+github.com/muhlemmer/gu v0.3.1/go.mod h1:YHtHR+gxM+bKEIIs7Hmi9sPT3ZDUvTN/i88wQpZkrdM=
+github.com/muhlemmer/httpforwarded v0.1.0 h1:x4DLrzXdliq8mprgUMR0olDvHGkou5BJsK/vWUetyzY=
+github.com/muhlemmer/httpforwarded v0.1.0/go.mod h1:yo9czKedo2pdZhoXe+yDkGVbU0TJ0q9oQ90BVoDEtw0=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
@@ -696,6 +709,8 @@ github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6po
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
+github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA=
+github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
github.com/rubenv/sql-migrate v1.7.1 h1:f/o0WgfO/GqNuVg+6801K/KW3WdDSupzSjDYODmiUq4=
github.com/rubenv/sql-migrate v1.7.1/go.mod h1:Ob2Psprc0/3ggbM6wCzyYVFFuc6FyZrb2AS+ezLDFb4=
github.com/russellhaering/gosaml2 v0.9.1 h1:H/whrl8NuSoxyW46Ww5lKPskm+5K+qYLw9afqJ/Zef0=
@@ -794,6 +809,12 @@ github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f h1
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
github.com/zeebo/errs v1.3.0 h1:hmiaKqgYZzcVgRL1Vkc1Mn2914BbzB0IBxs+ebeutGs=
github.com/zeebo/errs v1.3.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4=
+github.com/zitadel/logging v0.6.2 h1:MW2kDDR0ieQynPZ0KIZPrh9ote2WkxfBif5QoARDQcU=
+github.com/zitadel/logging v0.6.2/go.mod h1:z6VWLWUkJpnNVDSLzrPSQSQyttysKZ6bCRongw0ROK4=
+github.com/zitadel/oidc/v3 v3.38.1 h1:VTf1Bv/33UbSwJnIWbfEIdpUGYKfoHetuBNIqVTcjvA=
+github.com/zitadel/oidc/v3 v3.38.1/go.mod h1:muukzAasaWmn3vBwEVMglJfuTE0PKCvLJGombPwXIRw=
+github.com/zitadel/schema v1.3.1 h1:QT3kwiRIRXXLVAs6gCK/u044WmUVh6IlbLXUsn6yRQU=
+github.com/zitadel/schema v1.3.1/go.mod h1:071u7D2LQacy1HAN+YnMd/mx1qVE2isb0Mjeqg46xnU=
github.com/zmap/rc2 v0.0.0-20131011165748-24b9757f5521/go.mod h1:3YZ9o3WnatTIZhuOtot4IcUfzoKVjUHqu6WALIyI0nE=
github.com/zmap/rc2 v0.0.0-20190804163417-abaa70531248/go.mod h1:3YZ9o3WnatTIZhuOtot4IcUfzoKVjUHqu6WALIyI0nE=
github.com/zmap/zcertificate v0.0.0-20180516150559-0e3d58b1bac4/go.mod h1:5iU54tB79AMBcySS0R2XIyZBAVmeHranShAFELYx7is=
diff --git a/integrations/terraform/go.mod b/integrations/terraform/go.mod
index 6778a82e6bbd2..f11992ea9dfcb 100644
--- a/integrations/terraform/go.mod
+++ b/integrations/terraform/go.mod
@@ -113,7 +113,7 @@ require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/bgentry/speakeasy v0.1.0 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
- github.com/bmatcuk/doublestar/v4 v4.6.1 // indirect
+ github.com/bmatcuk/doublestar/v4 v4.8.1 // indirect
github.com/boombuler/barcode v1.0.1 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
@@ -200,6 +200,7 @@ require (
github.com/googleapis/enterprise-certificate-proxy v0.3.5 // indirect
github.com/googleapis/gax-go/v2 v2.14.1 // indirect
github.com/gorilla/mux v1.8.1 // indirect
+ github.com/gorilla/securecookie v1.1.2 // indirect
github.com/gorilla/websocket v1.5.3 // indirect
github.com/gosuri/uitable v0.0.4 // indirect
github.com/gravitational/license v0.0.0-20240313232707-8312e719d624 // indirect
@@ -276,6 +277,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
github.com/morikuni/aec v1.0.0 // indirect
+ github.com/muhlemmer/gu v0.3.1 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
github.com/oklog/run v1.0.0 // indirect
@@ -340,6 +342,9 @@ require (
github.com/yusufpapurcu/wmi v1.2.4 // indirect
github.com/zclconf/go-cty v1.14.4 // indirect
github.com/zeebo/errs v1.3.0 // indirect
+ github.com/zitadel/logging v0.6.2 // indirect
+ github.com/zitadel/oidc/v3 v3.38.1 // indirect
+ github.com/zitadel/schema v1.3.1 // indirect
github.com/zmap/zcrypto v0.0.0-20231219022726-a1f61fb1661c // indirect
github.com/zmap/zlint/v3 v3.6.0 // indirect
go.abhg.dev/goldmark/frontmatter v0.2.0 // indirect
diff --git a/integrations/terraform/go.sum b/integrations/terraform/go.sum
index 6f6b88de69023..12f5a0f9a24f7 100644
--- a/integrations/terraform/go.sum
+++ b/integrations/terraform/go.sum
@@ -302,8 +302,8 @@ github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQ
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
-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/bmatcuk/doublestar/v4 v4.8.1 h1:54Bopc5c2cAvhLRAzqOGCYHYyhcDHsFF4wWIR5wKP38=
+github.com/bmatcuk/doublestar/v4 v4.8.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/boombuler/barcode v1.0.1 h1:NDBbPmhS+EqABEs5Kg3n/5ZNjy73Pz7SIV+KCeqyXcs=
github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
@@ -460,6 +460,9 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-asn1-ber/asn1-ber v1.5.5 h1:MNHlNMBDgEKD4TcKr36vQN68BA00aDfjIt3/bD50WnA=
github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
+github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec=
+github.com/go-chi/chi/v5 v5.2.1 h1:KOIHODQj58PmL80G2Eak4WdvUzjSJSm0vG72crDCqb8=
+github.com/go-chi/chi/v5 v5.2.1/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-faster/city v1.0.1 h1:4WAxSZ3V2Ws4QRDrscLEDcibJY8uf41H6AhXDrNDcGw=
@@ -658,6 +661,8 @@ github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyE
github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
+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.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
@@ -828,6 +833,8 @@ github.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh6
github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs=
github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY=
github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
+github.com/jeremija/gosubmit v0.2.8 h1:mmSITBz9JxVtu8eqbN+zmmwX7Ij2RidQxhcwRVI4wqA=
+github.com/jeremija/gosubmit v0.2.8/go.mod h1:Ui+HS073lCFREXBbdfrJzMB57OI/bdxTiLtrDHHhFPI=
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74=
github.com/jhump/protoreflect v1.16.0 h1:54fZg+49widqXYQ0b+usAFHbMkBGR4PpXrsHc8+TBDg=
@@ -979,6 +986,10 @@ github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/mreiferson/go-httpclient v0.0.0-20160630210159-31f0106b4474/go.mod h1:OQA4XLvDbMgS8P0CevmM4m9Q3Jq4phKUzcocxuGJ5m8=
github.com/mreiferson/go-httpclient v0.0.0-20201222173833-5e475fde3a4d/go.mod h1:OQA4XLvDbMgS8P0CevmM4m9Q3Jq4phKUzcocxuGJ5m8=
+github.com/muhlemmer/gu v0.3.1 h1:7EAqmFrW7n3hETvuAdmFmn4hS8W+z3LgKtrnow+YzNM=
+github.com/muhlemmer/gu v0.3.1/go.mod h1:YHtHR+gxM+bKEIIs7Hmi9sPT3ZDUvTN/i88wQpZkrdM=
+github.com/muhlemmer/httpforwarded v0.1.0 h1:x4DLrzXdliq8mprgUMR0olDvHGkou5BJsK/vWUetyzY=
+github.com/muhlemmer/httpforwarded v0.1.0/go.mod h1:yo9czKedo2pdZhoXe+yDkGVbU0TJ0q9oQ90BVoDEtw0=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
@@ -1088,6 +1099,8 @@ github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6po
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
+github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA=
+github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
github.com/rs/zerolog v1.28.0 h1:MirSo27VyNi7RJYP3078AA1+Cyzd2GB66qy3aUHvsWY=
github.com/rs/zerolog v1.28.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0=
github.com/rubenv/sql-migrate v1.7.1 h1:f/o0WgfO/GqNuVg+6801K/KW3WdDSupzSjDYODmiUq4=
@@ -1234,6 +1247,12 @@ github.com/zclconf/go-cty v1.14.4/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgr
github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8=
github.com/zeebo/errs v1.3.0 h1:hmiaKqgYZzcVgRL1Vkc1Mn2914BbzB0IBxs+ebeutGs=
github.com/zeebo/errs v1.3.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4=
+github.com/zitadel/logging v0.6.2 h1:MW2kDDR0ieQynPZ0KIZPrh9ote2WkxfBif5QoARDQcU=
+github.com/zitadel/logging v0.6.2/go.mod h1:z6VWLWUkJpnNVDSLzrPSQSQyttysKZ6bCRongw0ROK4=
+github.com/zitadel/oidc/v3 v3.38.1 h1:VTf1Bv/33UbSwJnIWbfEIdpUGYKfoHetuBNIqVTcjvA=
+github.com/zitadel/oidc/v3 v3.38.1/go.mod h1:muukzAasaWmn3vBwEVMglJfuTE0PKCvLJGombPwXIRw=
+github.com/zitadel/schema v1.3.1 h1:QT3kwiRIRXXLVAs6gCK/u044WmUVh6IlbLXUsn6yRQU=
+github.com/zitadel/schema v1.3.1/go.mod h1:071u7D2LQacy1HAN+YnMd/mx1qVE2isb0Mjeqg46xnU=
github.com/zmap/rc2 v0.0.0-20131011165748-24b9757f5521/go.mod h1:3YZ9o3WnatTIZhuOtot4IcUfzoKVjUHqu6WALIyI0nE=
github.com/zmap/rc2 v0.0.0-20190804163417-abaa70531248/go.mod h1:3YZ9o3WnatTIZhuOtot4IcUfzoKVjUHqu6WALIyI0nE=
github.com/zmap/zcertificate v0.0.0-20180516150559-0e3d58b1bac4/go.mod h1:5iU54tB79AMBcySS0R2XIyZBAVmeHranShAFELYx7is=
diff --git a/lib/auth/auth.go b/lib/auth/auth.go
index 3165eaa006f24..cc8b0eed844fb 100644
--- a/lib/auth/auth.go
+++ b/lib/auth/auth.go
@@ -91,6 +91,7 @@ import (
wanlib "github.com/gravitational/teleport/lib/auth/webauthn"
wantypes "github.com/gravitational/teleport/lib/auth/webauthntypes"
"github.com/gravitational/teleport/lib/authz"
+ "github.com/gravitational/teleport/lib/azuredevops"
"github.com/gravitational/teleport/lib/backend"
"github.com/gravitational/teleport/lib/bitbucket"
"github.com/gravitational/teleport/lib/cache"
@@ -656,6 +657,9 @@ func NewServer(cfg *InitConfig, opts ...ServerOption) (*Server, error) {
return nil, trace.Wrap(err)
}
}
+ if as.azureDevopsIDTokenValidator == nil {
+ as.azureDevopsIDTokenValidator = azuredevops.NewIDTokenValidator()
+ }
if as.circleCITokenValidate == nil {
as.circleCITokenValidate = func(
ctx context.Context, organizationID, token string,
@@ -1090,6 +1094,11 @@ type Server struct {
// the auth server. It can be overridden for the purpose of tests.
gitlabIDTokenValidator gitlabIDTokenValidator
+ // azureDevopsIDTokenValidator allows ID tokens from Azure DevOps to be
+ // validated by the auth server. It can be overridden for the purpose of
+ // tests.
+ azureDevopsIDTokenValidator azureDevopsIDTokenValidator
+
// tpmValidator allows TPMs to be validated by the auth server. It can be
// overridden for the purpose of tests.
tpmValidator func(
diff --git a/lib/auth/join.go b/lib/auth/join.go
index 0f3480e8fb9ac..092d28806257f 100644
--- a/lib/auth/join.go
+++ b/lib/auth/join.go
@@ -313,6 +313,15 @@ func (a *Server) RegisterUsingToken(ctx context.Context, req *types.RegisterUsin
if err != nil {
return nil, trace.Wrap(err)
}
+ case types.JoinMethodAzureDevops:
+ claims, err := a.checkAzureDevopsJoinRequest(ctx, req, provisionToken)
+ if claims != nil {
+ rawClaims = claims.ForAudit()
+ attrs.AzureDevops = claims.JoinAttrs()
+ }
+ if err != nil {
+ return nil, trace.Wrap(err)
+ }
case types.JoinMethodToken:
// no additional validation to perform - the name is enough.
default:
diff --git a/lib/auth/join/join.go b/lib/auth/join/join.go
index db38a45d87022..4ce551b695a5f 100644
--- a/lib/auth/join/join.go
+++ b/lib/auth/join/join.go
@@ -43,6 +43,7 @@ import (
"github.com/gravitational/teleport/lib/auth/join/iam"
"github.com/gravitational/teleport/lib/auth/join/oracle"
"github.com/gravitational/teleport/lib/auth/state"
+ "github.com/gravitational/teleport/lib/azuredevops"
"github.com/gravitational/teleport/lib/bitbucket"
"github.com/gravitational/teleport/lib/circleci"
proxyinsecureclient "github.com/gravitational/teleport/lib/client/proxy/insecure"
@@ -275,6 +276,11 @@ func Register(ctx context.Context, params RegisterParams) (result *RegisterResul
if err != nil {
return nil, trace.Wrap(err)
}
+ case types.JoinMethodAzureDevops:
+ params.IDToken, err = azuredevops.NewIDTokenSource(os.Getenv).GetIDToken(ctx)
+ if err != nil {
+ return nil, trace.Wrap(err)
+ }
}
// If an explicit AuthClient has been provided, we want to go straight to
diff --git a/lib/auth/join_azure_devops.go b/lib/auth/join_azure_devops.go
new file mode 100644
index 0000000000000..03674cdb02938
--- /dev/null
+++ b/lib/auth/join_azure_devops.go
@@ -0,0 +1,90 @@
+/*
+ * Teleport
+ * Copyright (C) 2025 Gravitational, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package auth
+
+import (
+ "context"
+
+ "github.com/gravitational/trace"
+
+ "github.com/gravitational/teleport/api/types"
+ "github.com/gravitational/teleport/lib/azuredevops"
+)
+
+type azureDevopsIDTokenValidator interface {
+ Validate(ctx context.Context, organizationID string, idToken string) (*azuredevops.IDTokenClaims, error)
+}
+
+func (a *Server) checkAzureDevopsJoinRequest(
+ ctx context.Context,
+ req *types.RegisterUsingTokenRequest,
+ pt types.ProvisionToken,
+) (*azuredevops.IDTokenClaims, error) {
+ if req.IDToken == "" {
+ return nil, trace.BadParameter("IDToken not provided for %q join request", types.JoinMethodAzureDevops)
+ }
+ token, ok := pt.(*types.ProvisionTokenV2)
+ if !ok {
+ return nil, trace.BadParameter("%q join method only support ProvisionTokenV2, '%T' was provided", types.JoinMethodAzureDevops, pt)
+ }
+
+ claims, err := a.azureDevopsIDTokenValidator.Validate(
+ ctx,
+ token.Spec.AzureDevops.OrganizationID,
+ req.IDToken,
+ )
+ if err != nil {
+ return nil, trace.Wrap(err)
+ }
+
+ return claims, trace.Wrap(checkAzureDevopsAllowRules(token, claims))
+}
+
+func checkAzureDevopsAllowRules(token *types.ProvisionTokenV2, claims *azuredevops.IDTokenClaims) error {
+ // If a single rule passes, accept the IDToken
+ for _, rule := range token.Spec.AzureDevops.Allow {
+ if rule.Sub != "" && rule.Sub != claims.Sub {
+ continue
+ }
+ if rule.ProjectName != "" && rule.ProjectName != claims.ProjectName {
+ continue
+ }
+ if rule.PipelineName != "" && rule.PipelineName != claims.PipelineName {
+ continue
+ }
+ if rule.ProjectID != "" && claims.ProjectID != rule.ProjectID {
+ continue
+ }
+ if rule.DefinitionID != "" && claims.DefinitionID != rule.DefinitionID {
+ continue
+ }
+ if rule.RepositoryURI != "" && claims.RepositoryURI != rule.RepositoryURI {
+ continue
+ }
+ if rule.RepositoryVersion != "" && claims.RepositoryVersion != rule.RepositoryVersion {
+ continue
+ }
+ if rule.RepositoryRef != "" && claims.RepositoryRef != rule.RepositoryRef {
+ continue
+ }
+ return nil
+ }
+
+ return trace.AccessDenied("id token claims failed to match any allow rules")
+}
diff --git a/lib/auth/join_azure_devops_test.go b/lib/auth/join_azure_devops_test.go
new file mode 100644
index 0000000000000..dcae909be7952
--- /dev/null
+++ b/lib/auth/join_azure_devops_test.go
@@ -0,0 +1,338 @@
+/*
+ * Teleport
+ * Copyright (C) 2025 Gravitational, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package auth
+
+import (
+ "context"
+ "fmt"
+ "testing"
+ "time"
+
+ "github.com/gravitational/trace"
+ "github.com/stretchr/testify/require"
+
+ "github.com/gravitational/teleport/api/types"
+ "github.com/gravitational/teleport/lib/auth/testauthority"
+ "github.com/gravitational/teleport/lib/azuredevops"
+)
+
+type mockAzureDevopsTokenValidator struct {
+ tokens map[string]map[string]azuredevops.IDTokenClaims
+}
+
+func (m *mockAzureDevopsTokenValidator) Validate(
+ _ context.Context, organizationID string, token string,
+) (*azuredevops.IDTokenClaims, error) {
+ orgTokens := m.tokens[organizationID]
+ if orgTokens == nil {
+ return nil, fmt.Errorf("bad organization ID: %s", organizationID)
+ }
+ claims, ok := orgTokens[token]
+ if !ok {
+ return nil, errMockInvalidToken
+ }
+
+ return &claims, nil
+}
+
+func TestAuth_RegisterUsingToken_AzureDevops(t *testing.T) {
+ const (
+ validIDToken = "test.fake.jwt"
+ validOrgID = "0000-0000-0000-1337"
+ fakeSub = "p://my-org/my-project/my-pipeline"
+ fakeOrgName = "my-org"
+ fakeProjectName = "my-project"
+ fakePipelineName = "my-pipeline"
+ fakeProjectID = "711ef6f7-0000-0000-0000-4b54d912999"
+ fakeDefinitionID = "1"
+ fakeRepositoryURI = "https://github.com/gravitational/teleport.git"
+ fakeRepositoryVersion = "e6b9eb29a288b27a3a82cc19c48b9d94b80aff36"
+ fakeRepositoryRef = "refs/heads/main"
+ )
+
+ idTokenValidator := &mockAzureDevopsTokenValidator{
+ tokens: map[string]map[string]azuredevops.IDTokenClaims{
+ validOrgID: {
+ validIDToken: {
+ Sub: fakeSub,
+ ProjectName: fakeProjectName,
+ OrganizationName: fakeOrgName,
+ ProjectID: fakeProjectID,
+ DefinitionID: fakeDefinitionID,
+ RepositoryURI: fakeRepositoryURI,
+ RepositoryVersion: fakeRepositoryVersion,
+ RepositoryRef: fakeRepositoryRef,
+ PipelineName: fakePipelineName,
+ },
+ },
+ },
+ }
+
+ ctx := context.Background()
+ p, err := newTestPack(ctx, t.TempDir(), func(server *Server) error {
+ server.azureDevopsIDTokenValidator = idTokenValidator
+ return nil
+ })
+ require.NoError(t, err)
+ auth := p.a
+
+ // helper for creating RegisterUsingTokenRequest
+ sshPrivateKey, sshPublicKey, err := testauthority.New().GenerateKeyPair()
+ require.NoError(t, err)
+ tlsPublicKey, err := PrivateKeyToPublicKeyTLS(sshPrivateKey)
+ require.NoError(t, err)
+ newRequest := func(idToken string) *types.RegisterUsingTokenRequest {
+ return &types.RegisterUsingTokenRequest{
+ HostID: "host-id",
+ Role: types.RoleNode,
+ IDToken: idToken,
+ PublicTLSKey: tlsPublicKey,
+ PublicSSHKey: sshPublicKey,
+ }
+ }
+
+ allowRule := func(modifier func(devops *types.ProvisionTokenSpecV2AzureDevops_Rule)) *types.ProvisionTokenSpecV2AzureDevops_Rule {
+ rule := &types.ProvisionTokenSpecV2AzureDevops_Rule{
+ Sub: fakeSub,
+ ProjectName: fakeProjectName,
+ PipelineName: fakePipelineName,
+ ProjectID: fakeProjectID,
+ DefinitionID: fakeDefinitionID,
+ RepositoryURI: fakeRepositoryURI,
+ RepositoryVersion: fakeRepositoryVersion,
+ RepositoryRef: fakeRepositoryRef,
+ }
+ if modifier != nil {
+ modifier(rule)
+ }
+ return rule
+ }
+
+ allowRulesNotMatched := require.ErrorAssertionFunc(func(t require.TestingT, err error, i ...interface{}) {
+ require.ErrorContains(t, err, "id token claims failed to match any allow rules")
+ require.True(t, trace.IsAccessDenied(err))
+ })
+
+ tests := []struct {
+ name string
+ request *types.RegisterUsingTokenRequest
+ tokenSpec types.ProvisionTokenSpecV2
+ assertError require.ErrorAssertionFunc
+ }{
+ {
+ name: "success",
+ tokenSpec: types.ProvisionTokenSpecV2{
+ JoinMethod: types.JoinMethodAzureDevops,
+ Roles: []types.SystemRole{types.RoleNode},
+ AzureDevops: &types.ProvisionTokenSpecV2AzureDevops{
+ OrganizationID: validOrgID,
+ Allow: []*types.ProvisionTokenSpecV2AzureDevops_Rule{
+ allowRule(nil),
+ },
+ },
+ },
+ request: newRequest(validIDToken),
+ assertError: require.NoError,
+ },
+ {
+ name: "multiple allow rules",
+ tokenSpec: types.ProvisionTokenSpecV2{
+ JoinMethod: types.JoinMethodAzureDevops,
+ Roles: []types.SystemRole{types.RoleNode},
+ AzureDevops: &types.ProvisionTokenSpecV2AzureDevops{
+ OrganizationID: validOrgID,
+ Allow: []*types.ProvisionTokenSpecV2AzureDevops_Rule{
+ allowRule(func(rule *types.ProvisionTokenSpecV2AzureDevops_Rule) {
+ rule.Sub = "no-match"
+ }),
+ allowRule(nil),
+ },
+ },
+ },
+ request: newRequest(validIDToken),
+ assertError: require.NoError,
+ },
+ {
+ name: "incorrect sub",
+ tokenSpec: types.ProvisionTokenSpecV2{
+ JoinMethod: types.JoinMethodAzureDevops,
+ Roles: []types.SystemRole{types.RoleNode},
+ AzureDevops: &types.ProvisionTokenSpecV2AzureDevops{
+ OrganizationID: validOrgID,
+ Allow: []*types.ProvisionTokenSpecV2AzureDevops_Rule{
+ allowRule(func(rule *types.ProvisionTokenSpecV2AzureDevops_Rule) {
+ rule.Sub = "wrong"
+ }),
+ },
+ },
+ },
+ request: newRequest(validIDToken),
+ assertError: allowRulesNotMatched,
+ },
+ {
+ name: "incorrect project_name",
+ tokenSpec: types.ProvisionTokenSpecV2{
+ JoinMethod: types.JoinMethodAzureDevops,
+ Roles: []types.SystemRole{types.RoleNode},
+ AzureDevops: &types.ProvisionTokenSpecV2AzureDevops{
+ OrganizationID: validOrgID,
+ Allow: []*types.ProvisionTokenSpecV2AzureDevops_Rule{
+ allowRule(func(rule *types.ProvisionTokenSpecV2AzureDevops_Rule) {
+ rule.ProjectName = "wrong"
+ }),
+ },
+ },
+ },
+ request: newRequest(validIDToken),
+ assertError: allowRulesNotMatched,
+ },
+ {
+ name: "incorrect pipeline name",
+ tokenSpec: types.ProvisionTokenSpecV2{
+ JoinMethod: types.JoinMethodAzureDevops,
+ Roles: []types.SystemRole{types.RoleNode},
+ AzureDevops: &types.ProvisionTokenSpecV2AzureDevops{
+ OrganizationID: validOrgID,
+ Allow: []*types.ProvisionTokenSpecV2AzureDevops_Rule{
+ allowRule(func(rule *types.ProvisionTokenSpecV2AzureDevops_Rule) {
+ rule.PipelineName = "wrong"
+ }),
+ },
+ },
+ },
+ request: newRequest(validIDToken),
+ assertError: allowRulesNotMatched,
+ },
+ {
+ name: "incorrect project id",
+ tokenSpec: types.ProvisionTokenSpecV2{
+ JoinMethod: types.JoinMethodAzureDevops,
+ Roles: []types.SystemRole{types.RoleNode},
+ AzureDevops: &types.ProvisionTokenSpecV2AzureDevops{
+ OrganizationID: validOrgID,
+ Allow: []*types.ProvisionTokenSpecV2AzureDevops_Rule{
+ allowRule(func(rule *types.ProvisionTokenSpecV2AzureDevops_Rule) {
+ rule.ProjectID = "wrong"
+ }),
+ },
+ },
+ },
+ request: newRequest(validIDToken),
+ assertError: allowRulesNotMatched,
+ },
+ {
+ name: "incorrect definition id",
+ tokenSpec: types.ProvisionTokenSpecV2{
+ JoinMethod: types.JoinMethodAzureDevops,
+ Roles: []types.SystemRole{types.RoleNode},
+ AzureDevops: &types.ProvisionTokenSpecV2AzureDevops{
+ OrganizationID: validOrgID,
+ Allow: []*types.ProvisionTokenSpecV2AzureDevops_Rule{
+ allowRule(func(rule *types.ProvisionTokenSpecV2AzureDevops_Rule) {
+ rule.DefinitionID = "wrong"
+ }),
+ },
+ },
+ },
+ request: newRequest(validIDToken),
+ assertError: allowRulesNotMatched,
+ },
+ {
+ name: "incorrect repository uri",
+ tokenSpec: types.ProvisionTokenSpecV2{
+ JoinMethod: types.JoinMethodAzureDevops,
+ Roles: []types.SystemRole{types.RoleNode},
+ AzureDevops: &types.ProvisionTokenSpecV2AzureDevops{
+ OrganizationID: validOrgID,
+ Allow: []*types.ProvisionTokenSpecV2AzureDevops_Rule{
+ allowRule(func(rule *types.ProvisionTokenSpecV2AzureDevops_Rule) {
+ rule.RepositoryURI = "wrong"
+ }),
+ },
+ },
+ },
+ request: newRequest(validIDToken),
+ assertError: allowRulesNotMatched,
+ },
+ {
+ name: "incorrect repository version",
+ tokenSpec: types.ProvisionTokenSpecV2{
+ JoinMethod: types.JoinMethodAzureDevops,
+ Roles: []types.SystemRole{types.RoleNode},
+ AzureDevops: &types.ProvisionTokenSpecV2AzureDevops{
+ OrganizationID: validOrgID,
+ Allow: []*types.ProvisionTokenSpecV2AzureDevops_Rule{
+ allowRule(func(rule *types.ProvisionTokenSpecV2AzureDevops_Rule) {
+ rule.RepositoryVersion = "wrong"
+ }),
+ },
+ },
+ },
+ request: newRequest(validIDToken),
+ assertError: allowRulesNotMatched,
+ },
+ {
+ name: "incorrect repository ref",
+ tokenSpec: types.ProvisionTokenSpecV2{
+ JoinMethod: types.JoinMethodAzureDevops,
+ Roles: []types.SystemRole{types.RoleNode},
+ AzureDevops: &types.ProvisionTokenSpecV2AzureDevops{
+ OrganizationID: validOrgID,
+ Allow: []*types.ProvisionTokenSpecV2AzureDevops_Rule{
+ allowRule(func(rule *types.ProvisionTokenSpecV2AzureDevops_Rule) {
+ rule.RepositoryRef = "wrong"
+ }),
+ },
+ },
+ },
+ request: newRequest(validIDToken),
+ assertError: allowRulesNotMatched,
+ },
+ {
+ name: "invalid token",
+ tokenSpec: types.ProvisionTokenSpecV2{
+ JoinMethod: types.JoinMethodAzureDevops,
+ Roles: []types.SystemRole{types.RoleNode},
+ AzureDevops: &types.ProvisionTokenSpecV2AzureDevops{
+ OrganizationID: validOrgID,
+ Allow: []*types.ProvisionTokenSpecV2AzureDevops_Rule{
+ allowRule(nil),
+ },
+ },
+ },
+ request: newRequest("some other token"),
+ assertError: func(t require.TestingT, err error, i ...interface{}) {
+ require.ErrorIs(t, err, errMockInvalidToken)
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ token, err := types.NewProvisionTokenFromSpec(
+ tt.name, time.Now().Add(time.Minute), tt.tokenSpec,
+ )
+ require.NoError(t, err)
+ require.NoError(t, auth.CreateToken(ctx, token))
+ tt.request.Token = tt.name
+
+ _, err = auth.RegisterUsingToken(ctx, tt.request)
+ tt.assertError(t, err)
+ })
+ }
+}
diff --git a/lib/auth/machineid/machineidv1/bot_service.go b/lib/auth/machineid/machineidv1/bot_service.go
index 139612f54b056..848a6da25d431 100644
--- a/lib/auth/machineid/machineidv1/bot_service.go
+++ b/lib/auth/machineid/machineidv1/bot_service.go
@@ -47,6 +47,7 @@ import (
// lib/tbot/config
var SupportedJoinMethods = []types.JoinMethod{
types.JoinMethodAzure,
+ types.JoinMethodAzureDevops,
types.JoinMethodCircleCI,
types.JoinMethodGCP,
types.JoinMethodGitHub,
diff --git a/lib/azuredevops/azuredevops.go b/lib/azuredevops/azuredevops.go
index 1abb290966daa..2bf0344e2474b 100644
--- a/lib/azuredevops/azuredevops.go
+++ b/lib/azuredevops/azuredevops.go
@@ -68,6 +68,27 @@ func (c *IDTokenClaims) GetSubject() string {
return c.Sub
}
+// ForAudit returns a map of the claims with the names adjusted to match the
+// definition in the JoinToken allow rules. This allows us to provide a better
+// UX by using the same names in the allow rules as are presented in the audit
+// logs.
+func (c *IDTokenClaims) ForAudit() map[string]any {
+ return map[string]any{
+ "sub": c.Sub,
+ "organization_name": c.OrganizationName,
+ "project_name": c.ProjectName,
+ "pipeline_name": c.PipelineName,
+ "organization_id": c.OrganizationID,
+ "project_id": c.ProjectID,
+ "definition_id": c.DefinitionID,
+ "repository_id": c.RepositoryID,
+ "repository_uri": c.RepositoryURI,
+ "repository_ver": c.RepositoryVersion,
+ "repository_ref": c.RepositoryRef,
+ "raw": c,
+ }
+}
+
// JoinAttrs returns the protobuf representation of the attested identity.
// This is used for auditing and for evaluation of WorkloadIdentity rules and
// templating.
diff --git a/lib/service/service.go b/lib/service/service.go
index 30cf53df37571..a92d73e74967a 100644
--- a/lib/service/service.go
+++ b/lib/service/service.go
@@ -6632,6 +6632,7 @@ func readOrGenerateHostID(ctx context.Context, cfg *servicecfg.Config, kubeBacke
switch cfg.JoinMethod {
case types.JoinMethodToken,
types.JoinMethodUnspecified,
+ types.JoinMethodAzureDevops,
types.JoinMethodIAM,
types.JoinMethodCircleCI,
types.JoinMethodKubernetes,
diff --git a/lib/tbot/config/config.go b/lib/tbot/config/config.go
index 9577e1a2c4e00..4e3217884ac2c 100644
--- a/lib/tbot/config/config.go
+++ b/lib/tbot/config/config.go
@@ -51,6 +51,7 @@ var tracer = otel.Tracer("github.com/gravitational/teleport/lib/tbot/config")
var SupportedJoinMethods = []string{
string(types.JoinMethodAzure),
+ string(types.JoinMethodAzureDevops),
string(types.JoinMethodBitbucket),
string(types.JoinMethodCircleCI),
string(types.JoinMethodGCP),