SoarPolicyAccessManager

This Access Manager adheres to SoarAm::AmApi. It is initialized with a soar_sr service registy client (https://rubygems.org/gems/soar_sr)

This access manager denies access for unauthenticated requests, that is, request that do not have request.session['user'] set. If set, this access manager then queries the service registry for meta regarding the service identifier in question.

If the service meta indicates no policy, the request is allowed. It the service meta indicates a policy, the policy service is asked, given the authenticated subject identifier, service identifier, resource identifier and request parameters, whether the request should be allowed. This access manager then allows / denies accordingly.

In the case of the service not found in the service registry, or a failure of any kind, the request is denied. In the interest of security, exceptions while authorizing will be swallowed by this access manager. Only the last exception message will be reported to STDERR.

Quickstart

When using soar_sc the soar_authorization gem automagically passes values set in your router as post parameters in authorization requests to policies.

SoarSc Routing params SoarAuthorization params AccessManager Params Policy Params
service_name service_identifier requestor_identifier
path resource_identifier resource_identifier
authentication.identifier authentication_identifier subject_identifier

Stub provider

Use this provider during tests and development when you don't want any http policy authorization requests.

Create meta variable mapping services to policy identifiers (names)

> meta = {
    'service_identifier1' => {
        'policy' => 'policy1'
    }
}

Create policies variable mapping policy identifiers to resources. Access to a resource is allowed if your authentication identifier (uuid) is present in the array.

> policies = {
    'policy1' => {
        '/resource_identifier1' => ['authentication_identifier1'],
        '/resource_identifier2' => []
    }
}

Instantiate the stub provider and pass it to the access manager model.

> provider = Soar::Policy::AccessManager::ModelProvider::Stub.new(meta: meta, policies: policies})
> policy_am = Soar::Policy::AccessManager::Model.new(provider)
> puts policy_am.authorized?({
    service_identifier: 'service_identifier1', 
    resource_identifier: '/resource_identifier1', 
    request: {
      params: {},
      authentication_identifier: 'authentication_identifier1'
    }
})

Policy provider

Use this provider during tests and development to send authorization requests directly to a policy.

Create meta variable mapping services to policy identifiers (names)

> meta = {
    'service_identifier1' => 'policy1',
    'service_identifier2' => 'policy2'
}

Create policies variable mapping policy identifiers to policy endpoints.

> policies = {
    'policy1' => 'http://localhost:8080/allow',
    'policy2' => 'http://localhost:8080/deny'
}

Instantiate the stub provider and pass it to the access manager model.

> provider = Soar::Policy::AccessManager::ModelProvider::Policy.new(meta: meta, policies: policies})
> policy_am = Soar::Policy::AccessManager::Model.new(provider)
> puts policy_am.authorized?({
    service_identifier: 'service_identifier1', 
    resource_identifier: '', 
    request: {
      params: {},
      authentication_identifier: ''
    }
})

Service registry provider

Use this provider during production. It reaches out to the service registry and policies. It's used by soar sc.

> service_registry = SoarSc::service_registry
> provider = Soar::Policy::AccessManager::ModelProvider::ServiceRegistry.new(service_registry)
> policy_am = Soar::Policy::AccessManager::Model.new(provider)
> puts policy_am.authorized?({
    service_identifier: 'service_identifier1',
    resource_identifier: '/path', 
    request: {
      params: request.params,
      authentication_identifier: SoarAuthentication::Authentication.new(request).identifier
    }
})

This access manager can be used with the SoarAuthorization::Authorize middleware:

> SoarAuthorization::Authorize::register_access_manager('/path', 'path-service', policy_am)
> use SoarAuthorization::Authorize

Tests

Local

Unit Tests

$ bundle exec rspec

Provider Integration Tests

Stub provider
$ TEST_ORCHESTRATION_PROVIDER=Stub bundle exec cucumber
Service Registry provider

Serve two policies, allow all and deny all, locally via file config.ru using Rack webserver.

$ docker-compose up

Test providers for the stub and service registry via the model api interface

$ TEST_ORCHESTRATION_PROVIDER=ServiceRegistry bundle exec cucumber
Policy provider

Serve two policies, allow all and deny all, locally via file config.ru using Rack webserver.

$ docker-compose up

Test providers for the stub and service registry via the model api interface

$ TEST_ORCHESTRATION_PROVIDER=Policy bundle exec cucumber

CI

$ USER_NAME=$USER USER_ID=$(id -u) POLICY_HOST=policy:8080 TEST_ORCHESTRATION_PROVIDER=ServiceRegistry docker-compose --file docker-compose.test.yml up --abort-on-container-exit --remove-orphans 
EXIT_CODE=$(docker ps -a -f "name=soar-policy-access_manager-tests" -q | xargs docker inspect -f "{{ .State.ExitCode }}")
exit $EXIT_CODE

Enviroment Variables explained

Sets USER_NAME and USER_ID to your currently logged in user. This is important when you're mounting volumes into a container. Root in the container = root on your local.

USER_NAME=$USER
USER_ID=$(id -u)

Select whether you're testing the ServiceRegistry , Policy or Stub provider. Defaults to Stub

TEST_ORCHESTRATION_PROVIDER=Stub

Contributing

Please send feedback and comments to the author at:

Ernst van Graan [email protected]

This gem is sponsored by Hetzner (Pty) Ltd - http://hetzner.co.za

License

The gem is available as open source under the terms of the MIT License.

Resources