Skip to content

Commit

Permalink
Add Core RBAC Primatives
Browse files Browse the repository at this point in the history
  • Loading branch information
spjmurray committed Mar 22, 2024
1 parent 99c131a commit 22cc3b8
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 15 deletions.
4 changes: 2 additions & 2 deletions charts/core/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: A Helm chart for deploying Unikorn Core

type: application

version: v0.1.12
appVersion: v0.1.12
version: v0.1.13
appVersion: v0.1.13

icon: https://assets.unikorn-cloud.org/images/logos/dark-on-light/icon.svg
47 changes: 47 additions & 0 deletions pkg/authorization/rbac/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
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 rbac

import (
"github.com/unikorn-cloud/core/pkg/authorization/roles"
)

// GroupPermissions are privilege grants for a project.
type GroupPermissions struct {
// ID is the unique, immutable project identifier.
ID string `json:"id"`
// Roles are the privileges a user has for the group.
Roles []roles.Role `json:"roles"`
}

// OrganizationPermissions are privilege grants for an organization.
type OrganizationPermissions struct {
// IsAdmin allows the user to play with all resources in an organization.
IsAdmin bool `json:"isAdmin,omitempty"`
// Name is the name of the organization.
Name string `json:"name"`
// Groups are any groups the user belongs to in an organization.
Groups []GroupPermissions `json:"groups,omitempty"`
}

// Permissions are privilege grants for the entire system.
type Permissions struct {
// IsSuperAdmin HAS SUPER COW POWERS!!!
IsSuperAdmin bool `json:"isSuperAdmin,omitempty"`
// Organizations are any organizations the user has access to.
Organizations []OrganizationPermissions `json:"organizations,omitempty"`
}
8 changes: 3 additions & 5 deletions pkg/authorization/userinfo/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,18 @@ package userinfo

import (
"context"

"github.com/coreos/go-oidc/v3/oidc"
)

type keyType int

//nolint:gochecknoglobals
var key keyType

func NewContext(ctx context.Context, userinfo *oidc.UserInfo) context.Context {
func NewContext(ctx context.Context, userinfo *UserInfo) context.Context {
return context.WithValue(ctx, key, userinfo)
}

func FromContext(ctx context.Context) *oidc.UserInfo {
func FromContext(ctx context.Context) *UserInfo {
//nolint:forcetypeassert
return ctx.Value(key).(*oidc.UserInfo)
return ctx.Value(key).(*UserInfo)
}
28 changes: 28 additions & 0 deletions pkg/authorization/userinfo/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
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 userinfo

import (
"github.com/go-jose/go-jose/v3/jwt"

"github.com/unikorn-cloud/core/pkg/authorization/rbac"
)

type UserInfo struct {
jwt.Claims
RBAC *rbac.Permissions `json:"rbac,omitempty"`
}
5 changes: 3 additions & 2 deletions pkg/server/middleware/openapi/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@ limitations under the License.
package openapi

import (
"github.com/coreos/go-oidc/v3/oidc"
"github.com/getkin/kin-openapi/openapi3filter"

"github.com/unikorn-cloud/core/pkg/authorization/userinfo"
)

// Authorizer allows authorizers to be plugged in interchangeably.
type Authorizer interface {
// Authorize checks the request against the OpenAPI security scheme
// and returns the access token.
Authorize(authentication *openapi3filter.AuthenticationInput) (string, *oidc.UserInfo, error)
Authorize(authentication *openapi3filter.AuthenticationInput) (string, *userinfo.UserInfo, error)
}
15 changes: 11 additions & 4 deletions pkg/server/middleware/openapi/oidc/authorizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/spf13/pflag"
"golang.org/x/oauth2"

"github.com/unikorn-cloud/core/pkg/authorization/userinfo"
"github.com/unikorn-cloud/core/pkg/server/errors"
)

Expand Down Expand Up @@ -74,7 +75,7 @@ func getHTTPAuthenticationScheme(r *http.Request) (string, string, error) {
}

// authorizeOAuth2 checks APIs that require and oauth2 bearer token.
func (a *Authorizer) authorizeOAuth2(r *http.Request) (string, *oidc.UserInfo, error) {
func (a *Authorizer) authorizeOAuth2(r *http.Request) (string, *userinfo.UserInfo, error) {
authorizationScheme, rawToken, err := getHTTPAuthenticationScheme(r)
if err != nil {
return "", nil, err
Expand Down Expand Up @@ -118,16 +119,22 @@ func (a *Authorizer) authorizeOAuth2(r *http.Request) (string, *oidc.UserInfo, e
TokenType: authorizationScheme,
}

userinfo, err := provider.UserInfo(ctx, oauth2.StaticTokenSource(token))
ui, err := provider.UserInfo(ctx, oauth2.StaticTokenSource(token))
if err != nil {
return "", nil, err
}

return rawToken, userinfo, nil
uiInternal := &userinfo.UserInfo{}

if err := ui.Claims(ui); err != nil {
return "", nil, errors.OAuth2ServerError("failed to extrac user information").WithError(err)
}

return rawToken, uiInternal, nil
}

// Authorize checks the request against the OpenAPI security scheme.
func (a *Authorizer) Authorize(authentication *openapi3filter.AuthenticationInput) (string, *oidc.UserInfo, error) {
func (a *Authorizer) Authorize(authentication *openapi3filter.AuthenticationInput) (string, *userinfo.UserInfo, error) {
if authentication.SecurityScheme.Type == "oauth2" {
return a.authorizeOAuth2(authentication.RequestValidationInput.Request)
}
Expand Down
3 changes: 1 addition & 2 deletions pkg/server/middleware/openapi/openapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (
"io"
"net/http"

"github.com/coreos/go-oidc/v3/oidc"
"github.com/getkin/kin-openapi/openapi3filter"

"github.com/unikorn-cloud/core/pkg/authorization/accesstoken"
Expand All @@ -50,7 +49,7 @@ type Validator struct {
accessToken string

// userinfo is used for identity and RBAC.
userinfo *oidc.UserInfo
userinfo *userinfo.UserInfo

// err is used to indicate the actual openapi error.
err error
Expand Down

0 comments on commit 22cc3b8

Please sign in to comment.