Skip to content

Commit 1839baa

Browse files
authored
[UI] Remove manual authentication for login user (#2635)
* Remove manual authentication * update python libraries * remove psycopg2 and bring back wal-e * remove unused vars
1 parent 1b08ee1 commit 1839baa

File tree

6 files changed

+22
-198
lines changed

6 files changed

+22
-198
lines changed

ui/operator_ui/main.py

Lines changed: 8 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,11 @@
1616
Flask,
1717
Response,
1818
abort,
19-
redirect,
2019
render_template,
2120
request,
2221
send_from_directory,
23-
session,
2422
)
2523

26-
from flask_oauthlib.client import OAuth
27-
from functools import wraps
2824
from gevent import sleep, spawn
2925
from gevent.pywsgi import WSGIServer
3026
from jq import jq
@@ -34,11 +30,9 @@
3430
from re import X, compile
3531
from requests.exceptions import RequestException
3632
from signal import SIGTERM, signal
37-
from urllib.parse import urljoin
3833

3934
from . import __version__
4035
from .cluster_discovery import DEFAULT_CLUSTERS, StaticClusterDiscoverer
41-
from .oauth import OAuthRemoteAppWithRefresh
4236

4337
from .spiloutils import (
4438
apply_postgresql,
@@ -71,11 +65,8 @@
7165
SERVER_STATUS = {'shutdown': False}
7266

7367
APP_URL = getenv('APP_URL')
74-
AUTHORIZE_URL = getenv('AUTHORIZE_URL')
7568
SPILO_S3_BACKUP_BUCKET = getenv('SPILO_S3_BACKUP_BUCKET')
7669
TEAM_SERVICE_URL = getenv('TEAM_SERVICE_URL')
77-
ACCESS_TOKEN_URL = getenv('ACCESS_TOKEN_URL')
78-
TOKENINFO_URL = getenv('OAUTH2_TOKEN_INFO_URL')
7970

8071
OPERATOR_API_URL = getenv('OPERATOR_API_URL', 'http://postgres-operator')
8172
OPERATOR_CLUSTER_NAME_LABEL = getenv('OPERATOR_CLUSTER_NAME_LABEL', 'cluster-name')
@@ -184,38 +175,6 @@ def __call__(self, environ, start_response):
184175
return self.app(environ, start_response)
185176

186177

187-
oauth = OAuth(app)
188-
189-
auth = OAuthRemoteAppWithRefresh(
190-
oauth,
191-
'auth',
192-
request_token_url=None,
193-
access_token_method='POST',
194-
access_token_url=ACCESS_TOKEN_URL,
195-
authorize_url=AUTHORIZE_URL,
196-
)
197-
oauth.remote_apps['auth'] = auth
198-
199-
200-
def verify_token(token):
201-
if not token:
202-
return False
203-
204-
r = requests.get(TOKENINFO_URL, headers={'Authorization': token})
205-
206-
return r.status_code == 200
207-
208-
209-
def authorize(f):
210-
@wraps(f)
211-
def wrapper(*args, **kwargs):
212-
if AUTHORIZE_URL and 'auth_token' not in session:
213-
return redirect(urljoin(APP_URL, '/login'))
214-
return f(*args, **kwargs)
215-
216-
return wrapper
217-
218-
219178
def ok(body={}, status=200):
220179
return (
221180
Response(
@@ -297,19 +256,16 @@ def health():
297256

298257

299258
@app.route('/css/<path:path>')
300-
@authorize
301259
def send_css(path):
302260
return send_from_directory('static/', path), 200, STATIC_HEADERS
303261

304262

305263
@app.route('/js/<path:path>')
306-
@authorize
307264
def send_js(path):
308265
return send_from_directory('static/', path), 200, STATIC_HEADERS
309266

310267

311268
@app.route('/')
312-
@authorize
313269
def index():
314270
return render_template('index.html', google_analytics=GOOGLE_ANALYTICS)
315271

@@ -345,7 +301,6 @@ def index():
345301

346302

347303
@app.route('/config')
348-
@authorize
349304
def get_config():
350305
config = DEFAULT_UI_CONFIG.copy()
351306
config.update(OPERATOR_UI_CONFIG)
@@ -407,17 +362,15 @@ def get_teams_for_user(user_name):
407362

408363

409364
@app.route('/teams')
410-
@authorize
411365
def get_teams():
412366
return ok(
413367
get_teams_for_user(
414-
session.get('user_name', ''),
368+
request.headers.get('X-Uid', ''),
415369
)
416370
)
417371

418372

419373
@app.route('/services/<namespace>/<cluster>')
420-
@authorize
421374
def get_service(namespace: str, cluster: str):
422375

423376
if TARGET_NAMESPACE not in ['', '*', namespace]:
@@ -433,7 +386,6 @@ def get_service(namespace: str, cluster: str):
433386

434387

435388
@app.route('/pooler/<namespace>/<cluster>')
436-
@authorize
437389
def get_list_poolers(namespace: str, cluster: str):
438390

439391
if TARGET_NAMESPACE not in ['', '*', namespace]:
@@ -449,7 +401,6 @@ def get_list_poolers(namespace: str, cluster: str):
449401

450402

451403
@app.route('/statefulsets/<namespace>/<cluster>')
452-
@authorize
453404
def get_list_clusters(namespace: str, cluster: str):
454405

455406
if TARGET_NAMESPACE not in ['', '*', namespace]:
@@ -465,7 +416,6 @@ def get_list_clusters(namespace: str, cluster: str):
465416

466417

467418
@app.route('/statefulsets/<namespace>/<cluster>/pods')
468-
@authorize
469419
def get_list_members(namespace: str, cluster: str):
470420

471421
if TARGET_NAMESPACE not in ['', '*', namespace]:
@@ -485,7 +435,6 @@ def get_list_members(namespace: str, cluster: str):
485435

486436

487437
@app.route('/namespaces')
488-
@authorize
489438
def get_namespaces():
490439

491440
if TARGET_NAMESPACE not in ['', '*']:
@@ -503,7 +452,6 @@ def get_namespaces():
503452

504453

505454
@app.route('/postgresqls')
506-
@authorize
507455
def get_postgresqls():
508456
postgresqls = [
509457
{
@@ -602,7 +550,6 @@ def run(*args, **kwargs):
602550

603551

604552
@app.route('/postgresqls/<namespace>/<cluster>', methods=['POST'])
605-
@authorize
606553
@namespaced
607554
def update_postgresql(namespace: str, cluster: str):
608555
if READ_ONLY_MODE:
@@ -614,8 +561,8 @@ def update_postgresql(namespace: str, cluster: str):
614561

615562
postgresql = request.get_json(force=True)
616563

617-
teams = get_teams_for_user(session.get('user_name', ''))
618-
logger.info(f'Changes to: {cluster} by {session.get("user_name", "local-user")}/{teams} {postgresql}') # noqa
564+
teams = get_teams_for_user(request.headers.get('X-Uid', ''))
565+
logger.info(f'Changes to: {cluster} by {request.headers.get("X-Uid", "local-user")}/{teams} {postgresql}') # noqa
619566

620567
if SUPERUSER_TEAM and SUPERUSER_TEAM in teams:
621568
logger.info(f'Allowing edit due to membership in superuser team {SUPERUSER_TEAM}') # noqa
@@ -810,7 +757,6 @@ def update_postgresql(namespace: str, cluster: str):
810757

811758

812759
@app.route('/postgresqls/<namespace>/<cluster>', methods=['GET'])
813-
@authorize
814760
def get_postgresql(namespace: str, cluster: str):
815761

816762
if TARGET_NAMESPACE not in ['', '*', namespace]:
@@ -826,7 +772,6 @@ def get_postgresql(namespace: str, cluster: str):
826772

827773

828774
@app.route('/stored_clusters')
829-
@authorize
830775
def get_stored_clusters():
831776
return respond(
832777
read_stored_clusters(
@@ -837,7 +782,6 @@ def get_stored_clusters():
837782

838783

839784
@app.route('/stored_clusters/<pg_cluster>', methods=['GET'])
840-
@authorize
841785
def get_versions(pg_cluster: str):
842786
return respond(
843787
read_versions(
@@ -850,9 +794,7 @@ def get_versions(pg_cluster: str):
850794
)
851795

852796

853-
854797
@app.route('/stored_clusters/<pg_cluster>/<uid>', methods=['GET'])
855-
@authorize
856798
def get_basebackups(pg_cluster: str, uid: str):
857799
return respond(
858800
read_basebackups(
@@ -867,7 +809,6 @@ def get_basebackups(pg_cluster: str, uid: str):
867809

868810

869811
@app.route('/create-cluster', methods=['POST'])
870-
@authorize
871812
def create_new_cluster():
872813

873814
if READ_ONLY_MODE:
@@ -885,8 +826,8 @@ def create_new_cluster():
885826
if TARGET_NAMESPACE not in ['', '*', namespace]:
886827
return wrong_namespace()
887828

888-
teams = get_teams_for_user(session.get('user_name', ''))
889-
logger.info(f'Create cluster by {session.get("user_name", "local-user")}/{teams} {postgresql}') # noqa
829+
teams = get_teams_for_user(request.headers.get('X-Uid', ''))
830+
logger.info(f'Create cluster by {request.headers.get("X-Uid", "local-user")}/{teams} {postgresql}') # noqa
890831

891832
if SUPERUSER_TEAM and SUPERUSER_TEAM in teams:
892833
logger.info(f'Allowing create due to membership in superuser team {SUPERUSER_TEAM}') # noqa
@@ -898,7 +839,6 @@ def create_new_cluster():
898839

899840

900841
@app.route('/postgresqls/<namespace>/<cluster>', methods=['DELETE'])
901-
@authorize
902842
def delete_postgresql(namespace: str, cluster: str):
903843
if TARGET_NAMESPACE not in ['', '*', namespace]:
904844
return wrong_namespace()
@@ -910,9 +850,9 @@ def delete_postgresql(namespace: str, cluster: str):
910850
if postgresql is None:
911851
return not_found()
912852

913-
teams = get_teams_for_user(session.get('user_name', ''))
853+
teams = get_teams_for_user(request.headers.get('X-Uid', ''))
914854

915-
logger.info(f'Delete cluster: {cluster} by {session.get("user_name", "local-user")}/{teams}') # noqa
855+
logger.info(f'Delete cluster: {cluster} by {request.headers.get("X-Uid", "local-user")}/{teams}') # noqa
916856

917857
if SUPERUSER_TEAM and SUPERUSER_TEAM in teams:
918858
logger.info(f'Allowing delete due to membership in superuser team {SUPERUSER_TEAM}') # noqa
@@ -936,78 +876,30 @@ def proxy_operator(url: str):
936876

937877

938878
@app.route('/operator/status')
939-
@authorize
940879
def get_operator_status():
941880
return proxy_operator('/status/')
942881

943882

944883
@app.route('/operator/workers/<worker>/queue')
945-
@authorize
946884
def get_operator_get_queue(worker: int):
947885
return proxy_operator(f'/workers/{worker}/queue')
948886

949887

950888
@app.route('/operator/workers/<worker>/logs')
951-
@authorize
952889
def get_operator_get_logs(worker: int):
953890
return proxy_operator(f'/workers/{worker}/logs')
954891

955892

956893
@app.route('/operator/clusters/<namespace>/<cluster>/logs')
957-
@authorize
958894
def get_operator_get_logs_per_cluster(namespace: str, cluster: str):
959895
return proxy_operator(f'/clusters/{namespace}/{cluster}/logs/')
960896

961897

962-
@app.route('/login')
963-
def login():
964-
redirect = request.args.get('redirect', False)
965-
if not redirect:
966-
return render_template('login-deeplink.html')
967-
968-
redirect_uri = urljoin(APP_URL, '/login/authorized')
969-
return auth.authorize(callback=redirect_uri)
970-
971-
972-
@app.route('/logout')
973-
def logout():
974-
session.pop('auth_token', None)
975-
return redirect(urljoin(APP_URL, '/'))
976-
977-
978898
@app.route('/favicon.png')
979899
def favicon():
980900
return send_from_directory('static/', 'favicon-96x96.png'), 200
981901

982902

983-
@app.route('/login/authorized')
984-
def authorized():
985-
resp = auth.authorized_response()
986-
if resp is None:
987-
return 'Access denied: reason=%s error=%s' % (
988-
request.args['error'],
989-
request.args['error_description']
990-
)
991-
992-
if not isinstance(resp, dict):
993-
return 'Invalid auth response'
994-
995-
session['auth_token'] = (resp['access_token'], '')
996-
997-
r = requests.get(
998-
TOKENINFO_URL,
999-
headers={
1000-
'Authorization': f'Bearer {session["auth_token"][0]}',
1001-
},
1002-
)
1003-
session['user_name'] = r.json().get('uid')
1004-
1005-
logger.info(f'Login from: {session["user_name"]}')
1006-
1007-
# return redirect(urljoin(APP_URL, '/'))
1008-
return render_template('login-resolve-deeplink.html')
1009-
1010-
1011903
def shutdown():
1012904
# just wait some time to give Kubernetes time to update endpoints
1013905
# this requires changing the readinessProbe's
@@ -1083,28 +975,20 @@ def init_cluster():
1083975
help='Verbose logging',
1084976
is_flag=True,
1085977
)
1086-
@option(
1087-
'--secret-key',
1088-
default='development',
1089-
envvar='SECRET_KEY',
1090-
help='Secret key for session cookies',
1091-
)
1092978
@option(
1093979
'--clusters',
1094980
envvar='CLUSTERS',
1095981
help=f'Comma separated list of Kubernetes API server URLs (default: {DEFAULT_CLUSTERS})', # noqa
1096982
type=CommaSeparatedValues(),
1097983
)
1098-
def main(port, secret_key, debug, clusters: list):
984+
def main(port, debug, clusters: list):
1099985
global TARGET_NAMESPACE
1100986

1101987
basicConfig(stream=sys.stdout, level=(DEBUG if debug else INFO), format='%(asctime)s %(levelname)s: %(message)s',)
1102988

1103989
init_cluster()
1104990

1105-
logger.info(f'Access token URL: {ACCESS_TOKEN_URL}')
1106991
logger.info(f'App URL: {APP_URL}')
1107-
logger.info(f'Authorize URL: {AUTHORIZE_URL}')
1108992
logger.info(f'Operator API URL: {OPERATOR_API_URL}')
1109993
logger.info(f'Operator cluster name label: {OPERATOR_CLUSTER_NAME_LABEL}')
1110994
logger.info(f'Readonly mode: {"enabled" if READ_ONLY_MODE else "disabled"}') # noqa
@@ -1113,7 +997,6 @@ def main(port, secret_key, debug, clusters: list):
1113997
logger.info(f'Superuser team: {SUPERUSER_TEAM}')
1114998
logger.info(f'Target namespace: {TARGET_NAMESPACE}')
1115999
logger.info(f'Teamservice URL: {TEAM_SERVICE_URL}')
1116-
logger.info(f'Tokeninfo URL: {TOKENINFO_URL}')
11171000
logger.info(f'Use AWS instance_profile: {USE_AWS_INSTANCE_PROFILE}')
11181001
logger.info(f'WAL-E S3 endpoint: {WALE_S3_ENDPOINT}')
11191002
logger.info(f'AWS S3 endpoint: {AWS_ENDPOINT}')
@@ -1136,7 +1019,6 @@ def get_target_namespace():
11361019
logger.info(f'Target namespace set to: {TARGET_NAMESPACE or "*"}')
11371020

11381021
app.debug = debug
1139-
app.secret_key = secret_key
11401022

11411023
signal(SIGTERM, exit_gracefully)
11421024

0 commit comments

Comments
 (0)