acl

package
v1.2.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 10, 2021 License: Apache-2.0 Imports: 15 Imported by: 2

README

ACL Middleware

This middleware provides access control lists based authorization for the microservices.

Current implementation is based on Ladon.

Configure the ACL Middleware

The middleware requires ladon.Manager instance so it can load the needed policies.

Once you have a ladon.Manager configured, you can create and add the ACL middleware to the security chain:


aclMiddleware := acl.NewACLMiddleware(ladonManager)

securityChain.AddMiddleware(aclMiddleware)

Ladon Manager implementation

This package provides a MongoDB based implementation for ladon.Manager.

You can create new manager using NewMongoDBLadonManager. This requires connection parameters for MongoDB passed in config.DBConfig:

mongoConf := &config.DBConfig{
  DatabaseName: "my-database",
  Host: "localhost:27017",
  Username: "user",
  Password: "p@ss",
}

manager, err := acl.NewMongoDBLadonManager(&mongoConf)
if err != nil {
  panic(err)
}

The database configuration can be read from file.

A special collection with name "ACL" will be created by the manager itself during the starup. The data for ACL policies will be kept in that collection.

ACL Management API

Because the ACL data is kept usually in a separate store for each microservice, the library contains a Controller that exposes REST api for managing the ACL policies.

To use the controller you need to set up the data store and create new ACLController. In the microservice setup add:


import (
  // other imports

  "github.com/Microkubes/microservice-security/acl"
  "github.com/Microkubes/microservice-security/acl/rest"
  restApp "github.com/Microkubes/microservice-security/acl/rest/app"
)

func main(){
  // standard init here
  manager, cleanup, err := acl.NewMongoDBLadonManager(&acl.DBConfig{
    Host: "localhost:27017",
    DatabaseName: "user-profile",
    Username: "dbuser",
    Password: "dbpass",
  })
  if err != nil {
    panic(err)
  }
  defer cleanup()

  aclController, err := rest.NewAclController(service, manager)
  if err != nil {
    panic(err)
  }
  restApp.MountAclController(service, aclController)
}

ACL Management APIs

Create Policy

Creates new ACL policy.

  • Path: /acl
  • Method: POST
  • Consumes: ACLPolicy Object (JSON)
  • Returns: ACLPolicy Object (JSON)

See bellow for the structure of the ACL Policy object.

Get Policy

Retrieves an ACL policy by the policy ID.

  • Path: /acl/:policyId
  • Method: GET
  • Returns: ACLPolicy Object (JSON)

Update ACL Policy

Updates an existing ACL Policy.

  • Path: /acl/:policyId
  • Method: PUT
  • Consumes: ACLPolicy Object (JSON)
  • Returns: ACLPolicy Object (JSON)

Delete an ACL policy

Removes an ACL policy.

  • Path: /acl/:policyId
  • Method: DELETE
  • Consumes: ACLPolicy Object (JSON)
  • Returns: ACLPolicy Object (JSON)

Manage Access

This is a helper service that consumes a more semantic request object and creates an ACL policy based on it.

  • Path: /acl/access
  • Method: POST
  • Consumes: AccessPolicy Object (JSON)
  • Returns: ACLPolicy Object (JSON)

The AccessPolicy Object has the following structure:

{
  "description": "A description of the ACL policy",
  "resources": ["/path/to/specific/resource","/api/user/<.+>"],
  "users": ["user1","test-user-<.+>"],
  "organizations": ["org1","<.+>.jormungandr"],
  "allow": true,
  "scopes": ["api:read", "api:write"],
  "roles": ["user", "system"]
}

Where:

  • description is a description of the policy
  • resources is a list of resources patterns. You may user regex by placing it in angle brackets - "not-a-regex".
  • users is a list of user patterns. You may user regex by placing it in angle brackets - "not-a-regex". If no users are specified, the system will add a pattern to match all users - "<.+>".
  • organizations is a list of organizations. You may user regex by placing it in angle brackets - "not-a-regex". The list of organizations is optional.
  • allow - true or false. Whether to allow or deny the requests matching this policy.
  • scopes - list of scopes patterns. Usually the values are "api:read" or "api:write".
  • roles list of roles. You may user regex by placing it in angle brackets - "not-a-regex".

ACL Policies types

The ACL Policy Object has the following structure (example):

{
  "id": "4f8b7c93-2368-4019-8d6f-747a9e82ebee",
  "description": "Policy description. Text.",
  "subjects": ["user1","test-user-<.+>"],
  "effect": "allow",
  "resources": ["/path/to/specific/resource","/api/user/<.+>"],
  "actions":["api:read", "api:write"],
  "conditions": [{
      "name": "organizations",
      "type": "OrganizationsCondition",
      "patterns": ["<.+>.jormungandr","some-specific-org"]
    },{
      "name": "roles",
      "type": "RolesCondition",
      "patterns": ["user","admin", "system"]
    },{
      "name": "scopes",
      "type": "ScopesCondition",
      "patterns": ["api:read","api:write"]
    },{
      "name": "createdBy",
      "type": "OwnerCondition"
    }]
}

Documentation

Index

Constants

View Source
const APIReadAction = "api:read"

APIReadAction is "api:read". All HTTP methods except for POST, PUT, PATCH and DELETE are considered to be "api:read" action.

View Source
const APIWriteAction = "api:write"

APIWriteAction is "api:write". HTTP methods POST, PUT and DELETE are considered "api:write" action.

Variables

View Source
var AvailableConditions = []string{"RolesCondition", "ScopesCondition", "OrganizationsCondition"}

AvailableConditions is the list of names of the available AllowedPatternsCondition conditions. All of these are registered with ladon.

Functions

func CheckRequest

func CheckRequest(ctx context.Context, req *RequestContext) error

CheckRequest checks the request represented as RequestContext against the ACL policies. This is a helper function to do a custom ACL check with additional context data.

func IsAllowed

func IsAllowed(ctx context.Context, req *http.Request, subject string, aclContext AccessContext) error

IsAllowed is a helper function that can be used inside a controller action to perform additional checks for ACL when the default check is not enough. An example is prtotecting a resoruce to be accessed only by its owner. The resource owner is not known until the resource is fetched from the database, and the resource is not fetched util the actual action executes. In this scenario we can use IsAllowed to check once we have the resource fetched from database.

func NewACLMiddleware

func NewACLMiddleware(manager ladon.Manager) (chain.SecurityChainMiddleware, error)

NewACLMiddleware instantiates new SecurityChainMiddleware for ACL.

func NewCondition

func NewCondition(name string, patterns []string) (ladon.Condition, error)

NewCondition creates a new AllowedPatternsCondition with the given name and list of allowed patterns. This function checks if there is a condition factory registered with the requested name. If there isn't one, an error is returned - as the condition could not be deserialized when fetched from the persistence.

Types

type AccessContext

type AccessContext map[string]interface{}

AccessContext is a map string => interface used for additional ACL context data for the ACL check.

type AllowedPatternsCondition

type AllowedPatternsCondition struct {
	// Name is the name of the condition. The condition will be registerd with Ladon under this name.
	Name string

	// List of regex values for this condition. The context value is matched against all of these regex patterns to find a match.
	Values []string
}

AllowedPatternsCondition is a custom condition that matches the value of a custom ladon.Context property against a list of allowed regular expression patterns. If any of the regex patterns matches the value, the condition is fulfilled. If the value in the ACL Context (ladon.Context) is nil or not a string, the condition returns false (is NOT fulfilled).

func (*AllowedPatternsCondition) Fulfills

func (cond *AllowedPatternsCondition) Fulfills(value interface{}, r *ladon.Request) bool

Fulfills checks if the value provided as argument and the ladon.Request fullfill this Condition. The value is checked against the list of patterns in the condition. If the value mathes any of the condition patterns, the condition is fulfilled.

func (*AllowedPatternsCondition) GetName

func (cond *AllowedPatternsCondition) GetName() string

GetName returns the name of the condition. Used for condition registration and building.

type BackendLadonManager

type BackendLadonManager struct {
	// contains filtered or unexported fields
}

BackendLadonManager holds the mongo collection for storing the ladon policies in a Mongodb backend.

func NewBackendLadonManager

func NewBackendLadonManager(cfg *config.DBConfig) (*BackendLadonManager, func(), error)

NewBackendLadonManager builds a BackendLadonManager for the given database configuration.

func (*BackendLadonManager) Create

func (m *BackendLadonManager) Create(policy ladon.Policy) error

Create persists the policy.

func (*BackendLadonManager) CreateWithAuth

func (m *BackendLadonManager) CreateWithAuth(policy ladon.Policy, authObj *auth.Auth) error

CreateWithAuth persists the policy. It also sets the "createdBy" property to the provided authentication.

func (*BackendLadonManager) Delete

func (m *BackendLadonManager) Delete(id string) error

Delete removes a policy.

func (*BackendLadonManager) FindPoliciesForResource

func (m *BackendLadonManager) FindPoliciesForResource(resource string) (ladon.Policies, error)

FindPoliciesForResource retrieves all ladon.Policy candidates that can handle a request for a given resource.

func (*BackendLadonManager) FindPoliciesForSubject

func (m *BackendLadonManager) FindPoliciesForSubject(subject string) (ladon.Policies, error)

FindPoliciesForSubject retrieves all ladon.Policy candidates that can handle a request for a given subject.

func (*BackendLadonManager) FindRequestCandidates

func (m *BackendLadonManager) FindRequestCandidates(r *ladon.Request) (ladon.Policies, error)

FindRequestCandidates returns candidates that could match the request object. It either returns a set that exactly matches the request, or a superset of it. If an error occurs, it returns nil and the error.

func (*BackendLadonManager) Get

Get retrieves a policy.

func (*BackendLadonManager) GetAll

func (m *BackendLadonManager) GetAll(limit, offset int64) (ladon.Policies, error)

GetAll retrieves all policies.

func (*BackendLadonManager) Update

func (m *BackendLadonManager) Update(policy ladon.Policy) error

Update updates an existing policy.

type Configuration

type Configuration struct {
	// DBConfig is the configuration for the ACL database.
	config.DBConfig
}

Configuration is the configuration for the ACL middleware.

type OwnerCondition

type OwnerCondition struct {
}

OwnerCondition is used to implement a special kind of condition for checking the owner of a resource.

func (*OwnerCondition) Fulfills

func (o *OwnerCondition) Fulfills(value interface{}, req *ladon.Request) bool

Fulfills checks if the request context contains an owner. If so, it checks if the subject has the same value as the owner. If no owner values is set, then the request is allowed. The value of the owner is retrieved from the request context based on the name of the condition. When setting the condition in a policy, it is associated with a name, for example:

cond := &ladon.DefaultPolicy{
  conditions: ladon.Conditions{
    "createdBy": &OwnerCondition{},
  },
}

In this example, the owner value is extracted from the property "createdBy" of the request context.

func (*OwnerCondition) GetName

func (o *OwnerCondition) GetName() string

GetName returns the name of the condition - "OwnerCondition"

type RequestContext

type RequestContext struct {
	// Auth is the auth.Auth object generated by the security middlewares
	Auth *auth.Auth
	// Action is the action to be performed on the resource (api:read or api:write)
	Action string
	// Subject is a reference to who is accessing the resoruce (usually user id)
	Subject string
	// Scopes holds the values for the requested and approved scope of access of the client (api:read, api:write)
	Scopes []string
	// Resource is the accessed resource.
	Resource string

	// AccessContext contains additional data needed for ACL decision - for example it may hold the owner of the resource.
	AccessContext
}

RequestContext holds the values for the request to an API action. Holds the relevant values for the authentication and authorization.

Directories

Path Synopsis
app

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL