# Authorization

Authorization of users and services in Grey Matter is handled by setting up chains of Filters in each Sidecar. These filter chains can be composed into whatever way best suites the needs of the business, but a few reference flows are outlined here.

The contents here focus on HTTP level authorization. Authorization at the TCP level is also supported through the [Envoy TCP RBAC filter](https://github.com/DecipherNow/gm-gitbook-sync/tree/51c620aa4cc4734f2fd458547cc374fe00f1bb37/usage/fabric/filters/network/README.md#role-based-access-control).

## Key Components

| Filter               | Description                                                                 | Configuration                              |
| -------------------- | --------------------------------------------------------------------------- | ------------------------------------------ |
| `gm.inheaders`       | Set up request headers from certificates to allow authorization actions     | [link](../filters/http/gm-inheaders)       |
| `gm.ensurevariables` | Ensure headers/cookies/query strings are present at needed locations.       | [link](../filters/http/gm-ensurevariables) |
| `gm.jwtsecurity`     | Establish JWT token for user/service in request for later Authz.            | [link](../filters/http/gm-jwt-security)    |
| `gm.listauth`        | Apply whitelist or blacklist authentication based on USER\_DN header field. | [link](../filters/http/gm-listauth)        |
| `envoy.jwt_authn`    | Authorize requests to route/method based on user/role                       |                                            |
| `envoy.rbac`         | Authorize requests to route/method based on user/role                       | [link](../filters/envoy-rbac)              |

## Flows

### Users, Services, Guests

This authorization flow determines access to the service with 3 different policies. A policy for authenticated users coming through the edge, a policy for authenticated services, and a default policy for anything else.

The `service-admin` policy in the RBAC filter below allows any request coming in with the header `USER_DN: CN=quickstart,OU=Engineering,O=Decipher Technology Studios,L=Alexandria,ST=Virginia,C=US`. This policy requires the `gm-inheaders` filter to be set up at the Edge so that incoming requests have the USER\_DN appropriately set from the incoming certificates.

A `services` policy then follows. This is configured to allow any service using certs issued by the SPIRE integration to access the service. The regex matching permits any service as shown, but exact matches or more restrictive regex can be used to tune it to permit/deny specific services. E.g. exact matches on`spiffe://quickstart.greymatter.io/data` or `spiffe://quickstart.greymatter.io/catalog` would permit just those services to perform actions.

The last policy, `product-viewer`, allows any request that does not match either of the two preceding policies to perform only GET requests. Any other method will be denied. This is useful when only certain users/services should be permitted to perform modifications, but anyone should be able to read.

#### Config

```javascript
  "active_http_filters": [
    "envoy.rbac"
  ],
  "http_filters": {
    "envoy_rbac": {
      "rules": {
        "action": 0,
        "policies": {
          "service-admin": {
            "permissions": [
              {
                "any": true
              }
            ],
            "principals": [
              {
                "header": {
                  "name": "user_dn",
                  "exact_match": "CN=quickstart,OU=Engineering,O=Decipher Technology Studios,L=Alexandria,ST=Virginia,C=US"
                }
              }
            ]
          },
          "services": {
            "permissions": [
              {
                "any": true
              }
            ],
            "principals": [
              {
                "authenticated": {
                  "principal_name": {
                    "regex": "spiffe:\/\/quickstart.greymatter.io\/(.+)"
                  }
                }
              }
            ]
          },
          "product-viewer": {
            "permissions": [
              {
                "header": {
                  "name": ":method",
                  "exact_match": "GET"
                }
              }
            ],
            "principals": [
              {
                "any": true
              }
            ]
          }
        }
      }
    },
```

### Simple Access List

This authorization flow is a simple setup to only establish standard headers and then perform whitelisting. The `gm.inheaders` filter sets up the `USER_DN` header from incoming user's PKI certificates, and the `gm.listauth` will allow or deny based on the set whitelist and blacklist.

* [`gm.inheadeers` docs](../filters/http/gm-inheaders)
* [`gm.listauth` docs](../filters/http/gm-listauth)

> NOTE: in a typical setup, the `gm.inheaders` filter is setup on the originating Sidecar (usually the Edge node or an internal egress listener) rather than the destination. This allows common origination points to setup the needed header fields, and then each destination to setup it's own allow/deny rules. Both are shown in the same config below for reference, and because this is also permissible if desired.

#### Config

```javascript
  "active_http_filters": [
    "gm.inheaders",
    "gm.listauth"
  ],
  "http_filters": {
    "gm_listauth": {
      "whitelist": "CN=quickstart,OU=Engineering,O=Decipher Technology Studios,L=Alexandria,ST=Virginia,C=US",
      "blacklist": "CN=catalog,OU=Engineering,O=Decipher Technology Studios,L=Alexandria,ST=Virginia,C=US"
    }
  }
```

### inheaders + jwt-security + authn + rbac

This flow composes a number of filters to perform RBAC on user attributes in JWT tokens from Grey Matter's JWT Security Service. The filter chain here performs the following in sequence:

1. `gm.inheaders`: Establish USER\_DN header from incoming certs
2. `gm.jwtsecurity`: Exchange USER\_DN header for a JWT token with complete user claims.
3. `envoy.jwt_authn`: Verifies the JWT token and populates internal metadata with the claims.
4. `envoy.rbac`: Accesses the `envoy.jwt_authn` metadata from the JWT token to verify that the user's email address contains the greymatter.io domain and allow access.

#### Config

```javascript
  "active_http_filters": [
    "gm.inheaders",
    "gm.jwtsecurity",
    "envoy.jwt_authn"
    "envoy.rbac"
  ],
  "http_filters": {
    "gm.inheaders": {},
    "gm.jwtsecurity": {
      "apiKey": "dm9sY2Fuby1lcGlkZW1pYy10d2VsZLXRhbWFsZQ==",
      "endpoint": "https://localhost:10909/jwt",
      "jwtHeaderName": "userpolicy",
      "useTls": true,
      "caPath": "/etc/proxy/tls/sidecar/ca.crt",
      "certPath": "/etc/proxy/tls/sidecar/server.crt",
      "keyPath": "/etc/proxy/tls/sidecar/server.key",
      "insecureSkipVerify": true
    },
    "envoy_jwt_authn": {
      "providers": {
        "greymatter": {
          "issuer": "greymatter.io",
          "from_headers": [
            {
              "name": "userpolicy"
            }
          ],
          "payload_in_metadata": "claims",
          "local_jwks": {
            "inline_string": "{'keys':[{'crv': 'P-521','kid': '1','kty': 'EC','x': 'DxZd8I_IS4Am6jfjKNaqsAxWfxhweN6I081jLgq6hTL-qlReYXd62kH3v-chAWtqWKILz1CM-reeh5hlZ3qsDf4','y': 'AWs6sDyue4kBEM90K7IVweZ674QIyn4hEqPvsxZpGVAKoE466MdhCVI7RxceNGGxXtVa3zevbnP1Grju-DymFkVl'}]}"
          }
        }
      },
      "rules": [
        {
          "match": {
            "prefix": "/"
          },
          "requires": {
            "provider_name": "greymatter"
          }
        }
      ]
    },
    "envoy_rbac": {
      "rules": {
        "action": 0,
        "policies": {
          "greymatter-developer": {
            "permissions": [
              {
                "any": true
              }
            ],
            "principals": [
              {
                "metadata": {
                  "filter": "envoy.filters.http.jwt_authn",
                  "path": [
                    {
                      "key": "claims"
                    },
                    {
                      "key": "email"
                    }
                  ],
                  "value": {
                    "string_match": {
                      "suffix": "greymatter.io"
                    }
                  }
                }
              }
            ]
          },
          "admin_dn": {
            "permissions": [
              {
                "any": true
              }
            ],
            "principals": [
              {
                "header": {
                  "name": "user_dn",
                  "exact_match": "CN=quickstart,OU=Engineering,O=Decipher Technology Studios,L=Alexandria,ST=Virginia,C=US"
                }
              }
            ]
          },
          "anonymous": {
            "permissions": [
              {
                "header": {
                  "name": ":method",
                  "exact_match": "GET"
                }
              }
            ],
            "principals": [
              {
                "any": true
              }
            ]
          }
        }
      }
    }
  }
```
