Skip to content

Commit

Permalink
TheGraph Auth-Layer-Proxy (#43)
Browse files Browse the repository at this point in the history
Signed-off-by: Alfredo Gutierrez <[email protected]>
  • Loading branch information
AlfredoG87 authored Mar 28, 2024
1 parent db748f6 commit 142ba47
Show file tree
Hide file tree
Showing 17 changed files with 1,124 additions and 0 deletions.
50 changes: 50 additions & 0 deletions .github/workflows/proxy-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Auth Layer Proxy Tests

on:
pull_request:
branches: [ main, release/**]
push:
branches: [ main, release/*]
tags: [ v* ]

jobs:
proxy-tests:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3

- name: Install Lua
uses: leafo/gh-actions-lua@v8
with:
luaVersion: '5.3'

- name: Install LuaRocks
uses: leafo/gh-actions-luarocks@v4

- name: Install lunatest
run: luarocks install lunatest

- name: Install luacov
run: luarocks install luacov

- name: Install luacov-console
run: luarocks install luacov-console

- name: Install cjson
run: luarocks install lua-cjson

- name: Install luasocket
run: luarocks install luasocket

- name: Run tests
run: lua test.lua
working-directory: auth-layer-proxy/tests

- name: Generate coverage report
run: luacov
working-directory: auth-layer-proxy/tests

- name: Generate Console Report
run: luacov-console ../filters/ && luacov-console ../filters/ -s && luacov-console ../filters/ -s > coverage.txt
working-directory: auth-layer-proxy/tests
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,7 @@ charts/auth-layer-server/Chart.lock

# DS_Store
.DS_Store
auth-layer-proxy/tests/coverage.txt
auth-layer-proxy/tests/luacov.report.out
auth-layer-proxy/tests/luacov.report.out.index
auth-layer-proxy/tests/luacov.stats.out
13 changes: 13 additions & 0 deletions auth-layer-proxy/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FROM envoyproxy/envoy:v1.28-latest

# Copy the Filter Scripts
COPY /filters/ /filters/

# Install Lua and Luarocks
RUN apt-get update && apt-get install -y lua5.1 luarocks git

# Install Lua modules
RUN luarocks install lua-cjson

# Install http socket module
RUN luarocks install luasocket
189 changes: 189 additions & 0 deletions auth-layer-proxy/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
# Readme

This is a token verification auth-layer-proxy for Hedera-The-Graph implementation that will allow a node operator to publish a secured `admin port` of the-graph deployment for Hedera.

Uses EnvoyProxy as a reverse proxy that handles the token verification. The token is verified using the OAuth 2.0 token server and the token claims are validated for the required roles and subgraph access.

```mermaid
---
title: Overall Architecture
---
flowchart LR
A[Graph Cli] --->|1. Create / Deploy Subgraph| B(Auth-Layer)
B ---> | 4. Relay Request on Admin Port| F(TheGraph Service)
B --> | 3. 401 Unauthorized | A
F ---> | 5. response| B --> | 6. response| A
B <--> | 2. Check Token| db[(Database)]
linkStyle 2 stroke:#ff0000,stroke-width:2px;
linkStyle 3 stroke:#00ff00,stroke-width:2px;
linkStyle 4 stroke:#00ff00,stroke-width:2px;
```
More information on the **Authorization Layer** can be found [here](https://github.com/hashgraph/hedera-the-graph/blob/main/docs/design/auth-layer.md)

## Overview

This is an implementation of EnvoyProxy filters for authentication and authorization. It is a custom config with http filters using Lua scripts for performing the following actions:

1. JSON Validation
2. Token Extraction
4. Payload Params Extraction
5. Token Validation using JWT and Instrospect endpoint
6. Proxy Routing Configuration (using EnvoyProxy itself)

it includes a Dockerfile for building the image and a docker-compose file for running the container.

## Pre-requisites

### OAUTH 2.0 Token Server
This auth-token validation proxy layer relies on an OAuth 2.0 token server for token issuace and validation. The token server should be able to issue and validate the token using the `client_id` and `client_secret` provided in the `.env` file.

So make sure to have a token server running that is previously configured with a Client ID and Client Secret, and the `/token` and `/token/introspection` endpoints are accessible.

### Token structure

Make sure that the access token has the following claims:
- realm_access.roles: A list of roles that the user has. The roles are used to determine the access level of the user.
- subgraph_access: A list of subgraph names that the user has access to. The subgraph names are used to determine the access level of the user.
- active: A boolean value that indicates if the user is active or not.
- email_verified: A boolean value that indicates if the user's email is verified or not.
- email: The email of the user.

```json
{
"exp": 1711427468,
"iat": 1711391468,
"jti": "2fab170f-beb1-4821-acb4-ac19a71c9abe",
"iss": "http://host.docker.internal:8080/realms/HederaTheGraph",
"aud": "account",
"sub": "f60ffb03-d17f-4aa2-a34a-2c4891059c3c",
"typ": "Bearer",
"azp": "htg-auth-layer",
"session_state": "79fbb78a-3279-463e-8ee0-6ab37e06bcc2",
"acr": "1",
"allowed-origins": [
"/*"
],
"realm_access": {
"roles": [
"default-roles-hederathegraph",
"subgraph_remove",
"subgraph_create",
"subgraph_deploy",
"offline_access",
"uma_authorization",
"subgraph_resume",
"subgraph_pause"
]
},
"scope": "profile subgraph_access email",
"subgraph_access": "<CSV of subgraph names>",
"email_verified": true,
"active": true,
"email": "[email protected]",
"client_id": "htg-auth-layer"
}
```

For instructions on how to set-up the Auth Provider using KeyCloak, refer to the `Auth-Layer-Server` [README](https://github.com/hashgraph/hedera-the-graph/tree/main/charts/auth-layer-server)

## Usage

### Build the image

```bash

docker build -t envoy-auth-proxy .

```

### Configure the environment

Add Postgres or Redis credentials to the .env file

```
# OAuth
CLIENT_ID=<clientId>
CLIENT_SECRET=<client_secret>
TOKEN_INTROSPECTION_URL=http://host.docker.internal:8080/realms/HederaTheGraph/protocol/openid-connect/token/introspect
```

### Configure the details of the service to be proxied on the envoy.yam
Edit `envoy-auth.yaml` file with config needs, by default will be proxying/relaying the request to address: `host.docker.internal` and port `8020`

```yaml
clusters:
- name: local_service
connect_timeout: 5s
type: LOGICAL_DNS
load_assignment:
cluster_name: local_service
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: host.docker.internal
port_value: 8020
```
### Run the container
**Start the container:**
```bash
docker-compose up
```

### Test the service

```bash
curl --location 'http://localhost:10000' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer 12345' \
--data '{
"jsonrpc": "2.0",
"id": "2",
"method": "deploy_subgraph",
"params": {
"name": "test"
}
}'
```


## Testing

The tests are written using lunatest and can be run using the following command:

Make sure to have installed the following prerequisites:
1. lua
2. luarocks

Install the following luarocks packages:

```bash
luarocks install lua-cjson
luarocks install luasocket
luarocks install lunatest
luarocks install luacov
luarocks install luacov-console
```

Open a terminal and navigate to the folder containing the `tests` folder and run the following command:

```bash
lua test.lua
```

to show the coverage report, run the following command:

```bash
luacov
luacov-console ../filters/
luacov-console ../filters/ -s
```
49 changes: 49 additions & 0 deletions auth-layer-proxy/configs/envoy-auth.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
static_resources:
listeners:
- name: listener_0
address:
socket_address:
address: 0.0.0.0
port_value: 10000
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: edge
http_filters:
- name: envoy.filters.http.lua
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua
default_source_code:
filename: /filters/TokenVerificationFilter.lua

- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
route_config:
virtual_hosts:
- name: all_domains
domains: ["*"]
routes:
- match:
prefix: "/"
headers:
name: ":method"
exact_match: "POST"
route:
cluster: local_service

clusters:
- name: local_service
connect_timeout: 5s
type: LOGICAL_DNS
load_assignment:
cluster_name: local_service
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: host.docker.internal
port_value: 8020
16 changes: 16 additions & 0 deletions auth-layer-proxy/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
version: '3'

services:
envoy:
image: envoy-auth-layer:latest
command: -c /configs/envoy-auth.yaml
env_file:
- .env
volumes:
- ./configs/:/configs/
- ./filters/:/filters/
ports:
- "9901:9901"
- "10000:10000"
stdin_open: true
tty: true
4 changes: 4 additions & 0 deletions auth-layer-proxy/example.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# OAuth
CLIENT_ID=htg-auth-layer
CLIENT_SECRET=0cyYtDVVbVvaZjrDViiw4p2kegTy9Q5X
TOKEN_INTROSPECTION_URL=http://host.docker.internal:8080/realms/HederaTheGraph/protocol/openid-connect/token/introspect
Loading

0 comments on commit 142ba47

Please sign in to comment.