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.

Key Components

Filter

Description

Configuration

gm.inheaders

Set up request headers from certificates to allow authorization actions

gm.ensurevariables

Ensure headers/cookies/query strings are present at needed locations.

gm.jwtsecurity

Establish JWT token for user/service in request for later Authz.

gm.listauth

Apply whitelist or blacklist authentication based on USER_DN header field.

envoy.jwt_authn

Authorize requests to route/method based on user/role

envoy.rbac

Authorize requests to route/method based on user/role

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 onspiffe://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

  "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.

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

  "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

  "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
              }
            ]
          }
        }
      }
    }
  }

Last updated

Was this helpful?