-
Notifications
You must be signed in to change notification settings - Fork 24
/
server.py
147 lines (124 loc) · 4.26 KB
/
server.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import os
import logging
import uuid
import vakt.rules.net
import vakt.rules.string
import vakt.checker
from vakt.storage.mongo import MongoStorage, Migration0To1x1x0, Migration1x1x0To1x1x1
from vakt.storage.memory import MemoryStorage
from vakt.effects import DENY_ACCESS, ALLOW_ACCESS
from vakt.policy import Policy
from vakt.guard import Guard, Inquiry
from flask import Flask, request, session
from pymongo import MongoClient
# Set up vakt #
# ============================= #
# First of all we need to create Policies for our book library.
# They can be added at any time via Storage.
# Here comes the list of Policies:
policies = [
Policy(
uid=str(uuid.uuid4()),
description="Allow everyone to log-in",
effect=ALLOW_ACCESS,
subjects=['<.*>'],
resources=['<.*>'],
actions=['login'],
),
Policy(
uid=str(uuid.uuid4()),
description="""
Allow all readers of the book library whose surnames start with M get and read any book or magazine,
but only when they connect from local library's computer
""",
effect=ALLOW_ACCESS,
subjects=['<[\w]+ M[\w]+>'],
resources=('library:books:<.+>', 'office:magazines:<.+>'),
actions=['<read|get>'],
rules={
'ip': vakt.rules.net.CIDRRule('127.0.0.1/32'),
},
),
Policy(
uid=str(uuid.uuid4()),
description='Allow mr. Rooney and ms. Sparrow to do anything with the books',
effect=ALLOW_ACCESS,
subjects=('Edward Rooney', 'Florence Sparrow'),
actions=['<.*>'],
resources=['<.*>'],
rules={
'secret': vakt.rules.string.RegexMatchRule('[Ii]-am-a-teacher'),
},
),
Policy(
uid=str(uuid.uuid4()),
description='Disallow Ferris Bueller to do anything inside library. Even to log-in',
effect=DENY_ACCESS,
subjects=['Ferris Bueller'],
actions=['<.*>'],
resources=['<.*>'],
),
]
# Instantiate a global instance of Vakt guard.
# You can use local if you wish.
guard = None
def init():
# Here we instantiate the Policy Storage.
# In this case it's Memory or MongoDB Storage, but we can opt to SQL Storage, any other third-party storage, etc.
if os.environ.get('STORAGE') == 'mongo':
user, password, host = 'root', 'example', 'localhost:27017'
uri = 'mongodb://%s:%s@%s' % (user, password, host)
st = MongoStorage(MongoClient(host=host), 'vakt_db', collection='vakt_policies')
# We run migrations.
migrations = (Migration0To1x1x0(st), Migration1x1x0To1x1x1(st))
for m in sorted(migrations, key=lambda x: x.order):
m.up()
else:
st = MemoryStorage()
# And persist all our Policies so that to start serving our library.
for p in policies:
st.add(p)
# Create global guard instance
global guard
guard = Guard(st, vakt.checker.RegexChecker())
# Set up logger.
root = logging.getLogger()
root.setLevel(logging.INFO)
root.addHandler(logging.StreamHandler())
# Running server #
# ============================= #
# Let's serve our book library
app = Flask(__name__)
Flask.secret_key = os.urandom(24)
@app.route('/')
def hello():
return "Welcome to Online Book Library!"
@app.route('/login', methods=['POST'])
def login():
user = request.form['name']
inquiry = Inquiry(subject=user, action='login', context={'ip': request.remote_addr})
if guard.is_allowed(inquiry):
# check password here
session['fullname'] = user
session['secret'] = request.form.get('secret', '')
return "You've been logged-in", 200
else:
return "Go away, you violator!", 401
@app.route('/books/<action>/<book>')
def serve_book(action, book):
inquiry = Inquiry(
subject=session.get('fullname'),
action=action,
resource='library:books:%s' % book,
context={
'ip': request.remote_addr,
'secret': session.get('secret', '')
}
)
if guard.is_allowed(inquiry):
return "Enjoy! Here is the book you requested: '{}'!".format(book), 200
else:
return 'Sorry, but you are not allowed to do this!', 401
if __name__ == '__main__':
init()
app.run(debug=True)