diff --git a/go.mod b/go.mod
index baa02412d..ab2acaa53 100644
--- a/go.mod
+++ b/go.mod
@@ -1,11 +1,11 @@
module stash.appscode.dev/vault
-go 1.21.5
+go 1.21.7
require (
cloud.google.com/go/kms v1.15.0
cloud.google.com/go/storage v1.30.1
- github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0
+ github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0
github.com/Azure/azure-sdk-for-go/sdk/keyvault/azsecrets v0.12.0
github.com/aws/aws-sdk-go v1.45.7
github.com/hashicorp/vault/api v1.10.0
@@ -23,11 +23,11 @@ require (
k8s.io/apimachinery v0.29.0
k8s.io/client-go v0.29.0
k8s.io/klog/v2 v2.110.1
- kmodules.xyz/client-go v0.29.4
- kmodules.xyz/custom-resources v0.29.0
+ kmodules.xyz/client-go v0.29.6
+ kmodules.xyz/custom-resources v0.29.1
kmodules.xyz/offshoot-api v0.29.0
- kubevault.dev/apimachinery v0.16.1-0.20231231045328-9853d93f7dcb
- stash.appscode.dev/apimachinery v0.32.1-0.20240101013736-ef308633d8b2
+ kubevault.dev/apimachinery v0.17.0
+ stash.appscode.dev/apimachinery v0.32.1-0.20240209175028-1fb8e3376f2c
)
require (
@@ -35,33 +35,39 @@ require (
cloud.google.com/go/compute v1.23.0 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
cloud.google.com/go/iam v1.1.1 // indirect
- github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0 // indirect
- github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect
+ github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0 // indirect
+ github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 // indirect
- github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1 // indirect
+ github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1 // indirect
github.com/Masterminds/semver/v3 v3.2.1 // indirect
github.com/PuerkitoBio/purell v1.2.0 // indirect
github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2 // indirect
+ github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff/v3 v3.2.2 // indirect
+ github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
+ github.com/dnaeon/go-vcr v1.2.0 // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/evanphx/json-patch v5.7.0+incompatible // indirect
- github.com/evanphx/json-patch/v5 v5.7.0 // indirect
+ github.com/evanphx/json-patch/v5 v5.8.0 // indirect
github.com/fatih/structs v1.1.0 // indirect
+ github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/go-jose/go-jose/v3 v3.0.1 // indirect
- github.com/go-logr/logr v1.3.0 // indirect
+ github.com/go-logr/logr v1.4.1 // indirect
github.com/go-openapi/jsonpointer v0.20.0 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/swag v0.22.4 // indirect
+ github.com/go-sql-driver/mysql v1.7.1 // indirect
github.com/go-test/deep v1.1.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
- github.com/golang-jwt/jwt/v5 v5.0.0 // indirect
+ github.com/golang-jwt/jwt v3.2.1+incompatible // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
+ github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 // indirect
github.com/google/s2a-go v0.1.7 // indirect
github.com/google/uuid v1.4.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.2.5 // indirect
@@ -83,17 +89,20 @@ require (
github.com/json-iterator/go v1.1.12 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
+ github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/onsi/gomega v1.30.0 // indirect
- github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
+ github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 // indirect
github.com/pkg/errors v0.9.1 // indirect
- github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.70.0 // indirect
- github.com/rogpeppe/go-internal v1.11.0 // indirect
+ github.com/prometheus/client_golang v1.18.0 // indirect
+ github.com/prometheus/client_model v0.5.0 // indirect
+ github.com/prometheus/common v0.45.0 // indirect
+ github.com/prometheus/procfs v0.12.0 // indirect
github.com/ryanuber/go-glob v1.0.0 // indirect
github.com/sergi/go-diff v1.2.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
@@ -106,8 +115,8 @@ require (
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/net v0.19.0 // indirect
golang.org/x/oauth2 v0.15.0 // indirect
- golang.org/x/sync v0.4.0 // indirect
- golang.org/x/sys v0.15.0 // indirect
+ golang.org/x/sync v0.5.0 // indirect
+ golang.org/x/sys v0.16.0 // indirect
golang.org/x/term v0.15.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.5.0 // indirect
@@ -127,14 +136,15 @@ require (
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/apiextensions-apiserver v0.29.0 // indirect
k8s.io/apiserver v0.29.0 // indirect
+ k8s.io/component-base v0.29.0 // indirect
k8s.io/kube-aggregator v0.29.0 // indirect
k8s.io/kube-openapi v0.0.0-20231129212854-f0671cc7e66a // indirect
k8s.io/utils v0.0.0-20231127182322-b307cd553661 // indirect
kmodules.xyz/apiversion v0.2.0 // indirect
kmodules.xyz/monitoring-agent-api v0.29.0 // indirect
- kmodules.xyz/objectstore-api v0.29.0 // indirect
+ kmodules.xyz/objectstore-api v0.29.1 // indirect
kmodules.xyz/prober v0.29.0 // indirect
- sigs.k8s.io/controller-runtime v0.16.3 // indirect
+ sigs.k8s.io/controller-runtime v0.17.0 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
@@ -142,10 +152,10 @@ require (
replace github.com/Masterminds/sprig/v3 => github.com/gomodules/sprig/v3 v3.2.3-0.20220405051441-0a8a99bac1b8
-replace sigs.k8s.io/controller-runtime => github.com/kmodules/controller-runtime v0.16.1-0.20231224083233-bead154270db
+replace sigs.k8s.io/controller-runtime => github.com/kmodules/controller-runtime v0.16.1-0.20240128092212-43c4e15c56b1
replace github.com/imdario/mergo => github.com/imdario/mergo v0.3.6
-replace k8s.io/apiserver => github.com/kmodules/apiserver v0.29.1-0.20231224075222-50d5bb4aeb26
+replace k8s.io/apiserver => github.com/kmodules/apiserver v0.29.1-0.20240104121741-1fb217d4a573
replace k8s.io/kubernetes => github.com/kmodules/kubernetes v1.30.0-alpha.0.0.20231224075822-3bd9a13c86db
diff --git a/go.sum b/go.sum
index f565d84ca..822288527 100644
--- a/go.sum
+++ b/go.sum
@@ -23,18 +23,18 @@ cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiy
cloud.google.com/go/storage v1.30.1 h1:uOdMxAs8HExqBlnLtnQyP0YkvbiDpdGShGKtx6U/oNM=
cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
-github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0 h1:9kDVnTz3vbfweTqAUmk/a/pH5pWFCHtvRpHYC0G/dcA=
-github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0/go.mod h1:3Ug6Qzto9anB6mGlEdgYMDF5zHQ+wwhEaYR4s17PHMw=
-github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0 h1:BMAjVKJM0U/CYF27gA0ZMmXGkOcvfFtD0oHVZ1TIPRI=
-github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0/go.mod h1:1fXstnBMas5kzG+S3q8UoJcmyU6nUeunJcMDHcRYHhs=
-github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY=
-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/azcore v1.4.0 h1:rTnT/Jrcm+figWlYz4Ixzt0SJVR2cMC8lvZcimipiEY=
+github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0/go.mod h1:ON4tFdPTwRcgWEaVDrN3584Ef+b7GgSJaXxe5fW9t4M=
+github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 h1:QkAcEIAKbNL4KoFr4SathZPhDhF4mVwpBMFlYjyAqy8=
+github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0/go.mod h1:bhXu1AjYL+wutSL/kpSq6s7733q2Rb0yuot9Zgfqa/0=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 h1:leh5DwKv6Ihwi+h60uHtn6UWAxBbZ0q8DwQVMzf61zw=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
github.com/Azure/azure-sdk-for-go/sdk/keyvault/azsecrets v0.12.0 h1:xnO4sFyG8UH2fElBkcqLTOZsAajvKfnSlgBBW8dXYjw=
github.com/Azure/azure-sdk-for-go/sdk/keyvault/azsecrets v0.12.0/go.mod h1:XD3DIOOVgBCO03OleB1fHjgktVRFxlT++KwKgIOewdM=
github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 h1:FbH3BbSb4bvGluTesZZ+ttN/MDsnMmQP36OSnDuSXqw=
github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1/go.mod h1:9V2j0jn9jDEkCkv8w/bKTNppX/d0FVA1ud77xCIP4KA=
-github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1 h1:WpB/QDNLpMw72xHJc34BNNykqSOeEJDAWkhf0u12/Jk=
-github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
+github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1 h1:BWe8a+f/t+7KY7zH2mqygeUD0t8hNFXe08p1Pb3/jKE=
+github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1/go.mod h1:Vt9sXTKwMyGcOxSmLDMnGPgqsUg7m8pe215qMLrDXw4=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0=
@@ -60,7 +60,6 @@ github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJm
github.com/cenkalti/backoff/v3 v3.2.2 h1:cfUAAO3yvKMYKPrvhDuHSwQnhZNk/RMHKdZqKTxfm6M=
github.com/cenkalti/backoff/v3 v3.2.2/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
-github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -92,8 +91,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/evanphx/json-patch v5.7.0+incompatible h1:vgGkfT/9f8zE6tvSCe74nfpAVDQ2tG6yudJd8LBksgI=
github.com/evanphx/json-patch v5.7.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
-github.com/evanphx/json-patch/v5 v5.7.0 h1:nJqP7uwL84RJInrohHfW0Fx3awjbm8qZeFv0nW9SYGc=
-github.com/evanphx/json-patch/v5 v5.7.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ=
+github.com/evanphx/json-patch/v5 v5.8.0 h1:lRj6N9Nci7MvzrXuX6HFzU8XjmhPiXPlsKEy1u0KQro=
+github.com/evanphx/json-patch/v5 v5.8.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
@@ -112,8 +111,9 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
-github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
+github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
+github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ=
github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg=
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
@@ -124,6 +124,8 @@ github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU=
github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
+github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
+github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
@@ -133,8 +135,10 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
-github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE=
-github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
+github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c=
+github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
+github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
+github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -180,11 +184,12 @@ github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdf
github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
-github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=
-github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
+github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
+github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
+github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -265,10 +270,10 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
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/kmodules/apiserver v0.29.1-0.20231224075222-50d5bb4aeb26 h1:Nb2bxGlc5VkRlIEiHzK7/0JxiAbivD4YxZ28ia5zEGI=
-github.com/kmodules/apiserver v0.29.1-0.20231224075222-50d5bb4aeb26/go.mod h1:31n78PsRKPmfpee7/l9NYEv67u6hOL6AfcE761HapDM=
-github.com/kmodules/controller-runtime v0.16.1-0.20231224083233-bead154270db h1:r0mvemGEd/vOiQDbnYh5TxLT7hN+E3r3scujge2n3Ac=
-github.com/kmodules/controller-runtime v0.16.1-0.20231224083233-bead154270db/go.mod h1:R//DPbq8lk8vvdJ931v3FxDSXkICZIssoGQ1vOSnaFg=
+github.com/kmodules/apiserver v0.29.1-0.20240104121741-1fb217d4a573 h1:6v7bTFGH/Ha1idq1sLX9px2KJhcx6cpuMowuYRyCht4=
+github.com/kmodules/apiserver v0.29.1-0.20240104121741-1fb217d4a573/go.mod h1:31n78PsRKPmfpee7/l9NYEv67u6hOL6AfcE761HapDM=
+github.com/kmodules/controller-runtime v0.16.1-0.20240128092212-43c4e15c56b1 h1:Pq/2P0Wp7HANIM6vd6YqQxZTEqlqifAzfw1Bz/CR0zo=
+github.com/kmodules/controller-runtime v0.16.1-0.20240128092212-43c4e15c56b1/go.mod h1:+MngTvIQQQhfXtwfdGw/UOQ/aIaqsYywfCINOtwMO/s=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@@ -295,8 +300,8 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k
github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98=
github.com/mattn/go-isatty v0.0.18/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.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
-github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
+github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg=
+github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
@@ -317,6 +322,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
+github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
@@ -325,14 +332,14 @@ github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JX
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
-github.com/onsi/ginkgo/v2 v2.13.2 h1:Bi2gGVkfn6gQcjNjZJVO8Gf0FHzMPf2phUei9tejVMs=
-github.com/onsi/ginkgo/v2 v2.13.2/go.mod h1:XStQ8QcGwLyF4HdfcZB8SFOS/MWCgDuXMSBe6zrvLgM=
+github.com/onsi/ginkgo/v2 v2.14.0 h1:vSmGj2Z5YPb9JwCWT6z6ihcUvDhuXLc3sJiqd3jMKAY=
+github.com/onsi/ginkgo/v2 v2.14.0/go.mod h1:JkUdW7JkN0V6rFvsHcJ478egV3XH9NxpD27Hal/PhZw=
github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8=
github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
-github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
-github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
+github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 h1:Qj1ukM4GlMWXNdMBuXcXfz/Kw9s1qm0CLY32QxuSImI=
+github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -345,8 +352,8 @@ github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.70.0 h
github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.70.0/go.mod h1:npfc20mPOAu7ViOVnATVMbI7PoXvW99EzgJVqkAomIQ=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
-github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q=
-github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY=
+github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk=
+github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@@ -354,12 +361,12 @@ github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cY
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
-github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY=
-github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY=
+github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM=
+github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
-github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI=
-github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY=
+github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
+github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
@@ -430,6 +437,8 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
+go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
+go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
@@ -505,8 +514,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
-golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
+golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
+golang.org/x/sync v0.5.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=
@@ -524,16 +533,16 @@ golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
-golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
+golang.org/x/sys v0.16.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/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -574,8 +583,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
-golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
-golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
+golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA=
+golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
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=
@@ -693,6 +702,8 @@ k8s.io/apimachinery v0.29.0 h1:+ACVktwyicPz0oc6MTMLwa2Pw3ouLAfAon1wPLtG48o=
k8s.io/apimachinery v0.29.0/go.mod h1:eVBxQ/cwiJxH58eK/jd/vAk4mrxmVlnpBH5J2GbMeis=
k8s.io/client-go v0.29.0 h1:KmlDtFcrdUzOYrBhXHgKw5ycWzc3ryPX5mQe0SkG3y8=
k8s.io/client-go v0.29.0/go.mod h1:yLkXH4HKMAywcrD82KMSmfYg2DlE8mepPR4JGSo5n38=
+k8s.io/component-base v0.29.0 h1:T7rjd5wvLnPBV1vC4zWd/iWRbV8Mdxs+nGaoaFzGw3s=
+k8s.io/component-base v0.29.0/go.mod h1:sADonFTQ9Zc9yFLghpDpmNXEdHyQmFIGbiuZbqAXQ1M=
k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0=
k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo=
@@ -704,20 +715,20 @@ k8s.io/utils v0.0.0-20231127182322-b307cd553661 h1:FepOBzJ0GXm8t0su67ln2wAZjbQ6R
k8s.io/utils v0.0.0-20231127182322-b307cd553661/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
kmodules.xyz/apiversion v0.2.0 h1:vAQYqZFm4xu4pbB1cAdHbFEPES6EQkcR4wc06xdTOWk=
kmodules.xyz/apiversion v0.2.0/go.mod h1:oPX8g8LvlPdPX3Yc5YvCzJHQnw3YF/X4/jdW0b1am80=
-kmodules.xyz/client-go v0.29.4 h1:WW4vlYtzLc9JXrJjcFuJO4DX/kIZ5ia7QtDyhNDUwfI=
-kmodules.xyz/client-go v0.29.4/go.mod h1:xWlS/1zWkx1sIKCAkzULy9570mHZYi2exDECEoP1ek4=
-kmodules.xyz/custom-resources v0.29.0 h1:RaDM2+wSVXiwIvLqmkTVYpwoH83AC8wruXe2p2rOZNY=
-kmodules.xyz/custom-resources v0.29.0/go.mod h1:MzZyXtxdg1PDxGk3RTTO1Xv3KiVqZnIonSwmxVbagOY=
+kmodules.xyz/client-go v0.29.6 h1:xTVq5LZvsPBUTLY7PORq7zveLOj/vpuTDvkpHWOk3RM=
+kmodules.xyz/client-go v0.29.6/go.mod h1:pHuzpwzEcDUIGjVVvwz9N8lY+6A7HXwvs2d7NtK7Hho=
+kmodules.xyz/custom-resources v0.29.1 h1:xiNylhs3ILRbcUhxxy306AOy9GMA4Mq7xFIptZKgal4=
+kmodules.xyz/custom-resources v0.29.1/go.mod h1:829zDY1EjaxPP52h1T73LZx/vgv8Pld9/uTT/ViZTc0=
kmodules.xyz/monitoring-agent-api v0.29.0 h1:gpFl6OZrlMLb/ySMHdREI9EwGtnJ91oZBn9H1UFRwB4=
kmodules.xyz/monitoring-agent-api v0.29.0/go.mod h1:iNbvaMTgVFOI5q2LJtGK91j4Dmjv4ZRiRdasGmWLKQI=
-kmodules.xyz/objectstore-api v0.29.0 h1:dK53fQXdoboyW/EyBBAMjykT8u7jstKrM1DS4RJvhEU=
-kmodules.xyz/objectstore-api v0.29.0/go.mod h1:Kxmv6F7Kd/7EoKX3X2xIzhHT++zlj2qdXLcp/8avUYI=
+kmodules.xyz/objectstore-api v0.29.1 h1:uUsjf8KU0w4LYowSEOnl0AbHT3hsHIu1wNLHqGe1o6s=
+kmodules.xyz/objectstore-api v0.29.1/go.mod h1:xG+5awH1SXYKxwN/+k1FEQvzixd5tgNqEN/1LEiB2FE=
kmodules.xyz/offshoot-api v0.29.0 h1:GHLhxxT9jU1N8+FvOCCeJNyU5g0duYS46UGrs6AHNLY=
kmodules.xyz/offshoot-api v0.29.0/go.mod h1:5NxhBblXoDHWStx9HCDJR2KFTwYjEZ7i1Id3jelIunw=
kmodules.xyz/prober v0.29.0 h1:Ex7m4F9rH7uWNNJlLgP63ROOM+nUATJkC2L5OQ7nwMg=
kmodules.xyz/prober v0.29.0/go.mod h1:UtK+HKyI1lFLEKX+HFLyOCVju6TO93zv3kwGpzqmKOo=
-kubevault.dev/apimachinery v0.16.1-0.20231231045328-9853d93f7dcb h1:thbKOmbGRI2EAUPepXY4Dp4AHc8Nm8GJ7Tana0BpMr0=
-kubevault.dev/apimachinery v0.16.1-0.20231231045328-9853d93f7dcb/go.mod h1:PIkUIpDCY5S/c9LxgeTaS8uuZDFRoP18FCmGCUK3WFI=
+kubevault.dev/apimachinery v0.17.0 h1:6NpSSTCk2ZeFTGb4DEVEzHZYAN2d6Nz36borHHevuFM=
+kubevault.dev/apimachinery v0.17.0/go.mod h1:ImeKe0ZBHRHzbfZNPb25lS53CDaAh5daXj/W/G2ag5Q=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
@@ -725,5 +736,5 @@ sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+s
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
-stash.appscode.dev/apimachinery v0.32.1-0.20240101013736-ef308633d8b2 h1:dePrbjp7o57sKe33K1ppaWQK/Ely4QgxmCcab0sDOpY=
-stash.appscode.dev/apimachinery v0.32.1-0.20240101013736-ef308633d8b2/go.mod h1:hTslVqyx20fF2i2s/m0rqXD+pZwnI2oG3k5zPzsDnXQ=
+stash.appscode.dev/apimachinery v0.32.1-0.20240209175028-1fb8e3376f2c h1:swyyQ3GXY7/DkOCCPe9s8FO4+g8/D47eCwDZyOyAOC0=
+stash.appscode.dev/apimachinery v0.32.1-0.20240209175028-1fb8e3376f2c/go.mod h1:E+mbh2FR1oKyP7WQS5W3MzOrZ3iZUSvrzSCCJPa8qRc=
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/CHANGELOG.md b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/CHANGELOG.md
index b618676c5..5ad5318d2 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/CHANGELOG.md
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/CHANGELOG.md
@@ -1,121 +1,5 @@
# Release History
-## 1.8.0 (2023-10-05)
-
-### Features Added
-
-* Added `Claims` and `EnableCAE` fields to `policy.TokenRequestOptions`.
-* ARM bearer token policy handles CAE challenges.
-* `messaging/CloudEvent` allows you to serialize/deserialize CloudEvents, as described in the CloudEvents 1.0 specification: [link](https://github.com/cloudevents/spec)
-* Added functions `FetcherForNextLink` and `EncodeQueryParams` along with `FetcherForNextLinkOptions` to the `runtime` package to centralize creation of `Pager[T].Fetcher` from a next link URL.
-* Added types `KeyCredential` and `SASCredential` to the `azcore` package.
- * Includes their respective constructor functions.
-* Added types `KeyCredentialPolicy` and `SASCredentialPolicy` to the `azcore/runtime` package.
- * Includes their respective constructor functions and options types.
-
-### Breaking Changes
-> These changes affect only code written against beta versions of `v1.8.0`
-* The beta features for tracing and fakes have been omitted for this release.
-
-### Bugs Fixed
-
-* Fixed an issue that could cause some ARM RPs to not be automatically registered.
-* Block bearer token authentication for non TLS protected endpoints.
-
-### Other Changes
-
-* The following functions in the `runtime` package are now exposed from the `policy` package, and the `runtime` versions have been deprecated.
- * `WithCaptureResponse`
- * `WithHTTPHeader`
- * `WithRetryOptions`
-* Updated dependencies.
-
-## 1.7.2 (2023-09-06)
-
-### Bugs Fixed
-
-* Fix default HTTP transport to work in WASM modules.
-
-## 1.7.1 (2023-08-14)
-
-## Bugs Fixed
-
-* Enable TLS renegotiation in the default transport policy.
-
-## 1.7.0 (2023-07-12)
-
-### Features Added
-* Added method `WithClientName()` to type `azcore.Client` to support shallow cloning of a client with a new name used for tracing.
-
-### Breaking Changes
-> These changes affect only code written against beta versions v1.7.0-beta.1 or v1.7.0-beta.2
-* The beta features for CAE, tracing, and fakes have been omitted for this release.
-
-## 1.7.0-beta.2 (2023-06-06)
-
-### Breaking Changes
-> These changes affect only code written against beta version v1.7.0-beta.1
-* Method `SpanFromContext()` on type `tracing.Tracer` had the `bool` return value removed.
- * This includes the field `SpanFromContext` in supporting type `tracing.TracerOptions`.
-* Method `AddError()` has been removed from type `tracing.Span`.
-* Method `Span.End()` now requires an argument of type `*tracing.SpanEndOptions`.
-
-## 1.6.1 (2023-06-06)
-
-### Bugs Fixed
-* Fixed an issue in `azcore.NewClient()` and `arm.NewClient()` that could cause an incorrect module name to be used in telemetry.
-
-### Other Changes
-* This version contains all bug fixes from `v1.7.0-beta.1`
-
-## 1.7.0-beta.1 (2023-05-24)
-
-### Features Added
-* Restored CAE support for ARM clients.
-* Added supporting features to enable distributed tracing.
- * Added func `runtime.StartSpan()` for use by SDKs to start spans.
- * Added method `WithContext()` to `runtime.Request` to support shallow cloning with a new context.
- * Added field `TracingNamespace` to `runtime.PipelineOptions`.
- * Added field `Tracer` to `runtime.NewPollerOptions` and `runtime.NewPollerFromResumeTokenOptions` types.
- * Added field `SpanFromContext` to `tracing.TracerOptions`.
- * Added methods `Enabled()`, `SetAttributes()`, and `SpanFromContext()` to `tracing.Tracer`.
- * Added supporting pipeline policies to include HTTP spans when creating clients.
-* Added package `fake` to support generated fakes packages in SDKs.
- * The package contains public surface area exposed by fake servers and supporting APIs intended only for use by the fake server implementations.
- * Added an internal fake poller implementation.
-
-### Bugs Fixed
-* Retry policy always clones the underlying `*http.Request` before invoking the next policy.
-* Added some non-standard error codes to the list of error codes for unregistered resource providers.
-
-## 1.6.0 (2023-05-04)
-
-### Features Added
-* Added support for ARM cross-tenant authentication. Set the `AuxiliaryTenants` field of `arm.ClientOptions` to enable.
-* Added `TenantID` field to `policy.TokenRequestOptions`.
-
-## 1.5.0 (2023-04-06)
-
-### Features Added
-* Added `ShouldRetry` to `policy.RetryOptions` for finer-grained control over when to retry.
-
-### Breaking Changes
-> These changes affect only code written against a beta version such as v1.5.0-beta.1
-> These features will return in v1.6.0-beta.1.
-* Removed `TokenRequestOptions.Claims` and `.TenantID`
-* Removed ARM client support for CAE and cross-tenant auth.
-
-### Bugs Fixed
-* Added non-conformant LRO terminal states `Cancelled` and `Completed`.
-
-### Other Changes
-* Updated to latest `internal` module.
-
-## 1.5.0-beta.1 (2023-03-02)
-
-### Features Added
-* This release includes the features added in v1.4.0-beta.1
-
## 1.4.0 (2023-03-02)
> This release doesn't include features added in v1.4.0-beta.1. They will return in v1.5.0-beta.1.
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/core.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/core.go
index 9f051ba4a..72c2cf21e 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/core.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/core.go
@@ -22,24 +22,6 @@ type AccessToken = exported.AccessToken
// TokenCredential represents a credential capable of providing an OAuth token.
type TokenCredential = exported.TokenCredential
-// KeyCredential contains an authentication key used to authenticate to an Azure service.
-type KeyCredential = exported.KeyCredential
-
-// NewKeyCredential creates a new instance of [KeyCredential] with the specified values.
-// - key is the authentication key
-func NewKeyCredential(key string) *KeyCredential {
- return exported.NewKeyCredential(key)
-}
-
-// SASCredential contains a shared access signature used to authenticate to an Azure service.
-type SASCredential = exported.SASCredential
-
-// NewSASCredential creates a new instance of [SASCredential] with the specified values.
-// - sas is the shared access signature
-func NewSASCredential(sas string) *SASCredential {
- return exported.NewSASCredential(sas)
-}
-
// holds sentinel values used to send nulls
var nullables map[reflect.Type]interface{} = map[reflect.Type]interface{}{}
@@ -91,20 +73,15 @@ type ClientOptions = policy.ClientOptions
type Client struct {
pl runtime.Pipeline
tr tracing.Tracer
-
- // cached on the client to support shallow copying with new values
- tp tracing.Provider
- modVer string
}
// NewClient creates a new Client instance with the provided values.
-// - clientName - the fully qualified name of the client ("module/package.Client"); this is used by the telemetry policy and tracing provider.
-// if module and package are the same value, the "module/" prefix can be omitted.
+// - clientName - the fully qualified name of the client ("package.Client"); this is used by the tracing provider when creating spans
// - moduleVersion - the semantic version of the containing module; used by the telemetry policy
// - plOpts - pipeline configuration options; can be the zero-value
// - options - optional client configurations; pass nil to accept the default values
func NewClient(clientName, moduleVersion string, plOpts runtime.PipelineOptions, options *ClientOptions) (*Client, error) {
- mod, client, err := shared.ExtractModuleName(clientName)
+ pkg, err := shared.ExtractPackageName(clientName)
if err != nil {
return nil, err
}
@@ -119,16 +96,10 @@ func NewClient(clientName, moduleVersion string, plOpts runtime.PipelineOptions,
}
}
- pl := runtime.NewPipeline(mod, moduleVersion, plOpts, options)
-
- tr := options.TracingProvider.NewTracer(client, moduleVersion)
+ pl := runtime.NewPipeline(pkg, moduleVersion, plOpts, options)
- return &Client{
- pl: pl,
- tr: tr,
- tp: options.TracingProvider,
- modVer: moduleVersion,
- }, nil
+ tr := options.TracingProvider.NewTracer(clientName, moduleVersion)
+ return &Client{pl: pl, tr: tr}, nil
}
// Pipeline returns the pipeline for this client.
@@ -140,11 +111,3 @@ func (c *Client) Pipeline() runtime.Pipeline {
func (c *Client) Tracer() tracing.Tracer {
return c.tr
}
-
-// WithClientName returns a shallow copy of the Client with its tracing client name changed to clientName.
-// Note that the values for module name and version will be preserved from the source Client.
-// - clientName - the fully qualified name of the client ("package.Client"); this is used by the tracing provider when creating spans
-func (c *Client) WithClientName(clientName string) *Client {
- tr := c.tp.NewTracer(clientName, c.modVer)
- return &Client{pl: c.pl, tr: tr, tp: c.tp, modVer: c.modVer}
-}
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/exported.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/exported.go
index e793b31db..2ffbc0e47 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/exported.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/exported.go
@@ -10,8 +10,9 @@ import (
"context"
"io"
"net/http"
- "sync/atomic"
"time"
+
+ "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared"
)
type nopCloser struct {
@@ -42,6 +43,24 @@ func HasStatusCode(resp *http.Response, statusCodes ...int) bool {
return false
}
+// Payload reads and returns the response body or an error.
+// On a successful read, the response body is cached.
+// Subsequent reads will access the cached value.
+// Exported as runtime.Payload().
+func Payload(resp *http.Response) ([]byte, error) {
+ // r.Body won't be a nopClosingBytesReader if downloading was skipped
+ if buf, ok := resp.Body.(*shared.NopClosingBytesReader); ok {
+ return buf.Bytes(), nil
+ }
+ bytesBody, err := io.ReadAll(resp.Body)
+ resp.Body.Close()
+ if err != nil {
+ return nil, err
+ }
+ resp.Body = shared.NewNopClosingBytesReader(bytesBody)
+ return bytesBody, nil
+}
+
// AccessToken represents an Azure service bearer access token with expiry information.
// Exported as azcore.AccessToken.
type AccessToken struct {
@@ -52,23 +71,8 @@ type AccessToken struct {
// TokenRequestOptions contain specific parameter that may be used by credentials types when attempting to get a token.
// Exported as policy.TokenRequestOptions.
type TokenRequestOptions struct {
- // Claims are any additional claims required for the token to satisfy a conditional access policy, such as a
- // service may return in a claims challenge following an authorization failure. If a service returned the
- // claims value base64 encoded, it must be decoded before setting this field.
- Claims string
-
- // EnableCAE indicates whether to enable Continuous Access Evaluation (CAE) for the requested token. When true,
- // azidentity credentials request CAE tokens for resource APIs supporting CAE. Clients are responsible for
- // handling CAE challenges. If a client that doesn't handle CAE challenges receives a CAE token, it may end up
- // in a loop retrying an API call with a token that has been revoked due to CAE.
- EnableCAE bool
-
// Scopes contains the list of permission scopes required for the token.
Scopes []string
-
- // TenantID identifies the tenant from which to request the token. azidentity credentials authenticate in
- // their configured default tenants when this field isn't set.
- TenantID string
}
// TokenCredential represents a credential capable of providing an OAuth token.
@@ -77,65 +81,3 @@ type TokenCredential interface {
// GetToken requests an access token for the specified set of scopes.
GetToken(ctx context.Context, options TokenRequestOptions) (AccessToken, error)
}
-
-// KeyCredential contains an authentication key used to authenticate to an Azure service.
-// Exported as azcore.KeyCredential.
-type KeyCredential struct {
- cred *keyCredential
-}
-
-// NewKeyCredential creates a new instance of [KeyCredential] with the specified values.
-// - key is the authentication key
-func NewKeyCredential(key string) *KeyCredential {
- return &KeyCredential{cred: newKeyCredential(key)}
-}
-
-// Update replaces the existing key with the specified value.
-func (k *KeyCredential) Update(key string) {
- k.cred.Update(key)
-}
-
-// SASCredential contains a shared access signature used to authenticate to an Azure service.
-// Exported as azcore.SASCredential.
-type SASCredential struct {
- cred *keyCredential
-}
-
-// NewSASCredential creates a new instance of [SASCredential] with the specified values.
-// - sas is the shared access signature
-func NewSASCredential(sas string) *SASCredential {
- return &SASCredential{cred: newKeyCredential(sas)}
-}
-
-// Update replaces the existing shared access signature with the specified value.
-func (k *SASCredential) Update(sas string) {
- k.cred.Update(sas)
-}
-
-// KeyCredentialGet returns the key for cred.
-func KeyCredentialGet(cred *KeyCredential) string {
- return cred.cred.Get()
-}
-
-// SASCredentialGet returns the shared access sig for cred.
-func SASCredentialGet(cred *SASCredential) string {
- return cred.cred.Get()
-}
-
-type keyCredential struct {
- key atomic.Value // string
-}
-
-func newKeyCredential(key string) *keyCredential {
- keyCred := keyCredential{}
- keyCred.key.Store(key)
- return &keyCred
-}
-
-func (k *keyCredential) Get() string {
- return k.key.Load().(string)
-}
-
-func (k *keyCredential) Update(key string) {
- k.key.Store(key)
-}
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/response_error.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/response_error.go
index 7df2f88c1..3db6acc83 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/response_error.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/response_error.go
@@ -12,8 +12,6 @@ import (
"fmt"
"net/http"
"regexp"
-
- "github.com/Azure/azure-sdk-for-go/sdk/internal/exported"
)
// NewResponseError creates a new *ResponseError from the provided HTTP response.
@@ -31,7 +29,7 @@ func NewResponseError(resp *http.Response) error {
}
// if we didn't get x-ms-error-code, check in the response body
- body, err := exported.Payload(resp, nil)
+ body, err := Payload(resp)
if err != nil {
return err
}
@@ -123,7 +121,7 @@ func (e *ResponseError) Error() string {
fmt.Fprintln(msg, "ERROR CODE UNAVAILABLE")
}
fmt.Fprintln(msg, "--------------------------------------------------------------------------------")
- body, err := exported.Payload(e.RawResponse, nil)
+ body, err := Payload(e.RawResponse)
if err != nil {
// this really shouldn't fail at this point as the response
// body is already cached (it was read in NewResponseError)
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/async/async.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/async/async.go
index b05bd8b38..d34f161c7 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/async/async.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/async/async.go
@@ -16,7 +16,6 @@ import (
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/log"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared"
- "github.com/Azure/azure-sdk-for-go/sdk/internal/poller"
)
// see https://github.com/Azure/azure-resource-manager-rpc/blob/master/v1.0/async-api-reference.md
@@ -69,15 +68,15 @@ func New[T any](pl exported.Pipeline, resp *http.Response, finalState pollers.Fi
if asyncURL == "" {
return nil, errors.New("response is missing Azure-AsyncOperation header")
}
- if !poller.IsValidURL(asyncURL) {
+ if !pollers.IsValidURL(asyncURL) {
return nil, fmt.Errorf("invalid polling URL %s", asyncURL)
}
// check for provisioning state. if the operation is a RELO
// and terminates synchronously this will prevent extra polling.
// it's ok if there's no provisioning state.
- state, _ := poller.GetProvisioningState(resp)
+ state, _ := pollers.GetProvisioningState(resp)
if state == "" {
- state = poller.StatusInProgress
+ state = pollers.StatusInProgress
}
p := &Poller[T]{
pl: pl,
@@ -94,17 +93,17 @@ func New[T any](pl exported.Pipeline, resp *http.Response, finalState pollers.Fi
// Done returns true if the LRO is in a terminal state.
func (p *Poller[T]) Done() bool {
- return poller.IsTerminalState(p.CurState)
+ return pollers.IsTerminalState(p.CurState)
}
// Poll retrieves the current state of the LRO.
func (p *Poller[T]) Poll(ctx context.Context) (*http.Response, error) {
err := pollers.PollHelper(ctx, p.AsyncURL, p.pl, func(resp *http.Response) (string, error) {
- if !poller.StatusCodeValid(resp) {
+ if !pollers.StatusCodeValid(resp) {
p.resp = resp
return "", exported.NewResponseError(resp)
}
- state, err := poller.GetStatus(resp)
+ state, err := pollers.GetStatus(resp)
if err != nil {
return "", err
} else if state == "" {
@@ -123,7 +122,7 @@ func (p *Poller[T]) Poll(ctx context.Context) (*http.Response, error) {
func (p *Poller[T]) Result(ctx context.Context, out *T) error {
if p.resp.StatusCode == http.StatusNoContent {
return nil
- } else if poller.Failed(p.CurState) {
+ } else if pollers.Failed(p.CurState) {
return exported.NewResponseError(p.resp)
}
var req *exported.Request
@@ -155,5 +154,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, pollers.Failed(p.CurState), out)
}
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/body/body.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/body/body.go
index 2bb9e105b..7efdd8a0d 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/body/body.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/body/body.go
@@ -14,7 +14,6 @@ import (
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/log"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers"
- "github.com/Azure/azure-sdk-for-go/sdk/internal/poller"
)
// Kind is the identifier of this type in a resume token.
@@ -73,9 +72,9 @@ func New[T any](pl exported.Pipeline, resp *http.Response) (*Poller[T], error) {
}
// default initial state to InProgress. depending on the HTTP
// status code and provisioning state, we might change the value.
- curState := poller.StatusInProgress
- provState, err := poller.GetProvisioningState(resp)
- if err != nil && !errors.Is(err, poller.ErrNoBody) {
+ curState := pollers.StatusInProgress
+ provState, err := pollers.GetProvisioningState(resp)
+ if err != nil && !errors.Is(err, pollers.ErrNoBody) {
return nil, err
}
if resp.StatusCode == http.StatusCreated && provState != "" {
@@ -86,37 +85,37 @@ func New[T any](pl exported.Pipeline, resp *http.Response) (*Poller[T], error) {
curState = provState
} else if provState == "" {
// for a 200, absense of provisioning state indicates success
- curState = poller.StatusSucceeded
+ curState = pollers.StatusSucceeded
}
} else if resp.StatusCode == http.StatusNoContent {
- curState = poller.StatusSucceeded
+ curState = pollers.StatusSucceeded
}
p.CurState = curState
return p, nil
}
func (p *Poller[T]) Done() bool {
- return poller.IsTerminalState(p.CurState)
+ return pollers.IsTerminalState(p.CurState)
}
func (p *Poller[T]) Poll(ctx context.Context) (*http.Response, error) {
err := pollers.PollHelper(ctx, p.PollURL, p.pl, func(resp *http.Response) (string, error) {
- if !poller.StatusCodeValid(resp) {
+ if !pollers.StatusCodeValid(resp) {
p.resp = resp
return "", exported.NewResponseError(resp)
}
if resp.StatusCode == http.StatusNoContent {
p.resp = resp
- p.CurState = poller.StatusSucceeded
+ p.CurState = pollers.StatusSucceeded
return p.CurState, nil
}
- state, err := poller.GetProvisioningState(resp)
- if errors.Is(err, poller.ErrNoBody) {
+ state, err := pollers.GetProvisioningState(resp)
+ if errors.Is(err, pollers.ErrNoBody) {
// a missing response body in non-204 case is an error
return "", err
} else if state == "" {
// a response body without provisioning state is considered terminal success
- state = poller.StatusSucceeded
+ state = pollers.StatusSucceeded
} else if err != nil {
return "", err
}
@@ -131,5 +130,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, pollers.Failed(p.CurState), out)
}
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/loc/loc.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/loc/loc.go
index d6be89876..276685da4 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/loc/loc.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/loc/loc.go
@@ -16,7 +16,6 @@ import (
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/log"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared"
- "github.com/Azure/azure-sdk-for-go/sdk/internal/poller"
)
// Kind is the identifier of this type in a resume token.
@@ -62,15 +61,15 @@ func New[T any](pl exported.Pipeline, resp *http.Response) (*Poller[T], error) {
if locURL == "" {
return nil, errors.New("response is missing Location header")
}
- if !poller.IsValidURL(locURL) {
+ if !pollers.IsValidURL(locURL) {
return nil, fmt.Errorf("invalid polling URL %s", locURL)
}
// check for provisioning state. if the operation is a RELO
// and terminates synchronously this will prevent extra polling.
// it's ok if there's no provisioning state.
- state, _ := poller.GetProvisioningState(resp)
+ state, _ := pollers.GetProvisioningState(resp)
if state == "" {
- state = poller.StatusInProgress
+ state = pollers.StatusInProgress
}
return &Poller[T]{
pl: pl,
@@ -82,7 +81,7 @@ func New[T any](pl exported.Pipeline, resp *http.Response) (*Poller[T], error) {
}
func (p *Poller[T]) Done() bool {
- return poller.IsTerminalState(p.CurState)
+ return pollers.IsTerminalState(p.CurState)
}
func (p *Poller[T]) Poll(ctx context.Context) (*http.Response, error) {
@@ -94,17 +93,17 @@ func (p *Poller[T]) Poll(ctx context.Context) (*http.Response, error) {
// if provisioning state is available, use that. this is only
// for some ARM LRO scenarios (e.g. DELETE with a Location header)
// so if it's missing then use HTTP status code.
- provState, _ := poller.GetProvisioningState(resp)
+ provState, _ := pollers.GetProvisioningState(resp)
p.resp = resp
if provState != "" {
p.CurState = provState
} else if resp.StatusCode == http.StatusAccepted {
- p.CurState = poller.StatusInProgress
+ p.CurState = pollers.StatusInProgress
} else if resp.StatusCode > 199 && resp.StatusCode < 300 {
// any 2xx other than a 202 indicates success
- p.CurState = poller.StatusSucceeded
+ p.CurState = pollers.StatusSucceeded
} else {
- p.CurState = poller.StatusFailed
+ p.CurState = pollers.StatusFailed
}
return p.CurState, nil
})
@@ -115,5 +114,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, pollers.Failed(p.CurState), out)
}
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/op/op.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/op/op.go
index 1bc7ad0ac..c3c648266 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/op/op.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/op/op.go
@@ -16,7 +16,6 @@ import (
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/log"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared"
- "github.com/Azure/azure-sdk-for-go/sdk/internal/poller"
)
// Applicable returns true if the LRO is using Operation-Location.
@@ -55,19 +54,19 @@ func New[T any](pl exported.Pipeline, resp *http.Response, finalState pollers.Fi
if opURL == "" {
return nil, errors.New("response is missing Operation-Location header")
}
- if !poller.IsValidURL(opURL) {
+ if !pollers.IsValidURL(opURL) {
return nil, fmt.Errorf("invalid Operation-Location URL %s", opURL)
}
locURL := resp.Header.Get(shared.HeaderLocation)
// Location header is optional
- if locURL != "" && !poller.IsValidURL(locURL) {
+ if locURL != "" && !pollers.IsValidURL(locURL) {
return nil, fmt.Errorf("invalid Location URL %s", locURL)
}
// default initial state to InProgress. if the
// service sent us a status then use that instead.
- curState := poller.StatusInProgress
- status, err := poller.GetStatus(resp)
- if err != nil && !errors.Is(err, poller.ErrNoBody) {
+ curState := pollers.StatusInProgress
+ status, err := pollers.GetStatus(resp)
+ if err != nil && !errors.Is(err, pollers.ErrNoBody) {
return nil, err
}
if status != "" {
@@ -87,16 +86,16 @@ func New[T any](pl exported.Pipeline, resp *http.Response, finalState pollers.Fi
}
func (p *Poller[T]) Done() bool {
- return poller.IsTerminalState(p.CurState)
+ return pollers.IsTerminalState(p.CurState)
}
func (p *Poller[T]) Poll(ctx context.Context) (*http.Response, error) {
err := pollers.PollHelper(ctx, p.OpLocURL, p.pl, func(resp *http.Response) (string, error) {
- if !poller.StatusCodeValid(resp) {
+ if !pollers.StatusCodeValid(resp) {
p.resp = resp
return "", exported.NewResponseError(resp)
}
- state, err := poller.GetStatus(resp)
+ state, err := pollers.GetStatus(resp)
if err != nil {
return "", err
} else if state == "" {
@@ -119,7 +118,7 @@ func (p *Poller[T]) Result(ctx context.Context, out *T) error {
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) {
+ } else if rl, rlErr := pollers.GetResourceLocation(p.resp); rlErr != nil && !errors.Is(rlErr, pollers.ErrNoBody) {
return rlErr
} else if rl != "" {
req, err = exported.NewRequest(ctx, http.MethodGet, rl)
@@ -141,5 +140,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, pollers.Failed(p.CurState), out)
}
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/util.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/util.go
index d8d86a46c..17ab7dadc 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/util.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/util.go
@@ -12,15 +12,49 @@ import (
"errors"
"fmt"
"net/http"
+ "net/url"
"reflect"
+ "strings"
- azexported "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported"
+ "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/log"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared"
- "github.com/Azure/azure-sdk-for-go/sdk/internal/exported"
- "github.com/Azure/azure-sdk-for-go/sdk/internal/poller"
)
+// the well-known set of LRO status/provisioning state values.
+const (
+ StatusSucceeded = "Succeeded"
+ StatusCanceled = "Canceled"
+ StatusFailed = "Failed"
+ StatusInProgress = "InProgress"
+)
+
+// IsTerminalState returns true if the LRO's state is terminal.
+func IsTerminalState(s string) bool {
+ return strings.EqualFold(s, StatusSucceeded) || strings.EqualFold(s, StatusFailed) || strings.EqualFold(s, StatusCanceled)
+}
+
+// Failed returns true if the LRO's state is terminal failure.
+func Failed(s string) bool {
+ return strings.EqualFold(s, StatusFailed) || strings.EqualFold(s, StatusCanceled)
+}
+
+// Succeeded returns true if the LRO's state is terminal success.
+func Succeeded(s string) bool {
+ return strings.EqualFold(s, StatusSucceeded)
+}
+
+// returns true if the LRO response contains a valid HTTP status code
+func StatusCodeValid(resp *http.Response) bool {
+ return exported.HasStatusCode(resp, http.StatusOK, http.StatusAccepted, http.StatusCreated, http.StatusNoContent)
+}
+
+// IsValidURL verifies that the URL is valid and absolute.
+func IsValidURL(s string) bool {
+ u, err := url.Parse(s)
+ return err == nil && u.IsAbs()
+}
+
// getTokenTypeName creates a type name from the type parameter T.
func getTokenTypeName[T any]() (string, error) {
tt := shared.TypeOfT[T]()
@@ -96,6 +130,102 @@ func IsTokenValid[T any](token string) error {
return nil
}
+// ErrNoBody is returned if the response didn't contain a body.
+var ErrNoBody = errors.New("the response did not contain a body")
+
+// GetJSON reads the response body into a raw JSON object.
+// It returns ErrNoBody if there was no content.
+func GetJSON(resp *http.Response) (map[string]interface{}, error) {
+ body, err := exported.Payload(resp)
+ if err != nil {
+ return nil, err
+ }
+ if len(body) == 0 {
+ return nil, ErrNoBody
+ }
+ // unmarshall the body to get the value
+ var jsonBody map[string]interface{}
+ if err = json.Unmarshal(body, &jsonBody); err != nil {
+ return nil, err
+ }
+ return jsonBody, nil
+}
+
+// provisioningState returns the provisioning state from the response or the empty string.
+func provisioningState(jsonBody map[string]interface{}) string {
+ jsonProps, ok := jsonBody["properties"]
+ if !ok {
+ return ""
+ }
+ props, ok := jsonProps.(map[string]interface{})
+ if !ok {
+ return ""
+ }
+ rawPs, ok := props["provisioningState"]
+ if !ok {
+ return ""
+ }
+ ps, ok := rawPs.(string)
+ if !ok {
+ return ""
+ }
+ return ps
+}
+
+// status returns the status from the response or the empty string.
+func status(jsonBody map[string]interface{}) string {
+ rawStatus, ok := jsonBody["status"]
+ if !ok {
+ return ""
+ }
+ status, ok := rawStatus.(string)
+ if !ok {
+ return ""
+ }
+ return status
+}
+
+// GetStatus returns the LRO's status from the response body.
+// Typically used for Azure-AsyncOperation flows.
+// If there is no status in the response body the empty string is returned.
+func GetStatus(resp *http.Response) (string, error) {
+ jsonBody, err := GetJSON(resp)
+ if err != nil {
+ return "", err
+ }
+ return status(jsonBody), nil
+}
+
+// GetProvisioningState returns the LRO's state from the response body.
+// If there is no state in the response body the empty string is returned.
+func GetProvisioningState(resp *http.Response) (string, error) {
+ jsonBody, err := GetJSON(resp)
+ if err != nil {
+ return "", err
+ }
+ return provisioningState(jsonBody), nil
+}
+
+// GetResourceLocation returns the LRO's resourceLocation value from the response body.
+// Typically used for Operation-Location flows.
+// If there is no resourceLocation in the response body the empty string is returned.
+func GetResourceLocation(resp *http.Response) (string, error) {
+ jsonBody, err := GetJSON(resp)
+ if err != nil {
+ return "", err
+ }
+ v, ok := jsonBody["resourceLocation"]
+ if !ok {
+ // it might be ok if the field doesn't exist, the caller must make that determination
+ return "", nil
+ }
+ vv, ok := v.(string)
+ if !ok {
+ return "", fmt.Errorf("the resourceLocation value %v was not in string format", v)
+ }
+ return vv, nil
+}
+
// used if the operation synchronously completed
type NopPoller[T any] struct {
resp *http.Response
@@ -109,7 +239,7 @@ func NewNopPoller[T any](resp *http.Response) (*NopPoller[T], error) {
if resp.StatusCode == http.StatusNoContent {
return np, nil
}
- payload, err := exported.Payload(resp, nil)
+ payload, err := exported.Payload(resp)
if err != nil {
return nil, err
}
@@ -139,8 +269,8 @@ func (p *NopPoller[T]) Result(ctx context.Context, out *T) error {
// If the request fails, the update func is not called.
// The update func returns the state of the operation for logging purposes or an error
// if it fails to extract the required state from the response.
-func PollHelper(ctx context.Context, endpoint string, pl azexported.Pipeline, update func(resp *http.Response) (string, error)) error {
- req, err := azexported.NewRequest(ctx, http.MethodGet, endpoint)
+func PollHelper(ctx context.Context, endpoint string, pl exported.Pipeline, update func(resp *http.Response) (string, error)) error {
+ req, err := exported.NewRequest(ctx, http.MethodGet, endpoint)
if err != nil {
return err
}
@@ -166,13 +296,13 @@ func ResultHelper[T any](resp *http.Response, failed bool, out *T) error {
}
defer resp.Body.Close()
- if !poller.StatusCodeValid(resp) || failed {
+ if !StatusCodeValid(resp) || failed {
// the LRO failed. unmarshall the error and update state
- return azexported.NewResponseError(resp)
+ return exported.NewResponseError(resp)
}
// success case
- payload, err := exported.Payload(resp, nil)
+ payload, err := exported.Payload(resp)
if err != nil {
return err
}
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/constants.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/constants.go
index 05e53aa76..b3b477f90 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/constants.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/constants.go
@@ -21,7 +21,6 @@ const (
HeaderOperationLocation = "Operation-Location"
HeaderRetryAfter = "Retry-After"
HeaderUserAgent = "User-Agent"
- HeaderWWWAuthenticate = "WWW-Authenticate"
HeaderXMSClientRequestID = "x-ms-client-request-id"
)
@@ -32,5 +31,5 @@ const (
Module = "azcore"
// Version is the semantic version (see http://semver.org) of this module.
- Version = "v1.8.0"
+ Version = "v1.4.0"
)
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/shared.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/shared.go
index 1bf3aca91..7c71df307 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/shared.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/shared.go
@@ -8,14 +8,15 @@ package shared
import (
"context"
+ "errors"
"fmt"
+ "io"
"net/http"
"reflect"
"regexp"
"strconv"
+ "strings"
"time"
-
- "github.com/Azure/azure-sdk-for-go/sdk/internal/errorinfo"
)
// CtxWithHTTPHeaderKey is used as a context key for adding/retrieving http.Header.
@@ -24,8 +25,8 @@ type CtxWithHTTPHeaderKey struct{}
// CtxWithRetryOptionsKey is used as a context key for adding/retrieving RetryOptions.
type CtxWithRetryOptionsKey struct{}
-// CtxWithCaptureResponse is used as a context key for retrieving the raw response.
-type CtxWithCaptureResponse struct{}
+// CtxIncludeResponseKey is used as a context key for retrieving the raw response.
+type CtxIncludeResponseKey struct{}
// Delay waits for the duration to elapse or the context to be cancelled.
func Delay(ctx context.Context, delay time.Duration) error {
@@ -63,6 +64,71 @@ func TypeOfT[T any]() reflect.Type {
return reflect.TypeOf((*T)(nil)).Elem()
}
+// BytesSetter abstracts replacing a byte slice on some type.
+type BytesSetter interface {
+ Set(b []byte)
+}
+
+// NewNopClosingBytesReader creates a new *NopClosingBytesReader for the specified slice.
+func NewNopClosingBytesReader(data []byte) *NopClosingBytesReader {
+ return &NopClosingBytesReader{s: data}
+}
+
+// NopClosingBytesReader is an io.ReadSeekCloser around a byte slice.
+// It also provides direct access to the byte slice to avoid rereading.
+type NopClosingBytesReader struct {
+ s []byte
+ i int64
+}
+
+// Bytes returns the underlying byte slice.
+func (r *NopClosingBytesReader) Bytes() []byte {
+ return r.s
+}
+
+// Close implements the io.Closer interface.
+func (*NopClosingBytesReader) Close() error {
+ return nil
+}
+
+// Read implements the io.Reader interface.
+func (r *NopClosingBytesReader) Read(b []byte) (n int, err error) {
+ if r.i >= int64(len(r.s)) {
+ return 0, io.EOF
+ }
+ n = copy(b, r.s[r.i:])
+ r.i += int64(n)
+ return
+}
+
+// Set replaces the existing byte slice with the specified byte slice and resets the reader.
+func (r *NopClosingBytesReader) Set(b []byte) {
+ r.s = b
+ r.i = 0
+}
+
+// Seek implements the io.Seeker interface.
+func (r *NopClosingBytesReader) Seek(offset int64, whence int) (int64, error) {
+ var i int64
+ switch whence {
+ case io.SeekStart:
+ i = offset
+ case io.SeekCurrent:
+ i = r.i + offset
+ case io.SeekEnd:
+ i = int64(len(r.s)) + offset
+ default:
+ return 0, errors.New("nopClosingBytesReader: invalid whence")
+ }
+ if i < 0 {
+ return 0, errors.New("nopClosingBytesReader: negative position")
+ }
+ r.i = i
+ return i, nil
+}
+
+var _ BytesSetter = (*NopClosingBytesReader)(nil)
+
// TransportFunc is a helper to use a first-class func to satisfy the Transporter interface.
type TransportFunc func(*http.Request) (*http.Response, error)
@@ -80,49 +146,14 @@ func ValidateModVer(moduleVersion string) error {
return nil
}
-// ExtractModuleName returns "module", "package.Client" from "module/package.Client" or
-// "package", "package.Client" from "package.Client" when there's no "module/" prefix.
+// ExtractPackageName returns "package" from "package.Client".
// If clientName is malformed, an error is returned.
-func ExtractModuleName(clientName string) (string, string, error) {
- // uses unnamed capturing for "module", "package.Client", and "package"
- regex, err := regexp.Compile(`^(?:([a-z0-9]+)/)?(([a-z0-9]+)\.(?:[A-Za-z0-9]+))$`)
- if err != nil {
- return "", "", err
- }
-
- matches := regex.FindStringSubmatch(clientName)
- if len(matches) < 4 {
- return "", "", fmt.Errorf("malformed clientName %s", clientName)
+func ExtractPackageName(clientName string) (string, error) {
+ pkg, client, ok := strings.Cut(clientName, ".")
+ if !ok {
+ return "", fmt.Errorf("missing . in clientName %s", clientName)
+ } else if pkg == "" || client == "" {
+ return "", fmt.Errorf("malformed clientName %s", clientName)
}
-
- // the first match is the entire string, the second is "module", the third is
- // "package.Client" and the fourth is "package".
- // if there was no "module/" prefix, the second match will be the empty string
- if matches[1] != "" {
- return matches[1], matches[2], nil
- }
- return matches[3], matches[2], nil
-}
-
-// NonRetriableError marks the specified error as non-retriable.
-func NonRetriableError(err error) error {
- return &nonRetriableError{err}
+ return pkg, nil
}
-
-type nonRetriableError struct {
- error
-}
-
-func (p *nonRetriableError) Error() string {
- return p.error.Error()
-}
-
-func (*nonRetriableError) NonRetriable() {
- // marker method
-}
-
-func (p *nonRetriableError) Unwrap() error {
- return p.error
-}
-
-var _ errorinfo.NonRetriable = (*nonRetriableError)(nil)
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/policy/policy.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/policy/policy.go
index f73704cf0..c427e14d8 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/policy/policy.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/policy/policy.go
@@ -7,13 +7,11 @@
package policy
import (
- "context"
"net/http"
"time"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported"
- "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/tracing"
)
@@ -101,7 +99,7 @@ type RetryOptions struct {
// MaxRetryDelay specifies the maximum delay allowed before retrying an operation.
// Typically the value is greater than or equal to the value specified in RetryDelay.
- // The default Value is 60 seconds. A value less than zero means there is no cap.
+ // The default Value is 120 seconds. A value less than zero means there is no cap.
MaxRetryDelay time.Duration
// StatusCodes specifies the HTTP status codes that indicate the operation should be retried.
@@ -115,15 +113,6 @@ type RetryOptions struct {
// Specifying values will replace the default values.
// Specifying an empty slice will disable retries for HTTP status codes.
StatusCodes []int
-
- // ShouldRetry evaluates if the retry policy should retry the request.
- // When specified, the function overrides comparison against the list of
- // HTTP status codes and error checking within the retry policy. Context
- // and NonRetriable errors remain evaluated before calling ShouldRetry.
- // The *http.Response and error parameters are mutually exclusive, i.e.
- // if one is nil, the other is not nil.
- // A return value of true means the retry policy should retry.
- ShouldRetry func(*http.Response, error) bool
}
// TelemetryOptions configures the telemetry policy's behavior.
@@ -164,22 +153,3 @@ type AuthorizationHandler struct {
// the policy will return any 401 response to the client.
OnChallenge func(*Request, *http.Response, func(TokenRequestOptions) error) error
}
-
-// WithCaptureResponse applies the HTTP response retrieval annotation to the parent context.
-// The resp parameter will contain the HTTP response after the request has completed.
-func WithCaptureResponse(parent context.Context, resp **http.Response) context.Context {
- return context.WithValue(parent, shared.CtxWithCaptureResponse{}, resp)
-}
-
-// WithHTTPHeader adds the specified http.Header to the parent context.
-// Use this to specify custom HTTP headers at the API-call level.
-// Any overlapping headers will have their values replaced with the values specified here.
-func WithHTTPHeader(parent context.Context, header http.Header) context.Context {
- return context.WithValue(parent, shared.CtxWithHTTPHeaderKey{}, header)
-}
-
-// WithRetryOptions adds the specified RetryOptions to the parent context.
-// Use this to specify custom RetryOptions at the API-call level.
-func WithRetryOptions(parent context.Context, options RetryOptions) context.Context {
- return context.WithValue(parent, shared.CtxWithRetryOptionsKey{}, options)
-}
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/pager.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/pager.go
index 8a2e6c61e..5507665d6 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/pager.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/pager.go
@@ -10,9 +10,6 @@ import (
"context"
"encoding/json"
"errors"
- "net/http"
-
- "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
)
// PagingHandler contains the required data for constructing a Pager.
@@ -78,41 +75,3 @@ func (p *Pager[T]) NextPage(ctx context.Context) (T, error) {
func (p *Pager[T]) UnmarshalJSON(data []byte) error {
return json.Unmarshal(data, &p.current)
}
-
-// FetcherForNextLinkOptions contains the optional values for [FetcherForNextLink].
-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)
-}
-
-// FetcherForNextLink is a helper containing boilerplate code to simplify creating a PagingHandler[T].Fetcher from a next link URL.
-// - ctx is the [context.Context] controlling the lifetime of the HTTP operation
-// - pl is the [Pipeline] used to dispatch the HTTP request
-// - nextLink is the URL used to fetch the next page. the empty string indicates the first page is to be requested
-// - firstReq is the func to be called when creating the request for the first page
-// - options contains any optional parameters, pass nil to accept the default values
-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 nextLink == "" {
- req, err = firstReq(ctx)
- } else if nextLink, err = EncodeQueryParams(nextLink); err == nil {
- if options != nil && options.NextReq != nil {
- req, err = options.NextReq(ctx, nextLink)
- } else {
- req, err = NewRequest(ctx, http.MethodGet, nextLink)
- }
- }
- if err != nil {
- return nil, err
- }
- resp, err := pl.Do(req)
- if err != nil {
- return nil, err
- }
- if !HasStatusCode(resp, http.StatusOK) {
- return nil, NewResponseError(resp)
- }
- return resp, nil
-}
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_bearer_token.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_bearer_token.go
index ff4931cd2..b61e4c121 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_bearer_token.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_bearer_token.go
@@ -6,7 +6,6 @@ package runtime
import (
"errors"
"net/http"
- "strings"
"time"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported"
@@ -73,9 +72,6 @@ func (b *BearerTokenPolicy) authenticateAndAuthorize(req *policy.Request) func(p
// Do authorizes a request with a bearer token
func (b *BearerTokenPolicy) Do(req *policy.Request) (*http.Response, error) {
- if strings.ToLower(req.Raw().URL.Scheme) != "https" {
- return nil, shared.NonRetriableError(errors.New("bearer token authentication is not permitted for non TLS protected (https) endpoints"))
- }
var err error
if b.authzHandler.OnRequest != nil {
err = b.authzHandler.OnRequest(req, b.authenticateAndAuthorize(req))
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_body_download.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_body_download.go
index 99dc029f0..02d621ee8 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_body_download.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_body_download.go
@@ -11,6 +11,7 @@ import (
"net/http"
"strings"
+ "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
"github.com/Azure/azure-sdk-for-go/sdk/internal/errorinfo"
)
@@ -28,7 +29,7 @@ func bodyDownloadPolicy(req *policy.Request) (*http.Response, error) {
}
// Either bodyDownloadPolicyOpValues was not specified (so skip is false)
// or it was specified and skip is false: don't skip downloading the body
- _, err = Payload(resp)
+ _, err = exported.Payload(resp)
if err != nil {
return resp, newBodyDownloadError(err, req)
}
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_http_header.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_http_header.go
index c230af0af..770e0a2b6 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_http_header.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_http_header.go
@@ -34,7 +34,6 @@ func httpHeaderPolicy(req *policy.Request) (*http.Response, error) {
// WithHTTPHeader adds the specified http.Header to the parent context.
// Use this to specify custom HTTP headers at the API-call level.
// Any overlapping headers will have their values replaced with the values specified here.
-// Deprecated: use [policy.WithHTTPHeader] instead.
func WithHTTPHeader(parent context.Context, header http.Header) context.Context {
- return policy.WithHTTPHeader(parent, header)
+ return context.WithValue(parent, shared.CtxWithHTTPHeaderKey{}, header)
}
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_include_response.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_include_response.go
index bb00f6c2f..4714baa30 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_include_response.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_include_response.go
@@ -20,7 +20,7 @@ func includeResponsePolicy(req *policy.Request) (*http.Response, error) {
if resp == nil {
return resp, err
}
- if httpOutRaw := req.Raw().Context().Value(shared.CtxWithCaptureResponse{}); httpOutRaw != nil {
+ if httpOutRaw := req.Raw().Context().Value(shared.CtxIncludeResponseKey{}); httpOutRaw != nil {
httpOut := httpOutRaw.(**http.Response)
*httpOut = resp
}
@@ -29,7 +29,6 @@ func includeResponsePolicy(req *policy.Request) (*http.Response, error) {
// WithCaptureResponse applies the HTTP response retrieval annotation to the parent context.
// The resp parameter will contain the HTTP response after the request has completed.
-// Deprecated: use [policy.WithCaptureResponse] instead.
func WithCaptureResponse(parent context.Context, resp **http.Response) context.Context {
- return policy.WithCaptureResponse(parent, resp)
+ return context.WithValue(parent, shared.CtxIncludeResponseKey{}, resp)
}
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_key_credential.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_key_credential.go
deleted file mode 100644
index 2e47a5bad..000000000
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_key_credential.go
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package runtime
-
-import (
- "net/http"
-
- "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported"
- "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
-)
-
-// KeyCredentialPolicy authorizes requests with a [azcore.KeyCredential].
-type KeyCredentialPolicy struct {
- cred *exported.KeyCredential
- header string
- prefix string
-}
-
-// KeyCredentialPolicyOptions contains the optional values configuring [KeyCredentialPolicy].
-type KeyCredentialPolicyOptions struct {
- // Prefix is used if the key requires a prefix before it's inserted into the HTTP request.
- Prefix string
-}
-
-// NewKeyCredentialPolicy creates a new instance of [KeyCredentialPolicy].
-// - cred is the [azcore.KeyCredential] used to authenticate with the service
-// - header is the name of the HTTP request header in which the key is placed
-// - options contains optional configuration, pass nil to accept the default values
-func NewKeyCredentialPolicy(cred *exported.KeyCredential, header string, options *KeyCredentialPolicyOptions) *KeyCredentialPolicy {
- if options == nil {
- options = &KeyCredentialPolicyOptions{}
- }
- return &KeyCredentialPolicy{
- cred: cred,
- header: header,
- prefix: options.Prefix,
- }
-}
-
-// Do implementes the Do method on the [policy.Polilcy] interface.
-func (k *KeyCredentialPolicy) Do(req *policy.Request) (*http.Response, error) {
- val := exported.KeyCredentialGet(k.cred)
- if k.prefix != "" {
- val = k.prefix + val
- }
- req.Raw().Header.Add(k.header, val)
- return req.Next()
-}
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_retry.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_retry.go
index 21fcb3968..b33002018 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_retry.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_retry.go
@@ -19,7 +19,6 @@ 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/internal/errorinfo"
- "github.com/Azure/azure-sdk-for-go/sdk/internal/exported"
)
const (
@@ -125,8 +124,7 @@ func (p *retryPolicy) Do(req *policy.Request) (resp *http.Response, err error) {
}
if options.TryTimeout == 0 {
- clone := req.Clone(req.Raw().Context())
- resp, err = clone.Next()
+ resp, err = req.Next()
} else {
// Set the per-try time for this particular retry operation and then Do the operation.
tryCtx, tryCancel := context.WithTimeout(req.Raw().Context(), options.TryTimeout)
@@ -135,7 +133,7 @@ func (p *retryPolicy) Do(req *policy.Request) (resp *http.Response, err error) {
// if the body was already downloaded or there was an error it's safe to cancel the context now
if err != nil {
tryCancel()
- } else if exported.PayloadDownloaded(resp) {
+ } else if _, ok := resp.Body.(*shared.NopClosingBytesReader); ok {
tryCancel()
} else {
// must cancel the context after the body has been read and closed
@@ -148,7 +146,11 @@ func (p *retryPolicy) Do(req *policy.Request) (resp *http.Response, err error) {
log.Writef(log.EventRetryPolicy, "error %v", err)
}
- if ctxErr := req.Raw().Context().Err(); ctxErr != nil {
+ if err == nil && !HasStatusCode(resp, options.StatusCodes...) {
+ // if there is no error and the response code isn't in the list of retry codes then we're done.
+ log.Write(log.EventRetryPolicy, "exit due to non-retriable status code")
+ return
+ } else if ctxErr := req.Raw().Context().Err(); ctxErr != nil {
// don't retry if the parent context has been cancelled or its deadline exceeded
err = ctxErr
log.Writef(log.EventRetryPolicy, "abort due to %v", err)
@@ -163,19 +165,6 @@ func (p *retryPolicy) Do(req *policy.Request) (resp *http.Response, err error) {
return
}
- if options.ShouldRetry != nil {
- // a non-nil ShouldRetry overrides our HTTP status code check
- if !options.ShouldRetry(resp, err) {
- // predicate says we shouldn't retry
- log.Write(log.EventRetryPolicy, "exit due to ShouldRetry")
- return
- }
- } else if err == nil && !HasStatusCode(resp, options.StatusCodes...) {
- // if there is no error and the response code isn't in the list of retry codes then we're done.
- log.Write(log.EventRetryPolicy, "exit due to non-retriable status code")
- return
- }
-
if try == options.MaxRetries+1 {
// max number of tries has been reached, don't sleep again
log.Writef(log.EventRetryPolicy, "MaxRetries %d exceeded", options.MaxRetries)
@@ -209,9 +198,8 @@ func (p *retryPolicy) Do(req *policy.Request) (resp *http.Response, err error) {
// WithRetryOptions adds the specified RetryOptions to the parent context.
// Use this to specify custom RetryOptions at the API-call level.
-// Deprecated: use [policy.WithRetryOptions] instead.
func WithRetryOptions(parent context.Context, options policy.RetryOptions) context.Context {
- return policy.WithRetryOptions(parent, options)
+ return context.WithValue(parent, shared.CtxWithRetryOptionsKey{}, options)
}
// ********** The following type/methods implement the retryableRequestBody (a ReadSeekCloser)
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_sas_credential.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_sas_credential.go
deleted file mode 100644
index 25266030b..000000000
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_sas_credential.go
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package runtime
-
-import (
- "net/http"
-
- "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported"
- "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
-)
-
-// SASCredentialPolicy authorizes requests with a [azcore.SASCredential].
-type SASCredentialPolicy struct {
- cred *exported.SASCredential
- header string
-}
-
-// SASCredentialPolicyOptions contains the optional values configuring [SASCredentialPolicy].
-type SASCredentialPolicyOptions struct {
- // placeholder for future optional values
-}
-
-// NewSASCredentialPolicy creates a new instance of [SASCredentialPolicy].
-// - cred is the [azcore.SASCredential] used to authenticate with the service
-// - header is the name of the HTTP request header in which the shared access signature is placed
-// - options contains optional configuration, pass nil to accept the default values
-func NewSASCredentialPolicy(cred *exported.SASCredential, header string, options *SASCredentialPolicyOptions) *SASCredentialPolicy {
- return &SASCredentialPolicy{
- cred: cred,
- header: header,
- }
-}
-
-// Do implementes the Do method on the [policy.Polilcy] interface.
-func (k *SASCredentialPolicy) Do(req *policy.Request) (*http.Response, error) {
- req.Raw().Header.Add(k.header, exported.SASCredentialGet(k.cred))
- return req.Next()
-}
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/poller.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/poller.go
index 3d029a3d1..0be5210a4 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/poller.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/poller.go
@@ -23,7 +23,6 @@ import (
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/loc"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/op"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared"
- "github.com/Azure/azure-sdk-for-go/sdk/internal/poller"
)
// FinalStateVia is the enumerated type for the possible final-state-via values.
@@ -76,7 +75,7 @@ func NewPoller[T any](resp *http.Response, pl exported.Pipeline, options *NewPol
defer resp.Body.Close()
// this is a back-stop in case the swagger is incorrect (i.e. missing one or more status codes for success).
// ideally the codegen should return an error if the initial response failed and not even create a poller.
- if !poller.StatusCodeValid(resp) {
+ if !pollers.StatusCodeValid(resp) {
return nil, errors.New("the operation failed or was cancelled")
}
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/request.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/request.go
index b7e6fb26f..98e007184 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/request.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/request.go
@@ -15,7 +15,6 @@ import (
"fmt"
"io"
"mime/multipart"
- "net/url"
"os"
"path"
"reflect"
@@ -45,19 +44,6 @@ func NewRequest(ctx context.Context, httpMethod string, endpoint string) (*polic
return exported.NewRequest(ctx, httpMethod, endpoint)
}
-// EncodeQueryParams will parse and encode any query parameters in the specified URL.
-func EncodeQueryParams(u string) (string, error) {
- before, after, found := strings.Cut(u, "?")
- if !found {
- return u, nil
- }
- qp, err := url.ParseQuery(after)
- if err != nil {
- return "", err
- }
- return before + "?" + qp.Encode(), nil
-}
-
// JoinPaths concatenates multiple URL path segments into one path,
// inserting path separation characters as required. JoinPaths will preserve
// query parameters in the root path
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/response.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/response.go
index d1f58e9e2..f86ec0b95 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/response.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/response.go
@@ -15,14 +15,15 @@ import (
"io"
"net/http"
- "github.com/Azure/azure-sdk-for-go/sdk/internal/exported"
+ "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported"
+ "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared"
)
// Payload reads and returns the response body or an error.
// On a successful read, the response body is cached.
// Subsequent reads will access the cached value.
func Payload(resp *http.Response) ([]byte, error) {
- return exported.Payload(resp, nil)
+ return exported.Payload(resp)
}
// HasStatusCode returns true if the Response's status code is one of the specified values.
@@ -91,15 +92,15 @@ func Drain(resp *http.Response) {
// removeBOM removes any byte-order mark prefix from the payload if present.
func removeBOM(resp *http.Response) error {
- _, err := exported.Payload(resp, &exported.PayloadOptions{
- BytesModifier: func(b []byte) []byte {
- // UTF8
- return bytes.TrimPrefix(b, []byte("\xef\xbb\xbf"))
- },
- })
+ payload, err := Payload(resp)
if err != nil {
return err
}
+ // UTF8
+ trimmed := bytes.TrimPrefix(payload, []byte("\xef\xbb\xbf"))
+ if len(trimmed) < len(payload) {
+ resp.Body.(shared.BytesSetter).Set(trimmed)
+ }
return nil
}
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/transport_default_dialer_other.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/transport_default_dialer_other.go
deleted file mode 100644
index 1c75d771f..000000000
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/transport_default_dialer_other.go
+++ /dev/null
@@ -1,15 +0,0 @@
-//go:build !wasm
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package runtime
-
-import (
- "context"
- "net"
-)
-
-func defaultTransportDialContext(dialer *net.Dialer) func(context.Context, string, string) (net.Conn, error) {
- return dialer.DialContext
-}
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/transport_default_dialer_wasm.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/transport_default_dialer_wasm.go
deleted file mode 100644
index 3dc9eeecd..000000000
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/transport_default_dialer_wasm.go
+++ /dev/null
@@ -1,15 +0,0 @@
-//go:build (js && wasm) || wasip1
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package runtime
-
-import (
- "context"
- "net"
-)
-
-func defaultTransportDialContext(dialer *net.Dialer) func(context.Context, string, string) (net.Conn, error) {
- return nil
-}
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/transport_default_http_client.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/transport_default_http_client.go
index 589d09f2c..869bed511 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/transport_default_http_client.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/transport_default_http_client.go
@@ -18,18 +18,17 @@ var defaultHTTPClient *http.Client
func init() {
defaultTransport := &http.Transport{
Proxy: http.ProxyFromEnvironment,
- DialContext: defaultTransportDialContext(&net.Dialer{
+ DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
- }),
+ }).DialContext,
ForceAttemptHTTP2: true,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
TLSClientConfig: &tls.Config{
- MinVersion: tls.VersionTLS12,
- Renegotiation: tls.RenegotiateFreelyAsClient,
+ MinVersion: tls.VersionTLS12,
},
}
defaultHTTPClient = &http.Client{
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/CHANGELOG.md b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/CHANGELOG.md
index 7ea119ab3..670839fd4 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/CHANGELOG.md
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/CHANGELOG.md
@@ -1,173 +1,11 @@
# Release History
-## 1.4.0 (2023-10-10)
-
-### Bugs Fixed
-* `ManagedIdentityCredential` will now retry when IMDS responds 410 or 503
-
-## 1.4.0-beta.5 (2023-09-12)
-
-### Features Added
-* Service principal credentials can request CAE tokens
-
-### Breaking Changes
-> These changes affect only code written against a beta version such as v1.4.0-beta.4
-* Whether `GetToken` requests a CAE token is now determined by `TokenRequestOptions.EnableCAE`. Azure
- SDK clients which support CAE will set this option automatically. Credentials no longer request CAE
- tokens by default or observe the environment variable "AZURE_IDENTITY_DISABLE_CP1".
-
-### Bugs Fixed
-* Credential chains such as `DefaultAzureCredential` now try their next credential, if any, when
- managed identity authentication fails in a Docker Desktop container
- ([#21417](https://github.com/Azure/azure-sdk-for-go/issues/21417))
-
-## 1.4.0-beta.4 (2023-08-16)
-
-### Other Changes
-* Upgraded dependencies
-
-## 1.3.1 (2023-08-16)
-
-### Other Changes
-* Upgraded dependencies
-
-## 1.4.0-beta.3 (2023-08-08)
-
-### Bugs Fixed
-* One invocation of `AzureCLICredential.GetToken()` and `OnBehalfOfCredential.GetToken()`
- can no longer make two authentication attempts
-
-## 1.4.0-beta.2 (2023-07-14)
-
-### Other Changes
-* `DefaultAzureCredentialOptions.TenantID` applies to workload identity authentication
-* Upgraded dependencies
-
-## 1.4.0-beta.1 (2023-06-06)
-
-### Other Changes
-* Re-enabled CAE support as in v1.3.0-beta.3
-
-## 1.3.0 (2023-05-09)
-
-### Breaking Changes
-> These changes affect only code written against a beta version such as v1.3.0-beta.5
-* Renamed `NewOnBehalfOfCredentialFromCertificate` to `NewOnBehalfOfCredentialWithCertificate`
-* Renamed `NewOnBehalfOfCredentialFromSecret` to `NewOnBehalfOfCredentialWithSecret`
-
-### Other Changes
-* Upgraded to MSAL v1.0.0
-
-## 1.3.0-beta.5 (2023-04-11)
-
-### Breaking Changes
-> These changes affect only code written against a beta version such as v1.3.0-beta.4
-* Moved `NewWorkloadIdentityCredential()` parameters into `WorkloadIdentityCredentialOptions`.
- The constructor now reads default configuration from environment variables set by the Azure
- workload identity webhook by default.
- ([#20478](https://github.com/Azure/azure-sdk-for-go/pull/20478))
-* Removed CAE support. It will return in v1.4.0-beta.1
- ([#20479](https://github.com/Azure/azure-sdk-for-go/pull/20479))
-
-### Bugs Fixed
-* Fixed an issue in `DefaultAzureCredential` that could cause the managed identity endpoint check to fail in rare circumstances.
-
-## 1.3.0-beta.4 (2023-03-08)
-
-### Features Added
-* Added `WorkloadIdentityCredentialOptions.AdditionallyAllowedTenants` and `.DisableInstanceDiscovery`
-
-### Bugs Fixed
-* Credentials now synchronize within `GetToken()` so a single instance can be shared among goroutines
- ([#20044](https://github.com/Azure/azure-sdk-for-go/issues/20044))
-
-### Other Changes
-* Upgraded dependencies
-
-## 1.2.2 (2023-03-07)
-
-### Other Changes
-* Upgraded dependencies
-
-## 1.3.0-beta.3 (2023-02-07)
-
-### Features Added
-* By default, credentials set client capability "CP1" to enable support for
- [Continuous Access Evaluation (CAE)](https://docs.microsoft.com/azure/active-directory/develop/app-resilience-continuous-access-evaluation).
- This indicates to Azure Active Directory that your application can handle CAE claims challenges.
- You can disable this behavior by setting the environment variable "AZURE_IDENTITY_DISABLE_CP1" to "true".
-* `InteractiveBrowserCredentialOptions.LoginHint` enables pre-populating the login
- prompt with a username ([#15599](https://github.com/Azure/azure-sdk-for-go/pull/15599))
-* Service principal and user credentials support ADFS authentication on Azure Stack.
- Specify "adfs" as the credential's tenant.
-* Applications running in private or disconnected clouds can prevent credentials from
- requesting Azure AD instance metadata by setting the `DisableInstanceDiscovery`
- field on credential options.
-* Many credentials can now be configured to authenticate in multiple tenants. The
- options types for these credentials have an `AdditionallyAllowedTenants` field
- that specifies additional tenants in which the credential may authenticate.
-
-## 1.3.0-beta.2 (2023-01-10)
-
-### Features Added
-* Added `OnBehalfOfCredential` to support the on-behalf-of flow
- ([#16642](https://github.com/Azure/azure-sdk-for-go/issues/16642))
-
-### Bugs Fixed
-* `AzureCLICredential` reports token expiration in local time (should be UTC)
-
-### Other Changes
-* `AzureCLICredential` imposes its default timeout only when the `Context`
- passed to `GetToken()` has no deadline
-* Added `NewCredentialUnavailableError()`. This function constructs an error indicating
- a credential can't authenticate and an encompassing `ChainedTokenCredential` should
- try its next credential, if any.
-
-## 1.3.0-beta.1 (2022-12-13)
-
-### Features Added
-* `WorkloadIdentityCredential` and `DefaultAzureCredential` support
- Workload Identity Federation on Kubernetes. `DefaultAzureCredential`
- support requires environment variable configuration as set by the
- Workload Identity webhook.
- ([#15615](https://github.com/Azure/azure-sdk-for-go/issues/15615))
-
-## 1.2.0 (2022-11-08)
-
-### Other Changes
-* This version includes all fixes and features from 1.2.0-beta.*
-
-## 1.2.0-beta.3 (2022-10-11)
-
-### Features Added
-* `ManagedIdentityCredential` caches tokens in memory
-
-### Bugs Fixed
-* `ClientCertificateCredential` sends only the leaf cert for SNI authentication
-
-## 1.2.0-beta.2 (2022-08-10)
-
-### Features Added
-* Added `ClientAssertionCredential` to enable applications to authenticate
- with custom client assertions
-
-### Other Changes
-* Updated AuthenticationFailedError with links to TROUBLESHOOTING.md for relevant errors
-* Upgraded `microsoft-authentication-library-for-go` requirement to v0.6.0
-
-## 1.2.0-beta.1 (2022-06-07)
-
-### Features Added
-* `EnvironmentCredential` reads certificate passwords from `AZURE_CLIENT_CERTIFICATE_PASSWORD`
- ([#17099](https://github.com/Azure/azure-sdk-for-go/pull/17099))
-
## 1.1.0 (2022-06-07)
### Features Added
* `ClientCertificateCredential` and `ClientSecretCredential` support ESTS-R. First-party
applications can set environment variable `AZURE_REGIONAL_AUTHORITY_NAME` with a
region name.
- ([#15605](https://github.com/Azure/azure-sdk-for-go/issues/15605))
## 1.0.1 (2022-06-07)
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/README.md b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/README.md
index da0baa9ad..68b35a545 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/README.md
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/README.md
@@ -55,9 +55,8 @@ an Azure AD access token. See [Credential Types](#credential-types "Credential T
![DefaultAzureCredential authentication flow](img/mermaidjs/DefaultAzureCredentialAuthFlow.svg)
1. **Environment** - `DefaultAzureCredential` will read account information specified via [environment variables](#environment-variables) and use it to authenticate.
-1. **Workload Identity** - If the app is deployed on Kubernetes with environment variables set by the workload identity webhook, `DefaultAzureCredential` will authenticate the configured identity.
-1. **Managed Identity** - If the app is deployed to an Azure host with managed identity enabled, `DefaultAzureCredential` will authenticate with it.
-1. **Azure CLI** - If a user or service principal has authenticated via the Azure CLI `az login` command, `DefaultAzureCredential` will authenticate that identity.
+2. **Managed Identity** - If the app is deployed to an Azure host with managed identity enabled, `DefaultAzureCredential` will authenticate with it.
+3. **Azure CLI** - If a user or service principal has authenticated via the Azure CLI `az login` command, `DefaultAzureCredential` will authenticate that identity.
> Note: `DefaultAzureCredential` is intended to simplify getting started with the SDK by handling common scenarios with reasonable default behaviors. Developers who want more control or whose scenario isn't served by the default settings should use other credential types.
@@ -129,15 +128,13 @@ client := armresources.NewResourceGroupsClient("subscription ID", chain, nil)
|[ChainedTokenCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#ChainedTokenCredential)|Define custom authentication flows, composing multiple credentials
|[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
### Authenticating Service Principals
|Credential|Usage
|-|-
-|[ClientAssertionCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#ClientAssertionCredential)|Authenticate a service principal with a signed client assertion
-|[ClientCertificateCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#ClientCertificateCredential)|Authenticate a service principal with a certificate
|[ClientSecretCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#ClientSecretCredential)|Authenticate a service principal with a secret
+|[ClientCertificateCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#ClientCertificateCredential)|Authenticate a service principal with a certificate
### Authenticating Users
@@ -171,8 +168,7 @@ client := armresources.NewResourceGroupsClient("subscription ID", chain, nil)
|-|-
|`AZURE_CLIENT_ID`|ID of an Azure Active Directory application
|`AZURE_TENANT_ID`|ID of the application's Azure Active Directory tenant
-|`AZURE_CLIENT_CERTIFICATE_PATH`|path to a certificate file including private key
-|`AZURE_CLIENT_CERTIFICATE_PASSWORD`|password of the certificate file, if any
+|`AZURE_CLIENT_CERTIFICATE_PATH`|path to a certificate file including private key (without password protection)
#### Username and password
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TROUBLESHOOTING.md b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TROUBLESHOOTING.md
index fef099813..1e28d181f 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TROUBLESHOOTING.md
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TROUBLESHOOTING.md
@@ -8,17 +8,16 @@ This troubleshooting guide covers failure investigation techniques, common error
- [Permission issues](#permission-issues)
- [Find relevant information in errors](#find-relevant-information-in-errors)
- [Enable and configure logging](#enable-and-configure-logging)
-- [Troubleshoot AzureCliCredential authentication issues](#troubleshoot-azureclicredential-authentication-issues)
-- [Troubleshoot ClientCertificateCredential authentication issues](#troubleshoot-clientcertificatecredential-authentication-issues)
-- [Troubleshoot ClientSecretCredential authentication issues](#troubleshoot-clientsecretcredential-authentication-issues)
- [Troubleshoot DefaultAzureCredential authentication issues](#troubleshoot-defaultazurecredential-authentication-issues)
- [Troubleshoot EnvironmentCredential authentication issues](#troubleshoot-environmentcredential-authentication-issues)
+- [Troubleshoot ClientSecretCredential authentication issues](#troubleshoot-clientsecretcredential-authentication-issues)
+- [Troubleshoot ClientCertificateCredential authentication issues](#troubleshoot-clientcertificatecredential-authentication-issues)
+- [Troubleshoot UsernamePasswordCredential authentication issues](#troubleshoot-usernamepasswordcredential-authentication-issues)
- [Troubleshoot ManagedIdentityCredential authentication issues](#troubleshoot-managedidentitycredential-authentication-issues)
+ - [Azure Virtual Machine managed identity](#azure-virtual-machine-managed-identity)
- [Azure App Service and Azure Functions managed identity](#azure-app-service-and-azure-functions-managed-identity)
- [Azure Kubernetes Service managed identity](#azure-kubernetes-service-managed-identity)
- - [Azure Virtual Machine managed identity](#azure-virtual-machine-managed-identity)
-- [Troubleshoot UsernamePasswordCredential authentication issues](#troubleshoot-usernamepasswordcredential-authentication-issues)
-- [Troubleshoot WorkloadIdentityCredential authentication issues](#troubleshoot-workloadidentitycredential-authentication-issues)
+- [Troubleshoot AzureCliCredential authentication issues](#troubleshoot-azureclicredential-authentication-issues)
- [Get additional help](#get-additional-help)
## Handle azidentity errors
@@ -76,14 +75,12 @@ azlog.SetListener(func(event azlog.Event, s string) {
azlog.SetEvents(azidentity.EventAuthentication)
```
-
## Troubleshoot DefaultAzureCredential authentication issues
| Error |Description| Mitigation |
|---|---|---|
-|"DefaultAzureCredential failed to acquire a token"|No credential in the `DefaultAzureCredential` chain provided a token|
- [Enable logging](#enable-and-configure-logging) to get further diagnostic information.
- Consult the troubleshooting guide for underlying credential types for more information.
- [EnvironmentCredential](#troubleshoot-environmentcredential-authentication-issues)
- [ManagedIdentityCredential](#troubleshoot-managedidentitycredential-authentication-issues)
- [AzureCLICredential](#troubleshoot-azureclicredential-authentication-issues)
|
+|"DefaultAzureCredential failed to acquire a token"|No credential in the `DefaultAzureCredential` chain provided a token|- [Enable logging](#enable-and-configure-logging) to get further diagnostic information.
- Consult the troubleshooting guide for underlying credential types for more information.
- [EnvironmentCredential](#troubleshoot-environmentcredential-authentication-issues)
- [ManagedIdentityCredential](#troubleshoot-visualstudiocredential-authentication-issues)
- [AzureCLICredential](#troubleshoot-azureclicredential-authentication-issues)
|
|Error from the client with a status code of 401 or 403|Authentication succeeded but the authorizing Azure service responded with a 401 (Unauthorized), or 403 (Forbidden) status code|- [Enable logging](#enable-and-configure-logging) to determine which credential in the chain returned the authenticating token.
- If an unexpected credential is returning a token, check application configuration such as environment variables.
- Ensure the correct role is assigned to the authenticated identity. For example, a service specific role rather than the subscription Owner role.
|
-|"managed identity timed out"|`DefaultAzureCredential` sets a short timeout on its first managed identity authentication attempt to prevent very long timeouts during local development when no managed identity is available. That timeout causes this error in production when an application requests a token before the hosting environment is ready to provide one.|Use [ManagedIdentityCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#ManagedIdentityCredential) directly, at least in production. It doesn't set a timeout on its authentication attempts.|
## Troubleshoot EnvironmentCredential authentication issues
@@ -91,7 +88,6 @@ azlog.SetEvents(azidentity.EventAuthentication)
|---|---|---|
|Missing or incomplete environment variable configuration|A valid combination of environment variables wasn't set|Ensure the appropriate environment variables are set for the intended authentication method as described in the [module documentation](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#EnvironmentCredential)|
-
## Troubleshoot ClientSecretCredential authentication issues
| Error Code | Issue | Mitigation |
@@ -100,7 +96,6 @@ azlog.SetEvents(azidentity.EventAuthentication)
|AADSTS7000222|An expired client secret was provided.|Create a new client secret using the Azure portal. Details on creating a new client secret are in [Azure AD documentation](https://docs.microsoft.com/azure/active-directory/develop/howto-create-service-principal-portal#option-2-create-a-new-application-secret).|
|AADSTS700016|The specified application wasn't found in the specified tenant.|Ensure the client and tenant IDs provided to the credential constructor are correct for your application registration. For multi-tenant apps, ensure the application has been added to the desired tenant by a tenant admin. To add a new application in the desired tenant, follow the [Azure AD instructions](https://docs.microsoft.com/azure/active-directory/develop/howto-create-service-principal-portal).|
-
## Troubleshoot ClientCertificateCredential authentication issues
| Error Code | Description | Mitigation |
@@ -108,14 +103,12 @@ azlog.SetEvents(azidentity.EventAuthentication)
|AADSTS700027|Client assertion contains an invalid signature.|Ensure the specified certificate has been uploaded to the application registration as described in [Azure AD documentation](https://docs.microsoft.com/azure/active-directory/develop/howto-create-service-principal-portal#option-1-upload-a-certificate).|
|AADSTS700016|The specified application wasn't found in the specified tenant.|Ensure the client and tenant IDs provided to the credential constructor are correct for your application registration. For multi-tenant apps, ensure the application has been added to the desired tenant by a tenant admin. To add a new application in the desired tenant, follow the [Azure AD instructions](https://docs.microsoft.com/azure/active-directory/develop/howto-create-service-principal-portal).|
-
## Troubleshoot UsernamePasswordCredential authentication issues
| Error Code | Issue | Mitigation |
|---|---|---|
|AADSTS50126|The provided username or password is invalid.|Ensure the username and password provided to the credential constructor are valid.|
-
## Troubleshoot ManagedIdentityCredential authentication issues
`ManagedIdentityCredential` is designed to work on a variety of Azure hosts support managed identity. Configuration and troubleshooting vary from host to host. The below table lists the Azure hosts that can be assigned a managed identity and are supported by `ManagedIdentityCredential`.
@@ -171,7 +164,6 @@ curl "$IDENTITY_ENDPOINT?resource=https://management.core.windows.net&api-versio
|---|---|---|
|"no azure identity found for request clientID"|The application attempted to authenticate before an identity was assigned to its pod|Verify the pod is labeled correctly. This also occurs when a correctly labeled pod authenticates before the identity is ready. To prevent initialization races, configure NMI to set the Retry-After header in its responses as described in [Pod Identity documentation](https://azure.github.io/aad-pod-identity/docs/configure/feature_flags/#set-retry-after-header-in-nmi-response).
-
## Troubleshoot AzureCliCredential authentication issues
| Error Message |Description| Mitigation |
@@ -195,13 +187,6 @@ az account get-access-token --output json --resource https://management.core.win
> This command's output will contain an access token and SHOULD NOT BE SHARED, to avoid compromising account security.
-
-## Troubleshoot `WorkloadIdentityCredential` authentication issues
-
-| Error Message |Description| Mitigation |
-|---|---|---|
-|no client ID/tenant ID/token file specified|Incomplete configuration|In most cases these values are provided via environment variables set by Azure Workload Identity.- If your application runs on Azure Kubernetes Servide (AKS) or a cluster that has deployed the Azure Workload Identity admission webhook, check pod labels and service account configuration. See the [AKS documentation](https://learn.microsoft.com/azure/aks/workload-identity-deploy-cluster#disable-workload-identity) and [Azure Workload Identity troubleshooting guide](https://azure.github.io/azure-workload-identity/docs/troubleshooting.html) for more details.
- If your application isn't running on AKS or your cluster hasn't deployed the Workload Identity admission webhook, set these values in `WorkloadIdentityCredentialOptions`
-
## Get additional help
Additional information on ways to reach out for support can be found in [SUPPORT.md](https://github.com/Azure/azure-sdk-for-go/blob/main/SUPPORT.md).
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/assets.json b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/assets.json
deleted file mode 100644
index 47e77f88e..000000000
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/assets.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "AssetsRepo": "Azure/azure-sdk-assets",
- "AssetsRepoPrefixPath": "go",
- "TagPrefix": "go/azidentity",
- "Tag": "go/azidentity_6225ab0470"
-}
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azidentity.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azidentity.go
index 10b742ce1..0faee55ef 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azidentity.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azidentity.go
@@ -10,8 +10,8 @@ import (
"bytes"
"context"
"errors"
- "fmt"
"io"
+ "io/ioutil"
"net/http"
"net/url"
"os"
@@ -26,33 +26,20 @@ import (
)
const (
- azureAdditionallyAllowedTenants = "AZURE_ADDITIONALLY_ALLOWED_TENANTS"
- azureAuthorityHost = "AZURE_AUTHORITY_HOST"
- azureClientCertificatePassword = "AZURE_CLIENT_CERTIFICATE_PASSWORD"
- azureClientCertificatePath = "AZURE_CLIENT_CERTIFICATE_PATH"
- azureClientID = "AZURE_CLIENT_ID"
- azureClientSecret = "AZURE_CLIENT_SECRET"
- azureFederatedTokenFile = "AZURE_FEDERATED_TOKEN_FILE"
- azurePassword = "AZURE_PASSWORD"
- azureRegionalAuthorityName = "AZURE_REGIONAL_AUTHORITY_NAME"
- azureTenantID = "AZURE_TENANT_ID"
- azureUsername = "AZURE_USERNAME"
+ azureAuthorityHost = "AZURE_AUTHORITY_HOST"
+ azureClientID = "AZURE_CLIENT_ID"
+ azureRegionalAuthorityName = "AZURE_REGIONAL_AUTHORITY_NAME"
organizationsTenantID = "organizations"
developerSignOnClientID = "04b07795-8ddb-461a-bbee-02f9e1bf7b46"
defaultSuffix = "/.default"
-)
-
-var (
- // capability CP1 indicates the client application is capable of handling CAE claims challenges
- cp1 = []string{"CP1"}
- 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")
+ tenantIDValidationErr = "invalid tenantID. You can locate your tenantID by following the instructions listed here: https://docs.microsoft.com/partner-center/find-ids-and-domain-names"
)
// setAuthorityHost initializes the authority host for credentials. Precedence is:
-// 1. cloud.Configuration.ActiveDirectoryAuthorityHost value set by user
-// 2. value of AZURE_AUTHORITY_HOST
-// 3. default: Azure Public Cloud
+// 1. cloud.Configuration.ActiveDirectoryAuthorityHost value set by user
+// 2. value of AZURE_AUTHORITY_HOST
+// 3. default: Azure Public Cloud
func setAuthorityHost(cc cloud.Configuration) (string, error) {
host := cc.ActiveDirectoryAuthorityHost
if host == "" {
@@ -74,41 +61,6 @@ func setAuthorityHost(cc cloud.Configuration) (string, error) {
return host, nil
}
-// resolveAdditionalTenants returns a copy of tenants, simplified when tenants contains a wildcard
-func resolveAdditionalTenants(tenants []string) []string {
- if len(tenants) == 0 {
- return nil
- }
- for _, t := range tenants {
- // a wildcard makes all other values redundant
- if t == "*" {
- return []string{"*"}
- }
- }
- cp := make([]string, len(tenants))
- copy(cp, tenants)
- return cp
-}
-
-// resolveTenant returns the correct tenant for a token request
-func resolveTenant(defaultTenant, specified, credName string, additionalTenants []string) (string, error) {
- if specified == "" || specified == defaultTenant {
- return defaultTenant, nil
- }
- if defaultTenant == "adfs" {
- return "", errors.New("ADFS doesn't support tenants")
- }
- if !validTenantID(specified) {
- return "", errInvalidTenantID
- }
- for _, t := range additionalTenants {
- if t == "*" || t == specified {
- return specified, nil
- }
- }
- return "", fmt.Errorf(`%s isn't configured to acquire tokens for tenant %q. To enable acquiring tokens for this tenant add it to the AdditionallyAllowedTenants on the credential options, or add "*" to allow acquiring tokens for any tenant`, credName, specified)
-}
-
// validTenantID return true is it receives a valid tenantID, returns false otherwise
func validTenantID(tenantID string) bool {
match, err := regexp.MatchString("^[0-9a-zA-Z-.]+$", tenantID)
@@ -142,7 +94,7 @@ func (p pipelineAdapter) Do(r *http.Request) (*http.Response, error) {
if rsc, ok := r.Body.(io.ReadSeekCloser); ok {
body = rsc
} else {
- b, err := io.ReadAll(r.Body)
+ b, err := ioutil.ReadAll(r.Body)
if err != nil {
return nil, err
}
@@ -161,18 +113,17 @@ func (p pipelineAdapter) Do(r *http.Request) (*http.Response, error) {
}
// enables fakes for test scenarios
-type msalConfidentialClient interface {
- AcquireTokenSilent(ctx context.Context, scopes []string, options ...confidential.AcquireSilentOption) (confidential.AuthResult, error)
- AcquireTokenByAuthCode(ctx context.Context, code string, redirectURI string, scopes []string, options ...confidential.AcquireByAuthCodeOption) (confidential.AuthResult, error)
- AcquireTokenByCredential(ctx context.Context, scopes []string, options ...confidential.AcquireByCredentialOption) (confidential.AuthResult, error)
- AcquireTokenOnBehalfOf(ctx context.Context, userAssertion string, scopes []string, options ...confidential.AcquireOnBehalfOfOption) (confidential.AuthResult, error)
+type confidentialClient interface {
+ AcquireTokenSilent(ctx context.Context, scopes []string, options ...confidential.AcquireTokenSilentOption) (confidential.AuthResult, error)
+ AcquireTokenByAuthCode(ctx context.Context, code string, redirectURI string, scopes []string, options ...confidential.AcquireTokenByAuthCodeOption) (confidential.AuthResult, error)
+ AcquireTokenByCredential(ctx context.Context, scopes []string) (confidential.AuthResult, error)
}
// enables fakes for test scenarios
-type msalPublicClient interface {
- AcquireTokenSilent(ctx context.Context, scopes []string, options ...public.AcquireSilentOption) (public.AuthResult, error)
- AcquireTokenByUsernamePassword(ctx context.Context, scopes []string, username string, password string, options ...public.AcquireByUsernamePasswordOption) (public.AuthResult, error)
- AcquireTokenByDeviceCode(ctx context.Context, scopes []string, options ...public.AcquireByDeviceCodeOption) (public.DeviceCode, error)
- AcquireTokenByAuthCode(ctx context.Context, code string, redirectURI string, scopes []string, options ...public.AcquireByAuthCodeOption) (public.AuthResult, error)
- AcquireTokenInteractive(ctx context.Context, scopes []string, options ...public.AcquireInteractiveOption) (public.AuthResult, error)
+type publicClient interface {
+ AcquireTokenSilent(ctx context.Context, scopes []string, options ...public.AcquireTokenSilentOption) (public.AuthResult, error)
+ AcquireTokenByUsernamePassword(ctx context.Context, scopes []string, username string, password string) (public.AuthResult, error)
+ AcquireTokenByDeviceCode(ctx context.Context, scopes []string) (public.DeviceCode, error)
+ AcquireTokenByAuthCode(ctx context.Context, code string, redirectURI string, scopes []string, options ...public.AcquireTokenByAuthCodeOption) (public.AuthResult, error)
+ AcquireTokenInteractive(ctx context.Context, scopes []string, options ...public.InteractiveAuthOption) (public.AuthResult, error)
}
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azure_cli_credential.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azure_cli_credential.go
index 55a0d6543..68f46d51a 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azure_cli_credential.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azure_cli_credential.go
@@ -17,28 +17,19 @@ import (
"regexp"
"runtime"
"strings"
- "sync"
"time"
"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/internal/log"
)
-const (
- credNameAzureCLI = "AzureCLICredential"
- timeoutCLIRequest = 10 * time.Second
-)
+const credNameAzureCLI = "AzureCLICredential"
// used by tests to fake invoking the CLI
type azureCLITokenProvider func(ctx context.Context, resource string, tenantID string) ([]byte, error)
// AzureCLICredentialOptions contains optional parameters for AzureCLICredential.
type AzureCLICredentialOptions struct {
- // AdditionallyAllowedTenants specifies tenants for which the credential may acquire tokens, in addition
- // to TenantID. Add the wildcard value "*" to allow the credential to acquire tokens for any tenant the
- // logged in account can access.
- AdditionallyAllowedTenants []string
// TenantID identifies the tenant the credential should authenticate in.
// Defaults to the CLI's default tenant, which is typically the home tenant of the logged in user.
TenantID string
@@ -49,14 +40,14 @@ type AzureCLICredentialOptions struct {
// init returns an instance of AzureCLICredentialOptions initialized with default values.
func (o *AzureCLICredentialOptions) init() {
if o.tokenProvider == nil {
- o.tokenProvider = defaultTokenProvider
+ o.tokenProvider = defaultTokenProvider()
}
}
// AzureCLICredential authenticates as the identity logged in to the Azure CLI.
type AzureCLICredential struct {
- mu *sync.Mutex
- opts AzureCLICredentialOptions
+ tokenProvider azureCLITokenProvider
+ tenantID string
}
// NewAzureCLICredential constructs an AzureCLICredential. Pass nil to accept default options.
@@ -66,8 +57,10 @@ func NewAzureCLICredential(options *AzureCLICredentialOptions) (*AzureCLICredent
cp = *options
}
cp.init()
- cp.AdditionallyAllowedTenants = resolveAdditionalTenants(cp.AdditionallyAllowedTenants)
- return &AzureCLICredential{mu: &sync.Mutex{}, opts: cp}, nil
+ return &AzureCLICredential{
+ tokenProvider: cp.tokenProvider,
+ tenantID: cp.TenantID,
+ }, nil
}
// GetToken requests a token from the Azure CLI. This credential doesn't cache tokens, so every call invokes the CLI.
@@ -76,77 +69,75 @@ func (c *AzureCLICredential) GetToken(ctx context.Context, opts policy.TokenRequ
if len(opts.Scopes) != 1 {
return azcore.AccessToken{}, errors.New(credNameAzureCLI + ": GetToken() requires exactly one scope")
}
- tenant, err := resolveTenant(c.opts.TenantID, opts.TenantID, credNameAzureCLI, c.opts.AdditionallyAllowedTenants)
- if err != nil {
- return azcore.AccessToken{}, err
- }
- // pass the CLI an AAD v1 resource because we don't know which CLI version is installed and older ones don't support v2 scopes
- opts.Scopes = []string{strings.TrimSuffix(opts.Scopes[0], defaultSuffix)}
- c.mu.Lock()
- defer c.mu.Unlock()
- b, err := c.opts.tokenProvider(ctx, opts.Scopes[0], tenant)
- if err != nil {
- return azcore.AccessToken{}, err
- }
- at, err := c.createAccessToken(b)
+ // CLI expects an AAD v1 resource, not a v2 scope
+ scope := strings.TrimSuffix(opts.Scopes[0], defaultSuffix)
+ at, err := c.authenticate(ctx, scope)
if err != nil {
return azcore.AccessToken{}, err
}
- msg := fmt.Sprintf("%s.GetToken() acquired a token for scope %q", credNameAzureCLI, strings.Join(opts.Scopes, ", "))
- log.Write(EventAuthentication, msg)
+ logGetTokenSuccess(c, opts)
return at, nil
}
-var defaultTokenProvider azureCLITokenProvider = func(ctx context.Context, resource string, tenantID string) ([]byte, error) {
- match, err := regexp.MatchString("^[0-9a-zA-Z-.:/]+$", resource)
+const timeoutCLIRequest = 10 * time.Second
+
+func (c *AzureCLICredential) authenticate(ctx context.Context, resource string) (azcore.AccessToken, error) {
+ output, err := c.tokenProvider(ctx, resource, c.tenantID)
if err != nil {
- return nil, err
- }
- if !match {
- return nil, fmt.Errorf(`%s: unexpected scope "%s". Only alphanumeric characters and ".", ";", "-", and "/" are allowed`, credNameAzureCLI, resource)
+ return azcore.AccessToken{}, err
}
- // set a default timeout for this authentication iff the application hasn't done so already
- var cancel context.CancelFunc
- if _, hasDeadline := ctx.Deadline(); !hasDeadline {
- ctx, cancel = context.WithTimeout(ctx, timeoutCLIRequest)
- defer cancel()
- }
+ return c.createAccessToken(output)
+}
- commandLine := "az account get-access-token -o json --resource " + resource
- if tenantID != "" {
- commandLine += " --tenant " + tenantID
- }
- var cliCmd *exec.Cmd
- if runtime.GOOS == "windows" {
- dir := os.Getenv("SYSTEMROOT")
- if dir == "" {
- return nil, newCredentialUnavailableError(credNameAzureCLI, "environment variable 'SYSTEMROOT' has no value")
+func defaultTokenProvider() func(ctx context.Context, resource string, tenantID string) ([]byte, error) {
+ return func(ctx context.Context, resource string, tenantID string) ([]byte, error) {
+ match, err := regexp.MatchString("^[0-9a-zA-Z-.:/]+$", resource)
+ if err != nil {
+ return nil, err
+ }
+ if !match {
+ return nil, fmt.Errorf(`%s: unexpected scope "%s". Only alphanumeric characters and ".", ";", "-", and "/" are allowed`, credNameAzureCLI, resource)
}
- cliCmd = exec.CommandContext(ctx, "cmd.exe", "/c", commandLine)
- cliCmd.Dir = dir
- } else {
- cliCmd = exec.CommandContext(ctx, "/bin/sh", "-c", commandLine)
- cliCmd.Dir = "/bin"
- }
- cliCmd.Env = os.Environ()
- var stderr bytes.Buffer
- cliCmd.Stderr = &stderr
- output, err := cliCmd.Output()
- if err != nil {
- msg := stderr.String()
- var exErr *exec.ExitError
- if errors.As(err, &exErr) && exErr.ExitCode() == 127 || strings.HasPrefix(msg, "'az' is not recognized") {
- msg = "Azure CLI not found on path"
+ ctx, cancel := context.WithTimeout(ctx, timeoutCLIRequest)
+ defer cancel()
+
+ commandLine := "az account get-access-token -o json --resource " + resource
+ if tenantID != "" {
+ commandLine += " --tenant " + tenantID
}
- if msg == "" {
- msg = err.Error()
+ var cliCmd *exec.Cmd
+ if runtime.GOOS == "windows" {
+ dir := os.Getenv("SYSTEMROOT")
+ if dir == "" {
+ return nil, newCredentialUnavailableError(credNameAzureCLI, "environment variable 'SYSTEMROOT' has no value")
+ }
+ cliCmd = exec.CommandContext(ctx, "cmd.exe", "/c", commandLine)
+ cliCmd.Dir = dir
+ } else {
+ cliCmd = exec.CommandContext(ctx, "/bin/sh", "-c", commandLine)
+ cliCmd.Dir = "/bin"
+ }
+ cliCmd.Env = os.Environ()
+ var stderr bytes.Buffer
+ cliCmd.Stderr = &stderr
+
+ output, err := cliCmd.Output()
+ if err != nil {
+ msg := stderr.String()
+ var exErr *exec.ExitError
+ if errors.As(err, &exErr) && exErr.ExitCode() == 127 || strings.HasPrefix(msg, "'az' is not recognized") {
+ msg = "Azure CLI not found on path"
+ }
+ if msg == "" {
+ msg = err.Error()
+ }
+ return nil, newCredentialUnavailableError(credNameAzureCLI, msg)
}
- return nil, newCredentialUnavailableError(credNameAzureCLI, msg)
- }
- return output, nil
+ return output, nil
+ }
}
func (c *AzureCLICredential) createAccessToken(tk []byte) (azcore.AccessToken, error) {
@@ -167,17 +158,32 @@ func (c *AzureCLICredential) createAccessToken(tk []byte) (azcore.AccessToken, e
return azcore.AccessToken{}, err
}
- // the Azure CLI's "expiresOn" is local time
- exp, err := time.ParseInLocation("2006-01-02 15:04:05.999999", t.ExpiresOn, time.Local)
+ tokenExpirationDate, err := parseExpirationDate(t.ExpiresOn)
if err != nil {
- return azcore.AccessToken{}, fmt.Errorf("Error parsing token expiration time %q: %v", t.ExpiresOn, err)
+ return azcore.AccessToken{}, fmt.Errorf("Error parsing Token Expiration Date %q: %+v", t.ExpiresOn, err)
}
converted := azcore.AccessToken{
Token: t.AccessToken,
- ExpiresOn: exp.UTC(),
+ ExpiresOn: *tokenExpirationDate,
}
return converted, nil
}
+// parseExpirationDate parses either a Azure CLI or CloudShell date into a time object
+func parseExpirationDate(input string) (*time.Time, error) {
+ // CloudShell (and potentially the Azure CLI in future)
+ expirationDate, cloudShellErr := time.Parse(time.RFC3339, input)
+ if cloudShellErr != nil {
+ // Azure CLI (Python) e.g. 2017-08-31 19:48:57.998857 (plus the local timezone)
+ const cliFormat = "2006-01-02 15:04:05.999999"
+ expirationDate, cliErr := time.ParseInLocation(cliFormat, input, time.Local)
+ if cliErr != nil {
+ return nil, fmt.Errorf("Error parsing expiration date %q.\n\nCloudShell Error: \n%+v\n\nCLI Error:\n%+v", input, cloudShellErr, cliErr)
+ }
+ return &expirationDate, nil
+ }
+ return &expirationDate, nil
+}
+
var _ azcore.TokenCredential = (*AzureCLICredential)(nil)
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/chained_token_credential.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/chained_token_credential.go
index dc855edf7..86a890645 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/chained_token_credential.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/chained_token_credential.go
@@ -81,13 +81,10 @@ func (c *ChainedTokenCredential) GetToken(ctx context.Context, opts policy.Token
}
}
- var (
- err error
- errs []error
- successfulCredential azcore.TokenCredential
- token azcore.AccessToken
- unavailableErr *credentialUnavailableError
- )
+ var err error
+ var errs []error
+ var token azcore.AccessToken
+ var successfulCredential azcore.TokenCredential
for _, cred := range c.sources {
token, err = cred.GetToken(ctx, opts)
if err == nil {
@@ -96,14 +93,12 @@ func (c *ChainedTokenCredential) GetToken(ctx context.Context, opts policy.Token
break
}
errs = append(errs, err)
- // continue to the next source iff this one returned credentialUnavailableError
- if !errors.As(err, &unavailableErr) {
+ if _, ok := err.(*credentialUnavailableError); !ok {
break
}
}
if c.iterating {
c.cond.L.Lock()
- // this is nil when all credentials returned an error
c.successfulCredential = successfulCredential
c.iterating = false
c.cond.L.Unlock()
@@ -113,11 +108,11 @@ 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) {
+ if _, ok := err.(*credentialUnavailableError); ok {
err = newCredentialUnavailableError(c.name, msg)
} else {
res := getResponseFromError(err)
- err = newAuthenticationFailedError(c.name, msg, res, err)
+ err = newAuthenticationFailedError(c.name, msg, res)
}
}
return token, err
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/ci.yml b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/ci.yml
index 9002ea0b0..3b443e8ee 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/ci.yml
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/ci.yml
@@ -26,9 +26,22 @@ stages:
parameters:
RunLiveTests: true
ServiceDirectory: 'azidentity'
- CloudConfig:
- Public:
- SubscriptionConfigurations:
- - $(sub-config-azure-cloud-test-resources)
- # Contains alternate tenant, AAD app and cert info for testing
- - $(sub-config-identity-test-resources)
+ PreSteps:
+ - pwsh: |
+ [System.Convert]::FromBase64String($env:PFX_CONTENTS) | Set-Content -Path $(Agent.TempDirectory)/test.pfx -AsByteStream
+ Set-Content -Path $(Agent.TempDirectory)/test.pem -Value $env:PEM_CONTENTS
+ [System.Convert]::FromBase64String($env:SNI_CONTENTS) | Set-Content -Path $(Agent.TempDirectory)/testsni.pfx -AsByteStream
+ env:
+ PFX_CONTENTS: $(net-identity-spcert-pfx)
+ PEM_CONTENTS: $(net-identity-spcert-pem)
+ SNI_CONTENTS: $(net-identity-spcert-sni)
+ EnvVars:
+ AZURE_IDENTITY_TEST_TENANTID: $(net-identity-tenantid)
+ AZURE_IDENTITY_TEST_USERNAME: $(net-identity-username)
+ AZURE_IDENTITY_TEST_PASSWORD: $(net-identity-password)
+ IDENTITY_SP_TENANT_ID: $(net-identity-sp-tenantid)
+ IDENTITY_SP_CLIENT_ID: $(net-identity-sp-clientid)
+ IDENTITY_SP_CLIENT_SECRET: $(net-identity-sp-clientsecret)
+ IDENTITY_SP_CERT_PEM: $(Agent.TempDirectory)/test.pem
+ IDENTITY_SP_CERT_PFX: $(Agent.TempDirectory)/test.pfx
+ IDENTITY_SP_CERT_SNI: $(Agent.TempDirectory)/testsni.pfx
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/client_assertion_credential.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/client_assertion_credential.go
deleted file mode 100644
index 303d5fc09..000000000
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/client_assertion_credential.go
+++ /dev/null
@@ -1,75 +0,0 @@
-//go:build go1.18
-// +build go1.18
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package azidentity
-
-import (
- "context"
- "errors"
-
- "github.com/Azure/azure-sdk-for-go/sdk/azcore"
- "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
- "github.com/AzureAD/microsoft-authentication-library-for-go/apps/confidential"
-)
-
-const credNameAssertion = "ClientAssertionCredential"
-
-// ClientAssertionCredential authenticates an application with assertions provided by a callback function.
-// This credential is for advanced scenarios. [ClientCertificateCredential] has a more convenient API for
-// the most common assertion scenario, authenticating a service principal with a certificate. See
-// [Azure AD documentation] for details of the assertion format.
-//
-// [Azure AD documentation]: https://docs.microsoft.com/azure/active-directory/develop/active-directory-certificate-credentials#assertion-format
-type ClientAssertionCredential struct {
- client *confidentialClient
-}
-
-// ClientAssertionCredentialOptions contains optional parameters for ClientAssertionCredential.
-type ClientAssertionCredentialOptions struct {
- azcore.ClientOptions
-
- // AdditionallyAllowedTenants specifies additional tenants for which the credential may acquire tokens.
- // Add the wildcard value "*" to allow the credential to acquire tokens for any tenant in which the
- // application is registered.
- AdditionallyAllowedTenants []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 Azure AD 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
-}
-
-// NewClientAssertionCredential constructs a ClientAssertionCredential. The getAssertion function must be thread safe. Pass nil for options to accept defaults.
-func NewClientAssertionCredential(tenantID, clientID string, getAssertion func(context.Context) (string, error), options *ClientAssertionCredentialOptions) (*ClientAssertionCredential, error) {
- if getAssertion == nil {
- return nil, errors.New("getAssertion must be a function that returns assertions")
- }
- if options == nil {
- options = &ClientAssertionCredentialOptions{}
- }
- cred := confidential.NewCredFromAssertionCallback(
- func(ctx context.Context, _ confidential.AssertionRequestOptions) (string, error) {
- return getAssertion(ctx)
- },
- )
- msalOpts := confidentialClientOptions{
- AdditionallyAllowedTenants: options.AdditionallyAllowedTenants,
- ClientOptions: options.ClientOptions,
- DisableInstanceDiscovery: options.DisableInstanceDiscovery,
- }
- c, err := newConfidentialClient(tenantID, clientID, credNameAssertion, cred, msalOpts)
- if err != nil {
- return nil, err
- }
- return &ClientAssertionCredential{client: c}, nil
-}
-
-// GetToken requests an access token from Azure Active Directory. This method is called automatically by Azure SDK clients.
-func (c *ClientAssertionCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
- return c.client.GetToken(ctx, opts)
-}
-
-var _ azcore.TokenCredential = (*ClientAssertionCredential)(nil)
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/client_certificate_credential.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/client_certificate_credential.go
index d3300e305..e50157b10 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/client_certificate_credential.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/client_certificate_credential.go
@@ -9,12 +9,17 @@ package azidentity
import (
"context"
"crypto"
+ "crypto/rsa"
+ "crypto/sha1"
"crypto/x509"
+ "encoding/base64"
"encoding/pem"
"errors"
+ "os"
"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/AzureAD/microsoft-authentication-library-for-go/apps/confidential"
"golang.org/x/crypto/pkcs12"
)
@@ -25,15 +30,6 @@ const credNameCert = "ClientCertificateCredential"
type ClientCertificateCredentialOptions struct {
azcore.ClientOptions
- // AdditionallyAllowedTenants specifies additional tenants for which the credential may acquire tokens.
- // Add the wildcard value "*" to allow the credential to acquire tokens for any tenant in which the
- // application is registered.
- AdditionallyAllowedTenants []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 Azure AD 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
// SendCertificateChain controls whether the credential sends the public certificate chain in the x5c
// header of each token request's JWT. This is required for Subject Name/Issuer (SNI) authentication.
// Defaults to False.
@@ -42,7 +38,7 @@ type ClientCertificateCredentialOptions struct {
// ClientCertificateCredential authenticates a service principal with a certificate.
type ClientCertificateCredential struct {
- client *confidentialClient
+ client confidentialClient
}
// NewClientCertificateCredential constructs a ClientCertificateCredential. Pass nil for options to accept defaults.
@@ -50,20 +46,37 @@ func NewClientCertificateCredential(tenantID string, clientID string, certs []*x
if len(certs) == 0 {
return nil, errors.New("at least one certificate is required")
}
+ pk, ok := key.(*rsa.PrivateKey)
+ if !ok {
+ return nil, errors.New("'key' must be an *rsa.PrivateKey")
+ }
+ if !validTenantID(tenantID) {
+ return nil, errors.New(tenantIDValidationErr)
+ }
if options == nil {
options = &ClientCertificateCredentialOptions{}
}
- cred, err := confidential.NewCredFromCert(certs, key)
+ authorityHost, err := setAuthorityHost(options.Cloud)
if err != nil {
return nil, err
}
- msalOpts := confidentialClientOptions{
- AdditionallyAllowedTenants: options.AdditionallyAllowedTenants,
- ClientOptions: options.ClientOptions,
- DisableInstanceDiscovery: options.DisableInstanceDiscovery,
- SendX5C: options.SendCertificateChain,
+ cert, err := newCertContents(certs, pk, options.SendCertificateChain)
+ if err != nil {
+ return nil, err
}
- c, err := newConfidentialClient(tenantID, clientID, credNameCert, cred, msalOpts)
+ cred := confidential.NewCredFromCert(cert.c, key) // TODO: NewCredFromCert should take a slice
+ if err != nil {
+ return nil, err
+ }
+ o := []confidential.Option{
+ confidential.WithAuthority(runtime.JoinPaths(authorityHost, tenantID)),
+ confidential.WithHTTPClient(newPipelineAdapter(&options.ClientOptions)),
+ confidential.WithAzureRegion(os.Getenv(azureRegionalAuthorityName)),
+ }
+ if options.SendCertificateChain {
+ o = append(o, confidential.WithX5C())
+ }
+ c, err := confidential.New(clientID, cred, o...)
if err != nil {
return nil, err
}
@@ -72,7 +85,21 @@ func NewClientCertificateCredential(tenantID string, clientID string, certs []*x
// GetToken requests an access token from Azure Active Directory. This method is called automatically by Azure SDK clients.
func (c *ClientCertificateCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
- return c.client.GetToken(ctx, opts)
+ if len(opts.Scopes) == 0 {
+ return azcore.AccessToken{}, errors.New(credNameCert + ": GetToken() requires at least one scope")
+ }
+ ar, err := c.client.AcquireTokenSilent(ctx, opts.Scopes)
+ if err == nil {
+ logGetTokenSuccess(c, opts)
+ return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
+ }
+
+ ar, err = c.client.AcquireTokenByCredential(ctx, opts.Scopes)
+ if err != nil {
+ return azcore.AccessToken{}, newAuthenticationFailedErrorFromMSALError(credNameCert, err)
+ }
+ logGetTokenSuccess(c, opts)
+ return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
}
// ParseCertificates loads certificates and a private key, in PEM or PKCS12 format, for use with NewClientCertificateCredential.
@@ -129,6 +156,36 @@ func ParseCertificates(certData []byte, password []byte) ([]*x509.Certificate, c
return certs, pk, nil
}
+type certContents struct {
+ c *x509.Certificate // the signing cert
+ fp []byte // the signing cert's fingerprint, a SHA-1 digest
+ pk *rsa.PrivateKey // the signing key
+ x5c []string // concatenation of every provided cert, base64 encoded
+}
+
+func newCertContents(certs []*x509.Certificate, key *rsa.PrivateKey, sendCertificateChain bool) (*certContents, error) {
+ cc := certContents{pk: key}
+ // need the the signing cert's fingerprint: identify that cert by matching its public key to the private key
+ for _, cert := range certs {
+ certKey, ok := cert.PublicKey.(*rsa.PublicKey)
+ if ok && key.E == certKey.E && key.N.Cmp(certKey.N) == 0 {
+ fp := sha1.Sum(cert.Raw)
+ cc.fp = fp[:]
+ cc.c = cert
+ if sendCertificateChain {
+ // signing cert must be first in x5c
+ cc.x5c = append([]string{base64.StdEncoding.EncodeToString(cert.Raw)}, cc.x5c...)
+ }
+ } else if sendCertificateChain {
+ cc.x5c = append(cc.x5c, base64.StdEncoding.EncodeToString(cert.Raw))
+ }
+ }
+ if len(cc.fp) == 0 || cc.c == nil {
+ return nil, errors.New("found no certificate matching 'key'")
+ }
+ return &cc, nil
+}
+
func loadPEMCert(certData []byte) ([]*pem.Block, error) {
blocks := []*pem.Block{}
for {
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/client_secret_credential.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/client_secret_credential.go
index d2ff7582b..6ecb8f4db 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/client_secret_credential.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/client_secret_credential.go
@@ -8,9 +8,12 @@ package azidentity
import (
"context"
+ "errors"
+ "os"
"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/AzureAD/microsoft-authentication-library-for-go/apps/confidential"
)
@@ -19,47 +22,57 @@ const credNameSecret = "ClientSecretCredential"
// ClientSecretCredentialOptions contains optional parameters for ClientSecretCredential.
type ClientSecretCredentialOptions struct {
azcore.ClientOptions
-
- // AdditionallyAllowedTenants specifies additional tenants for which the credential may acquire tokens.
- // Add the wildcard value "*" to allow the credential to acquire tokens for any tenant in which the
- // application is registered.
- AdditionallyAllowedTenants []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 Azure AD 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
}
// ClientSecretCredential authenticates an application with a client secret.
type ClientSecretCredential struct {
- client *confidentialClient
+ client confidentialClient
}
// NewClientSecretCredential constructs a ClientSecretCredential. Pass nil for options to accept defaults.
func NewClientSecretCredential(tenantID string, clientID string, clientSecret string, options *ClientSecretCredentialOptions) (*ClientSecretCredential, error) {
+ if !validTenantID(tenantID) {
+ return nil, errors.New(tenantIDValidationErr)
+ }
if options == nil {
options = &ClientSecretCredentialOptions{}
}
- cred, err := confidential.NewCredFromSecret(clientSecret)
+ authorityHost, err := setAuthorityHost(options.Cloud)
if err != nil {
return nil, err
}
- msalOpts := confidentialClientOptions{
- AdditionallyAllowedTenants: options.AdditionallyAllowedTenants,
- ClientOptions: options.ClientOptions,
- DisableInstanceDiscovery: options.DisableInstanceDiscovery,
+ cred, err := confidential.NewCredFromSecret(clientSecret)
+ if err != nil {
+ return nil, err
}
- c, err := newConfidentialClient(tenantID, clientID, credNameSecret, cred, msalOpts)
+ c, err := confidential.New(clientID, cred,
+ confidential.WithAuthority(runtime.JoinPaths(authorityHost, tenantID)),
+ confidential.WithHTTPClient(newPipelineAdapter(&options.ClientOptions)),
+ confidential.WithAzureRegion(os.Getenv(azureRegionalAuthorityName)),
+ )
if err != nil {
return nil, err
}
- return &ClientSecretCredential{c}, nil
+ return &ClientSecretCredential{client: c}, nil
}
// GetToken requests an access token from Azure Active Directory. This method is called automatically by Azure SDK clients.
func (c *ClientSecretCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
- return c.client.GetToken(ctx, opts)
+ if len(opts.Scopes) == 0 {
+ return azcore.AccessToken{}, errors.New(credNameSecret + ": GetToken() requires at least one scope")
+ }
+ ar, err := c.client.AcquireTokenSilent(ctx, opts.Scopes)
+ if err == nil {
+ logGetTokenSuccess(c, opts)
+ return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
+ }
+
+ ar, err = c.client.AcquireTokenByCredential(ctx, opts.Scopes)
+ if err != nil {
+ return azcore.AccessToken{}, newAuthenticationFailedErrorFromMSALError(credNameSecret, err)
+ }
+ logGetTokenSuccess(c, opts)
+ return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
}
var _ azcore.TokenCredential = (*ClientSecretCredential)(nil)
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/confidential_client.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/confidential_client.go
deleted file mode 100644
index 4853a9a00..000000000
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/confidential_client.go
+++ /dev/null
@@ -1,156 +0,0 @@
-//go:build go1.18
-// +build go1.18
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package azidentity
-
-import (
- "context"
- "errors"
- "fmt"
- "os"
- "strings"
- "sync"
-
- "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/azure-sdk-for-go/sdk/internal/log"
- "github.com/AzureAD/microsoft-authentication-library-for-go/apps/confidential"
-)
-
-type confidentialClientOptions struct {
- azcore.ClientOptions
-
- AdditionallyAllowedTenants []string
- // Assertion for on-behalf-of authentication
- Assertion string
- DisableInstanceDiscovery, SendX5C bool
-}
-
-// confidentialClient wraps the MSAL confidential client
-type confidentialClient struct {
- cae, noCAE msalConfidentialClient
- caeMu, noCAEMu, clientMu *sync.Mutex
- clientID, tenantID string
- cred confidential.Credential
- host string
- name string
- opts confidentialClientOptions
- region string
-}
-
-func newConfidentialClient(tenantID, clientID, name string, cred confidential.Credential, opts confidentialClientOptions) (*confidentialClient, error) {
- if !validTenantID(tenantID) {
- return nil, errInvalidTenantID
- }
- host, err := setAuthorityHost(opts.Cloud)
- if err != nil {
- return nil, err
- }
- opts.AdditionallyAllowedTenants = resolveAdditionalTenants(opts.AdditionallyAllowedTenants)
- return &confidentialClient{
- caeMu: &sync.Mutex{},
- clientID: clientID,
- clientMu: &sync.Mutex{},
- cred: cred,
- host: host,
- name: name,
- noCAEMu: &sync.Mutex{},
- opts: opts,
- region: os.Getenv(azureRegionalAuthorityName),
- tenantID: tenantID,
- }, nil
-}
-
-// GetToken requests an access token from MSAL, checking the cache first.
-func (c *confidentialClient) GetToken(ctx context.Context, tro policy.TokenRequestOptions) (azcore.AccessToken, error) {
- if len(tro.Scopes) < 1 {
- return azcore.AccessToken{}, fmt.Errorf("%s.GetToken() requires at least one scope", c.name)
- }
- // we don't resolve the tenant for managed identities because they acquire tokens only from their home tenants
- if c.name != credNameManagedIdentity {
- tenant, err := c.resolveTenant(tro.TenantID)
- if err != nil {
- return azcore.AccessToken{}, err
- }
- tro.TenantID = tenant
- }
- client, mu, err := c.client(ctx, tro)
- if err != nil {
- return azcore.AccessToken{}, err
- }
- mu.Lock()
- defer mu.Unlock()
- var ar confidential.AuthResult
- if c.opts.Assertion != "" {
- ar, err = client.AcquireTokenOnBehalfOf(ctx, c.opts.Assertion, tro.Scopes, confidential.WithClaims(tro.Claims), confidential.WithTenantID(tro.TenantID))
- } else {
- ar, err = client.AcquireTokenSilent(ctx, tro.Scopes, confidential.WithClaims(tro.Claims), confidential.WithTenantID(tro.TenantID))
- if err != nil {
- ar, err = client.AcquireTokenByCredential(ctx, tro.Scopes, confidential.WithClaims(tro.Claims), confidential.WithTenantID(tro.TenantID))
- }
- }
- 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 *credentialUnavailableError
- if !errors.As(err, &unavailableErr) {
- res := getResponseFromError(err)
- err = newAuthenticationFailedError(c.name, err.Error(), res, err)
- }
- } else {
- msg := fmt.Sprintf("%s.GetToken() acquired a token for scope %q", c.name, strings.Join(ar.GrantedScopes, ", "))
- log.Write(EventAuthentication, msg)
- }
- return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
-}
-
-func (c *confidentialClient) client(ctx context.Context, tro policy.TokenRequestOptions) (msalConfidentialClient, *sync.Mutex, error) {
- c.clientMu.Lock()
- defer c.clientMu.Unlock()
- if tro.EnableCAE {
- if c.cae == nil {
- client, err := c.newMSALClient(true)
- if err != nil {
- return nil, nil, err
- }
- c.cae = client
- }
- return c.cae, c.caeMu, nil
- }
- if c.noCAE == nil {
- client, err := c.newMSALClient(false)
- if err != nil {
- return nil, nil, err
- }
- c.noCAE = client
- }
- return c.noCAE, c.noCAEMu, nil
-}
-
-func (c *confidentialClient) newMSALClient(enableCAE bool) (msalConfidentialClient, error) {
- authority := runtime.JoinPaths(c.host, c.tenantID)
- o := []confidential.Option{
- confidential.WithAzureRegion(c.region),
- confidential.WithHTTPClient(newPipelineAdapter(&c.opts.ClientOptions)),
- }
- if enableCAE {
- o = append(o, confidential.WithClientCapabilities(cp1))
- }
- if c.opts.SendX5C {
- o = append(o, confidential.WithX5C())
- }
- if c.opts.DisableInstanceDiscovery || strings.ToLower(c.tenantID) == "adfs" {
- o = append(o, confidential.WithInstanceDiscovery(false))
- }
- return confidential.New(authority, c.clientID, c.cred, o...)
-}
-
-// resolveTenant returns the correct tenant for a token request given the client's
-// configuration, or an error when that configuration doesn't allow the specified tenant
-func (c *confidentialClient) resolveTenant(specified string) (string, error) {
- return resolveTenant(c.tenantID, specified, c.name, c.opts.AdditionallyAllowedTenants)
-}
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/default_azure_credential.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/default_azure_credential.go
index 7647c60b1..7358558ac 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/default_azure_credential.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/default_azure_credential.go
@@ -21,35 +21,19 @@ import (
// DefaultAzureCredentialOptions contains optional parameters for DefaultAzureCredential.
// These options may not apply to all credentials in the chain.
type DefaultAzureCredentialOptions struct {
- // ClientOptions has additional options for credentials that use an Azure SDK HTTP pipeline. These options don't apply
- // to credential types that authenticate via external tools such as the Azure CLI.
azcore.ClientOptions
- // AdditionallyAllowedTenants specifies additional tenants for which the credential may acquire tokens. Add
- // the wildcard value "*" to allow the credential to acquire tokens for any tenant. This value can also be
- // set as a semicolon delimited list of tenants in the environment variable AZURE_ADDITIONALLY_ALLOWED_TENANTS.
- AdditionallyAllowedTenants []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 Azure AD 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 sets the default tenant for authentication via the Azure CLI and workload identity.
+ // TenantID identifies the tenant the Azure CLI should authenticate in.
+ // Defaults to the CLI's default tenant, which is typically the home tenant of the user logged in to the CLI.
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:
-//
-// - [EnvironmentCredential]
-// - [WorkloadIdentityCredential], if environment variable configuration is set by the Azure workload
-// identity webhook. Use [WorkloadIdentityCredential] directly when not using the webhook or needing
-// more control over its configuration.
-// - [ManagedIdentityCredential]
-// - [AzureCLICredential]
-//
+// It attempts to authenticate with each of these credential types, in the following order, stopping when one provides a token:
+// EnvironmentCredential
+// ManagedIdentityCredential
+// AzureCLICredential
// Consult the documentation for these credential types for more information on how they authenticate.
// Once a credential has successfully authenticated, DefaultAzureCredential will use that credential for
// every subsequent authentication.
@@ -65,18 +49,8 @@ func NewDefaultAzureCredential(options *DefaultAzureCredentialOptions) (*Default
if options == nil {
options = &DefaultAzureCredentialOptions{}
}
- additionalTenants := options.AdditionallyAllowedTenants
- if len(additionalTenants) == 0 {
- if tenants := os.Getenv(azureAdditionallyAllowedTenants); tenants != "" {
- additionalTenants = strings.Split(tenants, ";")
- }
- }
- envCred, err := NewEnvironmentCredential(&EnvironmentCredentialOptions{
- ClientOptions: options.ClientOptions,
- DisableInstanceDiscovery: options.DisableInstanceDiscovery,
- additionallyAllowedTenants: additionalTenants,
- })
+ envCred, err := NewEnvironmentCredential(&EnvironmentCredentialOptions{ClientOptions: options.ClientOptions})
if err == nil {
creds = append(creds, envCred)
} else {
@@ -84,32 +58,20 @@ func NewDefaultAzureCredential(options *DefaultAzureCredentialOptions) (*Default
creds = append(creds, &defaultCredentialErrorReporter{credType: "EnvironmentCredential", err: err})
}
- wic, err := NewWorkloadIdentityCredential(&WorkloadIdentityCredentialOptions{
- AdditionallyAllowedTenants: additionalTenants,
- ClientOptions: options.ClientOptions,
- DisableInstanceDiscovery: options.DisableInstanceDiscovery,
- TenantID: options.TenantID,
- })
- if err == nil {
- creds = append(creds, wic)
- } else {
- errorMessages = append(errorMessages, credNameWorkloadIdentity+": "+err.Error())
- creds = append(creds, &defaultCredentialErrorReporter{credType: credNameWorkloadIdentity, err: err})
- }
-
o := &ManagedIdentityCredentialOptions{ClientOptions: options.ClientOptions}
if ID, ok := os.LookupEnv(azureClientID); ok {
o.ID = ClientID(ID)
}
- miCred, err := NewManagedIdentityCredential(o)
+ msiCred, err := NewManagedIdentityCredential(o)
if err == nil {
- creds = append(creds, &timeoutWrapper{mic: miCred, timeout: time.Second})
+ creds = append(creds, msiCred)
+ msiCred.client.imdsTimeout = time.Second
} else {
errorMessages = append(errorMessages, credNameManagedIdentity+": "+err.Error())
creds = append(creds, &defaultCredentialErrorReporter{credType: credNameManagedIdentity, err: err})
}
- cliCred, err := NewAzureCLICredential(&AzureCLICredentialOptions{AdditionallyAllowedTenants: additionalTenants, TenantID: options.TenantID})
+ cliCred, err := NewAzureCLICredential(&AzureCLICredentialOptions{TenantID: options.TenantID})
if err == nil {
creds = append(creds, cliCred)
} else {
@@ -117,8 +79,9 @@ func NewDefaultAzureCredential(options *DefaultAzureCredentialOptions) (*Default
creds = append(creds, &defaultCredentialErrorReporter{credType: credNameAzureCLI, err: err})
}
- if len(errorMessages) > 0 {
- log.Writef(EventAuthentication, "NewDefaultAzureCredential failed to initialize some credentials:\n\t%s", strings.Join(errorMessages, "\n\t"))
+ err = defaultAzureCredentialConstructorErrorHandler(len(creds), errorMessages)
+ if err != nil {
+ return nil, err
}
chain, err := NewChainedTokenCredential(creds, nil)
@@ -136,6 +99,20 @@ func (c *DefaultAzureCredential) GetToken(ctx context.Context, opts policy.Token
var _ azcore.TokenCredential = (*DefaultAzureCredential)(nil)
+func defaultAzureCredentialConstructorErrorHandler(numberOfSuccessfulCredentials int, errorMessages []string) (err error) {
+ errorMessage := strings.Join(errorMessages, "\n\t")
+
+ if numberOfSuccessfulCredentials == 0 {
+ return errors.New(errorMessage)
+ }
+
+ if len(errorMessages) != 0 {
+ log.Writef(EventAuthentication, "NewDefaultAzureCredential failed to initialize some credentials:\n\t%s", errorMessage)
+ }
+
+ return nil
+}
+
// defaultCredentialErrorReporter is a substitute for credentials that couldn't be constructed.
// Its GetToken method always returns a credentialUnavailableError having the same message as
// the error that prevented constructing the credential. This ensures the message is present
@@ -153,44 +130,3 @@ func (d *defaultCredentialErrorReporter) GetToken(ctx context.Context, opts poli
}
var _ azcore.TokenCredential = (*defaultCredentialErrorReporter)(nil)
-
-// timeoutWrapper prevents a potentially very long timeout when managed identity isn't available
-type timeoutWrapper struct {
- mic *ManagedIdentityCredential
- // timeout applies to all auth attempts until one doesn't time out
- timeout time.Duration
-}
-
-// GetToken wraps DefaultAzureCredential's initial managed identity auth attempt with a short timeout
-// because managed identity may not be available and connecting to IMDS can take several minutes to time out.
-func (w *timeoutWrapper) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
- var tk azcore.AccessToken
- var err error
- // no need to synchronize around this value because it's written only within ChainedTokenCredential's critical section
- if w.timeout > 0 {
- c, cancel := context.WithTimeout(ctx, w.timeout)
- defer cancel()
- tk, err = w.mic.GetToken(c, opts)
- if isAuthFailedDueToContext(err) {
- err = newCredentialUnavailableError(credNameManagedIdentity, "managed identity timed out. See https://aka.ms/azsdk/go/identity/troubleshoot#dac for more information")
- } else {
- // some managed identity implementation is available, so don't apply the timeout to future calls
- w.timeout = 0
- }
- } else {
- tk, err = w.mic.GetToken(ctx, opts)
- }
- return tk, err
-}
-
-// unwraps nested AuthenticationFailedErrors to get the root error
-func isAuthFailedDueToContext(err error) bool {
- for {
- var authFailedErr *AuthenticationFailedError
- if !errors.As(err, &authFailedErr) {
- break
- }
- err = authFailedErr.err
- }
- return errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded)
-}
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/device_code_credential.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/device_code_credential.go
index d245c269a..d0c72c348 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/device_code_credential.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/device_code_credential.go
@@ -8,10 +8,13 @@ package azidentity
import (
"context"
+ "errors"
"fmt"
"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/AzureAD/microsoft-authentication-library-for-go/apps/public"
)
const credNameDeviceCode = "DeviceCodeCredential"
@@ -20,22 +23,13 @@ const credNameDeviceCode = "DeviceCodeCredential"
type DeviceCodeCredentialOptions struct {
azcore.ClientOptions
- // AdditionallyAllowedTenants specifies additional tenants for which the credential may acquire
- // tokens. Add the wildcard value "*" to allow the credential to acquire tokens for any tenant.
- AdditionallyAllowedTenants []string
- // ClientID is the ID of the application users will authenticate to.
- // Defaults to the ID of an Azure development application.
- 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 Azure AD 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 is the Azure Active Directory tenant the credential authenticates in. Defaults to the
// "organizations" tenant, which can authenticate work and school accounts. Required for single-tenant
// applications.
TenantID string
-
+ // ClientID is the ID of the application users will authenticate to.
+ // Defaults to the ID of an Azure development application.
+ ClientID string
// 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.
@@ -73,7 +67,9 @@ type DeviceCodeMessage struct {
// If a web browser is available, InteractiveBrowserCredential is more convenient because it
// automatically opens a browser to the login page.
type DeviceCodeCredential struct {
- client *publicClient
+ client publicClient
+ userPrompt func(context.Context, DeviceCodeMessage) error
+ account public.Account
}
// NewDeviceCodeCredential creates a DeviceCodeCredential. Pass nil to accept default options.
@@ -83,24 +79,52 @@ func NewDeviceCodeCredential(options *DeviceCodeCredentialOptions) (*DeviceCodeC
cp = *options
}
cp.init()
- msalOpts := publicClientOptions{
- AdditionallyAllowedTenants: cp.AdditionallyAllowedTenants,
- ClientOptions: cp.ClientOptions,
- DeviceCodePrompt: cp.UserPrompt,
- DisableInstanceDiscovery: cp.DisableInstanceDiscovery,
+ if !validTenantID(cp.TenantID) {
+ return nil, errors.New(tenantIDValidationErr)
+ }
+ authorityHost, err := setAuthorityHost(cp.Cloud)
+ if err != nil {
+ return nil, err
}
- c, err := newPublicClient(cp.TenantID, cp.ClientID, credNameDeviceCode, msalOpts)
+ c, err := public.New(cp.ClientID,
+ public.WithAuthority(runtime.JoinPaths(authorityHost, cp.TenantID)),
+ public.WithHTTPClient(newPipelineAdapter(&cp.ClientOptions)),
+ )
if err != nil {
return nil, err
}
- c.name = credNameDeviceCode
- return &DeviceCodeCredential{client: c}, nil
+ return &DeviceCodeCredential{userPrompt: cp.UserPrompt, client: c}, nil
}
// GetToken requests an access token from Azure Active Directory. It will begin the device code flow and poll until the user completes authentication.
// This method is called automatically by Azure SDK clients.
func (c *DeviceCodeCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
- return c.client.GetToken(ctx, opts)
+ if len(opts.Scopes) == 0 {
+ return azcore.AccessToken{}, errors.New(credNameDeviceCode + ": GetToken() requires at least one scope")
+ }
+ ar, err := c.client.AcquireTokenSilent(ctx, opts.Scopes, public.WithSilentAccount(c.account))
+ if err == nil {
+ return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
+ }
+ dc, err := c.client.AcquireTokenByDeviceCode(ctx, opts.Scopes)
+ if err != nil {
+ return azcore.AccessToken{}, newAuthenticationFailedErrorFromMSALError(credNameDeviceCode, err)
+ }
+ err = c.userPrompt(ctx, DeviceCodeMessage{
+ UserCode: dc.Result.UserCode,
+ VerificationURL: dc.Result.VerificationURL,
+ Message: dc.Result.Message,
+ })
+ if err != nil {
+ return azcore.AccessToken{}, err
+ }
+ ar, err = dc.AuthenticationResult(ctx)
+ if err != nil {
+ return azcore.AccessToken{}, newAuthenticationFailedErrorFromMSALError(credNameDeviceCode, err)
+ }
+ c.account = ar.Account
+ logGetTokenSuccess(c, opts)
+ return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
}
var _ azcore.TokenCredential = (*DeviceCodeCredential)(nil)
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/environment_credential.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/environment_credential.go
index 7ecd928e0..16c595d1d 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/environment_credential.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/environment_credential.go
@@ -23,23 +23,12 @@ const envVarSendCertChain = "AZURE_CLIENT_SEND_CERTIFICATE_CHAIN"
// EnvironmentCredentialOptions contains optional parameters for EnvironmentCredential
type EnvironmentCredentialOptions struct {
azcore.ClientOptions
-
- // 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 Azure AD 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
- // additionallyAllowedTenants is used only by NewDefaultAzureCredential() to enable that constructor's explicit
- // option to override the value of AZURE_ADDITIONALLY_ALLOWED_TENANTS. Applications using EnvironmentCredential
- // directly should set that variable instead. This field should remain unexported to preserve this credential's
- // unambiguous "all configuration from environment variables" design.
- additionallyAllowedTenants []string
}
// EnvironmentCredential authenticates a service principal with a secret or certificate, or a user with a password, depending
// on environment variable configuration. It reads configuration from these variables, in the following order:
//
-// # Service principal with client secret
+// Service principal with client secret
//
// AZURE_TENANT_ID: ID of the service principal's tenant. Also called its "directory" ID.
//
@@ -47,17 +36,15 @@ type EnvironmentCredentialOptions struct {
//
// AZURE_CLIENT_SECRET: one of the service principal's client secrets
//
-// # Service principal with certificate
+// Service principal with certificate
//
// AZURE_TENANT_ID: ID of the service principal's tenant. Also called its "directory" ID.
//
// AZURE_CLIENT_ID: the service principal's client ID
//
-// AZURE_CLIENT_CERTIFICATE_PATH: path to a PEM or PKCS12 certificate file including the private key.
-//
-// AZURE_CLIENT_CERTIFICATE_PASSWORD: (optional) password for the certificate file.
+// AZURE_CLIENT_CERTIFICATE_PATH: path to a PEM or PKCS12 certificate file including the unencrypted private key.
//
-// # User with username and password
+// User with username and password
//
// AZURE_TENANT_ID: (optional) tenant to authenticate in. Defaults to "organizations".
//
@@ -66,12 +53,6 @@ type EnvironmentCredentialOptions struct {
// AZURE_USERNAME: a username (usually an email address)
//
// AZURE_PASSWORD: the user's password
-//
-// # Configuration for multitenant applications
-//
-// To enable multitenant authentication, set AZURE_ADDITIONALLY_ALLOWED_TENANTS with a semicolon delimited list of tenants
-// the credential may request tokens from in addition to the tenant specified by AZURE_TENANT_ID. Set
-// AZURE_ADDITIONALLY_ALLOWED_TENANTS to "*" to enable the credential to request a token from any tenant.
type EnvironmentCredential struct {
cred azcore.TokenCredential
}
@@ -81,7 +62,7 @@ func NewEnvironmentCredential(options *EnvironmentCredentialOptions) (*Environme
if options == nil {
options = &EnvironmentCredentialOptions{}
}
- tenantID := os.Getenv(azureTenantID)
+ tenantID := os.Getenv("AZURE_TENANT_ID")
if tenantID == "" {
return nil, errors.New("missing environment variable AZURE_TENANT_ID")
}
@@ -89,45 +70,26 @@ func NewEnvironmentCredential(options *EnvironmentCredentialOptions) (*Environme
if clientID == "" {
return nil, errors.New("missing environment variable " + azureClientID)
}
- // tenants set by NewDefaultAzureCredential() override the value of AZURE_ADDITIONALLY_ALLOWED_TENANTS
- additionalTenants := options.additionallyAllowedTenants
- if len(additionalTenants) == 0 {
- if tenants := os.Getenv(azureAdditionallyAllowedTenants); tenants != "" {
- additionalTenants = strings.Split(tenants, ";")
- }
- }
- if clientSecret := os.Getenv(azureClientSecret); clientSecret != "" {
+ if clientSecret := os.Getenv("AZURE_CLIENT_SECRET"); clientSecret != "" {
log.Write(EventAuthentication, "EnvironmentCredential will authenticate with ClientSecretCredential")
- o := &ClientSecretCredentialOptions{
- AdditionallyAllowedTenants: additionalTenants,
- ClientOptions: options.ClientOptions,
- DisableInstanceDiscovery: options.DisableInstanceDiscovery,
- }
+ o := &ClientSecretCredentialOptions{ClientOptions: options.ClientOptions}
cred, err := NewClientSecretCredential(tenantID, clientID, clientSecret, o)
if err != nil {
return nil, err
}
return &EnvironmentCredential{cred: cred}, nil
}
- if certPath := os.Getenv(azureClientCertificatePath); certPath != "" {
+ if certPath := os.Getenv("AZURE_CLIENT_CERTIFICATE_PATH"); certPath != "" {
log.Write(EventAuthentication, "EnvironmentCredential will authenticate with ClientCertificateCredential")
certData, err := os.ReadFile(certPath)
if err != nil {
return nil, fmt.Errorf(`failed to read certificate file "%s": %v`, certPath, err)
}
- var password []byte
- if v := os.Getenv(azureClientCertificatePassword); v != "" {
- password = []byte(v)
- }
- certs, key, err := ParseCertificates(certData, password)
+ certs, key, err := ParseCertificates(certData, nil)
if err != nil {
return nil, fmt.Errorf(`failed to load certificate from "%s": %v`, certPath, err)
}
- o := &ClientCertificateCredentialOptions{
- AdditionallyAllowedTenants: additionalTenants,
- ClientOptions: options.ClientOptions,
- DisableInstanceDiscovery: options.DisableInstanceDiscovery,
- }
+ o := &ClientCertificateCredentialOptions{ClientOptions: options.ClientOptions}
if v, ok := os.LookupEnv(envVarSendCertChain); ok {
o.SendCertificateChain = v == "1" || strings.ToLower(v) == "true"
}
@@ -137,14 +99,10 @@ func NewEnvironmentCredential(options *EnvironmentCredentialOptions) (*Environme
}
return &EnvironmentCredential{cred: cred}, nil
}
- if username := os.Getenv(azureUsername); username != "" {
- if password := os.Getenv(azurePassword); password != "" {
+ if username := os.Getenv("AZURE_USERNAME"); username != "" {
+ if password := os.Getenv("AZURE_PASSWORD"); password != "" {
log.Write(EventAuthentication, "EnvironmentCredential will authenticate with UsernamePasswordCredential")
- o := &UsernamePasswordCredentialOptions{
- AdditionallyAllowedTenants: additionalTenants,
- ClientOptions: options.ClientOptions,
- DisableInstanceDiscovery: options.DisableInstanceDiscovery,
- }
+ o := &UsernamePasswordCredentialOptions{ClientOptions: options.ClientOptions}
cred, err := NewUsernamePasswordCredential(tenantID, clientID, username, password, o)
if err != nil {
return nil, err
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/errors.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/errors.go
index e1a21e003..c60d13d00 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/errors.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/errors.go
@@ -11,9 +11,9 @@ import (
"encoding/json"
"errors"
"fmt"
+ "io"
"net/http"
- "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
"github.com/Azure/azure-sdk-for-go/sdk/internal/errorinfo"
msal "github.com/AzureAD/microsoft-authentication-library-for-go/apps/errors"
)
@@ -39,11 +39,15 @@ type AuthenticationFailedError struct {
credType string
message string
- err error
}
-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 string, message string, resp *http.Response) error {
+ return &AuthenticationFailedError{credType: credType, message: message, RawResponse: resp}
+}
+
+func newAuthenticationFailedErrorFromMSALError(credType string, err error) error {
+ res := getResponseFromError(err)
+ return newAuthenticationFailedError(credType, err.Error(), res)
}
// Error implements the error interface. Note that the message contents are not contractual and can change over time.
@@ -57,37 +61,20 @@ func (e *AuthenticationFailedError) Error() string {
fmt.Fprintln(msg, "--------------------------------------------------------------------------------")
fmt.Fprintf(msg, "RESPONSE %s\n", e.RawResponse.Status)
fmt.Fprintln(msg, "--------------------------------------------------------------------------------")
- body, err := runtime.Payload(e.RawResponse)
- switch {
- case err != nil:
+ body, err := io.ReadAll(e.RawResponse.Body)
+ e.RawResponse.Body.Close()
+ if err != nil {
fmt.Fprintf(msg, "Error reading response body: %v", err)
- case len(body) > 0:
+ } else if len(body) > 0 {
+ e.RawResponse.Body = io.NopCloser(bytes.NewReader(body))
if err := json.Indent(msg, body, "", " "); err != nil {
// failed to pretty-print so just dump it verbatim
fmt.Fprint(msg, string(body))
}
- default:
+ } else {
fmt.Fprint(msg, "Response contained no body")
}
fmt.Fprintln(msg, "\n--------------------------------------------------------------------------------")
- var anchor string
- switch e.credType {
- case credNameAzureCLI:
- anchor = "azure-cli"
- case credNameCert:
- anchor = "client-cert"
- case credNameSecret:
- anchor = "client-secret"
- case credNameManagedIdentity:
- anchor = "managed-id"
- case credNameUserPassword:
- anchor = "username-password"
- case credNameWorkloadIdentity:
- anchor = "workload"
- }
- if anchor != "" {
- fmt.Fprintf(msg, "To troubleshoot, visit https://aka.ms/azsdk/go/identity/troubleshoot#%s", anchor)
- }
return msg.String()
}
@@ -98,31 +85,24 @@ func (*AuthenticationFailedError) NonRetriable() {
var _ errorinfo.NonRetriable = (*AuthenticationFailedError)(nil)
-// credentialUnavailableError indicates a credential can't attempt authentication because it lacks required
-// data or state
+// credentialUnavailableError indicates a credential can't attempt
+// authentication because it lacks required data or state.
type credentialUnavailableError struct {
- message string
+ credType string
+ message string
}
-// newCredentialUnavailableError is an internal helper that ensures consistent error message formatting
func newCredentialUnavailableError(credType, message string) error {
- msg := fmt.Sprintf("%s: %s", credType, message)
- return &credentialUnavailableError{msg}
+ return &credentialUnavailableError{credType: credType, message: message}
}
-// NewCredentialUnavailableError constructs an error indicating a credential can't attempt authentication
-// because it lacks required data or state. When [ChainedTokenCredential] receives this error it will try
-// its next credential, if any.
-func NewCredentialUnavailableError(message string) error {
- return &credentialUnavailableError{message}
-}
-
-// Error implements the error interface. Note that the message contents are not contractual and can change over time.
func (e *credentialUnavailableError) Error() string {
- return e.message
+ return e.credType + ": " + e.message
}
-// NonRetriable is a marker method indicating this error should not be retried. It has no implementation.
-func (e *credentialUnavailableError) NonRetriable() {}
+// NonRetriable indicates that this error should not be retried.
+func (e *credentialUnavailableError) NonRetriable() {
+ // marker method
+}
var _ errorinfo.NonRetriable = (*credentialUnavailableError)(nil)
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/interactive_browser_credential.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/interactive_browser_credential.go
index 08f3efbf3..e4aaf45b6 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/interactive_browser_credential.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/interactive_browser_credential.go
@@ -8,40 +8,29 @@ package azidentity
import (
"context"
+ "errors"
"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/AzureAD/microsoft-authentication-library-for-go/apps/public"
)
-const credNameBrowser = "InteractiveBrowserCredential"
+const credNameBrowser = "InteractiveBrowserCredentiall"
// InteractiveBrowserCredentialOptions contains optional parameters for InteractiveBrowserCredential.
type InteractiveBrowserCredentialOptions struct {
azcore.ClientOptions
- // AdditionallyAllowedTenants specifies additional tenants for which the credential may acquire
- // tokens. Add the wildcard value "*" to allow the credential to acquire tokens for any tenant.
- AdditionallyAllowedTenants []string
+ // TenantID is the Azure Active Directory tenant the credential authenticates in. Defaults to the
+ // "organizations" tenant, which can authenticate work and school accounts.
+ TenantID string
// ClientID is the ID of the application users will authenticate to.
// Defaults to the ID of an Azure development application.
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 Azure AD 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
-
- // LoginHint pre-populates the account prompt with a username. Users may choose to authenticate a different account.
- LoginHint string
- // RedirectURL is the URL Azure Active Directory will redirect to with the access token. This is required
- // only when setting ClientID, and must match a redirect URI in the application's registration.
- // Applications which have registered "http://localhost" as a redirect URI need not set this option.
+ // RedirectURL will be supported in a future version but presently doesn't work: https://github.com/Azure/azure-sdk-for-go/issues/15632.
+ // Applications which have "http://localhost" registered as a redirect URL need not set this option.
RedirectURL string
-
- // TenantID is the Azure Active Directory tenant the credential authenticates in. Defaults to the
- // "organizations" tenant, which can authenticate work and school accounts.
- TenantID string
}
func (o *InteractiveBrowserCredentialOptions) init() {
@@ -55,7 +44,9 @@ func (o *InteractiveBrowserCredentialOptions) init() {
// InteractiveBrowserCredential opens a browser to interactively authenticate a user.
type InteractiveBrowserCredential struct {
- client *publicClient
+ client publicClient
+ options InteractiveBrowserCredentialOptions
+ account public.Account
}
// NewInteractiveBrowserCredential constructs a new InteractiveBrowserCredential. Pass nil to accept default options.
@@ -65,22 +56,45 @@ func NewInteractiveBrowserCredential(options *InteractiveBrowserCredentialOption
cp = *options
}
cp.init()
- msalOpts := publicClientOptions{
- ClientOptions: cp.ClientOptions,
- DisableInstanceDiscovery: cp.DisableInstanceDiscovery,
- LoginHint: cp.LoginHint,
- RedirectURL: cp.RedirectURL,
+ if !validTenantID(cp.TenantID) {
+ return nil, errors.New(tenantIDValidationErr)
}
- c, err := newPublicClient(cp.TenantID, cp.ClientID, credNameBrowser, msalOpts)
+ authorityHost, err := setAuthorityHost(cp.Cloud)
if err != nil {
return nil, err
}
- return &InteractiveBrowserCredential{client: c}, nil
+ c, err := public.New(cp.ClientID,
+ public.WithAuthority(runtime.JoinPaths(authorityHost, cp.TenantID)),
+ public.WithHTTPClient(newPipelineAdapter(&cp.ClientOptions)),
+ )
+ if err != nil {
+ return nil, err
+ }
+ return &InteractiveBrowserCredential{options: cp, client: c}, nil
}
// GetToken requests an access token from Azure Active Directory. This method is called automatically by Azure SDK clients.
func (c *InteractiveBrowserCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
- return c.client.GetToken(ctx, opts)
+ if len(opts.Scopes) == 0 {
+ return azcore.AccessToken{}, errors.New(credNameBrowser + ": GetToken() requires at least one scope")
+ }
+ ar, err := c.client.AcquireTokenSilent(ctx, opts.Scopes, public.WithSilentAccount(c.account))
+ if err == nil {
+ logGetTokenSuccess(c, opts)
+ return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
+ }
+
+ o := []public.InteractiveAuthOption{}
+ if c.options.RedirectURL != "" {
+ o = append(o, public.WithRedirectURI(c.options.RedirectURL))
+ }
+ ar, err = c.client.AcquireTokenInteractive(ctx, opts.Scopes, o...)
+ if err != nil {
+ return azcore.AccessToken{}, newAuthenticationFailedErrorFromMSALError(credNameBrowser, err)
+ }
+ c.account = ar.Account
+ logGetTokenSuccess(c, opts)
+ return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
}
var _ azcore.TokenCredential = (*InteractiveBrowserCredential)(nil)
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/logging.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/logging.go
index 1aa1e0fc7..569453e46 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/logging.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/logging.go
@@ -6,9 +6,25 @@
package azidentity
-import "github.com/Azure/azure-sdk-for-go/sdk/internal/log"
+import (
+ "fmt"
+ "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/internal/log"
+)
// EventAuthentication entries contain information about authentication.
// This includes information like the names of environment variables
// used when obtaining credentials and the type of credential used.
const EventAuthentication log.Event = "Authentication"
+
+func logGetTokenSuccess(cred azcore.TokenCredential, opts policy.TokenRequestOptions) {
+ if !log.Should(EventAuthentication) {
+ return
+ }
+ scope := strings.Join(opts.Scopes, ", ")
+ msg := fmt.Sprintf("%T.GetToken() acquired a token for scope %s\n", cred, scope)
+ log.Write(EventAuthentication, msg)
+}
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/managed_identity_client.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/managed_identity_client.go
index fdc3c1f67..ce6e1e614 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/managed_identity_client.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/managed_identity_client.go
@@ -11,6 +11,7 @@ import (
"encoding/json"
"errors"
"fmt"
+ "io/ioutil"
"net/http"
"net/url"
"os"
@@ -23,7 +24,6 @@ import (
"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/internal/log"
- "github.com/AzureAD/microsoft-authentication-library-for-go/apps/confidential"
)
const (
@@ -55,10 +55,11 @@ const (
// managedIdentityClient provides the base for authenticating in managed identity environments
// This type includes an runtime.Pipeline and TokenCredentialOptions.
type managedIdentityClient struct {
- pipeline runtime.Pipeline
- msiType msiType
- endpoint string
- id ManagedIDKind
+ pipeline runtime.Pipeline
+ msiType msiType
+ endpoint string
+ id ManagedIDKind
+ imdsTimeout time.Duration
}
type wrappedNumber json.Number
@@ -84,15 +85,13 @@ func setIMDSRetryOptionDefaults(o *policy.RetryOptions) {
}
if o.StatusCodes == nil {
o.StatusCodes = []int{
- // IMDS docs recommend retrying 404, 410, 429 and 5xx
- // https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/how-to-use-vm-token#error-handling
+ // IMDS docs recommend retrying 404, 429 and all 5xx
+ // https://docs.microsoft.com/azure/active-directory/managed-identities-azure-resources/how-to-use-vm-token#error-handling
http.StatusNotFound, // 404
- http.StatusGone, // 410
http.StatusTooManyRequests, // 429
http.StatusInternalServerError, // 500
http.StatusNotImplemented, // 501
http.StatusBadGateway, // 502
- http.StatusServiceUnavailable, // 503
http.StatusGatewayTimeout, // 504
http.StatusHTTPVersionNotSupported, // 505
http.StatusVariantAlsoNegotiates, // 506
@@ -150,19 +149,17 @@ func newManagedIdentityClient(options *ManagedIdentityCredentialOptions) (*manag
return &c, nil
}
-// provideToken acquires a token for MSAL's confidential.Client, which caches the token
-func (c *managedIdentityClient) provideToken(ctx context.Context, params confidential.TokenProviderParameters) (confidential.TokenProviderResult, error) {
- result := confidential.TokenProviderResult{}
- tk, err := c.authenticate(ctx, c.id, params.Scopes)
- if err == nil {
- result.AccessToken = tk.Token
- result.ExpiresInSeconds = int(time.Until(tk.ExpiresOn).Seconds())
- }
- return result, err
-}
-
-// authenticate acquires an access token
+// authenticate creates an authentication request for a Managed Identity and returns the resulting Access Token if successful.
+// ctx: The current context for controlling the request lifetime.
+// clientID: The client (application) ID of the service principal.
+// scopes: The scopes required for the token.
func (c *managedIdentityClient) authenticate(ctx context.Context, id ManagedIDKind, scopes []string) (azcore.AccessToken, error) {
+ var cancel context.CancelFunc
+ if c.imdsTimeout > 0 && c.msiType == msiTypeIMDS {
+ ctx, cancel = context.WithTimeout(ctx, c.imdsTimeout)
+ defer cancel()
+ }
+
msg, err := c.createAuthRequest(ctx, id, scopes)
if err != nil {
return azcore.AccessToken{}, err
@@ -170,35 +167,27 @@ func (c *managedIdentityClient) authenticate(ctx context.Context, id ManagedIDKi
resp, err := c.pipeline.Do(msg)
if err != nil {
- return azcore.AccessToken{}, newAuthenticationFailedError(credNameManagedIdentity, err.Error(), nil, err)
+ if cancel != nil && errors.Is(err, context.DeadlineExceeded) {
+ return azcore.AccessToken{}, newCredentialUnavailableError(credNameManagedIdentity, "IMDS token request timed out")
+ }
+ return azcore.AccessToken{}, newAuthenticationFailedError(credNameManagedIdentity, err.Error(), nil)
}
+ // got a response, remove the IMDS timeout so future requests use the transport's configuration
+ c.imdsTimeout = 0
+
if runtime.HasStatusCode(resp, http.StatusOK, http.StatusCreated) {
return c.createAccessToken(resp)
}
- if c.msiType == msiTypeIMDS {
- 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)
- }
- msg := "failed to authenticate a system assigned identity"
- if body, err := runtime.Payload(resp); err == nil && len(body) > 0 {
- msg += fmt.Sprintf(". The endpoint responded with %s", body)
- }
- return azcore.AccessToken{}, newCredentialUnavailableError(credNameManagedIdentity, msg)
- case http.StatusForbidden:
- // Docker Desktop runs a proxy that responds 403 to IMDS token requests. If we get that response,
- // we return credentialUnavailableError so credential chains continue to their next credential
- body, err := runtime.Payload(resp)
- if err == nil && strings.Contains(string(body), "A socket operation was attempted to an unreachable network") {
- return azcore.AccessToken{}, newCredentialUnavailableError(credNameManagedIdentity, fmt.Sprintf("unexpected response %q", string(body)))
- }
+ if c.msiType == msiTypeIMDS && resp.StatusCode == 400 {
+ if id != nil {
+ return azcore.AccessToken{}, newAuthenticationFailedError(credNameManagedIdentity, "the requested identity isn't assigned to this resource", resp)
}
+ return azcore.AccessToken{}, newCredentialUnavailableError(credNameManagedIdentity, "no default identity is assigned to this resource")
}
- return azcore.AccessToken{}, newAuthenticationFailedError(credNameManagedIdentity, "authentication failed", resp, nil)
+ return azcore.AccessToken{}, newAuthenticationFailedError(credNameManagedIdentity, "authentication failed", resp)
}
func (c *managedIdentityClient) createAccessToken(res *http.Response) (azcore.AccessToken, error) {
@@ -226,10 +215,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)
}
}
@@ -244,7 +233,7 @@ 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)
case msiTypeServiceFabric:
@@ -338,7 +327,7 @@ 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 {
@@ -349,7 +338,7 @@ func (c *managedIdentityClient) getAzureArcSecretKey(ctx context.Context, resour
if pos == -1 {
return "", fmt.Errorf("did not receive a correct value from WWW-Authenticate header: %s", header)
}
- key, err := os.ReadFile(header[pos+1:])
+ key, err := ioutil.ReadFile(header[pos+1:])
if err != nil {
return "", fmt.Errorf("could not read file (%s) contents: %v", header[pos+1:], err)
}
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/managed_identity_credential.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/managed_identity_credential.go
index 35c5e6725..f17ada1c3 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/managed_identity_credential.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/managed_identity_credential.go
@@ -8,12 +8,12 @@ package azidentity
import (
"context"
+ "errors"
"fmt"
"strings"
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
- "github.com/AzureAD/microsoft-authentication-library-for-go/apps/confidential"
)
const credNameManagedIdentity = "ManagedIdentityCredential"
@@ -70,8 +70,8 @@ type ManagedIdentityCredentialOptions struct {
// user-assigned identity. See Azure Active Directory documentation for more information about managed identities:
// https://docs.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview
type ManagedIdentityCredential struct {
- client *confidentialClient
- mic *managedIdentityClient
+ id ManagedIDKind
+ client *managedIdentityClient
}
// NewManagedIdentityCredential creates a ManagedIdentityCredential. Pass nil to accept default options.
@@ -79,35 +79,27 @@ func NewManagedIdentityCredential(options *ManagedIdentityCredentialOptions) (*M
if options == nil {
options = &ManagedIdentityCredentialOptions{}
}
- mic, err := newManagedIdentityClient(options)
+ client, err := newManagedIdentityClient(options)
if err != nil {
return nil, err
}
- cred := confidential.NewCredFromTokenProvider(mic.provideToken)
-
- // It's okay to give MSAL an invalid client ID because MSAL will use it only as part of a cache key.
- // ManagedIdentityClient handles all the details of authentication and won't receive this value from MSAL.
- clientID := "SYSTEM-ASSIGNED-MANAGED-IDENTITY"
- if options.ID != nil {
- clientID = options.ID.String()
- }
- // similarly, it's okay to give MSAL an incorrect tenant because MSAL won't use the value
- c, err := newConfidentialClient("common", clientID, credNameManagedIdentity, cred, confidentialClientOptions{})
- if err != nil {
- return nil, err
- }
- return &ManagedIdentityCredential{client: c, mic: mic}, nil
+ return &ManagedIdentityCredential{id: options.ID, client: client}, nil
}
// GetToken requests an access token from the hosting environment. This method is called automatically by Azure SDK clients.
func (c *ManagedIdentityCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
if len(opts.Scopes) != 1 {
- err := fmt.Errorf("%s.GetToken() requires exactly one scope", credNameManagedIdentity)
+ err := errors.New(credNameManagedIdentity + ": GetToken() requires exactly one scope")
return azcore.AccessToken{}, err
}
// managed identity endpoints require an AADv1 resource (i.e. token audience), not a v2 scope, so we remove "/.default" here
- opts.Scopes = []string{strings.TrimSuffix(opts.Scopes[0], defaultSuffix)}
- return c.client.GetToken(ctx, opts)
+ scopes := []string{strings.TrimSuffix(opts.Scopes[0], defaultSuffix)}
+ tk, err := c.client.authenticate(ctx, c.id, scopes)
+ if err != nil {
+ return azcore.AccessToken{}, err
+ }
+ logGetTokenSuccess(c, opts)
+ return tk, err
}
var _ azcore.TokenCredential = (*ManagedIdentityCredential)(nil)
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/on_behalf_of_credential.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/on_behalf_of_credential.go
deleted file mode 100644
index 2b360b681..000000000
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/on_behalf_of_credential.go
+++ /dev/null
@@ -1,92 +0,0 @@
-//go:build go1.18
-// +build go1.18
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package azidentity
-
-import (
- "context"
- "crypto"
- "crypto/x509"
-
- "github.com/Azure/azure-sdk-for-go/sdk/azcore"
- "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
- "github.com/AzureAD/microsoft-authentication-library-for-go/apps/confidential"
-)
-
-const credNameOBO = "OnBehalfOfCredential"
-
-// OnBehalfOfCredential authenticates a service principal via the on-behalf-of flow. This is typically used by
-// middle-tier services that authorize requests to other services with a delegated user identity. Because this
-// is not an interactive authentication flow, an application using it must have admin consent for any delegated
-// permissions before requesting tokens for them. See [Azure Active Directory documentation] for more details.
-//
-// [Azure Active Directory documentation]: https://docs.microsoft.com/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow
-type OnBehalfOfCredential struct {
- client *confidentialClient
-}
-
-// OnBehalfOfCredentialOptions contains optional parameters for OnBehalfOfCredential
-type OnBehalfOfCredentialOptions struct {
- azcore.ClientOptions
-
- // AdditionallyAllowedTenants specifies additional tenants for which the credential may acquire tokens.
- // Add the wildcard value "*" to allow the credential to acquire tokens for any tenant in which the
- // application is registered.
- AdditionallyAllowedTenants []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 Azure AD 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
- // SendCertificateChain applies only when the credential is configured to authenticate with a certificate.
- // This setting controls whether the credential sends the public certificate chain in the x5c header of each
- // token request's JWT. This is required for, and only used in, Subject Name/Issuer (SNI) authentication.
- SendCertificateChain bool
-}
-
-// NewOnBehalfOfCredentialWithCertificate constructs an OnBehalfOfCredential that authenticates with a certificate.
-// See [ParseCertificates] for help loading a certificate.
-func NewOnBehalfOfCredentialWithCertificate(tenantID, clientID, userAssertion string, certs []*x509.Certificate, key crypto.PrivateKey, options *OnBehalfOfCredentialOptions) (*OnBehalfOfCredential, error) {
- cred, err := confidential.NewCredFromCert(certs, key)
- if err != nil {
- return nil, err
- }
- return newOnBehalfOfCredential(tenantID, clientID, userAssertion, cred, options)
-}
-
-// NewOnBehalfOfCredentialWithSecret constructs an OnBehalfOfCredential that authenticates with a client secret.
-func NewOnBehalfOfCredentialWithSecret(tenantID, clientID, userAssertion, clientSecret string, options *OnBehalfOfCredentialOptions) (*OnBehalfOfCredential, error) {
- cred, err := confidential.NewCredFromSecret(clientSecret)
- if err != nil {
- return nil, err
- }
- return newOnBehalfOfCredential(tenantID, clientID, userAssertion, cred, options)
-}
-
-func newOnBehalfOfCredential(tenantID, clientID, userAssertion string, cred confidential.Credential, options *OnBehalfOfCredentialOptions) (*OnBehalfOfCredential, error) {
- if options == nil {
- options = &OnBehalfOfCredentialOptions{}
- }
- opts := confidentialClientOptions{
- AdditionallyAllowedTenants: options.AdditionallyAllowedTenants,
- Assertion: userAssertion,
- ClientOptions: options.ClientOptions,
- DisableInstanceDiscovery: options.DisableInstanceDiscovery,
- SendX5C: options.SendCertificateChain,
- }
- c, err := newConfidentialClient(tenantID, clientID, credNameOBO, cred, opts)
- if err != nil {
- return nil, err
- }
- return &OnBehalfOfCredential{c}, nil
-}
-
-// GetToken requests an access token from Azure Active Directory. This method is called automatically by Azure SDK clients.
-func (o *OnBehalfOfCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
- return o.client.GetToken(ctx, opts)
-}
-
-var _ azcore.TokenCredential = (*OnBehalfOfCredential)(nil)
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/public_client.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/public_client.go
deleted file mode 100644
index 6512d3e25..000000000
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/public_client.go
+++ /dev/null
@@ -1,178 +0,0 @@
-//go:build go1.18
-// +build go1.18
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package azidentity
-
-import (
- "context"
- "fmt"
- "strings"
- "sync"
-
- "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/azure-sdk-for-go/sdk/internal/log"
- "github.com/AzureAD/microsoft-authentication-library-for-go/apps/public"
-)
-
-type publicClientOptions struct {
- azcore.ClientOptions
-
- AdditionallyAllowedTenants []string
- DeviceCodePrompt func(context.Context, DeviceCodeMessage) error
- DisableInstanceDiscovery bool
- LoginHint, RedirectURL string
- Username, Password string
-}
-
-// publicClient wraps the MSAL public client
-type publicClient struct {
- account public.Account
- cae, noCAE msalPublicClient
- caeMu, noCAEMu, clientMu *sync.Mutex
- clientID, tenantID string
- host string
- name string
- opts publicClientOptions
-}
-
-func newPublicClient(tenantID, clientID, name string, o publicClientOptions) (*publicClient, error) {
- if !validTenantID(tenantID) {
- return nil, errInvalidTenantID
- }
- host, err := setAuthorityHost(o.Cloud)
- if err != nil {
- return nil, err
- }
- o.AdditionallyAllowedTenants = resolveAdditionalTenants(o.AdditionallyAllowedTenants)
- return &publicClient{
- caeMu: &sync.Mutex{},
- clientID: clientID,
- clientMu: &sync.Mutex{},
- host: host,
- name: name,
- noCAEMu: &sync.Mutex{},
- opts: o,
- tenantID: tenantID,
- }, nil
-}
-
-// GetToken requests an access token from MSAL, checking the cache first.
-func (p *publicClient) GetToken(ctx context.Context, tro policy.TokenRequestOptions) (azcore.AccessToken, error) {
- if len(tro.Scopes) < 1 {
- return azcore.AccessToken{}, fmt.Errorf("%s.GetToken() requires at least one scope", p.name)
- }
- tenant, err := p.resolveTenant(tro.TenantID)
- if err != nil {
- return azcore.AccessToken{}, err
- }
- client, mu, err := p.client(tro)
- if err != nil {
- return azcore.AccessToken{}, err
- }
- mu.Lock()
- defer mu.Unlock()
- ar, err := client.AcquireTokenSilent(ctx, tro.Scopes, public.WithSilentAccount(p.account), public.WithClaims(tro.Claims), public.WithTenantID(tenant))
- if err == nil {
- return p.token(ar, err)
- }
- at, err := p.reqToken(ctx, client, tro)
- if err == nil {
- msg := fmt.Sprintf("%s.GetToken() acquired a token for scope %q", p.name, strings.Join(ar.GrantedScopes, ", "))
- log.Write(EventAuthentication, msg)
- }
- return at, err
-}
-
-// reqToken requests a token from the MSAL public client. It's separate from GetToken() to enable Authenticate() to bypass the cache.
-func (p *publicClient) reqToken(ctx context.Context, c msalPublicClient, tro policy.TokenRequestOptions) (azcore.AccessToken, error) {
- tenant, err := p.resolveTenant(tro.TenantID)
- if err != nil {
- return azcore.AccessToken{}, err
- }
- var ar public.AuthResult
- switch p.name {
- case credNameBrowser:
- ar, err = c.AcquireTokenInteractive(ctx, tro.Scopes,
- public.WithClaims(tro.Claims),
- public.WithLoginHint(p.opts.LoginHint),
- public.WithRedirectURI(p.opts.RedirectURL),
- public.WithTenantID(tenant),
- )
- case credNameDeviceCode:
- dc, e := c.AcquireTokenByDeviceCode(ctx, tro.Scopes, public.WithClaims(tro.Claims), public.WithTenantID(tenant))
- if e != nil {
- return azcore.AccessToken{}, e
- }
- err = p.opts.DeviceCodePrompt(ctx, DeviceCodeMessage{
- Message: dc.Result.Message,
- UserCode: dc.Result.UserCode,
- VerificationURL: dc.Result.VerificationURL,
- })
- if err == nil {
- ar, err = dc.AuthenticationResult(ctx)
- }
- case credNameUserPassword:
- ar, err = c.AcquireTokenByUsernamePassword(ctx, tro.Scopes, p.opts.Username, p.opts.Password, public.WithClaims(tro.Claims), public.WithTenantID(tenant))
- default:
- return azcore.AccessToken{}, fmt.Errorf("unknown credential %q", p.name)
- }
- return p.token(ar, err)
-}
-
-func (p *publicClient) client(tro policy.TokenRequestOptions) (msalPublicClient, *sync.Mutex, error) {
- p.clientMu.Lock()
- defer p.clientMu.Unlock()
- if tro.EnableCAE {
- if p.cae == nil {
- client, err := p.newMSALClient(true)
- if err != nil {
- return nil, nil, err
- }
- p.cae = client
- }
- return p.cae, p.caeMu, nil
- }
- if p.noCAE == nil {
- client, err := p.newMSALClient(false)
- if err != nil {
- return nil, nil, err
- }
- p.noCAE = client
- }
- return p.noCAE, p.noCAEMu, nil
-}
-
-func (p *publicClient) newMSALClient(enableCAE bool) (msalPublicClient, error) {
- o := []public.Option{
- public.WithAuthority(runtime.JoinPaths(p.host, p.tenantID)),
- public.WithHTTPClient(newPipelineAdapter(&p.opts.ClientOptions)),
- }
- if enableCAE {
- o = append(o, public.WithClientCapabilities(cp1))
- }
- if p.opts.DisableInstanceDiscovery || strings.ToLower(p.tenantID) == "adfs" {
- o = append(o, public.WithInstanceDiscovery(false))
- }
- return public.New(p.clientID, o...)
-}
-
-func (p *publicClient) token(ar public.AuthResult, err error) (azcore.AccessToken, error) {
- if err == nil {
- p.account = ar.Account
- } else {
- res := getResponseFromError(err)
- err = newAuthenticationFailedError(p.name, err.Error(), res, err)
- }
- return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
-}
-
-// resolveTenant returns the correct tenant for a token request given the client's
-// configuration, or an error when that configuration doesn't allow the specified tenant
-func (p *publicClient) resolveTenant(specified string) (string, error) {
- return resolveTenant(p.tenantID, specified, p.name, p.opts.AdditionallyAllowedTenants)
-}
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/test-resources-pre.ps1 b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/test-resources-pre.ps1
deleted file mode 100644
index fe0183add..000000000
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/test-resources-pre.ps1
+++ /dev/null
@@ -1,36 +0,0 @@
-[CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')]
-param (
- # Captures any arguments from eng/New-TestResources.ps1 not declared here (no parameter errors).
- [Parameter(ValueFromRemainingArguments = $true)]
- $RemainingArguments
-)
-
-if (!$CI) {
- # TODO: Remove this once auto-cloud config downloads are supported locally
- Write-Host "Skipping cert setup in local testing mode"
- return
-}
-
-if ($EnvironmentVariables -eq $null -or $EnvironmentVariables.Count -eq 0) {
- throw "EnvironmentVariables must be set in the calling script New-TestResources.ps1"
-}
-
-$tmp = $env:TEMP ? $env:TEMP : [System.IO.Path]::GetTempPath()
-$pfxPath = Join-Path $tmp "test.pfx"
-$pemPath = Join-Path $tmp "test.pem"
-$sniPath = Join-Path $tmp "testsni.pfx"
-
-Write-Host "Creating identity test files: $pfxPath $pemPath $sniPath"
-
-[System.Convert]::FromBase64String($EnvironmentVariables['PFX_CONTENTS']) | Set-Content -Path $pfxPath -AsByteStream
-Set-Content -Path $pemPath -Value $EnvironmentVariables['PEM_CONTENTS']
-[System.Convert]::FromBase64String($EnvironmentVariables['SNI_CONTENTS']) | Set-Content -Path $sniPath -AsByteStream
-
-# Set for pipeline
-Write-Host "##vso[task.setvariable variable=IDENTITY_SP_CERT_PFX;]$pfxPath"
-Write-Host "##vso[task.setvariable variable=IDENTITY_SP_CERT_PEM;]$pemPath"
-Write-Host "##vso[task.setvariable variable=IDENTITY_SP_CERT_SNI;]$sniPath"
-# Set for local
-$env:IDENTITY_SP_CERT_PFX = $pfxPath
-$env:IDENTITY_SP_CERT_PEM = $pemPath
-$env:IDENTITY_SP_CERT_SNI = $sniPath
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/test-resources.bicep b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/test-resources.bicep
deleted file mode 100644
index b3490d3b5..000000000
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/test-resources.bicep
+++ /dev/null
@@ -1 +0,0 @@
-param baseName string
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/username_password_credential.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/username_password_credential.go
index f787ec0ce..8b02e7b47 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/username_password_credential.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/username_password_credential.go
@@ -8,9 +8,12 @@ package azidentity
import (
"context"
+ "errors"
"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/AzureAD/microsoft-authentication-library-for-go/apps/public"
)
const credNameUserPassword = "UsernamePasswordCredential"
@@ -18,16 +21,6 @@ const credNameUserPassword = "UsernamePasswordCredential"
// UsernamePasswordCredentialOptions contains optional parameters for UsernamePasswordCredential.
type UsernamePasswordCredentialOptions struct {
azcore.ClientOptions
-
- // AdditionallyAllowedTenants specifies additional tenants for which the credential may acquire tokens.
- // Add the wildcard value "*" to allow the credential to acquire tokens for any tenant in which the
- // application is registered.
- AdditionallyAllowedTenants []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 Azure AD 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
}
// UsernamePasswordCredential authenticates a user with a password. Microsoft doesn't recommend this kind of authentication,
@@ -35,32 +28,52 @@ type UsernamePasswordCredentialOptions struct {
// with any form of multi-factor authentication, and the application must already have user or admin consent.
// This credential can only authenticate work and school accounts; it can't authenticate Microsoft accounts.
type UsernamePasswordCredential struct {
- client *publicClient
+ client publicClient
+ username string
+ password string
+ account public.Account
}
// NewUsernamePasswordCredential creates a UsernamePasswordCredential. clientID is the ID of the application the user
// will authenticate to. Pass nil for options to accept defaults.
func NewUsernamePasswordCredential(tenantID string, clientID string, username string, password string, options *UsernamePasswordCredentialOptions) (*UsernamePasswordCredential, error) {
+ if !validTenantID(tenantID) {
+ return nil, errors.New(tenantIDValidationErr)
+ }
if options == nil {
options = &UsernamePasswordCredentialOptions{}
}
- opts := publicClientOptions{
- AdditionallyAllowedTenants: options.AdditionallyAllowedTenants,
- ClientOptions: options.ClientOptions,
- DisableInstanceDiscovery: options.DisableInstanceDiscovery,
- Password: password,
- Username: username,
+ authorityHost, err := setAuthorityHost(options.Cloud)
+ if err != nil {
+ return nil, err
}
- c, err := newPublicClient(tenantID, clientID, credNameUserPassword, opts)
+ c, err := public.New(clientID,
+ public.WithAuthority(runtime.JoinPaths(authorityHost, tenantID)),
+ public.WithHTTPClient(newPipelineAdapter(&options.ClientOptions)),
+ )
if err != nil {
return nil, err
}
- return &UsernamePasswordCredential{client: c}, err
+ return &UsernamePasswordCredential{username: username, password: password, client: c}, nil
}
// GetToken requests an access token from Azure Active Directory. This method is called automatically by Azure SDK clients.
func (c *UsernamePasswordCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
- return c.client.GetToken(ctx, opts)
+ if len(opts.Scopes) == 0 {
+ return azcore.AccessToken{}, errors.New(credNameUserPassword + ": GetToken() requires at least one scope")
+ }
+ ar, err := c.client.AcquireTokenSilent(ctx, opts.Scopes, public.WithSilentAccount(c.account))
+ if err == nil {
+ logGetTokenSuccess(c, opts)
+ return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
+ }
+ ar, err = c.client.AcquireTokenByUsernamePassword(ctx, opts.Scopes, c.username, c.password)
+ if err != nil {
+ return azcore.AccessToken{}, newAuthenticationFailedErrorFromMSALError(credNameUserPassword, err)
+ }
+ c.account = ar.Account
+ logGetTokenSuccess(c, opts)
+ return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
}
var _ azcore.TokenCredential = (*UsernamePasswordCredential)(nil)
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/version.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/version.go
index 65e74e31e..0fb125ace 100644
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/version.go
+++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/version.go
@@ -11,5 +11,5 @@ const (
component = "azidentity"
// Version is the semantic version (see http://semver.org) of this module.
- version = "v1.4.0"
+ version = "v1.1.0"
)
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/workload_identity.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/workload_identity.go
deleted file mode 100644
index 7e016324d..000000000
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/workload_identity.go
+++ /dev/null
@@ -1,126 +0,0 @@
-//go:build go1.18
-// +build go1.18
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package azidentity
-
-import (
- "context"
- "errors"
- "os"
- "sync"
- "time"
-
- "github.com/Azure/azure-sdk-for-go/sdk/azcore"
- "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
-)
-
-const credNameWorkloadIdentity = "WorkloadIdentityCredential"
-
-// WorkloadIdentityCredential supports Azure workload identity on Kubernetes.
-// See [Azure Kubernetes Service documentation] for more information.
-//
-// [Azure Kubernetes Service documentation]: https://learn.microsoft.com/azure/aks/workload-identity-overview
-type WorkloadIdentityCredential struct {
- assertion, file string
- cred *ClientAssertionCredential
- expires time.Time
- mtx *sync.RWMutex
-}
-
-// WorkloadIdentityCredentialOptions contains optional parameters for WorkloadIdentityCredential.
-type WorkloadIdentityCredentialOptions struct {
- azcore.ClientOptions
-
- // AdditionallyAllowedTenants specifies additional tenants for which the credential may acquire tokens.
- // Add the wildcard value "*" to allow the credential to acquire tokens for any tenant in which the
- // application is registered.
- AdditionallyAllowedTenants []string
- // 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 Azure AD 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
-}
-
-// NewWorkloadIdentityCredential constructs a WorkloadIdentityCredential. Service principal configuration is read
-// from environment variables as set by the Azure workload identity webhook. Set options to override those values.
-func NewWorkloadIdentityCredential(options *WorkloadIdentityCredentialOptions) (*WorkloadIdentityCredential, error) {
- if options == nil {
- options = &WorkloadIdentityCredentialOptions{}
- }
- ok := false
- clientID := options.ClientID
- if clientID == "" {
- if clientID, ok = os.LookupEnv(azureClientID); !ok {
- return nil, errors.New("no client ID specified. Check pod configuration or set ClientID in the options")
- }
- }
- file := options.TokenFilePath
- if file == "" {
- if file, ok = os.LookupEnv(azureFederatedTokenFile); !ok {
- return nil, errors.New("no token file specified. Check pod configuration or set TokenFilePath in the options")
- }
- }
- tenantID := options.TenantID
- if tenantID == "" {
- if tenantID, ok = os.LookupEnv(azureTenantID); !ok {
- return nil, errors.New("no tenant ID specified. Check pod configuration or set TenantID in the options")
- }
- }
- w := WorkloadIdentityCredential{file: file, mtx: &sync.RWMutex{}}
- caco := ClientAssertionCredentialOptions{
- AdditionallyAllowedTenants: options.AdditionallyAllowedTenants,
- ClientOptions: options.ClientOptions,
- DisableInstanceDiscovery: options.DisableInstanceDiscovery,
- }
- cred, err := NewClientAssertionCredential(tenantID, clientID, w.getAssertion, &caco)
- if err != nil {
- return nil, err
- }
- // we want "WorkloadIdentityCredential" in log messages, not "ClientAssertionCredential"
- cred.client.name = credNameWorkloadIdentity
- w.cred = cred
- return &w, nil
-}
-
-// GetToken requests an access token from Azure Active Directory. Azure SDK clients call this method automatically.
-func (w *WorkloadIdentityCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
- return w.cred.GetToken(ctx, opts)
-}
-
-// getAssertion returns the specified file's content, which is expected to be a Kubernetes service account token.
-// Kubernetes is responsible for updating the file as service account tokens expire.
-func (w *WorkloadIdentityCredential) getAssertion(context.Context) (string, error) {
- w.mtx.RLock()
- if w.expires.Before(time.Now()) {
- // ensure only one goroutine at a time updates the assertion
- w.mtx.RUnlock()
- w.mtx.Lock()
- defer w.mtx.Unlock()
- // double check because another goroutine may have acquired the write lock first and done the update
- if now := time.Now(); w.expires.Before(now) {
- content, err := os.ReadFile(w.file)
- if err != nil {
- return "", err
- }
- w.assertion = string(content)
- // Kubernetes rotates service account tokens when they reach 80% of their total TTL. The shortest TTL
- // is 1 hour. That implies the token we just read is valid for at least 12 minutes (20% of 1 hour),
- // but we add some margin for safety.
- w.expires = now.Add(10 * time.Minute)
- }
- } else {
- defer w.mtx.RUnlock()
- }
- return w.assertion, nil
-}
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/exported/exported.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/exported/exported.go
deleted file mode 100644
index d4ed6ccc8..000000000
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/exported/exported.go
+++ /dev/null
@@ -1,124 +0,0 @@
-//go:build go1.18
-// +build go1.18
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package exported
-
-import (
- "errors"
- "io"
- "net/http"
-)
-
-// HasStatusCode returns true if the Response's status code is one of the specified values.
-// Exported as runtime.HasStatusCode().
-func HasStatusCode(resp *http.Response, statusCodes ...int) bool {
- if resp == nil {
- return false
- }
- for _, sc := range statusCodes {
- if resp.StatusCode == sc {
- return true
- }
- }
- return false
-}
-
-// PayloadOptions contains the optional values for the Payload func.
-// NOT exported but used by azcore.
-type PayloadOptions struct {
- // BytesModifier receives the downloaded byte slice and returns an updated byte slice.
- // Use this to modify the downloaded bytes in a payload (e.g. removing a BOM).
- BytesModifier func([]byte) []byte
-}
-
-// Payload reads and returns the response body or an error.
-// On a successful read, the response body is cached.
-// Subsequent reads will access the cached value.
-// Exported as runtime.Payload() WITHOUT the opts parameter.
-func Payload(resp *http.Response, opts *PayloadOptions) ([]byte, error) {
- modifyBytes := func(b []byte) []byte { return b }
- if opts != nil && opts.BytesModifier != nil {
- modifyBytes = opts.BytesModifier
- }
-
- // r.Body won't be a nopClosingBytesReader if downloading was skipped
- if buf, ok := resp.Body.(*nopClosingBytesReader); ok {
- bytesBody := modifyBytes(buf.Bytes())
- buf.Set(bytesBody)
- return bytesBody, nil
- }
-
- bytesBody, err := io.ReadAll(resp.Body)
- resp.Body.Close()
- if err != nil {
- return nil, err
- }
-
- bytesBody = modifyBytes(bytesBody)
- resp.Body = &nopClosingBytesReader{s: bytesBody}
- return bytesBody, nil
-}
-
-// PayloadDownloaded returns true if the response body has already been downloaded.
-// This implies that the Payload() func above has been previously called.
-// NOT exported but used by azcore.
-func PayloadDownloaded(resp *http.Response) bool {
- _, ok := resp.Body.(*nopClosingBytesReader)
- return ok
-}
-
-// nopClosingBytesReader is an io.ReadSeekCloser around a byte slice.
-// It also provides direct access to the byte slice to avoid rereading.
-type nopClosingBytesReader struct {
- s []byte
- i int64
-}
-
-// Bytes returns the underlying byte slice.
-func (r *nopClosingBytesReader) Bytes() []byte {
- return r.s
-}
-
-// Close implements the io.Closer interface.
-func (*nopClosingBytesReader) Close() error {
- return nil
-}
-
-// Read implements the io.Reader interface.
-func (r *nopClosingBytesReader) Read(b []byte) (n int, err error) {
- if r.i >= int64(len(r.s)) {
- return 0, io.EOF
- }
- n = copy(b, r.s[r.i:])
- r.i += int64(n)
- return
-}
-
-// Set replaces the existing byte slice with the specified byte slice and resets the reader.
-func (r *nopClosingBytesReader) Set(b []byte) {
- r.s = b
- r.i = 0
-}
-
-// Seek implements the io.Seeker interface.
-func (r *nopClosingBytesReader) Seek(offset int64, whence int) (int64, error) {
- var i int64
- switch whence {
- case io.SeekStart:
- i = offset
- case io.SeekCurrent:
- i = r.i + offset
- case io.SeekEnd:
- i = int64(len(r.s)) + offset
- default:
- return 0, errors.New("nopClosingBytesReader: invalid whence")
- }
- if i < 0 {
- return 0, errors.New("nopClosingBytesReader: negative position")
- }
- r.i = i
- return i, nil
-}
diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/poller/util.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/poller/util.go
deleted file mode 100644
index db8269627..000000000
--- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/poller/util.go
+++ /dev/null
@@ -1,155 +0,0 @@
-//go:build go1.18
-// +build go1.18
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package poller
-
-import (
- "encoding/json"
- "errors"
- "fmt"
- "net/http"
- "net/url"
- "strings"
-
- "github.com/Azure/azure-sdk-for-go/sdk/internal/exported"
-)
-
-// the well-known set of LRO status/provisioning state values.
-const (
- StatusSucceeded = "Succeeded"
- StatusCanceled = "Canceled"
- StatusFailed = "Failed"
- StatusInProgress = "InProgress"
-)
-
-// these are non-conformant states that we've seen in the wild.
-// we support them for back-compat.
-const (
- StatusCancelled = "Cancelled"
- StatusCompleted = "Completed"
-)
-
-// IsTerminalState returns true if the LRO's state is terminal.
-func IsTerminalState(s string) bool {
- return Failed(s) || Succeeded(s)
-}
-
-// Failed returns true if the LRO's state is terminal failure.
-func Failed(s string) bool {
- return strings.EqualFold(s, StatusFailed) || strings.EqualFold(s, StatusCanceled) || strings.EqualFold(s, StatusCancelled)
-}
-
-// Succeeded returns true if the LRO's state is terminal success.
-func Succeeded(s string) bool {
- return strings.EqualFold(s, StatusSucceeded) || strings.EqualFold(s, StatusCompleted)
-}
-
-// returns true if the LRO response contains a valid HTTP status code
-func StatusCodeValid(resp *http.Response) bool {
- return exported.HasStatusCode(resp, http.StatusOK, http.StatusAccepted, http.StatusCreated, http.StatusNoContent)
-}
-
-// IsValidURL verifies that the URL is valid and absolute.
-func IsValidURL(s string) bool {
- u, err := url.Parse(s)
- return err == nil && u.IsAbs()
-}
-
-// ErrNoBody is returned if the response didn't contain a body.
-var ErrNoBody = errors.New("the response did not contain a body")
-
-// GetJSON reads the response body into a raw JSON object.
-// It returns ErrNoBody if there was no content.
-func GetJSON(resp *http.Response) (map[string]any, error) {
- body, err := exported.Payload(resp, nil)
- if err != nil {
- return nil, err
- }
- if len(body) == 0 {
- return nil, ErrNoBody
- }
- // unmarshall the body to get the value
- var jsonBody map[string]any
- if err = json.Unmarshal(body, &jsonBody); err != nil {
- return nil, err
- }
- return jsonBody, nil
-}
-
-// provisioningState returns the provisioning state from the response or the empty string.
-func provisioningState(jsonBody map[string]any) string {
- jsonProps, ok := jsonBody["properties"]
- if !ok {
- return ""
- }
- props, ok := jsonProps.(map[string]any)
- if !ok {
- return ""
- }
- rawPs, ok := props["provisioningState"]
- if !ok {
- return ""
- }
- ps, ok := rawPs.(string)
- if !ok {
- return ""
- }
- return ps
-}
-
-// status returns the status from the response or the empty string.
-func status(jsonBody map[string]any) string {
- rawStatus, ok := jsonBody["status"]
- if !ok {
- return ""
- }
- status, ok := rawStatus.(string)
- if !ok {
- return ""
- }
- return status
-}
-
-// GetStatus returns the LRO's status from the response body.
-// Typically used for Azure-AsyncOperation flows.
-// If there is no status in the response body the empty string is returned.
-func GetStatus(resp *http.Response) (string, error) {
- jsonBody, err := GetJSON(resp)
- if err != nil {
- return "", err
- }
- return status(jsonBody), nil
-}
-
-// GetProvisioningState returns the LRO's state from the response body.
-// If there is no state in the response body the empty string is returned.
-func GetProvisioningState(resp *http.Response) (string, error) {
- jsonBody, err := GetJSON(resp)
- if err != nil {
- return "", err
- }
- return provisioningState(jsonBody), nil
-}
-
-// GetResourceLocation returns the LRO's resourceLocation value from the response body.
-// Typically used for Operation-Location flows.
-// If there is no resourceLocation in the response body the empty string is returned.
-func GetResourceLocation(resp *http.Response) (string, error) {
- jsonBody, err := GetJSON(resp)
- if err != nil {
- return "", err
- }
- v, ok := jsonBody["resourceLocation"]
- if !ok {
- // it might be ok if the field doesn't exist, the caller must make that determination
- return "", nil
- }
- vv, ok := v.(string)
- if !ok {
- return "", fmt.Errorf("the resourceLocation value %v was not in string format", v)
- }
- return vv, nil
-}
diff --git a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/cache/cache.go b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/cache/cache.go
index 19210883b..259ca6d56 100644
--- a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/cache/cache.go
+++ b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/cache/cache.go
@@ -11,8 +11,6 @@ implementers on the format being passed.
*/
package cache
-import "context"
-
// Marshaler marshals data from an internal cache to bytes that can be stored.
type Marshaler interface {
Marshal() ([]byte, error)
@@ -29,26 +27,13 @@ type Serializer interface {
Unmarshaler
}
-// ExportHints are suggestions for storing data.
-type ExportHints struct {
- // PartitionKey is a suggested key for partitioning the cache
- PartitionKey string
-}
-
-// ReplaceHints are suggestions for loading data.
-type ReplaceHints struct {
- // PartitionKey is a suggested key for partitioning the cache
- PartitionKey string
-}
-
-// ExportReplace exports and replaces in-memory cache data. It doesn't support nil Context or
-// define the outcome of passing one. A Context without a timeout must receive a default timeout
-// specified by the implementor. Retries must be implemented inside the implementation.
+// ExportReplace is used export or replace what is in the cache.
type ExportReplace interface {
- // Replace replaces the cache with what is in external storage. Implementors should honor
- // Context cancellations and return context.Canceled or context.DeadlineExceeded in those cases.
- Replace(ctx context.Context, cache Unmarshaler, hints ReplaceHints) error
- // Export writes the binary representation of the cache (cache.Marshal()) to external storage.
- // This is considered opaque. Context cancellations should be honored as in Replace.
- Export(ctx context.Context, cache Marshaler, hints ExportHints) error
+ // Replace replaces the cache with what is in external storage.
+ // key is the suggested key which can be used for partioning the cache
+ Replace(cache Unmarshaler, key string)
+ // Export writes the binary representation of the cache (cache.Marshal()) to
+ // external storage. This is considered opaque.
+ // key is the suggested key which can be used for partioning the cache
+ Export(cache Marshaler, key string)
}
diff --git a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/confidential/confidential.go b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/confidential/confidential.go
index 6612feb4b..1c2c6ae24 100644
--- a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/confidential/confidential.go
+++ b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/confidential/confidential.go
@@ -12,21 +12,18 @@ package confidential
import (
"context"
"crypto"
- "crypto/rsa"
"crypto/x509"
- "encoding/base64"
"encoding/pem"
"errors"
"fmt"
+ "net/url"
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/cache"
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/base"
- "github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/exported"
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth"
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops"
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/accesstokens"
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/authority"
- "github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/options"
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/shared"
)
@@ -49,7 +46,8 @@ duplication.
.Net People, Take note on X509:
This uses x509.Certificates and private keys. x509 does not store private keys. .Net
has some x509.Certificate2 thing that has private keys, but that is just some bullcrap that .Net
-added, it doesn't exist in real life. As such I've put a PEM decoder into here.
+added, it doesn't exist in real life. Seriously, "x509.Certificate2", bahahahaha. As such I've
+put a PEM decoder into here.
*/
// TODO(msal): This should have example code for each method on client using Go's example doc framework.
@@ -61,10 +59,13 @@ type AuthResult = base.AuthResult
type Account = shared.Account
-// CertFromPEM converts a PEM file (.pem or .key) for use with [NewCredFromCert]. The file
-// must contain the public certificate and the private key. If a PEM block is encrypted and
-// password is not an empty string, it attempts to decrypt the PEM blocks using the password.
-// Multiple certs are due to certificate chaining for use cases like TLS that sign from root to leaf.
+// CertFromPEM converts a PEM file (.pem or .key) for use with NewCredFromCert(). The file
+// must have the public certificate and the private key encoded. The private key must be encoded
+// in PKCS8 (not PKCS1). This is usually denoted by the section "PRIVATE KEY" (instead of PKCS1's
+// "RSA PRIVATE KEY"). If a PEM block is encoded and password is not an empty string, it attempts
+// to decrypt the PEM blocks using the password. This will return multiple x509 certificates,
+// though this use case should have a single cert. Multiple certs are due to certificate
+// chaining for use cases like TLS that sign from root to leaf.
func CertFromPEM(pemData []byte, password string) ([]*x509.Certificate, crypto.PrivateKey, error) {
var certs []*x509.Certificate
var priv crypto.PrivateKey
@@ -78,7 +79,7 @@ func CertFromPEM(pemData []byte, password string) ([]*x509.Certificate, crypto.P
if x509.IsEncryptedPEMBlock(block) {
b, err := x509.DecryptPEMBlock(block, []byte(password))
if err != nil {
- return nil, nil, fmt.Errorf("could not decrypt encrypted PEM block: %v", err)
+ return nil, nil, fmt.Errorf("could not decrypt encrypted PEM block: %w", err)
}
block, _ = pem.Decode(b)
if block == nil {
@@ -90,27 +91,18 @@ func CertFromPEM(pemData []byte, password string) ([]*x509.Certificate, crypto.P
case "CERTIFICATE":
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
- return nil, nil, fmt.Errorf("block labelled 'CERTIFICATE' could not be parsed by x509: %v", err)
+ return nil, nil, fmt.Errorf("block labelled 'CERTIFICATE' could not be pared by x509: %w", err)
}
certs = append(certs, cert)
case "PRIVATE KEY":
if priv != nil {
- return nil, nil, errors.New("found multiple private key blocks")
+ return nil, nil, fmt.Errorf("found multiple blocks labelled 'PRIVATE KEY'")
}
var err error
- priv, err = x509.ParsePKCS8PrivateKey(block.Bytes)
+ priv, err = parsePrivateKey(block.Bytes)
if err != nil {
- return nil, nil, fmt.Errorf("could not decode private key: %v", err)
- }
- case "RSA PRIVATE KEY":
- if priv != nil {
- return nil, nil, errors.New("found multiple private key blocks")
- }
- var err error
- priv, err = x509.ParsePKCS1PrivateKey(block.Bytes)
- if err != nil {
- return nil, nil, fmt.Errorf("could not decode private key: %v", err)
+ return nil, nil, fmt.Errorf("could not decode private key: %w", err)
}
}
pemData = rest
@@ -127,8 +119,15 @@ func CertFromPEM(pemData []byte, password string) ([]*x509.Certificate, crypto.P
return certs, priv, nil
}
-// AssertionRequestOptions has required information for client assertion claims
-type AssertionRequestOptions = exported.AssertionRequestOptions
+// parsePrivateKey is based on https://gist.github.com/ukautz/cd118e298bbd8f0a88fc . I don't *think*
+// we need to do the extra decoding in the example, but *maybe*?
+func parsePrivateKey(der []byte) (crypto.PrivateKey, error) {
+ key, err := x509.ParsePKCS8PrivateKey(der)
+ if err != nil {
+ return nil, fmt.Errorf("problems decoding private key using PKCS8: %w", err)
+ }
+ return key, nil
+}
// Credential represents the credential used in confidential client flows.
type Credential struct {
@@ -136,37 +135,16 @@ type Credential struct {
cert *x509.Certificate
key crypto.PrivateKey
- x5c []string
-
- assertionCallback func(context.Context, AssertionRequestOptions) (string, error)
- tokenProvider func(context.Context, TokenProviderParameters) (TokenProviderResult, error)
+ assertion string
}
// toInternal returns the accesstokens.Credential that is used internally. The current structure of the
// code requires that client.go, requests.go and confidential.go share a credential type without
// having import recursion. That requires the type used between is in a shared package. Therefore
// we have this.
-func (c Credential) toInternal() (*accesstokens.Credential, error) {
- if c.secret != "" {
- return &accesstokens.Credential{Secret: c.secret}, nil
- }
- if c.cert != nil {
- if c.key == nil {
- return nil, errors.New("missing private key for certificate")
- }
- return &accesstokens.Credential{Cert: c.cert, Key: c.key, X5c: c.x5c}, nil
- }
- if c.key != nil {
- return nil, errors.New("missing certificate for private key")
- }
- if c.assertionCallback != nil {
- return &accesstokens.Credential{AssertionCallback: c.assertionCallback}, nil
- }
- if c.tokenProvider != nil {
- return &accesstokens.Credential{TokenProvider: c.tokenProvider}, nil
- }
- return nil, errors.New("invalid credential")
+func (c Credential) toInternal() *accesstokens.Credential {
+ return &accesstokens.Credential{Secret: c.secret, Cert: c.cert, Key: c.key, Assertion: c.assertion}
}
// NewCredFromSecret creates a Credential from a secret.
@@ -177,52 +155,18 @@ func NewCredFromSecret(secret string) (Credential, error) {
return Credential{secret: secret}, nil
}
-// NewCredFromAssertionCallback creates a Credential that invokes a callback to get assertions
-// authenticating the application. The callback must be thread safe.
-func NewCredFromAssertionCallback(callback func(context.Context, AssertionRequestOptions) (string, error)) Credential {
- return Credential{assertionCallback: callback}
-}
-
-// NewCredFromCert creates a Credential from a certificate or chain of certificates and an RSA private key
-// as returned by [CertFromPEM].
-func NewCredFromCert(certs []*x509.Certificate, key crypto.PrivateKey) (Credential, error) {
- cred := Credential{key: key}
- k, ok := key.(*rsa.PrivateKey)
- if !ok {
- return cred, errors.New("key must be an RSA key")
- }
- for _, cert := range certs {
- if cert == nil {
- // not returning an error here because certs may still contain a sufficient cert/key pair
- continue
- }
- certKey, ok := cert.PublicKey.(*rsa.PublicKey)
- if ok && k.E == certKey.E && k.N.Cmp(certKey.N) == 0 {
- // We know this is the signing cert because its public key matches the given private key.
- // This cert must be first in x5c.
- cred.cert = cert
- cred.x5c = append([]string{base64.StdEncoding.EncodeToString(cert.Raw)}, cred.x5c...)
- } else {
- cred.x5c = append(cred.x5c, base64.StdEncoding.EncodeToString(cert.Raw))
- }
- }
- if cred.cert == nil {
- return cred, errors.New("key doesn't match any certificate")
+// NewCredFromAssertion creates a Credential from a signed assertion.
+func NewCredFromAssertion(assertion string) (Credential, error) {
+ if assertion == "" {
+ return Credential{}, errors.New("assertion can't be empty string")
}
- return cred, nil
+ return Credential{assertion: assertion}, nil
}
-// TokenProviderParameters is the authentication parameters passed to token providers
-type TokenProviderParameters = exported.TokenProviderParameters
-
-// TokenProviderResult is the authentication result returned by custom token providers
-type TokenProviderResult = exported.TokenProviderResult
-
-// NewCredFromTokenProvider creates a Credential from a function that provides access tokens. The function
-// must be concurrency safe. This is intended only to allow the Azure SDK to cache MSI tokens. It isn't
-// useful to applications in general because the token provider must implement all authentication logic.
-func NewCredFromTokenProvider(provider func(context.Context, TokenProviderParameters) (TokenProviderResult, error)) Credential {
- return Credential{tokenProvider: provider}
+// NewCredFromCert creates a Credential from an x509.Certificate and a PKCS8 DER encoded private key.
+// CertFromPEM() can be used to get these values from a PEM file storing a PKCS8 private key.
+func NewCredFromCert(cert *x509.Certificate, key crypto.PrivateKey) Credential {
+ return Credential{cert: cert, key: key}
}
// AutoDetectRegion instructs MSAL Go to auto detect region for Azure regional token service.
@@ -235,56 +179,77 @@ func AutoDetectRegion() string {
// For more information, visit https://docs.microsoft.com/azure/active-directory/develop/msal-client-applications
type Client struct {
base base.Client
+
cred *accesstokens.Credential
+
+ // userID is some unique identifier for a user. It actually isn't used by us at all, it
+ // simply acts as another hint that a confidential.Client is for a single user.
+ userID string
}
-// clientOptions are optional settings for New(). These options are set using various functions
+// Options are optional settings for New(). These options are set using various functions
// returning Option calls.
-type clientOptions struct {
- accessor cache.ExportReplace
- authority, azureRegion string
- capabilities []string
- disableInstanceDiscovery, sendX5C bool
- httpClient ops.HTTPClient
+type Options struct {
+ // Accessor controls cache persistence.
+ // By default there is no cache persistence. This can be set using the WithAccessor() option.
+ Accessor cache.ExportReplace
+
+ // The host of the Azure Active Directory authority.
+ // The default is https://login.microsoftonline.com/common. This can be changed using the
+ // WithAuthority() option.
+ Authority string
+
+ // The HTTP client used for making requests.
+ // It defaults to a shared http.Client.
+ HTTPClient ops.HTTPClient
+
+ // SendX5C specifies if x5c claim(public key of the certificate) should be sent to STS.
+ SendX5C bool
+
+ // Instructs MSAL Go to use an Azure regional token service with sepcified AzureRegion.
+ AzureRegion string
+}
+
+func (o Options) validate() error {
+ u, err := url.Parse(o.Authority)
+ if err != nil {
+ return fmt.Errorf("the Authority(%s) does not parse as a valid URL", o.Authority)
+ }
+ if u.Scheme != "https" {
+ return fmt.Errorf("the Authority(%s) does not appear to use https", o.Authority)
+ }
+ return nil
}
// Option is an optional argument to New().
-type Option func(o *clientOptions)
+type Option func(o *Options)
-// WithCache provides an accessor that will read and write authentication data to an externally managed cache.
-func WithCache(accessor cache.ExportReplace) Option {
- return func(o *clientOptions) {
- o.accessor = accessor
+// WithAuthority allows you to provide a custom authority for use in the client.
+func WithAuthority(authority string) Option {
+ return func(o *Options) {
+ o.Authority = authority
}
}
-// WithClientCapabilities allows configuring one or more client capabilities such as "CP1"
-func WithClientCapabilities(capabilities []string) Option {
- return func(o *clientOptions) {
- // there's no danger of sharing the slice's underlying memory with the application because
- // this slice is simply passed to base.WithClientCapabilities, which copies its data
- o.capabilities = capabilities
+// WithAccessor provides a cache accessor that will read and write to some externally managed cache
+// that may or may not be shared with other applications.
+func WithAccessor(accessor cache.ExportReplace) Option {
+ return func(o *Options) {
+ o.Accessor = accessor
}
}
// WithHTTPClient allows for a custom HTTP client to be set.
func WithHTTPClient(httpClient ops.HTTPClient) Option {
- return func(o *clientOptions) {
- o.httpClient = httpClient
+ return func(o *Options) {
+ o.HTTPClient = httpClient
}
}
// WithX5C specifies if x5c claim(public key of the certificate) should be sent to STS to enable Subject Name Issuer Authentication.
func WithX5C() Option {
- return func(o *clientOptions) {
- o.sendX5C = true
- }
-}
-
-// WithInstanceDiscovery set to false to disable authority validation (to support private cloud scenarios)
-func WithInstanceDiscovery(enabled bool) Option {
- return func(o *clientOptions) {
- o.disableInstanceDiscovery = !enabled
+ return func(o *Options) {
+ o.SendX5C = true
}
}
@@ -300,343 +265,127 @@ func WithInstanceDiscovery(enabled bool) Option {
// If auto-detection fails, the non-regional endpoint will be used.
// If an invalid region name is provided, the non-regional endpoint MIGHT be used or the token request MIGHT fail.
func WithAzureRegion(val string) Option {
- return func(o *clientOptions) {
- o.azureRegion = val
+ return func(o *Options) {
+ o.AzureRegion = val
}
}
-// New is the constructor for Client. authority is the URL of a token authority such as "https://login.microsoftonline.com/".
-// If the Client will connect directly to AD FS, use "adfs" for the tenant. clientID is the application's client ID (also called its
-// "application ID").
-func New(authority, clientID string, cred Credential, options ...Option) (Client, error) {
- internalCred, err := cred.toInternal()
- if err != nil {
- return Client{}, err
+// New is the constructor for Client. userID is the unique identifier of the user this client
+// will store credentials for (a Client is per user). clientID is the Azure clientID and cred is
+// the type of credential to use.
+func New(clientID string, cred Credential, options ...Option) (Client, error) {
+ opts := Options{
+ Authority: base.AuthorityPublicCloud,
+ HTTPClient: shared.DefaultClient,
}
- opts := clientOptions{
- authority: authority,
- // if the caller specified a token provider, it will handle all details of authentication, using Client only as a token cache
- disableInstanceDiscovery: cred.tokenProvider != nil,
- httpClient: shared.DefaultClient,
- }
for _, o := range options {
o(&opts)
}
- baseOpts := []base.Option{
- base.WithCacheAccessor(opts.accessor),
- base.WithClientCapabilities(opts.capabilities),
- base.WithInstanceDiscovery(!opts.disableInstanceDiscovery),
- base.WithRegionDetection(opts.azureRegion),
- base.WithX5C(opts.sendX5C),
- }
- base, err := base.New(clientID, opts.authority, oauth.New(opts.httpClient), baseOpts...)
- if err != nil {
+ if err := opts.validate(); err != nil {
return Client{}, err
}
- base.AuthParams.IsConfidentialClient = true
- return Client{base: base, cred: internalCred}, nil
-}
-
-// authCodeURLOptions contains options for AuthCodeURL
-type authCodeURLOptions struct {
- claims, loginHint, tenantID, domainHint string
-}
-
-// AuthCodeURLOption is implemented by options for AuthCodeURL
-type AuthCodeURLOption interface {
- authCodeURLOption()
-}
-
-// AuthCodeURL creates a URL used to acquire an authorization code. Users need to call CreateAuthorizationCodeURLParameters and pass it in.
-//
-// Options: [WithClaims], [WithDomainHint], [WithLoginHint], [WithTenantID]
-func (cca Client) AuthCodeURL(ctx context.Context, clientID, redirectURI string, scopes []string, opts ...AuthCodeURLOption) (string, error) {
- o := authCodeURLOptions{}
- if err := options.ApplyOptions(&o, opts); err != nil {
- return "", err
- }
- ap, err := cca.base.AuthParams.WithTenant(o.tenantID)
+ base, err := base.New(clientID, opts.Authority, oauth.New(opts.HTTPClient), base.WithX5C(opts.SendX5C), base.WithCacheAccessor(opts.Accessor), base.WithRegionDetection(opts.AzureRegion))
if err != nil {
- return "", err
- }
- ap.Claims = o.claims
- ap.LoginHint = o.loginHint
- ap.DomainHint = o.domainHint
- return cca.base.AuthCodeURL(ctx, clientID, redirectURI, scopes, ap)
-}
-
-// WithLoginHint pre-populates the login prompt with a username.
-func WithLoginHint(username string) interface {
- AuthCodeURLOption
- options.CallOption
-} {
- return struct {
- AuthCodeURLOption
- options.CallOption
- }{
- CallOption: options.NewCallOption(
- func(a any) error {
- switch t := a.(type) {
- case *authCodeURLOptions:
- t.loginHint = username
- default:
- return fmt.Errorf("unexpected options type %T", a)
- }
- return nil
- },
- ),
+ return Client{}, err
}
-}
-// WithDomainHint adds the IdP domain as domain_hint query parameter in the auth url.
-func WithDomainHint(domain string) interface {
- AuthCodeURLOption
- options.CallOption
-} {
- return struct {
- AuthCodeURLOption
- options.CallOption
- }{
- CallOption: options.NewCallOption(
- func(a any) error {
- switch t := a.(type) {
- case *authCodeURLOptions:
- t.domainHint = domain
- default:
- return fmt.Errorf("unexpected options type %T", a)
- }
- return nil
- },
- ),
- }
+ return Client{
+ base: base,
+ cred: cred.toInternal(),
+ }, nil
}
-// WithClaims sets additional claims to request for the token, such as those required by conditional access policies.
-// Use this option when Azure AD returned a claims challenge for a prior request. The argument must be decoded.
-// This option is valid for any token acquisition method.
-func WithClaims(claims string) interface {
- AcquireByAuthCodeOption
- AcquireByCredentialOption
- AcquireOnBehalfOfOption
- AcquireSilentOption
- AuthCodeURLOption
- options.CallOption
-} {
- return struct {
- AcquireByAuthCodeOption
- AcquireByCredentialOption
- AcquireOnBehalfOfOption
- AcquireSilentOption
- AuthCodeURLOption
- options.CallOption
- }{
- CallOption: options.NewCallOption(
- func(a any) error {
- switch t := a.(type) {
- case *acquireTokenByAuthCodeOptions:
- t.claims = claims
- case *acquireTokenByCredentialOptions:
- t.claims = claims
- case *acquireTokenOnBehalfOfOptions:
- t.claims = claims
- case *acquireTokenSilentOptions:
- t.claims = claims
- case *authCodeURLOptions:
- t.claims = claims
- default:
- return fmt.Errorf("unexpected options type %T", a)
- }
- return nil
- },
- ),
- }
+// UserID is the unique user identifier this client if for.
+func (cca Client) UserID() string {
+ return cca.userID
}
-// WithTenantID specifies a tenant for a single authentication. It may be different than the tenant set in [New].
-// This option is valid for any token acquisition method.
-func WithTenantID(tenantID string) interface {
- AcquireByAuthCodeOption
- AcquireByCredentialOption
- AcquireOnBehalfOfOption
- AcquireSilentOption
- AuthCodeURLOption
- options.CallOption
-} {
- return struct {
- AcquireByAuthCodeOption
- AcquireByCredentialOption
- AcquireOnBehalfOfOption
- AcquireSilentOption
- AuthCodeURLOption
- options.CallOption
- }{
- CallOption: options.NewCallOption(
- func(a any) error {
- switch t := a.(type) {
- case *acquireTokenByAuthCodeOptions:
- t.tenantID = tenantID
- case *acquireTokenByCredentialOptions:
- t.tenantID = tenantID
- case *acquireTokenOnBehalfOfOptions:
- t.tenantID = tenantID
- case *acquireTokenSilentOptions:
- t.tenantID = tenantID
- case *authCodeURLOptions:
- t.tenantID = tenantID
- default:
- return fmt.Errorf("unexpected options type %T", a)
- }
- return nil
- },
- ),
- }
+// AuthCodeURL creates a URL used to acquire an authorization code. Users need to call CreateAuthorizationCodeURLParameters and pass it in.
+func (cca Client) AuthCodeURL(ctx context.Context, clientID, redirectURI string, scopes []string) (string, error) {
+ return cca.base.AuthCodeURL(ctx, clientID, redirectURI, scopes, cca.base.AuthParams)
}
-// acquireTokenSilentOptions are all the optional settings to an AcquireTokenSilent() call.
+// AcquireTokenSilentOptions are all the optional settings to an AcquireTokenSilent() call.
// These are set by using various AcquireTokenSilentOption functions.
-type acquireTokenSilentOptions struct {
- account Account
- claims, tenantID string
+type AcquireTokenSilentOptions struct {
+ // Account represents the account to use. To set, use the WithSilentAccount() option.
+ Account Account
}
-// AcquireSilentOption is implemented by options for AcquireTokenSilent
-type AcquireSilentOption interface {
- acquireSilentOption()
-}
+// AcquireTokenSilentOption changes options inside AcquireTokenSilentOptions used in .AcquireTokenSilent().
+type AcquireTokenSilentOption func(a *AcquireTokenSilentOptions)
// WithSilentAccount uses the passed account during an AcquireTokenSilent() call.
-func WithSilentAccount(account Account) interface {
- AcquireSilentOption
- options.CallOption
-} {
- return struct {
- AcquireSilentOption
- options.CallOption
- }{
- CallOption: options.NewCallOption(
- func(a any) error {
- switch t := a.(type) {
- case *acquireTokenSilentOptions:
- t.account = account
- default:
- return fmt.Errorf("unexpected options type %T", a)
- }
- return nil
- },
- ),
+func WithSilentAccount(account Account) AcquireTokenSilentOption {
+ return func(a *AcquireTokenSilentOptions) {
+ a.Account = account
}
}
// AcquireTokenSilent acquires a token from either the cache or using a refresh token.
-//
-// Options: [WithClaims], [WithSilentAccount], [WithTenantID]
-func (cca Client) AcquireTokenSilent(ctx context.Context, scopes []string, opts ...AcquireSilentOption) (AuthResult, error) {
- o := acquireTokenSilentOptions{}
- if err := options.ApplyOptions(&o, opts); err != nil {
- return AuthResult{}, err
+func (cca Client) AcquireTokenSilent(ctx context.Context, scopes []string, options ...AcquireTokenSilentOption) (AuthResult, error) {
+ opts := AcquireTokenSilentOptions{}
+ for _, o := range options {
+ o(&opts)
}
-
- if o.claims != "" {
- return AuthResult{}, errors.New("call another AcquireToken method to request a new token having these claims")
+ var isAppCache bool
+ if opts.Account.IsZero() {
+ isAppCache = true
}
silentParameters := base.AcquireTokenSilentParameters{
Scopes: scopes,
- Account: o.account,
+ Account: opts.Account,
RequestType: accesstokens.ATConfidential,
Credential: cca.cred,
- IsAppCache: o.account.IsZero(),
- TenantID: o.tenantID,
+ IsAppCache: isAppCache,
}
return cca.base.AcquireTokenSilent(ctx, silentParameters)
}
-// acquireTokenByAuthCodeOptions contains the optional parameters used to acquire an access token using the authorization code flow.
-type acquireTokenByAuthCodeOptions struct {
- challenge, claims, tenantID string
+// AcquireTokenByAuthCodeOptions contains the optional parameters used to acquire an access token using the authorization code flow.
+type AcquireTokenByAuthCodeOptions struct {
+ Challenge string
}
-// AcquireByAuthCodeOption is implemented by options for AcquireTokenByAuthCode
-type AcquireByAuthCodeOption interface {
- acquireByAuthCodeOption()
-}
+// AcquireTokenByAuthCodeOption changes options inside AcquireTokenByAuthCodeOptions used in .AcquireTokenByAuthCode().
+type AcquireTokenByAuthCodeOption func(a *AcquireTokenByAuthCodeOptions)
// WithChallenge allows you to provide a challenge for the .AcquireTokenByAuthCode() call.
-func WithChallenge(challenge string) interface {
- AcquireByAuthCodeOption
- options.CallOption
-} {
- return struct {
- AcquireByAuthCodeOption
- options.CallOption
- }{
- CallOption: options.NewCallOption(
- func(a any) error {
- switch t := a.(type) {
- case *acquireTokenByAuthCodeOptions:
- t.challenge = challenge
- default:
- return fmt.Errorf("unexpected options type %T", a)
- }
- return nil
- },
- ),
+func WithChallenge(challenge string) AcquireTokenByAuthCodeOption {
+ return func(a *AcquireTokenByAuthCodeOptions) {
+ a.Challenge = challenge
}
}
// AcquireTokenByAuthCode is a request to acquire a security token from the authority, using an authorization code.
// The specified redirect URI must be the same URI that was used when the authorization code was requested.
-//
-// Options: [WithChallenge], [WithClaims], [WithTenantID]
-func (cca Client) AcquireTokenByAuthCode(ctx context.Context, code string, redirectURI string, scopes []string, opts ...AcquireByAuthCodeOption) (AuthResult, error) {
- o := acquireTokenByAuthCodeOptions{}
- if err := options.ApplyOptions(&o, opts); err != nil {
- return AuthResult{}, err
+func (cca Client) AcquireTokenByAuthCode(ctx context.Context, code string, redirectURI string, scopes []string, options ...AcquireTokenByAuthCodeOption) (AuthResult, error) {
+ opts := AcquireTokenByAuthCodeOptions{}
+ for _, o := range options {
+ o(&opts)
}
params := base.AcquireTokenAuthCodeParameters{
Scopes: scopes,
Code: code,
- Challenge: o.challenge,
- Claims: o.claims,
+ Challenge: opts.Challenge,
AppType: accesstokens.ATConfidential,
Credential: cca.cred, // This setting differs from public.Client.AcquireTokenByAuthCode
RedirectURI: redirectURI,
- TenantID: o.tenantID,
}
return cca.base.AcquireTokenByAuthCode(ctx, params)
}
-// acquireTokenByCredentialOptions contains optional configuration for AcquireTokenByCredential
-type acquireTokenByCredentialOptions struct {
- claims, tenantID string
-}
-
-// AcquireByCredentialOption is implemented by options for AcquireTokenByCredential
-type AcquireByCredentialOption interface {
- acquireByCredOption()
-}
-
// AcquireTokenByCredential acquires a security token from the authority, using the client credentials grant.
-//
-// Options: [WithClaims], [WithTenantID]
-func (cca Client) AcquireTokenByCredential(ctx context.Context, scopes []string, opts ...AcquireByCredentialOption) (AuthResult, error) {
- o := acquireTokenByCredentialOptions{}
- err := options.ApplyOptions(&o, opts)
- if err != nil {
- return AuthResult{}, err
- }
- authParams, err := cca.base.AuthParams.WithTenant(o.tenantID)
- if err != nil {
- return AuthResult{}, err
- }
+func (cca Client) AcquireTokenByCredential(ctx context.Context, scopes []string) (AuthResult, error) {
+ authParams := cca.base.AuthParams
authParams.Scopes = scopes
authParams.AuthorizationType = authority.ATClientCredentials
- authParams.Claims = o.claims
token, err := cca.base.Token.Credential(ctx, authParams, cca.cred)
if err != nil {
@@ -645,41 +394,24 @@ func (cca Client) AcquireTokenByCredential(ctx context.Context, scopes []string,
return cca.base.AuthResultFromToken(ctx, authParams, token, true)
}
-// acquireTokenOnBehalfOfOptions contains optional configuration for AcquireTokenOnBehalfOf
-type acquireTokenOnBehalfOfOptions struct {
- claims, tenantID string
-}
-
-// AcquireOnBehalfOfOption is implemented by options for AcquireTokenOnBehalfOf
-type AcquireOnBehalfOfOption interface {
- acquireOBOOption()
-}
-
// AcquireTokenOnBehalfOf acquires a security token for an app using middle tier apps access token.
// Refer https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow.
-//
-// Options: [WithClaims], [WithTenantID]
-func (cca Client) AcquireTokenOnBehalfOf(ctx context.Context, userAssertion string, scopes []string, opts ...AcquireOnBehalfOfOption) (AuthResult, error) {
- o := acquireTokenOnBehalfOfOptions{}
- if err := options.ApplyOptions(&o, opts); err != nil {
- return AuthResult{}, err
- }
+func (cca Client) AcquireTokenOnBehalfOf(ctx context.Context, userAssertion string, scopes []string) (AuthResult, error) {
params := base.AcquireTokenOnBehalfOfParameters{
Scopes: scopes,
UserAssertion: userAssertion,
- Claims: o.claims,
Credential: cca.cred,
- TenantID: o.tenantID,
}
return cca.base.AcquireTokenOnBehalfOf(ctx, params)
}
// Account gets the account in the token cache with the specified homeAccountID.
-func (cca Client) Account(ctx context.Context, accountID string) (Account, error) {
- return cca.base.Account(ctx, accountID)
+func (cca Client) Account(homeAccountID string) Account {
+ return cca.base.Account(homeAccountID)
}
// RemoveAccount signs the account out and forgets account from token cache.
-func (cca Client) RemoveAccount(ctx context.Context, account Account) error {
- return cca.base.RemoveAccount(ctx, account)
+func (cca Client) RemoveAccount(account Account) error {
+ cca.base.RemoveAccount(account)
+ return nil
}
diff --git a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/errors/error_design.md b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/errors/error_design.md
index 7ef7862fe..34a699f48 100644
--- a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/errors/error_design.md
+++ b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/errors/error_design.md
@@ -69,7 +69,7 @@ func (e CallErr) Error() string {
// Verbose prints a versbose error message with the request or response.
func (e CallErr) Verbose() string {
- e.Resp.Request = nil // This brings in a bunch of TLS stuff we don't need
+ e.Resp.Request = nil // This brings in a bunch of TLS crap we don't need
e.Resp.TLS = nil // Same
return fmt.Sprintf("%s:\nRequest:\n%s\nResponse:\n%s", e.Err, prettyConf.Sprint(e.Req), prettyConf.Sprint(e.Resp))
}
diff --git a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/errors/errors.go b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/errors/errors.go
index c9b8dbed0..c8adf3da2 100644
--- a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/errors/errors.go
+++ b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/errors/errors.go
@@ -7,6 +7,7 @@ import (
"errors"
"fmt"
"io"
+ "io/ioutil"
"net/http"
"reflect"
"strings"
@@ -20,7 +21,7 @@ var prettyConf = &pretty.Config{
TrackCycles: true,
Formatter: map[reflect.Type]interface{}{
reflect.TypeOf((*io.Reader)(nil)).Elem(): func(r io.Reader) string {
- b, err := io.ReadAll(r)
+ b, err := ioutil.ReadAll(r)
if err != nil {
return "could not read io.Reader content"
}
diff --git a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/base/base.go b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/base/base.go
index 5f68384f6..ac2916433 100644
--- a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/base/base.go
+++ b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/base/base.go
@@ -10,7 +10,6 @@ import (
"net/url"
"reflect"
"strings"
- "sync"
"time"
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/cache"
@@ -28,21 +27,27 @@ const (
)
// manager provides an internal cache. It is defined to allow faking the cache in tests.
-// In production it's a *storage.Manager or *storage.PartitionedManager.
+// In all production use it is a *storage.Manager.
type manager interface {
- cache.Serializer
- Read(context.Context, authority.AuthParams) (storage.TokenResponse, error)
- Write(authority.AuthParams, accesstokens.TokenResponse) (shared.Account, error)
-}
-
-// accountManager is a manager that also caches accounts. In production it's a *storage.Manager.
-type accountManager interface {
- manager
+ Read(ctx context.Context, authParameters authority.AuthParams, account shared.Account) (storage.TokenResponse, error)
+ Write(authParameters authority.AuthParams, tokenResponse accesstokens.TokenResponse) (shared.Account, error)
AllAccounts() []shared.Account
Account(homeAccountID string) shared.Account
RemoveAccount(account shared.Account, clientID string)
}
+// partitionedManager provides an internal cache. It is defined to allow faking the cache in tests.
+// In all production use it is a *storage.Manager.
+type partitionedManager interface {
+ Read(ctx context.Context, authParameters authority.AuthParams, account shared.Account) (storage.TokenResponse, error)
+ Write(authParameters authority.AuthParams, tokenResponse accesstokens.TokenResponse) (shared.Account, error)
+}
+
+type noopCacheAccessor struct{}
+
+func (n noopCacheAccessor) Replace(cache cache.Unmarshaler, key string) {}
+func (n noopCacheAccessor) Export(cache cache.Marshaler, key string) {}
+
// AcquireTokenSilentParameters contains the parameters to acquire a token silently (from cache).
type AcquireTokenSilentParameters struct {
Scopes []string
@@ -50,10 +55,8 @@ type AcquireTokenSilentParameters struct {
RequestType accesstokens.AppType
Credential *accesstokens.Credential
IsAppCache bool
- TenantID string
UserAssertion string
AuthorizationType authority.AuthorizeType
- Claims string
}
// AcquireTokenAuthCodeParameters contains the parameters required to acquire an access token using the auth code flow.
@@ -64,18 +67,14 @@ type AcquireTokenAuthCodeParameters struct {
Scopes []string
Code string
Challenge string
- Claims string
RedirectURI string
AppType accesstokens.AppType
Credential *accesstokens.Credential
- TenantID string
}
type AcquireTokenOnBehalfOfParameters struct {
Scopes []string
- Claims string
Credential *accesstokens.Credential
- TenantID string
UserAssertion string
}
@@ -128,97 +127,57 @@ func NewAuthResult(tokenResponse accesstokens.TokenResponse, account shared.Acco
// Client is a base client that provides access to common methods and primatives that
// can be used by multiple clients.
type Client struct {
- Token *oauth.Client
- manager accountManager // *storage.Manager or fakeManager in tests
- // pmanager is a partitioned cache for OBO authentication. *storage.PartitionedManager or fakeManager in tests
- pmanager manager
-
- AuthParams authority.AuthParams // DO NOT EVER MAKE THIS A POINTER! See "Note" in New().
- cacheAccessor cache.ExportReplace
- cacheAccessorMu *sync.RWMutex
+ Token *oauth.Client
+ manager manager // *storage.Manager or fakeManager in tests
+ pmanager partitionedManager // *storage.PartitionedManager or fakeManager in tests
+
+ AuthParams authority.AuthParams // DO NOT EVER MAKE THIS A POINTER! See "Note" in New().
+ cacheAccessor cache.ExportReplace
}
// Option is an optional argument to the New constructor.
-type Option func(c *Client) error
+type Option func(c *Client)
// WithCacheAccessor allows you to set some type of cache for storing authentication tokens.
func WithCacheAccessor(ca cache.ExportReplace) Option {
- return func(c *Client) error {
+ return func(c *Client) {
if ca != nil {
c.cacheAccessor = ca
}
- return nil
- }
-}
-
-// WithClientCapabilities allows configuring one or more client capabilities such as "CP1"
-func WithClientCapabilities(capabilities []string) Option {
- return func(c *Client) error {
- var err error
- if len(capabilities) > 0 {
- cc, err := authority.NewClientCapabilities(capabilities)
- if err == nil {
- c.AuthParams.Capabilities = cc
- }
- }
- return err
- }
-}
-
-// WithKnownAuthorityHosts specifies hosts Client shouldn't validate or request metadata for because they're known to the user
-func WithKnownAuthorityHosts(hosts []string) Option {
- return func(c *Client) error {
- cp := make([]string, len(hosts))
- copy(cp, hosts)
- c.AuthParams.KnownAuthorityHosts = cp
- return nil
}
}
// WithX5C specifies if x5c claim(public key of the certificate) should be sent to STS to enable Subject Name Issuer Authentication.
func WithX5C(sendX5C bool) Option {
- return func(c *Client) error {
+ return func(c *Client) {
c.AuthParams.SendX5C = sendX5C
- return nil
}
}
func WithRegionDetection(region string) Option {
- return func(c *Client) error {
+ return func(c *Client) {
c.AuthParams.AuthorityInfo.Region = region
- return nil
- }
-}
-
-func WithInstanceDiscovery(instanceDiscoveryEnabled bool) Option {
- return func(c *Client) error {
- c.AuthParams.AuthorityInfo.ValidateAuthority = instanceDiscoveryEnabled
- c.AuthParams.AuthorityInfo.InstanceDiscoveryDisabled = !instanceDiscoveryEnabled
- return nil
}
}
// New is the constructor for Base.
func New(clientID string, authorityURI string, token *oauth.Client, options ...Option) (Client, error) {
- //By default, validateAuthority is set to true and instanceDiscoveryDisabled is set to false
- authInfo, err := authority.NewInfoFromAuthorityURI(authorityURI, true, false)
+ authInfo, err := authority.NewInfoFromAuthorityURI(authorityURI, true)
if err != nil {
return Client{}, err
}
authParams := authority.NewAuthParams(clientID, authInfo)
client := Client{ // Note: Hey, don't even THINK about making Base into *Base. See "design notes" in public.go and confidential.go
- Token: token,
- AuthParams: authParams,
- cacheAccessorMu: &sync.RWMutex{},
- manager: storage.New(token),
- pmanager: storage.NewPartitionedManager(token),
+ Token: token,
+ AuthParams: authParams,
+ cacheAccessor: noopCacheAccessor{},
+ manager: storage.New(token),
+ pmanager: storage.NewPartitionedManager(token),
}
for _, o := range options {
- if err = o(&client); err != nil {
- break
- }
+ o(&client)
}
- return client, err
+ return client, nil
}
@@ -234,11 +193,6 @@ func (b Client) AuthCodeURL(ctx context.Context, clientID, redirectURI string, s
return "", err
}
- claims, err := authParams.MergeCapabilitiesAndClaims()
- if err != nil {
- return "", err
- }
-
v := url.Values{}
v.Add("client_id", clientID)
v.Add("response_type", "code")
@@ -247,97 +201,87 @@ func (b Client) AuthCodeURL(ctx context.Context, clientID, redirectURI string, s
if authParams.State != "" {
v.Add("state", authParams.State)
}
- if claims != "" {
- v.Add("claims", claims)
- }
if authParams.CodeChallenge != "" {
v.Add("code_challenge", authParams.CodeChallenge)
}
if authParams.CodeChallengeMethod != "" {
v.Add("code_challenge_method", authParams.CodeChallengeMethod)
}
- if authParams.LoginHint != "" {
- v.Add("login_hint", authParams.LoginHint)
- }
if authParams.Prompt != "" {
v.Add("prompt", authParams.Prompt)
}
- if authParams.DomainHint != "" {
- v.Add("domain_hint", authParams.DomainHint)
- }
// There were left over from an implementation that didn't use any of these. We may
// need to add them later, but as of now aren't needed.
/*
if p.ResponseMode != "" {
urlParams.Add("response_mode", p.ResponseMode)
}
+ if p.LoginHint != "" {
+ urlParams.Add("login_hint", p.LoginHint)
+ }
+ if p.DomainHint != "" {
+ urlParams.Add("domain_hint", p.DomainHint)
+ }
*/
baseURL.RawQuery = v.Encode()
return baseURL.String(), nil
}
func (b Client) AcquireTokenSilent(ctx context.Context, silent AcquireTokenSilentParameters) (AuthResult, error) {
- ar := AuthResult{}
- // when tenant == "", the caller didn't specify a tenant and WithTenant will choose the client's configured tenant
- tenant := silent.TenantID
- authParams, err := b.AuthParams.WithTenant(tenant)
- if err != nil {
- return ar, err
- }
+ authParams := b.AuthParams // This is a copy, as we dont' have a pointer receiver and authParams is not a pointer.
authParams.Scopes = silent.Scopes
- authParams.HomeAccountID = silent.Account.HomeAccountID
+ authParams.HomeaccountID = silent.Account.HomeAccountID
authParams.AuthorizationType = silent.AuthorizationType
- authParams.Claims = silent.Claims
authParams.UserAssertion = silent.UserAssertion
- m := b.pmanager
- if authParams.AuthorizationType != authority.ATOnBehalfOf {
+ var storageTokenResponse storage.TokenResponse
+ var err error
+ if authParams.AuthorizationType == authority.ATOnBehalfOf {
+ if s, ok := b.pmanager.(cache.Serializer); ok {
+ suggestedCacheKey := authParams.CacheKey(silent.IsAppCache)
+ b.cacheAccessor.Replace(s, suggestedCacheKey)
+ defer b.cacheAccessor.Export(s, suggestedCacheKey)
+ }
+ storageTokenResponse, err = b.pmanager.Read(ctx, authParams, silent.Account)
+ if err != nil {
+ return AuthResult{}, err
+ }
+ } else {
+ if s, ok := b.manager.(cache.Serializer); ok {
+ suggestedCacheKey := authParams.CacheKey(silent.IsAppCache)
+ b.cacheAccessor.Replace(s, suggestedCacheKey)
+ defer b.cacheAccessor.Export(s, suggestedCacheKey)
+ }
authParams.AuthorizationType = authority.ATRefreshToken
- m = b.manager
- }
- if b.cacheAccessor != nil {
- key := authParams.CacheKey(silent.IsAppCache)
- b.cacheAccessorMu.RLock()
- err = b.cacheAccessor.Replace(ctx, m, cache.ReplaceHints{PartitionKey: key})
- b.cacheAccessorMu.RUnlock()
- }
- if err != nil {
- return ar, err
+ storageTokenResponse, err = b.manager.Read(ctx, authParams, silent.Account)
+ if err != nil {
+ return AuthResult{}, err
+ }
}
- storageTokenResponse, err := m.Read(ctx, authParams)
+
+ result, err := AuthResultFromStorage(storageTokenResponse)
if err != nil {
- return ar, err
- }
+ if reflect.ValueOf(storageTokenResponse.RefreshToken).IsZero() {
+ return AuthResult{}, errors.New("no refresh token found")
+ }
- // ignore cached access tokens when given claims
- if silent.Claims == "" {
- ar, err = AuthResultFromStorage(storageTokenResponse)
- if err == nil {
- return ar, err
+ var cc *accesstokens.Credential
+ if silent.RequestType == accesstokens.ATConfidential {
+ cc = silent.Credential
}
- }
- // redeem a cached refresh token, if available
- if reflect.ValueOf(storageTokenResponse.RefreshToken).IsZero() {
- return ar, errors.New("no token found")
- }
- var cc *accesstokens.Credential
- if silent.RequestType == accesstokens.ATConfidential {
- cc = silent.Credential
- }
- token, err := b.Token.Refresh(ctx, silent.RequestType, authParams, cc, storageTokenResponse.RefreshToken)
- if err != nil {
- return ar, err
+ token, err := b.Token.Refresh(ctx, silent.RequestType, b.AuthParams, cc, storageTokenResponse.RefreshToken)
+ if err != nil {
+ return AuthResult{}, err
+ }
+
+ return b.AuthResultFromToken(ctx, authParams, token, true)
}
- return b.AuthResultFromToken(ctx, authParams, token, true)
+ return result, nil
}
func (b Client) AcquireTokenByAuthCode(ctx context.Context, authCodeParams AcquireTokenAuthCodeParameters) (AuthResult, error) {
- authParams, err := b.AuthParams.WithTenant(authCodeParams.TenantID)
- if err != nil {
- return AuthResult{}, err
- }
- authParams.Claims = authCodeParams.Claims
+ authParams := b.AuthParams // This is a copy, as we dont' have a pointer receiver and .AuthParams is not a pointer.
authParams.Scopes = authCodeParams.Scopes
authParams.Redirecturi = authCodeParams.RedirectURI
authParams.AuthorizationType = authority.ATAuthCode
@@ -363,105 +307,91 @@ func (b Client) AcquireTokenByAuthCode(ctx context.Context, authCodeParams Acqui
// AcquireTokenOnBehalfOf acquires a security token for an app using middle tier apps access token.
func (b Client) AcquireTokenOnBehalfOf(ctx context.Context, onBehalfOfParams AcquireTokenOnBehalfOfParameters) (AuthResult, error) {
- var ar AuthResult
+ authParams := b.AuthParams // This is a copy, as we dont' have a pointer receiver and .AuthParams is not a pointer.
+ authParams.Scopes = onBehalfOfParams.Scopes
+ authParams.AuthorizationType = authority.ATOnBehalfOf
+ authParams.UserAssertion = onBehalfOfParams.UserAssertion
+
silentParameters := AcquireTokenSilentParameters{
Scopes: onBehalfOfParams.Scopes,
RequestType: accesstokens.ATConfidential,
Credential: onBehalfOfParams.Credential,
UserAssertion: onBehalfOfParams.UserAssertion,
AuthorizationType: authority.ATOnBehalfOf,
- TenantID: onBehalfOfParams.TenantID,
- Claims: onBehalfOfParams.Claims,
- }
- ar, err := b.AcquireTokenSilent(ctx, silentParameters)
- if err == nil {
- return ar, err
}
- authParams, err := b.AuthParams.WithTenant(onBehalfOfParams.TenantID)
+ token, err := b.AcquireTokenSilent(ctx, silentParameters)
if err != nil {
- return AuthResult{}, err
- }
- authParams.AuthorizationType = authority.ATOnBehalfOf
- authParams.Claims = onBehalfOfParams.Claims
- authParams.Scopes = onBehalfOfParams.Scopes
- authParams.UserAssertion = onBehalfOfParams.UserAssertion
- token, err := b.Token.OnBehalfOf(ctx, authParams, onBehalfOfParams.Credential)
- if err == nil {
- ar, err = b.AuthResultFromToken(ctx, authParams, token, true)
+ fmt.Println("Acquire Token Silent failed ")
+ token, err := b.Token.OnBehalfOf(ctx, authParams, onBehalfOfParams.Credential)
+ if err != nil {
+ return AuthResult{}, err
+ }
+ return b.AuthResultFromToken(ctx, authParams, token, true)
}
- return ar, err
+ return token, err
}
func (b Client) AuthResultFromToken(ctx context.Context, authParams authority.AuthParams, token accesstokens.TokenResponse, cacheWrite bool) (AuthResult, error) {
if !cacheWrite {
return NewAuthResult(token, shared.Account{})
}
- var m manager = b.manager
+
+ var account shared.Account
+ var err error
if authParams.AuthorizationType == authority.ATOnBehalfOf {
- m = b.pmanager
- }
- key := token.CacheKey(authParams)
- if b.cacheAccessor != nil {
- b.cacheAccessorMu.Lock()
- defer b.cacheAccessorMu.Unlock()
- err := b.cacheAccessor.Replace(ctx, m, cache.ReplaceHints{PartitionKey: key})
+ if s, ok := b.pmanager.(cache.Serializer); ok {
+ suggestedCacheKey := token.CacheKey(authParams)
+ b.cacheAccessor.Replace(s, suggestedCacheKey)
+ defer b.cacheAccessor.Export(s, suggestedCacheKey)
+ }
+ account, err = b.pmanager.Write(authParams, token)
if err != nil {
return AuthResult{}, err
}
- }
- account, err := m.Write(authParams, token)
- if err != nil {
- return AuthResult{}, err
- }
- ar, err := NewAuthResult(token, account)
- if err == nil && b.cacheAccessor != nil {
- err = b.cacheAccessor.Export(ctx, b.manager, cache.ExportHints{PartitionKey: key})
- }
- return ar, err
-}
-
-func (b Client) AllAccounts(ctx context.Context) ([]shared.Account, error) {
- if b.cacheAccessor != nil {
- b.cacheAccessorMu.RLock()
- defer b.cacheAccessorMu.RUnlock()
- key := b.AuthParams.CacheKey(false)
- err := b.cacheAccessor.Replace(ctx, b.manager, cache.ReplaceHints{PartitionKey: key})
+ } else {
+ if s, ok := b.manager.(cache.Serializer); ok {
+ suggestedCacheKey := token.CacheKey(authParams)
+ b.cacheAccessor.Replace(s, suggestedCacheKey)
+ defer b.cacheAccessor.Export(s, suggestedCacheKey)
+ }
+ account, err = b.manager.Write(authParams, token)
if err != nil {
- return nil, err
+ return AuthResult{}, err
}
}
- return b.manager.AllAccounts(), nil
+ return NewAuthResult(token, account)
}
-func (b Client) Account(ctx context.Context, homeAccountID string) (shared.Account, error) {
- if b.cacheAccessor != nil {
- b.cacheAccessorMu.RLock()
- defer b.cacheAccessorMu.RUnlock()
- authParams := b.AuthParams // This is a copy, as we don't have a pointer receiver and .AuthParams is not a pointer.
- authParams.AuthorizationType = authority.AccountByID
- authParams.HomeAccountID = homeAccountID
- key := b.AuthParams.CacheKey(false)
- err := b.cacheAccessor.Replace(ctx, b.manager, cache.ReplaceHints{PartitionKey: key})
- if err != nil {
- return shared.Account{}, err
- }
+func (b Client) AllAccounts() []shared.Account {
+ if s, ok := b.manager.(cache.Serializer); ok {
+ suggestedCacheKey := b.AuthParams.CacheKey(false)
+ b.cacheAccessor.Replace(s, suggestedCacheKey)
+ defer b.cacheAccessor.Export(s, suggestedCacheKey)
}
- return b.manager.Account(homeAccountID), nil
+
+ accounts := b.manager.AllAccounts()
+ return accounts
+}
+
+func (b Client) Account(homeAccountID string) shared.Account {
+ authParams := b.AuthParams // This is a copy, as we dont' have a pointer receiver and .AuthParams is not a pointer.
+ authParams.AuthorizationType = authority.AccountByID
+ authParams.HomeaccountID = homeAccountID
+ if s, ok := b.manager.(cache.Serializer); ok {
+ suggestedCacheKey := b.AuthParams.CacheKey(false)
+ b.cacheAccessor.Replace(s, suggestedCacheKey)
+ defer b.cacheAccessor.Export(s, suggestedCacheKey)
+ }
+ account := b.manager.Account(homeAccountID)
+ return account
}
// RemoveAccount removes all the ATs, RTs and IDTs from the cache associated with this account.
-func (b Client) RemoveAccount(ctx context.Context, account shared.Account) error {
- if b.cacheAccessor == nil {
- b.manager.RemoveAccount(account, b.AuthParams.ClientID)
- return nil
- }
- b.cacheAccessorMu.Lock()
- defer b.cacheAccessorMu.Unlock()
- key := b.AuthParams.CacheKey(false)
- err := b.cacheAccessor.Replace(ctx, b.manager, cache.ReplaceHints{PartitionKey: key})
- if err != nil {
- return err
+func (b Client) RemoveAccount(account shared.Account) {
+ if s, ok := b.manager.(cache.Serializer); ok {
+ suggestedCacheKey := b.AuthParams.CacheKey(false)
+ b.cacheAccessor.Replace(s, suggestedCacheKey)
+ defer b.cacheAccessor.Export(s, suggestedCacheKey)
}
b.manager.RemoveAccount(account, b.AuthParams.ClientID)
- return b.cacheAccessor.Export(ctx, b.manager, cache.ExportHints{PartitionKey: key})
}
diff --git a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/base/internal/storage/items.go b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/base/internal/storage/items.go
index 5d4c9f1d1..1e8d9a841 100644
--- a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/base/internal/storage/items.go
+++ b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/base/internal/storage/items.go
@@ -97,21 +97,14 @@ func NewAccessToken(homeID, env, realm, clientID string, cachedAt, expiresOn, ex
// Key outputs the key that can be used to uniquely look up this entry in a map.
func (a AccessToken) Key() string {
- key := strings.Join(
+ return strings.Join(
[]string{a.HomeAccountID, a.Environment, a.CredentialType, a.ClientID, a.Realm, a.Scopes},
shared.CacheKeySeparator,
)
- return strings.ToLower(key)
}
-// FakeValidate enables tests to fake access token validation
-var FakeValidate func(AccessToken) error
-
// Validate validates that this AccessToken can be used.
func (a AccessToken) Validate() error {
- if FakeValidate != nil {
- return FakeValidate(a)
- }
if a.CachedAt.T.After(time.Now()) {
return errors.New("access token isn't valid, it was cached at a future time")
}
@@ -168,11 +161,10 @@ func NewIDToken(homeID, env, realm, clientID, idToken string) IDToken {
// Key outputs the key that can be used to uniquely look up this entry in a map.
func (id IDToken) Key() string {
- key := strings.Join(
+ return strings.Join(
[]string{id.HomeAccountID, id.Environment, id.CredentialType, id.ClientID, id.Realm},
shared.CacheKeySeparator,
)
- return strings.ToLower(key)
}
// AppMetaData is the JSON representation of application metadata for encoding to storage.
@@ -195,9 +187,8 @@ func NewAppMetaData(familyID, clientID, environment string) AppMetaData {
// Key outputs the key that can be used to uniquely look up this entry in a map.
func (a AppMetaData) Key() string {
- key := strings.Join(
+ return strings.Join(
[]string{"AppMetaData", a.Environment, a.ClientID},
shared.CacheKeySeparator,
)
- return strings.ToLower(key)
}
diff --git a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/base/internal/storage/partitioned_storage.go b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/base/internal/storage/partitioned_storage.go
index 5e1cae0b8..4c7c1f1b5 100644
--- a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/base/internal/storage/partitioned_storage.go
+++ b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/base/internal/storage/partitioned_storage.go
@@ -36,56 +36,55 @@ func NewPartitionedManager(requests *oauth.Client) *PartitionedManager {
}
// Read reads a storage token from the cache if it exists.
-func (m *PartitionedManager) Read(ctx context.Context, authParameters authority.AuthParams) (TokenResponse, error) {
- tr := TokenResponse{}
+func (m *PartitionedManager) Read(ctx context.Context, authParameters authority.AuthParams, account shared.Account) (TokenResponse, error) {
realm := authParameters.AuthorityInfo.Tenant
clientID := authParameters.ClientID
scopes := authParameters.Scopes
- // fetch metadata if instanceDiscovery is enabled
- aliases := []string{authParameters.AuthorityInfo.Host}
- if !authParameters.AuthorityInfo.InstanceDiscoveryDisabled {
- metadata, err := m.getMetadataEntry(ctx, authParameters.AuthorityInfo)
- if err != nil {
- return TokenResponse{}, err
- }
- aliases = metadata.Aliases
+ metadata, err := m.getMetadataEntry(ctx, authParameters.AuthorityInfo)
+ if err != nil {
+ return TokenResponse{}, err
}
-
userAssertionHash := authParameters.AssertionHash()
partitionKeyFromRequest := userAssertionHash
- // errors returned by read* methods indicate a cache miss and are therefore non-fatal. We continue populating
- // TokenResponse fields so that e.g. lack of an ID token doesn't prevent the caller from receiving a refresh token.
- accessToken, err := m.readAccessToken(aliases, realm, clientID, userAssertionHash, scopes, partitionKeyFromRequest)
- if err == nil {
- tr.AccessToken = accessToken
+ accessToken, err := m.readAccessToken(metadata.Aliases, realm, clientID, userAssertionHash, scopes, partitionKeyFromRequest)
+ if err != nil {
+ return TokenResponse{}, err
}
- idToken, err := m.readIDToken(aliases, realm, clientID, userAssertionHash, getPartitionKeyIDTokenRead(accessToken))
- if err == nil {
- tr.IDToken = idToken
+
+ AppMetaData, err := m.readAppMetaData(metadata.Aliases, clientID)
+ if err != nil {
+ return TokenResponse{}, err
}
+ familyID := AppMetaData.FamilyID
- if appMetadata, err := m.readAppMetaData(aliases, clientID); err == nil {
- // we need the family ID to identify the correct refresh token, if any
- familyID := appMetadata.FamilyID
- refreshToken, err := m.readRefreshToken(aliases, familyID, clientID, userAssertionHash, partitionKeyFromRequest)
- if err == nil {
- tr.RefreshToken = refreshToken
- }
+ refreshToken, err := m.readRefreshToken(metadata.Aliases, familyID, clientID, userAssertionHash, partitionKeyFromRequest)
+ if err != nil {
+ return TokenResponse{}, err
}
- account, err := m.readAccount(aliases, realm, userAssertionHash, idToken.HomeAccountID)
- if err == nil {
- tr.Account = account
+ idToken, err := m.readIDToken(metadata.Aliases, realm, clientID, userAssertionHash, getPartitionKeyIDTokenRead(accessToken))
+ if err != nil {
+ return TokenResponse{}, err
}
- return tr, nil
+
+ account, err = m.readAccount(metadata.Aliases, realm, userAssertionHash, idToken.HomeAccountID)
+ if err != nil {
+ return TokenResponse{}, err
+ }
+ return TokenResponse{
+ AccessToken: accessToken,
+ RefreshToken: refreshToken,
+ IDToken: idToken,
+ Account: account,
+ }, nil
}
// Write writes a token response to the cache and returns the account information the token is stored with.
func (m *PartitionedManager) Write(authParameters authority.AuthParams, tokenResponse accesstokens.TokenResponse) (shared.Account, error) {
- authParameters.HomeAccountID = tokenResponse.HomeAccountID()
- homeAccountID := authParameters.HomeAccountID
+ authParameters.HomeaccountID = tokenResponse.ClientInfo.HomeAccountID()
+ homeAccountID := authParameters.HomeaccountID
environment := authParameters.AuthorityInfo.Host
realm := authParameters.AuthorityInfo.Tenant
clientID := authParameters.ClientID
@@ -144,18 +143,13 @@ func (m *PartitionedManager) Write(authParameters authority.AuthParams, tokenRes
localAccountID := idTokenJwt.LocalAccountID()
authorityType := authParameters.AuthorityInfo.AuthorityType
- preferredUsername := idTokenJwt.UPN
- if idTokenJwt.PreferredUsername != "" {
- preferredUsername = idTokenJwt.PreferredUsername
- }
-
account = shared.NewAccount(
homeAccountID,
environment,
realm,
localAccountID,
authorityType,
- preferredUsername,
+ idTokenJwt.PreferredUsername,
)
if authParameters.AuthorizationType == authority.ATOnBehalfOf {
account.UserAssertionHash = userAssertionHash
diff --git a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/base/internal/storage/storage.go b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/base/internal/storage/storage.go
index d3a39e005..881bd7c68 100644
--- a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/base/internal/storage/storage.go
+++ b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/base/internal/storage/storage.go
@@ -83,62 +83,68 @@ func isMatchingScopes(scopesOne []string, scopesTwo string) bool {
}
// Read reads a storage token from the cache if it exists.
-func (m *Manager) Read(ctx context.Context, authParameters authority.AuthParams) (TokenResponse, error) {
- tr := TokenResponse{}
- homeAccountID := authParameters.HomeAccountID
+func (m *Manager) Read(ctx context.Context, authParameters authority.AuthParams, account shared.Account) (TokenResponse, error) {
+ homeAccountID := authParameters.HomeaccountID
realm := authParameters.AuthorityInfo.Tenant
clientID := authParameters.ClientID
scopes := authParameters.Scopes
- // fetch metadata if instanceDiscovery is enabled
- aliases := []string{authParameters.AuthorityInfo.Host}
- if !authParameters.AuthorityInfo.InstanceDiscoveryDisabled {
- metadata, err := m.getMetadataEntry(ctx, authParameters.AuthorityInfo)
- if err != nil {
- return TokenResponse{}, err
- }
- aliases = metadata.Aliases
+ metadata, err := m.getMetadataEntry(ctx, authParameters.AuthorityInfo)
+ if err != nil {
+ return TokenResponse{}, err
}
- accessToken := m.readAccessToken(homeAccountID, aliases, realm, clientID, scopes)
- tr.AccessToken = accessToken
+ accessToken, err := m.readAccessToken(homeAccountID, metadata.Aliases, realm, clientID, scopes)
+ if err != nil {
+ return TokenResponse{}, err
+ }
- if homeAccountID == "" {
- // caller didn't specify a user, so there's no reason to search for an ID or refresh token
- return tr, nil
+ if account.IsZero() {
+ return TokenResponse{
+ AccessToken: accessToken,
+ RefreshToken: accesstokens.RefreshToken{},
+ IDToken: IDToken{},
+ Account: shared.Account{},
+ }, nil
}
- // errors returned by read* methods indicate a cache miss and are therefore non-fatal. We continue populating
- // TokenResponse fields so that e.g. lack of an ID token doesn't prevent the caller from receiving a refresh token.
- idToken, err := m.readIDToken(homeAccountID, aliases, realm, clientID)
- if err == nil {
- tr.IDToken = idToken
+ idToken, err := m.readIDToken(homeAccountID, metadata.Aliases, realm, clientID)
+ if err != nil {
+ return TokenResponse{}, err
}
- if appMetadata, err := m.readAppMetaData(aliases, clientID); err == nil {
- // we need the family ID to identify the correct refresh token, if any
- familyID := appMetadata.FamilyID
- refreshToken, err := m.readRefreshToken(homeAccountID, aliases, familyID, clientID)
- if err == nil {
- tr.RefreshToken = refreshToken
- }
+ AppMetaData, err := m.readAppMetaData(metadata.Aliases, clientID)
+ if err != nil {
+ return TokenResponse{}, err
}
+ familyID := AppMetaData.FamilyID
- account, err := m.readAccount(homeAccountID, aliases, realm)
- if err == nil {
- tr.Account = account
+ refreshToken, err := m.readRefreshToken(homeAccountID, metadata.Aliases, familyID, clientID)
+ if err != nil {
+ return TokenResponse{}, err
}
- return tr, nil
+ account, err = m.readAccount(homeAccountID, metadata.Aliases, realm)
+ if err != nil {
+ return TokenResponse{}, err
+ }
+ return TokenResponse{
+ AccessToken: accessToken,
+ RefreshToken: refreshToken,
+ IDToken: idToken,
+ Account: account,
+ }, nil
}
const scopeSeparator = " "
// Write writes a token response to the cache and returns the account information the token is stored with.
func (m *Manager) Write(authParameters authority.AuthParams, tokenResponse accesstokens.TokenResponse) (shared.Account, error) {
- homeAccountID := tokenResponse.HomeAccountID()
+ authParameters.HomeaccountID = tokenResponse.ClientInfo.HomeAccountID()
+ homeAccountID := authParameters.HomeaccountID
environment := authParameters.AuthorityInfo.Host
realm := authParameters.AuthorityInfo.Tenant
clientID := authParameters.ClientID
target := strings.Join(tokenResponse.GrantedScopes.Slice, scopeSeparator)
+
cachedAt := time.Now()
var account shared.Account
@@ -181,18 +187,13 @@ func (m *Manager) Write(authParameters authority.AuthParams, tokenResponse acces
localAccountID := idTokenJwt.LocalAccountID()
authorityType := authParameters.AuthorityInfo.AuthorityType
- preferredUsername := idTokenJwt.UPN
- if idTokenJwt.PreferredUsername != "" {
- preferredUsername = idTokenJwt.PreferredUsername
- }
-
account = shared.NewAccount(
homeAccountID,
environment,
realm,
localAccountID,
authorityType,
- preferredUsername,
+ idTokenJwt.PreferredUsername,
)
if err := m.writeAccount(account); err != nil {
return shared.Account{}, err
@@ -248,7 +249,7 @@ func (m *Manager) aadMetadata(ctx context.Context, authorityInfo authority.Info)
return m.aadCache[authorityInfo.Host], nil
}
-func (m *Manager) readAccessToken(homeID string, envAliases []string, realm, clientID string, scopes []string) AccessToken {
+func (m *Manager) readAccessToken(homeID string, envAliases []string, realm, clientID string, scopes []string) (AccessToken, error) {
m.contractMu.RLock()
defer m.contractMu.RUnlock()
// TODO: linear search (over a map no less) is slow for a large number (thousands) of tokens.
@@ -258,12 +259,12 @@ func (m *Manager) readAccessToken(homeID string, envAliases []string, realm, cli
if at.HomeAccountID == homeID && at.Realm == realm && at.ClientID == clientID {
if checkAlias(at.Environment, envAliases) {
if isMatchingScopes(scopes, at.Scopes) {
- return at
+ return at, nil
}
}
}
}
- return AccessToken{}
+ return AccessToken{}, fmt.Errorf("access token not found")
}
func (m *Manager) writeAccessToken(accessToken AccessToken) error {
@@ -493,8 +494,6 @@ func (m *Manager) update(cache *Contract) {
// Marshal implements cache.Marshaler.
func (m *Manager) Marshal() ([]byte, error) {
- m.contractMu.RLock()
- defer m.contractMu.RUnlock()
return json.Marshal(m.contract)
}
diff --git a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/base/internal/storage/test_serialized_cache.json b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/base/internal/storage/test_serialized_cache.json
new file mode 100644
index 000000000..1d8181924
--- /dev/null
+++ b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/base/internal/storage/test_serialized_cache.json
@@ -0,0 +1,56 @@
+{
+ "Account": {
+ "uid.utid-login.windows.net-contoso": {
+ "username": "John Doe",
+ "local_account_id": "object1234",
+ "realm": "contoso",
+ "environment": "login.windows.net",
+ "home_account_id": "uid.utid",
+ "authority_type": "MSSTS"
+ }
+ },
+ "RefreshToken": {
+ "uid.utid-login.windows.net-refreshtoken-my_client_id--s2 s1 s3": {
+ "target": "s2 s1 s3",
+ "environment": "login.windows.net",
+ "credential_type": "RefreshToken",
+ "secret": "a refresh token",
+ "client_id": "my_client_id",
+ "home_account_id": "uid.utid"
+ }
+ },
+ "AccessToken": {
+ "an-entry": {
+ "foo": "bar"
+ },
+ "uid.utid-login.windows.net-accesstoken-my_client_id-contoso-s2 s1 s3": {
+ "environment": "login.windows.net",
+ "credential_type": "AccessToken",
+ "secret": "an access token",
+ "realm": "contoso",
+ "target": "s2 s1 s3",
+ "client_id": "my_client_id",
+ "cached_at": "1000",
+ "home_account_id": "uid.utid",
+ "extended_expires_on": "4600",
+ "expires_on": "4600"
+ }
+ },
+ "IdToken": {
+ "uid.utid-login.windows.net-idtoken-my_client_id-contoso-": {
+ "realm": "contoso",
+ "environment": "login.windows.net",
+ "credential_type": "IdToken",
+ "secret": "header.eyJvaWQiOiAib2JqZWN0MTIzNCIsICJwcmVmZXJyZWRfdXNlcm5hbWUiOiAiSm9obiBEb2UiLCAic3ViIjogInN1YiJ9.signature",
+ "client_id": "my_client_id",
+ "home_account_id": "uid.utid"
+ }
+ },
+ "unknownEntity": {"field1":"1","field2":"whats"},
+ "AppMetadata": {
+ "AppMetadata-login.windows.net-my_client_id": {
+ "environment": "login.windows.net",
+ "client_id": "my_client_id"
+ }
+ }
+ }
\ No newline at end of file
diff --git a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/exported/exported.go b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/exported/exported.go
deleted file mode 100644
index 7b673e3fe..000000000
--- a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/exported/exported.go
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT license.
-
-// package exported contains internal types that are re-exported from a public package
-package exported
-
-// AssertionRequestOptions has information required to generate a client assertion
-type AssertionRequestOptions struct {
- // ClientID identifies the application for which an assertion is requested. Used as the assertion's "iss" and "sub" claims.
- ClientID string
-
- // TokenEndpoint is the intended token endpoint. Used as the assertion's "aud" claim.
- TokenEndpoint string
-}
-
-// TokenProviderParameters is the authentication parameters passed to token providers
-type TokenProviderParameters struct {
- // Claims contains any additional claims requested for the token
- Claims string
- // CorrelationID of the authentication request
- CorrelationID string
- // Scopes requested for the token
- Scopes []string
- // TenantID identifies the tenant in which to authenticate
- TenantID string
-}
-
-// TokenProviderResult is the authentication result returned by custom token providers
-type TokenProviderResult struct {
- // AccessToken is the requested token
- AccessToken string
- // ExpiresInSeconds is the lifetime of the token in seconds
- ExpiresInSeconds int
-}
diff --git a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/json/json.go b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/json/json.go
index 2238521f5..83bd60d41 100644
--- a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/json/json.go
+++ b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/json/json.go
@@ -52,7 +52,7 @@ func Marshal(i interface{}) ([]byte, error) {
if v.Kind() != reflect.Ptr && v.CanAddr() {
v = v.Addr()
}
- err := marshalStruct(v, &buff, enc)
+ err := marshalStruct(reflect.ValueOf(i), &buff, enc)
if err != nil {
return nil, err
}
diff --git a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/local/server.go b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/local/server.go
index 04236ff31..41f4373fa 100644
--- a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/local/server.go
+++ b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/local/server.go
@@ -11,7 +11,6 @@ import (
"net/http"
"strconv"
"strings"
- "time"
)
var okPage = []byte(`
@@ -85,7 +84,7 @@ func New(reqState string, port int) (*Server, error) {
serv := &Server{
Addr: fmt.Sprintf("http://localhost:%s", portStr),
- s: &http.Server{Addr: "localhost:0", ReadHeaderTimeout: time.Second},
+ s: &http.Server{Addr: "localhost:0"},
reqState: reqState,
resultCh: make(chan Result, 1),
}
diff --git a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/oauth.go b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/oauth.go
index ebd86e2ba..825f55fb7 100644
--- a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/oauth.go
+++ b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/oauth.go
@@ -7,18 +7,15 @@ import (
"context"
"encoding/json"
"fmt"
- "io"
+ "io/ioutil"
"time"
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/errors"
- "github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/exported"
- internalTime "github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/json/types/time"
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops"
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/accesstokens"
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/authority"
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/wstrust"
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/wstrust/defs"
- "github.com/google/uuid"
)
// ResolveEndpointer contains the methods for resolving authority endpoints.
@@ -76,17 +73,12 @@ func (t *Client) ResolveEndpoints(ctx context.Context, authorityInfo authority.I
return t.Resolver.ResolveEndpoints(ctx, authorityInfo, userPrincipalName)
}
-// AADInstanceDiscovery attempts to discover a tenant endpoint (used in OIDC auth with an authorization endpoint).
-// This is done by AAD which allows for aliasing of tenants (windows.sts.net is the same as login.windows.com).
func (t *Client) AADInstanceDiscovery(ctx context.Context, authorityInfo authority.Info) (authority.InstanceDiscoveryResponse, error) {
return t.Authority.AADInstanceDiscovery(ctx, authorityInfo)
}
// AuthCode returns a token based on an authorization code.
func (t *Client) AuthCode(ctx context.Context, req accesstokens.AuthCodeRequest) (accesstokens.TokenResponse, error) {
- if err := scopeError(req.AuthParams); err != nil {
- return accesstokens.TokenResponse{}, err
- }
if err := t.resolveEndpoint(ctx, &req.AuthParams, ""); err != nil {
return accesstokens.TokenResponse{}, err
}
@@ -100,33 +92,6 @@ func (t *Client) AuthCode(ctx context.Context, req accesstokens.AuthCodeRequest)
// Credential acquires a token from the authority using a client credentials grant.
func (t *Client) Credential(ctx context.Context, authParams authority.AuthParams, cred *accesstokens.Credential) (accesstokens.TokenResponse, error) {
- if cred.TokenProvider != nil {
- now := time.Now()
- scopes := make([]string, len(authParams.Scopes))
- copy(scopes, authParams.Scopes)
- params := exported.TokenProviderParameters{
- Claims: authParams.Claims,
- CorrelationID: uuid.New().String(),
- Scopes: scopes,
- TenantID: authParams.AuthorityInfo.Tenant,
- }
- tr, err := cred.TokenProvider(ctx, params)
- if err != nil {
- if len(scopes) == 0 {
- err = fmt.Errorf("token request had an empty authority.AuthParams.Scopes, which may cause the following error: %w", err)
- return accesstokens.TokenResponse{}, err
- }
- return accesstokens.TokenResponse{}, err
- }
- return accesstokens.TokenResponse{
- AccessToken: tr.AccessToken,
- ExpiresOn: internalTime.DurationTime{
- T: now.Add(time.Duration(tr.ExpiresInSeconds) * time.Second),
- },
- GrantedScopes: accesstokens.Scopes{Slice: authParams.Scopes},
- }, nil
- }
-
if err := t.resolveEndpoint(ctx, &authParams, ""); err != nil {
return accesstokens.TokenResponse{}, err
}
@@ -134,7 +99,7 @@ func (t *Client) Credential(ctx context.Context, authParams authority.AuthParams
if cred.Secret != "" {
return t.AccessTokens.FromClientSecret(ctx, authParams, cred.Secret)
}
- jwt, err := cred.JWT(ctx, authParams)
+ jwt, err := cred.JWT(authParams)
if err != nil {
return accesstokens.TokenResponse{}, err
}
@@ -143,49 +108,32 @@ func (t *Client) Credential(ctx context.Context, authParams authority.AuthParams
// Credential acquires a token from the authority using a client credentials grant.
func (t *Client) OnBehalfOf(ctx context.Context, authParams authority.AuthParams, cred *accesstokens.Credential) (accesstokens.TokenResponse, error) {
- if err := scopeError(authParams); err != nil {
- return accesstokens.TokenResponse{}, err
- }
if err := t.resolveEndpoint(ctx, &authParams, ""); err != nil {
return accesstokens.TokenResponse{}, err
}
if cred.Secret != "" {
return t.AccessTokens.FromUserAssertionClientSecret(ctx, authParams, authParams.UserAssertion, cred.Secret)
+
}
- jwt, err := cred.JWT(ctx, authParams)
- if err != nil {
- return accesstokens.TokenResponse{}, err
- }
- tr, err := t.AccessTokens.FromUserAssertionClientCertificate(ctx, authParams, authParams.UserAssertion, jwt)
+ jwt, err := cred.JWT(authParams)
if err != nil {
return accesstokens.TokenResponse{}, err
}
- return tr, nil
+ return t.AccessTokens.FromUserAssertionClientCertificate(ctx, authParams, authParams.UserAssertion, jwt)
}
func (t *Client) Refresh(ctx context.Context, reqType accesstokens.AppType, authParams authority.AuthParams, cc *accesstokens.Credential, refreshToken accesstokens.RefreshToken) (accesstokens.TokenResponse, error) {
- if err := scopeError(authParams); err != nil {
- return accesstokens.TokenResponse{}, err
- }
if err := t.resolveEndpoint(ctx, &authParams, ""); err != nil {
return accesstokens.TokenResponse{}, err
}
- tr, err := t.AccessTokens.FromRefreshToken(ctx, reqType, authParams, cc, refreshToken.Secret)
- if err != nil {
- return accesstokens.TokenResponse{}, err
- }
- return tr, nil
+ return t.AccessTokens.FromRefreshToken(ctx, reqType, authParams, cc, refreshToken.Secret)
}
// UsernamePassword retrieves a token where a username and password is used. However, if this is
// a user realm of "Federated", this uses SAML tokens. If "Managed", uses normal username/password.
func (t *Client) UsernamePassword(ctx context.Context, authParams authority.AuthParams) (accesstokens.TokenResponse, error) {
- if err := scopeError(authParams); err != nil {
- return accesstokens.TokenResponse{}, err
- }
-
if authParams.AuthorityInfo.AuthorityType == authority.ADFS {
if err := t.resolveEndpoint(ctx, &authParams, authParams.Username); err != nil {
return accesstokens.TokenResponse{}, err
@@ -198,32 +146,22 @@ func (t *Client) UsernamePassword(ctx context.Context, authParams authority.Auth
userRealm, err := t.Authority.UserRealm(ctx, authParams)
if err != nil {
- return accesstokens.TokenResponse{}, fmt.Errorf("problem getting user realm from authority: %w", err)
+ return accesstokens.TokenResponse{}, fmt.Errorf("problem getting user realm(user: %s) from authority: %w", authParams.Username, err)
}
switch userRealm.AccountType {
case authority.Federated:
mexDoc, err := t.WSTrust.Mex(ctx, userRealm.FederationMetadataURL)
if err != nil {
- err = fmt.Errorf("problem getting mex doc from federated url(%s): %w", userRealm.FederationMetadataURL, err)
- return accesstokens.TokenResponse{}, err
+ return accesstokens.TokenResponse{}, fmt.Errorf("problem getting mex doc from federated url(%s): %w", userRealm.FederationMetadataURL, err)
}
saml, err := t.WSTrust.SAMLTokenInfo(ctx, authParams, userRealm.CloudAudienceURN, mexDoc.UsernamePasswordEndpoint)
if err != nil {
- err = fmt.Errorf("problem getting SAML token info: %w", err)
- return accesstokens.TokenResponse{}, err
- }
- tr, err := t.AccessTokens.FromSamlGrant(ctx, authParams, saml)
- if err != nil {
- return accesstokens.TokenResponse{}, err
+ return accesstokens.TokenResponse{}, fmt.Errorf("problem getting SAML token info: %w", err)
}
- return tr, nil
+ return t.AccessTokens.FromSamlGrant(ctx, authParams, saml)
case authority.Managed:
- if len(authParams.Scopes) == 0 {
- err = fmt.Errorf("token request had an empty authority.AuthParams.Scopes, which may cause the following error: %w", err)
- return accesstokens.TokenResponse{}, err
- }
return t.AccessTokens.FromUsernamePassword(ctx, authParams)
}
return accesstokens.TokenResponse{}, errors.New("unknown account type")
@@ -249,6 +187,7 @@ func (d DeviceCode) Token(ctx context.Context) (accesstokens.TokenResponse, erro
}
var cancel context.CancelFunc
+ d.Result.ExpiresOn.Sub(time.Now().UTC())
if deadline, ok := ctx.Deadline(); !ok || d.Result.ExpiresOn.Before(deadline) {
ctx, cancel = context.WithDeadline(ctx, d.Result.ExpiresOn)
} else {
@@ -294,7 +233,7 @@ func isWaitDeviceCodeErr(err error) bool {
}
var dCErr deviceCodeError
defer c.Resp.Body.Close()
- body, err := io.ReadAll(c.Resp.Body)
+ body, err := ioutil.ReadAll(c.Resp.Body)
if err != nil {
return false
}
@@ -311,10 +250,6 @@ func isWaitDeviceCodeErr(err error) bool {
// DeviceCode returns a DeviceCode object that can be used to get the code that must be entered on the second
// device and optionally the token once the code has been entered on the second device.
func (t *Client) DeviceCode(ctx context.Context, authParams authority.AuthParams) (DeviceCode, error) {
- if err := scopeError(authParams); err != nil {
- return DeviceCode{}, err
- }
-
if err := t.resolveEndpoint(ctx, &authParams, ""); err != nil {
return DeviceCode{}, err
}
@@ -335,19 +270,3 @@ func (t *Client) resolveEndpoint(ctx context.Context, authParams *authority.Auth
authParams.Endpoints = endpoints
return nil
}
-
-// scopeError takes an authority.AuthParams and returns an error
-// if len(AuthParams.Scope) == 0.
-func scopeError(a authority.AuthParams) error {
- // TODO(someone): we could look deeper at the message to determine if
- // it's a scope error, but this is a good start.
- /*
- {error":"invalid_scope","error_description":"AADSTS1002012: The provided value for scope
- openid offline_access profile is not valid. Client credential flows must have a scope value
- with /.default suffixed to the resource identifier (application ID URI)...}
- */
- if len(a.Scopes) == 0 {
- return fmt.Errorf("token request had an empty authority.AuthParams.Scopes, which is invalid")
- }
- return nil
-}
diff --git a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/accesstokens/accesstokens.go b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/accesstokens/accesstokens.go
index 003d38648..65831b0b7 100644
--- a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/accesstokens/accesstokens.go
+++ b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/accesstokens/accesstokens.go
@@ -19,18 +19,17 @@ import (
"crypto/sha1"
"crypto/x509"
"encoding/base64"
- "encoding/json"
"fmt"
"net/url"
"strconv"
"strings"
+ "sync"
"time"
- "github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/exported"
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/authority"
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/internal/grant"
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/wstrust"
- "github.com/golang-jwt/jwt/v5"
+ "github.com/golang-jwt/jwt"
"github.com/google/uuid"
)
@@ -44,6 +43,9 @@ const (
password = "password"
)
+// assertionLifetime allows tests to control the expiration time of JWT assertions created by Credential.
+var assertionLifetime = 10 * time.Minute
+
//go:generate stringer -type=AppType
// AppType is whether the authorization code flow is for a public or confidential client.
@@ -88,37 +90,44 @@ type Credential struct {
// Secret contains the credential secret if we are doing auth by secret.
Secret string
- // Cert is the public certificate, if we're authenticating by certificate.
+ // Cert is the public x509 certificate if we are doing any auth other than secret.
Cert *x509.Certificate
- // Key is the private key for signing, if we're authenticating by certificate.
+ // Key is the private key for signing if we are doing any auth other than secret.
Key crypto.PrivateKey
- // X5c is the JWT assertion's x5c header value, required for SN/I authentication.
- X5c []string
-
- // AssertionCallback is a function provided by the application, if we're authenticating by assertion.
- AssertionCallback func(context.Context, exported.AssertionRequestOptions) (string, error)
- // TokenProvider is a function provided by the application that implements custom authentication
- // logic for a confidential client
- TokenProvider func(context.Context, exported.TokenProviderParameters) (exported.TokenProviderResult, error)
+ // mu protects everything below.
+ mu sync.Mutex
+ // Assertion is the signed JWT assertion if we have retrieved it or if it was passed.
+ Assertion string
+ // Expires is when the Assertion expires. Public to allow faking in tests.
+ // Any use outside msal is not supported by a compatibility promise.
+ Expires time.Time
}
// JWT gets the jwt assertion when the credential is not using a secret.
-func (c *Credential) JWT(ctx context.Context, authParams authority.AuthParams) (string, error) {
- if c.AssertionCallback != nil {
- options := exported.AssertionRequestOptions{
- ClientID: authParams.ClientID,
- TokenEndpoint: authParams.Endpoints.TokenEndpoint,
- }
- return c.AssertionCallback(ctx, options)
+func (c *Credential) JWT(authParams authority.AuthParams) (string, error) {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+
+ if c.Expires.After(time.Now()) {
+ return c.Assertion, nil
+ } else if c.Cert == nil || c.Key == nil {
+ // The assertion has expired and this Credential can't generate a new one. The assertion
+ // was presumably provided by the application via confidential.NewCredFromAssertion(). We
+ // return it despite its expiration to maintain the behavior of previous versions, and
+ // because there's no API enabling the application to replace the assertion
+ // (see https://github.com/AzureAD/microsoft-authentication-library-for-go/issues/292).
+ return c.Assertion, nil
}
+ expires := time.Now().Add(assertionLifetime)
+
token := jwt.NewWithClaims(jwt.SigningMethodRS256, jwt.MapClaims{
"aud": authParams.Endpoints.TokenEndpoint,
- "exp": json.Number(strconv.FormatInt(time.Now().Add(10*time.Minute).Unix(), 10)),
+ "exp": strconv.FormatInt(expires.Unix(), 10),
"iss": authParams.ClientID,
"jti": uuid.New().String(),
- "nbf": json.Number(strconv.FormatInt(time.Now().Unix(), 10)),
+ "nbf": strconv.FormatInt(time.Now().Unix(), 10),
"sub": authParams.ClientID,
})
token.Header = map[string]interface{}{
@@ -128,14 +137,16 @@ func (c *Credential) JWT(ctx context.Context, authParams authority.AuthParams) (
}
if authParams.SendX5C {
- token.Header["x5c"] = c.X5c
+ token.Header["x5c"] = []string{base64.StdEncoding.EncodeToString(c.Cert.Raw)}
}
-
- assertion, err := token.SignedString(c.Key)
+ var err error
+ c.Assertion, err = token.SignedString(c.Key)
if err != nil {
return "", fmt.Errorf("unable to sign a JWT token using private key: %w", err)
}
- return assertion, nil
+
+ c.Expires = expires
+ return c.Assertion, nil
}
// thumbprint runs the asn1.Der bytes through sha1 for use in the x5t parameter of JWT.
@@ -157,9 +168,6 @@ type Client struct {
// FromUsernamePassword uses a username and password to get an access token.
func (c Client) FromUsernamePassword(ctx context.Context, authParameters authority.AuthParams) (TokenResponse, error) {
qv := url.Values{}
- if err := addClaims(qv, authParameters); err != nil {
- return TokenResponse{}, err
- }
qv.Set(grantType, grant.Password)
qv.Set(username, authParameters.Username)
qv.Set(password, authParameters.Password)
@@ -205,7 +213,7 @@ func (c Client) FromAuthCode(ctx context.Context, req AuthCodeRequest) (TokenRes
if req.Credential == nil {
return TokenResponse{}, fmt.Errorf("AuthCodeRequest had nil Credential for Confidential app")
}
- qv, err = prepURLVals(ctx, req.Credential, req.AuthParams)
+ qv, err = prepURLVals(req.Credential, req.AuthParams)
if err != nil {
return TokenResponse{}, err
}
@@ -222,9 +230,6 @@ func (c Client) FromAuthCode(ctx context.Context, req AuthCodeRequest) (TokenRes
qv.Set(clientID, req.AuthParams.ClientID)
qv.Set(clientInfo, clientInfoVal)
addScopeQueryParam(qv, req.AuthParams)
- if err := addClaims(qv, req.AuthParams); err != nil {
- return TokenResponse{}, err
- }
return c.doTokenResp(ctx, req.AuthParams, qv)
}
@@ -234,14 +239,11 @@ func (c Client) FromRefreshToken(ctx context.Context, appType AppType, authParam
qv := url.Values{}
if appType == ATConfidential {
var err error
- qv, err = prepURLVals(ctx, cc, authParams)
+ qv, err = prepURLVals(cc, authParams)
if err != nil {
return TokenResponse{}, err
}
}
- if err := addClaims(qv, authParams); err != nil {
- return TokenResponse{}, err
- }
qv.Set(grantType, grant.RefreshToken)
qv.Set(clientID, authParams.ClientID)
qv.Set(clientInfo, clientInfoVal)
@@ -254,9 +256,6 @@ func (c Client) FromRefreshToken(ctx context.Context, appType AppType, authParam
// FromClientSecret uses a client's secret (aka password) to get a new token.
func (c Client) FromClientSecret(ctx context.Context, authParameters authority.AuthParams, clientSecret string) (TokenResponse, error) {
qv := url.Values{}
- if err := addClaims(qv, authParameters); err != nil {
- return TokenResponse{}, err
- }
qv.Set(grantType, grant.ClientCredential)
qv.Set("client_secret", clientSecret)
qv.Set(clientID, authParameters.ClientID)
@@ -271,9 +270,6 @@ func (c Client) FromClientSecret(ctx context.Context, authParameters authority.A
func (c Client) FromAssertion(ctx context.Context, authParameters authority.AuthParams, assertion string) (TokenResponse, error) {
qv := url.Values{}
- if err := addClaims(qv, authParameters); err != nil {
- return TokenResponse{}, err
- }
qv.Set(grantType, grant.ClientCredential)
qv.Set("client_assertion_type", grant.ClientAssertion)
qv.Set("client_assertion", assertion)
@@ -290,9 +286,6 @@ func (c Client) FromAssertion(ctx context.Context, authParameters authority.Auth
func (c Client) FromUserAssertionClientSecret(ctx context.Context, authParameters authority.AuthParams, userAssertion string, clientSecret string) (TokenResponse, error) {
qv := url.Values{}
- if err := addClaims(qv, authParameters); err != nil {
- return TokenResponse{}, err
- }
qv.Set(grantType, grant.JWT)
qv.Set(clientID, authParameters.ClientID)
qv.Set("client_secret", clientSecret)
@@ -306,9 +299,6 @@ func (c Client) FromUserAssertionClientSecret(ctx context.Context, authParameter
func (c Client) FromUserAssertionClientCertificate(ctx context.Context, authParameters authority.AuthParams, userAssertion string, assertion string) (TokenResponse, error) {
qv := url.Values{}
- if err := addClaims(qv, authParameters); err != nil {
- return TokenResponse{}, err
- }
qv.Set(grantType, grant.JWT)
qv.Set("client_assertion_type", grant.ClientAssertion)
qv.Set("client_assertion", assertion)
@@ -323,9 +313,6 @@ func (c Client) FromUserAssertionClientCertificate(ctx context.Context, authPara
func (c Client) DeviceCodeResult(ctx context.Context, authParameters authority.AuthParams) (DeviceCodeResult, error) {
qv := url.Values{}
- if err := addClaims(qv, authParameters); err != nil {
- return DeviceCodeResult{}, err
- }
qv.Set(clientID, authParameters.ClientID)
addScopeQueryParam(qv, authParameters)
@@ -342,9 +329,6 @@ func (c Client) DeviceCodeResult(ctx context.Context, authParameters authority.A
func (c Client) FromDeviceCodeResult(ctx context.Context, authParameters authority.AuthParams, deviceCodeResult DeviceCodeResult) (TokenResponse, error) {
qv := url.Values{}
- if err := addClaims(qv, authParameters); err != nil {
- return TokenResponse{}, err
- }
qv.Set(grantType, grant.DeviceCode)
qv.Set(deviceCode, deviceCodeResult.DeviceCode)
qv.Set(clientID, authParameters.ClientID)
@@ -356,9 +340,6 @@ func (c Client) FromDeviceCodeResult(ctx context.Context, authParameters authori
func (c Client) FromSamlGrant(ctx context.Context, authParameters authority.AuthParams, samlGrant wstrust.SamlTokenInfo) (TokenResponse, error) {
qv := url.Values{}
- if err := addClaims(qv, authParameters); err != nil {
- return TokenResponse{}, err
- }
qv.Set(username, authParameters.Username)
qv.Set(password, authParameters.Password)
qv.Set(clientID, authParameters.ClientID)
@@ -393,14 +374,14 @@ func (c Client) doTokenResp(ctx context.Context, authParams authority.AuthParams
// prepURLVals returns an url.Values that sets various key/values if we are doing secrets
// or JWT assertions.
-func prepURLVals(ctx context.Context, cc *Credential, authParams authority.AuthParams) (url.Values, error) {
+func prepURLVals(cc *Credential, authParams authority.AuthParams) (url.Values, error) {
params := url.Values{}
if cc.Secret != "" {
params.Set("client_secret", cc.Secret)
return params, nil
}
- jwt, err := cc.JWT(ctx, authParams)
+ jwt, err := cc.JWT(authParams)
if err != nil {
return nil, err
}
@@ -436,15 +417,6 @@ func AppendDefaultScopes(authParameters authority.AuthParams) []string {
return scopes
}
-// addClaims adds client capabilities and claims from AuthParams to the given url.Values
-func addClaims(v url.Values, ap authority.AuthParams) error {
- claims, err := ap.MergeCapabilitiesAndClaims()
- if err == nil && claims != "" {
- v.Set("claims", claims)
- }
- return err
-}
-
func addScopeQueryParam(queryParams url.Values, authParameters authority.AuthParams) {
scopes := AppendDefaultScopes(authParameters)
queryParams.Set("scope", strings.Join(scopes, " "))
diff --git a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/accesstokens/tokens.go b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/accesstokens/tokens.go
index 3dd61d5b5..cc8470019 100644
--- a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/accesstokens/tokens.go
+++ b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/accesstokens/tokens.go
@@ -146,6 +146,14 @@ func (c *ClientInfo) UnmarshalJSON(b []byte) error {
return nil
}
+// HomeAccountID creates the home account ID.
+func (c ClientInfo) HomeAccountID() string {
+ if c.UID == "" || c.UTID == "" {
+ return ""
+ }
+ return fmt.Sprintf("%s.%s", c.UID, c.UTID)
+}
+
// Scopes represents scopes in a TokenResponse.
type Scopes struct {
Slice []string
@@ -195,19 +203,6 @@ func (tr *TokenResponse) ComputeScope(authParams authority.AuthParams) {
tr.scopesComputed = true
}
-// HomeAccountID uniquely identifies the authenticated account, if any. It's "" when the token is an app token.
-func (tr *TokenResponse) HomeAccountID() string {
- id := tr.IDToken.Subject
- if uid := tr.ClientInfo.UID; uid != "" {
- utid := tr.ClientInfo.UTID
- if utid == "" {
- utid = uid
- }
- id = fmt.Sprintf("%s.%s", uid, utid)
- }
- return id
-}
-
// Validate validates the TokenResponse has basic valid values. It must be called
// after ComputeScopes() is called.
func (tr *TokenResponse) Validate() error {
@@ -233,7 +228,7 @@ func (tr *TokenResponse) CacheKey(authParams authority.AuthParams) string {
return authParams.AppKey()
}
if authParams.IsConfidentialClient || authParams.AuthorizationType == authority.ATRefreshToken {
- return tr.HomeAccountID()
+ return tr.ClientInfo.HomeAccountID()
}
return ""
}
@@ -296,11 +291,10 @@ func (rt RefreshToken) Key() string {
fourth = rt.ClientID
}
- key := strings.Join(
+ return strings.Join(
[]string{rt.HomeAccountID, rt.Environment, rt.CredentialType, fourth},
shared.CacheKeySeparator,
)
- return strings.ToLower(key)
}
func (rt RefreshToken) GetSecret() string {
diff --git a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/authority/authority.go b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/authority/authority.go
index 7b2ccb4f5..dcc6c53c2 100644
--- a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/authority/authority.go
+++ b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/authority/authority.go
@@ -7,14 +7,12 @@ import (
"context"
"crypto/sha256"
"encoding/base64"
- "encoding/json"
"errors"
"fmt"
- "io"
+ "io/ioutil"
"net/http"
"net/url"
"os"
- "path"
"strings"
"time"
@@ -24,23 +22,14 @@ import (
const (
authorizationEndpoint = "https://%v/%v/oauth2/v2.0/authorize"
instanceDiscoveryEndpoint = "https://%v/common/discovery/instance"
- tenantDiscoveryEndpointWithRegion = "https://%s.%s/%s/v2.0/.well-known/openid-configuration"
+ TenantDiscoveryEndpointWithRegion = "https://%v.r.%v/%v/v2.0/.well-known/openid-configuration"
regionName = "REGION_NAME"
defaultAPIVersion = "2021-10-01"
imdsEndpoint = "http://169.254.169.254/metadata/instance/compute/location?format=text&api-version=" + defaultAPIVersion
+ defaultHost = "login.microsoftonline.com"
autoDetectRegion = "TryAutoDetect"
)
-// These are various hosts that host AAD Instance discovery endpoints.
-const (
- defaultHost = "login.microsoftonline.com"
- loginMicrosoft = "login.microsoft.com"
- loginWindows = "login.windows.net"
- loginSTSWindows = "sts.windows.net"
- loginMicrosoftOnline = defaultHost
-)
-
-// jsonCaller is an interface that allows us to mock the JSONCall method.
type jsonCaller interface {
JSONCall(ctx context.Context, endpoint string, headers http.Header, qv url.Values, body, resp interface{}) error
}
@@ -63,8 +52,6 @@ func TrustedHost(host string) bool {
return false
}
-// OAuthResponseBase is the base JSON return message for an OAuth call.
-// This is embedded in other calls to get the base fields from every response.
type OAuthResponseBase struct {
Error string `json:"error"`
SubError string `json:"suberror"`
@@ -146,7 +133,7 @@ type AuthParams struct {
ClientID string
// Redirecturi is used for auth flows that specify a redirect URI (e.g. local server for interactive auth flow).
Redirecturi string
- HomeAccountID string
+ HomeaccountID string
// Username is the user-name portion for username/password auth flow.
Username string
// Password is the password portion for username/password auth flow.
@@ -169,17 +156,6 @@ type AuthParams struct {
SendX5C bool
// UserAssertion is the access token used to acquire token on behalf of user
UserAssertion string
- // Capabilities the client will include with each token request, for example "CP1".
- // Call [NewClientCapabilities] to construct a value for this field.
- Capabilities ClientCapabilities
- // Claims required for an access token to satisfy a conditional access policy
- Claims string
- // KnownAuthorityHosts don't require metadata discovery because they're known to the user
- KnownAuthorityHosts []string
- // LoginHint is a username with which to pre-populate account selection during interactive auth
- LoginHint string
- // DomainHint is a directive that can be used to accelerate the user to their federated IdP sign-in page
- DomainHint string
}
// NewAuthParams creates an authorization parameters object.
@@ -191,127 +167,15 @@ func NewAuthParams(clientID string, authorityInfo Info) AuthParams {
}
}
-// WithTenant returns a copy of the AuthParams having the specified tenant ID. If the given
-// ID is empty, the copy is identical to the original. This function returns an error in
-// several cases:
-// - ID isn't specific (for example, it's "common")
-// - ID is non-empty and the authority doesn't support tenants (for example, it's an ADFS authority)
-// - the client is configured to authenticate only Microsoft accounts via the "consumers" endpoint
-// - the resulting authority URL is invalid
-func (p AuthParams) WithTenant(ID string) (AuthParams, error) {
- switch ID {
- case "", p.AuthorityInfo.Tenant:
- // keep the default tenant because the caller didn't override it
- return p, nil
- case "common", "consumers", "organizations":
- if p.AuthorityInfo.AuthorityType == AAD {
- return p, fmt.Errorf(`tenant ID must be a specific tenant, not "%s"`, ID)
- }
- // else we'll return a better error below
- }
- if p.AuthorityInfo.AuthorityType != AAD {
- return p, errors.New("the authority doesn't support tenants")
- }
- if p.AuthorityInfo.Tenant == "consumers" {
- return p, errors.New(`client is configured to authenticate only personal Microsoft accounts, via the "consumers" endpoint`)
- }
- authority := "https://" + path.Join(p.AuthorityInfo.Host, ID)
- info, err := NewInfoFromAuthorityURI(authority, p.AuthorityInfo.ValidateAuthority, p.AuthorityInfo.InstanceDiscoveryDisabled)
- if err == nil {
- info.Region = p.AuthorityInfo.Region
- p.AuthorityInfo = info
- }
- return p, err
-}
-
-// MergeCapabilitiesAndClaims combines client capabilities and challenge claims into a value suitable for an authentication request's "claims" parameter.
-func (p AuthParams) MergeCapabilitiesAndClaims() (string, error) {
- claims := p.Claims
- if len(p.Capabilities.asMap) > 0 {
- if claims == "" {
- // without claims the result is simply the capabilities
- return p.Capabilities.asJSON, nil
- }
- // Otherwise, merge claims and capabilties into a single JSON object.
- // We handle the claims challenge as a map because we don't know its structure.
- var challenge map[string]any
- if err := json.Unmarshal([]byte(claims), &challenge); err != nil {
- return "", fmt.Errorf(`claims must be JSON. Are they base64 encoded? json.Unmarshal returned "%v"`, err)
- }
- if err := merge(p.Capabilities.asMap, challenge); err != nil {
- return "", err
- }
- b, err := json.Marshal(challenge)
- if err != nil {
- return "", err
- }
- claims = string(b)
- }
- return claims, nil
-}
-
-// merges a into b without overwriting b's values. Returns an error when a and b share a key for which either has a non-object value.
-func merge(a, b map[string]any) error {
- for k, av := range a {
- if bv, ok := b[k]; !ok {
- // b doesn't contain this key => simply set it to a's value
- b[k] = av
- } else {
- // b does contain this key => recursively merge a[k] into b[k], provided both are maps. If a[k] or b[k] isn't
- // a map, return an error because merging would overwrite some value in b. Errors shouldn't occur in practice
- // because the challenge will be from AAD, which knows the capabilities format.
- if A, ok := av.(map[string]any); ok {
- if B, ok := bv.(map[string]any); ok {
- return merge(A, B)
- } else {
- // b[k] isn't a map
- return errors.New("challenge claims conflict with client capabilities")
- }
- } else {
- // a[k] isn't a map
- return errors.New("challenge claims conflict with client capabilities")
- }
- }
- }
- return nil
-}
-
-// ClientCapabilities stores capabilities in the formats used by AuthParams.MergeCapabilitiesAndClaims.
-// [NewClientCapabilities] precomputes these representations because capabilities are static for the
-// lifetime of a client and are included with every authentication request i.e., these computations
-// always have the same result and would otherwise have to be repeated for every request.
-type ClientCapabilities struct {
- // asJSON is for the common case: adding the capabilities to an auth request with no challenge claims
- asJSON string
- // asMap is for merging the capabilities with challenge claims
- asMap map[string]any
-}
-
-func NewClientCapabilities(capabilities []string) (ClientCapabilities, error) {
- c := ClientCapabilities{}
- var err error
- if len(capabilities) > 0 {
- cpbs := make([]string, len(capabilities))
- for i := 0; i < len(cpbs); i++ {
- cpbs[i] = fmt.Sprintf(`"%s"`, capabilities[i])
- }
- c.asJSON = fmt.Sprintf(`{"access_token":{"xms_cc":{"values":[%s]}}}`, strings.Join(cpbs, ","))
- // note our JSON is valid but we can't stop users breaking it with garbage like "}"
- err = json.Unmarshal([]byte(c.asJSON), &c.asMap)
- }
- return c, err
-}
-
// Info consists of information about the authority.
type Info struct {
- Host string
- CanonicalAuthorityURI string
- AuthorityType string
- UserRealmURIPrefix string
- ValidateAuthority bool
- Tenant string
- Region string
- InstanceDiscoveryDisabled bool
+ Host string
+ CanonicalAuthorityURI string
+ AuthorityType string
+ UserRealmURIPrefix string
+ ValidateAuthority bool
+ Tenant string
+ Region string
}
func firstPathSegment(u *url.URL) (string, error) {
@@ -320,34 +184,39 @@ func firstPathSegment(u *url.URL) (string, error) {
return pathParts[1], nil
}
- return "", errors.New(`authority must be an https URL such as "https://login.microsoftonline.com/"`)
+ return "", errors.New("authority does not have two segments")
}
// NewInfoFromAuthorityURI creates an AuthorityInfo instance from the authority URL provided.
-func NewInfoFromAuthorityURI(authority string, validateAuthority bool, instanceDiscoveryDisabled bool) (Info, error) {
- u, err := url.Parse(strings.ToLower(authority))
- if err != nil || u.Scheme != "https" {
- return Info{}, errors.New(`authority must be an https URL such as "https://login.microsoftonline.com/"`)
+func NewInfoFromAuthorityURI(authorityURI string, validateAuthority bool) (Info, error) {
+ authorityURI = strings.ToLower(authorityURI)
+ var authorityType string
+ u, err := url.Parse(authorityURI)
+ if err != nil {
+ return Info{}, fmt.Errorf("authorityURI passed could not be parsed: %w", err)
+ }
+ if u.Scheme != "https" {
+ return Info{}, fmt.Errorf("authorityURI(%s) must have scheme https", authorityURI)
}
tenant, err := firstPathSegment(u)
- if err != nil {
- return Info{}, err
- }
- authorityType := AAD
if tenant == "adfs" {
authorityType = ADFS
+ } else {
+ authorityType = AAD
+ }
+
+ if err != nil {
+ return Info{}, err
}
- // u.Host includes the port, if any, which is required for private cloud deployments
return Info{
- Host: u.Host,
- CanonicalAuthorityURI: fmt.Sprintf("https://%v/%v/", u.Host, tenant),
- AuthorityType: authorityType,
- UserRealmURIPrefix: fmt.Sprintf("https://%v/common/userrealm/", u.Hostname()),
- ValidateAuthority: validateAuthority,
- Tenant: tenant,
- InstanceDiscoveryDisabled: instanceDiscoveryDisabled,
+ Host: u.Hostname(),
+ CanonicalAuthorityURI: fmt.Sprintf("https://%v/%v/", u.Hostname(), tenant),
+ AuthorityType: authorityType,
+ UserRealmURIPrefix: fmt.Sprintf("https://%v/common/userrealm/", u.Hostname()),
+ ValidateAuthority: validateAuthority,
+ Tenant: tenant,
}, nil
}
@@ -374,7 +243,7 @@ const (
Managed UserRealmAccountType = "Managed"
)
-// UserRealm is used for the username password request to determine user type
+//UserRealm is used for the username password request to determine user type
type UserRealm struct {
AccountType UserRealmAccountType `json:"account_type"`
DomainName string `json:"domain_name"`
@@ -453,8 +322,6 @@ func (c Client) GetTenantDiscoveryResponse(ctx context.Context, openIDConfigurat
return resp, err
}
-// AADInstanceDiscovery attempts to discover a tenant endpoint (used in OIDC auth with an authorization endpoint).
-// This is done by AAD which allows for aliasing of tenants (windows.sts.net is the same as login.windows.com).
func (c Client) AADInstanceDiscovery(ctx context.Context, authorityInfo Info) (InstanceDiscoveryResponse, error) {
region := ""
var err error
@@ -465,13 +332,7 @@ func (c Client) AADInstanceDiscovery(ctx context.Context, authorityInfo Info) (I
region = detectRegion(ctx)
}
if region != "" {
- environment := authorityInfo.Host
- switch environment {
- case loginMicrosoft, loginWindows, loginSTSWindows, defaultHost:
- environment = loginMicrosoft
- }
-
- resp.TenantDiscoveryEndpoint = fmt.Sprintf(tenantDiscoveryEndpointWithRegion, region, environment, authorityInfo.Tenant)
+ resp.TenantDiscoveryEndpoint = fmt.Sprintf(TenantDiscoveryEndpointWithRegion, region, authorityInfo.Host, authorityInfo.Tenant)
metadata := InstanceDiscoveryMetadata{
PreferredNetwork: fmt.Sprintf("%v.%v", region, authorityInfo.Host),
PreferredCache: authorityInfo.Host,
@@ -517,7 +378,7 @@ func detectRegion(ctx context.Context) string {
}
}
defer resp.Body.Close()
- response, err := io.ReadAll(resp.Body)
+ response, err := ioutil.ReadAll(resp.Body)
if err != nil {
return ""
}
@@ -532,7 +393,7 @@ func (a *AuthParams) CacheKey(isAppCache bool) string {
return a.AppKey()
}
if a.AuthorizationType == ATRefreshToken || a.AuthorizationType == AccountByID {
- return a.HomeAccountID
+ return a.HomeaccountID
}
return ""
}
diff --git a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/internal/comm/comm.go b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/internal/comm/comm.go
index 7d9ec7cd3..0620b3e41 100644
--- a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/internal/comm/comm.go
+++ b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/internal/comm/comm.go
@@ -11,6 +11,7 @@ import (
"encoding/xml"
"fmt"
"io"
+ "io/ioutil"
"net/http"
"net/url"
"reflect"
@@ -88,7 +89,7 @@ func (c *Client) JSONCall(ctx context.Context, endpoint string, headers http.Hea
if err != nil {
return fmt.Errorf("bug: conn.Call(): could not marshal the body object: %w", err)
}
- req.Body = io.NopCloser(bytes.NewBuffer(data))
+ req.Body = ioutil.NopCloser(bytes.NewBuffer(data))
req.Method = http.MethodPost
}
@@ -162,7 +163,7 @@ func (c *Client) xmlCall(ctx context.Context, u *url.URL, headers http.Header, b
if len(body) > 0 {
req.Method = http.MethodPost
- req.Body = io.NopCloser(strings.NewReader(body))
+ req.Body = ioutil.NopCloser(strings.NewReader(body))
}
data, err := c.do(ctx, req)
@@ -200,9 +201,9 @@ func (c *Client) URLFormCall(ctx context.Context, endpoint string, qv url.Values
URL: u,
Header: headers,
ContentLength: int64(len(enc)),
- Body: io.NopCloser(strings.NewReader(enc)),
+ Body: ioutil.NopCloser(strings.NewReader(enc)),
GetBody: func() (io.ReadCloser, error) {
- return io.NopCloser(strings.NewReader(enc)), nil
+ return ioutil.NopCloser(strings.NewReader(enc)), nil
},
}
@@ -247,7 +248,7 @@ func (c *Client) do(ctx context.Context, req *http.Request) ([]byte, error) {
if err != nil {
return nil, fmt.Errorf("could not read the body of an HTTP Response: %w", err)
}
- reply.Body = io.NopCloser(bytes.NewBuffer(data))
+ reply.Body = ioutil.NopCloser(bytes.NewBuffer(data))
// NOTE: This doesn't happen immediately after the call so that we can get an error message
// from the server and include it in our error.
@@ -296,7 +297,7 @@ func (c *Client) readBody(resp *http.Response) ([]byte, error) {
default:
return nil, fmt.Errorf("bug: comm.Client.JSONCall(): content was send with unsupported content-encoding %s", resp.Header.Get("Content-Encoding"))
}
- return io.ReadAll(reader)
+ return ioutil.ReadAll(reader)
}
var testID string
diff --git a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/ops.go b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/ops.go
index 1f9c543fa..01060ac62 100644
--- a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/ops.go
+++ b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/ops.go
@@ -6,7 +6,6 @@ Package ops provides operations to various backend services using REST clients.
The REST type provides several clients that can be used to communicate to backends.
Usage is simple:
-
rest := ops.New()
// Creates an authority client and calls the UserRealm() method.
diff --git a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/resolvers.go b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/resolvers.go
index 0ade41179..893ef4814 100644
--- a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/resolvers.go
+++ b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/resolvers.go
@@ -46,6 +46,9 @@ func newAuthorityEndpoint(rest *ops.REST) *authorityEndpoint {
// ResolveEndpoints gets the authorization and token endpoints and creates an AuthorityEndpoints instance
func (m *authorityEndpoint) ResolveEndpoints(ctx context.Context, authorityInfo authority.Info, userPrincipalName string) (authority.Endpoints, error) {
+ if authorityInfo.AuthorityType == ADFS && len(userPrincipalName) == 0 {
+ return authority.Endpoints{}, errors.New("UPN required for authority validation for ADFS")
+ }
if endpoints, found := m.cachedEndpoints(authorityInfo, userPrincipalName); found {
return endpoints, nil
diff --git a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/options/options.go b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/options/options.go
deleted file mode 100644
index 4561d72db..000000000
--- a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/options/options.go
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT license.
-
-package options
-
-import (
- "errors"
- "fmt"
-)
-
-// CallOption implements an optional argument to a method call. See
-// https://blog.devgenius.io/go-call-option-that-can-be-used-with-multiple-methods-6c81734f3dbe
-// for an explanation of the usage pattern.
-type CallOption interface {
- Do(any) error
- callOption()
-}
-
-// ApplyOptions applies all the callOptions to options. options must be a pointer to a struct and
-// callOptions must be a list of objects that implement CallOption.
-func ApplyOptions[O, C any](options O, callOptions []C) error {
- for _, o := range callOptions {
- if t, ok := any(o).(CallOption); !ok {
- return fmt.Errorf("unexpected option type %T", o)
- } else if err := t.Do(options); err != nil {
- return err
- }
- }
- return nil
-}
-
-// NewCallOption returns a new CallOption whose Do() method calls function "f".
-func NewCallOption(f func(any) error) CallOption {
- if f == nil {
- // This isn't a practical concern because only an MSAL maintainer can get
- // us here, by implementing a do-nothing option. But if someone does that,
- // the below ensures the method invoked with the option returns an error.
- return callOption(func(any) error {
- return errors.New("invalid option: missing implementation")
- })
- }
- return callOption(f)
-}
-
-// callOption is an adapter for a function to a CallOption
-type callOption func(any) error
-
-func (c callOption) Do(a any) error {
- return c(a)
-}
-
-func (callOption) callOption() {}
diff --git a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/shared/shared.go b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/shared/shared.go
index d8ab71356..f7e12a71b 100644
--- a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/shared/shared.go
+++ b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/shared/shared.go
@@ -46,8 +46,7 @@ func NewAccount(homeAccountID, env, realm, localAccountID, authorityType, userna
// Key creates the key for storing accounts in the cache.
func (acc Account) Key() string {
- key := strings.Join([]string{acc.HomeAccountID, acc.Environment, acc.Realm}, CacheKeySeparator)
- return strings.ToLower(key)
+ return strings.Join([]string{acc.HomeAccountID, acc.Environment, acc.Realm}, CacheKeySeparator)
}
// IsZero checks the zero value of account.
diff --git a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/version/version.go b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/version/version.go
index 2ac2d09e4..e50d5e97f 100644
--- a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/version/version.go
+++ b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/version/version.go
@@ -5,4 +5,4 @@
package version
// Version is the version of this client package that is communicated to the server.
-const Version = "1.1.1"
+const Version = "0.5.1"
diff --git a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/public/public.go b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/public/public.go
index 88b217ded..19118c25a 100644
--- a/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/public/public.go
+++ b/vendor/github.com/AzureAD/microsoft-authentication-library-for-go/apps/public/public.go
@@ -24,10 +24,8 @@ import (
"crypto/rand"
"crypto/sha256"
"encoding/base64"
- "errors"
"fmt"
"net/url"
- "reflect"
"strconv"
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/cache"
@@ -37,7 +35,6 @@ import (
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops"
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/accesstokens"
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/oauth/ops/authority"
- "github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/options"
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/internal/shared"
"github.com/google/uuid"
"github.com/pkg/browser"
@@ -49,19 +46,23 @@ type AuthResult = base.AuthResult
type Account = shared.Account
-var errNoAccount = errors.New("no account was specified with public.WithAccount(), or the specified account is invalid")
+// Options configures the Client's behavior.
+type Options struct {
+ // Accessor controls cache persistence. By default there is no cache persistence.
+ // This can be set with the WithCache() option.
+ Accessor cache.ExportReplace
-// clientOptions configures the Client's behavior.
-type clientOptions struct {
- accessor cache.ExportReplace
- authority string
- capabilities []string
- disableInstanceDiscovery bool
- httpClient ops.HTTPClient
+ // The host of the Azure Active Directory authority. The default is https://login.microsoftonline.com/common.
+ // This can be changed with the WithAuthority() option.
+ Authority string
+
+ // The HTTP client used for making requests.
+ // It defaults to a shared http.Client.
+ HTTPClient ops.HTTPClient
}
-func (p *clientOptions) validate() error {
- u, err := url.Parse(p.authority)
+func (p *Options) validate() error {
+ u, err := url.Parse(p.Authority)
if err != nil {
return fmt.Errorf("Authority options cannot be URL parsed: %w", err)
}
@@ -72,42 +73,26 @@ func (p *clientOptions) validate() error {
}
// Option is an optional argument to the New constructor.
-type Option func(o *clientOptions)
+type Option func(o *Options)
// WithAuthority allows for a custom authority to be set. This must be a valid https url.
func WithAuthority(authority string) Option {
- return func(o *clientOptions) {
- o.authority = authority
+ return func(o *Options) {
+ o.Authority = authority
}
}
-// WithCache provides an accessor that will read and write authentication data to an externally managed cache.
+// WithCache allows you to set some type of cache for storing authentication tokens.
func WithCache(accessor cache.ExportReplace) Option {
- return func(o *clientOptions) {
- o.accessor = accessor
- }
-}
-
-// WithClientCapabilities allows configuring one or more client capabilities such as "CP1"
-func WithClientCapabilities(capabilities []string) Option {
- return func(o *clientOptions) {
- // there's no danger of sharing the slice's underlying memory with the application because
- // this slice is simply passed to base.WithClientCapabilities, which copies its data
- o.capabilities = capabilities
+ return func(o *Options) {
+ o.Accessor = accessor
}
}
// WithHTTPClient allows for a custom HTTP client to be set.
func WithHTTPClient(httpClient ops.HTTPClient) Option {
- return func(o *clientOptions) {
- o.httpClient = httpClient
- }
-}
-
-// WithInstanceDiscovery set to false to disable authority validation (to support private cloud scenarios)
-func WithInstanceDiscovery(enabled bool) Option {
- return func(o *clientOptions) {
- o.disableInstanceDiscovery = !enabled
+ return func(o *Options) {
+ o.HTTPClient = httpClient
}
}
@@ -119,9 +104,9 @@ type Client struct {
// New is the constructor for Client.
func New(clientID string, options ...Option) (Client, error) {
- opts := clientOptions{
- authority: base.AuthorityPublicCloud,
- httpClient: shared.DefaultClient,
+ opts := Options{
+ Authority: base.AuthorityPublicCloud,
+ HTTPClient: shared.DefaultClient,
}
for _, o := range options {
@@ -131,216 +116,58 @@ func New(clientID string, options ...Option) (Client, error) {
return Client{}, err
}
- base, err := base.New(clientID, opts.authority, oauth.New(opts.httpClient), base.WithCacheAccessor(opts.accessor), base.WithClientCapabilities(opts.capabilities), base.WithInstanceDiscovery(!opts.disableInstanceDiscovery))
+ base, err := base.New(clientID, opts.Authority, oauth.New(opts.HTTPClient), base.WithCacheAccessor(opts.Accessor))
if err != nil {
return Client{}, err
}
return Client{base}, nil
}
-// authCodeURLOptions contains options for AuthCodeURL
-type authCodeURLOptions struct {
- claims, loginHint, tenantID, domainHint string
-}
-
-// AuthCodeURLOption is implemented by options for AuthCodeURL
-type AuthCodeURLOption interface {
- authCodeURLOption()
-}
-
-// AuthCodeURL creates a URL used to acquire an authorization code.
-//
-// Options: [WithClaims], [WithDomainHint], [WithLoginHint], [WithTenantID]
-func (pca Client) AuthCodeURL(ctx context.Context, clientID, redirectURI string, scopes []string, opts ...AuthCodeURLOption) (string, error) {
- o := authCodeURLOptions{}
- if err := options.ApplyOptions(&o, opts); err != nil {
- return "", err
- }
- ap, err := pca.base.AuthParams.WithTenant(o.tenantID)
- if err != nil {
- return "", err
- }
- ap.Claims = o.claims
- ap.LoginHint = o.loginHint
- ap.DomainHint = o.domainHint
- return pca.base.AuthCodeURL(ctx, clientID, redirectURI, scopes, ap)
-}
-
-// WithClaims sets additional claims to request for the token, such as those required by conditional access policies.
-// Use this option when Azure AD returned a claims challenge for a prior request. The argument must be decoded.
-// This option is valid for any token acquisition method.
-func WithClaims(claims string) interface {
- AcquireByAuthCodeOption
- AcquireByDeviceCodeOption
- AcquireByUsernamePasswordOption
- AcquireInteractiveOption
- AcquireSilentOption
- AuthCodeURLOption
- options.CallOption
-} {
- return struct {
- AcquireByAuthCodeOption
- AcquireByDeviceCodeOption
- AcquireByUsernamePasswordOption
- AcquireInteractiveOption
- AcquireSilentOption
- AuthCodeURLOption
- options.CallOption
- }{
- CallOption: options.NewCallOption(
- func(a any) error {
- switch t := a.(type) {
- case *acquireTokenByAuthCodeOptions:
- t.claims = claims
- case *acquireTokenByDeviceCodeOptions:
- t.claims = claims
- case *acquireTokenByUsernamePasswordOptions:
- t.claims = claims
- case *acquireTokenSilentOptions:
- t.claims = claims
- case *authCodeURLOptions:
- t.claims = claims
- case *interactiveAuthOptions:
- t.claims = claims
- default:
- return fmt.Errorf("unexpected options type %T", a)
- }
- return nil
- },
- ),
- }
+// CreateAuthCodeURL creates a URL used to acquire an authorization code.
+func (pca Client) CreateAuthCodeURL(ctx context.Context, clientID, redirectURI string, scopes []string) (string, error) {
+ return pca.base.AuthCodeURL(ctx, clientID, redirectURI, scopes, pca.base.AuthParams)
}
-// WithTenantID specifies a tenant for a single authentication. It may be different than the tenant set in [New] by [WithAuthority].
-// This option is valid for any token acquisition method.
-func WithTenantID(tenantID string) interface {
- AcquireByAuthCodeOption
- AcquireByDeviceCodeOption
- AcquireByUsernamePasswordOption
- AcquireInteractiveOption
- AcquireSilentOption
- AuthCodeURLOption
- options.CallOption
-} {
- return struct {
- AcquireByAuthCodeOption
- AcquireByDeviceCodeOption
- AcquireByUsernamePasswordOption
- AcquireInteractiveOption
- AcquireSilentOption
- AuthCodeURLOption
- options.CallOption
- }{
- CallOption: options.NewCallOption(
- func(a any) error {
- switch t := a.(type) {
- case *acquireTokenByAuthCodeOptions:
- t.tenantID = tenantID
- case *acquireTokenByDeviceCodeOptions:
- t.tenantID = tenantID
- case *acquireTokenByUsernamePasswordOptions:
- t.tenantID = tenantID
- case *acquireTokenSilentOptions:
- t.tenantID = tenantID
- case *authCodeURLOptions:
- t.tenantID = tenantID
- case *interactiveAuthOptions:
- t.tenantID = tenantID
- default:
- return fmt.Errorf("unexpected options type %T", a)
- }
- return nil
- },
- ),
- }
-}
-
-// acquireTokenSilentOptions are all the optional settings to an AcquireTokenSilent() call.
+// AcquireTokenSilentOptions are all the optional settings to an AcquireTokenSilent() call.
// These are set by using various AcquireTokenSilentOption functions.
-type acquireTokenSilentOptions struct {
- account Account
- claims, tenantID string
+type AcquireTokenSilentOptions struct {
+ // Account represents the account to use. To set, use the WithSilentAccount() option.
+ Account Account
}
-// AcquireSilentOption is implemented by options for AcquireTokenSilent
-type AcquireSilentOption interface {
- acquireSilentOption()
-}
+// AcquireTokenSilentOption changes options inside AcquireTokenSilentOptions used in .AcquireTokenSilent().
+type AcquireTokenSilentOption func(a *AcquireTokenSilentOptions)
// WithSilentAccount uses the passed account during an AcquireTokenSilent() call.
-func WithSilentAccount(account Account) interface {
- AcquireSilentOption
- options.CallOption
-} {
- return struct {
- AcquireSilentOption
- options.CallOption
- }{
- CallOption: options.NewCallOption(
- func(a any) error {
- switch t := a.(type) {
- case *acquireTokenSilentOptions:
- t.account = account
- default:
- return fmt.Errorf("unexpected options type %T", a)
- }
- return nil
- },
- ),
+func WithSilentAccount(account Account) AcquireTokenSilentOption {
+ return func(a *AcquireTokenSilentOptions) {
+ a.Account = account
}
}
// AcquireTokenSilent acquires a token from either the cache or using a refresh token.
-//
-// Options: [WithClaims], [WithSilentAccount], [WithTenantID]
-func (pca Client) AcquireTokenSilent(ctx context.Context, scopes []string, opts ...AcquireSilentOption) (AuthResult, error) {
- o := acquireTokenSilentOptions{}
- if err := options.ApplyOptions(&o, opts); err != nil {
- return AuthResult{}, err
- }
- // an account is required to find user tokens in the cache
- if reflect.ValueOf(o.account).IsZero() {
- return AuthResult{}, errNoAccount
+func (pca Client) AcquireTokenSilent(ctx context.Context, scopes []string, options ...AcquireTokenSilentOption) (AuthResult, error) {
+ opts := AcquireTokenSilentOptions{}
+ for _, o := range options {
+ o(&opts)
}
silentParameters := base.AcquireTokenSilentParameters{
Scopes: scopes,
- Account: o.account,
- Claims: o.claims,
+ Account: opts.Account,
RequestType: accesstokens.ATPublic,
IsAppCache: false,
- TenantID: o.tenantID,
}
return pca.base.AcquireTokenSilent(ctx, silentParameters)
}
-// acquireTokenByUsernamePasswordOptions contains optional configuration for AcquireTokenByUsernamePassword
-type acquireTokenByUsernamePasswordOptions struct {
- claims, tenantID string
-}
-
-// AcquireByUsernamePasswordOption is implemented by options for AcquireTokenByUsernamePassword
-type AcquireByUsernamePasswordOption interface {
- acquireByUsernamePasswordOption()
-}
-
// AcquireTokenByUsernamePassword acquires a security token from the authority, via Username/Password Authentication.
// NOTE: this flow is NOT recommended.
-//
-// Options: [WithClaims], [WithTenantID]
-func (pca Client) AcquireTokenByUsernamePassword(ctx context.Context, scopes []string, username, password string, opts ...AcquireByUsernamePasswordOption) (AuthResult, error) {
- o := acquireTokenByUsernamePasswordOptions{}
- if err := options.ApplyOptions(&o, opts); err != nil {
- return AuthResult{}, err
- }
- authParams, err := pca.base.AuthParams.WithTenant(o.tenantID)
- if err != nil {
- return AuthResult{}, err
- }
+func (pca Client) AcquireTokenByUsernamePassword(ctx context.Context, scopes []string, username string, password string) (AuthResult, error) {
+ authParams := pca.base.AuthParams
authParams.Scopes = scopes
authParams.AuthorizationType = authority.ATUsernamePassword
- authParams.Claims = o.claims
authParams.Username = username
authParams.Password = password
@@ -376,32 +203,12 @@ func (d DeviceCode) AuthenticationResult(ctx context.Context) (AuthResult, error
return d.client.base.AuthResultFromToken(ctx, d.authParams, token, true)
}
-// acquireTokenByDeviceCodeOptions contains optional configuration for AcquireTokenByDeviceCode
-type acquireTokenByDeviceCodeOptions struct {
- claims, tenantID string
-}
-
-// AcquireByDeviceCodeOption is implemented by options for AcquireTokenByDeviceCode
-type AcquireByDeviceCodeOption interface {
- acquireByDeviceCodeOptions()
-}
-
// AcquireTokenByDeviceCode acquires a security token from the authority, by acquiring a device code and using that to acquire the token.
// Users need to create an AcquireTokenDeviceCodeParameters instance and pass it in.
-//
-// Options: [WithClaims], [WithTenantID]
-func (pca Client) AcquireTokenByDeviceCode(ctx context.Context, scopes []string, opts ...AcquireByDeviceCodeOption) (DeviceCode, error) {
- o := acquireTokenByDeviceCodeOptions{}
- if err := options.ApplyOptions(&o, opts); err != nil {
- return DeviceCode{}, err
- }
- authParams, err := pca.base.AuthParams.WithTenant(o.tenantID)
- if err != nil {
- return DeviceCode{}, err
- }
+func (pca Client) AcquireTokenByDeviceCode(ctx context.Context, scopes []string) (DeviceCode, error) {
+ authParams := pca.base.AuthParams
authParams.Scopes = scopes
authParams.AuthorizationType = authority.ATDeviceCode
- authParams.Claims = o.claims
dc, err := pca.base.Token.DeviceCode(ctx, authParams)
if err != nil {
@@ -411,57 +218,35 @@ func (pca Client) AcquireTokenByDeviceCode(ctx context.Context, scopes []string,
return DeviceCode{Result: dc.Result, authParams: authParams, client: pca, dc: dc}, nil
}
-// acquireTokenByAuthCodeOptions contains the optional parameters used to acquire an access token using the authorization code flow.
-type acquireTokenByAuthCodeOptions struct {
- challenge, claims, tenantID string
+// AcquireTokenByAuthCodeOptions contains the optional parameters used to acquire an access token using the authorization code flow.
+type AcquireTokenByAuthCodeOptions struct {
+ Challenge string
}
-// AcquireByAuthCodeOption is implemented by options for AcquireTokenByAuthCode
-type AcquireByAuthCodeOption interface {
- acquireByAuthCodeOption()
-}
+// AcquireTokenByAuthCodeOption changes options inside AcquireTokenByAuthCodeOptions used in .AcquireTokenByAuthCode().
+type AcquireTokenByAuthCodeOption func(a *AcquireTokenByAuthCodeOptions)
// WithChallenge allows you to provide a code for the .AcquireTokenByAuthCode() call.
-func WithChallenge(challenge string) interface {
- AcquireByAuthCodeOption
- options.CallOption
-} {
- return struct {
- AcquireByAuthCodeOption
- options.CallOption
- }{
- CallOption: options.NewCallOption(
- func(a any) error {
- switch t := a.(type) {
- case *acquireTokenByAuthCodeOptions:
- t.challenge = challenge
- default:
- return fmt.Errorf("unexpected options type %T", a)
- }
- return nil
- },
- ),
+func WithChallenge(challenge string) AcquireTokenByAuthCodeOption {
+ return func(a *AcquireTokenByAuthCodeOptions) {
+ a.Challenge = challenge
}
}
// AcquireTokenByAuthCode is a request to acquire a security token from the authority, using an authorization code.
// The specified redirect URI must be the same URI that was used when the authorization code was requested.
-//
-// Options: [WithChallenge], [WithClaims], [WithTenantID]
-func (pca Client) AcquireTokenByAuthCode(ctx context.Context, code string, redirectURI string, scopes []string, opts ...AcquireByAuthCodeOption) (AuthResult, error) {
- o := acquireTokenByAuthCodeOptions{}
- if err := options.ApplyOptions(&o, opts); err != nil {
- return AuthResult{}, err
+func (pca Client) AcquireTokenByAuthCode(ctx context.Context, code string, redirectURI string, scopes []string, options ...AcquireTokenByAuthCodeOption) (AuthResult, error) {
+ opts := AcquireTokenByAuthCodeOptions{}
+ for _, o := range options {
+ o(&opts)
}
params := base.AcquireTokenAuthCodeParameters{
Scopes: scopes,
Code: code,
- Challenge: o.challenge,
- Claims: o.claims,
+ Challenge: opts.Challenge,
AppType: accesstokens.ATPublic,
RedirectURI: redirectURI,
- TenantID: o.tenantID,
}
return pca.base.AcquireTokenByAuthCode(ctx, params)
@@ -469,135 +254,39 @@ func (pca Client) AcquireTokenByAuthCode(ctx context.Context, code string, redir
// Accounts gets all the accounts in the token cache.
// If there are no accounts in the cache the returned slice is empty.
-func (pca Client) Accounts(ctx context.Context) ([]Account, error) {
- return pca.base.AllAccounts(ctx)
+func (pca Client) Accounts() []Account {
+ return pca.base.AllAccounts()
}
// RemoveAccount signs the account out and forgets account from token cache.
-func (pca Client) RemoveAccount(ctx context.Context, account Account) error {
- return pca.base.RemoveAccount(ctx, account)
-}
-
-// interactiveAuthOptions contains the optional parameters used to acquire an access token for interactive auth code flow.
-type interactiveAuthOptions struct {
- claims, domainHint, loginHint, redirectURI, tenantID string
- openURL func(url string) error
-}
-
-// AcquireInteractiveOption is implemented by options for AcquireTokenInteractive
-type AcquireInteractiveOption interface {
- acquireInteractiveOption()
-}
-
-// WithLoginHint pre-populates the login prompt with a username.
-func WithLoginHint(username string) interface {
- AcquireInteractiveOption
- AuthCodeURLOption
- options.CallOption
-} {
- return struct {
- AcquireInteractiveOption
- AuthCodeURLOption
- options.CallOption
- }{
- CallOption: options.NewCallOption(
- func(a any) error {
- switch t := a.(type) {
- case *authCodeURLOptions:
- t.loginHint = username
- case *interactiveAuthOptions:
- t.loginHint = username
- default:
- return fmt.Errorf("unexpected options type %T", a)
- }
- return nil
- },
- ),
- }
+func (pca Client) RemoveAccount(account Account) error {
+ pca.base.RemoveAccount(account)
+ return nil
}
-// WithDomainHint adds the IdP domain as domain_hint query parameter in the auth url.
-func WithDomainHint(domain string) interface {
- AcquireInteractiveOption
- AuthCodeURLOption
- options.CallOption
-} {
- return struct {
- AcquireInteractiveOption
- AuthCodeURLOption
- options.CallOption
- }{
- CallOption: options.NewCallOption(
- func(a any) error {
- switch t := a.(type) {
- case *authCodeURLOptions:
- t.domainHint = domain
- case *interactiveAuthOptions:
- t.domainHint = domain
- default:
- return fmt.Errorf("unexpected options type %T", a)
- }
- return nil
- },
- ),
- }
+// InteractiveAuthOptions contains the optional parameters used to acquire an access token for interactive auth code flow.
+type InteractiveAuthOptions struct {
+ // Used to specify a custom port for the local server. http://localhost:portnumber
+ // All other URI components are ignored.
+ RedirectURI string
}
-// WithRedirectURI sets a port for the local server used in interactive authentication, for
-// example http://localhost:port. All URI components other than the port are ignored.
-func WithRedirectURI(redirectURI string) interface {
- AcquireInteractiveOption
- options.CallOption
-} {
- return struct {
- AcquireInteractiveOption
- options.CallOption
- }{
- CallOption: options.NewCallOption(
- func(a any) error {
- switch t := a.(type) {
- case *interactiveAuthOptions:
- t.redirectURI = redirectURI
- default:
- return fmt.Errorf("unexpected options type %T", a)
- }
- return nil
- },
- ),
- }
-}
+// InteractiveAuthOption changes options inside InteractiveAuthOptions used in .AcquireTokenInteractive().
+type InteractiveAuthOption func(*InteractiveAuthOptions)
-// WithOpenURL allows you to provide a function to open the browser to complete the interactive login, instead of launching the system default browser.
-func WithOpenURL(openURL func(url string) error) interface {
- AcquireInteractiveOption
- options.CallOption
-} {
- return struct {
- AcquireInteractiveOption
- options.CallOption
- }{
- CallOption: options.NewCallOption(
- func(a any) error {
- switch t := a.(type) {
- case *interactiveAuthOptions:
- t.openURL = openURL
- default:
- return fmt.Errorf("unexpected options type %T", a)
- }
- return nil
- },
- ),
+// WithRedirectURI uses the specified redirect URI for interactive auth.
+func WithRedirectURI(redirectURI string) InteractiveAuthOption {
+ return func(o *InteractiveAuthOptions) {
+ o.RedirectURI = redirectURI
}
}
// AcquireTokenInteractive acquires a security token from the authority using the default web browser to select the account.
// https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-authentication-flows#interactive-and-non-interactive-authentication
-//
-// Options: [WithDomainHint], [WithLoginHint], [WithOpenURL], [WithRedirectURI], [WithTenantID]
-func (pca Client) AcquireTokenInteractive(ctx context.Context, scopes []string, opts ...AcquireInteractiveOption) (AuthResult, error) {
- o := interactiveAuthOptions{}
- if err := options.ApplyOptions(&o, opts); err != nil {
- return AuthResult{}, err
+func (pca Client) AcquireTokenInteractive(ctx context.Context, scopes []string, options ...InteractiveAuthOption) (AuthResult, error) {
+ opts := InteractiveAuthOptions{}
+ for _, opt := range options {
+ opt(&opts)
}
// the code verifier is a random 32-byte sequence that's been base-64 encoded without padding.
// it's used to prevent MitM attacks during auth code flow, see https://tools.ietf.org/html/rfc7636
@@ -606,29 +295,20 @@ func (pca Client) AcquireTokenInteractive(ctx context.Context, scopes []string,
return AuthResult{}, err
}
var redirectURL *url.URL
- if o.redirectURI != "" {
- redirectURL, err = url.Parse(o.redirectURI)
+ if opts.RedirectURI != "" {
+ redirectURL, err = url.Parse(opts.RedirectURI)
if err != nil {
return AuthResult{}, err
}
}
- if o.openURL == nil {
- o.openURL = browser.OpenURL
- }
- authParams, err := pca.base.AuthParams.WithTenant(o.tenantID)
- if err != nil {
- return AuthResult{}, err
- }
+ authParams := pca.base.AuthParams // This is a copy, as we dont' have a pointer receiver and .AuthParams is not a pointer.
authParams.Scopes = scopes
authParams.AuthorizationType = authority.ATInteractive
- authParams.Claims = o.claims
authParams.CodeChallenge = challenge
authParams.CodeChallengeMethod = "S256"
- authParams.LoginHint = o.loginHint
- authParams.DomainHint = o.domainHint
authParams.State = uuid.New().String()
authParams.Prompt = "select_account"
- res, err := pca.browserLogin(ctx, redirectURL, authParams, o.openURL)
+ res, err := pca.browserLogin(ctx, redirectURL, authParams)
if err != nil {
return AuthResult{}, err
}
@@ -652,6 +332,11 @@ type interactiveAuthResult struct {
redirectURI string
}
+// provides a test hook to simulate opening a browser
+var browserOpenURL = func(authURL string) error {
+ return browser.OpenURL(authURL)
+}
+
// parses the port number from the provided URL.
// returns 0 if nil or no port is specified.
func parsePort(u *url.URL) (int, error) {
@@ -665,8 +350,8 @@ func parsePort(u *url.URL) (int, error) {
return strconv.Atoi(p)
}
-// browserLogin calls openURL and waits for a user to log in
-func (pca Client) browserLogin(ctx context.Context, redirectURI *url.URL, params authority.AuthParams, openURL func(string) error) (interactiveAuthResult, error) {
+// browserLogin launches the system browser for interactive login
+func (pca Client) browserLogin(ctx context.Context, redirectURI *url.URL, params authority.AuthParams) (interactiveAuthResult, error) {
// start local redirect server so login can call us back
port, err := parsePort(redirectURI)
if err != nil {
@@ -683,7 +368,7 @@ func (pca Client) browserLogin(ctx context.Context, redirectURI *url.URL, params
return interactiveAuthResult{}, err
}
// open browser window so user can select credentials
- if err := openURL(authURL); err != nil {
+ if err := browserOpenURL(authURL); err != nil {
return interactiveAuthResult{}, err
}
// now wait until the logic calls us back
diff --git a/vendor/github.com/beorn7/perks/LICENSE b/vendor/github.com/beorn7/perks/LICENSE
new file mode 100644
index 000000000..339177be6
--- /dev/null
+++ b/vendor/github.com/beorn7/perks/LICENSE
@@ -0,0 +1,20 @@
+Copyright (C) 2013 Blake Mizerany
+
+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.
diff --git a/vendor/github.com/beorn7/perks/quantile/exampledata.txt b/vendor/github.com/beorn7/perks/quantile/exampledata.txt
new file mode 100644
index 000000000..1602287d7
--- /dev/null
+++ b/vendor/github.com/beorn7/perks/quantile/exampledata.txt
@@ -0,0 +1,2388 @@
+8
+5
+26
+12
+5
+235
+13
+6
+28
+30
+3
+3
+3
+3
+5
+2
+33
+7
+2
+4
+7
+12
+14
+5
+8
+3
+10
+4
+5
+3
+6
+6
+209
+20
+3
+10
+14
+3
+4
+6
+8
+5
+11
+7
+3
+2
+3
+3
+212
+5
+222
+4
+10
+10
+5
+6
+3
+8
+3
+10
+254
+220
+2
+3
+5
+24
+5
+4
+222
+7
+3
+3
+223
+8
+15
+12
+14
+14
+3
+2
+2
+3
+13
+3
+11
+4
+4
+6
+5
+7
+13
+5
+3
+5
+2
+5
+3
+5
+2
+7
+15
+17
+14
+3
+6
+6
+3
+17
+5
+4
+7
+6
+4
+4
+8
+6
+8
+3
+9
+3
+6
+3
+4
+5
+3
+3
+660
+4
+6
+10
+3
+6
+3
+2
+5
+13
+2
+4
+4
+10
+4
+8
+4
+3
+7
+9
+9
+3
+10
+37
+3
+13
+4
+12
+3
+6
+10
+8
+5
+21
+2
+3
+8
+3
+2
+3
+3
+4
+12
+2
+4
+8
+8
+4
+3
+2
+20
+1
+6
+32
+2
+11
+6
+18
+3
+8
+11
+3
+212
+3
+4
+2
+6
+7
+12
+11
+3
+2
+16
+10
+6
+4
+6
+3
+2
+7
+3
+2
+2
+2
+2
+5
+6
+4
+3
+10
+3
+4
+6
+5
+3
+4
+4
+5
+6
+4
+3
+4
+4
+5
+7
+5
+5
+3
+2
+7
+2
+4
+12
+4
+5
+6
+2
+4
+4
+8
+4
+15
+13
+7
+16
+5
+3
+23
+5
+5
+7
+3
+2
+9
+8
+7
+5
+8
+11
+4
+10
+76
+4
+47
+4
+3
+2
+7
+4
+2
+3
+37
+10
+4
+2
+20
+5
+4
+4
+10
+10
+4
+3
+7
+23
+240
+7
+13
+5
+5
+3
+3
+2
+5
+4
+2
+8
+7
+19
+2
+23
+8
+7
+2
+5
+3
+8
+3
+8
+13
+5
+5
+5
+2
+3
+23
+4
+9
+8
+4
+3
+3
+5
+220
+2
+3
+4
+6
+14
+3
+53
+6
+2
+5
+18
+6
+3
+219
+6
+5
+2
+5
+3
+6
+5
+15
+4
+3
+17
+3
+2
+4
+7
+2
+3
+3
+4
+4
+3
+2
+664
+6
+3
+23
+5
+5
+16
+5
+8
+2
+4
+2
+24
+12
+3
+2
+3
+5
+8
+3
+5
+4
+3
+14
+3
+5
+8
+2
+3
+7
+9
+4
+2
+3
+6
+8
+4
+3
+4
+6
+5
+3
+3
+6
+3
+19
+4
+4
+6
+3
+6
+3
+5
+22
+5
+4
+4
+3
+8
+11
+4
+9
+7
+6
+13
+4
+4
+4
+6
+17
+9
+3
+3
+3
+4
+3
+221
+5
+11
+3
+4
+2
+12
+6
+3
+5
+7
+5
+7
+4
+9
+7
+14
+37
+19
+217
+16
+3
+5
+2
+2
+7
+19
+7
+6
+7
+4
+24
+5
+11
+4
+7
+7
+9
+13
+3
+4
+3
+6
+28
+4
+4
+5
+5
+2
+5
+6
+4
+4
+6
+10
+5
+4
+3
+2
+3
+3
+6
+5
+5
+4
+3
+2
+3
+7
+4
+6
+18
+16
+8
+16
+4
+5
+8
+6
+9
+13
+1545
+6
+215
+6
+5
+6
+3
+45
+31
+5
+2
+2
+4
+3
+3
+2
+5
+4
+3
+5
+7
+7
+4
+5
+8
+5
+4
+749
+2
+31
+9
+11
+2
+11
+5
+4
+4
+7
+9
+11
+4
+5
+4
+7
+3
+4
+6
+2
+15
+3
+4
+3
+4
+3
+5
+2
+13
+5
+5
+3
+3
+23
+4
+4
+5
+7
+4
+13
+2
+4
+3
+4
+2
+6
+2
+7
+3
+5
+5
+3
+29
+5
+4
+4
+3
+10
+2
+3
+79
+16
+6
+6
+7
+7
+3
+5
+5
+7
+4
+3
+7
+9
+5
+6
+5
+9
+6
+3
+6
+4
+17
+2
+10
+9
+3
+6
+2
+3
+21
+22
+5
+11
+4
+2
+17
+2
+224
+2
+14
+3
+4
+4
+2
+4
+4
+4
+4
+5
+3
+4
+4
+10
+2
+6
+3
+3
+5
+7
+2
+7
+5
+6
+3
+218
+2
+2
+5
+2
+6
+3
+5
+222
+14
+6
+33
+3
+2
+5
+3
+3
+3
+9
+5
+3
+3
+2
+7
+4
+3
+4
+3
+5
+6
+5
+26
+4
+13
+9
+7
+3
+221
+3
+3
+4
+4
+4
+4
+2
+18
+5
+3
+7
+9
+6
+8
+3
+10
+3
+11
+9
+5
+4
+17
+5
+5
+6
+6
+3
+2
+4
+12
+17
+6
+7
+218
+4
+2
+4
+10
+3
+5
+15
+3
+9
+4
+3
+3
+6
+29
+3
+3
+4
+5
+5
+3
+8
+5
+6
+6
+7
+5
+3
+5
+3
+29
+2
+31
+5
+15
+24
+16
+5
+207
+4
+3
+3
+2
+15
+4
+4
+13
+5
+5
+4
+6
+10
+2
+7
+8
+4
+6
+20
+5
+3
+4
+3
+12
+12
+5
+17
+7
+3
+3
+3
+6
+10
+3
+5
+25
+80
+4
+9
+3
+2
+11
+3
+3
+2
+3
+8
+7
+5
+5
+19
+5
+3
+3
+12
+11
+2
+6
+5
+5
+5
+3
+3
+3
+4
+209
+14
+3
+2
+5
+19
+4
+4
+3
+4
+14
+5
+6
+4
+13
+9
+7
+4
+7
+10
+2
+9
+5
+7
+2
+8
+4
+6
+5
+5
+222
+8
+7
+12
+5
+216
+3
+4
+4
+6
+3
+14
+8
+7
+13
+4
+3
+3
+3
+3
+17
+5
+4
+3
+33
+6
+6
+33
+7
+5
+3
+8
+7
+5
+2
+9
+4
+2
+233
+24
+7
+4
+8
+10
+3
+4
+15
+2
+16
+3
+3
+13
+12
+7
+5
+4
+207
+4
+2
+4
+27
+15
+2
+5
+2
+25
+6
+5
+5
+6
+13
+6
+18
+6
+4
+12
+225
+10
+7
+5
+2
+2
+11
+4
+14
+21
+8
+10
+3
+5
+4
+232
+2
+5
+5
+3
+7
+17
+11
+6
+6
+23
+4
+6
+3
+5
+4
+2
+17
+3
+6
+5
+8
+3
+2
+2
+14
+9
+4
+4
+2
+5
+5
+3
+7
+6
+12
+6
+10
+3
+6
+2
+2
+19
+5
+4
+4
+9
+2
+4
+13
+3
+5
+6
+3
+6
+5
+4
+9
+6
+3
+5
+7
+3
+6
+6
+4
+3
+10
+6
+3
+221
+3
+5
+3
+6
+4
+8
+5
+3
+6
+4
+4
+2
+54
+5
+6
+11
+3
+3
+4
+4
+4
+3
+7
+3
+11
+11
+7
+10
+6
+13
+223
+213
+15
+231
+7
+3
+7
+228
+2
+3
+4
+4
+5
+6
+7
+4
+13
+3
+4
+5
+3
+6
+4
+6
+7
+2
+4
+3
+4
+3
+3
+6
+3
+7
+3
+5
+18
+5
+6
+8
+10
+3
+3
+3
+2
+4
+2
+4
+4
+5
+6
+6
+4
+10
+13
+3
+12
+5
+12
+16
+8
+4
+19
+11
+2
+4
+5
+6
+8
+5
+6
+4
+18
+10
+4
+2
+216
+6
+6
+6
+2
+4
+12
+8
+3
+11
+5
+6
+14
+5
+3
+13
+4
+5
+4
+5
+3
+28
+6
+3
+7
+219
+3
+9
+7
+3
+10
+6
+3
+4
+19
+5
+7
+11
+6
+15
+19
+4
+13
+11
+3
+7
+5
+10
+2
+8
+11
+2
+6
+4
+6
+24
+6
+3
+3
+3
+3
+6
+18
+4
+11
+4
+2
+5
+10
+8
+3
+9
+5
+3
+4
+5
+6
+2
+5
+7
+4
+4
+14
+6
+4
+4
+5
+5
+7
+2
+4
+3
+7
+3
+3
+6
+4
+5
+4
+4
+4
+3
+3
+3
+3
+8
+14
+2
+3
+5
+3
+2
+4
+5
+3
+7
+3
+3
+18
+3
+4
+4
+5
+7
+3
+3
+3
+13
+5
+4
+8
+211
+5
+5
+3
+5
+2
+5
+4
+2
+655
+6
+3
+5
+11
+2
+5
+3
+12
+9
+15
+11
+5
+12
+217
+2
+6
+17
+3
+3
+207
+5
+5
+4
+5
+9
+3
+2
+8
+5
+4
+3
+2
+5
+12
+4
+14
+5
+4
+2
+13
+5
+8
+4
+225
+4
+3
+4
+5
+4
+3
+3
+6
+23
+9
+2
+6
+7
+233
+4
+4
+6
+18
+3
+4
+6
+3
+4
+4
+2
+3
+7
+4
+13
+227
+4
+3
+5
+4
+2
+12
+9
+17
+3
+7
+14
+6
+4
+5
+21
+4
+8
+9
+2
+9
+25
+16
+3
+6
+4
+7
+8
+5
+2
+3
+5
+4
+3
+3
+5
+3
+3
+3
+2
+3
+19
+2
+4
+3
+4
+2
+3
+4
+4
+2
+4
+3
+3
+3
+2
+6
+3
+17
+5
+6
+4
+3
+13
+5
+3
+3
+3
+4
+9
+4
+2
+14
+12
+4
+5
+24
+4
+3
+37
+12
+11
+21
+3
+4
+3
+13
+4
+2
+3
+15
+4
+11
+4
+4
+3
+8
+3
+4
+4
+12
+8
+5
+3
+3
+4
+2
+220
+3
+5
+223
+3
+3
+3
+10
+3
+15
+4
+241
+9
+7
+3
+6
+6
+23
+4
+13
+7
+3
+4
+7
+4
+9
+3
+3
+4
+10
+5
+5
+1
+5
+24
+2
+4
+5
+5
+6
+14
+3
+8
+2
+3
+5
+13
+13
+3
+5
+2
+3
+15
+3
+4
+2
+10
+4
+4
+4
+5
+5
+3
+5
+3
+4
+7
+4
+27
+3
+6
+4
+15
+3
+5
+6
+6
+5
+4
+8
+3
+9
+2
+6
+3
+4
+3
+7
+4
+18
+3
+11
+3
+3
+8
+9
+7
+24
+3
+219
+7
+10
+4
+5
+9
+12
+2
+5
+4
+4
+4
+3
+3
+19
+5
+8
+16
+8
+6
+22
+3
+23
+3
+242
+9
+4
+3
+3
+5
+7
+3
+3
+5
+8
+3
+7
+5
+14
+8
+10
+3
+4
+3
+7
+4
+6
+7
+4
+10
+4
+3
+11
+3
+7
+10
+3
+13
+6
+8
+12
+10
+5
+7
+9
+3
+4
+7
+7
+10
+8
+30
+9
+19
+4
+3
+19
+15
+4
+13
+3
+215
+223
+4
+7
+4
+8
+17
+16
+3
+7
+6
+5
+5
+4
+12
+3
+7
+4
+4
+13
+4
+5
+2
+5
+6
+5
+6
+6
+7
+10
+18
+23
+9
+3
+3
+6
+5
+2
+4
+2
+7
+3
+3
+2
+5
+5
+14
+10
+224
+6
+3
+4
+3
+7
+5
+9
+3
+6
+4
+2
+5
+11
+4
+3
+3
+2
+8
+4
+7
+4
+10
+7
+3
+3
+18
+18
+17
+3
+3
+3
+4
+5
+3
+3
+4
+12
+7
+3
+11
+13
+5
+4
+7
+13
+5
+4
+11
+3
+12
+3
+6
+4
+4
+21
+4
+6
+9
+5
+3
+10
+8
+4
+6
+4
+4
+6
+5
+4
+8
+6
+4
+6
+4
+4
+5
+9
+6
+3
+4
+2
+9
+3
+18
+2
+4
+3
+13
+3
+6
+6
+8
+7
+9
+3
+2
+16
+3
+4
+6
+3
+2
+33
+22
+14
+4
+9
+12
+4
+5
+6
+3
+23
+9
+4
+3
+5
+5
+3
+4
+5
+3
+5
+3
+10
+4
+5
+5
+8
+4
+4
+6
+8
+5
+4
+3
+4
+6
+3
+3
+3
+5
+9
+12
+6
+5
+9
+3
+5
+3
+2
+2
+2
+18
+3
+2
+21
+2
+5
+4
+6
+4
+5
+10
+3
+9
+3
+2
+10
+7
+3
+6
+6
+4
+4
+8
+12
+7
+3
+7
+3
+3
+9
+3
+4
+5
+4
+4
+5
+5
+10
+15
+4
+4
+14
+6
+227
+3
+14
+5
+216
+22
+5
+4
+2
+2
+6
+3
+4
+2
+9
+9
+4
+3
+28
+13
+11
+4
+5
+3
+3
+2
+3
+3
+5
+3
+4
+3
+5
+23
+26
+3
+4
+5
+6
+4
+6
+3
+5
+5
+3
+4
+3
+2
+2
+2
+7
+14
+3
+6
+7
+17
+2
+2
+15
+14
+16
+4
+6
+7
+13
+6
+4
+5
+6
+16
+3
+3
+28
+3
+6
+15
+3
+9
+2
+4
+6
+3
+3
+22
+4
+12
+6
+7
+2
+5
+4
+10
+3
+16
+6
+9
+2
+5
+12
+7
+5
+5
+5
+5
+2
+11
+9
+17
+4
+3
+11
+7
+3
+5
+15
+4
+3
+4
+211
+8
+7
+5
+4
+7
+6
+7
+6
+3
+6
+5
+6
+5
+3
+4
+4
+26
+4
+6
+10
+4
+4
+3
+2
+3
+3
+4
+5
+9
+3
+9
+4
+4
+5
+5
+8
+2
+4
+2
+3
+8
+4
+11
+19
+5
+8
+6
+3
+5
+6
+12
+3
+2
+4
+16
+12
+3
+4
+4
+8
+6
+5
+6
+6
+219
+8
+222
+6
+16
+3
+13
+19
+5
+4
+3
+11
+6
+10
+4
+7
+7
+12
+5
+3
+3
+5
+6
+10
+3
+8
+2
+5
+4
+7
+2
+4
+4
+2
+12
+9
+6
+4
+2
+40
+2
+4
+10
+4
+223
+4
+2
+20
+6
+7
+24
+5
+4
+5
+2
+20
+16
+6
+5
+13
+2
+3
+3
+19
+3
+2
+4
+5
+6
+7
+11
+12
+5
+6
+7
+7
+3
+5
+3
+5
+3
+14
+3
+4
+4
+2
+11
+1
+7
+3
+9
+6
+11
+12
+5
+8
+6
+221
+4
+2
+12
+4
+3
+15
+4
+5
+226
+7
+218
+7
+5
+4
+5
+18
+4
+5
+9
+4
+4
+2
+9
+18
+18
+9
+5
+6
+6
+3
+3
+7
+3
+5
+4
+4
+4
+12
+3
+6
+31
+5
+4
+7
+3
+6
+5
+6
+5
+11
+2
+2
+11
+11
+6
+7
+5
+8
+7
+10
+5
+23
+7
+4
+3
+5
+34
+2
+5
+23
+7
+3
+6
+8
+4
+4
+4
+2
+5
+3
+8
+5
+4
+8
+25
+2
+3
+17
+8
+3
+4
+8
+7
+3
+15
+6
+5
+7
+21
+9
+5
+6
+6
+5
+3
+2
+3
+10
+3
+6
+3
+14
+7
+4
+4
+8
+7
+8
+2
+6
+12
+4
+213
+6
+5
+21
+8
+2
+5
+23
+3
+11
+2
+3
+6
+25
+2
+3
+6
+7
+6
+6
+4
+4
+6
+3
+17
+9
+7
+6
+4
+3
+10
+7
+2
+3
+3
+3
+11
+8
+3
+7
+6
+4
+14
+36
+3
+4
+3
+3
+22
+13
+21
+4
+2
+7
+4
+4
+17
+15
+3
+7
+11
+2
+4
+7
+6
+209
+6
+3
+2
+2
+24
+4
+9
+4
+3
+3
+3
+29
+2
+2
+4
+3
+3
+5
+4
+6
+3
+3
+2
+4
diff --git a/vendor/github.com/beorn7/perks/quantile/stream.go b/vendor/github.com/beorn7/perks/quantile/stream.go
new file mode 100644
index 000000000..d7d14f8eb
--- /dev/null
+++ b/vendor/github.com/beorn7/perks/quantile/stream.go
@@ -0,0 +1,316 @@
+// Package quantile computes approximate quantiles over an unbounded data
+// stream within low memory and CPU bounds.
+//
+// A small amount of accuracy is traded to achieve the above properties.
+//
+// Multiple streams can be merged before calling Query to generate a single set
+// of results. This is meaningful when the streams represent the same type of
+// data. See Merge and Samples.
+//
+// For more detailed information about the algorithm used, see:
+//
+// Effective Computation of Biased Quantiles over Data Streams
+//
+// http://www.cs.rutgers.edu/~muthu/bquant.pdf
+package quantile
+
+import (
+ "math"
+ "sort"
+)
+
+// Sample holds an observed value and meta information for compression. JSON
+// tags have been added for convenience.
+type Sample struct {
+ Value float64 `json:",string"`
+ Width float64 `json:",string"`
+ Delta float64 `json:",string"`
+}
+
+// Samples represents a slice of samples. It implements sort.Interface.
+type Samples []Sample
+
+func (a Samples) Len() int { return len(a) }
+func (a Samples) Less(i, j int) bool { return a[i].Value < a[j].Value }
+func (a Samples) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+
+type invariant func(s *stream, r float64) float64
+
+// NewLowBiased returns an initialized Stream for low-biased quantiles
+// (e.g. 0.01, 0.1, 0.5) where the needed quantiles are not known a priori, but
+// error guarantees can still be given even for the lower ranks of the data
+// distribution.
+//
+// The provided epsilon is a relative error, i.e. the true quantile of a value
+// returned by a query is guaranteed to be within (1±Epsilon)*Quantile.
+//
+// See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error
+// properties.
+func NewLowBiased(epsilon float64) *Stream {
+ ƒ := func(s *stream, r float64) float64 {
+ return 2 * epsilon * r
+ }
+ return newStream(ƒ)
+}
+
+// NewHighBiased returns an initialized Stream for high-biased quantiles
+// (e.g. 0.01, 0.1, 0.5) where the needed quantiles are not known a priori, but
+// error guarantees can still be given even for the higher ranks of the data
+// distribution.
+//
+// The provided epsilon is a relative error, i.e. the true quantile of a value
+// returned by a query is guaranteed to be within 1-(1±Epsilon)*(1-Quantile).
+//
+// See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error
+// properties.
+func NewHighBiased(epsilon float64) *Stream {
+ ƒ := func(s *stream, r float64) float64 {
+ return 2 * epsilon * (s.n - r)
+ }
+ return newStream(ƒ)
+}
+
+// NewTargeted returns an initialized Stream concerned with a particular set of
+// quantile values that are supplied a priori. Knowing these a priori reduces
+// space and computation time. The targets map maps the desired quantiles to
+// their absolute errors, i.e. the true quantile of a value returned by a query
+// is guaranteed to be within (Quantile±Epsilon).
+//
+// See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error properties.
+func NewTargeted(targetMap map[float64]float64) *Stream {
+ // Convert map to slice to avoid slow iterations on a map.
+ // ƒ is called on the hot path, so converting the map to a slice
+ // beforehand results in significant CPU savings.
+ targets := targetMapToSlice(targetMap)
+
+ ƒ := func(s *stream, r float64) float64 {
+ var m = math.MaxFloat64
+ var f float64
+ for _, t := range targets {
+ if t.quantile*s.n <= r {
+ f = (2 * t.epsilon * r) / t.quantile
+ } else {
+ f = (2 * t.epsilon * (s.n - r)) / (1 - t.quantile)
+ }
+ if f < m {
+ m = f
+ }
+ }
+ return m
+ }
+ return newStream(ƒ)
+}
+
+type target struct {
+ quantile float64
+ epsilon float64
+}
+
+func targetMapToSlice(targetMap map[float64]float64) []target {
+ targets := make([]target, 0, len(targetMap))
+
+ for quantile, epsilon := range targetMap {
+ t := target{
+ quantile: quantile,
+ epsilon: epsilon,
+ }
+ targets = append(targets, t)
+ }
+
+ return targets
+}
+
+// Stream computes quantiles for a stream of float64s. It is not thread-safe by
+// design. Take care when using across multiple goroutines.
+type Stream struct {
+ *stream
+ b Samples
+ sorted bool
+}
+
+func newStream(ƒ invariant) *Stream {
+ x := &stream{ƒ: ƒ}
+ return &Stream{x, make(Samples, 0, 500), true}
+}
+
+// Insert inserts v into the stream.
+func (s *Stream) Insert(v float64) {
+ s.insert(Sample{Value: v, Width: 1})
+}
+
+func (s *Stream) insert(sample Sample) {
+ s.b = append(s.b, sample)
+ s.sorted = false
+ if len(s.b) == cap(s.b) {
+ s.flush()
+ }
+}
+
+// Query returns the computed qth percentiles value. If s was created with
+// NewTargeted, and q is not in the set of quantiles provided a priori, Query
+// will return an unspecified result.
+func (s *Stream) Query(q float64) float64 {
+ if !s.flushed() {
+ // Fast path when there hasn't been enough data for a flush;
+ // this also yields better accuracy for small sets of data.
+ l := len(s.b)
+ if l == 0 {
+ return 0
+ }
+ i := int(math.Ceil(float64(l) * q))
+ if i > 0 {
+ i -= 1
+ }
+ s.maybeSort()
+ return s.b[i].Value
+ }
+ s.flush()
+ return s.stream.query(q)
+}
+
+// Merge merges samples into the underlying streams samples. This is handy when
+// merging multiple streams from separate threads, database shards, etc.
+//
+// ATTENTION: This method is broken and does not yield correct results. The
+// underlying algorithm is not capable of merging streams correctly.
+func (s *Stream) Merge(samples Samples) {
+ sort.Sort(samples)
+ s.stream.merge(samples)
+}
+
+// Reset reinitializes and clears the list reusing the samples buffer memory.
+func (s *Stream) Reset() {
+ s.stream.reset()
+ s.b = s.b[:0]
+}
+
+// Samples returns stream samples held by s.
+func (s *Stream) Samples() Samples {
+ if !s.flushed() {
+ return s.b
+ }
+ s.flush()
+ return s.stream.samples()
+}
+
+// Count returns the total number of samples observed in the stream
+// since initialization.
+func (s *Stream) Count() int {
+ return len(s.b) + s.stream.count()
+}
+
+func (s *Stream) flush() {
+ s.maybeSort()
+ s.stream.merge(s.b)
+ s.b = s.b[:0]
+}
+
+func (s *Stream) maybeSort() {
+ if !s.sorted {
+ s.sorted = true
+ sort.Sort(s.b)
+ }
+}
+
+func (s *Stream) flushed() bool {
+ return len(s.stream.l) > 0
+}
+
+type stream struct {
+ n float64
+ l []Sample
+ ƒ invariant
+}
+
+func (s *stream) reset() {
+ s.l = s.l[:0]
+ s.n = 0
+}
+
+func (s *stream) insert(v float64) {
+ s.merge(Samples{{v, 1, 0}})
+}
+
+func (s *stream) merge(samples Samples) {
+ // TODO(beorn7): This tries to merge not only individual samples, but
+ // whole summaries. The paper doesn't mention merging summaries at
+ // all. Unittests show that the merging is inaccurate. Find out how to
+ // do merges properly.
+ var r float64
+ i := 0
+ for _, sample := range samples {
+ for ; i < len(s.l); i++ {
+ c := s.l[i]
+ if c.Value > sample.Value {
+ // Insert at position i.
+ s.l = append(s.l, Sample{})
+ copy(s.l[i+1:], s.l[i:])
+ s.l[i] = Sample{
+ sample.Value,
+ sample.Width,
+ math.Max(sample.Delta, math.Floor(s.ƒ(s, r))-1),
+ // TODO(beorn7): How to calculate delta correctly?
+ }
+ i++
+ goto inserted
+ }
+ r += c.Width
+ }
+ s.l = append(s.l, Sample{sample.Value, sample.Width, 0})
+ i++
+ inserted:
+ s.n += sample.Width
+ r += sample.Width
+ }
+ s.compress()
+}
+
+func (s *stream) count() int {
+ return int(s.n)
+}
+
+func (s *stream) query(q float64) float64 {
+ t := math.Ceil(q * s.n)
+ t += math.Ceil(s.ƒ(s, t) / 2)
+ p := s.l[0]
+ var r float64
+ for _, c := range s.l[1:] {
+ r += p.Width
+ if r+c.Width+c.Delta > t {
+ return p.Value
+ }
+ p = c
+ }
+ return p.Value
+}
+
+func (s *stream) compress() {
+ if len(s.l) < 2 {
+ return
+ }
+ x := s.l[len(s.l)-1]
+ xi := len(s.l) - 1
+ r := s.n - 1 - x.Width
+
+ for i := len(s.l) - 2; i >= 0; i-- {
+ c := s.l[i]
+ if c.Width+x.Width+x.Delta <= s.ƒ(s, r) {
+ x.Width += c.Width
+ s.l[xi] = x
+ // Remove element at i.
+ copy(s.l[i:], s.l[i+1:])
+ s.l = s.l[:len(s.l)-1]
+ xi -= 1
+ } else {
+ x = c
+ xi = i
+ }
+ r -= c.Width
+ }
+}
+
+func (s *stream) samples() Samples {
+ samples := make(Samples, len(s.l))
+ copy(samples, s.l)
+ return samples
+}
diff --git a/vendor/github.com/cespare/xxhash/v2/LICENSE.txt b/vendor/github.com/cespare/xxhash/v2/LICENSE.txt
new file mode 100644
index 000000000..24b53065f
--- /dev/null
+++ b/vendor/github.com/cespare/xxhash/v2/LICENSE.txt
@@ -0,0 +1,22 @@
+Copyright (c) 2016 Caleb Spare
+
+MIT License
+
+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.
diff --git a/vendor/github.com/cespare/xxhash/v2/README.md b/vendor/github.com/cespare/xxhash/v2/README.md
new file mode 100644
index 000000000..8bf0e5b78
--- /dev/null
+++ b/vendor/github.com/cespare/xxhash/v2/README.md
@@ -0,0 +1,72 @@
+# xxhash
+
+[![Go Reference](https://pkg.go.dev/badge/github.com/cespare/xxhash/v2.svg)](https://pkg.go.dev/github.com/cespare/xxhash/v2)
+[![Test](https://github.com/cespare/xxhash/actions/workflows/test.yml/badge.svg)](https://github.com/cespare/xxhash/actions/workflows/test.yml)
+
+xxhash is a Go implementation of the 64-bit [xxHash] algorithm, XXH64. This is a
+high-quality hashing algorithm that is much faster than anything in the Go
+standard library.
+
+This package provides a straightforward API:
+
+```
+func Sum64(b []byte) uint64
+func Sum64String(s string) uint64
+type Digest struct{ ... }
+ func New() *Digest
+```
+
+The `Digest` type implements hash.Hash64. Its key methods are:
+
+```
+func (*Digest) Write([]byte) (int, error)
+func (*Digest) WriteString(string) (int, error)
+func (*Digest) Sum64() uint64
+```
+
+The package is written with optimized pure Go and also contains even faster
+assembly implementations for amd64 and arm64. If desired, the `purego` build tag
+opts into using the Go code even on those architectures.
+
+[xxHash]: http://cyan4973.github.io/xxHash/
+
+## Compatibility
+
+This package is in a module and the latest code is in version 2 of the module.
+You need a version of Go with at least "minimal module compatibility" to use
+github.com/cespare/xxhash/v2:
+
+* 1.9.7+ for Go 1.9
+* 1.10.3+ for Go 1.10
+* Go 1.11 or later
+
+I recommend using the latest release of Go.
+
+## Benchmarks
+
+Here are some quick benchmarks comparing the pure-Go and assembly
+implementations of Sum64.
+
+| input size | purego | asm |
+| ---------- | --------- | --------- |
+| 4 B | 1.3 GB/s | 1.2 GB/s |
+| 16 B | 2.9 GB/s | 3.5 GB/s |
+| 100 B | 6.9 GB/s | 8.1 GB/s |
+| 4 KB | 11.7 GB/s | 16.7 GB/s |
+| 10 MB | 12.0 GB/s | 17.3 GB/s |
+
+These numbers were generated on Ubuntu 20.04 with an Intel Xeon Platinum 8252C
+CPU using the following commands under Go 1.19.2:
+
+```
+benchstat <(go test -tags purego -benchtime 500ms -count 15 -bench 'Sum64$')
+benchstat <(go test -benchtime 500ms -count 15 -bench 'Sum64$')
+```
+
+## Projects using this package
+
+- [InfluxDB](https://github.com/influxdata/influxdb)
+- [Prometheus](https://github.com/prometheus/prometheus)
+- [VictoriaMetrics](https://github.com/VictoriaMetrics/VictoriaMetrics)
+- [FreeCache](https://github.com/coocood/freecache)
+- [FastCache](https://github.com/VictoriaMetrics/fastcache)
diff --git a/vendor/github.com/cespare/xxhash/v2/testall.sh b/vendor/github.com/cespare/xxhash/v2/testall.sh
new file mode 100644
index 000000000..94b9c4439
--- /dev/null
+++ b/vendor/github.com/cespare/xxhash/v2/testall.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+set -eu -o pipefail
+
+# Small convenience script for running the tests with various combinations of
+# arch/tags. This assumes we're running on amd64 and have qemu available.
+
+go test ./...
+go test -tags purego ./...
+GOARCH=arm64 go test
+GOARCH=arm64 go test -tags purego
diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash.go b/vendor/github.com/cespare/xxhash/v2/xxhash.go
new file mode 100644
index 000000000..a9e0d45c9
--- /dev/null
+++ b/vendor/github.com/cespare/xxhash/v2/xxhash.go
@@ -0,0 +1,228 @@
+// Package xxhash implements the 64-bit variant of xxHash (XXH64) as described
+// at http://cyan4973.github.io/xxHash/.
+package xxhash
+
+import (
+ "encoding/binary"
+ "errors"
+ "math/bits"
+)
+
+const (
+ prime1 uint64 = 11400714785074694791
+ prime2 uint64 = 14029467366897019727
+ prime3 uint64 = 1609587929392839161
+ prime4 uint64 = 9650029242287828579
+ prime5 uint64 = 2870177450012600261
+)
+
+// Store the primes in an array as well.
+//
+// The consts are used when possible in Go code to avoid MOVs but we need a
+// contiguous array of the assembly code.
+var primes = [...]uint64{prime1, prime2, prime3, prime4, prime5}
+
+// Digest implements hash.Hash64.
+type Digest struct {
+ v1 uint64
+ v2 uint64
+ v3 uint64
+ v4 uint64
+ total uint64
+ mem [32]byte
+ n int // how much of mem is used
+}
+
+// New creates a new Digest that computes the 64-bit xxHash algorithm.
+func New() *Digest {
+ var d Digest
+ d.Reset()
+ return &d
+}
+
+// Reset clears the Digest's state so that it can be reused.
+func (d *Digest) Reset() {
+ d.v1 = primes[0] + prime2
+ d.v2 = prime2
+ d.v3 = 0
+ d.v4 = -primes[0]
+ d.total = 0
+ d.n = 0
+}
+
+// Size always returns 8 bytes.
+func (d *Digest) Size() int { return 8 }
+
+// BlockSize always returns 32 bytes.
+func (d *Digest) BlockSize() int { return 32 }
+
+// Write adds more data to d. It always returns len(b), nil.
+func (d *Digest) Write(b []byte) (n int, err error) {
+ n = len(b)
+ d.total += uint64(n)
+
+ memleft := d.mem[d.n&(len(d.mem)-1):]
+
+ if d.n+n < 32 {
+ // This new data doesn't even fill the current block.
+ copy(memleft, b)
+ d.n += n
+ return
+ }
+
+ if d.n > 0 {
+ // Finish off the partial block.
+ c := copy(memleft, b)
+ d.v1 = round(d.v1, u64(d.mem[0:8]))
+ d.v2 = round(d.v2, u64(d.mem[8:16]))
+ d.v3 = round(d.v3, u64(d.mem[16:24]))
+ d.v4 = round(d.v4, u64(d.mem[24:32]))
+ b = b[c:]
+ d.n = 0
+ }
+
+ if len(b) >= 32 {
+ // One or more full blocks left.
+ nw := writeBlocks(d, b)
+ b = b[nw:]
+ }
+
+ // Store any remaining partial block.
+ copy(d.mem[:], b)
+ d.n = len(b)
+
+ return
+}
+
+// Sum appends the current hash to b and returns the resulting slice.
+func (d *Digest) Sum(b []byte) []byte {
+ s := d.Sum64()
+ return append(
+ b,
+ byte(s>>56),
+ byte(s>>48),
+ byte(s>>40),
+ byte(s>>32),
+ byte(s>>24),
+ byte(s>>16),
+ byte(s>>8),
+ byte(s),
+ )
+}
+
+// Sum64 returns the current hash.
+func (d *Digest) Sum64() uint64 {
+ var h uint64
+
+ if d.total >= 32 {
+ v1, v2, v3, v4 := d.v1, d.v2, d.v3, d.v4
+ h = rol1(v1) + rol7(v2) + rol12(v3) + rol18(v4)
+ h = mergeRound(h, v1)
+ h = mergeRound(h, v2)
+ h = mergeRound(h, v3)
+ h = mergeRound(h, v4)
+ } else {
+ h = d.v3 + prime5
+ }
+
+ h += d.total
+
+ b := d.mem[:d.n&(len(d.mem)-1)]
+ for ; len(b) >= 8; b = b[8:] {
+ k1 := round(0, u64(b[:8]))
+ h ^= k1
+ h = rol27(h)*prime1 + prime4
+ }
+ if len(b) >= 4 {
+ h ^= uint64(u32(b[:4])) * prime1
+ h = rol23(h)*prime2 + prime3
+ b = b[4:]
+ }
+ for ; len(b) > 0; b = b[1:] {
+ h ^= uint64(b[0]) * prime5
+ h = rol11(h) * prime1
+ }
+
+ h ^= h >> 33
+ h *= prime2
+ h ^= h >> 29
+ h *= prime3
+ h ^= h >> 32
+
+ return h
+}
+
+const (
+ magic = "xxh\x06"
+ marshaledSize = len(magic) + 8*5 + 32
+)
+
+// MarshalBinary implements the encoding.BinaryMarshaler interface.
+func (d *Digest) MarshalBinary() ([]byte, error) {
+ b := make([]byte, 0, marshaledSize)
+ b = append(b, magic...)
+ b = appendUint64(b, d.v1)
+ b = appendUint64(b, d.v2)
+ b = appendUint64(b, d.v3)
+ b = appendUint64(b, d.v4)
+ b = appendUint64(b, d.total)
+ b = append(b, d.mem[:d.n]...)
+ b = b[:len(b)+len(d.mem)-d.n]
+ return b, nil
+}
+
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
+func (d *Digest) UnmarshalBinary(b []byte) error {
+ if len(b) < len(magic) || string(b[:len(magic)]) != magic {
+ return errors.New("xxhash: invalid hash state identifier")
+ }
+ if len(b) != marshaledSize {
+ return errors.New("xxhash: invalid hash state size")
+ }
+ b = b[len(magic):]
+ b, d.v1 = consumeUint64(b)
+ b, d.v2 = consumeUint64(b)
+ b, d.v3 = consumeUint64(b)
+ b, d.v4 = consumeUint64(b)
+ b, d.total = consumeUint64(b)
+ copy(d.mem[:], b)
+ d.n = int(d.total % uint64(len(d.mem)))
+ return nil
+}
+
+func appendUint64(b []byte, x uint64) []byte {
+ var a [8]byte
+ binary.LittleEndian.PutUint64(a[:], x)
+ return append(b, a[:]...)
+}
+
+func consumeUint64(b []byte) ([]byte, uint64) {
+ x := u64(b)
+ return b[8:], x
+}
+
+func u64(b []byte) uint64 { return binary.LittleEndian.Uint64(b) }
+func u32(b []byte) uint32 { return binary.LittleEndian.Uint32(b) }
+
+func round(acc, input uint64) uint64 {
+ acc += input * prime2
+ acc = rol31(acc)
+ acc *= prime1
+ return acc
+}
+
+func mergeRound(acc, val uint64) uint64 {
+ val = round(0, val)
+ acc ^= val
+ acc = acc*prime1 + prime4
+ return acc
+}
+
+func rol1(x uint64) uint64 { return bits.RotateLeft64(x, 1) }
+func rol7(x uint64) uint64 { return bits.RotateLeft64(x, 7) }
+func rol11(x uint64) uint64 { return bits.RotateLeft64(x, 11) }
+func rol12(x uint64) uint64 { return bits.RotateLeft64(x, 12) }
+func rol18(x uint64) uint64 { return bits.RotateLeft64(x, 18) }
+func rol23(x uint64) uint64 { return bits.RotateLeft64(x, 23) }
+func rol27(x uint64) uint64 { return bits.RotateLeft64(x, 27) }
+func rol31(x uint64) uint64 { return bits.RotateLeft64(x, 31) }
diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_amd64.s b/vendor/github.com/cespare/xxhash/v2/xxhash_amd64.s
new file mode 100644
index 000000000..3e8b13257
--- /dev/null
+++ b/vendor/github.com/cespare/xxhash/v2/xxhash_amd64.s
@@ -0,0 +1,209 @@
+//go:build !appengine && gc && !purego
+// +build !appengine
+// +build gc
+// +build !purego
+
+#include "textflag.h"
+
+// Registers:
+#define h AX
+#define d AX
+#define p SI // pointer to advance through b
+#define n DX
+#define end BX // loop end
+#define v1 R8
+#define v2 R9
+#define v3 R10
+#define v4 R11
+#define x R12
+#define prime1 R13
+#define prime2 R14
+#define prime4 DI
+
+#define round(acc, x) \
+ IMULQ prime2, x \
+ ADDQ x, acc \
+ ROLQ $31, acc \
+ IMULQ prime1, acc
+
+// round0 performs the operation x = round(0, x).
+#define round0(x) \
+ IMULQ prime2, x \
+ ROLQ $31, x \
+ IMULQ prime1, x
+
+// mergeRound applies a merge round on the two registers acc and x.
+// It assumes that prime1, prime2, and prime4 have been loaded.
+#define mergeRound(acc, x) \
+ round0(x) \
+ XORQ x, acc \
+ IMULQ prime1, acc \
+ ADDQ prime4, acc
+
+// blockLoop processes as many 32-byte blocks as possible,
+// updating v1, v2, v3, and v4. It assumes that there is at least one block
+// to process.
+#define blockLoop() \
+loop: \
+ MOVQ +0(p), x \
+ round(v1, x) \
+ MOVQ +8(p), x \
+ round(v2, x) \
+ MOVQ +16(p), x \
+ round(v3, x) \
+ MOVQ +24(p), x \
+ round(v4, x) \
+ ADDQ $32, p \
+ CMPQ p, end \
+ JLE loop
+
+// func Sum64(b []byte) uint64
+TEXT ·Sum64(SB), NOSPLIT|NOFRAME, $0-32
+ // Load fixed primes.
+ MOVQ ·primes+0(SB), prime1
+ MOVQ ·primes+8(SB), prime2
+ MOVQ ·primes+24(SB), prime4
+
+ // Load slice.
+ MOVQ b_base+0(FP), p
+ MOVQ b_len+8(FP), n
+ LEAQ (p)(n*1), end
+
+ // The first loop limit will be len(b)-32.
+ SUBQ $32, end
+
+ // Check whether we have at least one block.
+ CMPQ n, $32
+ JLT noBlocks
+
+ // Set up initial state (v1, v2, v3, v4).
+ MOVQ prime1, v1
+ ADDQ prime2, v1
+ MOVQ prime2, v2
+ XORQ v3, v3
+ XORQ v4, v4
+ SUBQ prime1, v4
+
+ blockLoop()
+
+ MOVQ v1, h
+ ROLQ $1, h
+ MOVQ v2, x
+ ROLQ $7, x
+ ADDQ x, h
+ MOVQ v3, x
+ ROLQ $12, x
+ ADDQ x, h
+ MOVQ v4, x
+ ROLQ $18, x
+ ADDQ x, h
+
+ mergeRound(h, v1)
+ mergeRound(h, v2)
+ mergeRound(h, v3)
+ mergeRound(h, v4)
+
+ JMP afterBlocks
+
+noBlocks:
+ MOVQ ·primes+32(SB), h
+
+afterBlocks:
+ ADDQ n, h
+
+ ADDQ $24, end
+ CMPQ p, end
+ JG try4
+
+loop8:
+ MOVQ (p), x
+ ADDQ $8, p
+ round0(x)
+ XORQ x, h
+ ROLQ $27, h
+ IMULQ prime1, h
+ ADDQ prime4, h
+
+ CMPQ p, end
+ JLE loop8
+
+try4:
+ ADDQ $4, end
+ CMPQ p, end
+ JG try1
+
+ MOVL (p), x
+ ADDQ $4, p
+ IMULQ prime1, x
+ XORQ x, h
+
+ ROLQ $23, h
+ IMULQ prime2, h
+ ADDQ ·primes+16(SB), h
+
+try1:
+ ADDQ $4, end
+ CMPQ p, end
+ JGE finalize
+
+loop1:
+ MOVBQZX (p), x
+ ADDQ $1, p
+ IMULQ ·primes+32(SB), x
+ XORQ x, h
+ ROLQ $11, h
+ IMULQ prime1, h
+
+ CMPQ p, end
+ JL loop1
+
+finalize:
+ MOVQ h, x
+ SHRQ $33, x
+ XORQ x, h
+ IMULQ prime2, h
+ MOVQ h, x
+ SHRQ $29, x
+ XORQ x, h
+ IMULQ ·primes+16(SB), h
+ MOVQ h, x
+ SHRQ $32, x
+ XORQ x, h
+
+ MOVQ h, ret+24(FP)
+ RET
+
+// func writeBlocks(d *Digest, b []byte) int
+TEXT ·writeBlocks(SB), NOSPLIT|NOFRAME, $0-40
+ // Load fixed primes needed for round.
+ MOVQ ·primes+0(SB), prime1
+ MOVQ ·primes+8(SB), prime2
+
+ // Load slice.
+ MOVQ b_base+8(FP), p
+ MOVQ b_len+16(FP), n
+ LEAQ (p)(n*1), end
+ SUBQ $32, end
+
+ // Load vN from d.
+ MOVQ s+0(FP), d
+ MOVQ 0(d), v1
+ MOVQ 8(d), v2
+ MOVQ 16(d), v3
+ MOVQ 24(d), v4
+
+ // We don't need to check the loop condition here; this function is
+ // always called with at least one block of data to process.
+ blockLoop()
+
+ // Copy vN back to d.
+ MOVQ v1, 0(d)
+ MOVQ v2, 8(d)
+ MOVQ v3, 16(d)
+ MOVQ v4, 24(d)
+
+ // The number of bytes written is p minus the old base pointer.
+ SUBQ b_base+8(FP), p
+ MOVQ p, ret+32(FP)
+
+ RET
diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_arm64.s b/vendor/github.com/cespare/xxhash/v2/xxhash_arm64.s
new file mode 100644
index 000000000..7e3145a22
--- /dev/null
+++ b/vendor/github.com/cespare/xxhash/v2/xxhash_arm64.s
@@ -0,0 +1,183 @@
+//go:build !appengine && gc && !purego
+// +build !appengine
+// +build gc
+// +build !purego
+
+#include "textflag.h"
+
+// Registers:
+#define digest R1
+#define h R2 // return value
+#define p R3 // input pointer
+#define n R4 // input length
+#define nblocks R5 // n / 32
+#define prime1 R7
+#define prime2 R8
+#define prime3 R9
+#define prime4 R10
+#define prime5 R11
+#define v1 R12
+#define v2 R13
+#define v3 R14
+#define v4 R15
+#define x1 R20
+#define x2 R21
+#define x3 R22
+#define x4 R23
+
+#define round(acc, x) \
+ MADD prime2, acc, x, acc \
+ ROR $64-31, acc \
+ MUL prime1, acc
+
+// round0 performs the operation x = round(0, x).
+#define round0(x) \
+ MUL prime2, x \
+ ROR $64-31, x \
+ MUL prime1, x
+
+#define mergeRound(acc, x) \
+ round0(x) \
+ EOR x, acc \
+ MADD acc, prime4, prime1, acc
+
+// blockLoop processes as many 32-byte blocks as possible,
+// updating v1, v2, v3, and v4. It assumes that n >= 32.
+#define blockLoop() \
+ LSR $5, n, nblocks \
+ PCALIGN $16 \
+ loop: \
+ LDP.P 16(p), (x1, x2) \
+ LDP.P 16(p), (x3, x4) \
+ round(v1, x1) \
+ round(v2, x2) \
+ round(v3, x3) \
+ round(v4, x4) \
+ SUB $1, nblocks \
+ CBNZ nblocks, loop
+
+// func Sum64(b []byte) uint64
+TEXT ·Sum64(SB), NOSPLIT|NOFRAME, $0-32
+ LDP b_base+0(FP), (p, n)
+
+ LDP ·primes+0(SB), (prime1, prime2)
+ LDP ·primes+16(SB), (prime3, prime4)
+ MOVD ·primes+32(SB), prime5
+
+ CMP $32, n
+ CSEL LT, prime5, ZR, h // if n < 32 { h = prime5 } else { h = 0 }
+ BLT afterLoop
+
+ ADD prime1, prime2, v1
+ MOVD prime2, v2
+ MOVD $0, v3
+ NEG prime1, v4
+
+ blockLoop()
+
+ ROR $64-1, v1, x1
+ ROR $64-7, v2, x2
+ ADD x1, x2
+ ROR $64-12, v3, x3
+ ROR $64-18, v4, x4
+ ADD x3, x4
+ ADD x2, x4, h
+
+ mergeRound(h, v1)
+ mergeRound(h, v2)
+ mergeRound(h, v3)
+ mergeRound(h, v4)
+
+afterLoop:
+ ADD n, h
+
+ TBZ $4, n, try8
+ LDP.P 16(p), (x1, x2)
+
+ round0(x1)
+
+ // NOTE: here and below, sequencing the EOR after the ROR (using a
+ // rotated register) is worth a small but measurable speedup for small
+ // inputs.
+ ROR $64-27, h
+ EOR x1 @> 64-27, h, h
+ MADD h, prime4, prime1, h
+
+ round0(x2)
+ ROR $64-27, h
+ EOR x2 @> 64-27, h, h
+ MADD h, prime4, prime1, h
+
+try8:
+ TBZ $3, n, try4
+ MOVD.P 8(p), x1
+
+ round0(x1)
+ ROR $64-27, h
+ EOR x1 @> 64-27, h, h
+ MADD h, prime4, prime1, h
+
+try4:
+ TBZ $2, n, try2
+ MOVWU.P 4(p), x2
+
+ MUL prime1, x2
+ ROR $64-23, h
+ EOR x2 @> 64-23, h, h
+ MADD h, prime3, prime2, h
+
+try2:
+ TBZ $1, n, try1
+ MOVHU.P 2(p), x3
+ AND $255, x3, x1
+ LSR $8, x3, x2
+
+ MUL prime5, x1
+ ROR $64-11, h
+ EOR x1 @> 64-11, h, h
+ MUL prime1, h
+
+ MUL prime5, x2
+ ROR $64-11, h
+ EOR x2 @> 64-11, h, h
+ MUL prime1, h
+
+try1:
+ TBZ $0, n, finalize
+ MOVBU (p), x4
+
+ MUL prime5, x4
+ ROR $64-11, h
+ EOR x4 @> 64-11, h, h
+ MUL prime1, h
+
+finalize:
+ EOR h >> 33, h
+ MUL prime2, h
+ EOR h >> 29, h
+ MUL prime3, h
+ EOR h >> 32, h
+
+ MOVD h, ret+24(FP)
+ RET
+
+// func writeBlocks(d *Digest, b []byte) int
+TEXT ·writeBlocks(SB), NOSPLIT|NOFRAME, $0-40
+ LDP ·primes+0(SB), (prime1, prime2)
+
+ // Load state. Assume v[1-4] are stored contiguously.
+ MOVD d+0(FP), digest
+ LDP 0(digest), (v1, v2)
+ LDP 16(digest), (v3, v4)
+
+ LDP b_base+8(FP), (p, n)
+
+ blockLoop()
+
+ // Store updated state.
+ STP (v1, v2), 0(digest)
+ STP (v3, v4), 16(digest)
+
+ BIC $31, n
+ MOVD n, ret+32(FP)
+ RET
diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_asm.go b/vendor/github.com/cespare/xxhash/v2/xxhash_asm.go
new file mode 100644
index 000000000..9216e0a40
--- /dev/null
+++ b/vendor/github.com/cespare/xxhash/v2/xxhash_asm.go
@@ -0,0 +1,15 @@
+//go:build (amd64 || arm64) && !appengine && gc && !purego
+// +build amd64 arm64
+// +build !appengine
+// +build gc
+// +build !purego
+
+package xxhash
+
+// Sum64 computes the 64-bit xxHash digest of b.
+//
+//go:noescape
+func Sum64(b []byte) uint64
+
+//go:noescape
+func writeBlocks(d *Digest, b []byte) int
diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_other.go b/vendor/github.com/cespare/xxhash/v2/xxhash_other.go
new file mode 100644
index 000000000..26df13bba
--- /dev/null
+++ b/vendor/github.com/cespare/xxhash/v2/xxhash_other.go
@@ -0,0 +1,76 @@
+//go:build (!amd64 && !arm64) || appengine || !gc || purego
+// +build !amd64,!arm64 appengine !gc purego
+
+package xxhash
+
+// Sum64 computes the 64-bit xxHash digest of b.
+func Sum64(b []byte) uint64 {
+ // A simpler version would be
+ // d := New()
+ // d.Write(b)
+ // return d.Sum64()
+ // but this is faster, particularly for small inputs.
+
+ n := len(b)
+ var h uint64
+
+ if n >= 32 {
+ v1 := primes[0] + prime2
+ v2 := prime2
+ v3 := uint64(0)
+ v4 := -primes[0]
+ for len(b) >= 32 {
+ v1 = round(v1, u64(b[0:8:len(b)]))
+ v2 = round(v2, u64(b[8:16:len(b)]))
+ v3 = round(v3, u64(b[16:24:len(b)]))
+ v4 = round(v4, u64(b[24:32:len(b)]))
+ b = b[32:len(b):len(b)]
+ }
+ h = rol1(v1) + rol7(v2) + rol12(v3) + rol18(v4)
+ h = mergeRound(h, v1)
+ h = mergeRound(h, v2)
+ h = mergeRound(h, v3)
+ h = mergeRound(h, v4)
+ } else {
+ h = prime5
+ }
+
+ h += uint64(n)
+
+ for ; len(b) >= 8; b = b[8:] {
+ k1 := round(0, u64(b[:8]))
+ h ^= k1
+ h = rol27(h)*prime1 + prime4
+ }
+ if len(b) >= 4 {
+ h ^= uint64(u32(b[:4])) * prime1
+ h = rol23(h)*prime2 + prime3
+ b = b[4:]
+ }
+ for ; len(b) > 0; b = b[1:] {
+ h ^= uint64(b[0]) * prime5
+ h = rol11(h) * prime1
+ }
+
+ h ^= h >> 33
+ h *= prime2
+ h ^= h >> 29
+ h *= prime3
+ h ^= h >> 32
+
+ return h
+}
+
+func writeBlocks(d *Digest, b []byte) int {
+ v1, v2, v3, v4 := d.v1, d.v2, d.v3, d.v4
+ n := len(b)
+ for len(b) >= 32 {
+ v1 = round(v1, u64(b[0:8:len(b)]))
+ v2 = round(v2, u64(b[8:16:len(b)]))
+ v3 = round(v3, u64(b[16:24:len(b)]))
+ v4 = round(v4, u64(b[24:32:len(b)]))
+ b = b[32:len(b):len(b)]
+ }
+ d.v1, d.v2, d.v3, d.v4 = v1, v2, v3, v4
+ return n - len(b)
+}
diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_safe.go b/vendor/github.com/cespare/xxhash/v2/xxhash_safe.go
new file mode 100644
index 000000000..e86f1b5fd
--- /dev/null
+++ b/vendor/github.com/cespare/xxhash/v2/xxhash_safe.go
@@ -0,0 +1,16 @@
+//go:build appengine
+// +build appengine
+
+// This file contains the safe implementations of otherwise unsafe-using code.
+
+package xxhash
+
+// Sum64String computes the 64-bit xxHash digest of s.
+func Sum64String(s string) uint64 {
+ return Sum64([]byte(s))
+}
+
+// WriteString adds more data to d. It always returns len(s), nil.
+func (d *Digest) WriteString(s string) (n int, err error) {
+ return d.Write([]byte(s))
+}
diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_unsafe.go b/vendor/github.com/cespare/xxhash/v2/xxhash_unsafe.go
new file mode 100644
index 000000000..1c1638fd8
--- /dev/null
+++ b/vendor/github.com/cespare/xxhash/v2/xxhash_unsafe.go
@@ -0,0 +1,58 @@
+//go:build !appengine
+// +build !appengine
+
+// This file encapsulates usage of unsafe.
+// xxhash_safe.go contains the safe implementations.
+
+package xxhash
+
+import (
+ "unsafe"
+)
+
+// In the future it's possible that compiler optimizations will make these
+// XxxString functions unnecessary by realizing that calls such as
+// Sum64([]byte(s)) don't need to copy s. See https://go.dev/issue/2205.
+// If that happens, even if we keep these functions they can be replaced with
+// the trivial safe code.
+
+// NOTE: The usual way of doing an unsafe string-to-[]byte conversion is:
+//
+// var b []byte
+// bh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
+// bh.Data = (*reflect.StringHeader)(unsafe.Pointer(&s)).Data
+// bh.Len = len(s)
+// bh.Cap = len(s)
+//
+// Unfortunately, as of Go 1.15.3 the inliner's cost model assigns a high enough
+// weight to this sequence of expressions that any function that uses it will
+// not be inlined. Instead, the functions below use a different unsafe
+// conversion designed to minimize the inliner weight and allow both to be
+// inlined. There is also a test (TestInlining) which verifies that these are
+// inlined.
+//
+// See https://github.com/golang/go/issues/42739 for discussion.
+
+// Sum64String computes the 64-bit xxHash digest of s.
+// It may be faster than Sum64([]byte(s)) by avoiding a copy.
+func Sum64String(s string) uint64 {
+ b := *(*[]byte)(unsafe.Pointer(&sliceHeader{s, len(s)}))
+ return Sum64(b)
+}
+
+// WriteString adds more data to d. It always returns len(s), nil.
+// It may be faster than Write([]byte(s)) by avoiding a copy.
+func (d *Digest) WriteString(s string) (n int, err error) {
+ d.Write(*(*[]byte)(unsafe.Pointer(&sliceHeader{s, len(s)})))
+ // d.Write always returns len(s), nil.
+ // Ignoring the return output and returning these fixed values buys a
+ // savings of 6 in the inliner's cost model.
+ return len(s), nil
+}
+
+// sliceHeader is similar to reflect.SliceHeader, but it assumes that the layout
+// of the first two words is the same as the layout of a string.
+type sliceHeader struct {
+ s string
+ cap int
+}
diff --git a/vendor/github.com/evanphx/json-patch/v5/internal/json/decode.go b/vendor/github.com/evanphx/json-patch/v5/internal/json/decode.go
new file mode 100644
index 000000000..e9bb0efe7
--- /dev/null
+++ b/vendor/github.com/evanphx/json-patch/v5/internal/json/decode.go
@@ -0,0 +1,1385 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Represents JSON data structure using native Go types: booleans, floats,
+// strings, arrays, and maps.
+
+package json
+
+import (
+ "encoding"
+ "encoding/base64"
+ "fmt"
+ "reflect"
+ "strconv"
+ "strings"
+ "sync"
+ "unicode"
+ "unicode/utf16"
+ "unicode/utf8"
+)
+
+// Unmarshal parses the JSON-encoded data and stores the result
+// in the value pointed to by v. If v is nil or not a pointer,
+// Unmarshal returns an InvalidUnmarshalError.
+//
+// Unmarshal uses the inverse of the encodings that
+// Marshal uses, allocating maps, slices, and pointers as necessary,
+// with the following additional rules:
+//
+// To unmarshal JSON into a pointer, Unmarshal first handles the case of
+// the JSON being the JSON literal null. In that case, Unmarshal sets
+// the pointer to nil. Otherwise, Unmarshal unmarshals the JSON into
+// the value pointed at by the pointer. If the pointer is nil, Unmarshal
+// allocates a new value for it to point to.
+//
+// To unmarshal JSON into a value implementing the Unmarshaler interface,
+// Unmarshal calls that value's UnmarshalJSON method, including
+// when the input is a JSON null.
+// Otherwise, if the value implements encoding.TextUnmarshaler
+// and the input is a JSON quoted string, Unmarshal calls that value's
+// UnmarshalText method with the unquoted form of the string.
+//
+// To unmarshal JSON into a struct, Unmarshal matches incoming object
+// keys to the keys used by Marshal (either the struct field name or its tag),
+// preferring an exact match but also accepting a case-insensitive match. By
+// default, object keys which don't have a corresponding struct field are
+// ignored (see Decoder.DisallowUnknownFields for an alternative).
+//
+// To unmarshal JSON into an interface value,
+// Unmarshal stores one of these in the interface value:
+//
+// bool, for JSON booleans
+// float64, for JSON numbers
+// string, for JSON strings
+// []interface{}, for JSON arrays
+// map[string]interface{}, for JSON objects
+// nil for JSON null
+//
+// To unmarshal a JSON array into a slice, Unmarshal resets the slice length
+// to zero and then appends each element to the slice.
+// As a special case, to unmarshal an empty JSON array into a slice,
+// Unmarshal replaces the slice with a new empty slice.
+//
+// To unmarshal a JSON array into a Go array, Unmarshal decodes
+// JSON array elements into corresponding Go array elements.
+// If the Go array is smaller than the JSON array,
+// the additional JSON array elements are discarded.
+// If the JSON array is smaller than the Go array,
+// the additional Go array elements are set to zero values.
+//
+// To unmarshal a JSON object into a map, Unmarshal first establishes a map to
+// use. If the map is nil, Unmarshal allocates a new map. Otherwise Unmarshal
+// reuses the existing map, keeping existing entries. Unmarshal then stores
+// key-value pairs from the JSON object into the map. The map's key type must
+// either be any string type, an integer, implement json.Unmarshaler, or
+// implement encoding.TextUnmarshaler.
+//
+// If the JSON-encoded data contain a syntax error, Unmarshal returns a SyntaxError.
+//
+// If a JSON value is not appropriate for a given target type,
+// or if a JSON number overflows the target type, Unmarshal
+// skips that field and completes the unmarshaling as best it can.
+// If no more serious errors are encountered, Unmarshal returns
+// an UnmarshalTypeError describing the earliest such error. In any
+// case, it's not guaranteed that all the remaining fields following
+// the problematic one will be unmarshaled into the target object.
+//
+// The JSON null value unmarshals into an interface, map, pointer, or slice
+// by setting that Go value to nil. Because null is often used in JSON to mean
+// “not present,” unmarshaling a JSON null into any other Go type has no effect
+// on the value and produces no error.
+//
+// When unmarshaling quoted strings, invalid UTF-8 or
+// invalid UTF-16 surrogate pairs are not treated as an error.
+// Instead, they are replaced by the Unicode replacement
+// character U+FFFD.
+func Unmarshal(data []byte, v any) error {
+ // Check for well-formedness.
+ // Avoids filling out half a data structure
+ // before discovering a JSON syntax error.
+ d := ds.Get().(*decodeState)
+ defer ds.Put(d)
+ //var d decodeState
+ d.useNumber = true
+ err := checkValid(data, &d.scan)
+ if err != nil {
+ return err
+ }
+
+ d.init(data)
+ return d.unmarshal(v)
+}
+
+var ds = sync.Pool{
+ New: func() any {
+ return new(decodeState)
+ },
+}
+
+func UnmarshalWithKeys(data []byte, v any) ([]string, error) {
+ // Check for well-formedness.
+ // Avoids filling out half a data structure
+ // before discovering a JSON syntax error.
+
+ d := ds.Get().(*decodeState)
+ defer ds.Put(d)
+ //var d decodeState
+ d.useNumber = true
+ err := checkValid(data, &d.scan)
+ if err != nil {
+ return nil, err
+ }
+
+ d.init(data)
+ err = d.unmarshal(v)
+ if err != nil {
+ return nil, err
+ }
+
+ return d.lastKeys, nil
+}
+
+func UnmarshalValid(data []byte, v any) error {
+ // Check for well-formedness.
+ // Avoids filling out half a data structure
+ // before discovering a JSON syntax error.
+ d := ds.Get().(*decodeState)
+ defer ds.Put(d)
+ //var d decodeState
+ d.useNumber = true
+
+ d.init(data)
+ return d.unmarshal(v)
+}
+
+func UnmarshalValidWithKeys(data []byte, v any) ([]string, error) {
+ // Check for well-formedness.
+ // Avoids filling out half a data structure
+ // before discovering a JSON syntax error.
+
+ d := ds.Get().(*decodeState)
+ defer ds.Put(d)
+ //var d decodeState
+ d.useNumber = true
+
+ d.init(data)
+ err := d.unmarshal(v)
+ if err != nil {
+ return nil, err
+ }
+
+ return d.lastKeys, nil
+}
+
+// Unmarshaler is the interface implemented by types
+// that can unmarshal a JSON description of themselves.
+// The input can be assumed to be a valid encoding of
+// a JSON value. UnmarshalJSON must copy the JSON data
+// if it wishes to retain the data after returning.
+//
+// By convention, to approximate the behavior of Unmarshal itself,
+// Unmarshalers implement UnmarshalJSON([]byte("null")) as a no-op.
+type Unmarshaler interface {
+ UnmarshalJSON([]byte) error
+}
+
+// An UnmarshalTypeError describes a JSON value that was
+// not appropriate for a value of a specific Go type.
+type UnmarshalTypeError struct {
+ Value string // description of JSON value - "bool", "array", "number -5"
+ Type reflect.Type // type of Go value it could not be assigned to
+ Offset int64 // error occurred after reading Offset bytes
+ Struct string // name of the struct type containing the field
+ Field string // the full path from root node to the field
+}
+
+func (e *UnmarshalTypeError) Error() string {
+ if e.Struct != "" || e.Field != "" {
+ return "json: cannot unmarshal " + e.Value + " into Go struct field " + e.Struct + "." + e.Field + " of type " + e.Type.String()
+ }
+ return "json: cannot unmarshal " + e.Value + " into Go value of type " + e.Type.String()
+}
+
+// An UnmarshalFieldError describes a JSON object key that
+// led to an unexported (and therefore unwritable) struct field.
+//
+// Deprecated: No longer used; kept for compatibility.
+type UnmarshalFieldError struct {
+ Key string
+ Type reflect.Type
+ Field reflect.StructField
+}
+
+func (e *UnmarshalFieldError) Error() string {
+ return "json: cannot unmarshal object key " + strconv.Quote(e.Key) + " into unexported field " + e.Field.Name + " of type " + e.Type.String()
+}
+
+// An InvalidUnmarshalError describes an invalid argument passed to Unmarshal.
+// (The argument to Unmarshal must be a non-nil pointer.)
+type InvalidUnmarshalError struct {
+ Type reflect.Type
+}
+
+func (e *InvalidUnmarshalError) Error() string {
+ if e.Type == nil {
+ return "json: Unmarshal(nil)"
+ }
+
+ if e.Type.Kind() != reflect.Pointer {
+ return "json: Unmarshal(non-pointer " + e.Type.String() + ")"
+ }
+ return "json: Unmarshal(nil " + e.Type.String() + ")"
+}
+
+func (d *decodeState) unmarshal(v any) error {
+ rv := reflect.ValueOf(v)
+ if rv.Kind() != reflect.Pointer || rv.IsNil() {
+ return &InvalidUnmarshalError{reflect.TypeOf(v)}
+ }
+
+ d.scan.reset()
+ d.scanWhile(scanSkipSpace)
+ // We decode rv not rv.Elem because the Unmarshaler interface
+ // test must be applied at the top level of the value.
+ err := d.value(rv)
+ if err != nil {
+ return d.addErrorContext(err)
+ }
+ return d.savedError
+}
+
+// A Number represents a JSON number literal.
+type Number string
+
+// String returns the literal text of the number.
+func (n Number) String() string { return string(n) }
+
+// Float64 returns the number as a float64.
+func (n Number) Float64() (float64, error) {
+ return strconv.ParseFloat(string(n), 64)
+}
+
+// Int64 returns the number as an int64.
+func (n Number) Int64() (int64, error) {
+ return strconv.ParseInt(string(n), 10, 64)
+}
+
+// An errorContext provides context for type errors during decoding.
+type errorContext struct {
+ Struct reflect.Type
+ FieldStack []string
+}
+
+// decodeState represents the state while decoding a JSON value.
+type decodeState struct {
+ data []byte
+ off int // next read offset in data
+ opcode int // last read result
+ scan scanner
+ errorContext *errorContext
+ savedError error
+ useNumber bool
+ disallowUnknownFields bool
+ lastKeys []string
+}
+
+// readIndex returns the position of the last byte read.
+func (d *decodeState) readIndex() int {
+ return d.off - 1
+}
+
+// phasePanicMsg is used as a panic message when we end up with something that
+// shouldn't happen. It can indicate a bug in the JSON decoder, or that
+// something is editing the data slice while the decoder executes.
+const phasePanicMsg = "JSON decoder out of sync - data changing underfoot?"
+
+func (d *decodeState) init(data []byte) *decodeState {
+ d.data = data
+ d.off = 0
+ d.savedError = nil
+ if d.errorContext != nil {
+ d.errorContext.Struct = nil
+ // Reuse the allocated space for the FieldStack slice.
+ d.errorContext.FieldStack = d.errorContext.FieldStack[:0]
+ }
+ return d
+}
+
+// saveError saves the first err it is called with,
+// for reporting at the end of the unmarshal.
+func (d *decodeState) saveError(err error) {
+ if d.savedError == nil {
+ d.savedError = d.addErrorContext(err)
+ }
+}
+
+// addErrorContext returns a new error enhanced with information from d.errorContext
+func (d *decodeState) addErrorContext(err error) error {
+ if d.errorContext != nil && (d.errorContext.Struct != nil || len(d.errorContext.FieldStack) > 0) {
+ switch err := err.(type) {
+ case *UnmarshalTypeError:
+ err.Struct = d.errorContext.Struct.Name()
+ err.Field = strings.Join(d.errorContext.FieldStack, ".")
+ }
+ }
+ return err
+}
+
+// skip scans to the end of what was started.
+func (d *decodeState) skip() {
+ s, data, i := &d.scan, d.data, d.off
+ depth := len(s.parseState)
+ for {
+ op := s.step(s, data[i])
+ i++
+ if len(s.parseState) < depth {
+ d.off = i
+ d.opcode = op
+ return
+ }
+ }
+}
+
+// scanNext processes the byte at d.data[d.off].
+func (d *decodeState) scanNext() {
+ if d.off < len(d.data) {
+ d.opcode = d.scan.step(&d.scan, d.data[d.off])
+ d.off++
+ } else {
+ d.opcode = d.scan.eof()
+ d.off = len(d.data) + 1 // mark processed EOF with len+1
+ }
+}
+
+// scanWhile processes bytes in d.data[d.off:] until it
+// receives a scan code not equal to op.
+func (d *decodeState) scanWhile(op int) {
+ s, data, i := &d.scan, d.data, d.off
+ for i < len(data) {
+ newOp := s.step(s, data[i])
+ i++
+ if newOp != op {
+ d.opcode = newOp
+ d.off = i
+ return
+ }
+ }
+
+ d.off = len(data) + 1 // mark processed EOF with len+1
+ d.opcode = d.scan.eof()
+}
+
+// rescanLiteral is similar to scanWhile(scanContinue), but it specialises the
+// common case where we're decoding a literal. The decoder scans the input
+// twice, once for syntax errors and to check the length of the value, and the
+// second to perform the decoding.
+//
+// Only in the second step do we use decodeState to tokenize literals, so we
+// know there aren't any syntax errors. We can take advantage of that knowledge,
+// and scan a literal's bytes much more quickly.
+func (d *decodeState) rescanLiteral() {
+ data, i := d.data, d.off
+Switch:
+ switch data[i-1] {
+ case '"': // string
+ for ; i < len(data); i++ {
+ switch data[i] {
+ case '\\':
+ i++ // escaped char
+ case '"':
+ i++ // tokenize the closing quote too
+ break Switch
+ }
+ }
+ case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-': // number
+ for ; i < len(data); i++ {
+ switch data[i] {
+ case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ '.', 'e', 'E', '+', '-':
+ default:
+ break Switch
+ }
+ }
+ case 't': // true
+ i += len("rue")
+ case 'f': // false
+ i += len("alse")
+ case 'n': // null
+ i += len("ull")
+ }
+ if i < len(data) {
+ d.opcode = stateEndValue(&d.scan, data[i])
+ } else {
+ d.opcode = scanEnd
+ }
+ d.off = i + 1
+}
+
+// value consumes a JSON value from d.data[d.off-1:], decoding into v, and
+// reads the following byte ahead. If v is invalid, the value is discarded.
+// The first byte of the value has been read already.
+func (d *decodeState) value(v reflect.Value) error {
+ switch d.opcode {
+ default:
+ panic(phasePanicMsg)
+
+ case scanBeginArray:
+ if v.IsValid() {
+ if err := d.array(v); err != nil {
+ return err
+ }
+ } else {
+ d.skip()
+ }
+ d.scanNext()
+
+ case scanBeginObject:
+ if v.IsValid() {
+ if err := d.object(v); err != nil {
+ return err
+ }
+ } else {
+ d.skip()
+ }
+ d.scanNext()
+
+ case scanBeginLiteral:
+ // All bytes inside literal return scanContinue op code.
+ start := d.readIndex()
+ d.rescanLiteral()
+
+ if v.IsValid() {
+ if err := d.literalStore(d.data[start:d.readIndex()], v, false); err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
+
+type unquotedValue struct{}
+
+// valueQuoted is like value but decodes a
+// quoted string literal or literal null into an interface value.
+// If it finds anything other than a quoted string literal or null,
+// valueQuoted returns unquotedValue{}.
+func (d *decodeState) valueQuoted() any {
+ switch d.opcode {
+ default:
+ panic(phasePanicMsg)
+
+ case scanBeginArray, scanBeginObject:
+ d.skip()
+ d.scanNext()
+
+ case scanBeginLiteral:
+ v := d.literalInterface()
+ switch v.(type) {
+ case nil, string:
+ return v
+ }
+ }
+ return unquotedValue{}
+}
+
+// indirect walks down v allocating pointers as needed,
+// until it gets to a non-pointer.
+// If it encounters an Unmarshaler, indirect stops and returns that.
+// If decodingNull is true, indirect stops at the first settable pointer so it
+// can be set to nil.
+func indirect(v reflect.Value, decodingNull bool) (Unmarshaler, encoding.TextUnmarshaler, reflect.Value) {
+ // Issue #24153 indicates that it is generally not a guaranteed property
+ // that you may round-trip a reflect.Value by calling Value.Addr().Elem()
+ // and expect the value to still be settable for values derived from
+ // unexported embedded struct fields.
+ //
+ // The logic below effectively does this when it first addresses the value
+ // (to satisfy possible pointer methods) and continues to dereference
+ // subsequent pointers as necessary.
+ //
+ // After the first round-trip, we set v back to the original value to
+ // preserve the original RW flags contained in reflect.Value.
+ v0 := v
+ haveAddr := false
+
+ // If v is a named type and is addressable,
+ // start with its address, so that if the type has pointer methods,
+ // we find them.
+ if v.Kind() != reflect.Pointer && v.Type().Name() != "" && v.CanAddr() {
+ haveAddr = true
+ v = v.Addr()
+ }
+ for {
+ // Load value from interface, but only if the result will be
+ // usefully addressable.
+ if v.Kind() == reflect.Interface && !v.IsNil() {
+ e := v.Elem()
+ if e.Kind() == reflect.Pointer && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Pointer) {
+ haveAddr = false
+ v = e
+ continue
+ }
+ }
+
+ if v.Kind() != reflect.Pointer {
+ break
+ }
+
+ if decodingNull && v.CanSet() {
+ break
+ }
+
+ // Prevent infinite loop if v is an interface pointing to its own address:
+ // var v interface{}
+ // v = &v
+ if v.Elem().Kind() == reflect.Interface && v.Elem().Elem() == v {
+ v = v.Elem()
+ break
+ }
+ if v.IsNil() {
+ v.Set(reflect.New(v.Type().Elem()))
+ }
+ if v.Type().NumMethod() > 0 && v.CanInterface() {
+ if u, ok := v.Interface().(Unmarshaler); ok {
+ return u, nil, reflect.Value{}
+ }
+ if !decodingNull {
+ if u, ok := v.Interface().(encoding.TextUnmarshaler); ok {
+ return nil, u, reflect.Value{}
+ }
+ }
+ }
+
+ if haveAddr {
+ v = v0 // restore original value after round-trip Value.Addr().Elem()
+ haveAddr = false
+ } else {
+ v = v.Elem()
+ }
+ }
+ return nil, nil, v
+}
+
+// array consumes an array from d.data[d.off-1:], decoding into v.
+// The first byte of the array ('[') has been read already.
+func (d *decodeState) array(v reflect.Value) error {
+ // Check for unmarshaler.
+ u, ut, pv := indirect(v, false)
+ if u != nil {
+ start := d.readIndex()
+ d.skip()
+ return u.UnmarshalJSON(d.data[start:d.off])
+ }
+ if ut != nil {
+ d.saveError(&UnmarshalTypeError{Value: "array", Type: v.Type(), Offset: int64(d.off)})
+ d.skip()
+ return nil
+ }
+ v = pv
+
+ // Check type of target.
+ switch v.Kind() {
+ case reflect.Interface:
+ if v.NumMethod() == 0 {
+ // Decoding into nil interface? Switch to non-reflect code.
+ ai := d.arrayInterface()
+ v.Set(reflect.ValueOf(ai))
+ return nil
+ }
+ // Otherwise it's invalid.
+ fallthrough
+ default:
+ d.saveError(&UnmarshalTypeError{Value: "array", Type: v.Type(), Offset: int64(d.off)})
+ d.skip()
+ return nil
+ case reflect.Array, reflect.Slice:
+ break
+ }
+
+ i := 0
+ for {
+ // Look ahead for ] - can only happen on first iteration.
+ d.scanWhile(scanSkipSpace)
+ if d.opcode == scanEndArray {
+ break
+ }
+
+ // Get element of array, growing if necessary.
+ if v.Kind() == reflect.Slice {
+ // Grow slice if necessary
+ if i >= v.Cap() {
+ newcap := v.Cap() + v.Cap()/2
+ if newcap < 4 {
+ newcap = 4
+ }
+ newv := reflect.MakeSlice(v.Type(), v.Len(), newcap)
+ reflect.Copy(newv, v)
+ v.Set(newv)
+ }
+ if i >= v.Len() {
+ v.SetLen(i + 1)
+ }
+ }
+
+ if i < v.Len() {
+ // Decode into element.
+ if err := d.value(v.Index(i)); err != nil {
+ return err
+ }
+ } else {
+ // Ran out of fixed array: skip.
+ if err := d.value(reflect.Value{}); err != nil {
+ return err
+ }
+ }
+ i++
+
+ // Next token must be , or ].
+ if d.opcode == scanSkipSpace {
+ d.scanWhile(scanSkipSpace)
+ }
+ if d.opcode == scanEndArray {
+ break
+ }
+ if d.opcode != scanArrayValue {
+ panic(phasePanicMsg)
+ }
+ }
+
+ if i < v.Len() {
+ if v.Kind() == reflect.Array {
+ // Array. Zero the rest.
+ z := reflect.Zero(v.Type().Elem())
+ for ; i < v.Len(); i++ {
+ v.Index(i).Set(z)
+ }
+ } else {
+ v.SetLen(i)
+ }
+ }
+ if i == 0 && v.Kind() == reflect.Slice {
+ v.Set(reflect.MakeSlice(v.Type(), 0, 0))
+ }
+ return nil
+}
+
+var nullLiteral = []byte("null")
+var textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
+
+// object consumes an object from d.data[d.off-1:], decoding into v.
+// The first byte ('{') of the object has been read already.
+func (d *decodeState) object(v reflect.Value) error {
+ // Check for unmarshaler.
+ u, ut, pv := indirect(v, false)
+ if u != nil {
+ start := d.readIndex()
+ d.skip()
+ return u.UnmarshalJSON(d.data[start:d.off])
+ }
+ if ut != nil {
+ d.saveError(&UnmarshalTypeError{Value: "object", Type: v.Type(), Offset: int64(d.off)})
+ d.skip()
+ return nil
+ }
+ v = pv
+ t := v.Type()
+
+ // Decoding into nil interface? Switch to non-reflect code.
+ if v.Kind() == reflect.Interface && v.NumMethod() == 0 {
+ oi := d.objectInterface()
+ v.Set(reflect.ValueOf(oi))
+ return nil
+ }
+
+ var fields structFields
+
+ // Check type of target:
+ // struct or
+ // map[T1]T2 where T1 is string, an integer type,
+ // or an encoding.TextUnmarshaler
+ switch v.Kind() {
+ case reflect.Map:
+ // Map key must either have string kind, have an integer kind,
+ // or be an encoding.TextUnmarshaler.
+ switch t.Key().Kind() {
+ case reflect.String,
+ reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
+ reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ default:
+ if !reflect.PointerTo(t.Key()).Implements(textUnmarshalerType) {
+ d.saveError(&UnmarshalTypeError{Value: "object", Type: t, Offset: int64(d.off)})
+ d.skip()
+ return nil
+ }
+ }
+ if v.IsNil() {
+ v.Set(reflect.MakeMap(t))
+ }
+ case reflect.Struct:
+ fields = cachedTypeFields(t)
+ // ok
+ default:
+ d.saveError(&UnmarshalTypeError{Value: "object", Type: t, Offset: int64(d.off)})
+ d.skip()
+ return nil
+ }
+
+ var mapElem reflect.Value
+ var origErrorContext errorContext
+ if d.errorContext != nil {
+ origErrorContext = *d.errorContext
+ }
+
+ var keys []string
+
+ for {
+ // Read opening " of string key or closing }.
+ d.scanWhile(scanSkipSpace)
+ if d.opcode == scanEndObject {
+ // closing } - can only happen on first iteration.
+ break
+ }
+ if d.opcode != scanBeginLiteral {
+ panic(phasePanicMsg)
+ }
+
+ // Read key.
+ start := d.readIndex()
+ d.rescanLiteral()
+ item := d.data[start:d.readIndex()]
+ key, ok := unquoteBytes(item)
+ if !ok {
+ panic(phasePanicMsg)
+ }
+
+ keys = append(keys, string(key))
+
+ // Figure out field corresponding to key.
+ var subv reflect.Value
+ destring := false // whether the value is wrapped in a string to be decoded first
+
+ if v.Kind() == reflect.Map {
+ elemType := t.Elem()
+ if !mapElem.IsValid() {
+ mapElem = reflect.New(elemType).Elem()
+ } else {
+ mapElem.Set(reflect.Zero(elemType))
+ }
+ subv = mapElem
+ } else {
+ var f *field
+ if i, ok := fields.nameIndex[string(key)]; ok {
+ // Found an exact name match.
+ f = &fields.list[i]
+ } else {
+ // Fall back to the expensive case-insensitive
+ // linear search.
+ for i := range fields.list {
+ ff := &fields.list[i]
+ if ff.equalFold(ff.nameBytes, key) {
+ f = ff
+ break
+ }
+ }
+ }
+ if f != nil {
+ subv = v
+ destring = f.quoted
+ for _, i := range f.index {
+ if subv.Kind() == reflect.Pointer {
+ if subv.IsNil() {
+ // If a struct embeds a pointer to an unexported type,
+ // it is not possible to set a newly allocated value
+ // since the field is unexported.
+ //
+ // See https://golang.org/issue/21357
+ if !subv.CanSet() {
+ d.saveError(fmt.Errorf("json: cannot set embedded pointer to unexported struct: %v", subv.Type().Elem()))
+ // Invalidate subv to ensure d.value(subv) skips over
+ // the JSON value without assigning it to subv.
+ subv = reflect.Value{}
+ destring = false
+ break
+ }
+ subv.Set(reflect.New(subv.Type().Elem()))
+ }
+ subv = subv.Elem()
+ }
+ subv = subv.Field(i)
+ }
+ if d.errorContext == nil {
+ d.errorContext = new(errorContext)
+ }
+ d.errorContext.FieldStack = append(d.errorContext.FieldStack, f.name)
+ d.errorContext.Struct = t
+ } else if d.disallowUnknownFields {
+ d.saveError(fmt.Errorf("json: unknown field %q", key))
+ }
+ }
+
+ // Read : before value.
+ if d.opcode == scanSkipSpace {
+ d.scanWhile(scanSkipSpace)
+ }
+ if d.opcode != scanObjectKey {
+ panic(phasePanicMsg)
+ }
+ d.scanWhile(scanSkipSpace)
+
+ if destring {
+ switch qv := d.valueQuoted().(type) {
+ case nil:
+ if err := d.literalStore(nullLiteral, subv, false); err != nil {
+ return err
+ }
+ case string:
+ if err := d.literalStore([]byte(qv), subv, true); err != nil {
+ return err
+ }
+ default:
+ d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal unquoted value into %v", subv.Type()))
+ }
+ } else {
+ if err := d.value(subv); err != nil {
+ return err
+ }
+ }
+
+ // Write value back to map;
+ // if using struct, subv points into struct already.
+ if v.Kind() == reflect.Map {
+ kt := t.Key()
+ var kv reflect.Value
+ switch {
+ case reflect.PointerTo(kt).Implements(textUnmarshalerType):
+ kv = reflect.New(kt)
+ if err := d.literalStore(item, kv, true); err != nil {
+ return err
+ }
+ kv = kv.Elem()
+ case kt.Kind() == reflect.String:
+ kv = reflect.ValueOf(key).Convert(kt)
+ default:
+ switch kt.Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ s := string(key)
+ n, err := strconv.ParseInt(s, 10, 64)
+ if err != nil || reflect.Zero(kt).OverflowInt(n) {
+ d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: kt, Offset: int64(start + 1)})
+ break
+ }
+ kv = reflect.ValueOf(n).Convert(kt)
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ s := string(key)
+ n, err := strconv.ParseUint(s, 10, 64)
+ if err != nil || reflect.Zero(kt).OverflowUint(n) {
+ d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: kt, Offset: int64(start + 1)})
+ break
+ }
+ kv = reflect.ValueOf(n).Convert(kt)
+ default:
+ panic("json: Unexpected key type") // should never occur
+ }
+ }
+ if kv.IsValid() {
+ v.SetMapIndex(kv, subv)
+ }
+ }
+
+ // Next token must be , or }.
+ if d.opcode == scanSkipSpace {
+ d.scanWhile(scanSkipSpace)
+ }
+ if d.errorContext != nil {
+ // Reset errorContext to its original state.
+ // Keep the same underlying array for FieldStack, to reuse the
+ // space and avoid unnecessary allocs.
+ d.errorContext.FieldStack = d.errorContext.FieldStack[:len(origErrorContext.FieldStack)]
+ d.errorContext.Struct = origErrorContext.Struct
+ }
+ if d.opcode == scanEndObject {
+ break
+ }
+ if d.opcode != scanObjectValue {
+ panic(phasePanicMsg)
+ }
+ }
+
+ if v.Kind() == reflect.Map {
+ d.lastKeys = keys
+ }
+ return nil
+}
+
+// convertNumber converts the number literal s to a float64 or a Number
+// depending on the setting of d.useNumber.
+func (d *decodeState) convertNumber(s string) (any, error) {
+ if d.useNumber {
+ return Number(s), nil
+ }
+ f, err := strconv.ParseFloat(s, 64)
+ if err != nil {
+ return nil, &UnmarshalTypeError{Value: "number " + s, Type: reflect.TypeOf(0.0), Offset: int64(d.off)}
+ }
+ return f, nil
+}
+
+var numberType = reflect.TypeOf(Number(""))
+
+// literalStore decodes a literal stored in item into v.
+//
+// fromQuoted indicates whether this literal came from unwrapping a
+// string from the ",string" struct tag option. this is used only to
+// produce more helpful error messages.
+func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool) error {
+ // Check for unmarshaler.
+ if len(item) == 0 {
+ //Empty string given
+ d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
+ return nil
+ }
+ isNull := item[0] == 'n' // null
+ u, ut, pv := indirect(v, isNull)
+ if u != nil {
+ return u.UnmarshalJSON(item)
+ }
+ if ut != nil {
+ if item[0] != '"' {
+ if fromQuoted {
+ d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
+ return nil
+ }
+ val := "number"
+ switch item[0] {
+ case 'n':
+ val = "null"
+ case 't', 'f':
+ val = "bool"
+ }
+ d.saveError(&UnmarshalTypeError{Value: val, Type: v.Type(), Offset: int64(d.readIndex())})
+ return nil
+ }
+ s, ok := unquoteBytes(item)
+ if !ok {
+ if fromQuoted {
+ return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())
+ }
+ panic(phasePanicMsg)
+ }
+ return ut.UnmarshalText(s)
+ }
+
+ v = pv
+
+ switch c := item[0]; c {
+ case 'n': // null
+ // The main parser checks that only true and false can reach here,
+ // but if this was a quoted string input, it could be anything.
+ if fromQuoted && string(item) != "null" {
+ d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
+ break
+ }
+ switch v.Kind() {
+ case reflect.Interface, reflect.Pointer, reflect.Map, reflect.Slice:
+ v.Set(reflect.Zero(v.Type()))
+ // otherwise, ignore null for primitives/string
+ }
+ case 't', 'f': // true, false
+ value := item[0] == 't'
+ // The main parser checks that only true and false can reach here,
+ // but if this was a quoted string input, it could be anything.
+ if fromQuoted && string(item) != "true" && string(item) != "false" {
+ d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
+ break
+ }
+ switch v.Kind() {
+ default:
+ if fromQuoted {
+ d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
+ } else {
+ d.saveError(&UnmarshalTypeError{Value: "bool", Type: v.Type(), Offset: int64(d.readIndex())})
+ }
+ case reflect.Bool:
+ v.SetBool(value)
+ case reflect.Interface:
+ if v.NumMethod() == 0 {
+ v.Set(reflect.ValueOf(value))
+ } else {
+ d.saveError(&UnmarshalTypeError{Value: "bool", Type: v.Type(), Offset: int64(d.readIndex())})
+ }
+ }
+
+ case '"': // string
+ s, ok := unquoteBytes(item)
+ if !ok {
+ if fromQuoted {
+ return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())
+ }
+ panic(phasePanicMsg)
+ }
+ switch v.Kind() {
+ default:
+ d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.readIndex())})
+ case reflect.Slice:
+ if v.Type().Elem().Kind() != reflect.Uint8 {
+ d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.readIndex())})
+ break
+ }
+ b := make([]byte, base64.StdEncoding.DecodedLen(len(s)))
+ n, err := base64.StdEncoding.Decode(b, s)
+ if err != nil {
+ d.saveError(err)
+ break
+ }
+ v.SetBytes(b[:n])
+ case reflect.String:
+ if v.Type() == numberType && !isValidNumber(string(s)) {
+ return fmt.Errorf("json: invalid number literal, trying to unmarshal %q into Number", item)
+ }
+ v.SetString(string(s))
+ case reflect.Interface:
+ if v.NumMethod() == 0 {
+ v.Set(reflect.ValueOf(string(s)))
+ } else {
+ d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.readIndex())})
+ }
+ }
+
+ default: // number
+ if c != '-' && (c < '0' || c > '9') {
+ if fromQuoted {
+ return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())
+ }
+ panic(phasePanicMsg)
+ }
+ s := string(item)
+ switch v.Kind() {
+ default:
+ if v.Kind() == reflect.String && v.Type() == numberType {
+ // s must be a valid number, because it's
+ // already been tokenized.
+ v.SetString(s)
+ break
+ }
+ if fromQuoted {
+ return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())
+ }
+ d.saveError(&UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.readIndex())})
+ case reflect.Interface:
+ n, err := d.convertNumber(s)
+ if err != nil {
+ d.saveError(err)
+ break
+ }
+ if v.NumMethod() != 0 {
+ d.saveError(&UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.readIndex())})
+ break
+ }
+ v.Set(reflect.ValueOf(n))
+
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ n, err := strconv.ParseInt(s, 10, 64)
+ if err != nil || v.OverflowInt(n) {
+ d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.readIndex())})
+ break
+ }
+ v.SetInt(n)
+
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ n, err := strconv.ParseUint(s, 10, 64)
+ if err != nil || v.OverflowUint(n) {
+ d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.readIndex())})
+ break
+ }
+ v.SetUint(n)
+
+ case reflect.Float32, reflect.Float64:
+ n, err := strconv.ParseFloat(s, v.Type().Bits())
+ if err != nil || v.OverflowFloat(n) {
+ d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.readIndex())})
+ break
+ }
+ v.SetFloat(n)
+ }
+ }
+ return nil
+}
+
+// The xxxInterface routines build up a value to be stored
+// in an empty interface. They are not strictly necessary,
+// but they avoid the weight of reflection in this common case.
+
+// valueInterface is like value but returns interface{}
+func (d *decodeState) valueInterface() (val any) {
+ switch d.opcode {
+ default:
+ panic(phasePanicMsg)
+ case scanBeginArray:
+ val = d.arrayInterface()
+ d.scanNext()
+ case scanBeginObject:
+ val = d.objectInterface()
+ d.scanNext()
+ case scanBeginLiteral:
+ val = d.literalInterface()
+ }
+ return
+}
+
+// arrayInterface is like array but returns []interface{}.
+func (d *decodeState) arrayInterface() []any {
+ var v = make([]any, 0)
+ for {
+ // Look ahead for ] - can only happen on first iteration.
+ d.scanWhile(scanSkipSpace)
+ if d.opcode == scanEndArray {
+ break
+ }
+
+ v = append(v, d.valueInterface())
+
+ // Next token must be , or ].
+ if d.opcode == scanSkipSpace {
+ d.scanWhile(scanSkipSpace)
+ }
+ if d.opcode == scanEndArray {
+ break
+ }
+ if d.opcode != scanArrayValue {
+ panic(phasePanicMsg)
+ }
+ }
+ return v
+}
+
+// objectInterface is like object but returns map[string]interface{}.
+func (d *decodeState) objectInterface() map[string]any {
+ m := make(map[string]any)
+ for {
+ // Read opening " of string key or closing }.
+ d.scanWhile(scanSkipSpace)
+ if d.opcode == scanEndObject {
+ // closing } - can only happen on first iteration.
+ break
+ }
+ if d.opcode != scanBeginLiteral {
+ panic(phasePanicMsg)
+ }
+
+ // Read string key.
+ start := d.readIndex()
+ d.rescanLiteral()
+ item := d.data[start:d.readIndex()]
+ key, ok := unquote(item)
+ if !ok {
+ panic(phasePanicMsg)
+ }
+
+ // Read : before value.
+ if d.opcode == scanSkipSpace {
+ d.scanWhile(scanSkipSpace)
+ }
+ if d.opcode != scanObjectKey {
+ panic(phasePanicMsg)
+ }
+ d.scanWhile(scanSkipSpace)
+
+ // Read value.
+ m[key] = d.valueInterface()
+
+ // Next token must be , or }.
+ if d.opcode == scanSkipSpace {
+ d.scanWhile(scanSkipSpace)
+ }
+ if d.opcode == scanEndObject {
+ break
+ }
+ if d.opcode != scanObjectValue {
+ panic(phasePanicMsg)
+ }
+ }
+ return m
+}
+
+// literalInterface consumes and returns a literal from d.data[d.off-1:] and
+// it reads the following byte ahead. The first byte of the literal has been
+// read already (that's how the caller knows it's a literal).
+func (d *decodeState) literalInterface() any {
+ // All bytes inside literal return scanContinue op code.
+ start := d.readIndex()
+ d.rescanLiteral()
+
+ item := d.data[start:d.readIndex()]
+
+ switch c := item[0]; c {
+ case 'n': // null
+ return nil
+
+ case 't', 'f': // true, false
+ return c == 't'
+
+ case '"': // string
+ s, ok := unquote(item)
+ if !ok {
+ panic(phasePanicMsg)
+ }
+ return s
+
+ default: // number
+ if c != '-' && (c < '0' || c > '9') {
+ panic(phasePanicMsg)
+ }
+ n, err := d.convertNumber(string(item))
+ if err != nil {
+ d.saveError(err)
+ }
+ return n
+ }
+}
+
+// getu4 decodes \uXXXX from the beginning of s, returning the hex value,
+// or it returns -1.
+func getu4(s []byte) rune {
+ if len(s) < 6 || s[0] != '\\' || s[1] != 'u' {
+ return -1
+ }
+ var r rune
+ for _, c := range s[2:6] {
+ switch {
+ case '0' <= c && c <= '9':
+ c = c - '0'
+ case 'a' <= c && c <= 'f':
+ c = c - 'a' + 10
+ case 'A' <= c && c <= 'F':
+ c = c - 'A' + 10
+ default:
+ return -1
+ }
+ r = r*16 + rune(c)
+ }
+ return r
+}
+
+// unquote converts a quoted JSON string literal s into an actual string t.
+// The rules are different than for Go, so cannot use strconv.Unquote.
+func unquote(s []byte) (t string, ok bool) {
+ s, ok = unquoteBytes(s)
+ t = string(s)
+ return
+}
+
+func unquoteBytes(s []byte) (t []byte, ok bool) {
+ if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' {
+ return
+ }
+ s = s[1 : len(s)-1]
+
+ // Check for unusual characters. If there are none,
+ // then no unquoting is needed, so return a slice of the
+ // original bytes.
+ r := 0
+ for r < len(s) {
+ c := s[r]
+ if c == '\\' || c == '"' || c < ' ' {
+ break
+ }
+ if c < utf8.RuneSelf {
+ r++
+ continue
+ }
+ rr, size := utf8.DecodeRune(s[r:])
+ if rr == utf8.RuneError && size == 1 {
+ break
+ }
+ r += size
+ }
+ if r == len(s) {
+ return s, true
+ }
+
+ b := make([]byte, len(s)+2*utf8.UTFMax)
+ w := copy(b, s[0:r])
+ for r < len(s) {
+ // Out of room? Can only happen if s is full of
+ // malformed UTF-8 and we're replacing each
+ // byte with RuneError.
+ if w >= len(b)-2*utf8.UTFMax {
+ nb := make([]byte, (len(b)+utf8.UTFMax)*2)
+ copy(nb, b[0:w])
+ b = nb
+ }
+ switch c := s[r]; {
+ case c == '\\':
+ r++
+ if r >= len(s) {
+ return
+ }
+ switch s[r] {
+ default:
+ return
+ case '"', '\\', '/', '\'':
+ b[w] = s[r]
+ r++
+ w++
+ case 'b':
+ b[w] = '\b'
+ r++
+ w++
+ case 'f':
+ b[w] = '\f'
+ r++
+ w++
+ case 'n':
+ b[w] = '\n'
+ r++
+ w++
+ case 'r':
+ b[w] = '\r'
+ r++
+ w++
+ case 't':
+ b[w] = '\t'
+ r++
+ w++
+ case 'u':
+ r--
+ rr := getu4(s[r:])
+ if rr < 0 {
+ return
+ }
+ r += 6
+ if utf16.IsSurrogate(rr) {
+ rr1 := getu4(s[r:])
+ if dec := utf16.DecodeRune(rr, rr1); dec != unicode.ReplacementChar {
+ // A valid pair; consume.
+ r += 6
+ w += utf8.EncodeRune(b[w:], dec)
+ break
+ }
+ // Invalid surrogate; fall back to replacement rune.
+ rr = unicode.ReplacementChar
+ }
+ w += utf8.EncodeRune(b[w:], rr)
+ }
+
+ // Quote, control characters are invalid.
+ case c == '"', c < ' ':
+ return
+
+ // ASCII
+ case c < utf8.RuneSelf:
+ b[w] = c
+ r++
+ w++
+
+ // Coerce to well-formed UTF-8.
+ default:
+ rr, size := utf8.DecodeRune(s[r:])
+ r += size
+ w += utf8.EncodeRune(b[w:], rr)
+ }
+ }
+ return b[0:w], true
+}
diff --git a/vendor/github.com/evanphx/json-patch/v5/internal/json/encode.go b/vendor/github.com/evanphx/json-patch/v5/internal/json/encode.go
new file mode 100644
index 000000000..a1819b16a
--- /dev/null
+++ b/vendor/github.com/evanphx/json-patch/v5/internal/json/encode.go
@@ -0,0 +1,1473 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package json implements encoding and decoding of JSON as defined in
+// RFC 7159. The mapping between JSON and Go values is described
+// in the documentation for the Marshal and Unmarshal functions.
+//
+// See "JSON and Go" for an introduction to this package:
+// https://golang.org/doc/articles/json_and_go.html
+package json
+
+import (
+ "bytes"
+ "encoding"
+ "encoding/base64"
+ "fmt"
+ "math"
+ "reflect"
+ "sort"
+ "strconv"
+ "strings"
+ "sync"
+ "unicode"
+ "unicode/utf8"
+)
+
+// Marshal returns the JSON encoding of v.
+//
+// Marshal traverses the value v recursively.
+// If an encountered value implements the Marshaler interface
+// and is not a nil pointer, Marshal calls its MarshalJSON method
+// to produce JSON. If no MarshalJSON method is present but the
+// value implements encoding.TextMarshaler instead, Marshal calls
+// its MarshalText method and encodes the result as a JSON string.
+// The nil pointer exception is not strictly necessary
+// but mimics a similar, necessary exception in the behavior of
+// UnmarshalJSON.
+//
+// Otherwise, Marshal uses the following type-dependent default encodings:
+//
+// Boolean values encode as JSON booleans.
+//
+// Floating point, integer, and Number values encode as JSON numbers.
+//
+// String values encode as JSON strings coerced to valid UTF-8,
+// replacing invalid bytes with the Unicode replacement rune.
+// So that the JSON will be safe to embed inside HTML