Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scope updates #69

Merged
merged 4 commits into from
Jun 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions pkg/handler/auth/endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,32 +41,30 @@ var (
func (service *auth) AddEndpoints(ctx context.Context, r server.Router) {
// Path: /
// Methods: GET
// Scopes: read // TODO: Add scopes
// Scopes: read
// Description: Get current set of tokens and groups
r.AddHandlerFuncRe(ctx, reRoot, service.ListTokens, http.MethodGet).(router.Route).
SetScope(service.ScopeRead()...)

// Path: /
// Methods: POST
// Scopes: write // TODO: Add scopes
// Scopes: write
// Description: Create a new token
r.AddHandlerFuncRe(ctx, reRoot, service.CreateToken, http.MethodPost).(router.Route).
SetScope(service.ScopeRead()...).
SetScope(service.ScopeWrite()...)

// Path: /<token-name>
// Methods: GET
// Scopes: read // TODO: Add scopes
// Scopes: read
// Description: Get a token
r.AddHandlerFuncRe(ctx, reToken, service.GetToken, http.MethodGet).(router.Route).
SetScope(service.ScopeRead()...)

// Path: /<token-name>
// Methods: DELETE, PATCH
// Scopes: write // TODO: Add scopes
// Scopes: write
// Description: Delete or update a token
r.AddHandlerFuncRe(ctx, reToken, service.UpdateToken, http.MethodDelete, http.MethodPatch).(router.Route).
SetScope(service.ScopeRead()...).
SetScope(service.ScopeWrite()...)

}
Expand Down
4 changes: 3 additions & 1 deletion pkg/handler/auth/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,20 +50,22 @@ func (middleware *auth) Wrap(ctx context.Context, next http.HandlerFunc) http.Ha
authorized := true
if token.IsZero() {
authorized = false
httpresponse.Error(w, http.StatusUnauthorized, "invalid or missing token")
} else if !token.IsValid() {
authorized = false
httpresponse.Error(w, http.StatusUnauthorized, "invalid or missing token")
} else if token.IsScope(ScopeRoot) {
// Allow - token is a super-user token
} else if allowedScopes := router.Scope(r.Context()); len(allowedScopes) == 0 {
// Allow - no scopes have been defined on this endpoint
} else if !token.IsScope(allowedScopes...) {
// Deny - token does not have the required scopes
authorized = false
httpresponse.Error(w, http.StatusUnauthorized, "required scope: ", strings.Join(allowedScopes, ","))
}

// Return unauthorized if token is not found or not valid
if !authorized {
httpresponse.Error(w, http.StatusUnauthorized)
return
}

Expand Down
10 changes: 5 additions & 5 deletions pkg/handler/auth/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ import (
// TYPES

type Token struct {
Name string `json:"name,omitempty"` // Name of the token
Value string `json:"token,omitempty"` // Token value
Expire time.Time `json:"expire_time,omitempty"` // Time of expiration for the token
Time time.Time `json:"access_time"` // Time of last access
Scope []string `json:"scopes,omitempty"` // Authentication scopes
Name string `json:"name,omitempty"` // Name of the token
Value string `json:"token,omitempty"` // Token value
Expire time.Time `json:"expire_time,omitempty" writer:",width:29"` // Time of expiration for the token
Time time.Time `json:"access_time,omitempty" writer:",width:29"` // Time of last access
Scope []string `json:"scopes,omitempty" writer:",wrap"` // Authentication scopes
}

type TokenCreate struct {
Expand Down
32 changes: 19 additions & 13 deletions pkg/handler/nginx/endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,42 +50,48 @@ var (
// PUBLIC METHODS - ENDPOINTS

// Add endpoints to the router
func (service *nginx) AddEndpoints(ctx context.Context, router server.Router) {
func (service *nginx) AddEndpoints(ctx context.Context, r server.Router) {
// Path: /
// Methods: GET
// Scopes: read // TODO: Add scopes
// Scopes: read
// Description: Get nginx status (version, uptime, available and enabled configurations)
router.AddHandlerFuncRe(ctx, reRoot, service.GetHealth, http.MethodGet)
r.AddHandlerFuncRe(ctx, reRoot, service.GetHealth, http.MethodGet).(router.Route).
SetScope(service.ScopeRead()...)

// Path: /(test|reload|reopen)
// Methods: PUT
// Scopes: write // TODO: Add scopes
// Scopes: write
// Description: Test, reload and reopen nginx configuration
router.AddHandlerFuncRe(ctx, reAction, service.PutAction, http.MethodPut)
r.AddHandlerFuncRe(ctx, reAction, service.PutAction, http.MethodPut).(router.Route).
SetScope(service.ScopeWrite()...)

// Path: /config
// Methods: GET
// Scopes: read // TODO: Add scopes
// Scopes: read
// Description: Read the current set of configurations
router.AddHandlerFuncRe(ctx, reListConfig, service.ListConfig, http.MethodGet)
r.AddHandlerFuncRe(ctx, reListConfig, service.ListConfig, http.MethodGet).(router.Route).
SetScope(service.ScopeRead()...)

// Path: /config
// Methods: POST
// Scopes: read // TODO: Add scopes
// Scopes: write
// Description: Create a new configuration
router.AddHandlerFuncRe(ctx, reListConfig, service.CreateConfig, http.MethodPost)
r.AddHandlerFuncRe(ctx, reListConfig, service.CreateConfig, http.MethodPost).(router.Route).
SetScope(service.ScopeWrite()...)

// Path: /config/{id}
// Methods: GET
// Scopes: read // TODO: Add scopes
// Scopes: read
// Description: Read a configuration
router.AddHandlerFuncRe(ctx, reConfig, service.ReadConfig, http.MethodGet)
r.AddHandlerFuncRe(ctx, reConfig, service.ReadConfig, http.MethodGet).(router.Route).
SetScope(service.ScopeRead()...)

// Path: /config/{id}
// Methods: DELETE, POST, PATCH
// Scopes: write // TODO: Add scopes
// Scopes: write
// Description: Modify a configuration
router.AddHandlerFuncRe(ctx, reConfig, service.WriteConfig, http.MethodDelete, http.MethodPatch)
r.AddHandlerFuncRe(ctx, reConfig, service.WriteConfig, http.MethodDelete, http.MethodPatch).(router.Route).
SetScope(service.ScopeWrite()...)
}

///////////////////////////////////////////////////////////////////////////////
Expand Down
33 changes: 33 additions & 0 deletions pkg/handler/nginx/scope.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package nginx

import (
// Packages
"github.com/mutablelogic/go-server/pkg/version"
)

////////////////////////////////////////////////////////////////////////////////
// GLOBALS

var (
// Prefix
scopePrefix = version.GitSource + "/scope/"
)

////////////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS

func (nginx *nginx) ScopeRead() []string {
// Return read (list, get) scopes
return []string{
scopePrefix + nginx.Label() + "/read",
scopePrefix + defaultName + "/read",
}
}

func (nginx *nginx) ScopeWrite() []string {
// Return write (create, delete, update) scopes
return []string{
scopePrefix + nginx.Label() + "/write",
scopePrefix + defaultName + "/write",
}
}
43 changes: 43 additions & 0 deletions pkg/handler/router/endpoints.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package router

import (
"context"
"net/http"
"regexp"

// Packages
server "github.com/mutablelogic/go-server"
httpresponse "github.com/mutablelogic/go-server/pkg/httpresponse"
)

///////////////////////////////////////////////////////////////////////////////
// GLOBALS

const (
jsonIndent = 2
)

var (
reRoot = regexp.MustCompile(`^/?$`)
)

///////////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS - ENDPOINTS

// Add endpoints to the router
func (service *router) AddEndpoints(ctx context.Context, r server.Router) {
// Path: /
// Methods: GET
// Scopes: read
// Description: Get router services
r.AddHandlerFuncRe(ctx, reRoot, service.GetScopes, http.MethodGet).(Route).
SetScope(service.ScopeRead()...)
}

///////////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS

// Get registered scopes
func (service *router) GetScopes(w http.ResponseWriter, r *http.Request) {
httpresponse.JSON(w, service.Scopes(), http.StatusOK, jsonIndent)
}
3 changes: 3 additions & 0 deletions pkg/handler/router/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ type Router interface {
// http status code, which will be 200 on success, 404 or 405 and
// path parameters extracted from the path.
Match(host, method, path string) (*matchedRoute, int)

// Return all known scopes
Scopes() []string
}

type Route interface {
Expand Down
25 changes: 25 additions & 0 deletions pkg/handler/router/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,31 @@ func (router *router) Match(host, method, path string) (*matchedRoute, int) {
return nil, http.StatusMethodNotAllowed
}

func (router *router) Scopes() []string {
scopes := make(map[string]bool)
for _, r := range router.host {
for _, h := range r.prefix {
for _, r := range h.handlers {
for _, s := range r.scopes {
scopes[s] = true
}
}
}
}

// Gather all scopes
result := make([]string, 0, len(scopes))
for scope := range scopes {
result = append(result, scope)
}

// Sort alphabetically
sort.Strings(result)

// Return the result
return result
}

///////////////////////////////////////////////////////////////////////////////
// PRIVATE METHODS

Expand Down
33 changes: 33 additions & 0 deletions pkg/handler/router/scope.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package router

import (
// Packages
"github.com/mutablelogic/go-server/pkg/version"
)

////////////////////////////////////////////////////////////////////////////////
// GLOBALS

var (
// Prefix
scopePrefix = version.GitSource + "/scope/"
)

////////////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS

func (router *router) ScopeRead() []string {
// Return read (list, get) scopes
return []string{
scopePrefix + router.Label() + "/read",
scopePrefix + defaultName + "/read",
}
}

func (router *router) ScopeWrite() []string {
// Return write (create, delete, update) scopes
return []string{
scopePrefix + router.Label() + "/write",
scopePrefix + defaultName + "/write",
}
}
Loading