-
Notifications
You must be signed in to change notification settings - Fork 36
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add API auth endpoints / Kubernetes service
- Loading branch information
Alexandra Anghel
committed
Mar 11, 2019
1 parent
8eafb57
commit e2e1f47
Showing
5 changed files
with
168 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
35
pipelines/api_auth_service/auth_kubernetes_deployment.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
|