зеркало из https://github.com/Azure/ARO-RP.git
Merge pull request #3920 from Azure/gniranjan/checkaccess
Fix CheckAccess group expansion bug
This commit is contained in:
Коммит
52447fd112
|
@ -98,6 +98,7 @@ github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV
|
|||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
|
@ -121,11 +122,15 @@ github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQL
|
|||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc=
|
||||
github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||
github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=
|
||||
github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI=
|
||||
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||
github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
|
||||
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
|
||||
github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=
|
||||
github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
|
@ -142,6 +147,8 @@ github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7
|
|||
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
|
||||
github.com/go-logr/logr v1.2.0 h1:QK40JKJyMdUDz+h+xvCsru/bJhvG0UxvePV0ufL/AcE=
|
||||
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
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/zapr v1.2.0/go.mod h1:Qa4Bsj2Vb+FAVeAKsLD8RLQ+YRJB8YDmOAKxaBQf7Ro=
|
||||
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
|
@ -152,6 +159,8 @@ github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/
|
|||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gobuffalo/flect v0.2.5 h1:H6vvsv2an0lalEaCDRThvtBfmg44W/QHXBCYUXf/6S4=
|
||||
github.com/gobuffalo/flect v0.2.5/go.mod h1:1ZyCLIbg0YD7sDkzvFdPoOydPtD8y9JQnrOROolUcM8=
|
||||
github.com/gobuffalo/flect v1.0.3 h1:xeWBM2nui+qnVvNM4S3foBhCAL2XgPU+a7FdpelbTq4=
|
||||
github.com/gobuffalo/flect v1.0.3/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
|
@ -207,9 +216,12 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
|
||||
github.com/google/gofuzz v1.1.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/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
|
@ -263,6 +275,8 @@ github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:
|
|||
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
|
@ -297,9 +311,14 @@ github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJ
|
|||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
|
||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
|
@ -395,6 +414,8 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU
|
|||
github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
|
||||
github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q=
|
||||
github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
|
||||
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
|
||||
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
|
@ -403,15 +424,22 @@ github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5q
|
|||
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
|
@ -506,6 +534,8 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
|
||||
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
|
||||
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
@ -555,6 +585,8 @@ golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qx
|
|||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
|
||||
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
|
||||
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=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
|
@ -579,6 +611,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
|
|||
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/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
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=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
|
@ -645,6 +679,10 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c=
|
||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
||||
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
@ -657,6 +695,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
|
||||
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
|
@ -721,6 +761,8 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
|||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.10-0.20220218145154-897bd77cd717 h1:hI3jKY4Hpf63ns040onEbB3dAkR/H/P83hw1TG8dD3Y=
|
||||
golang.org/x/tools v0.1.10-0.20220218145154-897bd77cd717/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
|
||||
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
|
||||
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
|
||||
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=
|
||||
|
@ -863,6 +905,8 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
|
|||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
||||
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
@ -874,10 +918,16 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
|
|||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
k8s.io/api v0.24.0 h1:J0hann2hfxWr1hinZIDefw7Q96wmCBx6SSB8IY0MdDg=
|
||||
k8s.io/api v0.24.0/go.mod h1:5Jl90IUrJHUJYEMANRURMiVvJ0g7Ax7r3R1bqO8zx8I=
|
||||
k8s.io/api v0.31.1 h1:Xe1hX/fPW3PXYYv8BlozYqw63ytA92snr96zMW9gWTU=
|
||||
k8s.io/api v0.31.1/go.mod h1:sbN1g6eY6XVLeqNsZGLnI5FwVseTrZX7Fv3O26rhAaI=
|
||||
k8s.io/apiextensions-apiserver v0.24.0 h1:JfgFqbA8gKJ/uDT++feAqk9jBIwNnL9YGdQvaI9DLtY=
|
||||
k8s.io/apiextensions-apiserver v0.24.0/go.mod h1:iuVe4aEpe6827lvO6yWQVxiPSpPoSKVjkq+MIdg84cM=
|
||||
k8s.io/apiextensions-apiserver v0.31.1 h1:L+hwULvXx+nvTYX/MKM3kKMZyei+UiSXQWciX/N6E40=
|
||||
k8s.io/apiextensions-apiserver v0.31.1/go.mod h1:tWMPR3sgW+jsl2xm9v7lAyRF1rYEK71i9G5dRtkknoQ=
|
||||
k8s.io/apimachinery v0.24.0 h1:ydFCyC/DjCvFCHK5OPMKBlxayQytB8pxy8YQInd5UyQ=
|
||||
k8s.io/apimachinery v0.24.0/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM=
|
||||
k8s.io/apimachinery v0.31.1 h1:mhcUBbj7KUjaVhyXILglcVjuS4nYXiwC+KKFBgIVy7U=
|
||||
k8s.io/apimachinery v0.31.1/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
|
||||
k8s.io/apiserver v0.24.0/go.mod h1:WFx2yiOMawnogNToVvUYT9nn1jaIkMKj41ZYCVycsBA=
|
||||
k8s.io/client-go v0.24.0/go.mod h1:VFPQET+cAFpYxh6Bq6f4xyMY80G6jKKktU6G0m00VDw=
|
||||
k8s.io/code-generator v0.24.0/go.mod h1:dpVhs00hTuTdTY6jvVxvTFCk6gSMrtfRydbhZwHI15w=
|
||||
|
@ -888,21 +938,33 @@ k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
|
|||
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
|
||||
k8s.io/klog/v2 v2.60.1 h1:VW25q3bZx9uE3vvdL6M8ezOX79vA2Aq1nEWLqNQclHc=
|
||||
k8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
|
||||
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
||||
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||
k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk=
|
||||
k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 h1:HNSDgDCrr/6Ly3WEGKZftiE7IY19Vz2GdbOCyI4qqhc=
|
||||
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A=
|
||||
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.30/go.mod h1:fEO7lRTdivWO2qYVCVG7dEADOMo/MLDCVr8So2g88Uw=
|
||||
sigs.k8s.io/controller-tools v0.9.0 h1:b/vSEPpA8hiMiyzDfLbZdCn3hoAcy3/868OHhYtHY9w=
|
||||
sigs.k8s.io/controller-tools v0.9.0/go.mod h1:NUkn8FTV3Sad3wWpSK7dt/145qfuQ8CKJV6j4jHC5rM=
|
||||
sigs.k8s.io/controller-tools v0.16.4 h1:VXmar78eDXbx1by/H09ikEq1hiq3bqInxuV3lMr3GmQ=
|
||||
sigs.k8s.io/controller-tools v0.16.4/go.mod h1:kcsZyYMXiOFuBhofSPtkB90zTSxVRxVVyvtKQcx3q1A=
|
||||
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 h1:kDi4JBNAsJWfz1aEXhO8Jg87JJaPNLh5tIzYHgStQ9Y=
|
||||
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY=
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 h1:bKCqE9GvQ5tiVHn5rfn1r+yao3aLQEaLzkkmAkf+A6Y=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
|
||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
|
||||
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
|
||||
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
||||
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
||||
|
|
7
go.mod
7
go.mod
|
@ -4,8 +4,8 @@ go 1.21
|
|||
|
||||
require (
|
||||
github.com/Azure/azure-sdk-for-go v63.1.0+incompatible
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v3 v3.0.0-beta.2
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/cosmos/armcosmos/v2 v2.5.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0
|
||||
|
@ -15,6 +15,7 @@ require (
|
|||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.5.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.1.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.3.2
|
||||
github.com/Azure/checkaccess-v2-go-sdk v0.0.3
|
||||
github.com/Azure/go-autorest/autorest v0.11.29
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.23
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0
|
||||
|
@ -97,7 +98,7 @@ require (
|
|||
|
||||
require (
|
||||
dario.cat/mergo v1.0.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.1 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
||||
|
|
24
go.sum
24
go.sum
|
@ -4,12 +4,14 @@ github.com/14rcole/gopopulate v0.0.0-20180821133914-b175b219e774 h1:SCbEWT58NSt7
|
|||
github.com/14rcole/gopopulate v0.0.0-20180821133914-b175b219e774/go.mod h1:6/0dYRLLXyJjbkIPeeGyoJ/eKOSI0eU6eTlCBYibgd0=
|
||||
github.com/Azure/azure-sdk-for-go v63.1.0+incompatible h1:yNC7qlSUWVF8p0TzxdmWW1FJ3DdIA+0Pge41IU/2+9U=
|
||||
github.com/Azure/azure-sdk-for-go v63.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 h1:E+OJmp2tPvt1W+amx48v1eqbjDYsgN+RzP4q16yV5eM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1/go.mod h1:a6xsAQUZg+VsS3TJ05SRp524Hs4pZ/AeFSr5ENf0Yjo=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 h1:tfLQ34V6F7tVSwoTf/4lH5sE0o6eCJuNDTmH09nDpbc=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 h1:jBQA3cKT4L2rWMpgE7Yt3Hwh2aUj8KXjIGLxjHeYNNo=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0/go.mod h1:4OG6tQ9EOP/MT0NMjDlRzWoVFxfu9rN9B2X+tlSVktg=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0 h1:JZg6HRh6W6U4OLl6lk7BZ7BLisIzM9dG1R50zUk9C/M=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0/go.mod h1:YL1xnZ6QejvQHWJrX/AvhFl4WW4rqHVoKspWNVwFk0M=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0 h1:B/dfvscEQtew9dVuoxqxrUKKv8Ih2f55PydknDamU+g=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0/go.mod h1:fiPSssYvltE08HJchL04dOy+RD4hgrjph0cwGGMntdI=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.0 h1:+m0M/LFxN43KvULkDNfdXOgrjtg6UYJPFBJyuEcRCAw=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.0/go.mod h1:PwOyop78lveYMRs6oCxjiVyBdyCgIYH6XHIVZO9/SFQ=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v3 v3.0.0-beta.2 h1:qiir/pptnHqp6hV8QwV+IExYIf6cPsXBfUDUXQ27t2Y=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v3 v3.0.0-beta.2/go.mod h1:jVRrRDLCOuif95HDYC23ADTMlvahB7tMdl519m9Iyjc=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/cosmos/armcosmos/v2 v2.5.0 h1:FTNvxTFH/08JBmhcbL5lmLaGYVXokZM6Ni92Mqr+gSg=
|
||||
|
@ -36,6 +38,8 @@ github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.1 h1:9fXQS
|
|||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.1/go.mod h1:f+OaoSg0VQYPMqB0Jp2D54j1VHzITYcJaCNwV+k00ts=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.3.2 h1:YUUxeiOWgdAQE3pXt2H7QXzZs0q8UBjgRbl56qo8GYM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.3.2/go.mod h1:dmXQgZuiSubAecswZE+Sm8jkvEa7kQgTPVRvwL/nd0E=
|
||||
github.com/Azure/checkaccess-v2-go-sdk v0.0.3 h1:c0RL1qvQV/YvM4XVuHkJr1dVI2m5T9cZxtyUeFSQWeU=
|
||||
github.com/Azure/checkaccess-v2-go-sdk v0.0.3/go.mod h1:rpcmeUsB980fGSfoxhGdU9e52mHzNyRgWftOm93Tkio=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
|
||||
|
@ -58,6 +62,8 @@ github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUM
|
|||
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
|
||||
github.com/Azure/msi-dataplane v0.0.6 h1:+IhGETRF9lLNlbs6793xWFKMcbborBtaR2ops1XWlPo=
|
||||
github.com/Azure/msi-dataplane v0.0.6/go.mod h1:/fXvAsxSogxoT7If0xfaeyaIQ7Q/0xAY9ISn7lOpA4o=
|
||||
github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM=
|
||||
github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
|
||||
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
|
||||
|
@ -172,6 +178,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
|||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/disiqueira/gotree/v3 v3.0.2 h1:ik5iuLQQoufZBNPY518dXhiO5056hyNBIK9lWhkNRq8=
|
||||
github.com/disiqueira/gotree/v3 v3.0.2/go.mod h1:ZuyjE4+mUQZlbpkI24AmruZKhg3VHEgPLDY8Qk+uUu8=
|
||||
github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0=
|
||||
|
@ -394,6 +402,8 @@ github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2E
|
|||
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6 h1:IsMZxCuZqKuao2vNdfD82fjjgPLfyHLpR41Z88viRWs=
|
||||
github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6/go.mod h1:3VeWNIJaW+O5xpRQbPp0Ybqu1vJd/pm7s2F473HRrkw=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
|
@ -575,6 +585,8 @@ github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSz
|
|||
github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc=
|
||||
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
|
||||
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
|
||||
github.com/redis/go-redis/v9 v9.6.1 h1:HHDteefn6ZkTtY5fGUE8tj8uy85AHk6zP7CpzIAM0y4=
|
||||
github.com/redis/go-redis/v9 v9.6.1/go.mod h1:0C0c6ycQsdpVNQpxb1njEQIqkx5UcsM8FJCQLgE9+RA=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
|
|
|
@ -169,10 +169,11 @@ func New(ctx context.Context, log *logrus.Entry, _env env.Interface, db database
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fpspID, err := token.GetObjectId(t.Token)
|
||||
tokenClaims, err := token.ExtractClaims(t.Token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fpspID := tokenClaims.ObjectId
|
||||
|
||||
fpCredRPTenant, err := _env.FPNewClientCertificateCredential(_env.TenantID())
|
||||
if err != nil {
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
package remotepdp
|
||||
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the Apache License 2.0.
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
|
||||
|
||||
testhttp "github.com/Azure/ARO-RP/test/util/http/server"
|
||||
)
|
||||
|
||||
func TestClientCreate(t *testing.T) {
|
||||
endpoint := "https://westus.authorization.azure.net/providers/Microsoft.Authorization/checkAccess?api-version=2021-06-01-preview"
|
||||
scope := "https://authorization.azure.net/.default"
|
||||
cred, err := azidentity.NewClientSecretCredential("888988bf-86f1-31ea-91cd-2d7cd011db48", "clientID", "clientSecret", nil)
|
||||
if err != nil {
|
||||
t.Error("Unable to create a new PDP client")
|
||||
}
|
||||
client := NewRemotePDPClient(endpoint, scope, cred)
|
||||
if client.endpoint != endpoint {
|
||||
t.Error("The client endpoint doesn't equal to the target endpoint")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCallingCheckAccess(t *testing.T) {
|
||||
cases := []struct {
|
||||
desc string
|
||||
returnedHttpCode int
|
||||
expectedDecision *AuthorizationDecisionResponse
|
||||
expectedErr error
|
||||
}{
|
||||
{
|
||||
desc: "Successful calls should return an access decision",
|
||||
returnedHttpCode: http.StatusOK,
|
||||
expectedDecision: &AuthorizationDecisionResponse{},
|
||||
expectedErr: nil,
|
||||
}, {
|
||||
desc: "Call resulting in a failure should return an error",
|
||||
returnedHttpCode: http.StatusUnauthorized,
|
||||
expectedDecision: nil,
|
||||
expectedErr: errors.New("An error"),
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
srv, close := testhttp.NewTLSServer()
|
||||
srv.SetResponse(testhttp.WithStatusCode(c.returnedHttpCode))
|
||||
client := createClientWithServer(srv)
|
||||
decision, err := client.CheckAccess(context.Background(), AuthorizationRequest{})
|
||||
if decision != c.expectedDecision && err != c.expectedErr {
|
||||
t.Errorf("%s: expected decision to be %v; and error to be %s. Got %v and %s",
|
||||
c.desc, c.expectedDecision, c.expectedErr, decision, err)
|
||||
}
|
||||
close()
|
||||
}
|
||||
}
|
||||
|
||||
func createClientWithServer(s *testhttp.Server) RemotePDPClient {
|
||||
return &remotePDPClient{
|
||||
endpoint: s.URL(),
|
||||
pipeline: runtime.NewPipeline(
|
||||
"remotepdpclient_test",
|
||||
"v1.0.0",
|
||||
runtime.PipelineOptions{},
|
||||
&policy.ClientOptions{Transport: s},
|
||||
),
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
package remotepdp
|
||||
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the Apache License 2.0.
|
||||
|
||||
//go:generate rm -rf ../../../../../mocks/azureclient/authz/$GOPACKAGE
|
||||
//go:generate mockgen -destination=../../../mocks/azureclient/authz/$GOPACKAGE/$GOPACKAGE.go github.com/Azure/ARO-RP/pkg/util/azureclient/authz/$GOPACKAGE RemotePDPClient
|
||||
//go:generate goimports -local=github.com/Azure/ARO-RP -e -w ../../../mocks/azureclient/authz/$GOPACKAGE/$GOPACKAGE.go
|
|
@ -1,21 +1,20 @@
|
|||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: github.com/Azure/ARO-RP/pkg/util/azureclient/authz/remotepdp (interfaces: RemotePDPClient)
|
||||
// Source: github.com/Azure/checkaccess-v2-go-sdk/client (interfaces: RemotePDPClient)
|
||||
//
|
||||
// Generated by this command:
|
||||
//
|
||||
// mockgen -destination=../../../mocks/azureclient/authz/remotepdp/remotepdp.go github.com/Azure/ARO-RP/pkg/util/azureclient/authz/remotepdp RemotePDPClient
|
||||
// mockgen -destination=../../../pkg/util/mocks/checkaccess/checkaccess.go github.com/Azure/checkaccess-v2-go-sdk/client RemotePDPClient
|
||||
//
|
||||
|
||||
// Package mock_remotepdp is a generated GoMock package.
|
||||
package mock_remotepdp
|
||||
// Package mock_client is a generated GoMock package.
|
||||
package mock_client
|
||||
|
||||
import (
|
||||
context "context"
|
||||
reflect "reflect"
|
||||
|
||||
client "github.com/Azure/checkaccess-v2-go-sdk/client"
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
|
||||
remotepdp "github.com/Azure/ARO-RP/pkg/util/azureclient/authz/remotepdp"
|
||||
)
|
||||
|
||||
// MockRemotePDPClient is a mock of RemotePDPClient interface.
|
||||
|
@ -42,10 +41,10 @@ func (m *MockRemotePDPClient) EXPECT() *MockRemotePDPClientMockRecorder {
|
|||
}
|
||||
|
||||
// CheckAccess mocks base method.
|
||||
func (m *MockRemotePDPClient) CheckAccess(arg0 context.Context, arg1 remotepdp.AuthorizationRequest) (*remotepdp.AuthorizationDecisionResponse, error) {
|
||||
func (m *MockRemotePDPClient) CheckAccess(arg0 context.Context, arg1 client.AuthorizationRequest) (*client.AuthorizationDecisionResponse, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "CheckAccess", arg0, arg1)
|
||||
ret0, _ := ret[0].(*remotepdp.AuthorizationDecisionResponse)
|
||||
ret0, _ := ret[0].(*client.AuthorizationDecisionResponse)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
@ -55,3 +54,18 @@ func (mr *MockRemotePDPClientMockRecorder) CheckAccess(arg0, arg1 any) *gomock.C
|
|||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckAccess", reflect.TypeOf((*MockRemotePDPClient)(nil).CheckAccess), arg0, arg1)
|
||||
}
|
||||
|
||||
// CreateAuthorizationRequest mocks base method.
|
||||
func (m *MockRemotePDPClient) CreateAuthorizationRequest(arg0 string, arg1 []string, arg2 string) (*client.AuthorizationRequest, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "CreateAuthorizationRequest", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(*client.AuthorizationRequest)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// CreateAuthorizationRequest indicates an expected call of CreateAuthorizationRequest.
|
||||
func (mr *MockRemotePDPClientMockRecorder) CreateAuthorizationRequest(arg0, arg1, arg2 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateAuthorizationRequest", reflect.TypeOf((*MockRemotePDPClient)(nil).CreateAuthorizationRequest), arg0, arg1, arg2)
|
||||
}
|
|
@ -6,17 +6,19 @@ package token
|
|||
import "github.com/golang-jwt/jwt/v4"
|
||||
|
||||
type custom struct {
|
||||
ObjectId string `json:"oid"`
|
||||
jwt.StandardClaims
|
||||
ObjectId string `json:"oid"`
|
||||
ClaimNames map[string]interface{} `json:"_claim_names"`
|
||||
Groups []string `json:"groups"`
|
||||
jwt.RegisteredClaims
|
||||
}
|
||||
|
||||
// GetObjectId extracts the "oid" claim from a given access jwtToken
|
||||
func GetObjectId(jwtToken string) (string, error) {
|
||||
// ExtractClaims extracts the "oid", "_claim_names", and "groups" claims from a given access jwtToken and return them as a custom struct
|
||||
func ExtractClaims(jwtToken string) (*custom, error) {
|
||||
p := jwt.NewParser(jwt.WithoutClaimsValidation())
|
||||
c := &custom{}
|
||||
_, _, err := p.ParseUnverified(jwtToken, c)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return nil, err
|
||||
}
|
||||
return c.ObjectId, nil
|
||||
return c, nil
|
||||
}
|
||||
|
|
|
@ -3,40 +3,61 @@ package token
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the Apache License 2.0.
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/Azure/ARO-RP/pkg/util/cmp"
|
||||
"github.com/Azure/ARO-RP/test/util/token"
|
||||
)
|
||||
|
||||
func TestExtractClaims(t *testing.T) {
|
||||
dummyObjectId := "1234567890"
|
||||
validTestToken, err := token.CreateTestToken(dummyObjectId, nil)
|
||||
if err != nil {
|
||||
t.Errorf("Error creating test token: %v", err)
|
||||
}
|
||||
|
||||
func TestGetObjectId(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
token string
|
||||
want string
|
||||
wantErr bool
|
||||
name string
|
||||
token string
|
||||
wantOid string
|
||||
wantClaims map[string]interface{}
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Can extract oid from a valid token",
|
||||
token: "eyJhbGciOiJIUzI1NiJ9.eyJJc3N1ZXIiOiJJc3N1ZXIiLCJvaWQiOiJub3dheXRoaXNpc2FyZWFsYXBwIiwiZXhwIjoxNjgwODQ2MDI2LCJpYXQiOjE2ODA4NDYwMjZ9.GQxPJbMJYhrXK1YlWUXR_5IpBlvkv9kEdX_Z_vJRxsU",
|
||||
want: "nowaythisisarealapp",
|
||||
wantErr: false,
|
||||
name: "Can extract oid from a valid token",
|
||||
token: validTestToken,
|
||||
wantOid: dummyObjectId,
|
||||
wantClaims: map[string]interface{}{"example_claim": "example_value"},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Return an error when given an invalid jwt",
|
||||
token: "invalid",
|
||||
want: "",
|
||||
wantErr: true,
|
||||
name: "Return an error when given an invalid jwt",
|
||||
token: "invalid",
|
||||
wantOid: "",
|
||||
wantClaims: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := GetObjectId(tt.token)
|
||||
got, err := ExtractClaims(tt.token)
|
||||
t.Log(got, err)
|
||||
if got != tt.want {
|
||||
t.Errorf("Got oid: %q, want %q", got, tt.want)
|
||||
}
|
||||
if tt.wantErr && err == nil {
|
||||
t.Errorf("Expect an error but got nothing")
|
||||
}
|
||||
if !tt.wantErr && err != nil {
|
||||
t.Errorf("Expect no error but got one")
|
||||
|
||||
if tt.wantErr {
|
||||
if err == nil {
|
||||
t.Errorf("Expect an error but got nothing")
|
||||
}
|
||||
} else {
|
||||
if got.ObjectId != tt.wantOid {
|
||||
t.Errorf("Got oid: %q, want %q", got.ObjectId, tt.wantOid)
|
||||
}
|
||||
if diff := cmp.Diff(got.ClaimNames, tt.wantClaims); diff != "" {
|
||||
t.Errorf("Got claimNames: %q, want %q", got.ClaimNames, tt.wantClaims)
|
||||
}
|
||||
if err != nil {
|
||||
t.Errorf("Expect no error but got one")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"testing"
|
||||
|
||||
mgmtcompute "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2020-06-01/compute"
|
||||
"github.com/Azure/checkaccess-v2-go-sdk/client"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
"github.com/Azure/go-autorest/autorest/azure"
|
||||
"github.com/Azure/go-autorest/autorest/to"
|
||||
|
@ -19,10 +20,10 @@ import (
|
|||
|
||||
"github.com/Azure/ARO-RP/pkg/api"
|
||||
"github.com/Azure/ARO-RP/pkg/util/azureclient"
|
||||
"github.com/Azure/ARO-RP/pkg/util/azureclient/authz/remotepdp"
|
||||
mock_remotepdp "github.com/Azure/ARO-RP/pkg/util/mocks/azureclient/authz/remotepdp"
|
||||
mock_azcore "github.com/Azure/ARO-RP/pkg/util/mocks/azureclient/azuresdk/azcore"
|
||||
mock_compute "github.com/Azure/ARO-RP/pkg/util/mocks/azureclient/mgmt/compute"
|
||||
mock_checkaccess "github.com/Azure/ARO-RP/pkg/util/mocks/checkaccess"
|
||||
mock_env "github.com/Azure/ARO-RP/pkg/util/mocks/env"
|
||||
utilerror "github.com/Azure/ARO-RP/test/util/error"
|
||||
)
|
||||
|
||||
|
@ -48,10 +49,10 @@ func TestValidateDiskEncryptionSets(t *testing.T) {
|
|||
for _, tt := range []struct {
|
||||
name string
|
||||
oc *api.OpenShiftCluster
|
||||
actionInfos []remotepdp.ActionInfo
|
||||
actionInfos []client.ActionInfo
|
||||
platformIdentities map[string]api.PlatformWorkloadIdentity
|
||||
platformIdentityMap map[string][]string
|
||||
mocks func(*mock_compute.MockDiskEncryptionSetsClient, *mock_remotepdp.MockRemotePDPClient, *mock_azcore.MockTokenCredential, context.CancelFunc)
|
||||
mocks func(*mock_env.MockInterface, *mock_compute.MockDiskEncryptionSetsClient, *mock_checkaccess.MockRemotePDPClient, *mock_azcore.MockTokenCredential, context.CancelFunc)
|
||||
wantErr string
|
||||
wantFPSPErr string
|
||||
}{
|
||||
|
@ -72,8 +73,11 @@ func TestValidateDiskEncryptionSets(t *testing.T) {
|
|||
}},
|
||||
},
|
||||
},
|
||||
mocks: func(diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, pdpClient *mock_remotepdp.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, cancel context.CancelFunc) {
|
||||
mocks: func(env *mock_env.MockInterface, diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, pdpClient *mock_checkaccess.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, cancel context.CancelFunc) {
|
||||
mockTokenCredential(tokenCred)
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
gomock.Any(), gomock.Any(), gomock.Any()).Return(&client.AuthorizationRequest{}, nil)
|
||||
pdpClient.EXPECT().
|
||||
CheckAccess(gomock.Any(), gomock.Any()).
|
||||
Return(validDiskEncryptionAuthorizationDecision, nil)
|
||||
|
@ -95,8 +99,11 @@ func TestValidateDiskEncryptionSets(t *testing.T) {
|
|||
}},
|
||||
},
|
||||
},
|
||||
mocks: func(diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, pdpClient *mock_remotepdp.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, cancel context.CancelFunc) {
|
||||
mocks: func(env *mock_env.MockInterface, diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, pdpClient *mock_checkaccess.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, cancel context.CancelFunc) {
|
||||
mockTokenCredential(tokenCred)
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
gomock.Any(), gomock.Any(), gomock.Any()).Return(&client.AuthorizationRequest{}, nil)
|
||||
pdpClient.EXPECT().
|
||||
CheckAccess(gomock.Any(), gomock.Any()).
|
||||
Return(validDiskEncryptionAuthorizationDecision, nil)
|
||||
|
@ -122,7 +129,7 @@ func TestValidateDiskEncryptionSets(t *testing.T) {
|
|||
}},
|
||||
},
|
||||
},
|
||||
mocks: func(diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, pdpClient *mock_remotepdp.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, cancel context.CancelFunc) {
|
||||
mocks: func(env *mock_env.MockInterface, diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, pdpClient *mock_checkaccess.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, cancel context.CancelFunc) {
|
||||
mockTokenCredential(tokenCred)
|
||||
diskEncryptionSets.EXPECT().
|
||||
Get(gomock.Any(), fakeDesR1.ResourceGroup, fakeDesR1.ResourceName).
|
||||
|
@ -146,8 +153,11 @@ func TestValidateDiskEncryptionSets(t *testing.T) {
|
|||
}},
|
||||
},
|
||||
},
|
||||
mocks: func(diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, pdpClient *mock_remotepdp.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, cancel context.CancelFunc) {
|
||||
mocks: func(env *mock_env.MockInterface, diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, pdpClient *mock_checkaccess.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, cancel context.CancelFunc) {
|
||||
mockTokenCredential(tokenCred)
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
gomock.Any(), gomock.Any(), gomock.Any()).Return(&client.AuthorizationRequest{}, nil)
|
||||
pdpClient.EXPECT().
|
||||
CheckAccess(gomock.Any(), gomock.Any()).
|
||||
Return(validDiskEncryptionAuthorizationDecision, nil)
|
||||
|
@ -169,11 +179,16 @@ func TestValidateDiskEncryptionSets(t *testing.T) {
|
|||
}},
|
||||
},
|
||||
},
|
||||
mocks: func(diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, pdpClient *mock_remotepdp.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, cancel context.CancelFunc) {
|
||||
mocks: func(env *mock_env.MockInterface, diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, pdpClient *mock_checkaccess.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, cancel context.CancelFunc) {
|
||||
mockTokenCredential(tokenCred)
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(&client.AuthorizationRequest{
|
||||
Resource: client.ResourceInfo{Id: fakeDesR1.String()},
|
||||
}, nil)
|
||||
pdpClient.EXPECT().
|
||||
CheckAccess(gomock.Any(), gomock.Any()).
|
||||
DoAndReturn(func(_ context.Context, authReq remotepdp.AuthorizationRequest) (*remotepdp.AuthorizationDecisionResponse, error) {
|
||||
DoAndReturn(func(_ context.Context, authReq client.AuthorizationRequest) (*client.AuthorizationDecisionResponse, error) {
|
||||
cancel() // wait.PollImmediateUntil will always be invoked at least once
|
||||
switch authReq.Resource.Id {
|
||||
case fakeDesR1.String():
|
||||
|
@ -205,8 +220,11 @@ func TestValidateDiskEncryptionSets(t *testing.T) {
|
|||
}},
|
||||
},
|
||||
},
|
||||
mocks: func(diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, pdpClient *mock_remotepdp.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, cancel context.CancelFunc) {
|
||||
mocks: func(env *mock_env.MockInterface, diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, pdpClient *mock_checkaccess.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, cancel context.CancelFunc) {
|
||||
mockTokenCredential(tokenCred)
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
gomock.Any(), gomock.Any(), gomock.Any()).Return(&client.AuthorizationRequest{}, nil)
|
||||
pdpClient.EXPECT().
|
||||
CheckAccess(gomock.Any(), gomock.Any()).
|
||||
Return(validDiskEncryptionAuthorizationDecision, nil)
|
||||
|
@ -229,8 +247,11 @@ func TestValidateDiskEncryptionSets(t *testing.T) {
|
|||
}},
|
||||
},
|
||||
},
|
||||
mocks: func(diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, pdpClient *mock_remotepdp.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, cancel context.CancelFunc) {
|
||||
mocks: func(env *mock_env.MockInterface, diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, pdpClient *mock_checkaccess.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, cancel context.CancelFunc) {
|
||||
mockTokenCredential(tokenCred)
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
gomock.Any(), gomock.Any(), gomock.Any()).Return(&client.AuthorizationRequest{}, nil)
|
||||
pdpClient.EXPECT().
|
||||
CheckAccess(gomock.Any(), gomock.Any()).
|
||||
Return(nil, errors.New("fakeerr"))
|
||||
|
@ -250,8 +271,11 @@ func TestValidateDiskEncryptionSets(t *testing.T) {
|
|||
}},
|
||||
},
|
||||
},
|
||||
mocks: func(diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, pdpClient *mock_remotepdp.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, cancel context.CancelFunc) {
|
||||
mocks: func(env *mock_env.MockInterface, diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, pdpClient *mock_checkaccess.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, cancel context.CancelFunc) {
|
||||
mockTokenCredential(tokenCred)
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
gomock.Any(), gomock.Any(), gomock.Any()).Return(&client.AuthorizationRequest{}, nil)
|
||||
pdpClient.EXPECT().
|
||||
CheckAccess(gomock.Any(), gomock.Any()).
|
||||
Return(validDiskEncryptionAuthorizationDecision, nil)
|
||||
|
@ -274,8 +298,11 @@ func TestValidateDiskEncryptionSets(t *testing.T) {
|
|||
}},
|
||||
},
|
||||
},
|
||||
mocks: func(diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, pdpClient *mock_remotepdp.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, cancel context.CancelFunc) {
|
||||
mocks: func(env *mock_env.MockInterface, diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, pdpClient *mock_checkaccess.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, cancel context.CancelFunc) {
|
||||
mockTokenCredential(tokenCred)
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
gomock.Any(), gomock.Any(), gomock.Any()).Return(&client.AuthorizationRequest{}, nil)
|
||||
pdpClient.EXPECT().
|
||||
CheckAccess(gomock.Any(), gomock.Any()).
|
||||
Do(func(arg0, arg1 interface{}) {
|
||||
|
@ -297,8 +324,11 @@ func TestValidateDiskEncryptionSets(t *testing.T) {
|
|||
}},
|
||||
},
|
||||
},
|
||||
mocks: func(diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, pdpClient *mock_remotepdp.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, cancel context.CancelFunc) {
|
||||
mocks: func(env *mock_env.MockInterface, diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, pdpClient *mock_checkaccess.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, cancel context.CancelFunc) {
|
||||
mockTokenCredential(tokenCred)
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
gomock.Any(), gomock.Any(), gomock.Any()).Return(&client.AuthorizationRequest{}, nil)
|
||||
pdpClient.EXPECT().
|
||||
CheckAccess(gomock.Any(), gomock.Any()).
|
||||
Do(func(arg0, arg1 interface{}) {
|
||||
|
@ -325,11 +355,20 @@ func TestValidateDiskEncryptionSets(t *testing.T) {
|
|||
}},
|
||||
},
|
||||
},
|
||||
mocks: func(diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, pdpClient *mock_remotepdp.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, cancel context.CancelFunc) {
|
||||
mocks: func(env *mock_env.MockInterface, diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, pdpClient *mock_checkaccess.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, cancel context.CancelFunc) {
|
||||
mockTokenCredential(tokenCred)
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
gomock.Any(), gomock.Any(), gomock.Any()).Return(&client.AuthorizationRequest{
|
||||
Resource: client.ResourceInfo{Id: fakeDesID1},
|
||||
}, nil).Times(1)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
gomock.Any(), gomock.Any(), gomock.Any()).Return(&client.AuthorizationRequest{
|
||||
Resource: client.ResourceInfo{Id: fakeDesID2},
|
||||
}, nil)
|
||||
pdpClient.EXPECT().
|
||||
CheckAccess(gomock.Any(), gomock.Any()).
|
||||
DoAndReturn(func(_ context.Context, authReq remotepdp.AuthorizationRequest) (*remotepdp.AuthorizationDecisionResponse, error) {
|
||||
DoAndReturn(func(_ context.Context, authReq client.AuthorizationRequest) (*client.AuthorizationDecisionResponse, error) {
|
||||
cancel() // wait.PollImmediateUntil will always be invoked at least once
|
||||
switch authReq.Resource.Id {
|
||||
case fakeDesR1.String():
|
||||
|
@ -359,8 +398,11 @@ func TestValidateDiskEncryptionSets(t *testing.T) {
|
|||
}},
|
||||
},
|
||||
},
|
||||
mocks: func(diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, pdpClient *mock_remotepdp.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, cancel context.CancelFunc) {
|
||||
mocks: func(env *mock_env.MockInterface, diskEncryptionSets *mock_compute.MockDiskEncryptionSetsClient, pdpClient *mock_checkaccess.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, cancel context.CancelFunc) {
|
||||
mockTokenCredential(tokenCred)
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
gomock.Any(), gomock.Any(), gomock.Any()).Return(&client.AuthorizationRequest{}, nil)
|
||||
pdpClient.EXPECT().
|
||||
CheckAccess(gomock.Any(), gomock.Any()).
|
||||
Return(validDiskEncryptionAuthorizationDecision, nil)
|
||||
|
@ -378,17 +420,18 @@ func TestValidateDiskEncryptionSets(t *testing.T) {
|
|||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
_env := mock_env.NewMockInterface(controller)
|
||||
diskEncryptionSetsClient := mock_compute.NewMockDiskEncryptionSetsClient(controller)
|
||||
tokenCred := mock_azcore.NewMockTokenCredential(controller)
|
||||
remotePDPClient := mock_remotepdp.NewMockRemotePDPClient(controller)
|
||||
remotePDPClient := mock_checkaccess.NewMockRemotePDPClient(controller)
|
||||
|
||||
if tt.mocks != nil {
|
||||
tt.mocks(diskEncryptionSetsClient, remotePDPClient, tokenCred, cancel)
|
||||
tt.mocks(_env, diskEncryptionSetsClient, remotePDPClient, tokenCred, cancel)
|
||||
}
|
||||
|
||||
dv := &dynamic{
|
||||
appID: to.StringPtr("fff51942-b1f9-4119-9453-aaa922259eb7"),
|
||||
azEnv: &azureclient.PublicCloud,
|
||||
env: _env,
|
||||
authorizerType: authorizerType,
|
||||
log: logrus.NewEntry(logrus.StandardLogger()),
|
||||
diskEncryptionSets: diskEncryptionSetsClient,
|
||||
|
@ -415,19 +458,19 @@ func TestValidateDiskEncryptionSets(t *testing.T) {
|
|||
}
|
||||
|
||||
var (
|
||||
invalidDiskEncryptionAuthorizationDecisionsReadNotAllowed = &remotepdp.AuthorizationDecisionResponse{
|
||||
Value: []remotepdp.AuthorizationDecision{
|
||||
invalidDiskEncryptionAuthorizationDecisionsReadNotAllowed = &client.AuthorizationDecisionResponse{
|
||||
Value: []client.AuthorizationDecision{
|
||||
{
|
||||
ActionId: "Microsoft.Compute/diskEncryptionSets/read",
|
||||
AccessDecision: remotepdp.NotAllowed,
|
||||
AccessDecision: client.NotAllowed,
|
||||
},
|
||||
},
|
||||
}
|
||||
validDiskEncryptionAuthorizationDecision = &remotepdp.AuthorizationDecisionResponse{
|
||||
Value: []remotepdp.AuthorizationDecision{
|
||||
validDiskEncryptionAuthorizationDecision = &client.AuthorizationDecisionResponse{
|
||||
Value: []client.AuthorizationDecision{
|
||||
{
|
||||
ActionId: "Microsoft.Compute/diskEncryptionSets/read",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
|
||||
mgmtnetwork "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2020-08-01/network"
|
||||
"github.com/Azure/checkaccess-v2-go-sdk/client"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
"github.com/Azure/go-autorest/autorest/azure"
|
||||
"github.com/apparentlymart/go-cidr/cidr"
|
||||
|
@ -24,7 +25,6 @@ import (
|
|||
apisubnet "github.com/Azure/ARO-RP/pkg/api/util/subnet"
|
||||
"github.com/Azure/ARO-RP/pkg/env"
|
||||
"github.com/Azure/ARO-RP/pkg/util/azureclient"
|
||||
"github.com/Azure/ARO-RP/pkg/util/azureclient/authz/remotepdp"
|
||||
"github.com/Azure/ARO-RP/pkg/util/azureclient/azuresdk/armauthorization"
|
||||
"github.com/Azure/ARO-RP/pkg/util/azureclient/mgmt/compute"
|
||||
"github.com/Azure/ARO-RP/pkg/util/azureclient/mgmt/network"
|
||||
|
@ -98,7 +98,7 @@ type dynamic struct {
|
|||
resourceSkusClient compute.ResourceSkusClient
|
||||
spNetworkUsage network.UsageClient
|
||||
loadBalancerBackendAddressPoolsClient network.LoadBalancerBackendAddressPoolsClient
|
||||
pdpClient remotepdp.RemotePDPClient
|
||||
pdpClient client.RemotePDPClient
|
||||
}
|
||||
|
||||
type AuthorizerType string
|
||||
|
@ -118,7 +118,7 @@ func NewValidator(
|
|||
appID *string,
|
||||
authorizerType AuthorizerType,
|
||||
cred azcore.TokenCredential,
|
||||
pdpClient remotepdp.RemotePDPClient,
|
||||
pdpClient client.RemotePDPClient,
|
||||
) Dynamic {
|
||||
return &dynamic{
|
||||
log: log,
|
||||
|
@ -446,31 +446,45 @@ type closure struct {
|
|||
resource *azure.Resource
|
||||
actions []string
|
||||
oid *string
|
||||
jwtToken *string
|
||||
}
|
||||
|
||||
func (c *closure) checkAccessAuthReqToken() error {
|
||||
scope := c.dv.env.Environment().ResourceManagerEndpoint + "/.default"
|
||||
t, err := c.dv.checkAccessSubjectInfoCred.GetToken(c.ctx, policy.TokenRequestOptions{Scopes: []string{scope}})
|
||||
if err != nil {
|
||||
c.dv.log.Error("Unable to get the token from AAD: ", err)
|
||||
return err
|
||||
}
|
||||
claims, err := token.ExtractClaims(t.Token)
|
||||
if err != nil {
|
||||
c.dv.log.Error("Unable to get the oid from token: ", err)
|
||||
return err
|
||||
}
|
||||
|
||||
c.oid = &claims.ObjectId
|
||||
c.jwtToken = &t.Token
|
||||
return nil
|
||||
}
|
||||
|
||||
// usingCheckAccessV2 uses the new RBAC checkAccessV2 API
|
||||
func (c closure) usingCheckAccessV2() (bool, error) {
|
||||
c.dv.log.Info("validateActions with CheckAccessV2")
|
||||
|
||||
// reusing oid during retries
|
||||
if c.oid == nil {
|
||||
scope := c.dv.azEnv.ResourceManagerEndpoint + "/.default"
|
||||
t, err := c.dv.checkAccessSubjectInfoCred.GetToken(c.ctx, policy.TokenRequestOptions{Scopes: []string{scope}})
|
||||
if err != nil {
|
||||
c.dv.log.Error("Unable to get the token from AAD: ", err)
|
||||
//ensure token and oid is available during retries
|
||||
if c.jwtToken == nil || c.oid == nil {
|
||||
if err := c.checkAccessAuthReqToken(); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
oid, err := token.GetObjectId(t.Token)
|
||||
if err != nil {
|
||||
c.dv.log.Error("Unable to parse the token oid claim: ", err)
|
||||
return false, err
|
||||
}
|
||||
c.oid = &oid
|
||||
}
|
||||
|
||||
authReq := createAuthorizationRequest(*c.oid, c.resource.String(), c.actions...)
|
||||
results, err := c.dv.pdpClient.CheckAccess(c.ctx, authReq)
|
||||
authReq, err := c.dv.pdpClient.CreateAuthorizationRequest(c.resource.String(), c.actions, *c.jwtToken)
|
||||
if err != nil {
|
||||
c.dv.log.Error("Unexpected error when creating CheckAccessV2 AuthorizationRequest: ", err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
results, err := c.dv.pdpClient.CheckAccess(c.ctx, *authReq)
|
||||
if err != nil {
|
||||
c.dv.log.Error("Unexpected error when calling CheckAccessV2: ", err)
|
||||
return false, err
|
||||
|
@ -489,7 +503,7 @@ func (c closure) usingCheckAccessV2() (bool, error) {
|
|||
_, ok := actionsToFind[result.ActionId]
|
||||
if ok {
|
||||
delete(actionsToFind, result.ActionId)
|
||||
if result.AccessDecision != remotepdp.Allowed {
|
||||
if result.AccessDecision != client.Allowed {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
@ -502,26 +516,6 @@ func (c closure) usingCheckAccessV2() (bool, error) {
|
|||
return true, nil
|
||||
}
|
||||
|
||||
func createAuthorizationRequest(subject, resourceId string, actions ...string) remotepdp.AuthorizationRequest {
|
||||
actionInfos := []remotepdp.ActionInfo{}
|
||||
for _, action := range actions {
|
||||
actionInfos = append(actionInfos, remotepdp.ActionInfo{Id: action})
|
||||
}
|
||||
|
||||
return remotepdp.AuthorizationRequest{
|
||||
Subject: remotepdp.SubjectInfo{
|
||||
Attributes: remotepdp.SubjectAttributes{
|
||||
ObjectId: subject,
|
||||
ClaimName: remotepdp.GroupExpansion, // always do group expansion
|
||||
},
|
||||
},
|
||||
Actions: actionInfos,
|
||||
Resource: remotepdp.ResourceInfo{
|
||||
Id: resourceId,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (dv *dynamic) validateCIDRRanges(ctx context.Context, subnets []Subnet, additionalCIDRs ...string) error {
|
||||
dv.log.Print("ValidateCIDRRanges")
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
|
||||
mgmtnetwork "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2020-08-01/network"
|
||||
"github.com/Azure/checkaccess-v2-go-sdk/client"
|
||||
"github.com/Azure/go-autorest/autorest/azure"
|
||||
"github.com/Azure/go-autorest/autorest/to"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
@ -19,12 +20,13 @@ import (
|
|||
|
||||
"github.com/Azure/ARO-RP/pkg/api"
|
||||
"github.com/Azure/ARO-RP/pkg/util/azureclient"
|
||||
"github.com/Azure/ARO-RP/pkg/util/azureclient/authz/remotepdp"
|
||||
mock_remotepdp "github.com/Azure/ARO-RP/pkg/util/mocks/azureclient/authz/remotepdp"
|
||||
mock_azcore "github.com/Azure/ARO-RP/pkg/util/mocks/azureclient/azuresdk/azcore"
|
||||
mock_network "github.com/Azure/ARO-RP/pkg/util/mocks/azureclient/mgmt/network"
|
||||
mock_checkaccess "github.com/Azure/ARO-RP/pkg/util/mocks/checkaccess"
|
||||
mock_env "github.com/Azure/ARO-RP/pkg/util/mocks/env"
|
||||
"github.com/Azure/ARO-RP/pkg/util/uuid"
|
||||
utilerror "github.com/Azure/ARO-RP/test/util/error"
|
||||
"github.com/Azure/ARO-RP/test/util/token"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -599,10 +601,13 @@ func TestValidateSubnets(t *testing.T) {
|
|||
// This will totally replace the current unit tests using ListPermissions (ListForResource)
|
||||
// once fully migrated to CheckAccessV2
|
||||
|
||||
var mockAccessToken = azcore.AccessToken{
|
||||
Token: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE2ODExNDk2NjksImV4cCI6MTcxMjY4NTY2OSwiYXVkIjoid3d3LmV4YW1wbGUuY29tIiwic3ViIjoianJvY2tldEBleGFtcGxlLmNvbSIsIkdpdmVuTmFtZSI6IkpvaG5ueSIsIlN1cm5hbWUiOiJSb2NrZXQiLCJFbWFpbCI6Impyb2NrZXRAZXhhbXBsZS5jb20iLCJSb2xlIjpbIk1hbmFnZXIiLCJQcm9qZWN0IEFkbWluaXN0cmF0b3IiXSwib2lkIjoiYmlsbHlxZWlsbG9yIn0.3MZk1YRSME8FW0l2DzXsIilEZh08CzjVopy30lbvLqQ", // mocked up data
|
||||
ExpiresOn: time.Now(),
|
||||
}
|
||||
var (
|
||||
validTestToken, _ = token.CreateTestToken(dummyObjectId, nil)
|
||||
mockAccessToken = azcore.AccessToken{
|
||||
Token: validTestToken, // mocked up data
|
||||
ExpiresOn: time.Now(),
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
platformIdentity1SubnetActions = []string{
|
||||
|
@ -622,85 +627,85 @@ var (
|
|||
ObjectID: dummyObjectId,
|
||||
},
|
||||
}
|
||||
validSubnetsAuthorizationDecisions = remotepdp.AuthorizationDecisionResponse{
|
||||
Value: []remotepdp.AuthorizationDecision{
|
||||
validSubnetsAuthorizationDecisions = client.AuthorizationDecisionResponse{
|
||||
Value: []client.AuthorizationDecision{
|
||||
{
|
||||
ActionId: "Microsoft.Network/virtualNetworks/join/action",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
{
|
||||
ActionId: "Microsoft.Network/virtualNetworks/read",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
{
|
||||
ActionId: "Microsoft.Network/virtualNetworks/write",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
{
|
||||
ActionId: "Microsoft.Network/virtualNetworks/subnets/join/action",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
{
|
||||
ActionId: "Microsoft.Network/virtualNetworks/subnets/read",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
{
|
||||
ActionId: "Microsoft.Network/virtualNetworks/subnets/write",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
invalidSubnetsAuthorizationDecisionsReadNotAllowed = remotepdp.AuthorizationDecisionResponse{
|
||||
Value: []remotepdp.AuthorizationDecision{
|
||||
invalidSubnetsAuthorizationDecisionsReadNotAllowed = client.AuthorizationDecisionResponse{
|
||||
Value: []client.AuthorizationDecision{
|
||||
{
|
||||
ActionId: "Microsoft.Network/virtualNetworks/join/action",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
{
|
||||
ActionId: "Microsoft.Network/virtualNetworks/read",
|
||||
AccessDecision: remotepdp.NotAllowed,
|
||||
AccessDecision: client.NotAllowed,
|
||||
},
|
||||
{
|
||||
ActionId: "Microsoft.Network/virtualNetworks/write",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
{
|
||||
ActionId: "Microsoft.Network/virtualNetworks/subnets/join/action",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
{
|
||||
ActionId: "Microsoft.Network/virtualNetworks/subnets/read",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
{
|
||||
ActionId: "Microsoft.Network/virtualNetworks/subnets/write",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
invalidSubnetsAuthorizationDecisionsMissingWrite = remotepdp.AuthorizationDecisionResponse{
|
||||
Value: []remotepdp.AuthorizationDecision{
|
||||
invalidSubnetsAuthorizationDecisionsMissingWrite = client.AuthorizationDecisionResponse{
|
||||
Value: []client.AuthorizationDecision{
|
||||
{
|
||||
ActionId: "Microsoft.Network/virtualNetworks/join/action",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
{
|
||||
ActionId: "Microsoft.Network/virtualNetworks/read",
|
||||
AccessDecision: remotepdp.NotAllowed,
|
||||
AccessDecision: client.NotAllowed,
|
||||
},
|
||||
{
|
||||
ActionId: "Microsoft.Network/virtualNetworks/write",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
{
|
||||
ActionId: "Microsoft.Network/virtualNetworks/subnets/join/action",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
{
|
||||
ActionId: "Microsoft.Network/virtualNetworks/subnets/read",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
// deliberately missing subnets write
|
||||
},
|
||||
|
@ -721,13 +726,16 @@ func TestValidateVnetPermissions(t *testing.T) {
|
|||
name string
|
||||
platformIdentities map[string]api.PlatformWorkloadIdentity
|
||||
platformIdentityMap map[string][]string
|
||||
mocks func(*mock_azcore.MockTokenCredential, *mock_remotepdp.MockRemotePDPClient, context.CancelFunc)
|
||||
mocks func(*mock_env.MockInterface, *mock_azcore.MockTokenCredential, *mock_checkaccess.MockRemotePDPClient, context.CancelFunc)
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "pass",
|
||||
mocks: func(tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_remotepdp.MockRemotePDPClient, _ context.CancelFunc) {
|
||||
mocks: func(env *mock_env.MockInterface, tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_checkaccess.MockRemotePDPClient, _ context.CancelFunc) {
|
||||
mockTokenCredential(tokenCred)
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
gomock.Any(), gomock.Any(), gomock.Any()).Return(&client.AuthorizationRequest{}, nil)
|
||||
pdpClient.EXPECT().
|
||||
CheckAccess(gomock.Any(), gomock.Any()).
|
||||
Return(&validSubnetsAuthorizationDecisions, nil)
|
||||
|
@ -739,8 +747,11 @@ func TestValidateVnetPermissions(t *testing.T) {
|
|||
platformIdentityMap: map[string][]string{
|
||||
"Dummy": platformIdentity1SubnetActions,
|
||||
},
|
||||
mocks: func(tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_remotepdp.MockRemotePDPClient, _ context.CancelFunc) {
|
||||
mocks: func(env *mock_env.MockInterface, tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_checkaccess.MockRemotePDPClient, _ context.CancelFunc) {
|
||||
mockTokenCredential(tokenCred)
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
gomock.Any(), gomock.Any(), gomock.Any()).Return(&client.AuthorizationRequest{}, nil)
|
||||
pdpClient.EXPECT().
|
||||
CheckAccess(gomock.Any(), gomock.Any()).
|
||||
Return(&validSubnetsAuthorizationDecisions, nil)
|
||||
|
@ -752,14 +763,17 @@ func TestValidateVnetPermissions(t *testing.T) {
|
|||
platformIdentityMap: map[string][]string{
|
||||
"Dummy": platformIdentity1SubnetActionsNoIntersect,
|
||||
},
|
||||
mocks: func(tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_remotepdp.MockRemotePDPClient, _ context.CancelFunc) {
|
||||
mocks: func(env *mock_env.MockInterface, tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_checkaccess.MockRemotePDPClient, _ context.CancelFunc) {
|
||||
mockTokenCredential(tokenCred)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "fail: missing permissions",
|
||||
mocks: func(tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_remotepdp.MockRemotePDPClient, cancel context.CancelFunc) {
|
||||
mocks: func(env *mock_env.MockInterface, tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_checkaccess.MockRemotePDPClient, cancel context.CancelFunc) {
|
||||
mockTokenCredential(tokenCred)
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
gomock.Any(), gomock.Any(), gomock.Any()).Return(&client.AuthorizationRequest{}, nil)
|
||||
pdpClient.EXPECT().
|
||||
CheckAccess(gomock.Any(), gomock.Any()).
|
||||
Do(func(arg0, arg1 interface{}) {
|
||||
|
@ -775,8 +789,11 @@ func TestValidateVnetPermissions(t *testing.T) {
|
|||
platformIdentityMap: map[string][]string{
|
||||
"Dummy": platformIdentity1SubnetActions,
|
||||
},
|
||||
mocks: func(tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_remotepdp.MockRemotePDPClient, cancel context.CancelFunc) {
|
||||
mocks: func(env *mock_env.MockInterface, tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_checkaccess.MockRemotePDPClient, cancel context.CancelFunc) {
|
||||
mockTokenCredential(tokenCred)
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
gomock.Any(), gomock.Any(), gomock.Any()).Return(&client.AuthorizationRequest{}, nil)
|
||||
pdpClient.EXPECT().
|
||||
CheckAccess(gomock.Any(), gomock.Any()).
|
||||
Do(func(arg0, arg1 interface{}) {
|
||||
|
@ -788,8 +805,11 @@ func TestValidateVnetPermissions(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "fail: CheckAccess Return less entries than requested",
|
||||
mocks: func(tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_remotepdp.MockRemotePDPClient, cancel context.CancelFunc) {
|
||||
mocks: func(env *mock_env.MockInterface, tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_checkaccess.MockRemotePDPClient, cancel context.CancelFunc) {
|
||||
mockTokenCredential(tokenCred)
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
gomock.Any(), gomock.Any(), gomock.Any()).Return(&client.AuthorizationRequest{}, nil)
|
||||
pdpClient.EXPECT().
|
||||
CheckAccess(gomock.Any(), gomock.Any()).
|
||||
Do(func(arg0, arg1 interface{}) {
|
||||
|
@ -801,7 +821,8 @@ func TestValidateVnetPermissions(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "fail: getting an invalid token from AAD",
|
||||
mocks: func(tokenCred *mock_azcore.MockTokenCredential, _ *mock_remotepdp.MockRemotePDPClient, _ context.CancelFunc) {
|
||||
mocks: func(env *mock_env.MockInterface, tokenCred *mock_azcore.MockTokenCredential, _ *mock_checkaccess.MockRemotePDPClient, _ context.CancelFunc) {
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
tokenCred.EXPECT().GetToken(gomock.Any(), gomock.Any()).
|
||||
Return(azcore.AccessToken{}, nil)
|
||||
},
|
||||
|
@ -809,8 +830,11 @@ func TestValidateVnetPermissions(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "fail: getting an error when calling CheckAccessV2",
|
||||
mocks: func(tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_remotepdp.MockRemotePDPClient, cancel context.CancelFunc) {
|
||||
mocks: func(env *mock_env.MockInterface, tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_checkaccess.MockRemotePDPClient, cancel context.CancelFunc) {
|
||||
mockTokenCredential(tokenCred)
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
gomock.Any(), gomock.Any(), gomock.Any()).Return(&client.AuthorizationRequest{}, nil)
|
||||
pdpClient.EXPECT().
|
||||
CheckAccess(gomock.Any(), gomock.Any()).
|
||||
Do(func(arg0, arg1 interface{}) {
|
||||
|
@ -822,8 +846,11 @@ func TestValidateVnetPermissions(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "fail: getting a nil response from CheckAccessV2",
|
||||
mocks: func(tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_remotepdp.MockRemotePDPClient, cancel context.CancelFunc) {
|
||||
mocks: func(env *mock_env.MockInterface, tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_checkaccess.MockRemotePDPClient, cancel context.CancelFunc) {
|
||||
mockTokenCredential(tokenCred)
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
gomock.Any(), gomock.Any(), gomock.Any()).Return(&client.AuthorizationRequest{}, nil)
|
||||
pdpClient.EXPECT().
|
||||
CheckAccess(gomock.Any(), gomock.Any()).
|
||||
Do(func(arg0, arg1 interface{}) {
|
||||
|
@ -842,12 +869,12 @@ func TestValidateVnetPermissions(t *testing.T) {
|
|||
defer cancel()
|
||||
|
||||
tokenCred := mock_azcore.NewMockTokenCredential(controller)
|
||||
|
||||
pdpClient := mock_remotepdp.NewMockRemotePDPClient(controller)
|
||||
tt.mocks(tokenCred, pdpClient, cancel)
|
||||
env := mock_env.NewMockInterface(controller)
|
||||
pdpClient := mock_checkaccess.NewMockRemotePDPClient(controller)
|
||||
tt.mocks(env, tokenCred, pdpClient, cancel)
|
||||
|
||||
dv := &dynamic{
|
||||
azEnv: &azureclient.PublicCloud,
|
||||
env: env,
|
||||
appID: to.StringPtr("fff51942-b1f9-4119-9453-aaa922259eb7"),
|
||||
authorizerType: AuthorizerClusterServicePrincipal,
|
||||
log: logrus.NewEntry(logrus.StandardLogger()),
|
||||
|
@ -873,48 +900,48 @@ func TestValidateVnetPermissions(t *testing.T) {
|
|||
}
|
||||
|
||||
var (
|
||||
invalidRouteTablesAuthorizationDecisionsWriteNotAllowed = remotepdp.AuthorizationDecisionResponse{
|
||||
Value: []remotepdp.AuthorizationDecision{
|
||||
invalidRouteTablesAuthorizationDecisionsWriteNotAllowed = client.AuthorizationDecisionResponse{
|
||||
Value: []client.AuthorizationDecision{
|
||||
{
|
||||
ActionId: "Microsoft.Network/routeTables/join/action",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
{
|
||||
ActionId: "Microsoft.Network/routeTables/read",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
{
|
||||
ActionId: "Microsoft.Network/routeTables/write",
|
||||
AccessDecision: remotepdp.NotAllowed,
|
||||
AccessDecision: client.NotAllowed,
|
||||
},
|
||||
},
|
||||
}
|
||||
invalidRouteTablesAuthorizationDecisionsMissingWrite = remotepdp.AuthorizationDecisionResponse{
|
||||
Value: []remotepdp.AuthorizationDecision{
|
||||
invalidRouteTablesAuthorizationDecisionsMissingWrite = client.AuthorizationDecisionResponse{
|
||||
Value: []client.AuthorizationDecision{
|
||||
{
|
||||
ActionId: "Microsoft.Network/routeTables/join/action",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
{
|
||||
ActionId: "Microsoft.Network/routeTables/read",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
// deliberately missing routetables write
|
||||
},
|
||||
}
|
||||
validRouteTablesAuthorizationDecisions = remotepdp.AuthorizationDecisionResponse{
|
||||
Value: []remotepdp.AuthorizationDecision{
|
||||
validRouteTablesAuthorizationDecisions = client.AuthorizationDecisionResponse{
|
||||
Value: []client.AuthorizationDecision{
|
||||
{
|
||||
ActionId: "Microsoft.Network/routeTables/join/action",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
{
|
||||
ActionId: "Microsoft.Network/routeTables/read",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
{
|
||||
ActionId: "Microsoft.Network/routeTables/write",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -928,7 +955,7 @@ func TestValidateRouteTablesPermissions(t *testing.T) {
|
|||
subnet Subnet
|
||||
platformIdentities map[string]api.PlatformWorkloadIdentity
|
||||
platformIdentityMap map[string][]string
|
||||
pdpClientMocks func(*mock_azcore.MockTokenCredential, *mock_remotepdp.MockRemotePDPClient, context.CancelFunc)
|
||||
pdpClientMocks func(*mock_env.MockInterface, *mock_azcore.MockTokenCredential, *mock_checkaccess.MockRemotePDPClient, context.CancelFunc)
|
||||
vnetMocks func(*mock_network.MockVirtualNetworksClient, mgmtnetwork.VirtualNetwork)
|
||||
wantErr string
|
||||
}{
|
||||
|
@ -983,8 +1010,11 @@ func TestValidateRouteTablesPermissions(t *testing.T) {
|
|||
Get(gomock.Any(), resourceGroupName, vnetName, "").
|
||||
Return(vnet, nil)
|
||||
},
|
||||
pdpClientMocks: func(tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_remotepdp.MockRemotePDPClient, cancel context.CancelFunc) {
|
||||
pdpClientMocks: func(env *mock_env.MockInterface, tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_checkaccess.MockRemotePDPClient, cancel context.CancelFunc) {
|
||||
mockTokenCredential(tokenCred)
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
gomock.Any(), gomock.Any(), gomock.Any()).Return(&client.AuthorizationRequest{}, nil)
|
||||
pdpClient.EXPECT().
|
||||
CheckAccess(gomock.Any(), gomock.Any()).
|
||||
Do(func(arg0, arg1 interface{}) {
|
||||
|
@ -1006,8 +1036,11 @@ func TestValidateRouteTablesPermissions(t *testing.T) {
|
|||
Get(gomock.Any(), resourceGroupName, vnetName, "").
|
||||
Return(vnet, nil)
|
||||
},
|
||||
pdpClientMocks: func(tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_remotepdp.MockRemotePDPClient, cancel context.CancelFunc) {
|
||||
pdpClientMocks: func(env *mock_env.MockInterface, tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_checkaccess.MockRemotePDPClient, cancel context.CancelFunc) {
|
||||
mockTokenCredential(tokenCred)
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
gomock.Any(), gomock.Any(), gomock.Any()).Return(&client.AuthorizationRequest{}, nil)
|
||||
pdpClient.EXPECT().
|
||||
CheckAccess(gomock.Any(), gomock.Any()).
|
||||
Do(func(arg0, arg1 interface{}) {
|
||||
|
@ -1025,8 +1058,11 @@ func TestValidateRouteTablesPermissions(t *testing.T) {
|
|||
Get(gomock.Any(), resourceGroupName, vnetName, "").
|
||||
Return(vnet, nil)
|
||||
},
|
||||
pdpClientMocks: func(tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_remotepdp.MockRemotePDPClient, cancel context.CancelFunc) {
|
||||
pdpClientMocks: func(env *mock_env.MockInterface, tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_checkaccess.MockRemotePDPClient, cancel context.CancelFunc) {
|
||||
mockTokenCredential(tokenCred)
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
gomock.Any(), gomock.Any(), gomock.Any()).Return(&client.AuthorizationRequest{}, nil)
|
||||
pdpClient.EXPECT().
|
||||
CheckAccess(gomock.Any(), gomock.Any()).
|
||||
Do(func(arg0, arg1 interface{}) {
|
||||
|
@ -1044,8 +1080,11 @@ func TestValidateRouteTablesPermissions(t *testing.T) {
|
|||
Get(gomock.Any(), resourceGroupName, vnetName, "").
|
||||
Return(vnet, nil)
|
||||
},
|
||||
pdpClientMocks: func(tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_remotepdp.MockRemotePDPClient, cancel context.CancelFunc) {
|
||||
pdpClientMocks: func(env *mock_env.MockInterface, tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_checkaccess.MockRemotePDPClient, cancel context.CancelFunc) {
|
||||
mockTokenCredential(tokenCred)
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
gomock.Any(), gomock.Any(), gomock.Any()).Return(&client.AuthorizationRequest{}, nil)
|
||||
pdpClient.EXPECT().
|
||||
CheckAccess(gomock.Any(), gomock.Any()).
|
||||
Return(&validRouteTablesAuthorizationDecisions, nil)
|
||||
|
@ -1063,8 +1102,11 @@ func TestValidateRouteTablesPermissions(t *testing.T) {
|
|||
Get(gomock.Any(), resourceGroupName, vnetName, "").
|
||||
Return(vnet, nil)
|
||||
},
|
||||
pdpClientMocks: func(tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_remotepdp.MockRemotePDPClient, cancel context.CancelFunc) {
|
||||
pdpClientMocks: func(env *mock_env.MockInterface, tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_checkaccess.MockRemotePDPClient, cancel context.CancelFunc) {
|
||||
mockTokenCredential(tokenCred)
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
gomock.Any(), gomock.Any(), gomock.Any()).Return(&client.AuthorizationRequest{}, nil)
|
||||
pdpClient.EXPECT().
|
||||
CheckAccess(gomock.Any(), gomock.Any()).
|
||||
Return(&validRouteTablesAuthorizationDecisions, nil)
|
||||
|
@ -1082,7 +1124,7 @@ func TestValidateRouteTablesPermissions(t *testing.T) {
|
|||
Get(gomock.Any(), resourceGroupName, vnetName, "").
|
||||
Return(vnet, nil)
|
||||
},
|
||||
pdpClientMocks: func(tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_remotepdp.MockRemotePDPClient, cancel context.CancelFunc) {
|
||||
pdpClientMocks: func(env *mock_env.MockInterface, tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_checkaccess.MockRemotePDPClient, cancel context.CancelFunc) {
|
||||
mockTokenCredential(tokenCred)
|
||||
},
|
||||
},
|
||||
|
@ -1095,9 +1137,8 @@ func TestValidateRouteTablesPermissions(t *testing.T) {
|
|||
defer cancel()
|
||||
|
||||
tokenCred := mock_azcore.NewMockTokenCredential(controller)
|
||||
|
||||
pdpClient := mock_remotepdp.NewMockRemotePDPClient(controller)
|
||||
|
||||
env := mock_env.NewMockInterface(controller)
|
||||
pdpClient := mock_checkaccess.NewMockRemotePDPClient(controller)
|
||||
vnetClient := mock_network.NewMockVirtualNetworksClient(controller)
|
||||
|
||||
vnet := &mgmtnetwork.VirtualNetwork{
|
||||
|
@ -1126,7 +1167,7 @@ func TestValidateRouteTablesPermissions(t *testing.T) {
|
|||
|
||||
dv := &dynamic{
|
||||
appID: to.StringPtr("fff51942-b1f9-4119-9453-aaa922259eb7"),
|
||||
azEnv: &azureclient.PublicCloud,
|
||||
env: env,
|
||||
authorizerType: AuthorizerClusterServicePrincipal,
|
||||
log: logrus.NewEntry(logrus.StandardLogger()),
|
||||
checkAccessSubjectInfoCred: tokenCred,
|
||||
|
@ -1135,7 +1176,7 @@ func TestValidateRouteTablesPermissions(t *testing.T) {
|
|||
}
|
||||
|
||||
if tt.pdpClientMocks != nil {
|
||||
tt.pdpClientMocks(tokenCred, pdpClient, cancel)
|
||||
tt.pdpClientMocks(env, tokenCred, pdpClient, cancel)
|
||||
}
|
||||
|
||||
if tt.vnetMocks != nil {
|
||||
|
@ -1155,48 +1196,48 @@ func TestValidateRouteTablesPermissions(t *testing.T) {
|
|||
}
|
||||
|
||||
var (
|
||||
invalidNatGWAuthorizationDecisionsReadNotAllowed = remotepdp.AuthorizationDecisionResponse{
|
||||
Value: []remotepdp.AuthorizationDecision{
|
||||
invalidNatGWAuthorizationDecisionsReadNotAllowed = client.AuthorizationDecisionResponse{
|
||||
Value: []client.AuthorizationDecision{
|
||||
{
|
||||
ActionId: "Microsoft.Network/natGateways/join/action",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
{
|
||||
ActionId: "Microsoft.Network/natGateways/read",
|
||||
AccessDecision: remotepdp.NotAllowed,
|
||||
AccessDecision: client.NotAllowed,
|
||||
},
|
||||
{
|
||||
ActionId: "Microsoft.Network/natGateways/write",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
},
|
||||
}
|
||||
invalidNatGWAuthorizationDecisionsMissingWrite = remotepdp.AuthorizationDecisionResponse{
|
||||
Value: []remotepdp.AuthorizationDecision{
|
||||
invalidNatGWAuthorizationDecisionsMissingWrite = client.AuthorizationDecisionResponse{
|
||||
Value: []client.AuthorizationDecision{
|
||||
{
|
||||
ActionId: "Microsoft.Network/natGateways/join/action",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
{
|
||||
ActionId: "Microsoft.Network/natGateways/read",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
// deliberately missing natGateway write
|
||||
},
|
||||
}
|
||||
validNatGWAuthorizationDecision = remotepdp.AuthorizationDecisionResponse{
|
||||
Value: []remotepdp.AuthorizationDecision{
|
||||
validNatGWAuthorizationDecision = client.AuthorizationDecisionResponse{
|
||||
Value: []client.AuthorizationDecision{
|
||||
{
|
||||
ActionId: "Microsoft.Network/natGateways/join/action",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
{
|
||||
ActionId: "Microsoft.Network/natGateways/read",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
{
|
||||
ActionId: "Microsoft.Network/natGateways/write",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -1210,7 +1251,7 @@ func TestValidateNatGatewaysPermissions(t *testing.T) {
|
|||
subnet Subnet
|
||||
platformIdentities map[string]api.PlatformWorkloadIdentity
|
||||
platformIdentityMap map[string][]string
|
||||
pdpClientMocks func(*mock_azcore.MockTokenCredential, *mock_remotepdp.MockRemotePDPClient, context.CancelFunc)
|
||||
pdpClientMocks func(*mock_env.MockInterface, *mock_azcore.MockTokenCredential, *mock_checkaccess.MockRemotePDPClient, context.CancelFunc)
|
||||
vnetMocks func(*mock_network.MockVirtualNetworksClient, mgmtnetwork.VirtualNetwork)
|
||||
wantErr string
|
||||
}{
|
||||
|
@ -1254,8 +1295,11 @@ func TestValidateNatGatewaysPermissions(t *testing.T) {
|
|||
Get(gomock.Any(), resourceGroupName, vnetName, "").
|
||||
Return(vnet, nil)
|
||||
},
|
||||
pdpClientMocks: func(tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_remotepdp.MockRemotePDPClient, cancel context.CancelFunc) {
|
||||
pdpClientMocks: func(env *mock_env.MockInterface, tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_checkaccess.MockRemotePDPClient, cancel context.CancelFunc) {
|
||||
mockTokenCredential(tokenCred)
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
gomock.Any(), gomock.Any(), gomock.Any()).Return(&client.AuthorizationRequest{}, nil)
|
||||
pdpClient.
|
||||
EXPECT().
|
||||
CheckAccess(gomock.Any(), gomock.Any()).
|
||||
|
@ -1278,8 +1322,11 @@ func TestValidateNatGatewaysPermissions(t *testing.T) {
|
|||
Get(gomock.Any(), resourceGroupName, vnetName, "").
|
||||
Return(vnet, nil)
|
||||
},
|
||||
pdpClientMocks: func(tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_remotepdp.MockRemotePDPClient, cancel context.CancelFunc) {
|
||||
pdpClientMocks: func(env *mock_env.MockInterface, tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_checkaccess.MockRemotePDPClient, cancel context.CancelFunc) {
|
||||
mockTokenCredential(tokenCred)
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
gomock.Any(), gomock.Any(), gomock.Any()).Return(&client.AuthorizationRequest{}, nil)
|
||||
pdpClient.
|
||||
EXPECT().
|
||||
CheckAccess(gomock.Any(), gomock.Any()).
|
||||
|
@ -1298,8 +1345,11 @@ func TestValidateNatGatewaysPermissions(t *testing.T) {
|
|||
Get(gomock.Any(), resourceGroupName, vnetName, "").
|
||||
Return(vnet, nil)
|
||||
},
|
||||
pdpClientMocks: func(tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_remotepdp.MockRemotePDPClient, cancel context.CancelFunc) {
|
||||
pdpClientMocks: func(env *mock_env.MockInterface, tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_checkaccess.MockRemotePDPClient, cancel context.CancelFunc) {
|
||||
mockTokenCredential(tokenCred)
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
gomock.Any(), gomock.Any(), gomock.Any()).Return(&client.AuthorizationRequest{}, nil)
|
||||
pdpClient.
|
||||
EXPECT().
|
||||
CheckAccess(gomock.Any(), gomock.Any()).
|
||||
|
@ -1318,8 +1368,11 @@ func TestValidateNatGatewaysPermissions(t *testing.T) {
|
|||
Get(gomock.Any(), resourceGroupName, vnetName, "").
|
||||
Return(vnet, nil)
|
||||
},
|
||||
pdpClientMocks: func(tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_remotepdp.MockRemotePDPClient, cancel context.CancelFunc) {
|
||||
pdpClientMocks: func(env *mock_env.MockInterface, tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_checkaccess.MockRemotePDPClient, cancel context.CancelFunc) {
|
||||
mockTokenCredential(tokenCred)
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
gomock.Any(), gomock.Any(), gomock.Any()).Return(&client.AuthorizationRequest{}, nil)
|
||||
pdpClient.EXPECT().
|
||||
CheckAccess(gomock.Any(), gomock.Any()).
|
||||
Return(&validNatGWAuthorizationDecision, nil)
|
||||
|
@ -1337,8 +1390,11 @@ func TestValidateNatGatewaysPermissions(t *testing.T) {
|
|||
Get(gomock.Any(), resourceGroupName, vnetName, "").
|
||||
Return(vnet, nil)
|
||||
},
|
||||
pdpClientMocks: func(tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_remotepdp.MockRemotePDPClient, cancel context.CancelFunc) {
|
||||
pdpClientMocks: func(env *mock_env.MockInterface, tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_checkaccess.MockRemotePDPClient, cancel context.CancelFunc) {
|
||||
mockTokenCredential(tokenCred)
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
gomock.Any(), gomock.Any(), gomock.Any()).Return(&client.AuthorizationRequest{}, nil)
|
||||
pdpClient.EXPECT().
|
||||
CheckAccess(gomock.Any(), gomock.Any()).
|
||||
Return(&validNatGWAuthorizationDecision, nil)
|
||||
|
@ -1356,7 +1412,7 @@ func TestValidateNatGatewaysPermissions(t *testing.T) {
|
|||
Get(gomock.Any(), resourceGroupName, vnetName, "").
|
||||
Return(vnet, nil)
|
||||
},
|
||||
pdpClientMocks: func(tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_remotepdp.MockRemotePDPClient, cancel context.CancelFunc) {
|
||||
pdpClientMocks: func(env *mock_env.MockInterface, tokenCred *mock_azcore.MockTokenCredential, pdpClient *mock_checkaccess.MockRemotePDPClient, cancel context.CancelFunc) {
|
||||
mockTokenCredential(tokenCred)
|
||||
},
|
||||
},
|
||||
|
@ -1380,10 +1436,9 @@ func TestValidateNatGatewaysPermissions(t *testing.T) {
|
|||
defer cancel()
|
||||
|
||||
vnetClient := mock_network.NewMockVirtualNetworksClient(controller)
|
||||
|
||||
env := mock_env.NewMockInterface(controller)
|
||||
tokenCred := mock_azcore.NewMockTokenCredential(controller)
|
||||
|
||||
pdpClient := mock_remotepdp.NewMockRemotePDPClient(controller)
|
||||
pdpClient := mock_checkaccess.NewMockRemotePDPClient(controller)
|
||||
|
||||
vnet := &mgmtnetwork.VirtualNetwork{
|
||||
ID: &vnetID,
|
||||
|
@ -1411,7 +1466,7 @@ func TestValidateNatGatewaysPermissions(t *testing.T) {
|
|||
|
||||
dv := &dynamic{
|
||||
appID: to.StringPtr("fff51942-b1f9-4119-9453-aaa922259eb7"),
|
||||
azEnv: &azureclient.PublicCloud,
|
||||
env: env,
|
||||
authorizerType: AuthorizerClusterServicePrincipal,
|
||||
log: logrus.NewEntry(logrus.StandardLogger()),
|
||||
checkAccessSubjectInfoCred: tokenCred,
|
||||
|
@ -1420,7 +1475,7 @@ func TestValidateNatGatewaysPermissions(t *testing.T) {
|
|||
}
|
||||
|
||||
if tt.pdpClientMocks != nil {
|
||||
tt.pdpClientMocks(tokenCred, pdpClient, cancel)
|
||||
tt.pdpClientMocks(env, tokenCred, pdpClient, cancel)
|
||||
}
|
||||
|
||||
if tt.vnetMocks != nil {
|
||||
|
@ -1492,19 +1547,19 @@ func TestCheckPreconfiguredNSG(t *testing.T) {
|
|||
}
|
||||
|
||||
var (
|
||||
canJoinNSG = remotepdp.AuthorizationDecisionResponse{
|
||||
Value: []remotepdp.AuthorizationDecision{
|
||||
canJoinNSG = client.AuthorizationDecisionResponse{
|
||||
Value: []client.AuthorizationDecision{
|
||||
{
|
||||
ActionId: "Microsoft.Network/networkSecurityGroups/join/action",
|
||||
AccessDecision: remotepdp.Allowed},
|
||||
AccessDecision: client.Allowed},
|
||||
},
|
||||
}
|
||||
|
||||
cannotJoinNSG = remotepdp.AuthorizationDecisionResponse{
|
||||
Value: []remotepdp.AuthorizationDecision{
|
||||
cannotJoinNSG = client.AuthorizationDecisionResponse{
|
||||
Value: []client.AuthorizationDecision{
|
||||
{
|
||||
ActionId: "Microsoft.Network/networkSecurityGroups/join/action",
|
||||
AccessDecision: remotepdp.NotAllowed},
|
||||
AccessDecision: client.NotAllowed},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
@ -1516,7 +1571,7 @@ func TestValidatePreconfiguredNSGPermissions(t *testing.T) {
|
|||
modifyOC func(*api.OpenShiftCluster)
|
||||
platformIdentities map[string]api.PlatformWorkloadIdentity
|
||||
platformIdentityMap map[string][]string
|
||||
checkAccessMocks func(context.CancelFunc, *mock_remotepdp.MockRemotePDPClient, *mock_azcore.MockTokenCredential)
|
||||
checkAccessMocks func(context.CancelFunc, *mock_checkaccess.MockRemotePDPClient, *mock_azcore.MockTokenCredential, *mock_env.MockInterface)
|
||||
vnetMocks func(*mock_network.MockVirtualNetworksClient, mgmtnetwork.VirtualNetwork)
|
||||
wantErr string
|
||||
}{
|
||||
|
@ -1537,10 +1592,19 @@ func TestValidatePreconfiguredNSGPermissions(t *testing.T) {
|
|||
AnyTimes().
|
||||
Return(vnet, nil)
|
||||
},
|
||||
checkAccessMocks: func(cancel context.CancelFunc, pdpClient *mock_remotepdp.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential) {
|
||||
checkAccessMocks: func(cancel context.CancelFunc, pdpClient *mock_checkaccess.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, env *mock_env.MockInterface) {
|
||||
mockTokenCredential(tokenCred)
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
gomock.Any(), gomock.Any(), gomock.Any()).Return(&client.AuthorizationRequest{
|
||||
Resource: client.ResourceInfo{Id: masterNSGv1},
|
||||
}, nil).Times(1)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
gomock.Any(), gomock.Any(), gomock.Any()).Return(&client.AuthorizationRequest{
|
||||
Resource: client.ResourceInfo{Id: workerNSGv1},
|
||||
}, nil)
|
||||
pdpClient.EXPECT().CheckAccess(gomock.Any(), gomock.Any()).
|
||||
DoAndReturn(func(_ context.Context, authReq remotepdp.AuthorizationRequest) (*remotepdp.AuthorizationDecisionResponse, error) {
|
||||
DoAndReturn(func(_ context.Context, authReq client.AuthorizationRequest) (*client.AuthorizationDecisionResponse, error) {
|
||||
cancel() // wait.PollImmediateUntil will always be invoked at least once
|
||||
switch authReq.Resource.Id {
|
||||
case masterNSGv1:
|
||||
|
@ -1565,10 +1629,19 @@ func TestValidatePreconfiguredNSGPermissions(t *testing.T) {
|
|||
AnyTimes().
|
||||
Return(vnet, nil)
|
||||
},
|
||||
checkAccessMocks: func(cancel context.CancelFunc, pdpClient *mock_remotepdp.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential) {
|
||||
checkAccessMocks: func(cancel context.CancelFunc, pdpClient *mock_checkaccess.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, env *mock_env.MockInterface) {
|
||||
mockTokenCredential(tokenCred)
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
gomock.Any(), gomock.Any(), gomock.Any()).Return(&client.AuthorizationRequest{
|
||||
Resource: client.ResourceInfo{Id: masterNSGv1},
|
||||
}, nil).Times(1)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
gomock.Any(), gomock.Any(), gomock.Any()).Return(&client.AuthorizationRequest{
|
||||
Resource: client.ResourceInfo{Id: workerNSGv1},
|
||||
}, nil)
|
||||
pdpClient.EXPECT().CheckAccess(gomock.Any(), gomock.Any()).
|
||||
DoAndReturn(func(_ context.Context, authReq remotepdp.AuthorizationRequest) (*remotepdp.AuthorizationDecisionResponse, error) {
|
||||
DoAndReturn(func(_ context.Context, authReq client.AuthorizationRequest) (*client.AuthorizationDecisionResponse, error) {
|
||||
cancel() // wait.PollImmediateUntil will always be invoked at least once
|
||||
switch authReq.Resource.Id {
|
||||
case masterNSGv1:
|
||||
|
@ -1597,8 +1670,13 @@ func TestValidatePreconfiguredNSGPermissions(t *testing.T) {
|
|||
AnyTimes().
|
||||
Return(vnet, nil)
|
||||
},
|
||||
checkAccessMocks: func(cancel context.CancelFunc, pdpClient *mock_remotepdp.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential) {
|
||||
checkAccessMocks: func(cancel context.CancelFunc, pdpClient *mock_checkaccess.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, env *mock_env.MockInterface) {
|
||||
mockTokenCredential(tokenCred)
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
gomock.Any(), gomock.Any(), gomock.Any()).Return(&client.AuthorizationRequest{
|
||||
Resource: client.ResourceInfo{Id: workerNSGv1},
|
||||
}, nil).AnyTimes()
|
||||
pdpClient.EXPECT().CheckAccess(gomock.Any(), gomock.Any()).
|
||||
Do(func(_, _ interface{}) {
|
||||
cancel()
|
||||
|
@ -1618,8 +1696,13 @@ func TestValidatePreconfiguredNSGPermissions(t *testing.T) {
|
|||
AnyTimes().
|
||||
Return(vnet, nil)
|
||||
},
|
||||
checkAccessMocks: func(cancel context.CancelFunc, pdpClient *mock_remotepdp.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential) {
|
||||
checkAccessMocks: func(cancel context.CancelFunc, pdpClient *mock_checkaccess.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, env *mock_env.MockInterface) {
|
||||
mockTokenCredential(tokenCred)
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
gomock.Any(), gomock.Any(), gomock.Any()).Return(&client.AuthorizationRequest{
|
||||
Resource: client.ResourceInfo{Id: workerNSGv1},
|
||||
}, nil).AnyTimes()
|
||||
pdpClient.EXPECT().CheckAccess(gomock.Any(), gomock.Any()).
|
||||
Do(func(_, _ interface{}) {
|
||||
cancel()
|
||||
|
@ -1643,7 +1726,7 @@ func TestValidatePreconfiguredNSGPermissions(t *testing.T) {
|
|||
AnyTimes().
|
||||
Return(vnet, nil)
|
||||
},
|
||||
checkAccessMocks: func(cancel context.CancelFunc, pdpClient *mock_remotepdp.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential) {
|
||||
checkAccessMocks: func(cancel context.CancelFunc, pdpClient *mock_checkaccess.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, env *mock_env.MockInterface) {
|
||||
mockTokenCredential(tokenCred)
|
||||
pdpClient.EXPECT().CheckAccess(gomock.Any(), gomock.Any()).
|
||||
Do(func(_, _ interface{}) {
|
||||
|
@ -1710,15 +1793,16 @@ func TestValidatePreconfiguredNSGPermissions(t *testing.T) {
|
|||
tt.vnetMocks(vnetClient, vnet)
|
||||
}
|
||||
|
||||
env := mock_env.NewMockInterface(controller)
|
||||
tokenCred := mock_azcore.NewMockTokenCredential(controller)
|
||||
pdpClient := mock_remotepdp.NewMockRemotePDPClient(controller)
|
||||
pdpClient := mock_checkaccess.NewMockRemotePDPClient(controller)
|
||||
|
||||
if tt.checkAccessMocks != nil {
|
||||
tt.checkAccessMocks(cancel, pdpClient, tokenCred)
|
||||
tt.checkAccessMocks(cancel, pdpClient, tokenCred, env)
|
||||
}
|
||||
|
||||
dv := &dynamic{
|
||||
azEnv: &azureclient.PublicCloud,
|
||||
env: env,
|
||||
appID: to.StringPtr("fff51942-b1f9-4119-9453-aaa922259eb7"),
|
||||
authorizerType: AuthorizerClusterServicePrincipal,
|
||||
virtualNetworks: vnetClient,
|
||||
|
|
|
@ -9,4 +9,6 @@ package dynamic
|
|||
|
||||
//go:generate rm -rf ../../../pkg/util/mocks/$GOPACKAGE
|
||||
//go:generate mockgen -destination=../../../pkg/util/mocks/$GOPACKAGE/$GOPACKAGE.go -source=dynamic.go
|
||||
//go:generate mockgen -destination=../../../pkg/util/mocks/checkaccess/checkaccess.go github.com/Azure/checkaccess-v2-go-sdk/client RemotePDPClient
|
||||
//go:generate goimports -local=github.com/Azure/ARO-RP -e -w ../../../pkg/util/mocks/$GOPACKAGE/$GOPACKAGE.go
|
||||
//go:generate goimports -local=github.com/Azure/ARO-RP -e -w ../../../pkg/util/mocks/checkaccess/checkaccess.go
|
||||
|
|
|
@ -11,78 +11,78 @@ import (
|
|||
"testing"
|
||||
|
||||
sdkauthorization "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v3"
|
||||
"github.com/Azure/checkaccess-v2-go-sdk/client"
|
||||
"github.com/sirupsen/logrus"
|
||||
"go.uber.org/mock/gomock"
|
||||
"k8s.io/utils/ptr"
|
||||
|
||||
"github.com/Azure/ARO-RP/pkg/api"
|
||||
"github.com/Azure/ARO-RP/pkg/util/azureclient/authz/remotepdp"
|
||||
mock_remotepdp "github.com/Azure/ARO-RP/pkg/util/mocks/azureclient/authz/remotepdp"
|
||||
"github.com/Azure/ARO-RP/pkg/util/azureclient"
|
||||
mock_armauthorization "github.com/Azure/ARO-RP/pkg/util/mocks/azureclient/azuresdk/armauthorization"
|
||||
mock_azcore "github.com/Azure/ARO-RP/pkg/util/mocks/azureclient/azuresdk/azcore"
|
||||
mock_checkaccess "github.com/Azure/ARO-RP/pkg/util/mocks/checkaccess"
|
||||
mock_env "github.com/Azure/ARO-RP/pkg/util/mocks/env"
|
||||
"github.com/Azure/ARO-RP/pkg/util/pointerutils"
|
||||
"github.com/Azure/ARO-RP/pkg/util/rbac"
|
||||
"github.com/Azure/ARO-RP/pkg/util/uuid"
|
||||
utilerror "github.com/Azure/ARO-RP/test/util/error"
|
||||
)
|
||||
|
||||
var (
|
||||
msiAllowedActions = remotepdp.AuthorizationDecisionResponse{
|
||||
Value: []remotepdp.AuthorizationDecision{
|
||||
msiAllowedActions = client.AuthorizationDecisionResponse{
|
||||
Value: []client.AuthorizationDecision{
|
||||
{
|
||||
ActionId: "FakeMSIAction1",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
{
|
||||
ActionId: "FakeMSIAction2",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
{
|
||||
ActionId: "FakeMSIDataAction1",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
{
|
||||
ActionId: "FakeMSIDataAction2",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
msiNotAllowedActions = remotepdp.AuthorizationDecisionResponse{
|
||||
Value: []remotepdp.AuthorizationDecision{
|
||||
msiNotAllowedActions = client.AuthorizationDecisionResponse{
|
||||
Value: []client.AuthorizationDecision{
|
||||
{
|
||||
ActionId: "FakeMSIAction1",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
{
|
||||
ActionId: "FakeMSIAction2",
|
||||
AccessDecision: remotepdp.Denied,
|
||||
AccessDecision: client.Denied,
|
||||
},
|
||||
{
|
||||
ActionId: "FakeMSIDataAction1",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
{
|
||||
ActionId: "FakeMSIDataAction2",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
msiActionMissing = remotepdp.AuthorizationDecisionResponse{
|
||||
Value: []remotepdp.AuthorizationDecision{
|
||||
msiActionMissing = client.AuthorizationDecisionResponse{
|
||||
Value: []client.AuthorizationDecision{
|
||||
{
|
||||
ActionId: "FakeMSIAction1",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
{
|
||||
ActionId: "FakeMSIAction2",
|
||||
AccessDecision: remotepdp.Denied,
|
||||
AccessDecision: client.Denied,
|
||||
},
|
||||
{
|
||||
ActionId: "FakeMSIDataAction2",
|
||||
AccessDecision: remotepdp.Allowed,
|
||||
AccessDecision: client.Allowed,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -107,6 +107,17 @@ var (
|
|||
}
|
||||
msiRequiredPermissionsList = []string{"FakeMSIAction1", "FakeMSIAction2", "FakeMSIDataAction1", "FakeMSIDataAction2"}
|
||||
|
||||
msiAuthZRequest = client.AuthorizationRequest{
|
||||
Subject: client.SubjectInfo{
|
||||
Attributes: client.SubjectAttributes{
|
||||
ObjectId: dummyObjectId,
|
||||
ClaimName: client.GroupExpansion,
|
||||
},
|
||||
},
|
||||
Actions: []client.ActionInfo{{Id: "FakeMSIAction1"}, {Id: "FakeMSIAction2"}, {Id: "FakeMSIDataAction1"}, {Id: "FakeMSIDataAction2"}},
|
||||
Resource: client.ResourceInfo{Id: platformIdentity1},
|
||||
}
|
||||
|
||||
platformIdentityRequiredPermissions = sdkauthorization.RoleDefinitionsClientGetByIDResponse{
|
||||
RoleDefinition: sdkauthorization.RoleDefinition{
|
||||
Properties: &sdkauthorization.RoleDefinitionProperties{
|
||||
|
@ -133,8 +144,6 @@ func TestValidatePlatformWorkloadIdentityProfile(t *testing.T) {
|
|||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
msiResourceID := resourceGroupID + "/providers/Microsoft.ManagedIdentity/userAssignedIdentities/miwi-msi-resource"
|
||||
dummyClientId := uuid.DefaultGenerator.Generate()
|
||||
dummyObjectId := uuid.DefaultGenerator.Generate()
|
||||
platformWorkloadIdentities := map[string]api.PlatformWorkloadIdentity{
|
||||
"Dummy2": {
|
||||
ResourceID: platformIdentity1,
|
||||
|
@ -173,7 +182,7 @@ func TestValidatePlatformWorkloadIdentityProfile(t *testing.T) {
|
|||
mocks func(*mock_armauthorization.MockRoleDefinitionsClient)
|
||||
wantPlatformIdentities map[string]api.PlatformWorkloadIdentity
|
||||
wantPlatformIdentitiesActionsMap map[string][]string
|
||||
checkAccessMocks func(context.CancelFunc, *mock_remotepdp.MockRemotePDPClient, *mock_azcore.MockTokenCredential)
|
||||
checkAccessMocks func(context.CancelFunc, *mock_checkaccess.MockRemotePDPClient, *mock_azcore.MockTokenCredential, *mock_env.MockInterface)
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
|
@ -200,10 +209,15 @@ func TestValidatePlatformWorkloadIdentityProfile(t *testing.T) {
|
|||
roleDefinitions.EXPECT().GetByID(ctx, rbac.RoleAzureRedHatOpenShiftFederatedCredentialRole, &sdkauthorization.RoleDefinitionsClientGetByIDOptions{}).Return(msiRequiredPermissions, nil)
|
||||
roleDefinitions.EXPECT().GetByID(ctx, gomock.Any(), &sdkauthorization.RoleDefinitionsClientGetByIDOptions{}).AnyTimes().Return(platformIdentityRequiredPermissions, nil)
|
||||
},
|
||||
checkAccessMocks: func(cancel context.CancelFunc, pdpClient *mock_remotepdp.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential) {
|
||||
checkAccessMocks: func(cancel context.CancelFunc, pdpClient *mock_checkaccess.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, env *mock_env.MockInterface) {
|
||||
mockTokenCredential(tokenCred)
|
||||
msiAuthReq := createAuthorizationRequest(dummyObjectId, platformIdentity1, msiRequiredPermissionsList...)
|
||||
pdpClient.EXPECT().CheckAccess(gomock.Any(), msiAuthReq).Return(&msiAllowedActions, nil).AnyTimes()
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
platformIdentity1,
|
||||
msiRequiredPermissionsList,
|
||||
validTestToken,
|
||||
).AnyTimes().Return(&msiAuthZRequest, nil)
|
||||
pdpClient.EXPECT().CheckAccess(gomock.Any(), msiAuthZRequest).Return(&msiAllowedActions, nil).AnyTimes()
|
||||
},
|
||||
wantPlatformIdentities: desiredPlatformWorkloadIdentities,
|
||||
wantPlatformIdentitiesActionsMap: map[string][]string{
|
||||
|
@ -231,10 +245,15 @@ func TestValidatePlatformWorkloadIdentityProfile(t *testing.T) {
|
|||
roleDefinitions.EXPECT().GetByID(ctx, rbac.RoleAzureRedHatOpenShiftFederatedCredentialRole, &sdkauthorization.RoleDefinitionsClientGetByIDOptions{}).Return(msiRequiredPermissions, nil)
|
||||
roleDefinitions.EXPECT().GetByID(ctx, gomock.Any(), &sdkauthorization.RoleDefinitionsClientGetByIDOptions{}).AnyTimes().Return(platformIdentityRequiredPermissions, nil)
|
||||
},
|
||||
checkAccessMocks: func(cancel context.CancelFunc, pdpClient *mock_remotepdp.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential) {
|
||||
checkAccessMocks: func(cancel context.CancelFunc, pdpClient *mock_checkaccess.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, env *mock_env.MockInterface) {
|
||||
mockTokenCredential(tokenCred)
|
||||
msiAuthReq := createAuthorizationRequest(dummyObjectId, platformIdentity1, msiRequiredPermissionsList...)
|
||||
pdpClient.EXPECT().CheckAccess(gomock.Any(), msiAuthReq).Return(&msiAllowedActions, nil).AnyTimes()
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
platformIdentity1,
|
||||
msiRequiredPermissionsList,
|
||||
validTestToken,
|
||||
).AnyTimes().Return(&msiAuthZRequest, nil)
|
||||
pdpClient.EXPECT().CheckAccess(gomock.Any(), msiAuthZRequest).Return(&msiAllowedActions, nil).AnyTimes()
|
||||
},
|
||||
wantPlatformIdentities: map[string]api.PlatformWorkloadIdentity{
|
||||
"Dummy1": {
|
||||
|
@ -265,10 +284,15 @@ func TestValidatePlatformWorkloadIdentityProfile(t *testing.T) {
|
|||
roleDefinitions.EXPECT().GetByID(ctx, rbac.RoleAzureRedHatOpenShiftFederatedCredentialRole, &sdkauthorization.RoleDefinitionsClientGetByIDOptions{}).Return(msiRequiredPermissions, nil)
|
||||
roleDefinitions.EXPECT().GetByID(ctx, gomock.Any(), &sdkauthorization.RoleDefinitionsClientGetByIDOptions{}).AnyTimes().Return(platformIdentityRequiredPermissions, nil)
|
||||
},
|
||||
checkAccessMocks: func(cancel context.CancelFunc, pdpClient *mock_remotepdp.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential) {
|
||||
checkAccessMocks: func(cancel context.CancelFunc, pdpClient *mock_checkaccess.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, env *mock_env.MockInterface) {
|
||||
mockTokenCredential(tokenCred)
|
||||
msiAuthReq := createAuthorizationRequest(dummyObjectId, platformIdentity1, msiRequiredPermissionsList...)
|
||||
pdpClient.EXPECT().CheckAccess(gomock.Any(), msiAuthReq).Return(&msiAllowedActions, nil).AnyTimes()
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
platformIdentity1,
|
||||
msiRequiredPermissionsList,
|
||||
validTestToken,
|
||||
).AnyTimes().Return(&msiAuthZRequest, nil)
|
||||
pdpClient.EXPECT().CheckAccess(gomock.Any(), msiAuthZRequest).Return(&msiAllowedActions, nil).AnyTimes()
|
||||
},
|
||||
wantPlatformIdentities: desiredPlatformWorkloadIdentities,
|
||||
wantPlatformIdentitiesActionsMap: map[string][]string{
|
||||
|
@ -473,10 +497,15 @@ func TestValidatePlatformWorkloadIdentityProfile(t *testing.T) {
|
|||
roleDefinitions.EXPECT().GetByID(ctx, rbac.RoleAzureRedHatOpenShiftFederatedCredentialRole, &sdkauthorization.RoleDefinitionsClientGetByIDOptions{}).Return(msiRequiredPermissions, nil)
|
||||
roleDefinitions.EXPECT().GetByID(ctx, gomock.Any(), &sdkauthorization.RoleDefinitionsClientGetByIDOptions{}).AnyTimes().Return(platformIdentityRequiredPermissions, nil)
|
||||
},
|
||||
checkAccessMocks: func(cancel context.CancelFunc, pdpClient *mock_remotepdp.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential) {
|
||||
checkAccessMocks: func(cancel context.CancelFunc, pdpClient *mock_checkaccess.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, env *mock_env.MockInterface) {
|
||||
mockTokenCredential(tokenCred)
|
||||
msiAuthReq := createAuthorizationRequest(dummyObjectId, platformIdentity1, msiRequiredPermissionsList...)
|
||||
pdpClient.EXPECT().CheckAccess(gomock.Any(), msiAuthReq).Do(func(arg0, arg1 interface{}) {
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
platformIdentity1,
|
||||
msiRequiredPermissionsList,
|
||||
validTestToken,
|
||||
).AnyTimes().Return(&msiAuthZRequest, nil)
|
||||
pdpClient.EXPECT().CheckAccess(gomock.Any(), msiAuthZRequest).Do(func(arg0, arg1 interface{}) {
|
||||
cancel()
|
||||
}).Return(&msiNotAllowedActions, nil).AnyTimes()
|
||||
},
|
||||
|
@ -502,10 +531,15 @@ func TestValidatePlatformWorkloadIdentityProfile(t *testing.T) {
|
|||
roleDefinitions.EXPECT().GetByID(ctx, rbac.RoleAzureRedHatOpenShiftFederatedCredentialRole, &sdkauthorization.RoleDefinitionsClientGetByIDOptions{}).Return(msiRequiredPermissions, nil)
|
||||
roleDefinitions.EXPECT().GetByID(ctx, gomock.Any(), &sdkauthorization.RoleDefinitionsClientGetByIDOptions{}).AnyTimes().Return(platformIdentityRequiredPermissions, nil)
|
||||
},
|
||||
checkAccessMocks: func(cancel context.CancelFunc, pdpClient *mock_remotepdp.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential) {
|
||||
checkAccessMocks: func(cancel context.CancelFunc, pdpClient *mock_checkaccess.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, env *mock_env.MockInterface) {
|
||||
mockTokenCredential(tokenCred)
|
||||
msiAuthReq := createAuthorizationRequest(dummyObjectId, platformIdentity1, msiRequiredPermissionsList...)
|
||||
pdpClient.EXPECT().CheckAccess(gomock.Any(), msiAuthReq).Do(func(arg0, arg1 interface{}) {
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
platformIdentity1,
|
||||
msiRequiredPermissionsList,
|
||||
validTestToken,
|
||||
).AnyTimes().Return(&msiAuthZRequest, nil)
|
||||
pdpClient.EXPECT().CheckAccess(gomock.Any(), msiAuthZRequest).Do(func(arg0, arg1 interface{}) {
|
||||
cancel()
|
||||
}).Return(&msiActionMissing, nil).AnyTimes()
|
||||
},
|
||||
|
@ -531,10 +565,15 @@ func TestValidatePlatformWorkloadIdentityProfile(t *testing.T) {
|
|||
roleDefinitions.EXPECT().GetByID(ctx, rbac.RoleAzureRedHatOpenShiftFederatedCredentialRole, &sdkauthorization.RoleDefinitionsClientGetByIDOptions{}).Return(msiRequiredPermissions, nil)
|
||||
roleDefinitions.EXPECT().GetByID(ctx, gomock.Any(), &sdkauthorization.RoleDefinitionsClientGetByIDOptions{}).AnyTimes().Return(platformIdentityRequiredPermissions, errors.New("Generic Error"))
|
||||
},
|
||||
checkAccessMocks: func(cancel context.CancelFunc, pdpClient *mock_remotepdp.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential) {
|
||||
checkAccessMocks: func(cancel context.CancelFunc, pdpClient *mock_checkaccess.MockRemotePDPClient, tokenCred *mock_azcore.MockTokenCredential, env *mock_env.MockInterface) {
|
||||
mockTokenCredential(tokenCred)
|
||||
msiAuthReq := createAuthorizationRequest(dummyObjectId, platformIdentity1, msiRequiredPermissionsList...)
|
||||
pdpClient.EXPECT().CheckAccess(gomock.Any(), msiAuthReq).Return(&msiAllowedActions, errors.New("Generic Error")).AnyTimes()
|
||||
env.EXPECT().Environment().AnyTimes().Return(&azureclient.PublicCloud)
|
||||
pdpClient.EXPECT().CreateAuthorizationRequest(
|
||||
platformIdentity1,
|
||||
msiRequiredPermissionsList,
|
||||
validTestToken,
|
||||
).AnyTimes().Return(&msiAuthZRequest, nil)
|
||||
pdpClient.EXPECT().CheckAccess(gomock.Any(), msiAuthZRequest).Return(&msiAllowedActions, errors.New("Generic Error")).AnyTimes()
|
||||
},
|
||||
wantErr: "Generic Error",
|
||||
},
|
||||
|
@ -545,19 +584,19 @@ func TestValidatePlatformWorkloadIdentityProfile(t *testing.T) {
|
|||
|
||||
_env := mock_env.NewMockInterface(controller)
|
||||
roleDefinitions := mock_armauthorization.NewMockRoleDefinitionsClient(controller)
|
||||
pdpClient := mock_remotepdp.NewMockRemotePDPClient(controller)
|
||||
|
||||
dv := &dynamic{
|
||||
env: _env,
|
||||
authorizerType: AuthorizerClusterServicePrincipal,
|
||||
log: logrus.NewEntry(logrus.StandardLogger()),
|
||||
pdpClient: pdpClient,
|
||||
}
|
||||
|
||||
pdpClient := mock_checkaccess.NewMockRemotePDPClient(controller)
|
||||
tokenCred := mock_azcore.NewMockTokenCredential(controller)
|
||||
|
||||
dv := &dynamic{
|
||||
env: _env,
|
||||
authorizerType: AuthorizerClusterServicePrincipal,
|
||||
log: logrus.NewEntry(logrus.StandardLogger()),
|
||||
pdpClient: pdpClient,
|
||||
checkAccessSubjectInfoCred: tokenCred,
|
||||
}
|
||||
|
||||
if tt.checkAccessMocks != nil {
|
||||
tt.checkAccessMocks(cancel, pdpClient, tokenCred)
|
||||
tt.checkAccessMocks(cancel, pdpClient, tokenCred, _env)
|
||||
}
|
||||
|
||||
if tt.mocks != nil {
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
|
||||
"github.com/Azure/checkaccess-v2-go-sdk/client"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
"github.com/Azure/go-autorest/autorest/to"
|
||||
"github.com/form3tech-oss/jwt-go"
|
||||
|
@ -18,7 +19,7 @@ import (
|
|||
|
||||
"github.com/Azure/ARO-RP/pkg/api"
|
||||
"github.com/Azure/ARO-RP/pkg/env"
|
||||
"github.com/Azure/ARO-RP/pkg/util/azureclient/authz/remotepdp"
|
||||
"github.com/Azure/ARO-RP/pkg/util/azureclient"
|
||||
"github.com/Azure/ARO-RP/pkg/util/azureclient/azuresdk/armauthorization"
|
||||
"github.com/Azure/ARO-RP/pkg/util/platformworkloadidentity"
|
||||
"github.com/Azure/ARO-RP/pkg/validate/dynamic"
|
||||
|
@ -127,11 +128,20 @@ func (dv *openShiftClusterDynamicValidator) Dynamic(ctx context.Context) error {
|
|||
}
|
||||
|
||||
aroEnv := dv.env.Environment()
|
||||
pdpClient := remotepdp.NewRemotePDPClient(
|
||||
clientOptions := &azcore.ClientOptions{
|
||||
Transport: &http.Client{
|
||||
Transport: azureclient.NewCustomRoundTripper(http.DefaultTransport),
|
||||
},
|
||||
}
|
||||
pdpClient, err := client.NewRemotePDPClient(
|
||||
fmt.Sprintf(aroEnv.Endpoint, dv.env.Location()),
|
||||
aroEnv.OAuthScope,
|
||||
fpClientCred,
|
||||
clientOptions,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
scopes := []string{dv.env.Environment().ResourceManagerScope}
|
||||
var spDynamic dynamic.Dynamic
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
package token
|
||||
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the Apache License 2.0.
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
)
|
||||
|
||||
type Custom struct {
|
||||
ObjectId string `json:"oid"`
|
||||
ClaimNames map[string]interface{} `json:"_claim_names"`
|
||||
Groups []string `json:"groups"`
|
||||
jwt.RegisteredClaims
|
||||
}
|
||||
|
||||
func CreateTestToken(oid string, fakeClaims *Custom) (string, error) {
|
||||
// Define the signing key
|
||||
signingKey := []byte("test-secret-key")
|
||||
|
||||
// Create the custom claims
|
||||
claims := Custom{
|
||||
ObjectId: oid,
|
||||
ClaimNames: map[string]interface{}{
|
||||
"example_claim": "example_value",
|
||||
},
|
||||
RegisteredClaims: jwt.RegisteredClaims{
|
||||
Issuer: "test-issuer",
|
||||
Subject: "test-subject",
|
||||
Audience: []string{"test-audience"},
|
||||
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour * 24)),
|
||||
IssuedAt: jwt.NewNumericDate(time.Now()),
|
||||
ID: "unique-id",
|
||||
},
|
||||
}
|
||||
|
||||
if fakeClaims != nil {
|
||||
claims = *fakeClaims
|
||||
}
|
||||
|
||||
// Create the token
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
|
||||
// Sign the token
|
||||
tokenString, err := token.SignedString(signingKey)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error signing token: %v", err)
|
||||
}
|
||||
|
||||
return tokenString, nil
|
||||
}
|
|
@ -1,5 +1,61 @@
|
|||
# Release History
|
||||
|
||||
## 1.16.0 (2024-10-17)
|
||||
|
||||
### Features Added
|
||||
|
||||
* Added field `Kind` to `runtime.StartSpanOptions` to allow a kind to be set when starting a span.
|
||||
|
||||
### Bugs Fixed
|
||||
|
||||
* `BearerTokenPolicy` now rewinds request bodies before retrying
|
||||
|
||||
## 1.15.0 (2024-10-14)
|
||||
|
||||
### Features Added
|
||||
|
||||
* `BearerTokenPolicy` handles CAE claims challenges
|
||||
|
||||
### Bugs Fixed
|
||||
|
||||
* Omit the `ResponseError.RawResponse` field from JSON marshaling so instances can be marshaled.
|
||||
* Fixed an integer overflow in the retry policy.
|
||||
|
||||
### Other Changes
|
||||
|
||||
* Update dependencies.
|
||||
|
||||
## 1.14.0 (2024-08-07)
|
||||
|
||||
### Features Added
|
||||
|
||||
* Added field `Attributes` to `runtime.StartSpanOptions` to simplify creating spans with attributes.
|
||||
|
||||
### Other Changes
|
||||
|
||||
* Include the HTTP verb and URL in `log.EventRetryPolicy` log entries so it's clear which operation is being retried.
|
||||
|
||||
## 1.13.0 (2024-07-16)
|
||||
|
||||
### Features Added
|
||||
|
||||
- Added runtime.NewRequestFromRequest(), allowing for a policy.Request to be created from an existing *http.Request.
|
||||
|
||||
## 1.12.0 (2024-06-06)
|
||||
|
||||
### Features Added
|
||||
|
||||
* Added field `StatusCodes` to `runtime.FetcherForNextLinkOptions` allowing for additional HTTP status codes indicating success.
|
||||
* Added func `NewUUID` to the `runtime` package for generating UUIDs.
|
||||
|
||||
### Bugs Fixed
|
||||
|
||||
* Fixed an issue that prevented pollers using the `Operation-Location` strategy from unmarshaling the final result in some cases.
|
||||
|
||||
### Other Changes
|
||||
|
||||
* Updated dependencies.
|
||||
|
||||
## 1.11.1 (2024-04-02)
|
||||
|
||||
### Bugs Fixed
|
||||
|
|
2
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/internal/resource/resource_identifier.go
сгенерированный
поставляемый
2
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/internal/resource/resource_identifier.go
сгенерированный
поставляемый
|
@ -192,7 +192,7 @@ func appendNext(parent *ResourceID, parts []string, id string) (*ResourceID, err
|
|||
}
|
||||
|
||||
if strings.EqualFold(parts[0], providersKey) && (len(parts) == 2 || strings.EqualFold(parts[2], providersKey)) {
|
||||
//provider resource can only be on a tenant or a subscription parent
|
||||
// provider resource can only be on a tenant or a subscription parent
|
||||
if parent.ResourceType.String() != SubscriptionResourceType.String() && parent.ResourceType.String() != TenantResourceType.String() {
|
||||
return nil, fmt.Errorf("invalid resource ID: %s", id)
|
||||
}
|
||||
|
|
8
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/runtime/pipeline.go
сгенерированный
поставляемый
8
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/runtime/pipeline.go
сгенерированный
поставляемый
|
@ -34,18 +34,22 @@ func NewPipeline(module, version string, cred azcore.TokenCredential, plOpts azr
|
|||
InsecureAllowCredentialWithHTTP: options.InsecureAllowCredentialWithHTTP,
|
||||
Scopes: []string{conf.Audience + "/.default"},
|
||||
})
|
||||
// we don't want to modify the underlying array in plOpts.PerRetry
|
||||
perRetry := make([]azpolicy.Policy, len(plOpts.PerRetry), len(plOpts.PerRetry)+1)
|
||||
copy(perRetry, plOpts.PerRetry)
|
||||
plOpts.PerRetry = append(perRetry, authPolicy, exported.PolicyFunc(httpTraceNamespacePolicy))
|
||||
perRetry = append(perRetry, authPolicy, exported.PolicyFunc(httpTraceNamespacePolicy))
|
||||
plOpts.PerRetry = perRetry
|
||||
if !options.DisableRPRegistration {
|
||||
regRPOpts := armpolicy.RegistrationOptions{ClientOptions: options.ClientOptions}
|
||||
regPolicy, err := NewRPRegistrationPolicy(cred, ®RPOpts)
|
||||
if err != nil {
|
||||
return azruntime.Pipeline{}, err
|
||||
}
|
||||
// we don't want to modify the underlying array in plOpts.PerCall
|
||||
perCall := make([]azpolicy.Policy, len(plOpts.PerCall), len(plOpts.PerCall)+1)
|
||||
copy(perCall, plOpts.PerCall)
|
||||
plOpts.PerCall = append(perCall, regPolicy)
|
||||
perCall = append(perCall, regPolicy)
|
||||
plOpts.PerCall = perCall
|
||||
}
|
||||
if plOpts.APIVersion.Name == "" {
|
||||
plOpts.APIVersion.Name = "api-version"
|
||||
|
|
48
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/runtime/policy_bearer_token.go
сгенерированный
поставляемый
48
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/runtime/policy_bearer_token.go
сгенерированный
поставляемый
|
@ -5,7 +5,6 @@ package runtime
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
@ -66,31 +65,16 @@ func NewBearerTokenPolicy(cred azcore.TokenCredential, opts *armpolicy.BearerTok
|
|||
p.btp = azruntime.NewBearerTokenPolicy(cred, opts.Scopes, &azpolicy.BearerTokenOptions{
|
||||
InsecureAllowCredentialWithHTTP: opts.InsecureAllowCredentialWithHTTP,
|
||||
AuthorizationHandler: azpolicy.AuthorizationHandler{
|
||||
OnChallenge: p.onChallenge,
|
||||
OnRequest: p.onRequest,
|
||||
OnRequest: p.onRequest,
|
||||
},
|
||||
})
|
||||
return p
|
||||
}
|
||||
|
||||
func (b *BearerTokenPolicy) onChallenge(req *azpolicy.Request, res *http.Response, authNZ func(azpolicy.TokenRequestOptions) error) error {
|
||||
challenge := res.Header.Get(shared.HeaderWWWAuthenticate)
|
||||
claims, err := parseChallenge(challenge)
|
||||
if err != nil {
|
||||
// the challenge contains claims we can't parse
|
||||
return err
|
||||
} else if claims != "" {
|
||||
// request a new token having the specified claims, send the request again
|
||||
return authNZ(azpolicy.TokenRequestOptions{Claims: claims, EnableCAE: true, Scopes: b.scopes})
|
||||
}
|
||||
// auth challenge didn't include claims, so this is a simple authorization failure
|
||||
return azruntime.NewResponseError(res)
|
||||
}
|
||||
|
||||
// onRequest authorizes requests with one or more bearer tokens
|
||||
func (b *BearerTokenPolicy) onRequest(req *azpolicy.Request, authNZ func(azpolicy.TokenRequestOptions) error) error {
|
||||
// authorize the request with a token for the primary tenant
|
||||
err := authNZ(azpolicy.TokenRequestOptions{EnableCAE: true, Scopes: b.scopes})
|
||||
err := authNZ(azpolicy.TokenRequestOptions{Scopes: b.scopes})
|
||||
if err != nil || len(b.auxResources) == 0 {
|
||||
return err
|
||||
}
|
||||
|
@ -116,31 +100,3 @@ func (b *BearerTokenPolicy) onRequest(req *azpolicy.Request, authNZ func(azpolic
|
|||
func (b *BearerTokenPolicy) Do(req *azpolicy.Request) (*http.Response, error) {
|
||||
return b.btp.Do(req)
|
||||
}
|
||||
|
||||
// parseChallenge parses claims from an authentication challenge issued by ARM so a client can request a token
|
||||
// that will satisfy conditional access policies. It returns a non-nil error when the given value contains
|
||||
// claims it can't parse. If the value contains no claims, it returns an empty string and a nil error.
|
||||
func parseChallenge(wwwAuthenticate string) (string, error) {
|
||||
claims := ""
|
||||
var err error
|
||||
for _, param := range strings.Split(wwwAuthenticate, ",") {
|
||||
if _, after, found := strings.Cut(param, "claims="); found {
|
||||
if claims != "" {
|
||||
// The header contains multiple challenges, at least two of which specify claims. The specs allow this
|
||||
// but it's unclear what a client should do in this case and there's as yet no concrete example of it.
|
||||
err = fmt.Errorf("found multiple claims challenges in %q", wwwAuthenticate)
|
||||
break
|
||||
}
|
||||
// trim stuff that would get an error from RawURLEncoding; claims may or may not be padded
|
||||
claims = strings.Trim(after, `\"=`)
|
||||
// we don't return this error because it's something unhelpful like "illegal base64 data at input byte 42"
|
||||
if b, decErr := base64.RawURLEncoding.DecodeString(claims); decErr == nil {
|
||||
claims = string(b)
|
||||
} else {
|
||||
err = fmt.Errorf("failed to parse claims from %q", wwwAuthenticate)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return claims, err
|
||||
}
|
||||
|
|
|
@ -11,4 +11,7 @@ import "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported"
|
|||
// ResponseError is returned when a request is made to a service and
|
||||
// the service returns a non-success HTTP status code.
|
||||
// Use errors.As() to access this type in the error chain.
|
||||
//
|
||||
// When marshaling instances, the RawResponse field will be omitted.
|
||||
// However, the contents returned by Error() will be preserved.
|
||||
type ResponseError = exported.ResponseError
|
||||
|
|
37
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/request.go
сгенерированный
поставляемый
37
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/request.go
сгенерированный
поставляемый
|
@ -7,6 +7,7 @@
|
|||
package exported
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
|
@ -67,6 +68,42 @@ func (ov opValues) get(value any) bool {
|
|||
return ok
|
||||
}
|
||||
|
||||
// NewRequestFromRequest creates a new policy.Request with an existing *http.Request
|
||||
// Exported as runtime.NewRequestFromRequest().
|
||||
func NewRequestFromRequest(req *http.Request) (*Request, error) {
|
||||
policyReq := &Request{req: req}
|
||||
|
||||
if req.Body != nil {
|
||||
// we can avoid a body copy here if the underlying stream is already a
|
||||
// ReadSeekCloser.
|
||||
readSeekCloser, isReadSeekCloser := req.Body.(io.ReadSeekCloser)
|
||||
|
||||
if !isReadSeekCloser {
|
||||
// since this is an already populated http.Request we want to copy
|
||||
// over its body, if it has one.
|
||||
bodyBytes, err := io.ReadAll(req.Body)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := req.Body.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
readSeekCloser = NopCloser(bytes.NewReader(bodyBytes))
|
||||
}
|
||||
|
||||
// SetBody also takes care of updating the http.Request's body
|
||||
// as well, so they should stay in-sync from this point.
|
||||
if err := policyReq.SetBody(readSeekCloser, req.Header.Get("Content-Type")); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return policyReq, nil
|
||||
}
|
||||
|
||||
// NewRequest creates a new Request with the specified input.
|
||||
// Exported as runtime.NewRequest().
|
||||
func NewRequest(ctx context.Context, httpMethod string, endpoint string) (*Request, error) {
|
||||
|
|
38
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/response_error.go
сгенерированный
поставляемый
38
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/response_error.go
сгенерированный
поставляемый
|
@ -117,12 +117,18 @@ type ResponseError struct {
|
|||
StatusCode int
|
||||
|
||||
// RawResponse is the underlying HTTP response.
|
||||
RawResponse *http.Response
|
||||
RawResponse *http.Response `json:"-"`
|
||||
|
||||
errMsg string
|
||||
}
|
||||
|
||||
// Error implements the error interface for type ResponseError.
|
||||
// Note that the message contents are not contractual and can change over time.
|
||||
func (e *ResponseError) Error() string {
|
||||
if e.errMsg != "" {
|
||||
return e.errMsg
|
||||
}
|
||||
|
||||
const separator = "--------------------------------------------------------------------------------"
|
||||
// write the request method and URL with response status code
|
||||
msg := &bytes.Buffer{}
|
||||
|
@ -163,5 +169,33 @@ func (e *ResponseError) Error() string {
|
|||
}
|
||||
fmt.Fprintln(msg, separator)
|
||||
|
||||
return msg.String()
|
||||
e.errMsg = msg.String()
|
||||
return e.errMsg
|
||||
}
|
||||
|
||||
// internal type used for marshaling/unmarshaling
|
||||
type responseError struct {
|
||||
ErrorCode string `json:"errorCode"`
|
||||
StatusCode int `json:"statusCode"`
|
||||
ErrorMessage string `json:"errorMessage"`
|
||||
}
|
||||
|
||||
func (e ResponseError) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(responseError{
|
||||
ErrorCode: e.ErrorCode,
|
||||
StatusCode: e.StatusCode,
|
||||
ErrorMessage: e.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
func (e *ResponseError) UnmarshalJSON(data []byte) error {
|
||||
re := responseError{}
|
||||
if err := json.Unmarshal(data, &re); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
e.ErrorCode = re.ErrorCode
|
||||
e.StatusCode = re.StatusCode
|
||||
e.errMsg = re.ErrorMessage
|
||||
return nil
|
||||
}
|
||||
|
|
2
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/async/async.go
сгенерированный
поставляемый
2
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/async/async.go
сгенерированный
поставляемый
|
@ -155,5 +155,5 @@ func (p *Poller[T]) Result(ctx context.Context, out *T) error {
|
|||
p.resp = resp
|
||||
}
|
||||
|
||||
return pollers.ResultHelper(p.resp, poller.Failed(p.CurState), out)
|
||||
return pollers.ResultHelper(p.resp, poller.Failed(p.CurState), "", out)
|
||||
}
|
||||
|
|
2
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/body/body.go
сгенерированный
поставляемый
2
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/body/body.go
сгенерированный
поставляемый
|
@ -131,5 +131,5 @@ func (p *Poller[T]) Poll(ctx context.Context) (*http.Response, error) {
|
|||
}
|
||||
|
||||
func (p *Poller[T]) Result(ctx context.Context, out *T) error {
|
||||
return pollers.ResultHelper(p.resp, poller.Failed(p.CurState), out)
|
||||
return pollers.ResultHelper(p.resp, poller.Failed(p.CurState), "", out)
|
||||
}
|
||||
|
|
2
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/fake/fake.go
сгенерированный
поставляемый
2
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/fake/fake.go
сгенерированный
поставляемый
|
@ -124,7 +124,7 @@ func (p *Poller[T]) Result(ctx context.Context, out *T) error {
|
|||
return exported.NewResponseError(p.resp)
|
||||
}
|
||||
|
||||
return pollers.ResultHelper(p.resp, poller.Failed(p.FakeStatus), out)
|
||||
return pollers.ResultHelper(p.resp, poller.Failed(p.FakeStatus), "", out)
|
||||
}
|
||||
|
||||
// SanitizePollerPath removes any fake-appended suffix from a URL's path.
|
||||
|
|
2
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/loc/loc.go
сгенерированный
поставляемый
2
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/loc/loc.go
сгенерированный
поставляемый
|
@ -119,5 +119,5 @@ func (p *Poller[T]) Poll(ctx context.Context) (*http.Response, error) {
|
|||
}
|
||||
|
||||
func (p *Poller[T]) Result(ctx context.Context, out *T) error {
|
||||
return pollers.ResultHelper(p.resp, poller.Failed(p.CurState), out)
|
||||
return pollers.ResultHelper(p.resp, poller.Failed(p.CurState), "", out)
|
||||
}
|
||||
|
|
11
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/op/op.go
сгенерированный
поставляемый
11
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/op/op.go
сгенерированный
поставляемый
|
@ -115,10 +115,13 @@ func (p *Poller[T]) Poll(ctx context.Context) (*http.Response, error) {
|
|||
func (p *Poller[T]) Result(ctx context.Context, out *T) error {
|
||||
var req *exported.Request
|
||||
var err error
|
||||
|
||||
// when the payload is included with the status monitor on
|
||||
// terminal success it's in the "result" JSON property
|
||||
payloadPath := "result"
|
||||
|
||||
if p.FinalState == pollers.FinalStateViaLocation && p.LocURL != "" {
|
||||
req, err = exported.NewRequest(ctx, http.MethodGet, p.LocURL)
|
||||
} else if p.FinalState == pollers.FinalStateViaOpLocation && p.Method == http.MethodPost {
|
||||
// no final GET required, terminal response should have it
|
||||
} else if rl, rlErr := poller.GetResourceLocation(p.resp); rlErr != nil && !errors.Is(rlErr, poller.ErrNoBody) {
|
||||
return rlErr
|
||||
} else if rl != "" {
|
||||
|
@ -134,6 +137,8 @@ func (p *Poller[T]) Result(ctx context.Context, out *T) error {
|
|||
|
||||
// if a final GET request has been created, execute it
|
||||
if req != nil {
|
||||
// no JSON path when making a final GET request
|
||||
payloadPath = ""
|
||||
resp, err := p.pl.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -141,5 +146,5 @@ func (p *Poller[T]) Result(ctx context.Context, out *T) error {
|
|||
p.resp = resp
|
||||
}
|
||||
|
||||
return pollers.ResultHelper(p.resp, poller.Failed(p.CurState), out)
|
||||
return pollers.ResultHelper(p.resp, poller.Failed(p.CurState), payloadPath, out)
|
||||
}
|
||||
|
|
14
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/util.go
сгенерированный
поставляемый
14
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/util.go
сгенерированный
поставляемый
|
@ -159,7 +159,7 @@ func PollHelper(ctx context.Context, endpoint string, pl azexported.Pipeline, up
|
|||
// ResultHelper processes the response as success or failure.
|
||||
// In the success case, it unmarshals the payload into either a new instance of T or out.
|
||||
// In the failure case, it creates an *azcore.Response error from the response.
|
||||
func ResultHelper[T any](resp *http.Response, failed bool, out *T) error {
|
||||
func ResultHelper[T any](resp *http.Response, failed bool, jsonPath string, out *T) error {
|
||||
// short-circuit the simple success case with no response body to unmarshal
|
||||
if resp.StatusCode == http.StatusNoContent {
|
||||
return nil
|
||||
|
@ -176,6 +176,18 @@ func ResultHelper[T any](resp *http.Response, failed bool, out *T) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if jsonPath != "" && len(payload) > 0 {
|
||||
// extract the payload from the specified JSON path.
|
||||
// do this before the zero-length check in case there
|
||||
// is no payload.
|
||||
jsonBody := map[string]json.RawMessage{}
|
||||
if err = json.Unmarshal(payload, &jsonBody); err != nil {
|
||||
return err
|
||||
}
|
||||
payload = jsonBody[jsonPath]
|
||||
}
|
||||
|
||||
if len(payload) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
|
2
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/constants.go
сгенерированный
поставляемый
2
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/constants.go
сгенерированный
поставляемый
|
@ -40,5 +40,5 @@ const (
|
|||
Module = "azcore"
|
||||
|
||||
// Version is the semantic version (see http://semver.org) of this module.
|
||||
Version = "v1.11.1"
|
||||
Version = "v1.16.0"
|
||||
)
|
||||
|
|
23
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/policy/policy.go
сгенерированный
поставляемый
23
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/policy/policy.go
сгенерированный
поставляемый
|
@ -161,19 +161,20 @@ type BearerTokenOptions struct {
|
|||
|
||||
// AuthorizationHandler allows SDK developers to insert custom logic that runs when BearerTokenPolicy must authorize a request.
|
||||
type AuthorizationHandler struct {
|
||||
// OnRequest is called each time the policy receives a request. Its func parameter authorizes the request with a token
|
||||
// from the policy's given credential. Implementations that need to perform I/O should use the Request's context,
|
||||
// available from Request.Raw().Context(). When OnRequest returns an error, the policy propagates that error and doesn't
|
||||
// send the request. When OnRequest is nil, the policy follows its default behavior, authorizing the request with a
|
||||
// token from its credential according to its configuration.
|
||||
// OnRequest provides TokenRequestOptions the policy can use to acquire a token for a request. The policy calls OnRequest
|
||||
// whenever it needs a token and may call it multiple times for the same request. Its func parameter authorizes the request
|
||||
// with a token from the policy's credential. Implementations that need to perform I/O should use the Request's context,
|
||||
// available from Request.Raw().Context(). When OnRequest returns an error, the policy propagates that error and doesn't send
|
||||
// the request. When OnRequest is nil, the policy follows its default behavior, which is to authorize the request with a token
|
||||
// from its credential according to its configuration.
|
||||
OnRequest func(*Request, func(TokenRequestOptions) error) error
|
||||
|
||||
// OnChallenge is called when the policy receives a 401 response, allowing the AuthorizationHandler to re-authorize the
|
||||
// request according to an authentication challenge (the Response's WWW-Authenticate header). OnChallenge is responsible
|
||||
// for parsing parameters from the challenge. Its func parameter will authorize the request with a token from the policy's
|
||||
// given credential. Implementations that need to perform I/O should use the Request's context, available from
|
||||
// Request.Raw().Context(). When OnChallenge returns nil, the policy will send the request again. When OnChallenge is nil,
|
||||
// the policy will return any 401 response to the client.
|
||||
// OnChallenge allows clients to implement custom HTTP authentication challenge handling. BearerTokenPolicy calls it upon
|
||||
// receiving a 401 response containing multiple Bearer challenges or a challenge BearerTokenPolicy itself can't handle.
|
||||
// OnChallenge is responsible for parsing challenge(s) (the Response's WWW-Authenticate header) and reauthorizing the
|
||||
// Request accordingly. Its func argument authorizes the Request with a token from the policy's credential using the given
|
||||
// TokenRequestOptions. OnChallenge should honor the Request's context, available from Request.Raw().Context(). When
|
||||
// OnChallenge returns nil, the policy will send the Request again.
|
||||
OnChallenge func(*Request, *http.Response, func(TokenRequestOptions) error) error
|
||||
}
|
||||
|
||||
|
|
13
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/pager.go
сгенерированный
поставляемый
13
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/pager.go
сгенерированный
поставляемый
|
@ -94,6 +94,10 @@ type FetcherForNextLinkOptions struct {
|
|||
// NextReq is the func to be called when requesting subsequent pages.
|
||||
// Used for paged operations that have a custom next link operation.
|
||||
NextReq func(context.Context, string) (*policy.Request, error)
|
||||
|
||||
// StatusCodes contains additional HTTP status codes indicating success.
|
||||
// The default value is http.StatusOK.
|
||||
StatusCodes []int
|
||||
}
|
||||
|
||||
// FetcherForNextLink is a helper containing boilerplate code to simplify creating a PagingHandler[T].Fetcher from a next link URL.
|
||||
|
@ -105,10 +109,13 @@ type FetcherForNextLinkOptions struct {
|
|||
func FetcherForNextLink(ctx context.Context, pl Pipeline, nextLink string, firstReq func(context.Context) (*policy.Request, error), options *FetcherForNextLinkOptions) (*http.Response, error) {
|
||||
var req *policy.Request
|
||||
var err error
|
||||
if options == nil {
|
||||
options = &FetcherForNextLinkOptions{}
|
||||
}
|
||||
if nextLink == "" {
|
||||
req, err = firstReq(ctx)
|
||||
} else if nextLink, err = EncodeQueryParams(nextLink); err == nil {
|
||||
if options != nil && options.NextReq != nil {
|
||||
if options.NextReq != nil {
|
||||
req, err = options.NextReq(ctx, nextLink)
|
||||
} else {
|
||||
req, err = NewRequest(ctx, http.MethodGet, nextLink)
|
||||
|
@ -121,7 +128,9 @@ func FetcherForNextLink(ctx context.Context, pl Pipeline, nextLink string, first
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !HasStatusCode(resp, http.StatusOK) {
|
||||
successCodes := []int{http.StatusOK}
|
||||
successCodes = append(successCodes, options.StatusCodes...)
|
||||
if !HasStatusCode(resp, successCodes...) {
|
||||
return nil, NewResponseError(resp)
|
||||
}
|
||||
return resp, nil
|
||||
|
|
139
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_bearer_token.go
сгенерированный
поставляемый
139
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_bearer_token.go
сгенерированный
поставляемый
|
@ -4,9 +4,12 @@
|
|||
package runtime
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported"
|
||||
|
@ -17,6 +20,11 @@ import (
|
|||
)
|
||||
|
||||
// BearerTokenPolicy authorizes requests with bearer tokens acquired from a TokenCredential.
|
||||
// It handles [Continuous Access Evaluation] (CAE) challenges. Clients needing to handle
|
||||
// additional authentication challenges, or needing more control over authorization, should
|
||||
// provide a [policy.AuthorizationHandler] in [policy.BearerTokenOptions].
|
||||
//
|
||||
// [Continuous Access Evaluation]: https://learn.microsoft.com/entra/identity/conditional-access/concept-continuous-access-evaluation
|
||||
type BearerTokenPolicy struct {
|
||||
// mainResource is the resource to be retreived using the tenant specified in the credential
|
||||
mainResource *temporal.Resource[exported.AccessToken, acquiringResourceState]
|
||||
|
@ -51,8 +59,18 @@ func NewBearerTokenPolicy(cred exported.TokenCredential, scopes []string, opts *
|
|||
if opts == nil {
|
||||
opts = &policy.BearerTokenOptions{}
|
||||
}
|
||||
ah := opts.AuthorizationHandler
|
||||
if ah.OnRequest == nil {
|
||||
// Set a default OnRequest that simply requests a token with the given scopes. OnChallenge
|
||||
// doesn't get a default so the policy can use a nil check to determine whether the caller
|
||||
// provided an implementation.
|
||||
ah.OnRequest = func(_ *policy.Request, authNZ func(policy.TokenRequestOptions) error) error {
|
||||
// authNZ sets EnableCAE: true in all cases, no need to duplicate that here
|
||||
return authNZ(policy.TokenRequestOptions{Scopes: scopes})
|
||||
}
|
||||
}
|
||||
return &BearerTokenPolicy{
|
||||
authzHandler: opts.AuthorizationHandler,
|
||||
authzHandler: ah,
|
||||
cred: cred,
|
||||
scopes: scopes,
|
||||
mainResource: temporal.NewResource(acquire),
|
||||
|
@ -63,6 +81,7 @@ func NewBearerTokenPolicy(cred exported.TokenCredential, scopes []string, opts *
|
|||
// authenticateAndAuthorize returns a function which authorizes req with a token from the policy's credential
|
||||
func (b *BearerTokenPolicy) authenticateAndAuthorize(req *policy.Request) func(policy.TokenRequestOptions) error {
|
||||
return func(tro policy.TokenRequestOptions) error {
|
||||
tro.EnableCAE = true
|
||||
as := acquiringResourceState{p: b, req: req, tro: tro}
|
||||
tk, err := b.mainResource.Get(as)
|
||||
if err != nil {
|
||||
|
@ -86,12 +105,7 @@ func (b *BearerTokenPolicy) Do(req *policy.Request) (*http.Response, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
var err error
|
||||
if b.authzHandler.OnRequest != nil {
|
||||
err = b.authzHandler.OnRequest(req, b.authenticateAndAuthorize(req))
|
||||
} else {
|
||||
err = b.authenticateAndAuthorize(req)(policy.TokenRequestOptions{Scopes: b.scopes})
|
||||
}
|
||||
err := b.authzHandler.OnRequest(req, b.authenticateAndAuthorize(req))
|
||||
if err != nil {
|
||||
return nil, errorinfo.NonRetriableError(err)
|
||||
}
|
||||
|
@ -101,17 +115,54 @@ func (b *BearerTokenPolicy) Do(req *policy.Request) (*http.Response, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
res, err = b.handleChallenge(req, res, false)
|
||||
return res, err
|
||||
}
|
||||
|
||||
// handleChallenge handles authentication challenges either directly (for CAE challenges) or by calling
|
||||
// the AuthorizationHandler. It's a no-op when the response doesn't include an authentication challenge.
|
||||
// It will recurse at most once, to handle a CAE challenge following a non-CAE challenge handled by the
|
||||
// AuthorizationHandler.
|
||||
func (b *BearerTokenPolicy) handleChallenge(req *policy.Request, res *http.Response, recursed bool) (*http.Response, error) {
|
||||
var err error
|
||||
if res.StatusCode == http.StatusUnauthorized {
|
||||
b.mainResource.Expire()
|
||||
if res.Header.Get("WWW-Authenticate") != "" && b.authzHandler.OnChallenge != nil {
|
||||
if err = b.authzHandler.OnChallenge(req, res, b.authenticateAndAuthorize(req)); err == nil {
|
||||
res, err = req.Next()
|
||||
if res.Header.Get(shared.HeaderWWWAuthenticate) != "" {
|
||||
caeChallenge, parseErr := parseCAEChallenge(res)
|
||||
if parseErr != nil {
|
||||
return res, parseErr
|
||||
}
|
||||
switch {
|
||||
case caeChallenge != nil:
|
||||
authNZ := func(tro policy.TokenRequestOptions) error {
|
||||
// Take the TokenRequestOptions provided by OnRequest and add the challenge claims. The value
|
||||
// will be empty at time of writing because CAE is the only feature involving claims. If in
|
||||
// the future some client needs to specify unrelated claims, this function may need to merge
|
||||
// them with the challenge claims.
|
||||
tro.Claims = caeChallenge.params["claims"]
|
||||
return b.authenticateAndAuthorize(req)(tro)
|
||||
}
|
||||
if err = b.authzHandler.OnRequest(req, authNZ); err == nil {
|
||||
if err = req.RewindBody(); err == nil {
|
||||
res, err = req.Next()
|
||||
}
|
||||
}
|
||||
case b.authzHandler.OnChallenge != nil && !recursed:
|
||||
if err = b.authzHandler.OnChallenge(req, res, b.authenticateAndAuthorize(req)); err == nil {
|
||||
if err = req.RewindBody(); err == nil {
|
||||
if res, err = req.Next(); err == nil {
|
||||
res, err = b.handleChallenge(req, res, true)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// don't retry challenge handling errors
|
||||
err = errorinfo.NonRetriableError(err)
|
||||
}
|
||||
default:
|
||||
// return the response to the pipeline
|
||||
}
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
err = errorinfo.NonRetriableError(err)
|
||||
}
|
||||
return res, err
|
||||
}
|
||||
|
||||
|
@ -121,3 +172,65 @@ func checkHTTPSForAuth(req *policy.Request, allowHTTP bool) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseCAEChallenge returns a *authChallenge representing Response's CAE challenge (nil when Response has none).
|
||||
// If Response includes a CAE challenge having invalid claims, it returns a NonRetriableError.
|
||||
func parseCAEChallenge(res *http.Response) (*authChallenge, error) {
|
||||
var (
|
||||
caeChallenge *authChallenge
|
||||
err error
|
||||
)
|
||||
for _, c := range parseChallenges(res) {
|
||||
if c.scheme == "Bearer" {
|
||||
if claims := c.params["claims"]; claims != "" && c.params["error"] == "insufficient_claims" {
|
||||
if b, de := base64.StdEncoding.DecodeString(claims); de == nil {
|
||||
c.params["claims"] = string(b)
|
||||
caeChallenge = &c
|
||||
} else {
|
||||
// don't include the decoding error because it's something
|
||||
// unhelpful like "illegal base64 data at input byte 42"
|
||||
err = errorinfo.NonRetriableError(errors.New("authentication challenge contains invalid claims: " + claims))
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return caeChallenge, err
|
||||
}
|
||||
|
||||
var (
|
||||
challenge, challengeParams *regexp.Regexp
|
||||
once = &sync.Once{}
|
||||
)
|
||||
|
||||
type authChallenge struct {
|
||||
scheme string
|
||||
params map[string]string
|
||||
}
|
||||
|
||||
// parseChallenges assumes authentication challenges have quoted parameter values
|
||||
func parseChallenges(res *http.Response) []authChallenge {
|
||||
once.Do(func() {
|
||||
// matches challenges having quoted parameters, capturing scheme and parameters
|
||||
challenge = regexp.MustCompile(`(?:(\w+) ((?:\w+="[^"]*",?\s*)+))`)
|
||||
// captures parameter names and values in a match of the above expression
|
||||
challengeParams = regexp.MustCompile(`(\w+)="([^"]*)"`)
|
||||
})
|
||||
parsed := []authChallenge{}
|
||||
// WWW-Authenticate can have multiple values, each containing multiple challenges
|
||||
for _, h := range res.Header.Values(shared.HeaderWWWAuthenticate) {
|
||||
for _, sm := range challenge.FindAllStringSubmatch(h, -1) {
|
||||
// sm is [challenge, scheme, params] (see regexp documentation on submatches)
|
||||
c := authChallenge{
|
||||
params: make(map[string]string),
|
||||
scheme: sm[1],
|
||||
}
|
||||
for _, sm := range challengeParams.FindAllStringSubmatch(sm[2], -1) {
|
||||
// sm is [key="value", key, value] (see regexp documentation on submatches)
|
||||
c.params[sm[1]] = sm[2]
|
||||
}
|
||||
parsed = append(parsed, c)
|
||||
}
|
||||
}
|
||||
return parsed
|
||||
}
|
||||
|
|
19
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_http_trace.go
сгенерированный
поставляемый
19
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_http_trace.go
сгенерированный
поставляемый
|
@ -96,7 +96,10 @@ func (h *httpTracePolicy) Do(req *policy.Request) (resp *http.Response, err erro
|
|||
|
||||
// StartSpanOptions contains the optional values for StartSpan.
|
||||
type StartSpanOptions struct {
|
||||
// for future expansion
|
||||
// Kind indicates the kind of Span.
|
||||
Kind tracing.SpanKind
|
||||
// Attributes contains key-value pairs of attributes for the span.
|
||||
Attributes []tracing.Attribute
|
||||
}
|
||||
|
||||
// StartSpan starts a new tracing span.
|
||||
|
@ -114,7 +117,6 @@ func StartSpan(ctx context.Context, name string, tracer tracing.Tracer, options
|
|||
// we MUST propagate the active tracer before returning so that the trace policy can access it
|
||||
ctx = context.WithValue(ctx, shared.CtxWithTracingTracer{}, tracer)
|
||||
|
||||
const newSpanKind = tracing.SpanKindInternal
|
||||
if activeSpan := ctx.Value(ctxActiveSpan{}); activeSpan != nil {
|
||||
// per the design guidelines, if a SDK method Foo() calls SDK method Bar(),
|
||||
// then the span for Bar() must be suppressed. however, if Bar() makes a REST
|
||||
|
@ -126,10 +128,19 @@ func StartSpan(ctx context.Context, name string, tracer tracing.Tracer, options
|
|||
return ctx, func(err error) {}
|
||||
}
|
||||
}
|
||||
|
||||
if options == nil {
|
||||
options = &StartSpanOptions{}
|
||||
}
|
||||
if options.Kind == 0 {
|
||||
options.Kind = tracing.SpanKindInternal
|
||||
}
|
||||
|
||||
ctx, span := tracer.Start(ctx, name, &tracing.SpanOptions{
|
||||
Kind: newSpanKind,
|
||||
Kind: options.Kind,
|
||||
Attributes: options.Attributes,
|
||||
})
|
||||
ctx = context.WithValue(ctx, ctxActiveSpan{}, newSpanKind)
|
||||
ctx = context.WithValue(ctx, ctxActiveSpan{}, options.Kind)
|
||||
return ctx, func(err error) {
|
||||
if err != nil {
|
||||
errType := strings.Replace(fmt.Sprintf("%T", err), "*exported.", "*azcore.", 1)
|
||||
|
|
31
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_retry.go
сгенерированный
поставляемый
31
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_retry.go
сгенерированный
поставляемый
|
@ -59,13 +59,33 @@ func setDefaults(o *policy.RetryOptions) {
|
|||
}
|
||||
|
||||
func calcDelay(o policy.RetryOptions, try int32) time.Duration { // try is >=1; never 0
|
||||
delay := time.Duration((1<<try)-1) * o.RetryDelay
|
||||
// avoid overflow when shifting left
|
||||
factor := time.Duration(math.MaxInt64)
|
||||
if try < 63 {
|
||||
factor = time.Duration(int64(1<<try) - 1)
|
||||
}
|
||||
|
||||
// Introduce some jitter: [0.0, 1.0) / 2 = [0.0, 0.5) + 0.8 = [0.8, 1.3)
|
||||
delay = time.Duration(delay.Seconds() * (rand.Float64()/2 + 0.8) * float64(time.Second)) // NOTE: We want math/rand; not crypto/rand
|
||||
if delay > o.MaxRetryDelay {
|
||||
delay := factor * o.RetryDelay
|
||||
if delay < factor {
|
||||
// overflow has happened so set to max value
|
||||
delay = time.Duration(math.MaxInt64)
|
||||
}
|
||||
|
||||
// Introduce jitter: [0.0, 1.0) / 2 = [0.0, 0.5) + 0.8 = [0.8, 1.3)
|
||||
jitterMultiplier := rand.Float64()/2 + 0.8 // NOTE: We want math/rand; not crypto/rand
|
||||
|
||||
delayFloat := float64(delay) * jitterMultiplier
|
||||
if delayFloat > float64(math.MaxInt64) {
|
||||
// the jitter pushed us over MaxInt64, so just use MaxInt64
|
||||
delay = time.Duration(math.MaxInt64)
|
||||
} else {
|
||||
delay = time.Duration(delayFloat)
|
||||
}
|
||||
|
||||
if delay > o.MaxRetryDelay { // MaxRetryDelay is backfilled with non-negative value
|
||||
delay = o.MaxRetryDelay
|
||||
}
|
||||
|
||||
return delay
|
||||
}
|
||||
|
||||
|
@ -102,7 +122,8 @@ func (p *retryPolicy) Do(req *policy.Request) (resp *http.Response, err error) {
|
|||
try := int32(1)
|
||||
for {
|
||||
resp = nil // reset
|
||||
log.Writef(log.EventRetryPolicy, "=====> Try=%d", try)
|
||||
// unfortunately we don't have access to the custom allow-list of query params, so we'll redact everything but the default allowed QPs
|
||||
log.Writef(log.EventRetryPolicy, "=====> Try=%d for %s %s", try, req.Raw().Method, getSanitizedURL(*req.Raw().URL, getAllowedQueryParams(nil)))
|
||||
|
||||
// For each try, seek to the beginning of the Body stream. We do this even for the 1st try because
|
||||
// the stream may not be at offset 0 when we first get it and we want the same behavior for the
|
||||
|
|
16
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/request.go
сгенерированный
поставляемый
16
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/request.go
сгенерированный
поставляемый
|
@ -15,6 +15,7 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"net/textproto"
|
||||
"net/url"
|
||||
"path"
|
||||
|
@ -24,6 +25,7 @@ import (
|
|||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/internal/uuid"
|
||||
)
|
||||
|
||||
// Base64Encoding is usesd to specify which base-64 encoder/decoder to use when
|
||||
|
@ -44,6 +46,11 @@ func NewRequest(ctx context.Context, httpMethod string, endpoint string) (*polic
|
|||
return exported.NewRequest(ctx, httpMethod, endpoint)
|
||||
}
|
||||
|
||||
// NewRequestFromRequest creates a new policy.Request with an existing *http.Request
|
||||
func NewRequestFromRequest(req *http.Request) (*policy.Request, error) {
|
||||
return exported.NewRequestFromRequest(req)
|
||||
}
|
||||
|
||||
// EncodeQueryParams will parse and encode any query parameters in the specified URL.
|
||||
// Any semicolons will automatically be escaped.
|
||||
func EncodeQueryParams(u string) (string, error) {
|
||||
|
@ -263,3 +270,12 @@ func SkipBodyDownload(req *policy.Request) {
|
|||
|
||||
// CtxAPINameKey is used as a context key for adding/retrieving the API name.
|
||||
type CtxAPINameKey = shared.CtxAPINameKey
|
||||
|
||||
// NewUUID returns a new UUID using the RFC4122 algorithm.
|
||||
func NewUUID() (string, error) {
|
||||
u, err := uuid.New()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return u.String(), nil
|
||||
}
|
||||
|
|
10
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/BREAKING_CHANGES.md
сгенерированный
поставляемый
Normal file
10
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/BREAKING_CHANGES.md
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,10 @@
|
|||
# Breaking Changes
|
||||
|
||||
## v1.6.0
|
||||
|
||||
### Behavioral change to `DefaultAzureCredential` in IMDS managed identity scenarios
|
||||
|
||||
As of `azidentity` v1.6.0, `DefaultAzureCredential` makes a minor behavioral change when it uses IMDS managed
|
||||
identity. It sends its first request to IMDS without the "Metadata" header, to expedite validating whether the endpoint
|
||||
is available. This precedes the credential's first token request and is guaranteed to fail with a 400 error. This error
|
||||
response can appear in logs but doesn't indicate authentication failed.
|
47
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/CHANGELOG.md
сгенерированный
поставляемый
47
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/CHANGELOG.md
сгенерированный
поставляемый
|
@ -1,5 +1,52 @@
|
|||
# Release History
|
||||
|
||||
## 1.8.0 (2024-10-08)
|
||||
|
||||
### Other Changes
|
||||
* `AzurePipelinesCredential` sets an additional OIDC request header so that it
|
||||
receives a 401 instead of a 302 after presenting an invalid system access token
|
||||
* Allow logging of debugging headers for `AzurePipelinesCredential` and include
|
||||
them in error messages
|
||||
|
||||
## 1.8.0-beta.3 (2024-09-17)
|
||||
|
||||
### Features Added
|
||||
* Added `ObjectID` type for `ManagedIdentityCredentialOptions.ID`
|
||||
|
||||
### Other Changes
|
||||
* Removed redundant content from error messages
|
||||
|
||||
## 1.8.0-beta.2 (2024-08-06)
|
||||
|
||||
### Breaking Changes
|
||||
* `NewManagedIdentityCredential` now returns an error when a user-assigned identity
|
||||
is specified on a platform whose managed identity API doesn't support that.
|
||||
`ManagedIdentityCredential.GetToken()` formerly logged a warning in these cases.
|
||||
Returning an error instead prevents the credential authenticating an unexpected
|
||||
identity, causing a client to act with unexpected privileges. The affected
|
||||
platforms are:
|
||||
* Azure Arc
|
||||
* Azure ML (when a resource ID is specified; client IDs are supported)
|
||||
* Cloud Shell
|
||||
* Service Fabric
|
||||
|
||||
### Other Changes
|
||||
* If `DefaultAzureCredential` receives a non-JSON response when probing IMDS before
|
||||
attempting to authenticate a managed identity, it continues to the next credential
|
||||
in the chain instead of immediately returning an error.
|
||||
|
||||
## 1.8.0-beta.1 (2024-07-17)
|
||||
|
||||
### Features Added
|
||||
* Restored persistent token caching feature
|
||||
|
||||
### Breaking Changes
|
||||
> These changes affect only code written against a beta version such as v1.7.0-beta.1
|
||||
* Redesigned the persistent caching API. Encryption is now required in all cases
|
||||
and persistent cache construction is separate from credential construction.
|
||||
The `PersistentUserAuthentication` example in the package docs has been updated
|
||||
to demonstrate the new API.
|
||||
|
||||
## 1.7.0 (2024-06-20)
|
||||
|
||||
### Features Added
|
||||
|
|
|
@ -54,7 +54,7 @@ The `azidentity` module focuses on OAuth authentication with Microsoft Entra ID.
|
|||
|
||||
### DefaultAzureCredential
|
||||
|
||||
`DefaultAzureCredential` is appropriate for most apps that will be deployed to Azure. It combines common production credentials with development credentials. It attempts to authenticate via the following mechanisms in this order, stopping when one succeeds:
|
||||
`DefaultAzureCredential` simplifies authentication while developing applications that deploy to Azure by combining credentials used in Azure hosting environments and credentials used in local development. In production, it's better to use a specific credential type so authentication is more predictable and easier to debug. `DefaultAzureCredential` attempts to authenticate via the following mechanisms in this order, stopping when one succeeds:
|
||||
|
||||
![DefaultAzureCredential authentication flow](img/mermaidjs/DefaultAzureCredentialAuthFlow.svg)
|
||||
|
||||
|
@ -126,12 +126,17 @@ client := armresources.NewResourceGroupsClient("subscription ID", chain, nil)
|
|||
|
||||
## Credential Types
|
||||
|
||||
### Authenticating Azure Hosted Applications
|
||||
### Credential chains
|
||||
|
||||
|Credential|Usage
|
||||
|-|-
|
||||
|[DefaultAzureCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#DefaultAzureCredential)|Simplified authentication experience for getting started developing Azure apps
|
||||
|[ChainedTokenCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#ChainedTokenCredential)|Define custom authentication flows, composing multiple credentials
|
||||
|
||||
### Authenticating Azure-Hosted Applications
|
||||
|
||||
|Credential|Usage
|
||||
|-|-
|
||||
|[EnvironmentCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#EnvironmentCredential)|Authenticate a service principal or user configured by environment variables
|
||||
|[ManagedIdentityCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#ManagedIdentityCredential)|Authenticate the managed identity of an Azure resource
|
||||
|[WorkloadIdentityCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#WorkloadIdentityCredential)|Authenticate a workload identity on Kubernetes
|
||||
|
@ -158,7 +163,7 @@ client := armresources.NewResourceGroupsClient("subscription ID", chain, nil)
|
|||
|Credential|Usage
|
||||
|-|-
|
||||
|[AzureCLICredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#AzureCLICredential)|Authenticate as the user signed in to the Azure CLI
|
||||
|[`AzureDeveloperCLICredential`](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#AzureDeveloperCLICredential)|Authenticates as the user signed in to the Azure Developer CLI
|
||||
|[AzureDeveloperCLICredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#AzureDeveloperCLICredential)|Authenticates as the user signed in to the Azure Developer CLI
|
||||
|
||||
## Environment Variables
|
||||
|
||||
|
|
50
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TOKEN_CACHING.MD
сгенерированный
поставляемый
50
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TOKEN_CACHING.MD
сгенерированный
поставляемый
|
@ -1,57 +1,40 @@
|
|||
## Token caching in the Azure Identity client module
|
||||
|
||||
*Token caching* is a feature provided by the Azure Identity library that allows apps to:
|
||||
Token caching helps apps:
|
||||
|
||||
- Improve their resilience and performance.
|
||||
- Reduce the number of requests made to Microsoft Entra ID to obtain access tokens.
|
||||
- Reduce the number of times the user is prompted to authenticate.
|
||||
- Reduce the number of requests sent to Microsoft Entra ID to obtain access tokens.
|
||||
- Reduce the number of times users are prompted to authenticate.
|
||||
|
||||
When an app needs to access a protected Azure resource, it typically needs to obtain an access token from Entra ID. Obtaining that token involves sending a request to Entra ID and may also involve prompting the user. Entra ID then validates the credentials provided in the request and issues an access token.
|
||||
When an app needs to access a protected Azure resource, it typically needs to obtain an access token from Entra ID by sending an HTTP request and sometimes prompting a user to authenticate interactively. Credentials with caches (see [the below table](#credentials-supporting-token-caching) for a list) store access tokens either [in memory](#in-memory-token-caching) or, optionally, [on disk](#persistent-token-caching). These credentials return cached tokens whenever possible, to avoid unnecessary token requests or user interaction. Both cache implementations are safe for concurrent use.
|
||||
|
||||
Token caching, via the Azure Identity library, allows the app to store this access token [in memory](#in-memory-token-caching), where it's accessible to the current process, or [on disk](#persistent-token-caching) where it can be accessed across application or process invocations. The token can then be retrieved quickly and easily the next time the app needs to access the same resource. The app can avoid making another request to Entra ID, which reduces network traffic and improves resilience. Additionally, in scenarios where the app is authenticating users, token caching also avoids prompting the user each time new tokens are requested.
|
||||
#### Caching can't be disabled
|
||||
|
||||
Whether a credential caches tokens isn't configurable. If a credential has a cache of either kind, it requests a new token only when it can't provide one from its cache. Azure SDK service clients have an additional, independent layer of in-memory token caching, to prevent redundant token requests. This cache works with any credential type, even a custom implementation defined outside the Azure SDK, and can't be disabled. Disabling token caching is therefore impossible when using Azure SDK clients or most `azidentity` credential types. However, in-memory caches can be cleared by constructing new credential and client instances.
|
||||
|
||||
### In-memory token caching
|
||||
|
||||
*In-memory token caching* is the default option provided by the Azure Identity library. This caching approach allows apps to store access tokens in memory. With in-memory token caching, the library first determines if a valid access token for the requested resource is already stored in memory. If a valid token is found, it's returned to the app without the need to make another request to Entra ID. If a valid token isn't found, the library will automatically acquire a token by sending a request to Entra ID. The in-memory token cache provided by the Azure Identity library is thread-safe.
|
||||
|
||||
**Note:** When Azure Identity library credentials are used with Azure service libraries (for example, Azure Blob Storage), the in-memory token caching is active in the `Pipeline` layer as well. All `TokenCredential` implementations are supported there, including custom implementations external to the Azure Identity library.
|
||||
|
||||
#### Caching cannot be disabled
|
||||
|
||||
As there are many levels of caching, it's not possible disable in-memory caching. However, the in-memory cache may be cleared by creating a new credential instance.
|
||||
Credential types that support caching store tokens in memory by default and require no configuration to do so. Each instance of these types has its own cache, and two credential instances never share an in-memory cache.
|
||||
|
||||
### Persistent token caching
|
||||
|
||||
> Only azidentity v1.5.0-beta versions support persistent token caching
|
||||
Some credential types support opt-in persistent token caching (see [the below table](#credentials-supporting-token-caching) for a list). This feature enables credentials to store and retrieve tokens across process executions, so an application doesn't need to authenticate every time it runs.
|
||||
|
||||
*Persistent disk token caching* is an opt-in feature in the Azure Identity library. The feature allows apps to cache access tokens in an encrypted, persistent storage mechanism. As indicated in the following table, the storage mechanism differs across operating systems.
|
||||
Persistent caches are encrypted at rest using a mechanism that depends on the operating system:
|
||||
|
||||
| Operating system | Storage mechanism |
|
||||
| Operating system | Encryption facility |
|
||||
|------------------|---------------------------------------|
|
||||
| Linux | kernel key retention service (keyctl) |
|
||||
| macOS | Keychain |
|
||||
| Windows | DPAPI |
|
||||
| Windows | Data Protection API (DPAPI) |
|
||||
|
||||
By default the token cache will protect any data which is persisted using the user data protection APIs available on the current platform.
|
||||
However, there are cases where no data protection is available, and applications may choose to allow storing the token cache in an unencrypted state by setting `TokenCachePersistenceOptions.AllowUnencryptedStorage` to `true`. This allows a credential to fall back to unencrypted storage if it can't encrypt the cache. However, we do not recommend using this storage method due to its significantly lower security measures. In addition, tokens are not encrypted solely to the current user, which could potentially allow unauthorized access to the cache by individuals with machine access.
|
||||
|
||||
With persistent disk token caching enabled, the library first determines if a valid access token for the requested resource is already stored in the persistent cache. If a valid token is found, it's returned to the app without the need to make another request to Entra ID. Additionally, the tokens are preserved across app runs, which:
|
||||
|
||||
- Makes the app more resilient to failures.
|
||||
- Ensures the app can continue to function during an Entra ID outage or disruption.
|
||||
- Avoids having to prompt users to authenticate each time the process is restarted.
|
||||
|
||||
>IMPORTANT! The token cache contains sensitive data and **MUST** be protected to prevent compromising accounts. All application decisions regarding the persistence of the token cache must consider that a breach of its content will fully compromise all the accounts it contains.
|
||||
|
||||
#### Example code
|
||||
|
||||
See the [package documentation](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity@v1.6.0-beta.2#pkg-overview) for example code demonstrating how to configure persistent caching and access cached data.
|
||||
Persistent caching requires encryption. When the required encryption facility is unuseable, or the application is running on an unsupported OS, the persistent cache constructor returns an error. This doesn't mean that authentication is impossible, only that credentials can't persist authentication data and the application will need to reauthenticate the next time it runs. See the [package documentation][example] for example code showing how to configure persistent caching and access cached data.
|
||||
|
||||
### Credentials supporting token caching
|
||||
|
||||
The following table indicates the state of in-memory and persistent caching in each credential type.
|
||||
|
||||
**Note:** In-memory caching is activated by default. Persistent token caching needs to be enabled as shown in [this example](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity@v1.5.0-beta.1#example-package-PersistentCache).
|
||||
**Note:** in-memory caching is enabled by default for every type supporting it. Persistent token caching must be enabled explicitly. See the [package documentation][user_example] for an example showing how to do this for credential types authenticating users. For types that authenticate service principals, set the `Cache` field on the constructor's options as shown in [this example][sp_example].
|
||||
|
||||
| Credential | In-memory token caching | Persistent token caching |
|
||||
|--------------------------------|---------------------------------------------------------------------|--------------------------|
|
||||
|
@ -66,6 +49,9 @@ The following table indicates the state of in-memory and persistent caching in e
|
|||
| `EnvironmentCredential` | Supported | Not Supported |
|
||||
| `InteractiveBrowserCredential` | Supported | Supported |
|
||||
| `ManagedIdentityCredential` | Supported | Not Supported |
|
||||
| `OnBehalfOfCredential` | Supported | Supported |
|
||||
| `OnBehalfOfCredential` | Supported | Not Supported |
|
||||
| `UsernamePasswordCredential` | Supported | Supported |
|
||||
| `WorkloadIdentityCredential` | Supported | Supported |
|
||||
|
||||
[sp_example]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#example-package-PersistentServicePrincipalAuthentication
|
||||
[user_example]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#example-package-PersistentUserAuthentication
|
||||
|
|
2
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TROUBLESHOOTING.md
сгенерированный
поставляемый
2
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TROUBLESHOOTING.md
сгенерированный
поставляемый
|
@ -234,7 +234,7 @@ azd auth token --output json --scope https://management.core.windows.net/.defaul
|
|||
|---|---|---|
|
||||
| AADSTS900023: Specified tenant identifier 'some tenant ID' is neither a valid DNS name, nor a valid external domain.|The `tenantID` argument to `NewAzurePipelinesCredential` is incorrect| Verify the tenant ID. It must identify the tenant of the user-assigned managed identity or service principal configured for the service connection.|
|
||||
| No service connection found with identifier |The `serviceConnectionID` argument to `NewAzurePipelinesCredential` is incorrect| Verify the service connection ID. This parameter refers to the `resourceId` of the Azure Service Connection. It can also be found in the query string of the service connection's configuration in Azure DevOps. [Azure Pipelines documentation](https://learn.microsoft.com/azure/devops/pipelines/library/service-endpoints?view=azure-devops&tabs=yaml) has more information about service connections.|
|
||||
|302 (Found) response from OIDC endpoint|The `systemAccessToken` argument to `NewAzurePipelinesCredential` is incorrect|Check pipeline configuration. This value comes from the predefined variable `System.AccessToken` [as described in Azure Pipelines documentation](https://learn.microsoft.com/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml#systemaccesstoken).|
|
||||
|401 (Unauthorized) response from OIDC endpoint|The `systemAccessToken` argument to `NewAzurePipelinesCredential` is incorrect|Check pipeline configuration. This value comes from the predefined variable `System.AccessToken` [as described in Azure Pipelines documentation](https://learn.microsoft.com/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml#systemaccesstoken).|
|
||||
|
||||
## Get additional help
|
||||
|
||||
|
|
|
@ -2,5 +2,5 @@
|
|||
"AssetsRepo": "Azure/azure-sdk-assets",
|
||||
"AssetsRepoPrefixPath": "go",
|
||||
"TagPrefix": "go/azidentity",
|
||||
"Tag": "go/azidentity_087379b475"
|
||||
"Tag": "go/azidentity_c55452bbf6"
|
||||
}
|
||||
|
|
18
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/authentication_record.go
сгенерированный
поставляемый
18
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/authentication_record.go
сгенерированный
поставляемый
|
@ -18,10 +18,10 @@ import (
|
|||
|
||||
var supportedAuthRecordVersions = []string{"1.0"}
|
||||
|
||||
// authenticationRecord is non-secret account information about an authenticated user that user credentials such as
|
||||
// AuthenticationRecord is non-secret account information about an authenticated user that user credentials such as
|
||||
// [DeviceCodeCredential] and [InteractiveBrowserCredential] can use to access previously cached authentication
|
||||
// data. Call these credentials' Authenticate method to get an authenticationRecord for a user.
|
||||
type authenticationRecord struct {
|
||||
// data. Call these credentials' Authenticate method to get an AuthenticationRecord for a user.
|
||||
type AuthenticationRecord struct {
|
||||
// Authority is the URL of the authority that issued the token.
|
||||
Authority string `json:"authority"`
|
||||
|
||||
|
@ -42,11 +42,11 @@ type authenticationRecord struct {
|
|||
}
|
||||
|
||||
// UnmarshalJSON implements json.Unmarshaler for AuthenticationRecord
|
||||
func (a *authenticationRecord) UnmarshalJSON(b []byte) error {
|
||||
func (a *AuthenticationRecord) UnmarshalJSON(b []byte) error {
|
||||
// Default unmarshaling is fine but we want to return an error if the record's version isn't supported i.e., we
|
||||
// want to inspect the unmarshalled values before deciding whether to return an error. Unmarshaling a formally
|
||||
// different type enables this by assigning all the fields without recursing into this method.
|
||||
type r authenticationRecord
|
||||
type r AuthenticationRecord
|
||||
err := json.Unmarshal(b, (*r)(a))
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -63,7 +63,7 @@ func (a *authenticationRecord) UnmarshalJSON(b []byte) error {
|
|||
}
|
||||
|
||||
// account returns the AuthenticationRecord as an MSAL Account. The account is zero-valued when the AuthenticationRecord is zero-valued.
|
||||
func (a *authenticationRecord) account() public.Account {
|
||||
func (a *AuthenticationRecord) account() public.Account {
|
||||
return public.Account{
|
||||
Environment: a.Authority,
|
||||
HomeAccountID: a.HomeAccountID,
|
||||
|
@ -71,10 +71,10 @@ func (a *authenticationRecord) account() public.Account {
|
|||
}
|
||||
}
|
||||
|
||||
func newAuthenticationRecord(ar public.AuthResult) (authenticationRecord, error) {
|
||||
func newAuthenticationRecord(ar public.AuthResult) (AuthenticationRecord, error) {
|
||||
u, err := url.Parse(ar.IDToken.Issuer)
|
||||
if err != nil {
|
||||
return authenticationRecord{}, fmt.Errorf("Authenticate expected a URL issuer but got %q", ar.IDToken.Issuer)
|
||||
return AuthenticationRecord{}, fmt.Errorf("Authenticate expected a URL issuer but got %q", ar.IDToken.Issuer)
|
||||
}
|
||||
tenant := ar.IDToken.TenantID
|
||||
if tenant == "" {
|
||||
|
@ -84,7 +84,7 @@ func newAuthenticationRecord(ar public.AuthResult) (authenticationRecord, error)
|
|||
if username == "" {
|
||||
username = ar.IDToken.UPN
|
||||
}
|
||||
return authenticationRecord{
|
||||
return AuthenticationRecord{
|
||||
Authority: fmt.Sprintf("%s://%s", u.Scheme, u.Host),
|
||||
ClientID: ar.IDToken.Audience,
|
||||
HomeAccountID: ar.Account.HomeAccountID,
|
||||
|
|
10
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azidentity.go
сгенерированный
поставляемый
10
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azidentity.go
сгенерированный
поставляемый
|
@ -53,8 +53,14 @@ var (
|
|||
errInvalidTenantID = errors.New("invalid tenantID. You can locate your tenantID by following the instructions listed here: https://learn.microsoft.com/partner-center/find-ids-and-domain-names")
|
||||
)
|
||||
|
||||
// tokenCachePersistenceOptions contains options for persistent token caching
|
||||
type tokenCachePersistenceOptions = internal.TokenCachePersistenceOptions
|
||||
// Cache represents a persistent cache that makes authentication data available across processes.
|
||||
// Construct one with [github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache.New]. This package's
|
||||
// [persistent user authentication example] shows how to use a persistent cache to reuse user
|
||||
// logins across application runs. For service principal credential types such as
|
||||
// [ClientCertificateCredential], simply set the Cache field on the credential options.
|
||||
//
|
||||
// [persistent user authentication example]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#example-package-PersistentUserAuthentication
|
||||
type Cache = internal.Cache
|
||||
|
||||
// setAuthorityHost initializes the authority host for credentials. Precedence is:
|
||||
// 1. cloud.Configuration.ActiveDirectoryAuthorityHost value set by user
|
||||
|
|
31
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azure_pipelines_credential.go
сгенерированный
поставляемый
31
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azure_pipelines_credential.go
сгенерированный
поставляемый
|
@ -20,6 +20,8 @@ const (
|
|||
credNameAzurePipelines = "AzurePipelinesCredential"
|
||||
oidcAPIVersion = "7.1"
|
||||
systemOIDCRequestURI = "SYSTEM_OIDCREQUESTURI"
|
||||
xMsEdgeRef = "x-msedge-ref"
|
||||
xVssE2eId = "x-vss-e2eid"
|
||||
)
|
||||
|
||||
// AzurePipelinesCredential authenticates with workload identity federation in an Azure Pipeline. See
|
||||
|
@ -40,6 +42,11 @@ type AzurePipelinesCredentialOptions struct {
|
|||
// application is registered.
|
||||
AdditionallyAllowedTenants []string
|
||||
|
||||
// Cache is a persistent cache the credential will use to store the tokens it acquires, making
|
||||
// them available to other processes and credential instances. The default, zero value means the
|
||||
// credential will store tokens in memory and not share them with any other credential instance.
|
||||
Cache Cache
|
||||
|
||||
// DisableInstanceDiscovery should be set true only by applications authenticating in disconnected clouds, or
|
||||
// private clouds such as Azure Stack. It determines whether the credential requests Microsoft Entra instance metadata
|
||||
// from https://login.microsoft.com before authenticating. Setting this to true will skip this request, making
|
||||
|
@ -81,8 +88,11 @@ func NewAzurePipelinesCredential(tenantID, clientID, serviceConnectionID, system
|
|||
if options == nil {
|
||||
options = &AzurePipelinesCredentialOptions{}
|
||||
}
|
||||
// these headers are useful to the DevOps team when debugging OIDC error responses
|
||||
options.ClientOptions.Logging.AllowedHeaders = append(options.ClientOptions.Logging.AllowedHeaders, xMsEdgeRef, xVssE2eId)
|
||||
caco := ClientAssertionCredentialOptions{
|
||||
AdditionallyAllowedTenants: options.AdditionallyAllowedTenants,
|
||||
Cache: options.Cache,
|
||||
ClientOptions: options.ClientOptions,
|
||||
DisableInstanceDiscovery: options.DisableInstanceDiscovery,
|
||||
}
|
||||
|
@ -108,33 +118,40 @@ func (a *AzurePipelinesCredential) getAssertion(ctx context.Context) (string, er
|
|||
url := a.oidcURI + "?api-version=" + oidcAPIVersion + "&serviceConnectionId=" + a.connectionID
|
||||
url, err := runtime.EncodeQueryParams(url)
|
||||
if err != nil {
|
||||
return "", newAuthenticationFailedError(credNameAzurePipelines, "couldn't encode OIDC URL: "+err.Error(), nil, nil)
|
||||
return "", newAuthenticationFailedError(credNameAzurePipelines, "couldn't encode OIDC URL: "+err.Error(), nil)
|
||||
}
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, nil)
|
||||
if err != nil {
|
||||
return "", newAuthenticationFailedError(credNameAzurePipelines, "couldn't create OIDC token request: "+err.Error(), nil, nil)
|
||||
return "", newAuthenticationFailedError(credNameAzurePipelines, "couldn't create OIDC token request: "+err.Error(), nil)
|
||||
}
|
||||
req.Header.Set("Authorization", "Bearer "+a.systemAccessToken)
|
||||
// instruct endpoint to return 401 instead of 302, if the system access token is invalid
|
||||
req.Header.Set("X-TFS-FedAuthRedirect", "Suppress")
|
||||
res, err := doForClient(a.cred.client.azClient, req)
|
||||
if err != nil {
|
||||
return "", newAuthenticationFailedError(credNameAzurePipelines, "couldn't send OIDC token request: "+err.Error(), nil, nil)
|
||||
return "", newAuthenticationFailedError(credNameAzurePipelines, "couldn't send OIDC token request: "+err.Error(), nil)
|
||||
}
|
||||
if res.StatusCode != http.StatusOK {
|
||||
msg := res.Status + " response from the OIDC endpoint. Check service connection ID and Pipeline configuration"
|
||||
msg := res.Status + " response from the OIDC endpoint. Check service connection ID and Pipeline configuration."
|
||||
for _, h := range []string{xMsEdgeRef, xVssE2eId} {
|
||||
if v := res.Header.Get(h); v != "" {
|
||||
msg += fmt.Sprintf("\n%s: %s", h, v)
|
||||
}
|
||||
}
|
||||
// include the response because its body, if any, probably contains an error message.
|
||||
// OK responses aren't included with errors because they probably contain secrets
|
||||
return "", newAuthenticationFailedError(credNameAzurePipelines, msg, res, nil)
|
||||
return "", newAuthenticationFailedError(credNameAzurePipelines, msg, res)
|
||||
}
|
||||
b, err := runtime.Payload(res)
|
||||
if err != nil {
|
||||
return "", newAuthenticationFailedError(credNameAzurePipelines, "couldn't read OIDC response content: "+err.Error(), nil, nil)
|
||||
return "", newAuthenticationFailedError(credNameAzurePipelines, "couldn't read OIDC response content: "+err.Error(), nil)
|
||||
}
|
||||
var r struct {
|
||||
OIDCToken string `json:"oidcToken"`
|
||||
}
|
||||
err = json.Unmarshal(b, &r)
|
||||
if err != nil {
|
||||
return "", newAuthenticationFailedError(credNameAzurePipelines, "unexpected response from OIDC endpoint", nil, nil)
|
||||
return "", newAuthenticationFailedError(credNameAzurePipelines, "unexpected response from OIDC endpoint", nil)
|
||||
}
|
||||
return r.OIDCToken, nil
|
||||
}
|
||||
|
|
16
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/chained_token_credential.go
сгенерированный
поставляемый
16
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/chained_token_credential.go
сгенерированный
поставляемый
|
@ -113,11 +113,19 @@ func (c *ChainedTokenCredential) GetToken(ctx context.Context, opts policy.Token
|
|||
if err != nil {
|
||||
// return credentialUnavailableError iff all sources did so; return AuthenticationFailedError otherwise
|
||||
msg := createChainedErrorMessage(errs)
|
||||
if errors.As(err, &unavailableErr) {
|
||||
var authFailedErr *AuthenticationFailedError
|
||||
switch {
|
||||
case errors.As(err, &authFailedErr):
|
||||
err = newAuthenticationFailedError(c.name, msg, authFailedErr.RawResponse)
|
||||
if af, ok := err.(*AuthenticationFailedError); ok {
|
||||
// stop Error() printing the response again; it's already in msg
|
||||
af.omitResponse = true
|
||||
}
|
||||
case errors.As(err, &unavailableErr):
|
||||
err = newCredentialUnavailableError(c.name, msg)
|
||||
} else {
|
||||
default:
|
||||
res := getResponseFromError(err)
|
||||
err = newAuthenticationFailedError(c.name, msg, res, err)
|
||||
err = newAuthenticationFailedError(c.name, msg, res)
|
||||
}
|
||||
}
|
||||
return token, err
|
||||
|
@ -126,7 +134,7 @@ func (c *ChainedTokenCredential) GetToken(ctx context.Context, opts policy.Token
|
|||
func createChainedErrorMessage(errs []error) string {
|
||||
msg := "failed to acquire a token.\nAttempted credentials:"
|
||||
for _, err := range errs {
|
||||
msg += fmt.Sprintf("\n\t%s", err.Error())
|
||||
msg += fmt.Sprintf("\n\t%s", strings.ReplaceAll(err.Error(), "\n", "\n\t\t"))
|
||||
}
|
||||
return msg
|
||||
}
|
||||
|
|
|
@ -26,16 +26,27 @@ extends:
|
|||
parameters:
|
||||
CloudConfig:
|
||||
Public:
|
||||
ServiceConnection: azure-sdk-tests
|
||||
SubscriptionConfigurationFilePaths:
|
||||
- eng/common/TestResources/sub-config/AzurePublicMsft.json
|
||||
SubscriptionConfigurations:
|
||||
- $(sub-config-azure-cloud-test-resources)
|
||||
- $(sub-config-identity-test-resources)
|
||||
EnvVars:
|
||||
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
||||
EnableRaceDetector: true
|
||||
RunLiveTests: true
|
||||
ServiceDirectory: azidentity
|
||||
UsePipelineProxy: false
|
||||
|
||||
${{ if endsWith(variables['Build.DefinitionName'], 'weekly') }}:
|
||||
PreSteps:
|
||||
- task: AzureCLI@2
|
||||
displayName: Set OIDC token
|
||||
inputs:
|
||||
addSpnToEnvironment: true
|
||||
azureSubscription: azure-sdk-tests
|
||||
inlineScript: Write-Host "##vso[task.setvariable variable=OIDC_TOKEN;]$($env:idToken)"
|
||||
scriptLocation: inlineScript
|
||||
scriptType: pscore
|
||||
MatrixConfigs:
|
||||
- Name: managed_identity_matrix
|
||||
GenerateVMJobs: true
|
||||
|
|
16
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/client_assertion_credential.go
сгенерированный
поставляемый
16
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/client_assertion_credential.go
сгенерированный
поставляемый
|
@ -37,14 +37,16 @@ type ClientAssertionCredentialOptions struct {
|
|||
// application is registered.
|
||||
AdditionallyAllowedTenants []string
|
||||
|
||||
// Cache is a persistent cache the credential will use to store the tokens it acquires, making
|
||||
// them available to other processes and credential instances. The default, zero value means the
|
||||
// credential will store tokens in memory and not share them with any other credential instance.
|
||||
Cache Cache
|
||||
|
||||
// DisableInstanceDiscovery should be set true only by applications authenticating in disconnected clouds, or
|
||||
// private clouds such as Azure Stack. It determines whether the credential requests Microsoft Entra instance metadata
|
||||
// from https://login.microsoft.com before authenticating. Setting this to true will skip this request, making
|
||||
// the application responsible for ensuring the configured authority is valid and trustworthy.
|
||||
DisableInstanceDiscovery bool
|
||||
|
||||
// tokenCachePersistenceOptions enables persistent token caching when not nil.
|
||||
tokenCachePersistenceOptions *tokenCachePersistenceOptions
|
||||
}
|
||||
|
||||
// NewClientAssertionCredential constructs a ClientAssertionCredential. The getAssertion function must be thread safe. Pass nil for options to accept defaults.
|
||||
|
@ -61,10 +63,10 @@ func NewClientAssertionCredential(tenantID, clientID string, getAssertion func(c
|
|||
},
|
||||
)
|
||||
msalOpts := confidentialClientOptions{
|
||||
AdditionallyAllowedTenants: options.AdditionallyAllowedTenants,
|
||||
ClientOptions: options.ClientOptions,
|
||||
DisableInstanceDiscovery: options.DisableInstanceDiscovery,
|
||||
tokenCachePersistenceOptions: options.tokenCachePersistenceOptions,
|
||||
AdditionallyAllowedTenants: options.AdditionallyAllowedTenants,
|
||||
Cache: options.Cache,
|
||||
ClientOptions: options.ClientOptions,
|
||||
DisableInstanceDiscovery: options.DisableInstanceDiscovery,
|
||||
}
|
||||
c, err := newConfidentialClient(tenantID, clientID, credNameAssertion, cred, msalOpts)
|
||||
if err != nil {
|
||||
|
|
18
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/client_certificate_credential.go
сгенерированный
поставляемый
18
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/client_certificate_credential.go
сгенерированный
поставляемый
|
@ -31,6 +31,11 @@ type ClientCertificateCredentialOptions struct {
|
|||
// application is registered.
|
||||
AdditionallyAllowedTenants []string
|
||||
|
||||
// Cache is a persistent cache the credential will use to store the tokens it acquires, making
|
||||
// them available to other processes and credential instances. The default, zero value means the
|
||||
// credential will store tokens in memory and not share them with any other credential instance.
|
||||
Cache Cache
|
||||
|
||||
// DisableInstanceDiscovery should be set true only by applications authenticating in disconnected clouds, or
|
||||
// private clouds such as Azure Stack. It determines whether the credential requests Microsoft Entra instance metadata
|
||||
// from https://login.microsoft.com before authenticating. Setting this to true will skip this request, making
|
||||
|
@ -41,9 +46,6 @@ type ClientCertificateCredentialOptions struct {
|
|||
// header of each token request's JWT. This is required for Subject Name/Issuer (SNI) authentication.
|
||||
// Defaults to False.
|
||||
SendCertificateChain bool
|
||||
|
||||
// tokenCachePersistenceOptions enables persistent token caching when not nil.
|
||||
tokenCachePersistenceOptions *tokenCachePersistenceOptions
|
||||
}
|
||||
|
||||
// ClientCertificateCredential authenticates a service principal with a certificate.
|
||||
|
@ -65,11 +67,11 @@ func NewClientCertificateCredential(tenantID string, clientID string, certs []*x
|
|||
return nil, err
|
||||
}
|
||||
msalOpts := confidentialClientOptions{
|
||||
AdditionallyAllowedTenants: options.AdditionallyAllowedTenants,
|
||||
ClientOptions: options.ClientOptions,
|
||||
DisableInstanceDiscovery: options.DisableInstanceDiscovery,
|
||||
SendX5C: options.SendCertificateChain,
|
||||
tokenCachePersistenceOptions: options.tokenCachePersistenceOptions,
|
||||
AdditionallyAllowedTenants: options.AdditionallyAllowedTenants,
|
||||
Cache: options.Cache,
|
||||
ClientOptions: options.ClientOptions,
|
||||
DisableInstanceDiscovery: options.DisableInstanceDiscovery,
|
||||
SendX5C: options.SendCertificateChain,
|
||||
}
|
||||
c, err := newConfidentialClient(tenantID, clientID, credNameCert, cred, msalOpts)
|
||||
if err != nil {
|
||||
|
|
14
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/client_secret_credential.go
сгенерированный
поставляемый
14
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/client_secret_credential.go
сгенерированный
поставляемый
|
@ -32,8 +32,10 @@ type ClientSecretCredentialOptions struct {
|
|||
// the application responsible for ensuring the configured authority is valid and trustworthy.
|
||||
DisableInstanceDiscovery bool
|
||||
|
||||
// tokenCachePersistenceOptions enables persistent token caching when not nil.
|
||||
tokenCachePersistenceOptions *tokenCachePersistenceOptions
|
||||
// Cache is a persistent cache the credential will use to store the tokens it acquires, making
|
||||
// them available to other processes and credential instances. The default, zero value means the
|
||||
// credential will store tokens in memory and not share them with any other credential instance.
|
||||
Cache Cache
|
||||
}
|
||||
|
||||
// ClientSecretCredential authenticates an application with a client secret.
|
||||
|
@ -51,10 +53,10 @@ func NewClientSecretCredential(tenantID string, clientID string, clientSecret st
|
|||
return nil, err
|
||||
}
|
||||
msalOpts := confidentialClientOptions{
|
||||
AdditionallyAllowedTenants: options.AdditionallyAllowedTenants,
|
||||
ClientOptions: options.ClientOptions,
|
||||
DisableInstanceDiscovery: options.DisableInstanceDiscovery,
|
||||
tokenCachePersistenceOptions: options.tokenCachePersistenceOptions,
|
||||
AdditionallyAllowedTenants: options.AdditionallyAllowedTenants,
|
||||
Cache: options.Cache,
|
||||
ClientOptions: options.ClientOptions,
|
||||
DisableInstanceDiscovery: options.DisableInstanceDiscovery,
|
||||
}
|
||||
c, err := newConfidentialClient(tenantID, clientID, credNameSecret, cred, msalOpts)
|
||||
if err != nil {
|
||||
|
|
16
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/confidential_client.go
сгенерированный
поставляемый
16
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/confidential_client.go
сгенерированный
поставляемый
|
@ -29,8 +29,8 @@ type confidentialClientOptions struct {
|
|||
AdditionallyAllowedTenants []string
|
||||
// Assertion for on-behalf-of authentication
|
||||
Assertion string
|
||||
Cache Cache
|
||||
DisableInstanceDiscovery, SendX5C bool
|
||||
tokenCachePersistenceOptions *tokenCachePersistenceOptions
|
||||
}
|
||||
|
||||
// confidentialClient wraps the MSAL confidential client
|
||||
|
@ -107,12 +107,12 @@ func (c *confidentialClient) GetToken(ctx context.Context, tro policy.TokenReque
|
|||
}
|
||||
}
|
||||
if err != nil {
|
||||
// We could get a credentialUnavailableError from managed identity authentication because in that case the error comes from our code.
|
||||
// We return it directly because it affects the behavior of credential chains. Otherwise, we return AuthenticationFailedError.
|
||||
var unavailableErr credentialUnavailable
|
||||
if !errors.As(err, &unavailableErr) {
|
||||
res := getResponseFromError(err)
|
||||
err = newAuthenticationFailedError(c.name, err.Error(), res, err)
|
||||
var (
|
||||
authFailedErr *AuthenticationFailedError
|
||||
unavailableErr credentialUnavailable
|
||||
)
|
||||
if !(errors.As(err, &unavailableErr) || errors.As(err, &authFailedErr)) {
|
||||
err = newAuthenticationFailedErrorFromMSAL(c.name, err)
|
||||
}
|
||||
} else {
|
||||
msg := fmt.Sprintf("%s.GetToken() acquired a token for scope %q", c.name, strings.Join(ar.GrantedScopes, ", "))
|
||||
|
@ -145,7 +145,7 @@ func (c *confidentialClient) client(tro policy.TokenRequestOptions) (msalConfide
|
|||
}
|
||||
|
||||
func (c *confidentialClient) newMSALClient(enableCAE bool) (msalConfidentialClient, error) {
|
||||
cache, err := internal.NewCache(c.opts.tokenCachePersistenceOptions, enableCAE)
|
||||
cache, err := internal.ExportReplace(c.opts.Cache, enableCAE)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
11
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/default_azure_credential.go
сгенерированный
поставляемый
11
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/default_azure_credential.go
сгенерированный
поставляемый
|
@ -36,10 +36,13 @@ type DefaultAzureCredentialOptions struct {
|
|||
TenantID string
|
||||
}
|
||||
|
||||
// DefaultAzureCredential is a default credential chain for applications that will deploy to Azure.
|
||||
// It combines credentials suitable for deployment with credentials suitable for local development.
|
||||
// It attempts to authenticate with each of these credential types, in the following order, stopping
|
||||
// when one provides a token:
|
||||
// DefaultAzureCredential simplifies authentication while developing applications that deploy to Azure by
|
||||
// combining credentials used in Azure hosting environments and credentials used in local development. In
|
||||
// production, it's better to use a specific credential type so authentication is more predictable and easier
|
||||
// to debug.
|
||||
//
|
||||
// DefaultAzureCredential attempts to authenticate with each of these credential types, in the following order,
|
||||
// stopping when one provides a token:
|
||||
//
|
||||
// - [EnvironmentCredential]
|
||||
// - [WorkloadIdentityCredential], if environment variable configuration is set by the Azure workload
|
||||
|
|
36
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/device_code_credential.go
сгенерированный
поставляемый
36
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/device_code_credential.go
сгенерированный
поставляемый
|
@ -25,18 +25,26 @@ type DeviceCodeCredentialOptions struct {
|
|||
// tokens. Add the wildcard value "*" to allow the credential to acquire tokens for any tenant.
|
||||
AdditionallyAllowedTenants []string
|
||||
|
||||
// authenticationRecord returned by a call to a credential's Authenticate method. Set this option
|
||||
// AuthenticationRecord returned by a call to a credential's Authenticate method. Set this option
|
||||
// to enable the credential to use data from a previous authentication.
|
||||
authenticationRecord authenticationRecord
|
||||
AuthenticationRecord AuthenticationRecord
|
||||
|
||||
// ClientID is the ID of the application users will authenticate to.
|
||||
// Defaults to the ID of an Azure development application.
|
||||
// Cache is a persistent cache the credential will use to store the tokens it acquires, making
|
||||
// them available to other processes and credential instances. The default, zero value means the
|
||||
// credential will store tokens in memory and not share them with any other credential instance.
|
||||
Cache Cache
|
||||
|
||||
// ClientID is the ID of the application to which users will authenticate. When not set, users
|
||||
// will authenticate to an Azure development application, which isn't recommended for production
|
||||
// scenarios. In production, developers should instead register their applications and assign
|
||||
// appropriate roles. See https://aka.ms/azsdk/identity/AppRegistrationAndRoleAssignment for more
|
||||
// information.
|
||||
ClientID string
|
||||
|
||||
// disableAutomaticAuthentication prevents the credential from automatically prompting the user to authenticate.
|
||||
// When this option is true, GetToken will return authenticationRequiredError when user interaction is necessary
|
||||
// DisableAutomaticAuthentication prevents the credential from automatically prompting the user to authenticate.
|
||||
// When this option is true, GetToken will return AuthenticationRequiredError when user interaction is necessary
|
||||
// to acquire a token.
|
||||
disableAutomaticAuthentication bool
|
||||
DisableAutomaticAuthentication bool
|
||||
|
||||
// DisableInstanceDiscovery should be set true only by applications authenticating in disconnected clouds, or
|
||||
// private clouds such as Azure Stack. It determines whether the credential requests Microsoft Entra instance metadata
|
||||
|
@ -49,9 +57,6 @@ type DeviceCodeCredentialOptions struct {
|
|||
// applications.
|
||||
TenantID string
|
||||
|
||||
// tokenCachePersistenceOptions enables persistent token caching when not nil.
|
||||
tokenCachePersistenceOptions *tokenCachePersistenceOptions
|
||||
|
||||
// UserPrompt controls how the credential presents authentication instructions. The credential calls
|
||||
// this function with authentication details when it receives a device code. By default, the credential
|
||||
// prints these details to stdout.
|
||||
|
@ -101,12 +106,12 @@ func NewDeviceCodeCredential(options *DeviceCodeCredentialOptions) (*DeviceCodeC
|
|||
cp.init()
|
||||
msalOpts := publicClientOptions{
|
||||
AdditionallyAllowedTenants: cp.AdditionallyAllowedTenants,
|
||||
Cache: cp.Cache,
|
||||
ClientOptions: cp.ClientOptions,
|
||||
DeviceCodePrompt: cp.UserPrompt,
|
||||
DisableAutomaticAuthentication: cp.disableAutomaticAuthentication,
|
||||
DisableAutomaticAuthentication: cp.DisableAutomaticAuthentication,
|
||||
DisableInstanceDiscovery: cp.DisableInstanceDiscovery,
|
||||
Record: cp.authenticationRecord,
|
||||
TokenCachePersistenceOptions: cp.tokenCachePersistenceOptions,
|
||||
Record: cp.AuthenticationRecord,
|
||||
}
|
||||
c, err := newPublicClient(cp.TenantID, cp.ClientID, credNameDeviceCode, msalOpts)
|
||||
if err != nil {
|
||||
|
@ -116,8 +121,9 @@ func NewDeviceCodeCredential(options *DeviceCodeCredentialOptions) (*DeviceCodeC
|
|||
return &DeviceCodeCredential{client: c}, nil
|
||||
}
|
||||
|
||||
// Authenticate a user via the device code flow. Subsequent calls to GetToken will automatically use the returned AuthenticationRecord.
|
||||
func (c *DeviceCodeCredential) authenticate(ctx context.Context, opts *policy.TokenRequestOptions) (authenticationRecord, error) {
|
||||
// Authenticate prompts a user to log in via the device code flow. Subsequent
|
||||
// GetToken calls will automatically use the returned AuthenticationRecord.
|
||||
func (c *DeviceCodeCredential) Authenticate(ctx context.Context, opts *policy.TokenRequestOptions) (AuthenticationRecord, error) {
|
||||
var err error
|
||||
ctx, endSpan := runtime.StartSpan(ctx, credNameDeviceCode+"."+traceOpAuthenticate, c.client.azClient.Tracer(), nil)
|
||||
defer func() { endSpan(err) }()
|
||||
|
|
|
@ -38,18 +38,30 @@ type AuthenticationFailedError struct {
|
|||
// RawResponse is the HTTP response motivating the error, if available.
|
||||
RawResponse *http.Response
|
||||
|
||||
credType string
|
||||
message string
|
||||
err error
|
||||
credType, message string
|
||||
omitResponse bool
|
||||
}
|
||||
|
||||
func newAuthenticationFailedError(credType string, message string, resp *http.Response, err error) error {
|
||||
return &AuthenticationFailedError{credType: credType, message: message, RawResponse: resp, err: err}
|
||||
func newAuthenticationFailedError(credType, message string, resp *http.Response) error {
|
||||
return &AuthenticationFailedError{credType: credType, message: message, RawResponse: resp}
|
||||
}
|
||||
|
||||
// newAuthenticationFailedErrorFromMSAL creates an AuthenticationFailedError from an MSAL error.
|
||||
// If the error is an MSAL CallErr, the new error includes an HTTP response and not the MSAL error
|
||||
// message, because that message is redundant given the response. If the original error isn't a
|
||||
// CallErr, the returned error incorporates its message.
|
||||
func newAuthenticationFailedErrorFromMSAL(credType string, err error) error {
|
||||
msg := ""
|
||||
res := getResponseFromError(err)
|
||||
if res == nil {
|
||||
msg = err.Error()
|
||||
}
|
||||
return newAuthenticationFailedError(credType, msg, res)
|
||||
}
|
||||
|
||||
// Error implements the error interface. Note that the message contents are not contractual and can change over time.
|
||||
func (e *AuthenticationFailedError) Error() string {
|
||||
if e.RawResponse == nil {
|
||||
if e.RawResponse == nil || e.omitResponse {
|
||||
return e.credType + ": " + e.message
|
||||
}
|
||||
msg := &bytes.Buffer{}
|
||||
|
@ -62,7 +74,7 @@ func (e *AuthenticationFailedError) Error() string {
|
|||
fmt.Fprintln(msg, "Request information not available")
|
||||
}
|
||||
fmt.Fprintln(msg, "--------------------------------------------------------------------------------")
|
||||
fmt.Fprintf(msg, "RESPONSE %s\n", e.RawResponse.Status)
|
||||
fmt.Fprintf(msg, "RESPONSE %d: %s\n", e.RawResponse.StatusCode, e.RawResponse.Status)
|
||||
fmt.Fprintln(msg, "--------------------------------------------------------------------------------")
|
||||
body, err := runtime.Payload(e.RawResponse)
|
||||
switch {
|
||||
|
@ -109,17 +121,17 @@ func (*AuthenticationFailedError) NonRetriable() {
|
|||
|
||||
var _ errorinfo.NonRetriable = (*AuthenticationFailedError)(nil)
|
||||
|
||||
// authenticationRequiredError indicates a credential's Authenticate method must be called to acquire a token
|
||||
// AuthenticationRequiredError indicates a credential's Authenticate method must be called to acquire a token
|
||||
// because the credential requires user interaction and is configured not to request it automatically.
|
||||
type authenticationRequiredError struct {
|
||||
type AuthenticationRequiredError struct {
|
||||
credentialUnavailableError
|
||||
|
||||
// TokenRequestOptions for the required token. Pass this to the credential's Authenticate method.
|
||||
TokenRequestOptions policy.TokenRequestOptions
|
||||
}
|
||||
|
||||
func newauthenticationRequiredError(credType string, tro policy.TokenRequestOptions) error {
|
||||
return &authenticationRequiredError{
|
||||
func newAuthenticationRequiredError(credType string, tro policy.TokenRequestOptions) error {
|
||||
return &AuthenticationRequiredError{
|
||||
credentialUnavailableError: credentialUnavailableError{
|
||||
credType + " can't acquire a token without user interaction. Call Authenticate to authenticate a user interactively",
|
||||
},
|
||||
|
@ -128,8 +140,8 @@ func newauthenticationRequiredError(credType string, tro policy.TokenRequestOpti
|
|||
}
|
||||
|
||||
var (
|
||||
_ credentialUnavailable = (*authenticationRequiredError)(nil)
|
||||
_ errorinfo.NonRetriable = (*authenticationRequiredError)(nil)
|
||||
_ credentialUnavailable = (*AuthenticationRequiredError)(nil)
|
||||
_ errorinfo.NonRetriable = (*AuthenticationRequiredError)(nil)
|
||||
)
|
||||
|
||||
type credentialUnavailable interface {
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0-beta.1 h1:ODs3brnqQM99Tq1PffODpAViYv3Bf8zOg464MU7p5ew=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0-beta.1/go.mod h1:3Ug6Qzto9anB6mGlEdgYMDF5zHQ+wwhEaYR4s17PHMw=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0 h1:fb8kj/Dh4CSwgsOzHeZY4Xh68cFVbzXx+ONXGMY//4w=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0/go.mod h1:uReU2sSxZExRPBAg3qKzmAucSi51+SP1OhohieR821Q=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2/go.mod h1:yInRyqWXAuaPrgI7p70+lDDgh3mlBohis29jGMISnmc=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/keybase/dbus v0.0.0-20220506165403-5aa21ea2c23a/go.mod h1:YPNKjjE7Ubp9dTbnWvsP3HT+hYnY6TfXzubYTBeUxc8=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/montanaflynn/stats v0.7.0/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
|
||||
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
|
||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
|
||||
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
|
||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||
golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
36
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/interactive_browser_credential.go
сгенерированный
поставляемый
36
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/interactive_browser_credential.go
сгенерированный
поставляемый
|
@ -24,18 +24,26 @@ type InteractiveBrowserCredentialOptions struct {
|
|||
// tokens. Add the wildcard value "*" to allow the credential to acquire tokens for any tenant.
|
||||
AdditionallyAllowedTenants []string
|
||||
|
||||
// authenticationRecord returned by a call to a credential's Authenticate method. Set this option
|
||||
// AuthenticationRecord returned by a call to a credential's Authenticate method. Set this option
|
||||
// to enable the credential to use data from a previous authentication.
|
||||
authenticationRecord authenticationRecord
|
||||
AuthenticationRecord AuthenticationRecord
|
||||
|
||||
// ClientID is the ID of the application users will authenticate to.
|
||||
// Defaults to the ID of an Azure development application.
|
||||
// Cache is a persistent cache the credential will use to store the tokens it acquires, making
|
||||
// them available to other processes and credential instances. The default, zero value means the
|
||||
// credential will store tokens in memory and not share them with any other credential instance.
|
||||
Cache Cache
|
||||
|
||||
// ClientID is the ID of the application to which users will authenticate. When not set, users
|
||||
// will authenticate to an Azure development application, which isn't recommended for production
|
||||
// scenarios. In production, developers should instead register their applications and assign
|
||||
// appropriate roles. See https://aka.ms/azsdk/identity/AppRegistrationAndRoleAssignment for more
|
||||
// information.
|
||||
ClientID string
|
||||
|
||||
// disableAutomaticAuthentication prevents the credential from automatically prompting the user to authenticate.
|
||||
// When this option is true, GetToken will return authenticationRequiredError when user interaction is necessary
|
||||
// DisableAutomaticAuthentication prevents the credential from automatically prompting the user to authenticate.
|
||||
// When this option is true, GetToken will return AuthenticationRequiredError when user interaction is necessary
|
||||
// to acquire a token.
|
||||
disableAutomaticAuthentication bool
|
||||
DisableAutomaticAuthentication bool
|
||||
|
||||
// DisableInstanceDiscovery should be set true only by applications authenticating in disconnected clouds, or
|
||||
// private clouds such as Azure Stack. It determines whether the credential requests Microsoft Entra instance metadata
|
||||
|
@ -54,9 +62,6 @@ type InteractiveBrowserCredentialOptions struct {
|
|||
// TenantID is the Microsoft Entra tenant the credential authenticates in. Defaults to the
|
||||
// "organizations" tenant, which can authenticate work and school accounts.
|
||||
TenantID string
|
||||
|
||||
// tokenCachePersistenceOptions enables persistent token caching when not nil.
|
||||
tokenCachePersistenceOptions *tokenCachePersistenceOptions
|
||||
}
|
||||
|
||||
func (o *InteractiveBrowserCredentialOptions) init() {
|
||||
|
@ -82,13 +87,13 @@ func NewInteractiveBrowserCredential(options *InteractiveBrowserCredentialOption
|
|||
cp.init()
|
||||
msalOpts := publicClientOptions{
|
||||
AdditionallyAllowedTenants: cp.AdditionallyAllowedTenants,
|
||||
Cache: cp.Cache,
|
||||
ClientOptions: cp.ClientOptions,
|
||||
DisableAutomaticAuthentication: cp.disableAutomaticAuthentication,
|
||||
DisableAutomaticAuthentication: cp.DisableAutomaticAuthentication,
|
||||
DisableInstanceDiscovery: cp.DisableInstanceDiscovery,
|
||||
LoginHint: cp.LoginHint,
|
||||
Record: cp.authenticationRecord,
|
||||
Record: cp.AuthenticationRecord,
|
||||
RedirectURL: cp.RedirectURL,
|
||||
TokenCachePersistenceOptions: cp.tokenCachePersistenceOptions,
|
||||
}
|
||||
c, err := newPublicClient(cp.TenantID, cp.ClientID, credNameBrowser, msalOpts)
|
||||
if err != nil {
|
||||
|
@ -97,8 +102,9 @@ func NewInteractiveBrowserCredential(options *InteractiveBrowserCredentialOption
|
|||
return &InteractiveBrowserCredential{client: c}, nil
|
||||
}
|
||||
|
||||
// Authenticate a user via the default browser. Subsequent calls to GetToken will automatically use the returned AuthenticationRecord.
|
||||
func (c *InteractiveBrowserCredential) authenticate(ctx context.Context, opts *policy.TokenRequestOptions) (authenticationRecord, error) {
|
||||
// Authenticate opens the default browser so a user can log in. Subsequent
|
||||
// GetToken calls will automatically use the returned AuthenticationRecord.
|
||||
func (c *InteractiveBrowserCredential) Authenticate(ctx context.Context, opts *policy.TokenRequestOptions) (AuthenticationRecord, error) {
|
||||
var err error
|
||||
ctx, endSpan := runtime.StartSpan(ctx, credNameBrowser+"."+traceOpAuthenticate, c.client.azClient.Tracer(), nil)
|
||||
defer func() { endSpan(err) }()
|
||||
|
|
86
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/internal/cache.go
сгенерированный
поставляемый
Normal file
86
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/internal/cache.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,86 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/cache"
|
||||
)
|
||||
|
||||
// Cache represents a persistent cache that makes authentication data available across processes.
|
||||
// Construct one with [github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache.New]. This package's
|
||||
// [persistent user authentication example] shows how to use a persistent cache to reuse user
|
||||
// logins across application runs. For service principal credential types such as
|
||||
// [ClientCertificateCredential], simply set the Cache field on the credential options.
|
||||
//
|
||||
// [persistent user authentication example]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#example-package-PersistentUserAuthentication
|
||||
type Cache struct {
|
||||
// impl is a pointer so a Cache can carry persistent state across copies
|
||||
impl *impl
|
||||
}
|
||||
|
||||
// impl is a Cache's private implementation
|
||||
type impl struct {
|
||||
// factory constructs storage implementations
|
||||
factory func(bool) (cache.ExportReplace, error)
|
||||
// cae and noCAE are previously constructed storage implementations. CAE
|
||||
// and non-CAE tokens must be stored separately because MSAL's cache doesn't
|
||||
// observe token claims. If a single storage implementation held both kinds
|
||||
// of tokens, it could create a reauthentication or error loop by returning
|
||||
// a non-CAE token lacking a required claim.
|
||||
cae, noCAE cache.ExportReplace
|
||||
// mu synchronizes around cae and noCAE
|
||||
mu *sync.RWMutex
|
||||
}
|
||||
|
||||
func (i *impl) exportReplace(cae bool) (cache.ExportReplace, error) {
|
||||
if i == nil {
|
||||
// zero-value Cache: return a nil ExportReplace and MSAL will cache in memory
|
||||
return nil, nil
|
||||
}
|
||||
var (
|
||||
err error
|
||||
xr cache.ExportReplace
|
||||
)
|
||||
i.mu.RLock()
|
||||
xr = i.cae
|
||||
if !cae {
|
||||
xr = i.noCAE
|
||||
}
|
||||
i.mu.RUnlock()
|
||||
if xr != nil {
|
||||
return xr, nil
|
||||
}
|
||||
i.mu.Lock()
|
||||
defer i.mu.Unlock()
|
||||
if cae {
|
||||
if i.cae == nil {
|
||||
if xr, err = i.factory(cae); err == nil {
|
||||
i.cae = xr
|
||||
}
|
||||
}
|
||||
return i.cae, err
|
||||
}
|
||||
if i.noCAE == nil {
|
||||
if xr, err = i.factory(cae); err == nil {
|
||||
i.noCAE = xr
|
||||
}
|
||||
}
|
||||
return i.noCAE, err
|
||||
}
|
||||
|
||||
// NewCache is the constructor for Cache. It takes a factory instead of an instance
|
||||
// because it doesn't know whether the Cache will store both CAE and non-CAE tokens.
|
||||
func NewCache(factory func(cae bool) (cache.ExportReplace, error)) Cache {
|
||||
return Cache{&impl{factory: factory, mu: &sync.RWMutex{}}}
|
||||
}
|
||||
|
||||
// ExportReplace returns an implementation satisfying MSAL's ExportReplace interface.
|
||||
// It's a function instead of a method on Cache so packages in azidentity and
|
||||
// azidentity/cache can call it while applications can't. "cae" declares whether the
|
||||
// caller intends this implementation to store CAE tokens.
|
||||
func ExportReplace(c Cache, cae bool) (cache.ExportReplace, error) {
|
||||
return c.impl.exportReplace(cae)
|
||||
}
|
18
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/internal/exported.go
сгенерированный
поставляемый
18
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/internal/exported.go
сгенерированный
поставляемый
|
@ -1,18 +0,0 @@
|
|||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package internal
|
||||
|
||||
// TokenCachePersistenceOptions contains options for persistent token caching
|
||||
type TokenCachePersistenceOptions struct {
|
||||
// AllowUnencryptedStorage controls whether the cache should fall back to storing its data in plain text
|
||||
// when encryption isn't possible. Setting this true doesn't disable encryption. The cache always attempts
|
||||
// encryption before falling back to plaintext storage.
|
||||
AllowUnencryptedStorage bool
|
||||
|
||||
// Name identifies the cache. Set this to isolate data from other applications.
|
||||
Name string
|
||||
}
|
31
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/internal/internal.go
сгенерированный
поставляемый
31
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/internal/internal.go
сгенерированный
поставляемый
|
@ -1,31 +0,0 @@
|
|||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/cache"
|
||||
)
|
||||
|
||||
var errMissingImport = errors.New("import github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache to enable persistent caching")
|
||||
|
||||
// NewCache constructs a persistent token cache when "o" isn't nil. Applications that intend to
|
||||
// use a persistent cache must first import the cache module, which will replace this function
|
||||
// with a platform-specific implementation.
|
||||
var NewCache = func(o *TokenCachePersistenceOptions, enableCAE bool) (cache.ExportReplace, error) {
|
||||
if o == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, errMissingImport
|
||||
}
|
||||
|
||||
// CacheFilePath returns the path to the cache file for the given name.
|
||||
// Defining it in this package makes it available to azidentity tests.
|
||||
var CacheFilePath = func(name string) (string, error) {
|
||||
return "", errMissingImport
|
||||
}
|
150
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/managed_identity_client.go
сгенерированный
поставляемый
150
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/managed_identity_client.go
сгенерированный
поставляемый
|
@ -143,6 +143,9 @@ func newManagedIdentityClient(options *ManagedIdentityCredentialOptions) (*manag
|
|||
if endpoint, ok := os.LookupEnv(identityEndpoint); ok {
|
||||
if _, ok := os.LookupEnv(identityHeader); ok {
|
||||
if _, ok := os.LookupEnv(identityServerThumbprint); ok {
|
||||
if options.ID != nil {
|
||||
return nil, errors.New("the Service Fabric API doesn't support specifying a user-assigned managed identity at runtime")
|
||||
}
|
||||
env = "Service Fabric"
|
||||
c.endpoint = endpoint
|
||||
c.msiType = msiTypeServiceFabric
|
||||
|
@ -152,6 +155,9 @@ func newManagedIdentityClient(options *ManagedIdentityCredentialOptions) (*manag
|
|||
c.msiType = msiTypeAppService
|
||||
}
|
||||
} else if _, ok := os.LookupEnv(arcIMDSEndpoint); ok {
|
||||
if options.ID != nil {
|
||||
return nil, errors.New("the Azure Arc API doesn't support specifying a user-assigned managed identity at runtime")
|
||||
}
|
||||
env = "Azure Arc"
|
||||
c.endpoint = endpoint
|
||||
c.msiType = msiTypeAzureArc
|
||||
|
@ -159,9 +165,15 @@ func newManagedIdentityClient(options *ManagedIdentityCredentialOptions) (*manag
|
|||
} else if endpoint, ok := os.LookupEnv(msiEndpoint); ok {
|
||||
c.endpoint = endpoint
|
||||
if _, ok := os.LookupEnv(msiSecret); ok {
|
||||
if options.ID != nil && options.ID.idKind() != miClientID {
|
||||
return nil, errors.New("the Azure ML API supports specifying a user-assigned managed identity by client ID only")
|
||||
}
|
||||
env = "Azure ML"
|
||||
c.msiType = msiTypeAzureML
|
||||
} else {
|
||||
if options.ID != nil {
|
||||
return nil, errors.New("the Cloud Shell API doesn't support user-assigned managed identities")
|
||||
}
|
||||
env = "Cloud Shell"
|
||||
c.msiType = msiTypeCloudShell
|
||||
}
|
||||
|
@ -207,9 +219,10 @@ func (c *managedIdentityClient) authenticate(ctx context.Context, id ManagedIDKi
|
|||
defer cancel()
|
||||
cx = policy.WithRetryOptions(cx, policy.RetryOptions{MaxRetries: -1})
|
||||
req, err := azruntime.NewRequest(cx, http.MethodGet, c.endpoint)
|
||||
if err == nil {
|
||||
_, err = c.azClient.Pipeline().Do(req)
|
||||
if err != nil {
|
||||
return azcore.AccessToken{}, fmt.Errorf("failed to create IMDS probe request: %s", err)
|
||||
}
|
||||
res, err := c.azClient.Pipeline().Do(req)
|
||||
if err != nil {
|
||||
msg := err.Error()
|
||||
if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
|
||||
|
@ -217,7 +230,16 @@ func (c *managedIdentityClient) authenticate(ctx context.Context, id ManagedIDKi
|
|||
}
|
||||
return azcore.AccessToken{}, newCredentialUnavailableError(credNameManagedIdentity, msg)
|
||||
}
|
||||
// send normal token requests from now on because something responded
|
||||
// because IMDS always responds with JSON, assume a non-JSON response is from something else, such
|
||||
// as a proxy, and return credentialUnavailableError so DefaultAzureCredential continues iterating
|
||||
b, err := azruntime.Payload(res)
|
||||
if err != nil {
|
||||
return azcore.AccessToken{}, newCredentialUnavailableError(credNameManagedIdentity, fmt.Sprintf("failed to read IMDS probe response: %s", err))
|
||||
}
|
||||
if !json.Valid(b) {
|
||||
return azcore.AccessToken{}, newCredentialUnavailableError(credNameManagedIdentity, "unexpected response to IMDS probe")
|
||||
}
|
||||
// send normal token requests from now on because IMDS responded
|
||||
c.probeIMDS = false
|
||||
}
|
||||
|
||||
|
@ -228,7 +250,7 @@ func (c *managedIdentityClient) authenticate(ctx context.Context, id ManagedIDKi
|
|||
|
||||
resp, err := c.azClient.Pipeline().Do(msg)
|
||||
if err != nil {
|
||||
return azcore.AccessToken{}, newAuthenticationFailedError(credNameManagedIdentity, err.Error(), nil, err)
|
||||
return azcore.AccessToken{}, newAuthenticationFailedError(credNameManagedIdentity, err.Error(), nil)
|
||||
}
|
||||
|
||||
if azruntime.HasStatusCode(resp, http.StatusOK, http.StatusCreated) {
|
||||
|
@ -239,7 +261,7 @@ func (c *managedIdentityClient) authenticate(ctx context.Context, id ManagedIDKi
|
|||
switch resp.StatusCode {
|
||||
case http.StatusBadRequest:
|
||||
if id != nil {
|
||||
return azcore.AccessToken{}, newAuthenticationFailedError(credNameManagedIdentity, "the requested identity isn't assigned to this resource", resp, nil)
|
||||
return azcore.AccessToken{}, newAuthenticationFailedError(credNameManagedIdentity, "the requested identity isn't assigned to this resource", resp)
|
||||
}
|
||||
msg := "failed to authenticate a system assigned identity"
|
||||
if body, err := azruntime.Payload(resp); err == nil && len(body) > 0 {
|
||||
|
@ -256,7 +278,7 @@ func (c *managedIdentityClient) authenticate(ctx context.Context, id ManagedIDKi
|
|||
}
|
||||
}
|
||||
|
||||
return azcore.AccessToken{}, newAuthenticationFailedError(credNameManagedIdentity, "authentication failed", resp, nil)
|
||||
return azcore.AccessToken{}, newAuthenticationFailedError(credNameManagedIdentity, "", resp)
|
||||
}
|
||||
|
||||
func (c *managedIdentityClient) createAccessToken(res *http.Response) (azcore.AccessToken, error) {
|
||||
|
@ -284,10 +306,10 @@ func (c *managedIdentityClient) createAccessToken(res *http.Response) (azcore.Ac
|
|||
if expiresOn, err := strconv.Atoi(v); err == nil {
|
||||
return azcore.AccessToken{Token: value.Token, ExpiresOn: time.Unix(int64(expiresOn), 0).UTC()}, nil
|
||||
}
|
||||
return azcore.AccessToken{}, newAuthenticationFailedError(credNameManagedIdentity, "unexpected expires_on value: "+v, res, nil)
|
||||
return azcore.AccessToken{}, newAuthenticationFailedError(credNameManagedIdentity, "unexpected expires_on value: "+v, res)
|
||||
default:
|
||||
msg := fmt.Sprintf("unsupported type received in expires_on: %T, %v", v, v)
|
||||
return azcore.AccessToken{}, newAuthenticationFailedError(credNameManagedIdentity, msg, res, nil)
|
||||
return azcore.AccessToken{}, newAuthenticationFailedError(credNameManagedIdentity, msg, res)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -302,15 +324,15 @@ func (c *managedIdentityClient) createAuthRequest(ctx context.Context, id Manage
|
|||
key, err := c.getAzureArcSecretKey(ctx, scopes)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("failed to retreive secret key from the identity endpoint: %v", err)
|
||||
return nil, newAuthenticationFailedError(credNameManagedIdentity, msg, nil, err)
|
||||
return nil, newAuthenticationFailedError(credNameManagedIdentity, msg, nil)
|
||||
}
|
||||
return c.createAzureArcAuthRequest(ctx, id, scopes, key)
|
||||
return c.createAzureArcAuthRequest(ctx, scopes, key)
|
||||
case msiTypeAzureML:
|
||||
return c.createAzureMLAuthRequest(ctx, id, scopes)
|
||||
case msiTypeServiceFabric:
|
||||
return c.createServiceFabricAuthRequest(ctx, id, scopes)
|
||||
return c.createServiceFabricAuthRequest(ctx, scopes)
|
||||
case msiTypeCloudShell:
|
||||
return c.createCloudShellAuthRequest(ctx, id, scopes)
|
||||
return c.createCloudShellAuthRequest(ctx, scopes)
|
||||
default:
|
||||
return nil, newCredentialUnavailableError(credNameManagedIdentity, "managed identity isn't supported in this environment")
|
||||
}
|
||||
|
@ -323,13 +345,16 @@ func (c *managedIdentityClient) createIMDSAuthRequest(ctx context.Context, id Ma
|
|||
}
|
||||
request.Raw().Header.Set(headerMetadata, "true")
|
||||
q := request.Raw().URL.Query()
|
||||
q.Add("api-version", imdsAPIVersion)
|
||||
q.Add("resource", strings.Join(scopes, " "))
|
||||
q.Set("api-version", imdsAPIVersion)
|
||||
q.Set("resource", strings.Join(scopes, " "))
|
||||
if id != nil {
|
||||
if id.idKind() == miResourceID {
|
||||
q.Add(msiResID, id.String())
|
||||
} else {
|
||||
q.Add(qpClientID, id.String())
|
||||
switch id.idKind() {
|
||||
case miClientID:
|
||||
q.Set(qpClientID, id.String())
|
||||
case miObjectID:
|
||||
q.Set("object_id", id.String())
|
||||
case miResourceID:
|
||||
q.Set(msiResID, id.String())
|
||||
}
|
||||
}
|
||||
request.Raw().URL.RawQuery = q.Encode()
|
||||
|
@ -343,13 +368,16 @@ func (c *managedIdentityClient) createAppServiceAuthRequest(ctx context.Context,
|
|||
}
|
||||
request.Raw().Header.Set("X-IDENTITY-HEADER", os.Getenv(identityHeader))
|
||||
q := request.Raw().URL.Query()
|
||||
q.Add("api-version", "2019-08-01")
|
||||
q.Add("resource", scopes[0])
|
||||
q.Set("api-version", "2019-08-01")
|
||||
q.Set("resource", scopes[0])
|
||||
if id != nil {
|
||||
if id.idKind() == miResourceID {
|
||||
q.Add(miResID, id.String())
|
||||
} else {
|
||||
q.Add(qpClientID, id.String())
|
||||
switch id.idKind() {
|
||||
case miClientID:
|
||||
q.Set(qpClientID, id.String())
|
||||
case miObjectID:
|
||||
q.Set("principal_id", id.String())
|
||||
case miResourceID:
|
||||
q.Set(miResID, id.String())
|
||||
}
|
||||
}
|
||||
request.Raw().URL.RawQuery = q.Encode()
|
||||
|
@ -363,23 +391,24 @@ func (c *managedIdentityClient) createAzureMLAuthRequest(ctx context.Context, id
|
|||
}
|
||||
request.Raw().Header.Set("secret", os.Getenv(msiSecret))
|
||||
q := request.Raw().URL.Query()
|
||||
q.Add("api-version", "2017-09-01")
|
||||
q.Add("resource", strings.Join(scopes, " "))
|
||||
q.Add("clientid", os.Getenv(defaultIdentityClientID))
|
||||
q.Set("api-version", "2017-09-01")
|
||||
q.Set("resource", strings.Join(scopes, " "))
|
||||
q.Set("clientid", os.Getenv(defaultIdentityClientID))
|
||||
if id != nil {
|
||||
if id.idKind() == miResourceID {
|
||||
log.Write(EventAuthentication, "WARNING: Azure ML doesn't support specifying a managed identity by resource ID")
|
||||
q.Set("clientid", "")
|
||||
q.Set(miResID, id.String())
|
||||
} else {
|
||||
switch id.idKind() {
|
||||
case miClientID:
|
||||
q.Set("clientid", id.String())
|
||||
case miObjectID:
|
||||
return nil, newAuthenticationFailedError(credNameManagedIdentity, "Azure ML doesn't support specifying a managed identity by object ID", nil)
|
||||
case miResourceID:
|
||||
return nil, newAuthenticationFailedError(credNameManagedIdentity, "Azure ML doesn't support specifying a managed identity by resource ID", nil)
|
||||
}
|
||||
}
|
||||
request.Raw().URL.RawQuery = q.Encode()
|
||||
return request, nil
|
||||
}
|
||||
|
||||
func (c *managedIdentityClient) createServiceFabricAuthRequest(ctx context.Context, id ManagedIDKind, scopes []string) (*policy.Request, error) {
|
||||
func (c *managedIdentityClient) createServiceFabricAuthRequest(ctx context.Context, scopes []string) (*policy.Request, error) {
|
||||
request, err := azruntime.NewRequest(ctx, http.MethodGet, c.endpoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -387,16 +416,8 @@ func (c *managedIdentityClient) createServiceFabricAuthRequest(ctx context.Conte
|
|||
q := request.Raw().URL.Query()
|
||||
request.Raw().Header.Set("Accept", "application/json")
|
||||
request.Raw().Header.Set("Secret", os.Getenv(identityHeader))
|
||||
q.Add("api-version", serviceFabricAPIVersion)
|
||||
q.Add("resource", strings.Join(scopes, " "))
|
||||
if id != nil {
|
||||
log.Write(EventAuthentication, "WARNING: Service Fabric doesn't support selecting a user-assigned identity at runtime")
|
||||
if id.idKind() == miResourceID {
|
||||
q.Add(miResID, id.String())
|
||||
} else {
|
||||
q.Add(qpClientID, id.String())
|
||||
}
|
||||
}
|
||||
q.Set("api-version", serviceFabricAPIVersion)
|
||||
q.Set("resource", strings.Join(scopes, " "))
|
||||
request.Raw().URL.RawQuery = q.Encode()
|
||||
return request, nil
|
||||
}
|
||||
|
@ -409,8 +430,8 @@ func (c *managedIdentityClient) getAzureArcSecretKey(ctx context.Context, resour
|
|||
}
|
||||
request.Raw().Header.Set(headerMetadata, "true")
|
||||
q := request.Raw().URL.Query()
|
||||
q.Add("api-version", azureArcAPIVersion)
|
||||
q.Add("resource", strings.Join(resources, " "))
|
||||
q.Set("api-version", azureArcAPIVersion)
|
||||
q.Set("resource", strings.Join(resources, " "))
|
||||
request.Raw().URL.RawQuery = q.Encode()
|
||||
// send the initial request to get the short-lived secret key
|
||||
response, err := c.azClient.Pipeline().Do(request)
|
||||
|
@ -421,39 +442,39 @@ func (c *managedIdentityClient) getAzureArcSecretKey(ctx context.Context, resour
|
|||
// of the secret key file. Any other status code indicates an error in the request.
|
||||
if response.StatusCode != 401 {
|
||||
msg := fmt.Sprintf("expected a 401 response, received %d", response.StatusCode)
|
||||
return "", newAuthenticationFailedError(credNameManagedIdentity, msg, response, nil)
|
||||
return "", newAuthenticationFailedError(credNameManagedIdentity, msg, response)
|
||||
}
|
||||
header := response.Header.Get("WWW-Authenticate")
|
||||
if len(header) == 0 {
|
||||
return "", newAuthenticationFailedError(credNameManagedIdentity, "HIMDS response has no WWW-Authenticate header", nil, nil)
|
||||
return "", newAuthenticationFailedError(credNameManagedIdentity, "HIMDS response has no WWW-Authenticate header", nil)
|
||||
}
|
||||
// the WWW-Authenticate header is expected in the following format: Basic realm=/some/file/path.key
|
||||
_, p, found := strings.Cut(header, "=")
|
||||
if !found {
|
||||
return "", newAuthenticationFailedError(credNameManagedIdentity, "unexpected WWW-Authenticate header from HIMDS: "+header, nil, nil)
|
||||
return "", newAuthenticationFailedError(credNameManagedIdentity, "unexpected WWW-Authenticate header from HIMDS: "+header, nil)
|
||||
}
|
||||
expected, err := arcKeyDirectory()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if filepath.Dir(p) != expected || !strings.HasSuffix(p, ".key") {
|
||||
return "", newAuthenticationFailedError(credNameManagedIdentity, "unexpected file path from HIMDS service: "+p, nil, nil)
|
||||
return "", newAuthenticationFailedError(credNameManagedIdentity, "unexpected file path from HIMDS service: "+p, nil)
|
||||
}
|
||||
f, err := os.Stat(p)
|
||||
if err != nil {
|
||||
return "", newAuthenticationFailedError(credNameManagedIdentity, fmt.Sprintf("could not stat %q: %v", p, err), nil, nil)
|
||||
return "", newAuthenticationFailedError(credNameManagedIdentity, fmt.Sprintf("could not stat %q: %v", p, err), nil)
|
||||
}
|
||||
if s := f.Size(); s > 4096 {
|
||||
return "", newAuthenticationFailedError(credNameManagedIdentity, fmt.Sprintf("key is too large (%d bytes)", s), nil, nil)
|
||||
return "", newAuthenticationFailedError(credNameManagedIdentity, fmt.Sprintf("key is too large (%d bytes)", s), nil)
|
||||
}
|
||||
key, err := os.ReadFile(p)
|
||||
if err != nil {
|
||||
return "", newAuthenticationFailedError(credNameManagedIdentity, fmt.Sprintf("could not read %q: %v", p, err), nil, nil)
|
||||
return "", newAuthenticationFailedError(credNameManagedIdentity, fmt.Sprintf("could not read %q: %v", p, err), nil)
|
||||
}
|
||||
return string(key), nil
|
||||
}
|
||||
|
||||
func (c *managedIdentityClient) createAzureArcAuthRequest(ctx context.Context, id ManagedIDKind, resources []string, key string) (*policy.Request, error) {
|
||||
func (c *managedIdentityClient) createAzureArcAuthRequest(ctx context.Context, resources []string, key string) (*policy.Request, error) {
|
||||
request, err := azruntime.NewRequest(ctx, http.MethodGet, c.endpoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -461,21 +482,13 @@ func (c *managedIdentityClient) createAzureArcAuthRequest(ctx context.Context, i
|
|||
request.Raw().Header.Set(headerMetadata, "true")
|
||||
request.Raw().Header.Set("Authorization", fmt.Sprintf("Basic %s", key))
|
||||
q := request.Raw().URL.Query()
|
||||
q.Add("api-version", azureArcAPIVersion)
|
||||
q.Add("resource", strings.Join(resources, " "))
|
||||
if id != nil {
|
||||
log.Write(EventAuthentication, "WARNING: Azure Arc doesn't support user-assigned managed identities")
|
||||
if id.idKind() == miResourceID {
|
||||
q.Add(miResID, id.String())
|
||||
} else {
|
||||
q.Add(qpClientID, id.String())
|
||||
}
|
||||
}
|
||||
q.Set("api-version", azureArcAPIVersion)
|
||||
q.Set("resource", strings.Join(resources, " "))
|
||||
request.Raw().URL.RawQuery = q.Encode()
|
||||
return request, nil
|
||||
}
|
||||
|
||||
func (c *managedIdentityClient) createCloudShellAuthRequest(ctx context.Context, id ManagedIDKind, scopes []string) (*policy.Request, error) {
|
||||
func (c *managedIdentityClient) createCloudShellAuthRequest(ctx context.Context, scopes []string) (*policy.Request, error) {
|
||||
request, err := azruntime.NewRequest(ctx, http.MethodPost, c.endpoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -488,14 +501,5 @@ func (c *managedIdentityClient) createCloudShellAuthRequest(ctx context.Context,
|
|||
if err := request.SetBody(body, "application/x-www-form-urlencoded"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if id != nil {
|
||||
log.Write(EventAuthentication, "WARNING: Cloud Shell doesn't support user-assigned managed identities")
|
||||
q := request.Raw().URL.Query()
|
||||
if id.idKind() == miResourceID {
|
||||
q.Add(miResID, id.String())
|
||||
} else {
|
||||
q.Add(qpClientID, id.String())
|
||||
}
|
||||
}
|
||||
return request, nil
|
||||
}
|
||||
|
|
52
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/managed_identity_credential.go
сгенерированный
поставляемый
52
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/managed_identity_credential.go
сгенерированный
поставляемый
|
@ -22,8 +22,9 @@ const credNameManagedIdentity = "ManagedIdentityCredential"
|
|||
type managedIdentityIDKind int
|
||||
|
||||
const (
|
||||
miClientID managedIdentityIDKind = 0
|
||||
miResourceID managedIdentityIDKind = 1
|
||||
miClientID managedIdentityIDKind = iota
|
||||
miObjectID
|
||||
miResourceID
|
||||
)
|
||||
|
||||
// ManagedIDKind identifies the ID of a managed identity as either a client or resource ID
|
||||
|
@ -32,7 +33,12 @@ type ManagedIDKind interface {
|
|||
idKind() managedIdentityIDKind
|
||||
}
|
||||
|
||||
// ClientID is the client ID of a user-assigned managed identity.
|
||||
// ClientID is the client ID of a user-assigned managed identity. [NewManagedIdentityCredential]
|
||||
// returns an error when a ClientID is specified on the following platforms:
|
||||
//
|
||||
// - Azure Arc
|
||||
// - Cloud Shell
|
||||
// - Service Fabric
|
||||
type ClientID string
|
||||
|
||||
func (ClientID) idKind() managedIdentityIDKind {
|
||||
|
@ -44,7 +50,31 @@ func (c ClientID) String() string {
|
|||
return string(c)
|
||||
}
|
||||
|
||||
// ResourceID is the resource ID of a user-assigned managed identity.
|
||||
// ObjectID is the object ID of a user-assigned managed identity. [NewManagedIdentityCredential]
|
||||
// returns an error when an ObjectID is specified on the following platforms:
|
||||
//
|
||||
// - Azure Arc
|
||||
// - Azure ML
|
||||
// - Cloud Shell
|
||||
// - Service Fabric
|
||||
type ObjectID string
|
||||
|
||||
func (ObjectID) idKind() managedIdentityIDKind {
|
||||
return miObjectID
|
||||
}
|
||||
|
||||
// String returns the string value of the ID.
|
||||
func (o ObjectID) String() string {
|
||||
return string(o)
|
||||
}
|
||||
|
||||
// ResourceID is the resource ID of a user-assigned managed identity. [NewManagedIdentityCredential]
|
||||
// returns an error when a ResourceID is specified on the following platforms:
|
||||
//
|
||||
// - Azure Arc
|
||||
// - Azure ML
|
||||
// - Cloud Shell
|
||||
// - Service Fabric
|
||||
type ResourceID string
|
||||
|
||||
func (ResourceID) idKind() managedIdentityIDKind {
|
||||
|
@ -60,9 +90,10 @@ func (r ResourceID) String() string {
|
|||
type ManagedIdentityCredentialOptions struct {
|
||||
azcore.ClientOptions
|
||||
|
||||
// ID is the ID of a managed identity the credential should authenticate. Set this field to use a specific identity
|
||||
// instead of the hosting environment's default. The value may be the identity's client ID or resource ID, but note that
|
||||
// some platforms don't accept resource IDs.
|
||||
// ID of a managed identity the credential should authenticate. Set this field to use a specific identity instead of
|
||||
// the hosting environment's default. The value may be the identity's client, object, or resource ID.
|
||||
// NewManagedIdentityCredential returns an error when the hosting environment doesn't support user-assigned managed
|
||||
// identities, or the specified kind of ID.
|
||||
ID ManagedIDKind
|
||||
|
||||
// dac indicates whether the credential is part of DefaultAzureCredential. When true, and the environment doesn't have
|
||||
|
@ -73,10 +104,11 @@ type ManagedIdentityCredentialOptions struct {
|
|||
dac bool
|
||||
}
|
||||
|
||||
// ManagedIdentityCredential authenticates an Azure managed identity in any hosting environment supporting managed identities.
|
||||
// ManagedIdentityCredential authenticates an [Azure managed identity] in any hosting environment supporting managed identities.
|
||||
// This credential authenticates a system-assigned identity by default. Use ManagedIdentityCredentialOptions.ID to specify a
|
||||
// user-assigned identity. See Microsoft Entra ID documentation for more information about managed identities:
|
||||
// https://learn.microsoft.com/entra/identity/managed-identities-azure-resources/overview
|
||||
// user-assigned identity.
|
||||
//
|
||||
// [Azure managed identity]: https://learn.microsoft.com/entra/identity/managed-identities-azure-resources/overview
|
||||
type ManagedIdentityCredential struct {
|
||||
client *confidentialClient
|
||||
mic *managedIdentityClient
|
||||
|
|
21
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/public_client.go
сгенерированный
поставляемый
21
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/public_client.go
сгенерированный
поставляемый
|
@ -30,12 +30,12 @@ type publicClientOptions struct {
|
|||
azcore.ClientOptions
|
||||
|
||||
AdditionallyAllowedTenants []string
|
||||
Cache Cache
|
||||
DeviceCodePrompt func(context.Context, DeviceCodeMessage) error
|
||||
DisableAutomaticAuthentication bool
|
||||
DisableInstanceDiscovery bool
|
||||
LoginHint, RedirectURL string
|
||||
Record authenticationRecord
|
||||
TokenCachePersistenceOptions *tokenCachePersistenceOptions
|
||||
Record AuthenticationRecord
|
||||
Username, Password string
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ type publicClient struct {
|
|||
host string
|
||||
name string
|
||||
opts publicClientOptions
|
||||
record authenticationRecord
|
||||
record AuthenticationRecord
|
||||
azClient *azcore.Client
|
||||
}
|
||||
|
||||
|
@ -107,19 +107,19 @@ func newPublicClient(tenantID, clientID, name string, o publicClientOptions) (*p
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (p *publicClient) Authenticate(ctx context.Context, tro *policy.TokenRequestOptions) (authenticationRecord, error) {
|
||||
func (p *publicClient) Authenticate(ctx context.Context, tro *policy.TokenRequestOptions) (AuthenticationRecord, error) {
|
||||
if tro == nil {
|
||||
tro = &policy.TokenRequestOptions{}
|
||||
}
|
||||
if len(tro.Scopes) == 0 {
|
||||
if p.defaultScope == nil {
|
||||
return authenticationRecord{}, errScopeRequired
|
||||
return AuthenticationRecord{}, errScopeRequired
|
||||
}
|
||||
tro.Scopes = p.defaultScope
|
||||
}
|
||||
client, mu, err := p.client(*tro)
|
||||
if err != nil {
|
||||
return authenticationRecord{}, err
|
||||
return AuthenticationRecord{}, err
|
||||
}
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
|
@ -152,7 +152,7 @@ func (p *publicClient) GetToken(ctx context.Context, tro policy.TokenRequestOpti
|
|||
return p.token(ar, err)
|
||||
}
|
||||
if p.opts.DisableAutomaticAuthentication {
|
||||
return azcore.AccessToken{}, newauthenticationRequiredError(p.name, tro)
|
||||
return azcore.AccessToken{}, newAuthenticationRequiredError(p.name, tro)
|
||||
}
|
||||
at, err := p.reqToken(ctx, client, tro)
|
||||
if err == nil {
|
||||
|
@ -222,13 +222,13 @@ func (p *publicClient) client(tro policy.TokenRequestOptions) (msalPublicClient,
|
|||
}
|
||||
|
||||
func (p *publicClient) newMSALClient(enableCAE bool) (msalPublicClient, error) {
|
||||
cache, err := internal.NewCache(p.opts.TokenCachePersistenceOptions, enableCAE)
|
||||
c, err := internal.ExportReplace(p.opts.Cache, enableCAE)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
o := []public.Option{
|
||||
public.WithAuthority(runtime.JoinPaths(p.host, p.tenantID)),
|
||||
public.WithCache(cache),
|
||||
public.WithCache(c),
|
||||
public.WithHTTPClient(p),
|
||||
}
|
||||
if enableCAE {
|
||||
|
@ -244,8 +244,7 @@ func (p *publicClient) token(ar public.AuthResult, err error) (azcore.AccessToke
|
|||
if err == nil {
|
||||
p.record, err = newAuthenticationRecord(ar)
|
||||
} else {
|
||||
res := getResponseFromError(err)
|
||||
err = newAuthenticationFailedError(p.name, err.Error(), res, err)
|
||||
err = newAuthenticationFailedErrorFromMSAL(p.name, err)
|
||||
}
|
||||
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
|
||||
}
|
||||
|
|
26
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/test-resources-post.ps1
сгенерированный
поставляемый
26
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/test-resources-post.ps1
сгенерированный
поставляемый
|
@ -5,7 +5,19 @@
|
|||
|
||||
param (
|
||||
[hashtable] $AdditionalParameters = @{},
|
||||
[hashtable] $DeploymentOutputs
|
||||
[hashtable] $DeploymentOutputs,
|
||||
|
||||
[Parameter(ParameterSetName = 'Provisioner', Mandatory = $true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string] $TenantId,
|
||||
|
||||
[Parameter()]
|
||||
[ValidatePattern('^[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}$')]
|
||||
[string] $TestApplicationId,
|
||||
|
||||
# Captures any arguments from eng/New-TestResources.ps1 not declared here (no parameter errors).
|
||||
[Parameter(ValueFromRemainingArguments = $true)]
|
||||
$RemainingArguments
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
@ -16,14 +28,14 @@ if ($CI) {
|
|||
Write-Host "Skipping post-provisioning script because resources weren't deployed"
|
||||
return
|
||||
}
|
||||
az login --service-principal -u $DeploymentOutputs['AZIDENTITY_CLIENT_ID'] -p $DeploymentOutputs['AZIDENTITY_CLIENT_SECRET'] --tenant $DeploymentOutputs['AZIDENTITY_TENANT_ID']
|
||||
az login --federated-token $env:OIDC_TOKEN --service-principal -t $TenantId -u $TestApplicationId
|
||||
az account set --subscription $DeploymentOutputs['AZIDENTITY_SUBSCRIPTION_ID']
|
||||
}
|
||||
|
||||
Write-Host "Building container"
|
||||
$image = "$($DeploymentOutputs['AZIDENTITY_ACR_LOGIN_SERVER'])/azidentity-managed-id-test"
|
||||
Set-Content -Path "$PSScriptRoot/Dockerfile" -Value @"
|
||||
FROM mcr.microsoft.com/oss/go/microsoft/golang:latest as builder
|
||||
FROM mcr.microsoft.com/oss/go/microsoft/golang:latest AS builder
|
||||
ENV GOARCH=amd64 GOWORK=off
|
||||
COPY . /azidentity
|
||||
WORKDIR /azidentity/testdata/managed-id-test
|
||||
|
@ -53,9 +65,11 @@ az container create -g $rg -n $aciName --image $image `
|
|||
--role "Storage Blob Data Reader" `
|
||||
--scope $($DeploymentOutputs['AZIDENTITY_STORAGE_ID']) `
|
||||
-e AZIDENTITY_STORAGE_NAME=$($DeploymentOutputs['AZIDENTITY_STORAGE_NAME']) `
|
||||
AZIDENTITY_STORAGE_NAME_USER_ASSIGNED=$($DeploymentOutputs['AZIDENTITY_STORAGE_NAME_USER_ASSIGNED']) `
|
||||
AZIDENTITY_USER_ASSIGNED_IDENTITY=$($DeploymentOutputs['AZIDENTITY_USER_ASSIGNED_IDENTITY']) `
|
||||
FUNCTIONS_CUSTOMHANDLER_PORT=80
|
||||
AZIDENTITY_STORAGE_NAME_USER_ASSIGNED=$($DeploymentOutputs['AZIDENTITY_STORAGE_NAME_USER_ASSIGNED']) `
|
||||
AZIDENTITY_USER_ASSIGNED_IDENTITY=$($DeploymentOutputs['AZIDENTITY_USER_ASSIGNED_IDENTITY']) `
|
||||
AZIDENTITY_USER_ASSIGNED_IDENTITY_CLIENT_ID=$($DeploymentOutputs['AZIDENTITY_USER_ASSIGNED_IDENTITY_CLIENT_ID']) `
|
||||
AZIDENTITY_USER_ASSIGNED_IDENTITY_OBJECT_ID=$($DeploymentOutputs['AZIDENTITY_USER_ASSIGNED_IDENTITY_OBJECT_ID']) `
|
||||
FUNCTIONS_CUSTOMHANDLER_PORT=80
|
||||
Write-Host "##vso[task.setvariable variable=AZIDENTITY_ACI_NAME;]$aciName"
|
||||
|
||||
# Azure Functions deployment: copy the Windows binary from the Docker image, deploy it in a zip
|
||||
|
|
9
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/test-resources.bicep
сгенерированный
поставляемый
9
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/test-resources.bicep
сгенерированный
поставляемый
|
@ -135,6 +135,14 @@ resource azfunc 'Microsoft.Web/sites@2021-03-01' = if (deployResources) {
|
|||
name: 'AZIDENTITY_USER_ASSIGNED_IDENTITY'
|
||||
value: deployResources ? usermgdid.id : null
|
||||
}
|
||||
{
|
||||
name: 'AZIDENTITY_USER_ASSIGNED_IDENTITY_CLIENT_ID'
|
||||
value: deployResources ? usermgdid.properties.clientId : null
|
||||
}
|
||||
{
|
||||
name: 'AZIDENTITY_USER_ASSIGNED_IDENTITY_OBJECT_ID'
|
||||
value: deployResources ? usermgdid.properties.principalId : null
|
||||
}
|
||||
{
|
||||
name: 'AzureWebJobsStorage'
|
||||
value: 'DefaultEndpointsProtocol=https;AccountName=${deployResources ? sa.name : ''};EndpointSuffix=${deployResources ? environment().suffixes.storage : ''};AccountKey=${deployResources ? sa.listKeys().keys[0].value : ''}'
|
||||
|
@ -217,3 +225,4 @@ output AZIDENTITY_STORAGE_NAME_USER_ASSIGNED string = deployResources ? saUserAs
|
|||
output AZIDENTITY_USER_ASSIGNED_IDENTITY string = deployResources ? usermgdid.id : ''
|
||||
output AZIDENTITY_USER_ASSIGNED_IDENTITY_CLIENT_ID string = deployResources ? usermgdid.properties.clientId : ''
|
||||
output AZIDENTITY_USER_ASSIGNED_IDENTITY_NAME string = deployResources ? usermgdid.name : ''
|
||||
output AZIDENTITY_USER_ASSIGNED_IDENTITY_OBJECT_ID string = deployResources ? usermgdid.properties.principalId : ''
|
||||
|
|
28
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/username_password_credential.go
сгенерированный
поставляемый
28
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/username_password_credential.go
сгенерированный
поставляемый
|
@ -25,18 +25,20 @@ type UsernamePasswordCredentialOptions struct {
|
|||
// application is registered.
|
||||
AdditionallyAllowedTenants []string
|
||||
|
||||
// authenticationRecord returned by a call to a credential's Authenticate method. Set this option
|
||||
// AuthenticationRecord returned by a call to a credential's Authenticate method. Set this option
|
||||
// to enable the credential to use data from a previous authentication.
|
||||
authenticationRecord authenticationRecord
|
||||
AuthenticationRecord AuthenticationRecord
|
||||
|
||||
// Cache is a persistent cache the credential will use to store the tokens it acquires, making
|
||||
// them available to other processes and credential instances. The default, zero value means the
|
||||
// credential will store tokens in memory and not share them with any other credential instance.
|
||||
Cache Cache
|
||||
|
||||
// DisableInstanceDiscovery should be set true only by applications authenticating in disconnected clouds, or
|
||||
// private clouds such as Azure Stack. It determines whether the credential requests Microsoft Entra instance metadata
|
||||
// from https://login.microsoft.com before authenticating. Setting this to true will skip this request, making
|
||||
// the application responsible for ensuring the configured authority is valid and trustworthy.
|
||||
DisableInstanceDiscovery bool
|
||||
|
||||
// tokenCachePersistenceOptions enables persistent token caching when not nil.
|
||||
tokenCachePersistenceOptions *tokenCachePersistenceOptions
|
||||
}
|
||||
|
||||
// UsernamePasswordCredential authenticates a user with a password. Microsoft doesn't recommend this kind of authentication,
|
||||
|
@ -54,13 +56,13 @@ func NewUsernamePasswordCredential(tenantID string, clientID string, username st
|
|||
options = &UsernamePasswordCredentialOptions{}
|
||||
}
|
||||
opts := publicClientOptions{
|
||||
AdditionallyAllowedTenants: options.AdditionallyAllowedTenants,
|
||||
ClientOptions: options.ClientOptions,
|
||||
DisableInstanceDiscovery: options.DisableInstanceDiscovery,
|
||||
Password: password,
|
||||
Record: options.authenticationRecord,
|
||||
TokenCachePersistenceOptions: options.tokenCachePersistenceOptions,
|
||||
Username: username,
|
||||
AdditionallyAllowedTenants: options.AdditionallyAllowedTenants,
|
||||
Cache: options.Cache,
|
||||
ClientOptions: options.ClientOptions,
|
||||
DisableInstanceDiscovery: options.DisableInstanceDiscovery,
|
||||
Password: password,
|
||||
Record: options.AuthenticationRecord,
|
||||
Username: username,
|
||||
}
|
||||
c, err := newPublicClient(tenantID, clientID, credNameUserPassword, opts)
|
||||
if err != nil {
|
||||
|
@ -70,7 +72,7 @@ func NewUsernamePasswordCredential(tenantID string, clientID string, username st
|
|||
}
|
||||
|
||||
// Authenticate the user. Subsequent calls to GetToken will automatically use the returned AuthenticationRecord.
|
||||
func (c *UsernamePasswordCredential) authenticate(ctx context.Context, opts *policy.TokenRequestOptions) (authenticationRecord, error) {
|
||||
func (c *UsernamePasswordCredential) Authenticate(ctx context.Context, opts *policy.TokenRequestOptions) (AuthenticationRecord, error) {
|
||||
var err error
|
||||
ctx, endSpan := runtime.StartSpan(ctx, credNameUserPassword+"."+traceOpAuthenticate, c.client.azClient.Tracer(), nil)
|
||||
defer func() { endSpan(err) }()
|
||||
|
|
|
@ -14,5 +14,5 @@ const (
|
|||
module = "github.com/Azure/azure-sdk-for-go/sdk/" + component
|
||||
|
||||
// Version is the semantic version (see http://semver.org) of this module.
|
||||
version = "v1.7.0"
|
||||
version = "v1.8.0"
|
||||
)
|
||||
|
|
10
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/workload_identity.go
сгенерированный
поставляемый
10
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/workload_identity.go
сгенерированный
поставляемый
|
@ -39,15 +39,24 @@ type WorkloadIdentityCredentialOptions struct {
|
|||
// Add the wildcard value "*" to allow the credential to acquire tokens for any tenant in which the
|
||||
// application is registered.
|
||||
AdditionallyAllowedTenants []string
|
||||
|
||||
// Cache is a persistent cache the credential will use to store the tokens it acquires, making
|
||||
// them available to other processes and credential instances. The default, zero value means the
|
||||
// credential will store tokens in memory and not share them with any other credential instance.
|
||||
Cache Cache
|
||||
|
||||
// ClientID of the service principal. Defaults to the value of the environment variable AZURE_CLIENT_ID.
|
||||
ClientID string
|
||||
|
||||
// DisableInstanceDiscovery should be set true only by applications authenticating in disconnected clouds, or
|
||||
// private clouds such as Azure Stack. It determines whether the credential requests Microsoft Entra instance metadata
|
||||
// from https://login.microsoft.com before authenticating. Setting this to true will skip this request, making
|
||||
// the application responsible for ensuring the configured authority is valid and trustworthy.
|
||||
DisableInstanceDiscovery bool
|
||||
|
||||
// TenantID of the service principal. Defaults to the value of the environment variable AZURE_TENANT_ID.
|
||||
TenantID string
|
||||
|
||||
// TokenFilePath is the path of a file containing a Kubernetes service account token. Defaults to the value of the
|
||||
// environment variable AZURE_FEDERATED_TOKEN_FILE.
|
||||
TokenFilePath string
|
||||
|
@ -81,6 +90,7 @@ func NewWorkloadIdentityCredential(options *WorkloadIdentityCredentialOptions) (
|
|||
w := WorkloadIdentityCredential{file: file, mtx: &sync.RWMutex{}}
|
||||
caco := ClientAssertionCredentialOptions{
|
||||
AdditionallyAllowedTenants: options.AdditionallyAllowedTenants,
|
||||
Cache: options.Cache,
|
||||
ClientOptions: options.ClientOptions,
|
||||
DisableInstanceDiscovery: options.DisableInstanceDiscovery,
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) Microsoft Corporation.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE
|
68
pkg/util/azureclient/authz/remotepdp/client.go → vendor/github.com/Azure/checkaccess-v2-go-sdk/client/client.go
сгенерированный
поставляемый
68
pkg/util/azureclient/authz/remotepdp/client.go → vendor/github.com/Azure/checkaccess-v2-go-sdk/client/client.go
сгенерированный
поставляемый
|
@ -1,4 +1,4 @@
|
|||
package remotepdp
|
||||
package client
|
||||
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the Apache License 2.0.
|
||||
|
@ -8,12 +8,13 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
|
||||
|
||||
"github.com/Azure/ARO-RP/pkg/util/azureclient"
|
||||
"github.com/Azure/checkaccess-v2-go-sdk/client/internal/token"
|
||||
)
|
||||
|
||||
// this asserts that &remotePDPClient{} would always implement RemotePDPClient
|
||||
|
@ -22,6 +23,7 @@ var _ RemotePDPClient = &remotePDPClient{}
|
|||
// RemotePDPClient represents the Microsoft Remote PDP API Spec
|
||||
type RemotePDPClient interface {
|
||||
CheckAccess(context.Context, AuthorizationRequest) (*AuthorizationDecisionResponse, error)
|
||||
CreateAuthorizationRequest(string, []string, string) (*AuthorizationRequest, error)
|
||||
}
|
||||
|
||||
// remotePDPClient implements RemotePDPClient
|
||||
|
@ -34,15 +36,19 @@ type remotePDPClient struct {
|
|||
// endpoint - the fqdn of the regional specific endpoint of PDP
|
||||
// scope - the oauth scope required by the PDP server
|
||||
// cred - the credential of the client to call the PDP server
|
||||
func NewRemotePDPClient(endpoint, scope string, cred azcore.TokenCredential) *remotePDPClient {
|
||||
authPolicy := runtime.NewBearerTokenPolicy(cred, []string{scope}, nil)
|
||||
|
||||
customRoundTripper := azureclient.NewCustomRoundTripper(http.DefaultTransport)
|
||||
clientOptions := &azcore.ClientOptions{
|
||||
Transport: &http.Client{
|
||||
Transport: customRoundTripper,
|
||||
},
|
||||
// ClientOptions - the optional settings for a client's pipeline.
|
||||
func NewRemotePDPClient(endpoint, scope string, cred azcore.TokenCredential, clientOptions *azcore.ClientOptions) (*remotePDPClient, error) {
|
||||
if strings.TrimSpace(endpoint) == "" {
|
||||
return nil, fmt.Errorf("endpoint: %s is not valid, need a valid endpoint in creating client", endpoint)
|
||||
}
|
||||
if strings.TrimSpace(scope) == "" {
|
||||
return nil, fmt.Errorf("scope: %s is not valid, need a valid scope in creating client", scope)
|
||||
}
|
||||
if cred == nil {
|
||||
return nil, fmt.Errorf("need TokenCredential in creating client")
|
||||
}
|
||||
|
||||
authPolicy := runtime.NewBearerTokenPolicy(cred, []string{scope}, nil)
|
||||
|
||||
pipeline := runtime.NewPipeline(
|
||||
modulename,
|
||||
|
@ -54,7 +60,7 @@ func NewRemotePDPClient(endpoint, scope string, cred azcore.TokenCredential) *re
|
|||
clientOptions,
|
||||
)
|
||||
|
||||
return &remotePDPClient{endpoint, pipeline}
|
||||
return &remotePDPClient{endpoint, pipeline}, nil
|
||||
}
|
||||
|
||||
// CheckAccess sends an Authorization query to the PDP server specified in the client
|
||||
|
@ -65,7 +71,9 @@ func (r *remotePDPClient) CheckAccess(ctx context.Context, authzReq Authorizatio
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
runtime.MarshalAsJSON(req, authzReq)
|
||||
if err := runtime.MarshalAsJSON(req, authzReq); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res, err := r.pipeline.Do(req)
|
||||
if err != nil {
|
||||
|
@ -100,3 +108,39 @@ func newCheckAccessError(r *http.Response) error {
|
|||
ErrorCode: fmt.Sprint(checkAccessError.StatusCode),
|
||||
}
|
||||
}
|
||||
|
||||
// CreateAuthorizationRequest creates an AuthorizationRequest object
|
||||
func (r *remotePDPClient) CreateAuthorizationRequest(resourceId string, actions []string, jwtToken string) (*AuthorizationRequest, error) {
|
||||
if strings.TrimSpace(jwtToken) == "" {
|
||||
return nil, fmt.Errorf("need token in creating AuthorizationRequest")
|
||||
}
|
||||
|
||||
tokenClaims, err := token.ExtractClaims(jwtToken)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error while parse the token, err: %v", err)
|
||||
}
|
||||
|
||||
subjectAttributes := SubjectAttributes{}
|
||||
subjectAttributes.ObjectId = tokenClaims.ObjectId
|
||||
|
||||
if tokenClaims.ClaimNames != nil && len(tokenClaims.Groups) == 0 {
|
||||
subjectAttributes.ClaimName = GroupExpansion
|
||||
} else if tokenClaims.ClaimNames == nil && len(tokenClaims.Groups) > 0 {
|
||||
subjectAttributes.Groups = tokenClaims.Groups
|
||||
}
|
||||
|
||||
actionInfos := []ActionInfo{}
|
||||
for _, action := range actions {
|
||||
actionInfos = append(actionInfos, ActionInfo{Id: action})
|
||||
}
|
||||
|
||||
return &AuthorizationRequest{
|
||||
Subject: SubjectInfo{
|
||||
Attributes: subjectAttributes,
|
||||
},
|
||||
Actions: actionInfos,
|
||||
Resource: ResourceInfo{
|
||||
Id: resourceId,
|
||||
},
|
||||
}, nil
|
||||
}
|
2
pkg/util/azureclient/authz/remotepdp/const.go → vendor/github.com/Azure/checkaccess-v2-go-sdk/client/const.go
сгенерированный
поставляемый
2
pkg/util/azureclient/authz/remotepdp/const.go → vendor/github.com/Azure/checkaccess-v2-go-sdk/client/const.go
сгенерированный
поставляемый
|
@ -1,4 +1,4 @@
|
|||
package remotepdp
|
||||
package client
|
||||
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the Apache License 2.0.
|
20
vendor/github.com/Azure/checkaccess-v2-go-sdk/client/internal/token/token.go
сгенерированный
поставляемый
Normal file
20
vendor/github.com/Azure/checkaccess-v2-go-sdk/client/internal/token/token.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,20 @@
|
|||
package token
|
||||
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the Apache License 2.0.
|
||||
|
||||
import (
|
||||
"github.com/Azure/checkaccess-v2-go-sdk/client/internal"
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
)
|
||||
|
||||
// ExtractClaims extracts the "oid", "_claim_names", and "groups" claims from a given access jwtToken and return them as a custom struct
|
||||
func ExtractClaims(jwtToken string) (*internal.Custom, error) {
|
||||
p := jwt.NewParser(jwt.WithoutClaimsValidation())
|
||||
c := &internal.Custom{}
|
||||
_, _, err := p.ParseUnverified(jwtToken, c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c, nil
|
||||
}
|
14
vendor/github.com/Azure/checkaccess-v2-go-sdk/client/internal/types.go
сгенерированный
поставляемый
Normal file
14
vendor/github.com/Azure/checkaccess-v2-go-sdk/client/internal/types.go
сгенерированный
поставляемый
Normal file
|
@ -0,0 +1,14 @@
|
|||
package internal
|
||||
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the Apache License 2.0.
|
||||
import (
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
)
|
||||
|
||||
type Custom struct {
|
||||
ObjectId string `json:"oid"`
|
||||
ClaimNames map[string]interface{} `json:"_claim_names"`
|
||||
Groups []string `json:"groups"`
|
||||
jwt.RegisteredClaims
|
||||
}
|
2
pkg/util/azureclient/authz/remotepdp/types.go → vendor/github.com/Azure/checkaccess-v2-go-sdk/client/types.go
сгенерированный
поставляемый
2
pkg/util/azureclient/authz/remotepdp/types.go → vendor/github.com/Azure/checkaccess-v2-go-sdk/client/types.go
сгенерированный
поставляемый
|
@ -1,4 +1,4 @@
|
|||
package remotepdp
|
||||
package client
|
||||
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the Apache License 2.0.
|
|
@ -20,7 +20,7 @@ github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2019-07-01/features
|
|||
github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2021-09-01/storage
|
||||
github.com/Azure/azure-sdk-for-go/storage
|
||||
github.com/Azure/azure-sdk-for-go/version
|
||||
# github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1
|
||||
# github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0
|
||||
## explicit; go 1.18
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore/arm
|
||||
|
@ -46,11 +46,11 @@ github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime
|
|||
github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore/to
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore/tracing
|
||||
# github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0
|
||||
# github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0
|
||||
## explicit; go 1.18
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity/internal
|
||||
# github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0
|
||||
# github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0
|
||||
## explicit; go 1.18
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal/diag
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal/errorinfo
|
||||
|
@ -102,6 +102,11 @@ github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/internal/shared
|
|||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/pageblob
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/sas
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/service
|
||||
# github.com/Azure/checkaccess-v2-go-sdk v0.0.3
|
||||
## explicit; go 1.21
|
||||
github.com/Azure/checkaccess-v2-go-sdk/client
|
||||
github.com/Azure/checkaccess-v2-go-sdk/client/internal
|
||||
github.com/Azure/checkaccess-v2-go-sdk/client/internal/token
|
||||
# github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161
|
||||
## explicit; go 1.16
|
||||
github.com/Azure/go-ansiterm
|
||||
|
|
Загрузка…
Ссылка в новой задаче