|
| 1 | +--- |
| 2 | +id: advanced-policies |
| 3 | +title: Build Advanced Policies |
| 4 | +description: In lesson 5, you'll learn how to build advanced policies. |
| 5 | +keywords: [pomerium, reverse proxy, authorization policy, advanced policies] |
| 6 | +sidebar_label: 5. Advanced Policies |
| 7 | +sidebar_position: 5 |
| 8 | +--- |
| 9 | + |
| 10 | +# Build Advanced Policies |
| 11 | + |
| 12 | +In this guide, you’ll learn how to build **Advanced Policies** with Pomerium. |
| 13 | + |
| 14 | +:::note **Before You Start** |
| 15 | + |
| 16 | +Make sure you’ve completed the following tutorials: |
| 17 | + |
| 18 | +- [**Get Started**](/docs/courses/fundamentals/get-started) |
| 19 | +- [**Build a Simple Route**](/docs/courses/fundamentals/build-routes) |
| 20 | +- [**Build a Simple Policy**](/docs/courses/fundamentals/build-policies) |
| 21 | +- [**Identity Verification with JWTs**](/docs/courses/fundamentals/jwt-verification) |
| 22 | + |
| 23 | +Each tutorial builds on the same configuration files. In this tutorial, you’ll add complexity to your authorization policy. |
| 24 | + |
| 25 | +::: |
| 26 | + |
| 27 | +## What’s an advanced policy? |
| 28 | + |
| 29 | +An “advanced policy” usually means the policy includes: |
| 30 | + |
| 31 | +- Chaining policy blocks |
| 32 | +- Additional operators, criteria, and matchers |
| 33 | + |
| 34 | +For example, the policy below will only grant access if a user’s email address includes an `example.com` domain: |
| 35 | + |
| 36 | +```yaml |
| 37 | +policy: |
| 38 | + allow: |
| 39 | + and: |
| 40 | + - domain: |
| 41 | + is: example.com |
| 42 | +``` |
| 43 | +
|
| 44 | +But, with Pomerium Policy Language (PPL), you can build richer policies that use all sorts of context to control access to upstream applications. |
| 45 | +
|
| 46 | +:::info **Establishing house rules** |
| 47 | +
|
| 48 | +Think of it like this: you have a dog, and obviously you normally let your dog in the house. But what if your dog was sprayed by a skunk? Suddenly the “allow my dog in the house” policy needs additional caveats. Advanced policies allow you to have better policy logic than what you currently have in your configuration file. |
| 49 | +
|
| 50 | +::: |
| 51 | +
|
| 52 | +### Evaluate claims |
| 53 | +
|
| 54 | +Let’s extend the policy above to include a claim from your JWT. If a user doesn’t have the matching claim in their JWT, Pomerium will deny the user access. |
| 55 | +
|
| 56 | +1. **Get the value of the** `Name` **claim** |
| 57 | + |
| 58 | +While running your Docker containers, access the Verify service. Under **Signed Identity Token**, you’ll see a list of claims: |
| 59 | + |
| 60 | + |
| 61 | + |
| 62 | +Find the **Name** claim and copy the value. |
| 63 | + |
| 64 | +2. **Update your policy** |
| 65 | + |
| 66 | +Right now, your policy consists of one `allow` block with the `and` logical operator. |
| 67 | + |
| 68 | +Change `and` to `or`. |
| 69 | + |
| 70 | +```yaml |
| 71 | +policy: |
| 72 | + allow: |
| 73 | + or: |
| 74 | + - domain: |
| 75 | + is: example.com |
| 76 | +``` |
| 77 | + |
| 78 | +The `or` operator grants access if either of two criteria are true. |
| 79 | + |
| 80 | +Right now, you only have one criterion: `domain`. |
| 81 | + |
| 82 | +Let’s add a second criterion, `claim`, and add it to the same policy block: |
| 83 | + |
| 84 | +```yaml |
| 85 | +policy: |
| 86 | + allow: |
| 87 | + or: |
| 88 | + - domain: |
| 89 | + is: example.com |
| 90 | + - claim/Name: <"Your Name"> |
| 91 | +``` |
| 92 | + |
| 93 | +The `claim` operator requires a sub-path and the value of a JWT claim. |
| 94 | + |
| 95 | +You use `/` to delimit the beginning of the sub-path. In this case, the claim we want is `Name`. The value of `Name` is the name included in your JWT. |
| 96 | + |
| 97 | +Replace `Your Name` with the value in your JWT. |
| 98 | + |
| 99 | +Now, if a user’s email address includes `example.com` _or_ their claim matches the `Name` claim, Pomerium will grant the user access. |
| 100 | + |
| 101 | +### Add a deny rule |
| 102 | + |
| 103 | +Now, let’s add a second `deny` block to this policy. We will write a policy that denies access if a user’s email starts with `admin`. |
| 104 | + |
| 105 | +```yaml |
| 106 | +policy: |
| 107 | + allow: |
| 108 | + or: |
| 109 | + - domain: |
| 110 | + is: example.com |
| 111 | + - claim/Name: <"Your Name"> |
| 112 | + deny: |
| 113 | + and: |
| 114 | + - email: |
| 115 | + starts_with: admin |
| 116 | +``` |
| 117 | + |
| 118 | +As is, this policy will deny access if a user’s email starts with `admin` (of course, you can change this value to whatever you want). |
| 119 | + |
| 120 | +Swap out the value with the beginning of your email address to test it out. This policy will still deny you access, even if your email’s domain and your JWT claim satisfy the `allow` block’s criteria. |
| 121 | + |
| 122 | +## Summary |
| 123 | + |
| 124 | +In this tutorial, you built more advanced policies that require multiple rules, logical operators, matchers, and criteria. Then, you attached these policies to your routes. |
| 125 | + |
| 126 | +Now, your Pomerium instance can evaluate claims and grant or deny access based on additional policies you’ve built! We’re teaching Pomerium to do exactly what you want it to do: Verify authorization whenever someone accesses a route. |
| 127 | + |
| 128 | +Organizations with multiple applications and services will want to know how they can scale Pomerium for their needs. |
| 129 | + |
| 130 | +In the next tutorial, you’ll learn how to build more complex routes! |
| 131 | + |
| 132 | +### Configuration file state |
| 133 | + |
| 134 | +By now, your configuration files should look similar to this: |
| 135 | + |
| 136 | +```yaml |
| 137 | +authenticate_service_url: https://authenticate.pomerium.app |
| 138 | +
|
| 139 | +signing_key: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUVSNThaeDA2SHJXTW9PUTRaNjlMaDdMZUtFZW5TSmJZcHJvZ3V3TEl0blNvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFK1FtamZKQ2ovdzkrOUhrRDVlbTlIZFhRM3ViUEhIdWNOMTlNOXJxR05PeEpTRmR3VHgvaAphdVkvcVFSWWR0YVpnVEpEUWZSYVQ2Q1pPYndSYTl2TXNnPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo= |
| 140 | +
|
| 141 | +routes: |
| 142 | + - from: https://verify.localhost.pomerium.io |
| 143 | + to: http://verify:8000 |
| 144 | + pass_identity_headers: true |
| 145 | + policy: |
| 146 | + allow: |
| 147 | + or: |
| 148 | + - domain: |
| 149 | + is: example.com |
| 150 | + - claim/Name: <"Your Name"> |
| 151 | + deny: |
| 152 | + and: |
| 153 | + - email: |
| 154 | + starts_with: admin |
| 155 | + - from: https://grafana.localhost.pomerium.io |
| 156 | + to: http://grafana:3000 |
| 157 | + pass_identity_headers: true |
| 158 | + policy: |
| 159 | + allow: |
| 160 | + and: |
| 161 | + - domain: |
| 162 | + is: example.com |
| 163 | +``` |
| 164 | + |
| 165 | +Docker Compose: |
| 166 | + |
| 167 | +```yaml |
| 168 | +version: '3' |
| 169 | +services: |
| 170 | + pomerium: |
| 171 | + image: pomerium/pomerium:latest |
| 172 | + volumes: |
| 173 | + - ./config.yaml:/pomerium/config.yaml:ro |
| 174 | + ports: |
| 175 | + - 443:443 |
| 176 | + verify: |
| 177 | + image: pomerium/verify:latest |
| 178 | + expose: |
| 179 | + - 8000 |
| 180 | + environment: |
| 181 | + - JWKS_ENDPOINT=https://pomerium/.well-known/pomerium/jwks.json |
| 182 | + grafana: |
| 183 | + image: grafana/grafana:latest |
| 184 | + ports: |
| 185 | + - 3000:3000 |
| 186 | +``` |
0 commit comments