Skip to content

Commit

Permalink
Add API auth endpoints / Kubernetes service
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexandra Anghel committed Mar 11, 2019
1 parent 8eafb57 commit e2e1f47
Show file tree
Hide file tree
Showing 5 changed files with 168 additions and 0 deletions.
3 changes: 3 additions & 0 deletions pipelines/api_auth_service/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# MorphL Auth API

Small Flask server & Kubernetes service for handling authorization for the MorphL Platform. This repository should be used as part of the [MorphL Orchestrator](https://github.com/Morphl-AI/MorphL-Orchestrator).
110 changes: 110 additions & 0 deletions pipelines/api_auth_service/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
from os import getenv

from flask import (Flask, request, jsonify)
from flask_cors import CORS

from gevent.pywsgi import WSGIServer

import jwt
from datetime import datetime, timedelta

"""
Database connector
"""


"""
API class for verifying credentials and handling JWTs.
"""


class API:
def __init__(self):
self.API_DOMAIN = getenv('API_DOMAIN')
self.MORPHL_DASHBOARD_USERNAME = getenv('MORPHL_DASHBOARD_USERNAME')
self.MORPHL_DASHBOARD_PASSWORD = getenv('MORPHL_DASHBOARD_PASSWORD')
self.MORPHL_API_KEY = getenv('MORPHL_API_KEY')
self.MORPHL_API_SECRET = getenv('MORPHL_API_SECRET')
self.MORPHL_API_JWT_SECRET = getenv('MORPHL_API_JWT_SECRET')

# Set JWT expiration date at 30 days
self.JWT_EXP_DELTA_DAYS = 30

def verify_login_credentials(self, username, password):
return username == self.MORPHL_DASHBOARD_USERNAME and password == self.MORPHL_DASHBOARD_PASSWORD

def verify_keys(self, api_key, api_secret):
return api_key == self.MORPHL_API_KEY and api_secret == self.MORPHL_API_SECRET

def generate_jwt(self):
payload = {
'iss': self.API_DOMAIN,
'sub': self.MORPHL_API_KEY,
'iat': datetime.utcnow(),
'exp': datetime.utcnow() + timedelta(days=self.JWT_EXP_DELTA_DAYS),
}

return jwt.encode(payload, self.MORPHL_API_JWT_SECRET, 'HS256').decode('utf-8')

def verify_jwt(self, token):
try:
decoded = jwt.decode(token, self.MORPHL_API_JWT_SECRET)
except Exception:
return False

return (decoded['iss'] == self.API_DOMAIN and
decoded['sub'] == self.MORPHL_API_KEY)


app = Flask(__name__)
CORS(app)


@app.route("/")
def main():
return "MorphL Predictions API"


@app.route('/authorize', methods=['POST'])
def authorize():

if request.form.get('api_key') is None or request.form.get('api_secret') is None:
return jsonify(error='Missing API key or secret')

if app.config['API'].verify_keys(
request.form['api_key'], request.form['api_secret']) == False:
return jsonify(error='Invalid API key or secret')

return jsonify(token=app.config['API'].generate_jwt())


@app.route("/dashboard/login", methods=['POST'])
def authorize_login():

if request.form.get('username') is None or request.form.get('password') is None:
return jsonify(status=0, error='Missing username or password.')

if not app.config['API'].verify_login_credentials(request.form['username'], request.form['password']):
return jsonify(status=0, error='Invalid username or password.')

return jsonify(status=1, token=app.config['API'].generate_jwt())


@app.route("/dashboard/verify-token", methods=['GET'])
def verify_token():

if request.headers.get('Authorization') is None or not app.config['API'].verify_jwt(request.headers['Authorization']):
return jsonify(status=0, error="Token invalid.")
return jsonify(status=1)


if __name__ == '__main__':
app.config['API'] = API()
if getenv('DEBUG'):
app.config['DEBUG'] = True
flask_port = 5858
app.run(host='0.0.0.0', port=flask_port)
else:
app.config['DEBUG'] = False
flask_port = 6868
WSGIServer(('', flask_port), app).serve_forever()
35 changes: 35 additions & 0 deletions pipelines/api_auth_service/auth_kubernetes_deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: auth-deployment
labels:
run: auth
namespace: default
spec:
replicas: 2
selector:
matchLabels:
run: auth
template:
metadata:
labels:
run: auth
spec:
containers:
- name: auth
image: pythoncontainer
command: ["bash", "/opt/auth/runapi.sh"]
imagePullPolicy: Never
ports:
- containerPort: 6868
protocol: TCP
envFrom:
- configMapRef:
name: environment-configmap
volumeMounts:
- name: opt-auth
mountPath: /opt/auth
volumes:
- name: opt-auth
hostPath:
path: /opt/auth
15 changes: 15 additions & 0 deletions pipelines/api_auth_service/auth_kubernetes_service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
apiVersion: v1
kind: Service
metadata:
name: auth-service
labels:
run: auth
namespace: default
spec:
type: LoadBalancer
ports:
- port: 80
protocol: TCP
targetPort: 6868
selector:
run: auth
5 changes: 5 additions & 0 deletions pipelines/api_auth_service/runapi.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
cp -r /opt/auth /opt/code
cd /opt/code
git pull
python /opt/code/api.py

0 comments on commit e2e1f47

Please sign in to comment.