Merge remote-tracking branch 'origin/main' into resource-store

This commit is contained in:
Ryan McKinley
2024-06-18 16:08:30 +03:00
59 changed files with 1499 additions and 169 deletions
+1
View File
@@ -36,4 +36,5 @@ require (
k8s.io/utils v0.0.0-20230726121419-3b25d923346b // 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
)
+1 -1
View File
@@ -33,4 +33,4 @@ k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7F
k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
+4 -4
View File
@@ -22,7 +22,7 @@ require (
require (
github.com/BurntSushi/toml v1.3.2 // indirect
github.com/NYTimes/gziphandler v1.1.1 // indirect
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230512164433-5d1fd1a340c9 // indirect
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
github.com/apache/arrow/go/v15 v15.0.2 // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/beorn7/perks v1.0.1 // indirect
@@ -53,7 +53,7 @@ require (
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/btree v1.1.2 // indirect
github.com/google/cel-go v0.17.7 // indirect
github.com/google/cel-go v0.20.1 // indirect
github.com/google/flatbuffers v24.3.25+incompatible // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/go-cmp v0.6.0 // indirect
@@ -128,7 +128,7 @@ require (
go.opentelemetry.io/otel/sdk v1.26.0 // indirect
go.opentelemetry.io/proto/otlp v1.2.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.26.0 // indirect
go.uber.org/zap v1.27.0 // indirect
golang.org/x/crypto v0.24.0 // indirect
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f // indirect
golang.org/x/net v0.26.0 // indirect
@@ -154,5 +154,5 @@ require (
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.28.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.3.0 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
)
+5 -7
View File
@@ -4,7 +4,7 @@ github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230512164433-5d1fd1a340c9 h1:goHVqTbFX3AIo0tzGr14pgfAW2ZfPChKO21Z9MGf/gk=
github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI=
github.com/apache/arrow/go/v15 v15.0.2 h1:60IliRbiyTWCWjERBCkO1W4Qun9svcYoZrSLcyOsMLE=
github.com/apache/arrow/go/v15 v15.0.2/go.mod h1:DGXsR3ajT524njufqf95822i+KTh+yea1jass9YXgjA=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
@@ -95,8 +95,8 @@ github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaW
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/google/cel-go v0.17.7 h1:6ebJFzu1xO2n7TLtN+UBqShGBhlD85bhvglh5DpcfqQ=
github.com/google/cel-go v0.17.7/go.mod h1:HXZKzB0LXqer5lHHgfWAnlYwJaQBDKMjxjulNQzhwhY=
github.com/google/cel-go v0.20.1 h1:nDx9r8S3L4pE61eDdt8igGj8rf5kjYR3ILxWIpWNi84=
github.com/google/cel-go v0.20.1/go.mod h1:kWcIzTsPX0zmQ+H3TirHstLLf9ep5QTsZBN9u4dOYLg=
github.com/google/flatbuffers v24.3.25+incompatible h1:CX395cjN9Kke9mmalRoL3d81AtFUxJM+yDthflgJGkI=
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
@@ -321,8 +321,7 @@ go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9i
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
@@ -452,5 +451,4 @@ sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMm
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
+5 -4
View File
@@ -23,7 +23,7 @@ require (
github.com/Masterminds/semver/v3 v3.2.0 // @grafana/grafana-release-guild
github.com/aws/aws-sdk-go v1.51.31 // @grafana/aws-datasources
github.com/blang/semver/v4 v4.0.0 // @grafana/grafana-release-guild
github.com/docker/docker v26.0.1+incompatible // @grafana/grafana-release-guild
github.com/docker/docker v26.0.2+incompatible // @grafana/grafana-release-guild
github.com/drone/drone-cli v1.6.1 // @grafana/grafana-release-guild
github.com/gogo/protobuf v1.3.2 // indirect; @grafana/alerting-backend
github.com/golang/protobuf v1.5.4 // indirect; @grafana/grafana-backend-group
@@ -66,7 +66,7 @@ require (
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/docker/distribution v2.8.2+incompatible // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-connections v0.5.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/drone-runners/drone-runner-docker v1.8.2 // indirect
github.com/drone/drone-go v1.7.1 // indirect
@@ -81,7 +81,7 @@ require (
github.com/google/s2a-go v0.1.7 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.3-0.20220512140940-7b36cea86235 // indirect
github.com/opencontainers/image-spec v1.1.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
@@ -98,8 +98,9 @@ require (
)
require (
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/moby/term v0.0.0-20221205130635-1aeaba878587 // indirect
github.com/moby/term v0.5.0 // indirect
github.com/rogpeppe/go-internal v1.12.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gotest.tools/v3 v3.5.1 // indirect
+4 -14
View File
@@ -14,8 +14,7 @@ cloud.google.com/go/storage v1.38.0/go.mod h1:tlUADB0mAb9BgYls9lq+8MGkfzOXuLrnHX
github.com/99designs/basicauth-go v0.0.0-20160802081356-2a93ba0f464d/go.mod h1:3cARGAK9CfW3HoxCy1a0G4TKrdiKke8ftOMEOHyySYs=
github.com/99designs/httpsignatures-go v0.0.0-20170731043157-88528bf4ca7e/go.mod h1:Xa6lInWHNQnuWoF0YPSsx+INFA9qk7/7pTjwb3PInkY=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g=
@@ -53,8 +52,7 @@ github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4Kfc
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/go-connections v0.3.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
@@ -154,8 +152,7 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/moby/moby v23.0.4+incompatible h1:A/pe8vi9KIKhNbzR0G3wW4ACKDsMgXILBveMqiJNa8M=
github.com/moby/moby v23.0.4+incompatible/go.mod h1:fDXVQ6+S340veQPv35CzDahGBmHsiclFwfEygB/TWMc=
github.com/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA=
github.com/moby/term v0.0.0-20221205130635-1aeaba878587/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/natessilva/dag v0.0.0-20180124060714-7194b8dcc5c4/go.mod h1:cojhOHk1gbMeklOyDP2oKKLftefXoJreOQGOrXk+Z38=
@@ -163,8 +160,7 @@ github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQ
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/image-spec v1.0.3-0.20220512140940-7b36cea86235 h1:DxS3bbeUSCpMQr3mTez5PIDrS+yBeBsoDsftOhqB1Fg=
github.com/opencontainers/image-spec v1.0.3-0.20220512140940-7b36cea86235/go.mod h1:K/JAU0m27RFhDRX4PcFdIKntROP6y5Ed6O91aZYDQfs=
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -176,7 +172,6 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
@@ -187,7 +182,6 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
@@ -198,9 +192,6 @@ github.com/urfave/cli v1.22.15 h1:nuqt+pdC/KqswQKhETJjo7pvn/k4xMUxgW6liI7XpnM=
github.com/urfave/cli v1.22.15/go.mod h1:wSan1hmo5zeyLGBjRJbzRTNk8gwoYa2B9n4q9dmRIc0=
github.com/urfave/cli/v2 v2.25.1 h1:zw8dSP7ghX0Gmm8vugrs6q9Ku0wzweqPyshy+syu9Gw=
github.com/urfave/cli/v2 v2.25.1/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -332,7 +323,6 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
@@ -14,7 +14,6 @@ import (
"github.com/grafana/grafana/pkg/login/social/connectors"
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
"github.com/grafana/grafana/pkg/services/featuremgmt"
ldap "github.com/grafana/grafana/pkg/services/ldap/service"
"github.com/grafana/grafana/pkg/services/licensing"
secretsfake "github.com/grafana/grafana/pkg/services/secrets/fakes"
"github.com/grafana/grafana/pkg/services/ssosettings/ssosettingsimpl"
@@ -82,7 +81,6 @@ func TestSocialService_ProvideService(t *testing.T) {
nil,
&setting.OSSImpl{Cfg: cfg},
&licensing.OSSLicensingService{},
ldap.ProvideService(cfg),
)
for _, tc := range testCases {
@@ -195,7 +193,6 @@ func TestSocialService_ProvideService_GrafanaComGrafanaNet(t *testing.T) {
nil,
nil,
&licensing.OSSLicensingService{},
ldap.ProvideService(cfg),
)
for _, tc := range testCases {
+2
View File
@@ -7,12 +7,14 @@ const (
Core string = "core"
GrafanaAPIServer string = "grafana-apiserver"
StorageServer string = "storage-server"
ZanzanaServer string = "zanzana-server"
InstrumentationServer string = "instrumentation-server"
)
var dependencyMap = map[string][]string{
GrafanaAPIServer: {InstrumentationServer},
StorageServer: {InstrumentationServer},
ZanzanaServer: {InstrumentationServer},
Core: {},
All: {Core},
}
+5
View File
@@ -13,6 +13,7 @@ import (
"github.com/grafana/grafana/pkg/api"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/modules"
"github.com/grafana/grafana/pkg/services/authz"
"github.com/grafana/grafana/pkg/services/featuremgmt"
storageServer "github.com/grafana/grafana/pkg/services/store/entity/server"
"github.com/grafana/grafana/pkg/setting"
@@ -133,6 +134,10 @@ func (s *ModuleServer) Run() error {
return storageServer.ProvideService(s.cfg, s.features, s.log)
})
m.RegisterModule(modules.ZanzanaServer, func() (services.Service, error) {
return authz.ProvideZanzanaService(s.cfg, s.features)
})
m.RegisterModule(modules.All, nil)
return m.Run(s.context)
+1
View File
@@ -6,4 +6,5 @@ import (
var WireSet = wire.NewSet(
ProvideAuthZClient,
ProvideZanzana,
)
+127
View File
@@ -0,0 +1,127 @@
package authz
import (
"context"
"errors"
"fmt"
"github.com/fullstorydev/grpchan/inprocgrpc"
"github.com/grafana/dskit/services"
openfgav1 "github.com/openfga/api/proto/openfga/v1"
"github.com/prometheus/client_golang/prometheus"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/services/authz/zanzana"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/grpcserver"
"github.com/grafana/grafana/pkg/setting"
)
type ZanzanaClient interface{}
func ProvideZanzana(cfg *setting.Cfg) (ZanzanaClient, error) {
var client *zanzana.Client
switch cfg.Zanzana.Mode {
case setting.ZanzanaModeClient:
conn, err := grpc.NewClient(cfg.Zanzana.Addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
return nil, fmt.Errorf("failed to create zanzana client to remote server: %w", err)
}
client = zanzana.NewClient(openfgav1.NewOpenFGAServiceClient(conn))
case setting.ZanzanaModeEmbedded:
srv, err := zanzana.NewServer(zanzana.NewStore())
if err != nil {
return nil, fmt.Errorf("failed to start zanzana: %w", err)
}
channel := &inprocgrpc.Channel{}
openfgav1.RegisterOpenFGAServiceServer(channel, srv)
client = zanzana.NewClient(openfgav1.NewOpenFGAServiceClient(channel))
default:
return nil, fmt.Errorf("unsupported zanzana mode: %s", cfg.Zanzana.Mode)
}
return client, nil
}
type ZanzanaService interface {
services.NamedService
}
var _ ZanzanaService = (*Zanzana)(nil)
// ProvideZanzanaService is used to register zanzana as a module so we can run it seperatly from grafana.
func ProvideZanzanaService(cfg *setting.Cfg, features featuremgmt.FeatureToggles) (*Zanzana, error) {
s := &Zanzana{
cfg: cfg,
features: features,
logger: log.New("zanzana"),
}
s.BasicService = services.NewBasicService(s.start, s.running, s.stopping).WithName("zanzana")
return s, nil
}
type Zanzana struct {
*services.BasicService
cfg *setting.Cfg
logger log.Logger
handle grpcserver.Provider
features featuremgmt.FeatureToggles
}
func (z *Zanzana) start(ctx context.Context) error {
srv, err := zanzana.NewServer(zanzana.NewStore())
if err != nil {
return fmt.Errorf("failed to start zanzana: %w", err)
}
tracingCfg, err := tracing.ProvideTracingConfig(z.cfg)
if err != nil {
return err
}
tracingCfg.ServiceName = "zanzana"
tracer, err := tracing.ProvideService(tracingCfg)
if err != nil {
return err
}
// FIXME(kalleep): For now we use noopAuthenticator but we should create an authenticator that can be shared
// between different services.
z.handle, err = grpcserver.ProvideService(z.cfg, z.features, noopAuthenticator{}, tracer, prometheus.DefaultRegisterer)
if err != nil {
return fmt.Errorf("failed to create zanzana grpc server: %w", err)
}
openfgav1.RegisterOpenFGAServiceServer(z.handle.GetServer(), srv)
if _, err := grpcserver.ProvideReflectionService(z.cfg, z.handle); err != nil {
return fmt.Errorf("failed to register reflection for zanzana: %w", err)
}
return nil
}
func (z *Zanzana) running(ctx context.Context) error {
// Run is blocking so we can just run it here
return z.handle.Run(ctx)
}
func (z *Zanzana) stopping(err error) error {
if err != nil && !errors.Is(err, context.Canceled) {
z.logger.Error("Stopping zanzana due to unexpected error", "err", err)
}
return nil
}
type noopAuthenticator struct{}
func (n noopAuthenticator) Authenticate(ctx context.Context) (context.Context, error) {
return ctx, nil
}
+14
View File
@@ -0,0 +1,14 @@
package zanzana
import (
openfgav1 "github.com/openfga/api/proto/openfga/v1"
)
// FIXME(kalleep): Build out our wrapper client for openFGA
type Client struct {
c openfgav1.OpenFGAServiceClient
}
func NewClient(c openfgav1.OpenFGAServiceClient) *Client {
return &Client{c}
}
+26
View File
@@ -0,0 +1,26 @@
package zanzana
import (
"github.com/openfga/openfga/pkg/logger"
"github.com/openfga/openfga/pkg/server"
"github.com/openfga/openfga/pkg/storage"
)
func NewServer(store storage.OpenFGADatastore) (*server.Server, error) {
// FIXME(kalleep): add support for more options, configure logging, tracing etc
opts := []server.OpenFGAServiceV1Option{
server.WithDatastore(store),
// FIXME(kalleep): Write and log adapter for open fga logging interface
server.WithLogger(logger.NewNoopLogger()),
}
// FIXME(kalleep): Interceptors
// We probably need to at least need to add store id interceptor also
// would be nice to inject our own requestid?
srv, err := server.NewServerWithOpts(opts...)
if err != nil {
return nil, err
}
return srv, nil
}
+13
View File
@@ -0,0 +1,13 @@
package zanzana
import (
"github.com/openfga/openfga/pkg/storage"
"github.com/openfga/openfga/pkg/storage/memory"
)
// FIXME(kalleep): Add support for postgres, mysql and sqlite data stores.
// Postgres and mysql is already implmented by openFGA so we just need to hook up migartions for them.
// There is no support for sqlite atm but we are working on adding it: https://github.com/openfga/openfga/pull/1615
func NewStore() storage.OpenFGADatastore {
return memory.New()
}
@@ -536,6 +536,10 @@ func (d *dashboardStore) GetSoftDeletedDashboard(ctx context.Context, orgID int6
func (d *dashboardStore) RestoreDashboard(ctx context.Context, orgID int64, dashboardUID string, folder *folder.Folder) error {
return d.store.WithTransactionalDbSession(ctx, func(sess *db.Session) error {
if folder == nil || folder.UID == "" {
_, err := sess.Exec("UPDATE dashboard SET deleted=NULL, folder_id=0, folder_uid=NULL WHERE org_id=? AND uid=?", orgID, dashboardUID)
return err
}
// nolint:staticcheck
_, err := sess.Exec("UPDATE dashboard SET deleted=NULL, folder_id = ?, folder_uid=? WHERE org_id=? AND uid=?", folder.ID, folder.UID, orgID, dashboardUID)
return err
+8
View File
@@ -1323,6 +1323,14 @@ var (
Stage: FeatureStagePublicPreview,
Owner: awsDatasourcesSquad,
},
{
Name: "ssoSettingsLDAP",
Description: "Use the new SSO Settings API to configure LDAP",
Stage: FeatureStageExperimental,
Owner: identityAccessTeam,
HideFromDocs: true,
HideFromAdminPage: true,
},
}
)
+1
View File
@@ -176,3 +176,4 @@ azureMonitorPrometheusExemplars,experimental,@grafana/partner-datasources,false,
pinNavItems,experimental,@grafana/grafana-frontend-platform,false,false,false
authZGRPCServer,experimental,@grafana/identity-access-team,false,false,false
openSearchBackendFlowEnabled,preview,@grafana/aws-datasources,false,false,false
ssoSettingsLDAP,experimental,@grafana/identity-access-team,false,false,false
1 Name Stage Owner requiresDevMode RequiresRestart FrontendOnly
176 pinNavItems experimental @grafana/grafana-frontend-platform false false false
177 authZGRPCServer experimental @grafana/identity-access-team false false false
178 openSearchBackendFlowEnabled preview @grafana/aws-datasources false false false
179 ssoSettingsLDAP experimental @grafana/identity-access-team false false false
+4
View File
@@ -714,4 +714,8 @@ const (
// FlagOpenSearchBackendFlowEnabled
// Enables the backend query flow for Open Search datasource plugin
FlagOpenSearchBackendFlowEnabled = "openSearchBackendFlowEnabled"
// FlagSsoSettingsLDAP
// Use the new SSO Settings API to configure LDAP
FlagSsoSettingsLDAP = "ssoSettingsLDAP"
)
+14
View File
@@ -2126,6 +2126,20 @@
"allowSelfServe": true
}
},
{
"metadata": {
"name": "ssoSettingsLDAP",
"resourceVersion": "1718624569822",
"creationTimestamp": "2024-06-17T11:42:49Z"
},
"spec": {
"description": "Use the new SSO Settings API to configure LDAP",
"stage": "experimental",
"codeowner": "@grafana/identity-access-team",
"hideFromAdminPage": true,
"hideFromDocs": true
}
},
{
"metadata": {
"name": "ssoSettingsSAML",
+4 -1
View File
@@ -209,7 +209,10 @@ func (s *Service) Get(ctx context.Context, q *folder.GetFolderQuery) (*folder.Fo
var dashFolder *folder.Folder
var err error
switch {
case q.UID != nil && *q.UID != "":
case q.UID != nil:
if *q.UID == "" {
return &folder.GeneralFolder, nil
}
dashFolder, err = s.getFolderByUID(ctx, q.OrgID, *q.UID)
if err != nil {
return nil, err
@@ -395,6 +395,21 @@ func TestIntegrationFolderService(t *testing.T) {
"For error '%s' expected error '%s', actual '%s'", tc.ActualError, tc.ExpectedError, actualError)
}
})
t.Run("Returns root folder", func(t *testing.T) {
t.Run("When the folder UID is blank should return the root folder", func(t *testing.T) {
emptyString := ""
actual, err := service.Get(context.Background(), &folder.GetFolderQuery{
UID: &emptyString,
OrgID: 1,
SignedInUser: usr,
})
assert.NoError(t, err)
assert.Equal(t, folder.GeneralFolder.UID, actual.UID)
assert.Equal(t, folder.GeneralFolder.Title, actual.Title)
})
})
})
}
+26
View File
@@ -1,8 +1,10 @@
package service
import (
"encoding/json"
"fmt"
"os"
"strconv"
"github.com/BurntSushi/toml"
@@ -85,3 +87,27 @@ func assertNotEmptyCfg(val any, propName string) error {
}
return nil
}
func resolveBool(input any, defaultValue bool) bool {
strInput := fmt.Sprintf("%v", input)
result, err := strconv.ParseBool(strInput)
if err != nil {
return defaultValue
}
return result
}
func resolveServerConfig(input any) (*ldap.ServersConfig, error) {
var ldapCfg ldap.ServersConfig
inputJson, err := json.Marshal(input)
if err != nil {
return nil, err
}
if err = json.Unmarshal(inputJson, &ldapCfg); err != nil {
return nil, err
}
return &ldapCfg, nil
}
+65 -16
View File
@@ -1,13 +1,19 @@
package service
import (
"context"
"errors"
"sync"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/login/social"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/ldap"
"github.com/grafana/grafana/pkg/services/ldap/multildap"
"github.com/grafana/grafana/pkg/services/login"
"github.com/grafana/grafana/pkg/services/ssosettings"
"github.com/grafana/grafana/pkg/services/ssosettings/models"
"github.com/grafana/grafana/pkg/setting"
)
@@ -29,39 +35,82 @@ type LDAP interface {
}
type LDAPImpl struct {
client multildap.IMultiLDAP
cfg *ldap.Config
ldapCfg *ldap.ServersConfig
log log.Logger
client multildap.IMultiLDAP
cfg *ldap.Config
ldapCfg *ldap.ServersConfig
log log.Logger
features featuremgmt.FeatureToggles
ssoSettings ssosettings.Service
// loadingMutex locks the reading of the config so multiple requests for reloading are sequential.
loadingMutex *sync.Mutex
}
func ProvideService(cfg *setting.Cfg) *LDAPImpl {
func ProvideService(cfg *setting.Cfg, features featuremgmt.FeatureToggles, ssoSettings ssosettings.Service) *LDAPImpl {
s := &LDAPImpl{
client: nil,
ldapCfg: nil,
cfg: ldap.GetLDAPConfig(cfg),
log: log.New("ldap.service"),
loadingMutex: &sync.Mutex{},
features: features,
ssoSettings: ssoSettings,
}
if !cfg.LDAPAuthEnabled {
return s
}
if s.features.IsEnabledGlobally(featuremgmt.FlagSsoSettingsApi) && s.features.IsEnabledGlobally(featuremgmt.FlagSsoSettingsLDAP) {
s.ssoSettings.RegisterReloadable(social.LDAPProviderName, s)
ldapCfg, err := multildap.GetConfig(s.cfg)
if err != nil {
s.log.Error("Failed to get LDAP config", "error", err)
ldapSettings, err := s.ssoSettings.GetForProvider(context.Background(), social.LDAPProviderName)
if err != nil {
s.log.Error("Failed to retrieve LDAP settings from SSO settings service", "error", err)
return s
}
err = s.Reload(context.Background(), *ldapSettings)
if err != nil {
s.log.Error("Failed to load LDAP settings", "error", err)
return s
}
} else {
s.ldapCfg = ldapCfg
s.client = multildap.New(s.ldapCfg.Servers, s.cfg)
s.cfg = ldap.GetLDAPConfig(cfg)
if !cfg.LDAPAuthEnabled {
return s
}
ldapCfg, err := multildap.GetConfig(s.cfg)
if err != nil {
s.log.Error("Failed to get LDAP config", "error", err)
} else {
s.ldapCfg = ldapCfg
s.client = multildap.New(s.ldapCfg.Servers, s.cfg)
}
}
return s
}
func (s *LDAPImpl) Reload(ctx context.Context, settings models.SSOSettings) error {
cfg := &ldap.Config{}
cfg.Enabled = resolveBool(settings.Settings["enabled"], false)
cfg.SkipOrgRoleSync = resolveBool(settings.Settings["skip_org_role_sync"], false)
cfg.AllowSignUp = resolveBool(settings.Settings["allow_sign_up"], true)
ldapCfg, err := resolveServerConfig(settings.Settings["config"])
if err != nil {
return err
}
s.loadingMutex.Lock()
defer s.loadingMutex.Unlock()
s.cfg = cfg
s.ldapCfg = ldapCfg
s.client = multildap.New(s.ldapCfg.Servers, s.cfg)
return nil
}
func (s *LDAPImpl) Validate(ctx context.Context, settings models.SSOSettings, oldSettings models.SSOSettings, requester identity.Requester) error {
return nil
}
func (s *LDAPImpl) ReloadConfig() error {
if !s.cfg.Enabled {
return nil
+299
View File
@@ -0,0 +1,299 @@
package service
import (
"context"
"sync"
"testing"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/ldap"
"github.com/grafana/grafana/pkg/services/ssosettings/models"
"github.com/stretchr/testify/require"
)
const (
validCert = `LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURYVENDQWtXZ0F3SUJBZ0lKQUxtVlZ1RFd1NE5ZTUEwR0NTcUdTSWIzRFFFQkN
3VUFNRVV4Q3pBSkJnTlYKQkFZVEFrRlZNUk13RVFZRFZRUUlEQXBUYjIxbExWTjBZWFJsTVNFd0h3WURWUVFLREJoSmJuUmxjbTVsZENCWAphV1JuYVhSekl
GQjBlU0JNZEdRd0hoY05NVFl4TWpNeE1UUXpORFEzV2hjTk5EZ3dOakkxTVRRek5EUTNXakJGCk1Rc3dDUVlEVlFRR0V3SkJWVEVUTUJFR0ExVUVDQXdLVTI
5dFpTMVRkR0YwWlRFaE1COEdBMVVFQ2d3WVNXNTAKWlhKdVpYUWdWMmxrWjJsMGN5QlFkSGtnVEhSa01JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUTh
BTUlJQgpDZ0tDQVFFQXpVQ0ZvemdOYjFoMU0wanpOUlNDamhPQm5SK3VWYlZwYVdmWFlJUitBaFdEZEVlNXJ5WStDZ2F2Ck9nOGJmTHlieXpGZGVobFlkRFJ
na2VkRUIvR2pHOGFKdzA2bDBxRjRqRE9BdzBrRXlnV0N1Mm1jSDdYT3hSdCsKWUFIM1RWSGEvSHUxVzNXanprb2JxcXFMUThna0tXV00yN2ZPZ0FaNkdpZWF
KQk42VkJTTU1jUGV5M0hXTEJtYworVFlKbXYxZGJhTzJqSGhLaDhwZkt3MFcxMlZNOFAxUElPOGd2NFBodS91dUpZaWVCV0tpeEJFeXkwbEhqeWl4CllGQ1I
xMnhkaDRDQTQ3cTk1OFpSR25uRFVHRlZFMVFoZ1JhY0pDT1o5YmQ1dDltcjhLTGFWQllUQ0pvNUVSRTgKanltYWI1ZFBxZTVxS2ZKc0NaaXFXZ2xialVvOXR
3SURBUUFCbzFBd1RqQWRCZ05WSFE0RUZnUVV4cHV3Y3MvQwpZUU95dWkrcjFHKzNLeEJOaHhrd0h3WURWUjBqQkJnd0ZvQVV4cHV3Y3MvQ1lRT3l1aStyMUc
rM0t4Qk5oeGt3CkRBWURWUjBUQkFVd0F3RUIvekFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBQWlXVUtzLzJ4L3ZpTkNLaTNZNmIKbEV1Q3RBR2h6T09aOUV
qcnZKOCtDT0gzUmFnM3RWQldyY0JaMy91aGhQcTVneTlscXc0T2t2RXdzOTkvNWpGcwpYMUZKNk1LQmdxZnV5N3loNXMxWWZNMEFOSFljek1tWXBaZUFjUWY
yQ0dBYVZmd1RUZlNsek5Mc0YybFcvbHk3CnlhcEZ6bFlTSkxHb1ZFK09IRXU4ZzVTbE5BQ1VFZmtYdys1RWdoaCtLemxJTjdSNlE3cjJpeFdORkJDL2pXZjc
KTktVZkp5WDhxSUc1bWQxWVVlVDZHQlc5Qm0yLzEvUmlPMjRKVGFZbGZMZEtLOVRZYjhzRzVCK09MYWIyREltRwo5OUNKMjVSa0FjU29iV05GNXpEME82bGd
PbzNjRWRCL2tzQ3EzaG10bEMvRGxMWi9EOENKKzdWdVpuUzFyUjJuCmFRPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ==`
validKey = `LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFdlFJQkFEQU5CZ2txaGtpRzl3MEJBUUVGQUFTQ0JLY3dnZ1NqQWdFQUFv
SUJBUUROUUlXak9BMXZXSFV6ClNQTTFGSUtPRTRHZEg2NVZ0V2xwWjlkZ2hINENGWU4wUjdtdkpqNEtCcTg2RHh0OHZKdkxNVjE2R1ZoME5HQ1IKNTBRSDhh
TWJ4b25EVHFYU29YaU1NNEREU1FUS0JZSzdhWndmdGM3RkczNWdBZmROVWRyOGU3VmJkYVBPU2h1cQpxb3REeUNRcFpZemJ0ODZBQm5vYUo1b2tFM3BVRkl3
eHc5N0xjZFlzR1p6NU5nbWEvVjF0bzdhTWVFcUh5bDhyCkRSYlhaVXp3L1U4Zzd5Qy9nK0c3KzY0bGlKNEZZcUxFRVRMTFNVZVBLTEZnVUpIWGJGMkhnSURq
dXIzbnhsRWEKZWNOUVlWVVRWQ0dCRnB3a0k1bjF0M20zMmF2d290cFVGaE1JbWprUkVUeVBLWnB2bDArcDdtb3A4bXdKbUtwYQpDVnVOU2oyM0FnTUJBQUVD
Z2dFQUJuNEkvQjIweHhYY056QVNpVlpKdnVhOURkUkh0bXhUbGtMem5CajB4Mm9ZCnkxL05iczNkM29GUm41dUV1aEJaT1RjcGhzZ3dkUlNIRFhac1AzZ1VP
YmV3K2QyTi96aWVVSWo4aExEVmx2SlAKclUvczRVL2w1M1EwTGlOQnlFOVRodkwrekpMUENLSnRkNXVIWmpCNWZGbTY5K1E3Z3U4eGc0eEhJdWIrMHBQNQpQ
SGFubUhDRHJiZ05OL29xbGFyNEZaMk1YVGdla1c2QW15Yy9rb0U5aEluNEJhYTJLZS9CL0FVR1k0cE1STHFwClRBcnQrR1RWZVdlb0ZZOVFBQ1VwYUhwSmhH
Yi9QaW91NnRsVTU3ZTQyY0xva2kxZjArU0FSc0JCS3lYQTdCQjEKMWZNSDEwS1FZRkE2OGRUWVdsS3pRYXUvSzR4YXFnNEZLbXR3RjY2R1FRS0JnUUQ5T3BO
VVM3b1J4TUhWSmFCUgpUTldXK1YxRlh5Y3FvamVrRnBEaWpQYjJYNUNXVjE2b2VXZ2FYcDBuT0hGZHk5RVdzM0d0R3BmWmFzYVJWSHNYClNIdFBoNE5iOEpx
SGRHRTAvQ0Q2dDArNERuczhCbjljU3F0ZFFCN1IzSm43SU1YaTlYL1U4TERLbytBMTgvSnEKVjhWZ1VuZ01ueTlZak1rUUliSzhUUldrWVFLQmdRRFBmNG54
TzZqdSt0T0hIT1JRdHkzYllERDArT1YzSTArTAoweXowdVByZXJ5QlZpOW5ZNDNLYWtINTJEN1VaRXd3c0JqakdYRCtXSDh4RXNtQldzR05YSnUwMjVQdnpJ
Sm96CmxBRWlYdk1wL05tWXArdFk0ckRtTzhSaHlWb2NCcVdIemgzOG0wSUZPZDRCeUZENW5MRURyQTNwRFZvMGFOZ1kKbjBHd1J5c1pGd0tCZ1FEa0NqM202
Wk1Vc1VXRXR5K2FSMEVKaG1LeU9EQkRPblkwOUlWaEgyUy9GZXhWRnpVTgpMdGZLOTIwNmhwL0F3ZXozTG4ydVQ0WnpxcTVLN2ZNelVuaUpkQldkVkIwMDRs
OHZvZVhwSWU5T1p1d2ZjQko5CmdGaTF6eXB4L3VGRHY0MjFCelFwQk4rUWZPZEtidmJkUVZGam5xQ3hiU0RyODB5VmxHTXJJNWZid1FLQmdHMDkKb1JyZXBP
N0VJTzhHTi9HQ3J1TEsvcHRLR2t5aHkzUTZ4blZFbWRiNDdoWDduY0pBNUlvWlBtcmJsQ1ZTVU5zdwpuMTFYSGFia3NMOE9CZ2c5cnQ4b1FFVGhRdi9hRHpU
T1c5YURsSk5yYWdlamlCVHdxOTlhWWVaMWdqbzFDWnE0CjJqS3VicENmeVpDNHJHRHRySWZaWWkxcStTMlVjUWh0ZDhEZGh3UWJBb0dBQU00RXBEQTR5SEI1
eWllazFwL28KQ2JxUkN0YS9EeDZFeW8wS2xOQXlQdUZQQXNodXBHNE5CeDdtVDJBU2ZMKzJWQkhvaTZtSFNyaStCRFg1cnlZRgpmTVl2cDdVUllvcTd3N3Fp
dlJsdnZFZzV5b1lySzEzRjIrR2o2eEo0akVOOW0wS2RNL2czbUpHcTBIQlRJUXJwClNtNzVXWHNmbE94dVRuMDhMYmdHYzRzPQotLS0tLUVORCBSU0EgUFJJ
VkFURSBLRVktLS0tLQ==`
)
var (
isAdmin = true
)
func TestReload(t *testing.T) {
testCases := []struct {
description string
settings models.SSOSettings
expectedServersConfig *ldap.ServersConfig
expectedConfig *ldap.Config
}{
{
description: "basic flow with minimal config",
settings: models.SSOSettings{
Provider: "ldap",
Settings: map[string]any{
"enabled": true,
"skip_org_role_sync": false,
"allow_sign_up": true,
"config": map[string]any{
"servers": []any{
map[string]any{
"host": "127.0.0.1",
},
},
},
},
IsDeleted: false,
},
expectedServersConfig: &ldap.ServersConfig{
Servers: []*ldap.ServerConfig{
{
Host: "127.0.0.1",
},
},
},
expectedConfig: &ldap.Config{
Enabled: true,
AllowSignUp: true,
SkipOrgRoleSync: false,
},
},
{
description: "complete set of server parameters",
settings: models.SSOSettings{
Provider: "ldap",
Settings: map[string]any{
"enabled": true,
"skip_org_role_sync": false,
"allow_sign_up": true,
"config": map[string]any{
"servers": []any{
map[string]any{
"host": "127.0.0.1",
"port": 3389,
"bind_dn": "cn=ldapservice,ou=users,dc=ldap,dc=goauthentik,dc=io",
"bind_password": "grafana",
"search_filter": "(cn=%s)",
"ssl_skip_verify": false,
"use_ssl": true,
"start_tls": true,
"min_tls_version": "TLS1.3",
"timeout": 10,
"root_ca_cert": "/path/to/certificate.crt",
"root_ca_cert_value": []string{validCert},
"client_cert": "/path/to/client.crt",
"client_cert_value": validCert,
"client_key": "/path/to/client.key",
"client_key_value": validKey,
"group_search_filter": "(&(objectClass=posixGroup)(memberUid=%s))",
"group_search_filter_user_attribute": "distinguishedName",
"group_search_base_dns": []string{"ou=groups,dc=grafana,dc=org"},
"tls_ciphers": []string{
"TLS_AES_256_GCM_SHA384",
},
"attributes": map[string]string{
"email": "mail",
"member_of": "memberOf",
"name": "displayName",
"surname": "sn",
"username": "cn",
},
"search_base_dns": []string{
"DC=ldap,DC=goauthentik,DC=io",
},
"group_mappings": []any{
map[string]any{
"group_dn": "cn=admin,ou=groups,dc=ldap,dc=goauthentik,dc=io",
"org_id": 1,
"org_role": "Admin",
"grafana_admin": true,
},
map[string]any{
"group_dn": "cn=editor,ou=groups,dc=ldap,dc=goauthentik,dc=io",
"org_id": 1,
"org_role": "Editor",
},
map[string]any{
"group_dn": "cn=viewer,ou=groups,dc=ldap,dc=goauthentik,dc=io",
"org_id": 1,
"org_role": "Viewer",
},
},
},
},
},
},
IsDeleted: false,
},
expectedServersConfig: &ldap.ServersConfig{
Servers: []*ldap.ServerConfig{
{
Host: "127.0.0.1",
Port: 3389,
UseSSL: true,
StartTLS: true,
SkipVerifySSL: false,
MinTLSVersion: "TLS1.3",
TLSCiphers: []string{
"TLS_AES_256_GCM_SHA384",
},
RootCACert: "/path/to/certificate.crt",
RootCACertValue: []string{validCert},
ClientCert: "/path/to/client.crt",
ClientCertValue: validCert,
ClientKey: "/path/to/client.key",
ClientKeyValue: validKey,
BindDN: "cn=ldapservice,ou=users,dc=ldap,dc=goauthentik,dc=io",
BindPassword: "grafana",
Timeout: 10,
Attr: ldap.AttributeMap{
Username: "cn",
Name: "displayName",
Surname: "sn",
Email: "mail",
MemberOf: "memberOf",
},
SearchFilter: "(cn=%s)",
SearchBaseDNs: []string{"DC=ldap,DC=goauthentik,DC=io"},
GroupSearchFilter: "(&(objectClass=posixGroup)(memberUid=%s))",
GroupSearchFilterUserAttribute: "distinguishedName",
GroupSearchBaseDNs: []string{"ou=groups,dc=grafana,dc=org"},
Groups: []*ldap.GroupToOrgRole{
{
GroupDN: "cn=admin,ou=groups,dc=ldap,dc=goauthentik,dc=io",
OrgId: 1,
OrgRole: "Admin",
IsGrafanaAdmin: &isAdmin,
},
{
GroupDN: "cn=editor,ou=groups,dc=ldap,dc=goauthentik,dc=io",
OrgId: 1,
OrgRole: "Editor",
},
{
GroupDN: "cn=viewer,ou=groups,dc=ldap,dc=goauthentik,dc=io",
OrgId: 1,
OrgRole: "Viewer",
},
},
},
},
},
expectedConfig: &ldap.Config{
Enabled: true,
AllowSignUp: true,
SkipOrgRoleSync: false,
},
},
{
description: "no servers config",
settings: models.SSOSettings{
Provider: "ldap",
Settings: map[string]any{
"enabled": true,
"skip_org_role_sync": false,
"allow_sign_up": true,
},
IsDeleted: false,
},
expectedServersConfig: &ldap.ServersConfig{Servers: nil},
expectedConfig: &ldap.Config{
Enabled: true,
AllowSignUp: true,
SkipOrgRoleSync: false,
},
},
{
description: "invalid settings",
settings: models.SSOSettings{
Provider: "ldap",
Settings: map[string]any{
"invalid": "some-value",
"another_one": true,
},
IsDeleted: false,
},
expectedServersConfig: &ldap.ServersConfig{Servers: nil},
expectedConfig: &ldap.Config{
AllowSignUp: true,
},
},
{
description: "config disabled",
settings: models.SSOSettings{
Provider: "ldap",
Settings: map[string]any{
"enabled": false,
"skip_org_role_sync": false,
"allow_sign_up": true,
"config": map[string]any{
"servers": []any{
map[string]any{
"host": "127.0.0.1",
},
},
},
},
IsDeleted: false,
},
expectedServersConfig: &ldap.ServersConfig{
Servers: []*ldap.ServerConfig{
{
Host: "127.0.0.1",
},
},
},
expectedConfig: &ldap.Config{
Enabled: false,
AllowSignUp: true,
SkipOrgRoleSync: false,
},
},
}
for _, tt := range testCases {
t.Run(tt.description, func(t *testing.T) {
ldapImpl := &LDAPImpl{
features: featuremgmt.WithManager(featuremgmt.FlagSsoSettingsApi),
loadingMutex: &sync.Mutex{},
}
err := ldapImpl.Reload(context.Background(), tt.settings)
require.NoError(t, err)
require.Equal(t, *tt.expectedServersConfig, *ldapImpl.ldapCfg)
require.Equal(t, *tt.expectedConfig, *ldapImpl.cfg)
})
}
}
+2 -2
View File
@@ -32,8 +32,8 @@ type ServersConfig struct {
// ServerConfig holds connection data to LDAP
type ServerConfig struct {
Host string `toml:"host"`
Port int `toml:"port"`
Host string `toml:"host" json:"host"`
Port int `toml:"port" json:"port,omitempty"`
UseSSL bool `toml:"use_ssl" json:"use_ssl,omitempty"`
StartTLS bool `toml:"start_tls" json:"start_tls,omitempty"`
@@ -18,7 +18,6 @@ import (
"github.com/grafana/grafana/pkg/login/social"
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/ldap/service"
"github.com/grafana/grafana/pkg/services/licensing"
"github.com/grafana/grafana/pkg/services/secrets"
"github.com/grafana/grafana/pkg/services/ssosettings"
@@ -48,10 +47,10 @@ type Service struct {
func ProvideService(cfg *setting.Cfg, sqlStore db.DB, ac ac.AccessControl,
routeRegister routing.RouteRegister, features featuremgmt.FeatureToggles,
secrets secrets.Service, usageStats usagestats.Service, registerer prometheus.Registerer,
settingsProvider setting.Provider, licensing licensing.Licensing, ldap service.LDAP) *Service {
settingsProvider setting.Provider, licensing licensing.Licensing) *Service {
fbStrategies := []ssosettings.FallbackStrategy{
strategies.NewOAuthStrategy(cfg),
strategies.NewLDAPStrategy(cfg, ldap),
strategies.NewLDAPStrategy(cfg),
}
configurableProviders := make(map[string]bool)
@@ -60,6 +59,11 @@ func ProvideService(cfg *setting.Cfg, sqlStore db.DB, ac ac.AccessControl,
}
providersList := ssosettings.AllOAuthProviders
if features.IsEnabledGlobally(featuremgmt.FlagSsoSettingsLDAP) {
providersList = append(providersList, social.LDAPProviderName)
}
if licensing.FeatureEnabled(social.SAMLProviderName) {
fbStrategies = append(fbStrategies, strategies.NewSAMLStrategy(settingsProvider))
@@ -22,7 +22,6 @@ import (
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/ldap/service"
"github.com/grafana/grafana/pkg/services/licensing/licensingtest"
secretsFakes "github.com/grafana/grafana/pkg/services/secrets/fakes"
"github.com/grafana/grafana/pkg/services/ssosettings"
@@ -1648,7 +1647,6 @@ func setupTestEnv(t *testing.T, isLicensingEnabled, keepFallbackStratergies, sam
prometheus.NewRegistry(),
&setting.OSSImpl{Cfg: cfg},
licensing,
service.ProvideService(cfg),
)
// overriding values for exposed fields
@@ -6,22 +6,20 @@ import (
"encoding/json"
"github.com/grafana/grafana/pkg/login/social"
"github.com/grafana/grafana/pkg/services/ldap/service"
"github.com/grafana/grafana/pkg/services/ldap"
"github.com/grafana/grafana/pkg/services/ssosettings"
"github.com/grafana/grafana/pkg/setting"
)
type LDAPStrategy struct {
cfg *setting.Cfg
ldap service.LDAP
cfg *setting.Cfg
}
var _ ssosettings.FallbackStrategy = (*LDAPStrategy)(nil)
func NewLDAPStrategy(cfg *setting.Cfg, ldap service.LDAP) *LDAPStrategy {
func NewLDAPStrategy(cfg *setting.Cfg) *LDAPStrategy {
return &LDAPStrategy{
cfg: cfg,
ldap: ldap,
cfg: cfg,
}
}
@@ -52,8 +50,13 @@ func (s *LDAPStrategy) GetProviderConfig(_ context.Context, _ string) (map[strin
func (s *LDAPStrategy) getLDAPConfig() (map[string]any, error) {
var configMap map[string]any
config := s.ldap.Config()
configJson, err := json.Marshal(config)
config := ldap.GetLDAPConfig(s.cfg)
ldapConfig, err := ldap.GetConfig(config)
if err != nil {
return nil, err
}
configJson, err := json.Marshal(ldapConfig)
if err != nil {
return nil, err
}
@@ -7,7 +7,6 @@ import (
"github.com/stretchr/testify/require"
"gopkg.in/ini.v1"
"github.com/grafana/grafana/pkg/services/ldap/service"
"github.com/grafana/grafana/pkg/setting"
)
@@ -29,8 +28,8 @@ var (
"config": map[string]interface{}{
"servers": []interface{}{
map[string]interface{}{
"Host": "127.0.0.1",
"Port": int64(3389),
"host": "127.0.0.1",
"port": int64(3389),
"attributes": map[string]interface{}{
"email": "mail",
"member_of": "memberOf",
@@ -76,9 +75,7 @@ func TestGetLDAPConfig(t *testing.T) {
cfg, err := setting.NewCfgFromINIFile(iniFile)
require.NoError(t, err)
ldap := service.ProvideService(cfg)
strategy := NewLDAPStrategy(cfg, ldap)
strategy := NewLDAPStrategy(cfg)
result, err := strategy.GetProviderConfig(context.Background(), "ldap")
require.NoError(t, err)
+1 -1
View File
@@ -365,7 +365,7 @@ func getTeamMember(sess *db.Session, orgId int64, teamId int64, userId int64) (t
func (ss *xormStore) IsMember(orgId int64, teamId int64, userId int64) (bool, error) {
var isMember bool
err := ss.db.WithTransactionalDbSession(context.Background(), func(sess *db.Session) error {
err := ss.db.WithDbSession(context.Background(), func(sess *db.Session) error {
var err error
isMember, err = isTeamMember(sess, orgId, teamId, userId)
return err
+7 -3
View File
@@ -16,7 +16,6 @@ import (
"path"
"path/filepath"
"regexp"
"runtime"
"strconv"
"strings"
"time"
@@ -475,6 +474,8 @@ type Cfg struct {
// RBAC single organization. This configuration option is subject to change.
RBACSingleOrganization bool
Zanzana ZanzanaSettings
// GRPC Server.
GRPCServerNetwork string
GRPCServerAddress string
@@ -1022,9 +1023,9 @@ func (cfg *Cfg) validateStaticRootPath() error {
func (cfg *Cfg) Load(args CommandLineArgs) error {
cfg.setHomePath(args)
// Fix for missing IANA db on Windows
// Fix for missing IANA db on Windows or Alpine
_, zoneInfoSet := os.LookupEnv(zoneInfo)
if runtime.GOOS == "windows" && !zoneInfoSet {
if !zoneInfoSet {
if err := os.Setenv(zoneInfo, filepath.Join(cfg.HomePath, "tools", "zoneinfo.zip")); err != nil {
cfg.Logger.Error("Can't set ZONEINFO environment variable", "err", err)
}
@@ -1113,6 +1114,9 @@ func (cfg *Cfg) parseINIFile(iniFile *ini.File) error {
readOAuth2ServerSettings(cfg)
readAccessControlSettings(iniFile, cfg)
cfg.readZanzanaSettings()
if err := cfg.readRenderingSettings(iniFile); err != nil {
return err
}
+37
View File
@@ -0,0 +1,37 @@
package setting
import (
"slices"
)
type ZanzanaMode string
const (
ZanzanaModeClient ZanzanaMode = "client"
ZanzanaModeEmbedded ZanzanaMode = "embedded"
)
type ZanzanaSettings struct {
// Addr is only used when mode is set to client
Addr string
// Mode can either be embedded or client
Mode ZanzanaMode
}
func (cfg *Cfg) readZanzanaSettings() {
s := ZanzanaSettings{}
sec := cfg.Raw.Section("zanzana")
s.Mode = ZanzanaMode(sec.Key("mode").MustString("embedded"))
validModes := []ZanzanaMode{ZanzanaModeEmbedded, ZanzanaModeClient}
if !slices.Contains(validModes, s.Mode) {
cfg.Logger.Warn("Invalid zanzana mode", "expected", validModes, "got", s.Mode)
s.Mode = "embedded"
}
s.Addr = sec.Key("address").MustString("")
cfg.Zanzana = s
}
+1 -1
View File
@@ -11,7 +11,7 @@ require (
require (
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/go-sql-driver/mysql v1.7.1 // indirect
github.com/go-sql-driver/mysql v1.8.1 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/rogpeppe/go-internal v1.12.0 // indirect
+3 -2
View File
@@ -1,10 +1,11 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
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-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:9wScpmSP5A3Bk8V3XHWUcJmYTh+ZnlHVyc+A4oZYS3Y=
github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:56xuuqnHyryaerycW3BfssRdxQstACi0Epw/yC5E2xM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=