Skip to content

Commit

Permalink
Merge 2314f3f into 6ea37ff
Browse files Browse the repository at this point in the history
  • Loading branch information
akariv committed Mar 10, 2016
2 parents 6ea37ff + 2314f3f commit 02f4995
Show file tree
Hide file tree
Showing 13 changed files with 350 additions and 53 deletions.
25 changes: 22 additions & 3 deletions conductor/blueprints/authentication/blueprint.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
from flask import Blueprint
import os
from flask import Blueprint, request, url_for
from flask.ext.jsonpify import jsonpify

from . import controllers

os_conductor = os.environ.get('OS_EXTERNAL_ADDRESS')


def create():
"""Create blueprint.
Expand All @@ -9,11 +14,25 @@ def create():
# Create instance
blueprint = Blueprint('authentication', 'authentication')

# Controller Proxies
check_controller = controllers.Check()
callback_controller = controllers.Callback()

def check():
token = request.values.get('jwt')
next_url = request.args.get('next', None)
callback_url = 'http://'+os_conductor+url_for('.callback')
return jsonpify(check_controller(token, next_url, callback_url))

def callback():
state = request.args.get('state')
return callback_controller(state)

# Register routes
blueprint.add_url_rule(
'check', 'check', controllers.Check(), methods=['GET'])
'check', 'check', check, methods=['GET'])
blueprint.add_url_rule(
'google_callback', 'callback', controllers.Callback(), methods=['GET'])
'google_callback', 'callback', callback, methods=['GET'])

# Return blueprint
return blueprint
22 changes: 9 additions & 13 deletions conductor/blueprints/authentication/controllers.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import os
import requests
import datetime
import logging

try:
import urllib.parse as urlparse
except ImportError:
import urlparse
import jwt

from flask import request, url_for, redirect
from flask.ext.jsonpify import jsonpify
from flask import redirect
from flask_oauthlib.client import OAuth, OAuthException

from .models import create_or_get_user, get_user
Expand All @@ -20,7 +19,6 @@ def readfile_or_default(filename, default):
return open(filename).read().strip()
except IOError:
return default
os_conductor = os.environ.get('OS_EXTERNAL_ADDRESS')

PRIVATE_KEY = readfile_or_default('/secrets/private.pem', 'private key stub')
GOOGLE_KEY = readfile_or_default('/secrets/google.key', 'google consumer key')
Expand Down Expand Up @@ -65,8 +63,7 @@ class Check:

# Public

def __call__(self):
token = request.values.get('jwt')
def __call__(self, token, next, callback_url):
if token is not None:
try:
token = jwt.decode(token, PRIVATE_KEY)
Expand All @@ -85,11 +82,9 @@ def __call__(self):
'avatar_url': user.avatar_url
}
}
return jsonpify(ret)
return ret

# Otherwise - not authenticated
callback = 'http://'+os_conductor+url_for('.callback')
next = request.args.get('next', None)
provider = 'google'
state = {
'next': next,
Expand All @@ -99,7 +94,7 @@ def __call__(self):
}
state = jwt.encode(state, PRIVATE_KEY)
google_login_url = google_remote_app()\
.authorize(callback=callback, state=state).headers['Location']
.authorize(callback=callback_url, state=state).headers['Location']

ret = {
'authenticated': False,
Expand All @@ -110,7 +105,7 @@ def __call__(self):
}
}

return jsonpify(ret)
return ret


class Callback:
Expand All @@ -119,18 +114,19 @@ class Callback:

# Public

def __call__(self):
def __call__(self, state):
resp = google_remote_app().authorized_response()
if isinstance(resp, OAuthException):
logging.log(logging.WARN, "OAuthException: %r" % resp)
resp = None

state = request.args.get('state')
try:
state = jwt.decode(state, PRIVATE_KEY)
except jwt.InvalidTokenError:
state = None

next_url = '/'
provider = None
if state is not None:
provider = state.get('provider')
next_url = state.get('next', next_url)
Expand Down
13 changes: 11 additions & 2 deletions conductor/blueprints/authorization/blueprint.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from flask import Blueprint
from flask import Blueprint, request
from flask.ext.jsonpify import jsonpify
from . import controllers


Expand All @@ -9,9 +10,17 @@ def create():
# Create instance
blueprint = Blueprint('authorization', 'authorization')

# Controller Proxies
check_controller = controllers.Check()

def check():
token = request.values.get('jwt')
service = request.values.get('service')
return jsonpify(check_controller(token, service))

# Register routes
blueprint.add_url_rule(
'check', 'check', controllers.Check(), methods=['GET'])
'check', 'check', check, methods=['GET'])
blueprint.add_url_rule(
'public-key', 'public-key', controllers.PublicKey(), methods=['GET'])
blueprint.add_url_rule(
Expand Down
49 changes: 40 additions & 9 deletions conductor/blueprints/authorization/controllers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@
import urlparse # silence pyflakes
import jwt

from flask import request, make_response
from flask.ext.jsonpify import jsonpify
from flask import make_response

from .models import get_permission

Expand All @@ -19,8 +18,42 @@ def readfile_or_default(filename, default):
return default
os_conductor = os.environ.get('OS_EXTERNAL_ADDRESS')

PUBLIC_KEY = readfile_or_default('/secrets/public.pem', 'public key stub')
PRIVATE_KEY = readfile_or_default('/secrets/private.pem', 'private key stub')
PUBLIC_KEY = readfile_or_default('/secrets/public.pem', '''-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzSrV/SxRNKufc6f0GQIu
YMASgBCOiJW5fvCnGtVMIrWvBQoCFAp9QwRHrbQrQJiPg6YqqnTvGhWssL5LMMvR
8jXXOpFUKzYaSgYaQt1LNMCwtqMB0FGSDjBrbmEmnDSo6g0Naxhi+SJX3BMcce1W
TgKRybv3N3F+gJ9d8wPkyx9xhd3H4200lHk4T5XK5+LyAPSnP7FNUYTdJRRxKFWg
ZFuII+Ex6mtUKU9LZsg9xeAC6033dmSYe5yWfdrFehmQvPBUVH4HLtL1fXTNyXuz
ZwtO1v61Qc1u/j7gMsrHXW+4csjS3lDwiiPIg6q1hTA7QJdB1M+rja2MG+owL0U9
owIDAQAB
-----END PUBLIC KEY-----''')
PRIVATE_KEY = readfile_or_default('/secrets/private.pem', '''-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAzSrV/SxRNKufc6f0GQIuYMASgBCOiJW5fvCnGtVMIrWvBQoC
FAp9QwRHrbQrQJiPg6YqqnTvGhWssL5LMMvR8jXXOpFUKzYaSgYaQt1LNMCwtqMB
0FGSDjBrbmEmnDSo6g0Naxhi+SJX3BMcce1WTgKRybv3N3F+gJ9d8wPkyx9xhd3H
4200lHk4T5XK5+LyAPSnP7FNUYTdJRRxKFWgZFuII+Ex6mtUKU9LZsg9xeAC6033
dmSYe5yWfdrFehmQvPBUVH4HLtL1fXTNyXuzZwtO1v61Qc1u/j7gMsrHXW+4csjS
3lDwiiPIg6q1hTA7QJdB1M+rja2MG+owL0U9owIDAQABAoIBAHgA7ytniZQSMnDW
szsRgIkMr4WCqawQT3CFWGikjCTdOiLraK3KONxDG53pfUcKNR9eySPsw5HxTZIP
rDE9dm6CuYJDUQT5X0Ue7qtffsa7UmFxVPVBUPnFroDgiFHjp01HFysmF3X7dYJ/
Fys4FDwK2rUxoXcnhkO7c5taErAPhpmv+QncVBkouQ3bB78av6cHdQfo+7PcvYRP
x6iDPAjMpz1wF1Fkd9mSHadjuqlC3FubbwEK5nTuSl4nPULK7KaCv9NjxyzTUi23
DWk9QCv+peIK/1h75cbB9eVvZayHlFlVNtD7Mrx5rediWABSqvNLRv/aZ0/o5+FM
1cxiYPECgYEA9AEr60CPlW9vBOacCImnWHWEH/UEwi4aNTBxpZEWRuN0HnmB+4Rt
1b+7LoX6olVBN1y8YIwzkDOCVblFaT+THBNiE7ABwB87c0jYd2ULQszqrebjXPoz
8q7MqghD+4iDfvP2QmivpadfeGGzYFI49b7W5c/Iv4w0oWgutib+hDsCgYEA10Dk
hMwg61q6YVAeTIqnV7zujfzTIif9AkePAfNLolLdn0Bx5LS6oPxeRUxyy4mImwrf
p6yZGOX/7ocy7rQ3X/F6fuxwuGa74PNZPwlLuD7UUPr//OPuQihoDKvL+52XWA5U
Q09sXK+KlvuH4DJ5UsHC9kgATyuGNUOeXYBHHbkCgYEA78Zq8x2ZOz6quQUolZc3
dEzezkyHJY4KQPRe6VUesAB5riy3F4M2L5LejMQp2/WtRYsCrll3nh+P109dryRD
GpbNjQ0rWzEVyZ7u4LzRiQ43GzbFfCt+et9czUWcEIRAu7Ne7jlTSZSk03Ymv+Ns
h8jGAkTiP6C2Y1oudN7ywtsCgYBAWIa3Z+oDUQjcJD4adWxW3wSU71oSINASSV/n
nloiuRDFFVe2nYwYqbhokNTUIVXzuwlmr0LI3aBnJoVENB1FkgMjQ/ziMtvBAB3S
qS24cxe26YFykJRdtIR+HTEKE271hLsNsAVdo6ATSDey/oOkCIYGZzmocQNaks8Z
dkpMCQKBgQCfZ75r1l/Hzphb78Ygf9tOz1YUFqw/xY9jfufW4C/5SgV2q2t/AZok
LixyPP8SzJcH20iKdc9kS7weiQA0ldT2SYv6VT7IqgQ3i/qYdOmaggjBGaIuIB/B
QZOJBnaSMVJFf/ZO1/1ilGVGfZZ3TMOA1TJlcTZisk56tRTbkivL9Q==
-----END RSA PRIVATE KEY-----''')
LIBJS = readfile_or_default(os.path.join(os.path.dirname(__file__),
'lib',
'lib.js'),
Expand All @@ -33,9 +66,7 @@ class Check:

# Public

def __call__(self):
token = request.values.get('jwt')
service = request.values.get('service')
def __call__(self, token, service):
if token is not None and service is not None:
try:
token = jwt.decode(token, PRIVATE_KEY)
Expand All @@ -58,12 +89,12 @@ def __call__(self):
token = jwt.encode(ret, PRIVATE_KEY, algorithm='RS256')\
.decode('ascii')
ret['token'] = token
return jsonpify(ret)
return ret

ret = {
'permissions': {}
}
return jsonpify(ret)
return ret


class PublicKey:
Expand Down
17 changes: 15 additions & 2 deletions conductor/blueprints/datastore/blueprint.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from flask import Blueprint
import json

from flask import Blueprint, request, Response
from . import controllers


Expand All @@ -9,9 +11,20 @@ def create():
# Create instase
blueprint = Blueprint('datastore', 'datastore')

# Controller proxies
authorize_controller = controllers.Authorize()

def authorize():
auth_token = request.headers.get('Auth-Token')
try:
req_payload = json.loads(request.data.decode())
return authorize_controller(auth_token, req_payload)
except json.JSONDecodeError:
return Response(status=400)

# Register routes
blueprint.add_url_rule(
'/', 'authorize', controllers.Authorize(), methods=['POST'])
'/', 'authorize', authorize, methods=['POST'])

# Return blueprint
return blueprint
6 changes: 2 additions & 4 deletions conductor/blueprints/datastore/controllers.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,11 @@ def __init__(self):
self.__bucket = self.__connection.get_bucket(
config.OPENSPENDING_STORAGE_BUCKET_NAME)

def __call__(self):

def __call__(self, auth_token, req_payload):
# Verify client, deny access if not verified
auth_token = request.headers.get('Auth-Token')

try:
# Get request payload
req_payload = json.loads(request.data.decode())
owner = req_payload.get('metadata', {}).get('owner')
dataset_name = req_payload.get('metadata', {}).get('name')
if owner is None or dataset_name is None:
Expand Down Expand Up @@ -79,6 +76,7 @@ def __call__(self):

except Exception as exception:

raise
# TODO: use logger
# Log bad request exception
print('Bad request: {0}'.format(exception))
Expand Down
Empty file.
21 changes: 21 additions & 0 deletions tests/module/blueprints/authentication/test_blueprint.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import unittest
try:
from unittest.mock import Mock, patch
except ImportError:
from mock import Mock, patch
from importlib import import_module
module = import_module('conductor.blueprints.authentication.blueprint')


class createTest(unittest.TestCase):

# Actions

def setUp(self):
self.addCleanup(patch.stopall)
self.controllers = patch.object(module, 'controllers').start()

# Tests

def test(self):
self.assertTrue(module.create())
Loading

0 comments on commit 02f4995

Please sign in to comment.