diff --git a/charts/identity/Chart.yaml b/charts/identity/Chart.yaml index 52a07b52..7374bff2 100644 --- a/charts/identity/Chart.yaml +++ b/charts/identity/Chart.yaml @@ -4,7 +4,7 @@ description: A Helm chart for deploying Unikorn's IdP type: application -version: v0.1.22 -appVersion: v0.1.22 +version: v0.1.23 +appVersion: v0.1.23 icon: https://raw.githubusercontent.com/unikorn-cloud/assets/main/images/logos/dark-on-light/icon.png diff --git a/charts/identity/crds/identity.unikorn-cloud.org_organizations.yaml b/charts/identity/crds/identity.unikorn-cloud.org_organizations.yaml index 639edb45..091625a6 100644 --- a/charts/identity/crds/identity.unikorn-cloud.org_organizations.yaml +++ b/charts/identity/crds/identity.unikorn-cloud.org_organizations.yaml @@ -90,13 +90,6 @@ spec: roles: description: Roles are a list of roles users of the group inherit. items: - description: Role defines the role a user has within the Scope - of a group. - enum: - - superAdmin - - admin - - user - - reader type: string type: array users: diff --git a/charts/identity/crds/identity.unikorn-cloud.org_roles.yaml b/charts/identity/crds/identity.unikorn-cloud.org_roles.yaml new file mode 100644 index 00000000..f21b7156 --- /dev/null +++ b/charts/identity/crds/identity.unikorn-cloud.org_roles.yaml @@ -0,0 +1,100 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: roles.identity.unikorn-cloud.org +spec: + group: identity.unikorn-cloud.org + names: + categories: + - unikorn + kind: Role + listKind: RoleList + plural: roles + singular: role + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + Role defines a role type that forms the basis of RBAC. Permissions are + applied to arbitrary scopes that are used by individual components to + allow or prevent API access. Roles are additive, so effective RBAC + permssions should be create from the boolean union for any roles that apply + to a user. Roles can optionally be scoped to an organization to allow + deep customization of roles and permissions within that organization, for + example the system management organization may have an onboarding role that + allows basic account creation before handing off to the user. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: RoleSpec defines the role's requested state. + properties: + isDefault: + description: |- + IsDefault indicates that all authenticated users are granted + the following scopes regardless of organizational group membership + and typically are required for organization discovery and RBAC functionality + in the first instance. + type: boolean + scopes: + description: Scopes are a list of uniquely named scopes for the role. + items: + properties: + name: + description: |- + Name is a unique name that applies to the scope. Individual APIs should + coordinate with one another to avoid clashes and privilege escallation. + type: string + permissions: + description: Permissions defines a set of CRUD permissions for + the scope. + items: + enum: + - create + - read + - update + - delete + type: string + type: array + x-kubernetes-list-type: set + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + status: + description: RoleStatus defines any role status information. + type: object + required: + - spec + type: object + served: true + storage: true + subresources: {} diff --git a/charts/identity/templates/deployment.yaml b/charts/identity/templates/deployment.yaml index 51394586..c07e755b 100644 --- a/charts/identity/templates/deployment.yaml +++ b/charts/identity/templates/deployment.yaml @@ -36,6 +36,9 @@ spec: {{ printf "- --cors-max-age=%s" $cors.maxAge | nindent 8 }} {{- end }} {{- end }} + {{- if .Values.otlpEndpoint }} + {{ printf "- --otlp-endpoint=%s" .Values.otlpEndpoint | nindent 8 }} + {{- end }} volumeMounts: - name: unikorn-identity-jose-tls mountPath: /var/lib/secrets/unikorn-cloud.org/jose diff --git a/charts/identity/templates/identity-role.yaml b/charts/identity/templates/identity-role.yaml new file mode 100644 index 00000000..4f9bdd4e --- /dev/null +++ b/charts/identity/templates/identity-role.yaml @@ -0,0 +1,18 @@ +{{- range $role, $spec := .Values.roles }} +--- +apiVersion: identity.unikorn-cloud.org/v1alpha1 +kind: Role +metadata: + name: {{ $role }} +spec: + {{- if $spec.isDefault }} + isDefault: true + {{- end }} + {{- with $scopes := $spec.scopes }} + scopes: + {{- range $scope, $permissions := $scopes }} + {{- printf "- name: %s" $scope | nindent 4 }} + {{- printf "permissions: [%v]" ($permissions | join ", ") | nindent 6 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/charts/identity/templates/role.yaml b/charts/identity/templates/role.yaml index 08a923c0..67ad3863 100644 --- a/charts/identity/templates/role.yaml +++ b/charts/identity/templates/role.yaml @@ -10,6 +10,7 @@ rules: resources: - oauth2clients - oauth2providers + - roles - organizations verbs: - list diff --git a/charts/identity/values.yaml b/charts/identity/values.yaml index 5129849e..64339bcd 100644 --- a/charts/identity/values.yaml +++ b/charts/identity/values.yaml @@ -54,6 +54,33 @@ host: identity.acme.org # # The client secret assigned by the identity provider. # clientSecret: GOCSPX-akjfdns3238r328r9832rewjbds +# A static list of roles. +roles: + # A default role contains permissions that work at any scope + # in the system, and are a set of minimum required permissions. + default: + isDefault: true + scopes: + roles: [read] + organizations: [read] + reader: + scopes: + projects: [read] + infrastructure: [read] + user: + scopes: + projects: [read] + infrastructure: [create,read,update,delete] + admin: + scopes: + roles: [read] + organizations: [read,update] + groups: [create,read,update,delete] + oauth2providers-public: [read] + oauth2providers-private: [create,read,update,delete] + projects: [create,read,update,delete] + infrastructure: [create,read,update,delete] + # A static list of oauth2 domain mappings. # organizations: # - # Must be a member of the the domain. @@ -106,3 +133,6 @@ ingress: # allowOrigin: ['*'] # # How long to cache the CORS preflight for, mostly useless as browsers override this. # maxAge: 86400 + +# Sets the OTLP endpoint for shipping spans. +# otlpEndpoint: jaeger-collector.default:4318 diff --git a/go.mod b/go.mod index 00be0bde..8a40f910 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/go-jose/go-jose/v3 v3.0.3 github.com/google/uuid v1.6.0 github.com/spf13/pflag v1.0.5 - github.com/unikorn-cloud/core v0.1.20 + github.com/unikorn-cloud/core v0.1.21 go.opentelemetry.io/otel v1.24.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 go.opentelemetry.io/otel/sdk v1.24.0 diff --git a/go.sum b/go.sum index eb8ad327..1a0b7df5 100644 --- a/go.sum +++ b/go.sum @@ -13,8 +13,6 @@ github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= -github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= -github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ= @@ -25,28 +23,21 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w= github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= -github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s= -github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM= github.com/bytedance/sonic v1.11.3 h1:jRN+yEjakWh8aK5FzrciUHG8OFXK+4/KrAX/ysEtHAA= github.com/bytedance/sonic v1.11.3/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4= -github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= -github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= -github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0= github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA= github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= github.com/chenzhuoyu/iasm v0.9.1 h1:tUHQJXo3NhBqw6s33wkGn9SP3bvrWLdlVIJ3hQBL7P0= github.com/chenzhuoyu/iasm v0.9.1/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= -github.com/coreos/go-oidc/v3 v3.9.0 h1:0J/ogVOd4y8P0f0xUh8l9t07xRP/d8tccvjHl2dcsSo= -github.com/coreos/go-oidc/v3 v3.9.0/go.mod h1:rTKz2PYwftcrtoCzV5g5kvfJoWcm0Mk8AF8y1iAQro4= github.com/coreos/go-oidc/v3 v3.10.0 h1:tDnXHnLyiTVyT/2zLDGj09pFPkhND8Gl8lnTRhoEaJU= github.com/coreos/go-oidc/v3 v3.10.0/go.mod h1:5j11xcw0D3+SGxn6Z/WFADsgcWVMyNAlSQupk0KK3ac= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -54,11 +45,10 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/deepmap/oapi-codegen v1.16.2 h1:xGHx0dNqYfy9gE8a7AVgVM8Sd5oF9SEgePzP+UPAUXI= github.com/deepmap/oapi-codegen v1.16.2/go.mod h1:rdYoEA2GE+riuZ91DvpmBX9hJbQpuY9wchXpfQ3n+ho= -github.com/emicklei/go-restful/v3 v3.11.2 h1:1onLa9DcsMYO9P+CXaL0dStDqQ2EHHXLiz+BtnqkLAU= -github.com/emicklei/go-restful/v3 v3.11.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/emicklei/go-restful/v3 v3.12.0 h1:y2DdzBAURM29NFF94q6RaY4vjIH1rtwDapwQtU84iWk= github.com/emicklei/go-restful/v3 v3.12.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls= +github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= @@ -69,8 +59,6 @@ github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0H github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= -github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/getkin/kin-openapi v0.123.0 h1:zIik0mRwFNLyvtXK274Q6ut+dPh6nlxBp0x7mNrPhs8= @@ -79,12 +67,8 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= -github.com/go-chi/chi/v5 v5.0.11 h1:BnpYbFZ3T3S1WMpD79r7R5ThWX40TaFB7L31Y8xqSwA= -github.com/go-chi/chi/v5 v5.0.11/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s= github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= -github.com/go-jose/go-jose/v3 v3.0.1 h1:pWmKFVtt+Jl0vBZTIpz/eAKwsm6LkIxDVVbFHKkchhA= -github.com/go-jose/go-jose/v3 v3.0.1/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k= github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ= github.com/go-jose/go-jose/v4 v4.0.1 h1:QVEPDE3OluqXBQZDcnNvQrInro2h0e4eqNbnZSWqS6U= @@ -96,16 +80,10 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= 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.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q= -github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs= github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= -github.com/go-openapi/jsonreference v0.20.4 h1:bKlDxQxQJgwpUSgOENiMPzCTBVuc7vTdXSSgNeAhojU= -github.com/go-openapi/jsonreference v0.20.4/go.mod h1:5pZJyJP2MnYCpoeoMAql78cCHauHj0V9Lhc506VOpw4= github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= -github.com/go-openapi/swag v0.22.9 h1:XX2DssF+mQKM2DHsbgZK74y/zj4mo9I99+89xUmuZCE= -github.com/go-openapi/swag v0.22.9/go.mod h1:3/OXnFfnMAwBD099SwYRk7GD3xOrr1iL7d/XNLXVVwE= github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= @@ -114,8 +92,6 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js= -github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/go-playground/validator/v10 v10.19.0 h1:ol+5Fu+cSq9JD7SoSqe04GMI92cbn0+wvQ3bZ8b/AU4= github.com/go-playground/validator/v10 v10.19.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= @@ -128,26 +104,18 @@ github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= -github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= -github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/gomarkdown/markdown v0.0.0-20230716120725-531d2d74bc12 h1:uK3X/2mt4tbSGoHvbLBHUny7CKiuwUip3MArtukol4E= -github.com/gomarkdown/markdown v0.0.0-20230716120725-531d2d74bc12/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= github.com/gomarkdown/markdown v0.0.0-20231222211730-1d6d20845b47 h1:k4Tw0nt6lwro3Uin8eqoET7MDA4JnT8YgbCjc/g5E3k= github.com/gomarkdown/markdown v0.0.0-20231222211730-1d6d20845b47/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= @@ -161,16 +129,12 @@ github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJY github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= -github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8= github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0QDGLKzqOmktBjT+Is= github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM= github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= @@ -188,20 +152,12 @@ github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFF github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE= -github.com/kataras/blocks v0.0.7 h1:cF3RDY/vxnSRezc7vLFlQFTYXG/yAr1o7WImJuZbzC4= -github.com/kataras/blocks v0.0.7/go.mod h1:UJIU97CluDo0f+zEjbnbkeMRlvYORtmc1304EeyXf4I= github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM= github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg= -github.com/kataras/golog v0.1.9 h1:vLvSDpP7kihFGKFAvBSofYo7qZNULYSHOH2D7rPTKJk= -github.com/kataras/golog v0.1.9/go.mod h1:jlpk/bOaYCyqDqH18pgDHdaJab72yBE6i0O3s30hpWY= github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20= github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A= -github.com/kataras/iris/v12 v12.2.6-0.20230908161203-24ba4e8933b9 h1:Vx8kDVhO2qepK8w44lBtp+RzN3ld743i+LYPzODJSpQ= -github.com/kataras/iris/v12 v12.2.6-0.20230908161203-24ba4e8933b9/go.mod h1:ldkoR3iXABBeqlTibQ3MYaviA1oSlPvim6f55biwBh4= github.com/kataras/iris/v12 v12.2.10 h1:rEJVM7qMoyhv8wpgkA1yGxibFcONE0jkJ70LFLibTAA= github.com/kataras/iris/v12 v12.2.10/go.mod h1:z4+E+kLMqZ7U4WtDsYfFnG7BjMTXLkdzMAXLVMLnMNs= -github.com/kataras/pio v0.0.12 h1:o52SfVYauS3J5X08fNjlGS5arXHjW/ItLkyLcKjoH6w= -github.com/kataras/pio v0.0.12/go.mod h1:ODK/8XBhhQ5WqrAhKy+9lTPS7sBf6O3KcLhc9klfRcY= github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM= github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM= github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= @@ -210,13 +166,9 @@ github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= -github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= -github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= @@ -226,33 +178,21 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/labstack/echo/v4 v4.11.1 h1:dEpLU2FLg4UVmvCGPuk/APjlH6GDpbEPti61srUUUs4= -github.com/labstack/echo/v4 v4.11.1/go.mod h1:YuYRTSM3CHs2ybfrL8Px48bO6BAnYIN4l8wSTMP6BDQ= github.com/labstack/echo/v4 v4.11.4 h1:vDZmA+qNeh1pd/cCkEicDMrjtrnMGQ1QFI9gWN1zGq8= github.com/labstack/echo/v4 v4.11.4/go.mod h1:noh7EvLwqDsmh/X/HWKPUl1AjzJrhyptRyEbQJfxen8= -github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8= -github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0= github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU= -github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= -github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/microcosm-cc/bluemonday v1.0.25 h1:4NEwSfiJ+Wva0VxN5B8OwMicaJvD8r9tlJWm9rtloEg= -github.com/microcosm-cc/bluemonday v1.0.25/go.mod h1:ZIOjCQp1OrzBBPIJmfX4qDYFuhU02nx4bn030ixfHLE= github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= @@ -271,8 +211,6 @@ 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/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= -github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeBAsoHo= github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= @@ -281,14 +219,14 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -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.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= -github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= -github.com/prometheus/common v0.46.0 h1:doXzt5ybi1HBKpsZOL0sSkaNHJJqkyfEWZGGqqScV0Y= -github.com/prometheus/common v0.46.0/go.mod h1:Tp0qkxpb9Jsg54QMe+EAmqXkSV7Evdy1BTn+g2pa/hQ= -github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= -github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.51.1 h1:eIjN50Bwglz6a/c3hAgSMcofL3nD+nFQkV6Dd4DsQCw= +github.com/prometheus/common v0.51.1/go.mod h1:lrWtQx+iDfn2mbH5GUzlH9TSHyfZpHkSiG1W7y3sF2Q= +github.com/prometheus/procfs v0.13.0 h1:GqzLlQyfsPbaEHaQkO7tbDlriv/4o5Hudv6OXHGKX7o= +github.com/prometheus/procfs v0.13.0/go.mod h1:cd4PFCR54QLnGKPaKGA6l+cfuNXtht43ZKY6tow0Y1g= 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/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= @@ -299,7 +237,6 @@ github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiy github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= @@ -312,46 +249,30 @@ 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.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/tdewolff/minify/v2 v2.12.9 h1:dvn5MtmuQ/DFMwqf5j8QhEVpPX6fi3WGImhv8RUB4zA= -github.com/tdewolff/minify/v2 v2.12.9/go.mod h1:qOqdlDfL+7v0/fyymB+OP497nIxJYSvX4MQWA8OoiXU= github.com/tdewolff/minify/v2 v2.20.19 h1:tX0SR0LUrIqGoLjXnkIzRSIbKJ7PaNnSENLD4CyH6Xo= github.com/tdewolff/minify/v2 v2.20.19/go.mod h1:ulkFoeAVWMLEyjuDz1ZIWOA31g5aWOawCFRp9R/MudM= -github.com/tdewolff/parse/v2 v2.6.8 h1:mhNZXYCx//xG7Yq2e/kVLNZw4YfYmeHbhx+Zc0OvFMA= -github.com/tdewolff/parse/v2 v2.6.8/go.mod h1:XHDhaU6IBgsryfdnpzUXBlT6leW/l25yrFBTEb4eIyM= github.com/tdewolff/parse/v2 v2.7.12 h1:tgavkHc2ZDEQVKy1oWxwIyh5bP4F5fEh/JmBwPP/3LQ= github.com/tdewolff/parse/v2 v2.7.12/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= -github.com/tdewolff/test v1.0.9 h1:SswqJCmeN4B+9gEAi/5uqT0qpi1y2/2O47V/1hhGZT0= -github.com/tdewolff/test v1.0.9/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= -github.com/unikorn-cloud/core v0.1.19 h1:nMXAnSEdE1q6rLqOt5fNvPSqTDx2fGk2kp0dHXqQDL0= -github.com/unikorn-cloud/core v0.1.19/go.mod h1:5LzHGYsCfMxC9tv+QblOKH6CDYryX1umvaLrYFh0y6M= -github.com/unikorn-cloud/core v0.1.20-0.20240328134126-0fc0502b1f91 h1:Zhy6DTSbxfMc8RtGQCpVSOsgqtLTUYA05yRGokPog0Q= -github.com/unikorn-cloud/core v0.1.20-0.20240328134126-0fc0502b1f91/go.mod h1:cP39UQN7aSmsfjQuSMsworI4oBIwx4oA4u20CbPpfZw= -github.com/unikorn-cloud/core v0.1.20-0.20240328134604-85598306b202 h1:6QTKNLr+a0WpZ9ywsvuqIrsIu1G1RRG1T8dJR1ijyA4= -github.com/unikorn-cloud/core v0.1.20-0.20240328134604-85598306b202/go.mod h1:cP39UQN7aSmsfjQuSMsworI4oBIwx4oA4u20CbPpfZw= -github.com/unikorn-cloud/core v0.1.20 h1:PLJ8PRQ6c+igApAtR5iN3w/ADcnobQ1UHgQArQYt2j8= -github.com/unikorn-cloud/core v0.1.20/go.mod h1:cP39UQN7aSmsfjQuSMsworI4oBIwx4oA4u20CbPpfZw= +github.com/unikorn-cloud/core v0.1.21 h1:2KGSzwJF/EXqFozt3FYMiJO+nwIGEcgcrF9zuSngY3E= +github.com/unikorn-cloud/core v0.1.21/go.mod h1:cP39UQN7aSmsfjQuSMsworI4oBIwx4oA4u20CbPpfZw= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= -github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU= -github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= @@ -376,51 +297,34 @@ github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 h1:9M3+rhx7kZCIQQhQRYaZCdNu1V73tm4TvXs2ntl98C4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0/go.mod h1:noq80iT8rrHP1SfybmPiRGc9dc5M8RPmGvtwo7Oo7tc= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 h1:t6wl9SPayj+c7lEIFgm4ooDBZVb01IhLB4InpomhRw8= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0/go.mod h1:iSDOcsnSA5INXzZtwaBPrKp/lWu/V14Dd+llD0oI2EA= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0 h1:FyjCyI9jVEfqhUh2MoSkmolPjfh5fp2hnV0b0irxH4Q= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0/go.mod h1:hYwym2nDEeZfG/motx0p7L7J1N1vyzIThemQsb4g2qY= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 h1:Xw8U6u2f8DK2XAkGRFV7BBLENgnTGX9i4rQRxJf+/vs= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0/go.mod h1:6KW1Fm6R/s6Z3PGXwSJN2K4eT6wQB3vXX6CVnYX9NmM= go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= -go.opentelemetry.io/otel/sdk v1.22.0 h1:6coWHw9xw7EfClIC/+O31R8IY3/+EiRFHevmHafB2Gw= -go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc= go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= -go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= -go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= 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.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -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= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= -golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k= -golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc= golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 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= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= -golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= -golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA= -golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 h1:aAcj0Da7eBAtrTp03QXWvm88pSyOt+UgdZw2BFZ+lEw= golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -438,12 +342,8 @@ golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= -golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ= -golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -459,19 +359,14 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/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-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-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/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-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= @@ -479,8 +374,6 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= -golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= @@ -502,8 +395,8 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= -golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= +golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw= +golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc= 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= @@ -512,25 +405,14 @@ gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= -google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 h1:SeZZZx0cP0fqUyA+oRzP9k7cSwJlvDFiROO72uwD6i0= -google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97/go.mod h1:t1VqOqqvce95G3hIDCT5FeO3YUc6Q4Oe24L/+rNMxRk= -google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ= -google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 h1:W18sezcAYs+3tDZX4F80yctqa12jcP1PUS2gQu1zTPU= -google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97/go.mod h1:iargEX0SFPm3xcfMI0d1domjg0ZF4Aa0p2awqyxhvF0= google.golang.org/genproto/googleapis/api v0.0.0-20240325203815-454cdb8f5daa h1:Jt1XW5PaLXF1/ePZrznsh/aAUvI7Adfc3LY1dAKlzRs= google.golang.org/genproto/googleapis/api v0.0.0-20240325203815-454cdb8f5daa/go.mod h1:K4kfzHtI0kqWA79gecJarFtDn/Mls+GxQcg3Zox91Ac= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 h1:6GQBEOdGkX6MMTLT9V+TjtIRZCw9VPD5Z+yHY9wMgS0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97/go.mod h1:v7nGkzlmW8P3n/bKmWBn2WpBjpOEx8Q6gMueudAmKfY= google.golang.org/genproto/googleapis/rpc v0.0.0-20240325203815-454cdb8f5daa h1:RBgMaUMP+6soRkik4VoN8ojR2nex2TqZwjSSogic+eo= google.golang.org/genproto/googleapis/rpc v0.0.0-20240325203815-454cdb8f5daa/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= -google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= -google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk= google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= -google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -545,42 +427,29 @@ 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.0/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= -k8s.io/api v0.29.1 h1:DAjwWX/9YT7NQD4INu49ROJuZAAAP/Ijki48GUPzxqw= -k8s.io/api v0.29.1/go.mod h1:7Kl10vBRUXhnQQI8YR/R327zXC8eJ7887/+Ybta+RoQ= k8s.io/api v0.29.3 h1:2ORfZ7+bGC3YJqGpV0KSDDEVf8hdGQ6A03/50vj8pmw= k8s.io/api v0.29.3/go.mod h1:y2yg2NTyHUUkIoTC+phinTnEa3KFM6RZ3szxt014a80= k8s.io/apiextensions-apiserver v0.29.0 h1:0VuspFG7Hj+SxyF/Z/2T0uFbI5gb5LRgEyUVE3Q4lV0= k8s.io/apiextensions-apiserver v0.29.0/go.mod h1:TKmpy3bTS0mr9pylH0nOt/QzQRrW7/h7yLdRForMZwc= -k8s.io/apimachinery v0.29.1 h1:KY4/E6km/wLBguvCZv8cKTeOwwOBqFNjwJIdMkMbbRc= -k8s.io/apimachinery v0.29.1/go.mod h1:6HVkd1FwxIagpYrHSwJlQqZI3G9LfYWRPAkUvLnXTKU= k8s.io/apimachinery v0.29.3 h1:2tbx+5L7RNvqJjn7RIuIKu9XTsIZ9Z5wX2G22XAa5EU= k8s.io/apimachinery v0.29.3/go.mod h1:hx/S4V2PNW4OMg3WizRrHutyB5la0iCUbZym+W0EQIU= -k8s.io/client-go v0.29.1 h1:19B/+2NGEwnFLzt0uB5kNJnfTsbV8w6TgQRz9l7ti7A= -k8s.io/client-go v0.29.1/go.mod h1:TDG/psL9hdet0TI9mGyHJSgRkW3H9JZk2dNEUS7bRks= k8s.io/client-go v0.29.3 h1:R/zaZbEAxqComZ9FHeQwOh3Y1ZUs7FaHKZdQtIc2WZg= k8s.io/client-go v0.29.3/go.mod h1:tkDisCvgPfiRpxGnOORfkljmS+UrW+WtXAy2fTvXJB0= -k8s.io/component-base v0.29.1 h1:MUimqJPCRnnHsskTTjKD+IC1EHBbRCVyi37IoFBrkYw= -k8s.io/component-base v0.29.1/go.mod h1:fP9GFjxYrLERq1GcWWZAE3bqbNcDKDytn2srWuHTtKc= +k8s.io/component-base v0.29.3 h1:Oq9/nddUxlnrCuuR2K/jp6aflVvc0uDvxMzAWxnGzAo= +k8s.io/component-base v0.29.3/go.mod h1:Yuj33XXjuOk2BAaHsIGHhCKZQAgYKhqIxIjIr2UXYio= k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20240126223410-2919ad4fcfec h1:iGTel2aR8vCZdxJDgmbeY0zrlXy9Qcvyw4R2sB4HLrA= -k8s.io/kube-openapi v0.0.0-20240126223410-2919ad4fcfec/go.mod h1:Pa1PvrP7ACSkuX6I7KYomY6cmMA0Tx86waBhDUgoKPw= k8s.io/kube-openapi v0.0.0-20240322212309-b815d8309940 h1:qVoMaQV5t62UUvHe16Q3eb2c5HPzLHYzsi0Tu/xLndo= k8s.io/kube-openapi v0.0.0-20240322212309-b815d8309940/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= -k8s.io/utils v0.0.0-20240102154912-e7106e64919e h1:eQ/4ljkx21sObifjzXwlPKpdGLrCfRziVtos3ofG/sQ= -k8s.io/utils v0.0.0-20240102154912-e7106e64919e/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= k8s.io/utils v0.0.0-20240310230437-4693a0247e57 h1:gbqbevonBh57eILzModw6mrkbwM0gQBEuevE/AaBsHY= k8s.io/utils v0.0.0-20240310230437-4693a0247e57/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= -sigs.k8s.io/controller-runtime v0.17.0 h1:fjJQf8Ukya+VjogLO6/bNX9HE6Y2xpsO5+fyS26ur/s= -sigs.k8s.io/controller-runtime v0.17.0/go.mod h1:+MngTvIQQQhfXtwfdGw/UOQ/aIaqsYywfCINOtwMO/s= sigs.k8s.io/controller-runtime v0.17.2 h1:FwHwD1CTUemg0pW2otk7/U5/i5m2ymzvOXdbeGOUvw0= sigs.k8s.io/controller-runtime v0.17.2/go.mod h1:+MngTvIQQQhfXtwfdGw/UOQ/aIaqsYywfCINOtwMO/s= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= diff --git a/openapi/server.spec.yaml b/openapi/server.spec.yaml index c5bc8ef1..d9ec0ce7 100644 --- a/openapi/server.spec.yaml +++ b/openapi/server.spec.yaml @@ -173,6 +173,25 @@ paths: $ref: '#/components/responses/unauthorizedResponse' '403': $ref: '#/components/responses/forbiddenResponse' + /api/v1/organizations/{organization}/acl: + description: |- + Gets an ACL associated with the user, scoped to the organization. + This is used to perform basic RBAC on remote services and to control + UX. + parameters: + - $ref: '#/components/parameters/organizationParameter' + get: + description: |- + Returns access control properties for the user. + security: + - oauth2Authentication: [] + responses: + '200': + $ref: '#/components/responses/aclResponse' + '401': + $ref: '#/components/responses/unauthorizedResponse' + '500': + $ref: '#/components/responses/internalServerErrorResponse' /api/v1/organizations/{organization}/oauth2/providers: description: |- Allows management of oauth2 providers. The identity service is typically @@ -630,6 +649,43 @@ components: type: array items: $ref: '#/components/schemas/organization' + aclPermissions: + description: A list of access control permissions. + type: array + items: + description: An access control permission. + type: string + enum: + - create + - read + - update + - delete + aclScope: + description: An access control scope. + type: object + required: + - name + - permissions + properties: + name: + description: The scope name + type: string + permissions: + $ref: '#/components/schemas/aclPermissions' + aclScopes: + description: A list of access control scopes. + type: array + items: + $ref: '#/components/schemas/aclScope' + acl: + description: A list of access control scopes and permissions. + type: object + properties: + isSuperAdmin: + description: Indicates the user can do all the things. + type: boolean + scopes: + $ref: '#/components/schemas/aclScopes' userList: description: A list of users. type: array @@ -859,6 +915,18 @@ components: - name: acme-corp domain: acme.corp providerName: google-identity + aclResponse: + description: |- + A list of access controls. + content: + application/json: + schema: + $ref: '#/components/schemas/acl' + example: + isSuperAdmin: false + scopes: + organizations: + - read groupResponse: description: |- A group in the organization. diff --git a/pkg/apis/unikorn/v1alpha1/register.go b/pkg/apis/unikorn/v1alpha1/register.go index 0a8c6953..d188086a 100644 --- a/pkg/apis/unikorn/v1alpha1/register.go +++ b/pkg/apis/unikorn/v1alpha1/register.go @@ -49,6 +49,7 @@ var ( func init() { SchemeBuilder.Register(&OAuth2Client{}, &OAuth2ClientList{}) SchemeBuilder.Register(&OAuth2Provider{}, &OAuth2ProviderList{}) + SchemeBuilder.Register(&Role{}, &RoleList{}) SchemeBuilder.Register(&Organization{}, &OrganizationList{}) } diff --git a/pkg/apis/unikorn/v1alpha1/types.go b/pkg/apis/unikorn/v1alpha1/types.go index ef9bec81..62b5241a 100644 --- a/pkg/apis/unikorn/v1alpha1/types.go +++ b/pkg/apis/unikorn/v1alpha1/types.go @@ -18,7 +18,7 @@ limitations under the License. package v1alpha1 import ( - "github.com/unikorn-cloud/core/pkg/authorization/roles" + "github.com/unikorn-cloud/core/pkg/authorization/constants" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -117,6 +117,58 @@ type OAuth2ProviderSpec struct { type OAuth2ProviderStatus struct { } +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type RoleList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Role `json:"items"` +} + +// Role defines a role type that forms the basis of RBAC. Permissions are +// applied to arbitrary scopes that are used by individual components to +// allow or prevent API access. Roles are additive, so effective RBAC +// permssions should be create from the boolean union for any roles that apply +// to a user. Roles can optionally be scoped to an organization to allow +// deep customization of roles and permissions within that organization, for +// example the system management organization may have an onboarding role that +// allows basic account creation before handing off to the user. +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:resource:scope=Namespaced,categories=unikorn +// +kubebuilder:printcolumn:name="age",type="date",JSONPath=".metadata.creationTimestamp" +type Role struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + Spec RoleSpec `json:"spec"` + Status RoleStatus `json:"status,omitempty"` +} + +// RoleSpec defines the role's requested state. +type RoleSpec struct { + // IsDefault indicates that all authenticated users are granted + // the following scopes regardless of organizational group membership + // and typically are required for organization discovery and RBAC functionality + // in the first instance. + IsDefault bool `json:"isDefault,omitempty"` + // Scopes are a list of uniquely named scopes for the role. + // +listType=map + // +listMapKey=name + Scopes []RoleScope `json:"scopes,omitempty"` +} + +type RoleScope struct { + // Name is a unique name that applies to the scope. Individual APIs should + // coordinate with one another to avoid clashes and privilege escallation. + Name string `json:"name"` + // Permissions defines a set of CRUD permissions for the scope. + // +listType=set + Permissions []constants.Permission `json:"permissions,omitempty"` +} + +// RoleStatus defines any role status information. +type RoleStatus struct { +} + // OrganizationList is a typed list of identity mappings. // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object type OrganizationList struct { @@ -189,7 +241,7 @@ type OrganizationGroup struct { // Users are a list of user names that are members of the group. Users []string `json:"users,omitempty"` // Roles are a list of roles users of the group inherit. - Roles []roles.Role `json:"roles,omitempty"` + Roles []string `json:"roles,omitempty"` } // OrganizationStatus defines the status of the server. diff --git a/pkg/apis/unikorn/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/unikorn/v1alpha1/zz_generated.deepcopy.go index f37e173e..b61f7f2a 100644 --- a/pkg/apis/unikorn/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/unikorn/v1alpha1/zz_generated.deepcopy.go @@ -22,7 +22,7 @@ limitations under the License. package v1alpha1 import ( - roles "github.com/unikorn-cloud/core/pkg/authorization/roles" + constants "github.com/unikorn-cloud/core/pkg/authorization/constants" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -265,7 +265,7 @@ func (in *OrganizationGroup) DeepCopyInto(out *OrganizationGroup) { } if in.Roles != nil { in, out := &in.Roles, &out.Roles - *out = make([]roles.Role, len(*in)) + *out = make([]string, len(*in)) copy(*out, *in) } return @@ -404,3 +404,124 @@ func (in *OrganizationStatus) DeepCopy() *OrganizationStatus { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Role) DeepCopyInto(out *Role) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + out.Status = in.Status + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Role. +func (in *Role) DeepCopy() *Role { + if in == nil { + return nil + } + out := new(Role) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Role) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RoleList) DeepCopyInto(out *RoleList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Role, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RoleList. +func (in *RoleList) DeepCopy() *RoleList { + if in == nil { + return nil + } + out := new(RoleList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *RoleList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RoleScope) DeepCopyInto(out *RoleScope) { + *out = *in + if in.Permissions != nil { + in, out := &in.Permissions, &out.Permissions + *out = make([]constants.Permission, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RoleScope. +func (in *RoleScope) DeepCopy() *RoleScope { + if in == nil { + return nil + } + out := new(RoleScope) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RoleSpec) DeepCopyInto(out *RoleSpec) { + *out = *in + if in.Scopes != nil { + in, out := &in.Scopes, &out.Scopes + *out = make([]RoleScope, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RoleSpec. +func (in *RoleSpec) DeepCopy() *RoleSpec { + if in == nil { + return nil + } + out := new(RoleSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RoleStatus) DeepCopyInto(out *RoleStatus) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RoleStatus. +func (in *RoleStatus) DeepCopy() *RoleStatus { + if in == nil { + return nil + } + out := new(RoleStatus) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/generated/client.go b/pkg/generated/client.go index d6e52aaa..0042d4f2 100644 --- a/pkg/generated/client.go +++ b/pkg/generated/client.go @@ -105,6 +105,9 @@ type ClientInterface interface { PutApiV1OrganizationsOrganization(ctx context.Context, organization OrganizationParameter, body PutApiV1OrganizationsOrganizationJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + // GetApiV1OrganizationsOrganizationAcl request + GetApiV1OrganizationsOrganizationAcl(ctx context.Context, organization OrganizationParameter, reqEditors ...RequestEditorFn) (*http.Response, error) + // GetApiV1OrganizationsOrganizationGroups request GetApiV1OrganizationsOrganizationGroups(ctx context.Context, organization OrganizationParameter, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -222,6 +225,18 @@ func (c *Client) PutApiV1OrganizationsOrganization(ctx context.Context, organiza return c.Client.Do(req) } +func (c *Client) GetApiV1OrganizationsOrganizationAcl(ctx context.Context, organization OrganizationParameter, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetApiV1OrganizationsOrganizationAclRequest(c.Server, organization) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + func (c *Client) GetApiV1OrganizationsOrganizationGroups(ctx context.Context, organization OrganizationParameter, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewGetApiV1OrganizationsOrganizationGroupsRequest(c.Server, organization) if err != nil { @@ -555,6 +570,40 @@ func NewPutApiV1OrganizationsOrganizationRequestWithBody(server string, organiza return req, nil } +// NewGetApiV1OrganizationsOrganizationAclRequest generates requests for GetApiV1OrganizationsOrganizationAcl +func NewGetApiV1OrganizationsOrganizationAclRequest(server string, organization OrganizationParameter) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "organization", runtime.ParamLocationPath, organization) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/api/v1/organizations/%s/acl", pathParam0) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + // NewGetApiV1OrganizationsOrganizationGroupsRequest generates requests for GetApiV1OrganizationsOrganizationGroups func NewGetApiV1OrganizationsOrganizationGroupsRequest(server string, organization OrganizationParameter) (*http.Request, error) { var err error @@ -1053,6 +1102,9 @@ type ClientWithResponsesInterface interface { PutApiV1OrganizationsOrganizationWithResponse(ctx context.Context, organization OrganizationParameter, body PutApiV1OrganizationsOrganizationJSONRequestBody, reqEditors ...RequestEditorFn) (*PutApiV1OrganizationsOrganizationResponse, error) + // GetApiV1OrganizationsOrganizationAcl request + GetApiV1OrganizationsOrganizationAclWithResponse(ctx context.Context, organization OrganizationParameter, reqEditors ...RequestEditorFn) (*GetApiV1OrganizationsOrganizationAclResponse, error) + // GetApiV1OrganizationsOrganizationGroups request GetApiV1OrganizationsOrganizationGroupsWithResponse(ctx context.Context, organization OrganizationParameter, reqEditors ...RequestEditorFn) (*GetApiV1OrganizationsOrganizationGroupsResponse, error) @@ -1192,6 +1244,30 @@ func (r PutApiV1OrganizationsOrganizationResponse) StatusCode() int { return 0 } +type GetApiV1OrganizationsOrganizationAclResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *Acl + JSON401 *Oauth2Error + JSON500 *Oauth2Error +} + +// Status returns HTTPResponse.Status +func (r GetApiV1OrganizationsOrganizationAclResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r GetApiV1OrganizationsOrganizationAclResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type GetApiV1OrganizationsOrganizationGroupsResponse struct { Body []byte HTTPResponse *http.Response @@ -1527,6 +1603,15 @@ func (c *ClientWithResponses) PutApiV1OrganizationsOrganizationWithResponse(ctx return ParsePutApiV1OrganizationsOrganizationResponse(rsp) } +// GetApiV1OrganizationsOrganizationAclWithResponse request returning *GetApiV1OrganizationsOrganizationAclResponse +func (c *ClientWithResponses) GetApiV1OrganizationsOrganizationAclWithResponse(ctx context.Context, organization OrganizationParameter, reqEditors ...RequestEditorFn) (*GetApiV1OrganizationsOrganizationAclResponse, error) { + rsp, err := c.GetApiV1OrganizationsOrganizationAcl(ctx, organization, reqEditors...) + if err != nil { + return nil, err + } + return ParseGetApiV1OrganizationsOrganizationAclResponse(rsp) +} + // GetApiV1OrganizationsOrganizationGroupsWithResponse request returning *GetApiV1OrganizationsOrganizationGroupsResponse func (c *ClientWithResponses) GetApiV1OrganizationsOrganizationGroupsWithResponse(ctx context.Context, organization OrganizationParameter, reqEditors ...RequestEditorFn) (*GetApiV1OrganizationsOrganizationGroupsResponse, error) { rsp, err := c.GetApiV1OrganizationsOrganizationGroups(ctx, organization, reqEditors...) @@ -1813,6 +1898,46 @@ func ParsePutApiV1OrganizationsOrganizationResponse(rsp *http.Response) (*PutApi return response, nil } +// ParseGetApiV1OrganizationsOrganizationAclResponse parses an HTTP response from a GetApiV1OrganizationsOrganizationAclWithResponse call +func ParseGetApiV1OrganizationsOrganizationAclResponse(rsp *http.Response) (*GetApiV1OrganizationsOrganizationAclResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &GetApiV1OrganizationsOrganizationAclResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest Acl + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: + var dest Oauth2Error + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON401 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: + var dest Oauth2Error + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON500 = &dest + + } + + return response, nil +} + // ParseGetApiV1OrganizationsOrganizationGroupsResponse parses an HTTP response from a GetApiV1OrganizationsOrganizationGroupsWithResponse call func ParseGetApiV1OrganizationsOrganizationGroupsResponse(rsp *http.Response) (*GetApiV1OrganizationsOrganizationGroupsResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) diff --git a/pkg/generated/router.go b/pkg/generated/router.go index 7568a957..f4becf02 100644 --- a/pkg/generated/router.go +++ b/pkg/generated/router.go @@ -27,6 +27,9 @@ type ServerInterface interface { // (PUT /api/v1/organizations/{organization}) PutApiV1OrganizationsOrganization(w http.ResponseWriter, r *http.Request, organization OrganizationParameter) + // (GET /api/v1/organizations/{organization}/acl) + GetApiV1OrganizationsOrganizationAcl(w http.ResponseWriter, r *http.Request, organization OrganizationParameter) + // (GET /api/v1/organizations/{organization}/groups) GetApiV1OrganizationsOrganizationGroups(w http.ResponseWriter, r *http.Request, organization OrganizationParameter) @@ -150,6 +153,34 @@ func (siw *ServerInterfaceWrapper) PutApiV1OrganizationsOrganization(w http.Resp handler.ServeHTTP(w, r.WithContext(ctx)) } +// GetApiV1OrganizationsOrganizationAcl operation middleware +func (siw *ServerInterfaceWrapper) GetApiV1OrganizationsOrganizationAcl(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + + var err error + + // ------------- Path parameter "organization" ------------- + var organization OrganizationParameter + + err = runtime.BindStyledParameterWithLocation("simple", false, "organization", runtime.ParamLocationPath, chi.URLParam(r, "organization"), &organization) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "organization", Err: err}) + return + } + + ctx = context.WithValue(ctx, Oauth2AuthenticationScopes, []string{""}) + + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + siw.Handler.GetApiV1OrganizationsOrganizationAcl(w, r, organization) + }) + + for _, middleware := range siw.HandlerMiddlewares { + handler = middleware(handler) + } + + handler.ServeHTTP(w, r.WithContext(ctx)) +} + // GetApiV1OrganizationsOrganizationGroups operation middleware func (siw *ServerInterfaceWrapper) GetApiV1OrganizationsOrganizationGroups(w http.ResponseWriter, r *http.Request) { ctx := r.Context() @@ -562,6 +593,9 @@ func HandlerWithOptions(si ServerInterface, options ChiServerOptions) http.Handl r.Group(func(r chi.Router) { r.Put(options.BaseURL+"/api/v1/organizations/{organization}", wrapper.PutApiV1OrganizationsOrganization) }) + r.Group(func(r chi.Router) { + r.Get(options.BaseURL+"/api/v1/organizations/{organization}/acl", wrapper.GetApiV1OrganizationsOrganizationAcl) + }) r.Group(func(r chi.Router) { r.Get(options.BaseURL+"/api/v1/organizations/{organization}/groups", wrapper.GetApiV1OrganizationsOrganizationGroups) }) diff --git a/pkg/generated/schema.go b/pkg/generated/schema.go index b9a48d09..215c6a1e 100644 --- a/pkg/generated/schema.go +++ b/pkg/generated/schema.go @@ -18,138 +18,143 @@ import ( // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/pkg/generated/types.go b/pkg/generated/types.go index a5ab8cc7..28e94895 100644 --- a/pkg/generated/types.go +++ b/pkg/generated/types.go @@ -91,6 +91,30 @@ const ( ES512 SigningAlgorithm = "ES512" ) +// Acl A list of access control scopes and permissions. +type Acl struct { + // IsSuperAdmin Indicates the user can do all the things. + IsSuperAdmin *bool `json:"isSuperAdmin,omitempty"` + + // Scopes A list of access control scopes. + Scopes *AclScopes `json:"scopes,omitempty"` +} + +// AclPermissions A list of access control permissions. +type AclPermissions = []string + +// AclScope An access control scope. +type AclScope struct { + // Name The scope name + Name string `json:"name"` + + // Permissions A list of access control permissions. + Permissions AclPermissions `json:"permissions"` +} + +// AclScopes A list of access control scopes. +type AclScopes = []AclScope + // AuthMethod Supported authentication methods. type AuthMethod string @@ -302,6 +326,9 @@ type GroupidParameter = string // OrganizationParameter defines model for organizationParameter. type OrganizationParameter = string +// AclResponse A list of access control scopes and permissions. +type AclResponse = Acl + // BadRequestResponse Generic error message. type BadRequestResponse = Oauth2Error diff --git a/pkg/handler/authorization.go b/pkg/handler/authorization.go new file mode 100644 index 00000000..ae01d98d --- /dev/null +++ b/pkg/handler/authorization.go @@ -0,0 +1,48 @@ +/* +Copyright 2024 the Unikorn Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package handler + +import ( + "context" + + coreRBAC "github.com/unikorn-cloud/core/pkg/authorization/rbac" + "github.com/unikorn-cloud/core/pkg/authorization/userinfo" + "github.com/unikorn-cloud/identity/pkg/rbac" + + "sigs.k8s.io/controller-runtime/pkg/client" +) + +// aclGetter gets an ACL from resourced owned by the identity service. +type aclGetter struct { + client client.Client + namespace string + organization string +} + +func newACLGetter(client client.Client, namespace, organization string) *aclGetter { + return &aclGetter{ + client: client, + namespace: namespace, + organization: organization, + } +} + +func (a *aclGetter) Get(ctx context.Context) (*coreRBAC.ACL, error) { + userinfo := userinfo.FromContext(ctx) + + return rbac.New(a.client, a.namespace).GetACL(ctx, userinfo.RBAC, a.organization) +} diff --git a/pkg/handler/groups/client.go b/pkg/handler/groups/client.go index 917fe1c1..e6a00d27 100644 --- a/pkg/handler/groups/client.go +++ b/pkg/handler/groups/client.go @@ -23,7 +23,6 @@ import ( "github.com/google/uuid" - "github.com/unikorn-cloud/core/pkg/authorization/roles" "github.com/unikorn-cloud/core/pkg/server/errors" unikornv1 "github.com/unikorn-cloud/identity/pkg/apis/unikorn/v1alpha1" "github.com/unikorn-cloud/identity/pkg/generated" @@ -43,21 +42,11 @@ func New(client client.Client, namespace string) *Client { } } -func convertRoleList(in []roles.Role) generated.RoleList { - out := make([]string, len(in)) - - for i, role := range in { - out[i] = string(role) - } - - return out -} - func convert(in *unikornv1.OrganizationGroup) *generated.Group { out := &generated.Group{ Id: in.ID, Name: in.Name, - Roles: convertRoleList(in.Roles), + Roles: in.Roles, } if len(in.Users) > 0 { @@ -109,21 +98,11 @@ func (c *Client) Get(ctx context.Context, organizationName, groupID string) (*ge return convert(&organization.Spec.Groups[index]), nil } -func generateRoleList(in generated.RoleList) []roles.Role { - out := make([]roles.Role, len(in)) - - for i, role := range in { - out[i] = roles.Role(role) - } - - return out -} - func generate(in *generated.Group) unikornv1.OrganizationGroup { out := unikornv1.OrganizationGroup{ ID: uuid.New().String(), Name: in.Name, - Roles: generateRoleList(in.Roles), + Roles: in.Roles, } if in.Users != nil { diff --git a/pkg/handler/handler.go b/pkg/handler/handler.go index 2e5ed4c4..30391051 100644 --- a/pkg/handler/handler.go +++ b/pkg/handler/handler.go @@ -23,7 +23,7 @@ import ( "fmt" "net/http" - "github.com/unikorn-cloud/core/pkg/authorization/roles" + "github.com/unikorn-cloud/core/pkg/authorization/constants" "github.com/unikorn-cloud/core/pkg/authorization/userinfo" "github.com/unikorn-cloud/core/pkg/server/errors" "github.com/unikorn-cloud/identity/pkg/authorization" @@ -50,26 +50,13 @@ type Handler struct { options *Options } -func checkRBACUnscoped(ctx context.Context, scope string, permission roles.Permission) error { - authorizer, err := userinfo.NewUnscopedAuthorizer(ctx) +func (h *Handler) checkRBAC(ctx context.Context, organization, scope string, permission constants.Permission) error { + authorizer, err := userinfo.NewAuthorizer(ctx, newACLGetter(h.client, h.namespace, organization)) if err != nil { return errors.HTTPForbidden("operation is not allowed by rbac").WithError(err) } - if err := authorizer.Allow(scope, permission); err != nil { - return errors.HTTPForbidden("operation is not allowed by rbac").WithError(err) - } - - return nil -} - -func checkRBAC(ctx context.Context, organization, scope string, permission roles.Permission) error { - authorizer, err := userinfo.NewScopedAuthorizer(ctx, organization) - if err != nil { - return errors.HTTPForbidden("operation is not allowed by rbac").WithError(err) - } - - if err := authorizer.Allow(scope, permission); err != nil { + if err := authorizer.Allow(ctx, scope, permission); err != nil { return errors.HTTPForbidden("operation is not allowed by rbac").WithError(err) } @@ -183,13 +170,25 @@ func (h *Handler) GetOidcCallback(w http.ResponseWriter, r *http.Request) { h.authenticator.OAuth2.OIDCCallback(w, r) } +func (h *Handler) GetApiV1OrganizationsOrganizationAcl(w http.ResponseWriter, r *http.Request, organization generated.OrganizationParameter) { + result, err := newACLGetter(h.client, h.namespace, organization).Get(r.Context()) + if err != nil { + errors.HandleError(w, r, errors.HTTPForbidden("operation is not allowed by rbac").WithError(err)) + return + } + + h.setUncacheable(w) + util.WriteJSONResponse(w, r, http.StatusOK, result) +} + func (h *Handler) GetApiV1OrganizationsOrganizationOauth2Providers(w http.ResponseWriter, r *http.Request, organization generated.OrganizationParameter) { - if err := checkRBAC(r.Context(), organization, "oauth2providers:public", roles.Read); err != nil { + // TODO: separate into different scopes as per unikornv1 + if err := h.checkRBAC(r.Context(), organization, "oauth2providers-public", constants.Read); err != nil { errors.HandleError(w, r, err) return } - if err := checkRBAC(r.Context(), organization, "oauth2providers:private", roles.Read); err != nil { + if err := h.checkRBAC(r.Context(), organization, "oauth2providers-private", constants.Read); err != nil { errors.HandleError(w, r, err) return } @@ -205,7 +204,7 @@ func (h *Handler) GetApiV1OrganizationsOrganizationOauth2Providers(w http.Respon } func (h *Handler) GetApiV1Organizations(w http.ResponseWriter, r *http.Request) { - if err := checkRBACUnscoped(r.Context(), "organizations", roles.Read); err != nil { + if err := h.checkRBAC(r.Context(), "", "organizations", constants.Read); err != nil { errors.HandleError(w, r, err) return } @@ -221,21 +220,21 @@ func (h *Handler) GetApiV1Organizations(w http.ResponseWriter, r *http.Request) } func (h *Handler) PostApiV1Organizations(w http.ResponseWriter, r *http.Request) { - if err := checkRBACUnscoped(r.Context(), "organizations", roles.Create); err != nil { + if err := h.checkRBAC(r.Context(), "", "organizations", constants.Create); err != nil { errors.HandleError(w, r, err) return } } func (h *Handler) PutApiV1OrganizationsOrganization(w http.ResponseWriter, r *http.Request, organization generated.OrganizationParameter) { - if err := checkRBACUnscoped(r.Context(), "organizations", roles.Update); err != nil { + if err := h.checkRBAC(r.Context(), "", "organizations", constants.Update); err != nil { errors.HandleError(w, r, err) return } } func (h *Handler) GetApiV1OrganizationsOrganizationGroups(w http.ResponseWriter, r *http.Request, organization generated.OrganizationParameter) { - if err := checkRBAC(r.Context(), organization, "groups", roles.Read); err != nil { + if err := h.checkRBAC(r.Context(), organization, "groups", constants.Read); err != nil { errors.HandleError(w, r, err) return } @@ -251,7 +250,7 @@ func (h *Handler) GetApiV1OrganizationsOrganizationGroups(w http.ResponseWriter, } func (h *Handler) PostApiV1OrganizationsOrganizationGroups(w http.ResponseWriter, r *http.Request, organization generated.OrganizationParameter) { - if err := checkRBAC(r.Context(), organization, "groups", roles.Create); err != nil { + if err := h.checkRBAC(r.Context(), organization, "groups", constants.Create); err != nil { errors.HandleError(w, r, err) return } @@ -273,7 +272,7 @@ func (h *Handler) PostApiV1OrganizationsOrganizationGroups(w http.ResponseWriter } func (h *Handler) GetApiV1OrganizationsOrganizationGroupsGroupid(w http.ResponseWriter, r *http.Request, organization generated.OrganizationParameter, groupid generated.GroupidParameter) { - if err := checkRBAC(r.Context(), organization, "groups", roles.Delete); err != nil { + if err := h.checkRBAC(r.Context(), organization, "groups", constants.Delete); err != nil { errors.HandleError(w, r, err) return } @@ -289,7 +288,7 @@ func (h *Handler) GetApiV1OrganizationsOrganizationGroupsGroupid(w http.Response } func (h *Handler) DeleteApiV1OrganizationsOrganizationGroupsGroupid(w http.ResponseWriter, r *http.Request, organization generated.OrganizationParameter, groupid generated.GroupidParameter) { - if err := checkRBAC(r.Context(), organization, "groups", roles.Delete); err != nil { + if err := h.checkRBAC(r.Context(), organization, "groups", constants.Delete); err != nil { errors.HandleError(w, r, err) return } @@ -304,7 +303,7 @@ func (h *Handler) DeleteApiV1OrganizationsOrganizationGroupsGroupid(w http.Respo } func (h *Handler) PutApiV1OrganizationsOrganizationGroupsGroupid(w http.ResponseWriter, r *http.Request, organization generated.OrganizationParameter, groupid generated.GroupidParameter) { - if err := checkRBAC(r.Context(), organization, "groups", roles.Update); err != nil { + if err := h.checkRBAC(r.Context(), organization, "groups", constants.Update); err != nil { errors.HandleError(w, r, err) return } diff --git a/pkg/rbac/rbac.go b/pkg/rbac/rbac.go index bd3108d5..4679ed70 100644 --- a/pkg/rbac/rbac.go +++ b/pkg/rbac/rbac.go @@ -21,8 +21,8 @@ import ( "slices" "strings" + "github.com/unikorn-cloud/core/pkg/authorization/constants" "github.com/unikorn-cloud/core/pkg/authorization/rbac" - "github.com/unikorn-cloud/core/pkg/authorization/roles" unikornv1 "github.com/unikorn-cloud/identity/pkg/apis/unikorn/v1alpha1" "sigs.k8s.io/controller-runtime/pkg/client" @@ -42,8 +42,8 @@ func New(client client.Client, namespace string) *RBAC { } } -// GetOrganizatons grabs all organizations for the system. -func (r *RBAC) GetOrganizatons(ctx context.Context) (*unikornv1.OrganizationList, error) { +// getOrganizatons grabs all organizations for the system. +func (r *RBAC) getOrganizatons(ctx context.Context) (*unikornv1.OrganizationList, error) { var organizations unikornv1.OrganizationList if err := r.client.List(ctx, &organizations, &client.ListOptions{Namespace: r.namespace}); err != nil { @@ -58,7 +58,7 @@ func (r *RBAC) GetOrganizatons(ctx context.Context) (*unikornv1.OrganizationList func (r *RBAC) UserPermissions(ctx context.Context, email string) (*rbac.Permissions, error) { permissions := &rbac.Permissions{} - organizations, err := r.GetOrganizatons(ctx) + organizations, err := r.getOrganizatons(ctx) if err != nil { return nil, err } @@ -73,13 +73,13 @@ func (r *RBAC) UserPermissions(ctx context.Context, email string) (*rbac.Permiss } // Hoist super admin powers. - if slices.Contains(group.Roles, roles.SuperAdmin) { + if slices.Contains(group.Roles, constants.SuperAdmin) { permissions.IsSuperAdmin = true } // Remove any special roles. - minifiedRoles := slices.DeleteFunc(group.Roles, func(role roles.Role) bool { - return role == roles.SuperAdmin + minifiedRoles := slices.DeleteFunc(group.Roles, func(role string) bool { + return role == constants.SuperAdmin }) if len(minifiedRoles) == 0 { @@ -113,7 +113,7 @@ func (r *RBAC) UserExists(ctx context.Context, email string) (bool, error) { domain := parts[1] - organizations, err := r.GetOrganizatons(ctx) + organizations, err := r.getOrganizatons(ctx) if err != nil { return false, err } @@ -132,3 +132,68 @@ func (r *RBAC) UserExists(ctx context.Context, email string) (bool, error) { return false, nil } + +// GetACL returns a granualr set of permissions for a user based on their scope. +// This is used for API leval access control and UX. +func (r *RBAC) GetACL(ctx context.Context, permissions *rbac.Permissions, organization string) (*rbac.ACL, error) { + // Super user gets everything, so shortcut. + if permissions.IsSuperAdmin { + acl := &rbac.ACL{ + IsSuperAdmin: true, + } + + return acl, nil + } + + // If this is scoped to an organization, do the lookup and deny entry if the user + // is not part of the organization. + var organizationPermissions *rbac.OrganizationPermissions + + if organization != "" { + temp, err := permissions.LookupOrganization(organization) + if err != nil { + return nil, err + } + + organizationPermissions = temp + } + + var roles unikornv1.RoleList + + if err := r.client.List(ctx, &roles, &client.ListOptions{Namespace: r.namespace}); err != nil { + return nil, err + } + + acl := &rbac.ACL{} + + for _, role := range roles.Items { + // If it's not a default role that everyone gets, or the user doesn't have + // access to it, ignore. + if !role.Spec.IsDefault && !organizationPermissions.HasRole(role.Name) { + continue + } + + for _, scope := range role.Spec.Scopes { + // Lookup the scope, it may be defined by a different role already, + // if it doesn't exist, create it and add to the ACL. + aclScope := acl.GetScope(scope.Name) + + if aclScope == nil { + aclScope = &rbac.Scope{ + Name: scope.Name, + } + + acl.Scopes = append(acl.Scopes, aclScope) + } + + // Do a boolean union of existing permissions and any new ones. + permissions := slices.Concat(aclScope.Permissions, scope.Permissions) + + slices.Sort(permissions) + + aclScope.Permissions = slices.Compact(permissions) + } + } + + return acl, nil +} diff --git a/pkg/server/server.go b/pkg/server/server.go index 9161f32f..89c51513 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -26,6 +26,7 @@ import ( "github.com/spf13/pflag" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" + "go.opentelemetry.io/otel/propagation" "go.opentelemetry.io/otel/sdk/trace" "github.com/unikorn-cloud/core/pkg/server/middleware/cors" @@ -86,6 +87,8 @@ func (s *Server) SetupLogging() { func (s *Server) SetupOpenTelemetry(ctx context.Context) error { otel.SetLogger(log.Log) + otel.SetTextMapPropagator(propagation.TraceContext{}) + opts := []trace.TracerProviderOption{ trace.WithSpanProcessor(&opentelemetry.LoggingSpanProcessor{}), }