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

Introduction to Open Policy Agent

Bo-Yi Wu
October 12, 2021

Introduction to Open Policy Agent

1. Why do we need a Policy Engine?
2. Why do we choose Open Policy Agent?
3. Workflow with Open Policy Agent?
4. What is Policy Language (Rego)?
5. RBAC and IAM Role Design
6. Three ways to deploy an Open Policy Agent.

Bo-Yi Wu

October 12, 2021
Tweet

More Decks by Bo-Yi Wu

Other Decks in Programming

Transcript

  1. Introduction to


    Open Policy Agent
    Bo-Yi Wu


    2021/10/23


    View Slide

  2. About me
    • Software Engineer in Mediatek


    • Member of Drone CI/CD Platform


    • Member of Gitea Platform


    • Member of Gin Golang Framework


    • Maintain Some GitHub Actions Plugins.

    View Slide

  3. Outline
    • Why we need Policy Engine?


    • Why we choose Open Policy Agent?


    • Work
    fl
    ow with Open Policy Agent?


    • What is Policy Language (Rego)?


    • RBAC and IAM Role Design


    • Three ways to deploy Open Policy Agent.

    View Slide

  4. Why we need


    Policy Engine?

    View Slide

  5. 1. RBAC is Hard

    View Slide

  6. 4JNQMF(SPVQ
    1FSNJTTJPO

    View Slide

  7. View Slide

  8. {


    "group_roles": {


    "project_leader": ["kpi_editor_design", "viewer_limit_ds"],


    "software_leader": ["kpi_editor_design", "kpi_editor_system"]


    },


    "role_permissions": {


    "kpi_editor_design": [


    {"action": "view_all", "object": "design"},


    {"action": "edit", "object": "design"}


    ],


    "viewer_limit_ds": [


    {"action": "view_all", "object": "design"},


    {"action": "view_all", "object": "system"}


    ],


    "kpi_editor_design": [


    {"action": "view_all", "object": "design"},


    {"action": "edit", "object": "design"}


    ],


    "kpi_editor_system": [


    {"action": "view_all", "object": "system"},


    {"action": "edit", "object": "system"}


    ]


    }


    }


    View Slide

  9. 2. Cross


    Multi-Service

    View Slide

  10. 1FSNJTTJPOGPSNVMUJQMFTFSWJDF

    View Slide

  11. 3. Applying to


    Multi-System

    View Slide

  12. 1FSNJTTJPOGPSNVMUJQMFTZTUFN

    View Slide

  13. Why we choose


    Open Policy Agent?

    View Slide

  14. Open Policy Engine
    • Written in Golang


    • Easy to write policy testing


    • Easy to integrate with Go Application


    • Embed in GO


    • RESTful API

    View Slide

  15. Request Work
    fl
    ow with


    Open Policy Agent

    View Slide


  16. Client Send Request

    View Slide



  17. Client Send Request
    Ask Permission

    View Slide



  18. Client Send Request
    Ask Permission
    Response Result

    View Slide




  19. Client Send Request
    Ask Permission
    Response Result
    Response to Client

    View Slide

  20. Query Input and Result


    with policy engine

    View Slide

  21. View Slide


  22. Upload Data

    View Slide


  23. Upload Data
    Upload Policy Rule

    View Slide



  24. Upload Data
    Upload Policy Rule
    Send Query Input
    *OQVUDBOCF
    "/:+40/WBMVF

    View Slide



  25. Upload Data
    Upload Policy Rule
    Send Query Input
    Get Query Result
    *OQVUDBOCF
    "/:+40/WBMVF
    0VUQVUDBOCF
    "/:+40/WBMVF

    View Slide

  26. Policy Decision
    • Data (JSON)


    • Policy (Rego)


    • Query Input (JSON)

    View Slide

  27. RBAC Example


    (Role-base Access Control)

    View Slide

  28. {


    "group_roles": {


    "project_leader": ["kpi_editor_design", "viewer_limit_ds"],


    "software_leader": ["kpi_editor_design", "kpi_editor_system"]


    },


    "role_permissions": {


    "kpi_editor_design": [


    {"action": "view_all", "object": "design"},


    {"action": "edit", "object": "design"}


    ],


    "viewer_limit_ds": [


    {"action": "view_all", "object": "design"},


    {"action": "view_all", "object": "system"}


    ],


    "kpi_editor_design": [


    {"action": "view_all", "object": "design"},


    {"action": "edit", "object": "design"}


    ],


    "kpi_editor_system": [


    {"action": "view_all", "object": "system"},


    {"action": "edit", "object": "system"}


    ]


    }


    }


    %BUB

    View Slide

  29. {


    "group_roles": {


    "project_leader": ["kpi_editor_design", "viewer_limit_ds"],


    "software_leader": ["kpi_editor_design", "kpi_editor_system"]


    },


    "role_permissions": {


    "kpi_editor_design": [


    {"action": "view_all", "object": "design"},


    {"action": "edit", "object": "design"}


    ],


    "viewer_limit_ds": [


    {"action": "view_all", "object": "design"},


    {"action": "view_all", "object": "system"}


    ],


    "kpi_editor_design": [


    {"action": "view_all", "object": "design"},


    {"action": "edit", "object": "design"}


    ],


    "kpi_editor_system": [


    {"action": "view_all", "object": "system"},


    {"action": "edit", "object": "system"}


    ]


    }


    }


    3PMF

    View Slide

  30. {


    "group_roles": {


    "project_leader": ["kpi_editor_design", "viewer_limit_ds"],


    "software_leader": ["kpi_editor_design", "kpi_editor_system"]


    },


    "role_permissions": {


    "kpi_editor_design": [


    {"action": "view_all", "object": "design"},


    {"action": "edit", "object": "design"}


    ],


    "viewer_limit_ds": [


    {"action": "view_all", "object": "design"},


    {"action": "view_all", "object": "system"}


    ],


    "kpi_editor_design": [


    {"action": "view_all", "object": "design"},


    {"action": "edit", "object": "design"}


    ],


    "kpi_editor_system": [


    {"action": "view_all", "object": "system"},


    {"action": "edit", "object": "system"}


    ]


    }


    }


    (SPVQ

    View Slide

  31. {


    "input": {


    "user": ["project_leader", "software_leader"],


    "action": "edit",


    "object": "design"


    }


    }
    *OQVU

    View Slide

  32. {


    "input": {


    "user": ["project_leader", "software_leader"],


    "action": "edit",


    "object": "design"


    }


    }
    6TFSHSPVQT

    View Slide

  33. package rbac.authz


    import data.rbac.authz.acl


    import input


    # logic that implements RBAC.


    default allow = false


    allow {


    # lookup the list of roles for the user


    roles
    : =
    acl.group_roles[input.user[_]]


    # for each role in that list


    r
    : =
    roles[_]


    # lookup the permissions list for role r


    permissions
    : =
    acl.role_permissions[r]


    # for each permission


    p
    : =
    permissions[_]


    # check if the permission granted to r matches the user's request


    p
    = =
    {"action": input.action, "object": input.object}


    }


    1PMJDZ

    View Slide

  34. Policy Language


    (Rego)

    View Slide

  35. Rego Playground

    https://play.openpolicyagent.org/

    View Slide

  36. rule01 {


    input.x < input.y


    }


    rule02 = "foobar" {


    input.x < input.y


    }


    rule03 = x {


    x
    : =
    input.x


    x < input.y


    }


    %F
    fi
    OF3VMF
    IUUQTQMBZPQFOQPMJDZBHFOUPSHQ7"IJ/[YN

    View Slide

  37. rule01 {


    input.x < input.y


    }


    rule02 = "foobar" {


    input.x < input.y


    }


    rule03 = x {


    x
    : =
    input.x


    x < input.y


    }


    %F
    fi
    OF3VMF
    SFUVSOCPPMFBO

    View Slide

  38. rule01 {


    input.x < input.y


    }


    rule02 = "foobar" {


    input.x < input.y


    }


    rule03 = x {


    x
    : =
    input.x


    x < input.y


    }


    %F
    fi
    OF3VMF
    SFUVSOCPPMFBO
    SFUVSOTUSJOH

    View Slide

  39. rule01 {


    input.x < input.y


    }


    rule02 = "foobar" {


    input.x < input.y


    }


    rule03 = x {


    x
    : =
    input.x


    x < input.y


    }


    %F
    fi
    OF3VMF
    SFUVSOCPPMFBO
    SFUVSOTUSJOH
    SFUVSOWBSJBCMF

    View Slide

  40. rule01 {


    input.x < input.y


    input.y < input.z


    }


    rule02 {


    input.x < input.y


    }


    rule02 {


    input.y < input.z


    }


    "OE0SDPOEJUJPO
    BOEDPOEJUJPO
    PSDPOEJUJPO
    IUUQTQMBZPQFOQPMJDZBHFOUPSHQ-Q1STV

    View Slide

  41. default rule01 = false


    default rule02 = false


    rule01 {


    input.x < input.y


    input.y < input.z


    }


    rule02 {


    input.x < input.y


    }


    rule02 {


    input.y < input.z


    }


    EFGBVMUWBMVF

    View Slide

  42. func allow() bool {


    if input.group
    = =
    "admin" {


    return true


    }


    if input.user
    = =
    data.admin {


    return true


    }


    return false


    }


    default allow = false


    allow {


    input.group
    = =
    "admin"


    }


    allow {


    input.user
    = =
    data.admin


    }
    (PMBOH
    3FHP

    View Slide

  43. numbers = [1, 2, 3, 4, 5]


    rule[x] {


    x
    : =
    numbers[_]


    x % 2
    = =
    0


    }


    containers = {


    "app": {


    "image": "app:18.04"


    },


    "db": {


    "image": "db:latest"


    }


    }


    rule01[key] = image {


    image
    : =
    containers[key].image


    endswith(image, ":latest")


    }
    'JOEFWFOOVNCFS
    'JOEMBUFTUJNBHF

    View Slide

  44. numbers = [1, 2, 3, 4, 5]


    rule01 {


    x
    : =
    numbers[_]


    x < 0


    }


    rule02 {


    not rule01


    }


    positives {


    negative
    : =

    [x | x
    : =
    numbers[_]; x < 0]


    count(negative)
    = =
    0


    }


    numbers = [1, 2, 3, 4, 5]


    rule {


    x
    : =
    numbers[_]


    x > 0


    }
    "OZOVNCFS
    HSFBUFSUIBO;FSP
    numbers = [-1, 2, 3, 4, 5]


    rule {


    x
    : =
    numbers[_]


    x > 0


    }
    "MMOVNCFS
    HSFBUFSUIBO;FSP

    View Slide

  45. numbers = [1, 2, 3, 4, 5]


    rule01 {


    x
    : =
    numbers[_]


    x < 0


    }


    rule02 {


    not rule01


    }


    positives {


    negative
    : =

    [x | x
    : =
    numbers[_]; x < 0]


    count(negative)
    = =
    0


    }


    numbers = [1, 2, 3, 4, 5]


    rule {


    x
    : =
    numbers[_]


    x > 0


    }
    numbers = [-1, 2, 3, 4, 5]


    rule {


    x
    : =
    numbers[_]


    x > 0


    }
    "OZOVNCFS
    HSFBUFSUIBO;FSP
    "MMOVNCFS
    HSFBUFSUIBO;FSP

    View Slide

  46. numbers = [1, 2, 3, 4, 5]


    rule01 {


    x
    : =
    numbers[_]


    x < 0


    }


    rule02 {


    not rule01


    }


    positives {


    negative
    : =

    [x | x
    : =
    numbers[_]; x < 0]


    count(negative)
    = =
    0


    }


    numbers = [1, 2, 3, 4, 5]


    rule {


    x
    : =
    numbers[_]


    x > 0


    }
    numbers = [-1, 2, 3, 4, 5]


    rule {


    x
    : =
    numbers[_]


    x > 0


    }
    "OZOVNCFS
    HSFBUFSUIBO;FSP
    "MMOVNCFS
    HSFBUFSUIBO;FSP

    View Slide

  47. func rule() []string {


    results
    : =
    []string{}


    for _, img
    : =
    range images {


    for _, repo
    : =
    range repos {


    if strings.HasPref
    i
    x(img, repo) {


    results = append(results, img)


    }


    }


    }


    return results


    }


    images = [


    "docker.io/nginx",


    "quay.io/ubuntu",


    "localhost/nginx"


    ]


    repos = [


    "docker.io",


    "quay.io"


    ]


    rule[image] {


    image = images[_]


    startswith(image, repos[_])


    }


    3FHP (P-BOHVBHF

    View Slide

  48. OPA


    Testing

    View Slide

  49. rule07verify(answer) {


    rule07.db
    = =
    answer


    }


    test_rule07 {


    rule07verify("db:latest") with input as {"containers": {


    "app": {"image": "app:18.04"},


    "db": {"image": "db:latest"},


    }}


    not rule07verify("db:latest") with input as {"containers": {


    "app": {"image": "app:18.04"},


    "db": {"image": "postgres:latest"},


    }}


    }


    View Slide

  50. rule12verify(answer) {


    count(rule12)
    = =
    answer


    }


    test_rule12 {


    rule12verify(2) with input as {


    "images": [


    "docker.io/nginx",


    "quay.io/ubuntu",


    "localhost/nginx",


    ],


    "repos": [


    "docker.io",


    "quay.io",


    ],


    }


    }


    rule12[image] {


    image = input.images[_]


    startswith(image, input.repos[_])


    }


    3VMF
    5FTUJOH

    View Slide

  51. $ opa test
    -
    v .


    data.example.test_rule01
    :
    PASS (5.9055ms)


    data.example.test_rule02
    :
    PASS (157.292µs)


    data.example.test_rule03
    :
    PASS (839.958µs)


    data.example.test_rule04
    :
    PASS (150.125µs)


    data.example.test_rule05
    :
    PASS (3.447417ms)


    data.example.test_rule06
    :
    PASS (224.833µs)


    data.example.test_rule07
    :
    PASS (721.959µs)


    data.example.test_rule08
    :
    PASS (354.917µs)


    data.example.test_rule09
    :
    PASS (207.583µs)


    data.example.test_rule11
    :
    PASS (169.708µs)


    data.example.test_rule12
    :
    PASS (198.042µs)


    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    PASS
    :
    11/11 IUUQTHJUIVCDPNHPUSBJOJOHPQBEFNP

    View Slide

  52. Upload Data and Policy

    View Slide

  53. View Slide

  54. {


    "group_roles": {


    "admin": ["admin"],


    "project_leader": ["viewer_limit_ds"]


    },


    "role_permissions": {


    "admin": [


    {"action": "view_all", "object": "design"},


    {"action": "edit", "object": "design"},


    ],


    "viewer_limit_ds": [


    {"action": "view_all", "object": "design"},


    {"action": "view_all", "object": "system"}


    ],


    "viewer_limit_m": [{"action": "view_l3_project"}]


    }


    }
    %BUB

    View Slide

  55. {


    "group_roles": {


    "admin": ["admin"],


    "project_leader": ["viewer_limit_ds"]


    },


    "role_permissions": {


    "admin": [


    {"action": "view_all", "object": "design"},


    {"action": "edit", "object": "design"},


    ],


    "viewer_limit_ds": [


    {"action": "view_all", "object": "design"},


    {"action": "view_all", "object": "system"}


    ],


    "viewer_limit_m": [{"action": "view_l3_project"}]


    }


    }
    package rbac.authz


    import data.rbac.authz.acl


    import input


    default allow = false


    allow {


    roles := acl.group_roles[input.user[_]]


    r := roles[_]


    permissions := acl.role_permissions[r]


    p := permissions[_]


    p == {"action": input.action, "object": input.object}


    }
    %BUB
    1PMJDZ

    View Slide

  56. Query Result

    View Slide

  57. View Slide

  58. {


    "input": {


    "user": ["admin", "system_group_kpi_editor"],


    "action": "edit",


    "object": "design"


    }


    }
    *OQVU

    View Slide

  59. {


    "input": {


    "user": ["admin", "system_group_kpi_editor"],


    "action": "edit",


    "object": "design"


    }


    }
    {


    "result": true


    }
    *OQVU
    3FTVMU

    View Slide

  60. RBAC


    Design

    View Slide

  61. View Slide

  62. Login Flow





    View Slide

  63. / /
    GetUserGroupNames get user groups


    func GetUserGroupNames(username string) ([]string, error) {


    if !helper.IsUsername(username) {


    return []string{}, errors.EBadRequest(errors.ErrUserNotExist, nil)


    }


    result
    : =
    &getUserGroups{}


    response, err
    : =
    resty.New().R().


    SetHeader("Content-Type", "application/json").


    SetHeader("Accept", "application/json").


    SetQueryParam("username", username).


    SetBasicAuth(conf
    i
    g.Crowd.BasicUsername, conf
    i
    g.Crowd.BasicPassword).


    SetResult(result).


    Get(conf
    i
    g.Crowd.Address + "/user/group/nested")


    if err
    ! =
    nil {


    return []string{}, err


    }


    if response.StatusCode()
    ! =
    http.StatusOK {


    log.Error().Msg("failed to get user groups from crowd:" + response.String())


    }


    groups
    : =
    []string{}


    for _, v
    : =
    range result.Groups {


    if strings.HasPref
    i
    x(v.Name, "prime_") {


    groups = append(groups, v.Name)


    }


    }


    return groups, err


    }


    View Slide

  64. 3PMF1FSNJTTJPO

    View Slide

  65. 3PMF1FSNJTTJPO

    View Slide

  66. # role
    -
    permissions assignments


    role_permissions
    : =
    {


    "admin": [


    {"action": "view_all", "object": "design"},


    {"action": "edit", "object": "design"},


    {"action": "view_all", "object": "system"},


    {"action": "edit", "object": "system"},


    {"action": "view_all", "object": "manufacture"},


    {"action": "edit", "object": "manufacture"},


    ],


    "quality_head_design": [


    {"action": "view_all", "object": "design"},


    {"action": "edit", "object": "design"},


    {"action": "view_all", "object": "system"},


    {"action": "view_all", "object": "manufacture"},


    ],


    "quality_head_system": [


    {"action": "view_all", "object": "design"},


    {"action": "view_all", "object": "system"},


    {"action": "edit", "object": "system"},


    {"action": "view_all", "object": "manufacture"},


    ],


    "quality_head_manufacture": [


    {"action": "view_all", "object": "design"},


    {"action": "view_all", "object": "system"},


    {"action": "view_all", "object": "manufacture"},


    {"action": "edit", "object": "manufacture"},


    ],


    }


    View Slide

  67. 3PMF1FSNJTTJPO

    View Slide

  68. # user
    -
    role assignments


    group_roles
    : =
    {


    "prime_cqc_admin": ["admin"],


    "prime_cqc_design_quality_head": ["quality_head_design"],


    "prime_cqc_system_quality_head": ["quality_head_system"],


    "prime_cqc_manufacturing_quality_head": ["quality_head_manufacture"],


    "prime_cqc_design_kpi_editor": ["kpi_editor_design"],


    "prime_cqc_system_kpi_editor": ["kpi_editor_system"],


    "prime_cqc_manufacturing_kpi_editor": ["kpi_editor_manufacture"],


    "prime_cqc_viewer": ["viewer"],


    "prime_cqc_limitedviewer_design_system": ["viewer_limit_ds"],


    "prime_cqc_limitedviewer_manufacturing": ["viewer_limit_m"],


    }


    View Slide

  69. 3PMF1FSNJTTJPO

    View Slide

  70. # user
    -
    role assignments


    group_roles
    : =
    {


    # for testing


    "design_group_kpi_editor": ["kpi_editor_design", "viewer_limit_ds"],


    "system_group_kpi_editor": ["kpi_editor_system", "viewer_limit_ds"],


    "manufacture_group_kpi_editor": ["kpi_editor_manufacture", "viewer"],


    "project_leader": ["viewer_limit_ds", "viewer_limit_m"],


    }


    View Slide

  71. RBAC


    Testing

    View Slide

  72. test_design_group_kpi_editor {


    allow with input as {"user": ["design_group_kpi_editor"], "action": "view_all", "object": "design"}


    allow with input as {"user": ["design_group_kpi_editor"], "action": "edit", "object": "design"}


    allow with input as {"user": ["design_group_kpi_editor"], "action": "view_all", "object": "system"}


    not allow with input as {"user": ["design_group_kpi_editor"], "action": "edit", "object": "system"}


    not allow with input as {"user": ["design_group_kpi_editor"], "action": "view_all", "object": "manufacture"}


    not allow with input as {"user": ["design_group_kpi_editor"], "action": "edit", "object": "manufacture"}


    }


    View Slide

  73. $ opa test
    -
    v ./module/opa/policy
    / *
    .rego


    data.rbac.authz.test_design_group_kpi_editor: PASS (13.0495ms)


    data.rbac.authz.test_system_group_kpi_editor: PASS (2.158583ms)


    data.rbac.authz.test_manufacture_group_kpi_editor: PASS (2.235167ms)


    data.rbac.authz.test_project_leader: PASS (1.90625ms)


    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    PASS
    :
    4/4

    View Slide

  74. How about


    Dynamic Actions and


    Dynamic Resources?

    View Slide

  75. "NB[POF8FC4FSWJDF*".

    View Slide

  76. {
    "Version": "2012-10-17",
    "Statement": [
    {
    "Sid": "FirstStatement",
    "Effect": "Allow",
    "Action": ["iam:ChangePassword"],
    "Resource": "*"
    },
    {
    "Sid": "SecondStatement",
    "Effect": "Allow",
    "Action": "s3:ListAllMyBuckets",
    "Resource": "*"
    },
    {
    "Sid": "ThirdStatement",
    "Effect": "Allow",
    "Action": [
    "s3:List*",
    "s3:Get*"
    ],
    "Resource": [
    "arn:aws:s3:::confidential-data",
    "arn:aws:s3:::confidential-data/*"
    ]
    }
    ]
    }
    "NB[POF8FC
    4FSWJDF*".

    View Slide

  77. package aws


    default allow = false


    allow {


    actions_match


    resources_match


    }


    actions_match {


    # iterate over the actions in the list


    actions
    : =
    ["s3
    :
    List.*","s3
    :
    Get.*"]


    action
    : =
    actions[_]


    # check if input.action matches an action


    regex.globs_match(input.action, action)


    }


    resources_match {


    # iterate over the resources in the list


    resources
    : =
    ["arn:aws:s3
    : : :
    conf
    i
    dential
    -
    data","arn:aws:s3
    : : :
    conf
    i
    dential
    -
    data/.*"]


    resource
    : =
    resources[_]


    # check if input.resource matches a resource


    regex.globs_match(input.resource, resource)


    }
    IUUQTXXXPQFOQPMJDZBHFOUPSHEPDTMBUFTUDPNQBSJTPOUPPUIFSTZTUFNTBNB[POXFCTFSWJDFTJBN
    {
    "Version": "2012-10-17",
    "Statement": [
    {
    "Sid": "FirstStatement",
    "Effect": "Allow",
    "Action": ["iam:ChangePassword"],
    "Resource": "*"
    },
    {
    "Sid": "SecondStatement",
    "Effect": "Allow",
    "Action": "s3:ListAllMyBuckets",
    "Resource": "*"
    },
    {
    "Sid": "ThirdStatement",
    "Effect": "Allow",
    "Action": [
    "s3:List*",
    "s3:Get*"
    ],
    "Resource": [
    "arn:aws:s3:::confidential-data",
    "arn:aws:s3:::confidential-data/*"
    ]
    }
    ]
    }
    1PMJDZ
    %BUB

    View Slide

  78. package aws


    default allow = false


    allow {


    actions_match


    resources_match


    }


    actions_match {


    # iterate over the actions in the list


    actions
    : =
    ["s3
    :
    List.*","s3
    :
    Get.*"]


    action
    : =
    actions[_]


    # check if input.action matches an action


    regex.globs_match(input.action, action)


    }


    resources_match {


    # iterate over the resources in the list


    resources
    : =
    ["arn:aws:s3
    : : :
    conf
    i
    dential
    -
    data","arn:aws:s3
    : : :
    conf
    i
    dential
    -
    data/.*"]


    resource
    : =
    resources[_]


    # check if input.resource matches a resource


    regex.globs_match(input.resource, resource)


    }
    IUUQTXXXPQFOQPMJDZBHFOUPSHEPDTMBUFTUDPNQBSJTPOUPPUIFSTZTUFNTBNB[POXFCTFSWJDFTJBN
    {
    "Version": "2012-10-17",
    "Statement": [
    {
    "Sid": "FirstStatement",
    "Effect": "Allow",
    "Action": ["iam:ChangePassword"],
    "Resource": "*"
    },
    {
    "Sid": "SecondStatement",
    "Effect": "Allow",
    "Action": "s3:ListAllMyBuckets",
    "Resource": "*"
    },
    {
    "Sid": "ThirdStatement",
    "Effect": "Allow",
    "Action": [
    "s3:List*",
    "s3:Get*"
    ],
    "Resource": [
    "arn:aws:s3:::confidential-data",
    "arn:aws:s3:::confidential-data/*"
    ]
    }
    ]
    }
    1PMJDZ
    %BUB

    View Slide

  79. How to resolve


    Multiple Statement and


    Multiple Effect?

    View Slide

  80. {
    "Version": "2012-10-17",
    "Statement": [
    {
    "Sid": "FirstStatement",
    "Effect": "Allow",
    "Action": ["iam:ChangePassword"],
    "Resource": "*"
    },
    {
    "Sid": "SecondStatement",
    "Effect": "Deny",
    "Action": "s3:GetFile",
    "Resource": "*"
    },
    {
    "Sid": "ThirdStatement",
    "Effect": "Allow",
    "Action": [
    "s3:List*",
    "s3:Get*"
    ],
    "Resource": [
    "arn:aws:s3:::bucket",
    "arn:aws:s3:::bucket/*"
    ]
    }
    ]
    }
    1FSNJTTJPO%BUB
    {
    "action": "s3:GetFile",
    "Resource": "arn:aws:s3:::bucket"
    }
    *OQVU%BUB

    View Slide

  81. {
    "Version": "2012-10-17",
    "Statement": [
    {
    "Sid": "FirstStatement",
    "Effect": "Allow",
    "Action": ["iam:ChangePassword"],
    "Resource": "*"
    },
    {
    "Sid": "SecondStatement",
    "Effect": "Deny",
    "Action": "s3:GetFile",
    "Resource": "*"
    },
    {
    "Sid": "ThirdStatement",
    "Effect": "Allow",
    "Action": [
    "s3:List*",
    "s3:Get*"
    ],
    "Resource": [
    "arn:aws:s3:::bucket",
    "arn:aws:s3:::bucket/*"
    ]
    }
    ]
    }
    1FSNJTTJPO%BUB
    {
    "action": "s3:GetFile",
    "Resource": "arn:aws:s3:::bucket"
    }
    *OQVU%BUB

    View Slide

  82. package iam.authz


    default authorized = false


    has_resource[statement_id] {


    statement_resource
    : =
    data.statements[statement_id].resources[_]


    regex.globs_match(input.resource, statement_resource)


    }


    has_action[statement_id] {


    statement_resource
    : =
    data.statements[statement_id].actions[_]


    regex.globs_match(input.action, statement_resource)


    }


    match[[effect, statement_id]] {


    effect
    : =
    data.statements[statement_id].effect


    has_resource[statement_id]


    has_action[statement_id]


    }


    allow {


    match[["allow", _]]


    }


    deny {


    match[["deny", _]]


    }


    authorized {


    allow


    not deny


    }

    View Slide

  83. Three Ways to Deploy


    Open Policy Agent

    View Slide

  84. Architectural Flexibility
    • Embed in Go Application


    • Deploy in Single Project (REST API)


    • Deploy one OPA service (REST API)

    View Slide

  85. Embed in Go Application

    View Slide

  86. Deploy in Single Project

    View Slide

  87. Deploy one OPA service

    View Slide

  88. AWS Lambda
    Function With OPA

    View Slide

  89. Thanks

    View Slide