Darin Gordon

PyGotham 2016

Based On

Authentication

Authorization

Session Management

All Through A Common API

Why

?

Security is a High Priority for my Projects

Looking For Support for RBAC policies

  • Scalable
  • Integrates with any kind of application
  • Trusted

Friends don't let Friends Roll their Own

Evolved over more than 10 years of production use, but written in Java

Yosai began a port of Apache Shiro v2 alpha, but took on its own unique identity

Goal of This Presentation

Showcase Few of the Main Features

Use Yosai to Secure a Web Application

  • Authentication
  • Authorization

NOT a talk about web app development

(I will include the app with upcoming release)

Pluggable Security

Web Integration Requires:

  1. Yosai instance accessible throughout the app
  • Using Yosai's threadlocals api
  • Using global registry of web app

2. Yosai hooks into the request/response workflow

Details will be provided with upcoming release!

Demo Project

Goal:  A Real-world, Practical Use of Yosai

Medical Prescription Workflow

- a much more simplified version

Medical Prescription Workflow

Actors

Activities

Security Requirements (Controls)

Physicians, Nurse Practitioners, Patients

  • Writing Prescriptions
  • Requesting Prescription Renewals
  • Approving Rx Renewal Requests
  • Who can use the system
  • How the system is used

Medical Prescription Workflow

Step 1

User logs into the application

Step 2

Role-based nav elements get rendered

Step 3

User navigates, performs activities constrained by authorization policy

User Identification

We need to control WHO

can use the system

Authentication

Verifying that a user is

who it claims to be

Password-based Authentication


current_user = Yosai.get_current_subject()

authc_token = UsernamePasswordToken(username='patient123', 
                                    credentials='pygotham')
try:
    current_user.login(authc_token)

except AuthenticationException:
    ...

Password-based Authentication in a Web Application (Pyramid)

    
    @view_config(route_name='login', renderer='../templates/login.jinja2')
    def login(request):

        login_form = LoginForm(request.POST, context={'request': request})

        if request.method == "POST" and login_form.validate():

            authc_token = UsernamePasswordToken(username=login_form.username.data,
                                                                                         password=login_form.password.data)

            try:
                subject = Yosai.get_current_subject()
                subject.login(authc_token)

                next_url = request.route_url('launchpad')
                return HTTPFound(location=next_url)

            except AuthenticationException:
                request.session.flash('Invalid Login Credentials.')
                return {'login_form': login_form}

        else:
            return {'login_form': login_form}

Secure Access Control

We need to control HOW

the system is used

Authorization

Rules and mechanisms govening who can do what

Terminology

"Do This to That"

A Permission

A Role

(Group of Permissions)

Yosai evaluates roles and permissions to answer questions:

  •  Is the user a member of [any, all] of these roles?
  • Does the user have [any, all] of these permissions?

Yosai Enables

Role Based Access Control

Yosai uses Permissions, which are derived from
 an RBAC data model

Customized RBAC data models can be very powerful!

  • hierarchical
  • scoped
  • enforce least privilege

RBAC Fundamentals

Core RBAC

Hierarchical RBAC

Authorization Policy

(Medical Prescription Workflow)

Nurse Practitioner

Physician

Patient

  • Write Prescriptions
  • Approve Prescription Renewals
  • Write Prescriptions for a particular type of medicine only
  • Request Prescription Renewals

RBAC Data Model Example

(Prescription Writing)

A user may write a prescription for any medicine if the user is a physician

1) Membership of the physician role
2) write-prescription permission assigned to physician role

A user may write a prescription only for a 
particular medicine if the user is a nurse practitioner

1) Membership of the nurse_practitioner role
2) write-prescription-medicineid permission assigned to nurse_practitioner role

Prescription Writing Authorization

Declarative Authz


@requires_permission(['prescription:write'])
@view_config(route_name='write_rx', renderer='../templates/write_rx.jinja2')
def write_rx(request):

    write_rx_form = WriteRXForm(request.POST, context={'request': request})

    if request.method == "POST" and write_rx_form.validate():

        current_user = Yosai.get_current_subject()

        create_rx(current_user, . . . )

        next_url = request.route_url('write_rx')
        return HTTPFound(location=next_url)

    else:

        return {'write_rx_form': write_rx_form}

Declarative Authz


@requires_dynamic_permission(['prescription:write:{medicine}'])
@view_config(route_name='write_rx', renderer='../templates/write_rx.jinja2')
def write_rx(request):

    write_rx_form = WriteRXForm(request.POST, context={'request': request})

    if request.method == "POST" and write_rx_form.validate():

        current_user = Yosai.get_current_subject()

        create_rx(current_user, . . . )

        next_url = request.route_url('write_rx')
        return HTTPFound(location=next_url)

    else:

        return {'write_rx_form': write_rx_form}

Prescription Writing Authorization

Imperative Authz

@view_config(route_name='write_rx', renderer='../templates/write_rx.jinja2')
def write_rx(request):

    write_rx_form = WriteRXForm(request.POST, context={'request': request})

    if request.method == "POST" and write_rx_form.validate():

        current_user = Yosai.get_current_subject()
        
        medicine = request.matchdict['medicine']
        permission = 'prescription:write:' + medicine

        try:
            current_subject.check_permission([permission])
        except AuthorizationException:
            print('Not Permitted')
        else:
            create_rx(current_user, . . . )
               . . . . 

Prescription Writing Authorization

... and that's only ONE scenario!

  • Write Prescriptions
  • Approve Prescription Renewals
  • Write Prescriptions for a particular type of medicine only
  • Request Prescription Renewals

Each activity has a unique access control requirement

(but the approach remains the same)

Project Status

First Milestone:  release v0.1  end of March 2016

  • Project Web Site
  • pypi release

Next Milestone:  release v0.2  (ETA Sept 2016)

  • Fully functional yosai.web library
    • CSRF and Flash messages in Sessions
  • pyramid_yosai
  • Fully functional demo
  • Some refactoring:  API and serialization

Questions?

Yosai in the Wild - PyGotham 2016

By Darin Gordon

Yosai in the Wild - PyGotham 2016

This talk demonstrates Yosai "in the wild", highlighting some of its best features

  • 666