Skip to content

Commit

Permalink
Add api key support to python client + server
Browse files Browse the repository at this point in the history
  • Loading branch information
sverhoeven committed Aug 14, 2024
1 parent 4dc8b6b commit 2bf549e
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 5 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,21 +68,21 @@ If the port is different, you can pass the port as the `image_port` argument to
Given you have a model class called `MyModel` in a package `mypackage` then the web service can be started with the following command.

```shell
BMI_MODULE=mypackage BMI_CLASS=MyModel run-bmi-server
BMI_MODULE=mypackage BMI_CLASS=MyModel BMI_API_KEY=somesecret run-bmi-server
```

For example [leakybucket](https://github.com/eWaterCycle/leakybucket-bmi):

```shell
pip install leakybucket
BMI_MODULE=leakybucket.leakybucket_bmi BMI_CLASS=LeakyBucketBmi run-bmi-server
BMI_MODULE=leakybucket.leakybucket_bmi BMI_CLASS=LeakyBucketBmi BMI_API_KEY=somesecret run-bmi-server
```

and the client can connect to it with the following code.

```python
> from remotebmi.client.client import RemoteBmiClient
> client = RemoteBmiClient('http://localhost:50051')
> client = RemoteBmiClient('http://localhost:50051', api_key='somesecret')
> client.get_component_name()
leakybucket
```
Expand Down
9 changes: 9 additions & 0 deletions openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ info:
servers:
- url: http://localhost:50051
description: Default URL for a BMI service
security:
# TODO allow server in anonymous or apikey mode
# - {}
- apikey: []
tags:
- name: IRF
description: Initialize, run, finalize
Expand Down Expand Up @@ -1264,3 +1268,8 @@ components:
of the problem.
It may or may not yield further information if dereferenced.
additionalProperties: true
securitySchemes:
apikey:
type: apiKey
name: X-Auth
in: header
7 changes: 5 additions & 2 deletions python/remotebmi/client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@


class RemoteBmiClient(Bmi):
def __init__(self, base_url):
self.client = Client(base_url=base_url)
def __init__(self, base_url, api_key=None):
headers = {}
if api_key:
headers["X-Auth"] = api_key
self.client = Client(base_url=base_url, headers=headers)

def __del__(self):
self.client.close()
Expand Down
3 changes: 3 additions & 0 deletions python/remotebmi/server/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ def make_app(model: Bmi):
async def lifespan_handler(app: ConnexionMiddleware) -> AsyncIterator: # noqa: ARG001
yield {"model": model}

if environ.get("BMI_API_KEY", None):
environ["APIKEYINFO_FUNC"] = "remotebmi.server.auth.apikey_auth"

app = AsyncApp(
"remotebmi.server",
strict_validation=True,
Expand Down
11 changes: 11 additions & 0 deletions python/remotebmi/server/auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from os import environ

from connexion.exceptions import OAuthProblem


def apikey_auth(token):
valid_key = environ.get("BMI_API_KEY")
if token != valid_key:
msg = "Invalid token"
raise OAuthProblem(msg)
return {"sub": "apikeyuser"}

0 comments on commit 2bf549e

Please sign in to comment.