# Reuni Server

Reuni Server is a core in reuni system, this server created following REST API standards. We created the server to handle every business logic and process, and also provide a security system. The server is coded in Golang and created to be stateless and disposable server.

## **Functionality:**

* Provide Authentication
* Provide Authorization max at Service Level using User-Group Access Control
* Provide a CRUD for services, namespaces and configurations
* Provide a Agent-sync handler

### Authentication

To support statelessness in reuni server, we decided to use [JWT](https://jwt.io) as our token-based authentication with RS256 (RSA + SHA256) digital signature algorithm. The token will be saved by user and look like this:

{% tabs %}
{% tab title="Encoded" %}
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwibmFtZSI6Iktlbm5ldGggSGFsaW0iLCJ1c2VybmFtZSI6ImthbmlzaXVza2VubmV0aCIsImVtYWlsIjoia2VubmV0aEBnby1zcXVhZHMuY29tIiwiaWF0IjoxNTMzMTExNTg5NTUzfQ.F1SUGY85lZhsK4lIFcceecjsRsagiqEiI3joRMNCP8aswvpDTwJ9wSaEyf59r6CO7AwEeW-5ZlwCev8O9NIFAg
{% endtab %}

{% tab title="Decoded" %}
{"alg":"RS256","typ":"JWT"}

{"id":1,"name":"Kenneth Halim","username":"kanisiuskenneth","email":"<kenneth@go-squads.com>","iat":1533111589553}

Sh1woOoxqNhspF8BIdrdGg7f6i9Yhp8BhoVjy67g6\_7lk-jSsRSR2LV\_mylYKzRpSn6GzGwRNBhuAtI1IfSzfw
{% endtab %}
{% endtabs %}

And the RSA Key used in our system need to follow PEM format and look like this:

{% tabs %}
{% tab title="Public Key" %}
\-----BEGIN RSA PUBLIC KEY-----&#x20;

MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMuMh/1/Qpi2ORGiCG6TLi4kULPU5qkh FQ20hK/77UY8mmpgsntFM/UVc54DvhkrNACjYUjEJUF6pgqdTXORFV8CAwEAAQ==&#x20;

\-----END RSA PUBLIC KEY-----
{% endtab %}

{% tab title="PrivateKey" %}
\-----BEGIN RSA PRIVATE KEY-----

MIIBOgIBAAJBAMuMh/1/Qpi2ORGiCG6TLi4kULPU5qkhFQ20hK/77UY8mmpgsntF M/UVc54DvhkrNACjYUjEJUF6pgqdTXORFV8CAwEAAQJAPjhB5YI+GDIzdaljDHHe ..........

\-----END RSA PRIVATE KEY-----
{% endtab %}
{% endtabs %}

### Authorization

Authorization will check for every service accessed by both user and agent. We authorize user with the user-group that he/she become a part of, basically we use a modified Role-Based Access Control (RBAC). For the agent we authorize it using authorization token which is a random byte stream encoded with base64 that can be copied by user and paste it in reuni agent environment.

### **Versioning**

In our system, configuration that saved are immutable, and to change it the user need to create new version of the configuration. Current versioning method is by using serial number as its identifier that always increment by 1. User cannot rolled back the configuration to specific version, the only way to achieve roll-back is by create new version with the exact same configuration. This are chosen for better accountability and audit trailing.

### **Audit Trail**

Audit trailing supported along with versioning, each configuration version created, we will save who create it to provide better accountability.

### Secret Handling

Handling secret are the hardest thing we can think of, we haven't decided yet how to handle secret. Probably the best way is to use Hashicorp Vault to save encryption key.

## API Specification

### Authentication Middleware

Every user endpoints are guarded by authentication middleware which fetch user token from HTTP Header:&#x20;

```typescript
Authorization: Bearer <jwt_token> 
```

## Get Services List

<mark style="color:blue;">`GET`</mark> `reuni-server/services`

{% tabs %}
{% tab title="200 " %}

```javascript
[
    {
        "id": 2,
        "name": "service",
        "authorization_token": "",
        "created_at": "2018-07-24T04:36:36.902145Z"
    },
    {
        "id": 3,
        "name": "service2",
        "authorization_token": "",
        "created_at": "2018-07-27T05:02:10.312858Z"
    },
    {
        "id": 4,
        "name": "service3",
        "authorization_token": "",
        "created_at": "2018-08-01T04:26:28.463431Z"
    }
]
```

{% endtab %}
{% endtabs %}

## Create Services

<mark style="color:green;">`POST`</mark> `reuni-server/services`

\
Request body should be formatted as JSON

#### Request Body

| Name | Type   | Description      |
| ---- | ------ | ---------------- |
| name | string | The service name |

{% tabs %}
{% tab title="201 " %}

```
```

{% endtab %}

{% tab title="400 " %}

```
```

{% endtab %}
{% endtabs %}

## Delete Services

<mark style="color:red;">`DELETE`</mark> `reuni-server/services/{service_name}`

{% tabs %}
{% tab title="200 " %}

```
```

{% endtab %}
{% endtabs %}

## Get Namespaces List

<mark style="color:blue;">`GET`</mark> `reuni-server/services/{service_name}/namespaces`

#### Path Parameters

| Name | Type   | Description |
| ---- | ------ | ----------- |
|      | string |             |

{% tabs %}
{% tab title="200 " %}

```
[
    {
        "namespace": "default",
        "version": 1
    },
    {
        "namespace": "development",
        "version": 51
    }
]
```

{% endtab %}
{% endtabs %}

## Create Namespace

<mark style="color:green;">`POST`</mark> `reuni-server/services/namespaces`

\
Request body should be formatted as JSON

#### Request Body

| Name           | Type   | Description                                                                             |
| -------------- | ------ | --------------------------------------------------------------------------------------- |
| configurations | object | The version 1 configuration for the namespaces contain list of key value in JSON format |
| namespace      | string | Namespace name                                                                          |

{% tabs %}
{% tab title="201 " %}

```
```

{% endtab %}

{% tab title="400 " %}

```
```

{% endtab %}
{% endtabs %}

## Get Namespaces Latest Version

<mark style="color:blue;">`GET`</mark> `reuni-server/services/{service_name}/{namespace}/latest`

{% tabs %}
{% tab title="200 " %}

```
{
    "version": 51
}
```

{% endtab %}
{% endtabs %}

## Get Namespace Version for Agent

<mark style="color:blue;">`GET`</mark> `reuni-host/services/{service_name}/{namespace}/agent`

This method response exactly the same with above, but the authentication skipped and instead to verification to agent token authorization

{% tabs %}
{% tab title="200 " %}

```
{
    "version": 51
}
```

{% endtab %}
{% endtabs %}

## Get Configuration List

<mark style="color:blue;">`GET`</mark> `reuni-host/services/{service_name}/{namespace}/{version}`

Response with list of configuration that are set

{% tabs %}
{% tab title="200 " %}

```
{
    "version": 19,
    "configuration": {
        "DB_HOST": "127.0.0.1",
        "DB_PASS": "testting",
        "DB_PORT": "5432",
        "SECRET_PASS": "This is secret pass",
        "TEST_CONFIG": "Hello!!!!"
    }
}
```

{% endtab %}
{% endtabs %}

## Get Configuration List

<mark style="color:blue;">`GET`</mark> `reuni-host/services/{service_name}/{namespace}/{version}/agent`

Same as above, but designed for agent

{% tabs %}
{% tab title="200 " %}

```
{
    "version": 19,
    "configuration": {
        "DB_HOST": "127.0.0.1",
        "DB_PASS": "testting",
        "DB_PORT": "5432",
        "SECRET_PASS": "This is secret pass",
        "TEST_CONFIG": "Hello!!!!"
    }
}
```

{% endtab %}
{% endtabs %}

## Create new version for the namespace

<mark style="color:green;">`POST`</mark> `reuni-server/services/{service_name}/{namespace}`

#### Path Parameters

| Name          | Type   | Description                                                   |
| ------------- | ------ | ------------------------------------------------------------- |
| configuration | object | Configuration should contain list of key-value in JSON format |

{% tabs %}
{% tab title="201 " %}

```
```

{% endtab %}
{% endtabs %}
