Upgrade to Pro — share decks privately, control downloads, hide ads and more …

flexible-authorization

 flexible-authorization

Flexible Authorization: Storing & Managing Rules in Database presentation for RDRC 2016

Giovanni Sakti

June 23, 2016
Tweet

More Decks by Giovanni Sakti

Other Decks in Programming

Transcript

  1. Storing & Managing Rules in Database
    Flexible Authorization

    View full-size slide

  2. @giosakti
    Giovanni Sakti

    View full-size slide

  3. Storing & Managing Rules in Database
    Flexible Authorization

    View full-size slide

  4. Storing & Managing Rules in Database
    Flexible Authorization

    View full-size slide

  5. Why is flexibility
    necessary?

    View full-size slide

  6. Why is flexibility
    necessary?
    It’s for future improvement and

    because my blood type is also O

    View full-size slide

  7. U: Can you make role A able to read this
    document after its state changes to approved?
    Me: *(hack the source code a bit)* Done
    U: Can you make role B release this document
    after at least 5 people agree?
    Me: *(hack the source code a bit)* Done
    U: *(Insert some very specific requests here)*
    Me: *(hack the source code a bit)* Done

    View full-size slide

  8. U: Can you just give me a nice interfaces to work
    with, so that I don’t have to bug you anymore
    when new requirements appear?

    View full-size slide

  9. Regulating
    Collecting
    Evaluating
    Enforcing / Scoping
    Subsystems

    View full-size slide

  10. Subsystems
    Store rules/regulations/policies
    Regulating
    1
    Can I read this document
    Enforcing /
    Scoping
    2
    3 Evaluating
    4 Collecting

    View full-size slide

  11. Subsystems
    Store rules/regulations/policies
    Regulating
    1
    Can I read this document
    Enforcing /
    Scoping
    2
    3 Evaluating
    4 Collecting

    View full-size slide

  12. Subject Who
    Action What
    Object / Resource What
    Environment When, Where, How, Why
    Elements

    View full-size slide

  13. users roles
    activities
    Defining Tables & Columns
    N N
    N
    N
    username
    password
    e-mail
    name
    name
    actions : JSONB
    object
    conditions : JSONB
    Regulating

    View full-size slide

  14. actions: ['READ'],
    object: 'Document',
    conditions: [
    "object.state = 'APPROVED'"
    ]
    actions: ['RELEASE'],
    object: 'Document',
    conditions: [
    "object.approver_count >= 5"
    ]
    Regulating

    View full-size slide

  15. actions: ['READ', 'UPDATE', 'DELETE'],
    object: 'Document',
    conditions: [
    "AND",
    "object.organization.code = 'A000'",
    "object.state = 'RELEASED"
    ]
    Regulating

    View full-size slide

  16. actions: ['READ', 'UPDATE', 'DELETE'],
    object: 'Document',
    conditions: [
    "AND",
    [
    "OR",
    "object.organization.code = 'A000'",
    "object.organization.code = ‘B000'"
    ],
    "object.state = 'RELEASED"
    ]
    Regulating

    View full-size slide

  17. WYSIWYGish editor
    document organization
    code = ‘A000’
    Live preview
    Regulating

    View full-size slide

  18. # documents_controller.rb
    ...
    def destroy
    authorize @document, :delete?
    @document.destroy!
    render json: @document
    end
    ...
    Collecting

    View full-size slide

  19. # application_policy.rb
    ...
    activities = @user.active_role.activities.
    where("actions ?? :action", action: "DESTROY").
    where(object: “Document")
    ...
    Collecting

    View full-size slide

  20. actions: ['READ', 'UPDATE', 'DELETE'],
    object: 'Document',
    conditions: [
    "AND",
    [
    "OR",
    "object.organization.code = 'A000'",
    "object.organization.code = ‘B000'"
    ],
    "object.state = 'RELEASED"
    ]
    Evaluate conditions tree
    Evaluating

    View full-size slide

  21. Enforcing / Scoping

    View full-size slide

  22. May I (read/update/approve) this
    document?
    Enforcing

    View full-size slide

  23. # documents_controller.rb
    ...
    def destroy
    authorize @document, :delete?
    @document.destroy!
    render json: @document
    end
    ...
    Enforcing

    View full-size slide

  24. What documents can I read?
    Scoping

    View full-size slide

  25. actions: ['READ', 'UPDATE', 'DELETE'],
    object: 'Document',
    conditions: [
    "AND",
    [
    "OR",
    "object.organization.code = 'A000'",
    "object.organization.code = ‘B000'"
    ],
    "object.state = 'RELEASED"
    ]
    Scoping
    def parse_json(opts = {})
    instruction = {}
    instruction[:joins] = []
    instruction[:selects] = {}
    # If json_arr is blank
    if opts[:json_arr].blank?
    instruction[:query] = TRUE_QUERY
    return instruction
    end
    # If json_arr is not blank
    operator = nil
    operand_stack = []
    opts[:json_arr].each_with_index do |token, idx|
    if (idx == 0) && (%w(AND OR).include? token)
    operator = token
    else
    if token.is_a? Array
    temp = parse_json(opts.merge({json_arr: token}))
    instruction[:joins] |= temp[:joins].flatten
    instruction[:selects].merge! temp[:selects]
    query = "(#{temp[:query]})"
    else
    query_tokens = token.scan(/(?:"(?:\\.|[^"])*"|[^" ])+/)
    if (query_tokens.size != 3) && (!%w(= IN).include? query_tokens[1])
    raise "Syntax error #{token}"
    else
    lhs_join = nil
    lhs_select = nil
    lhs_query = ""
    lhs_arr = query_tokens[0].split(".")
    lhs_arr.to_enum.with_index.reverse_each do |atom, idx|
    if idx == lhs_arr.size - 1
    lhs_query = atom
    lhs_select = {"#{atom}" => lhs_query}
    elsif idx < lhs_arr.size - 1 && idx > 0
    if lhs_join.nil?
    lhs_join = atom.to_sym
    else
    lhs_join = {atom.to_sym => lhs_join}
    end
    lhs_query = "#{atom}.#{lhs_arr[lhs_arr.size - 1]}"
    lhs_select = {"#{lhs_arr[lhs_arr.size - 1]}" => lhs_query}
    else
    # If array size is 2, then we should rename object to avoid ambiguity sql statement
    if lhs_arr.size == 2
    lhs_query = "#{opts[:object].table_name}.#{lhs_arr[lhs_arr.size - 1]}"
    lhs_select = {"#{lhs_arr[lhs_arr.size - 1]}" => lhs_query}
    end
    end
    end
    rhs_query = ""
    if query_tokens[2].start_with? "subject"
    subject_scope = opts[:subject]
    rhs_arr = query_tokens[2].split(".")
    rhs_arr.each_with_index do |atom, idx|
    # If subject is not exist then there is no need to construct query, move along
    unless subject_scope
    rhs_query = ""
    next
    end
    if idx == 0
    # NOP
    elsif idx > 0 && idx < (rhs_arr.size - 1)
    subject_scope = subject_scope.send(atom.to_sym)
    end
    if idx == (rhs_arr.size - 1)
    if query_tokens[1] == "IN"
    values = subject_scope.map{|m| "'#{m.send(atom.to_sym)}'"}
    rhs_query = "(#{values.join(',')})" if values.present?
    else
    rhs_query = "'#{subject_scope.send(atom.to_sym)}'"
    end
    end
    end
    else
    rhs_query = query_tokens[2]
    end
    instruction[:joins] |= [lhs_join] if lhs_join.present?
    instruction[:selects].merge! lhs_select if lhs_select.present?
    if rhs_query.present?
    query = "#{lhs_query} #{query_tokens[1]} #{rhs_query}"
    else
    query = FALSE_QUERY
    end
    end
    end
    operand_stack.push query
    end
    end
    if operator
    instruction[:query] = operand_stack.join(" #{operator} ")
    else
    instruction[:query] = operand_stack.shift
    end
    return instruction
    end
    What to select?
    What to join?
    What to filter?

    View full-size slide

  26. Challenges &
    Improvements

    View full-size slide

  27. Conflict Resolution
    What if there are two or more rules with different outcome

    View full-size slide

  28. e.g. XACML
    Use Open Standard ?

    View full-size slide

  29. With the help of oAuth
    Centralized Authorization

    View full-size slide

  30. 4 subsystems to consider
    regulating, collecting, evaluating, enforcing / scoping

    View full-size slide

  31. Format for storing authorization rules is important
    That’s why there’s even a standard for this

    View full-size slide

  32. The current focus is on how to make our
    authorization system less dependent on
    developers and give power to user

    View full-size slide

  33. Thanks!
    @giosakti
    https://speakerdeck.com/giosakti/flexible-authorization

    View full-size slide