From 369efb980f04aaeb357eb177b245205f48f22ca3 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 23 Jul 2021 19:28:19 +0200 Subject: [PATCH] Internal api will open some ports internally to wordpress initially --- admin/src/admin/__init__.py | 1 + admin/src/admin/auth/authentication.py | 5 ++ admin/src/admin/views/ApiViews.py | 4 -- admin/src/admin/views/InternalViews.py | 70 ++++++++++++++++++++++++++ admin/src/admin/views/decorators.py | 18 +++++++ admin/src/wordpress_saml_onlycerts.py | 2 +- docker/haproxy/haproxy.conf | 4 ++ 7 files changed, 99 insertions(+), 5 deletions(-) create mode 100644 admin/src/admin/views/InternalViews.py create mode 100644 admin/src/admin/views/decorators.py diff --git a/admin/src/admin/__init__.py b/admin/src/admin/__init__.py index f5ed74d..bf623a5 100644 --- a/admin/src/admin/__init__.py +++ b/admin/src/admin/__init__.py @@ -87,6 +87,7 @@ Import all views from .views import LoginViews from .views import WebViews from .views import ApiViews +from .views import InternalViews diff --git a/admin/src/admin/auth/authentication.py b/admin/src/admin/auth/authentication.py index 26b5a70..b89d42e 100644 --- a/admin/src/admin/auth/authentication.py +++ b/admin/src/admin/auth/authentication.py @@ -36,6 +36,11 @@ ram_users={ 'id': os.environ["KEYCLOAK_USER"], 'password': os.environ["KEYCLOAK_PASSWORD"], 'role': 'admin', + }, + os.environ["WORDPRESS_MARIADB_USER"]: { + 'id': os.environ["WORDPRESS_MARIADB_USER"], + 'password': os.environ["WORDPRESS_MARIADB_PASSWORD"], + 'role': 'manager', } } diff --git a/admin/src/admin/views/ApiViews.py b/admin/src/admin/views/ApiViews.py index e11a7ac..9c3287c 100644 --- a/admin/src/admin/views/ApiViews.py +++ b/admin/src/admin/views/ApiViews.py @@ -15,8 +15,6 @@ import threading threads={} # q = Queue.Queue() -from pprint import pprint - from keycloak.exceptions import KeycloakGetError @app.route('/api/resync') @@ -99,8 +97,6 @@ def groups(provider=False): if provider == 'keycloak': return json.dumps(app.admin.delete_keycloak_groups()), 200, {'Content-Type': 'application/json'} - - ### SYSADM USERS ONLY @app.route('/api/external', methods=['POST', 'PUT', 'GET','DELETE']) diff --git a/admin/src/admin/views/InternalViews.py b/admin/src/admin/views/InternalViews.py new file mode 100644 index 0000000..b0f9498 --- /dev/null +++ b/admin/src/admin/views/InternalViews.py @@ -0,0 +1,70 @@ +#!flask/bin/python +# coding=utf-8 +from admin import app +import logging as log +import traceback + +import time,json +import sys,os + +from flask import request +from .decorators import is_internal + +@app.route('/api/internal/users', methods=['GET']) +@is_internal +def internal_users(): + if request.method == 'GET': + sorted_users = sorted(app.admin.get_mix_users(), key=lambda k: k['username']) + # group_users = [user for user in sorted_users if data['path'] in user['keycloak_groups']] + users=[] + for user in sorted_users: + if not user['enabled']: continue + users.append(user_parser(user)) + return json.dumps(users), 200, {'Content-Type': 'application/json'} + +@app.route('/api/internal/users/filter', methods=['POST']) +@is_internal +def internal_users_search(): + if request.method == 'POST': + data=request.get_json(force=True) + users = app.admin.get_mix_users() + result = [user_parser(user) for user in users + if data['text'] in user['username'] or + data['text'] in user['first'] or + data['text'] in user['last'] or + data['text'] in user['email']] + sorted_result = sorted(result, key=lambda k: k['id']) + return json.dumps(sorted_result), 200, {'Content-Type': 'application/json'} + +@app.route('/api/internal/groups', methods=['GET']) +@is_internal +def internal_groups(): + if request.method == 'GET': + sorted_groups = sorted(app.admin.get_mix_groups(), key=lambda k: k['name']) + groups=[] + for group in sorted_groups: + groups.append({'id':group['path'], + 'name':group['name'], + 'description':group.get('description','')}) + return json.dumps(groups), 200, {'Content-Type': 'application/json'} + +@app.route('/api/internal/group/users', methods=['POST']) +@is_internal +def internal_group_users(): + if request.method == 'POST': + data=request.get_json(force=True) + sorted_users = sorted(app.admin.get_mix_users(), key=lambda k: k['username']) + # group_users = [user for user in sorted_users if data['path'] in user['keycloak_groups']] + users=[] + for user in sorted_users: + if data['path'] not in user['keycloak_groups'] or not user['enabled']: continue + users.append(user_parser(user)) + return json.dumps(users), 200, {'Content-Type': 'application/json'} + +def user_parser(user): + return {'id':user['username'], + 'first':user['first'], + 'last':user['last'], + 'role':user['roles'][0] if len(user['roles']) else None, + 'email':user['email'], + 'groups':user['keycloak_groups']} diff --git a/admin/src/admin/views/decorators.py b/admin/src/admin/views/decorators.py new file mode 100644 index 0000000..3b6c867 --- /dev/null +++ b/admin/src/admin/views/decorators.py @@ -0,0 +1,18 @@ +#!flask/bin/python +# coding=utf-8 + +from functools import wraps +from flask import request, redirect, url_for +from flask_login import logout_user +import socket + +def is_internal(fn): + @wraps(fn) + def decorated_view(*args, **kwargs): + remote_addr=request.headers['X-Forwarded-For'].split(',')[0] if 'X-Forwarded-For' in request.headers else request.remote_addr.split(',')[0] + ## Now only checks if it is wordpress container, + ## but we should check if it is internal net and not haproxy + if socket.gethostbyname('isard-apps-wordpress') == remote_addr: return fn(*args, **kwargs) + logout_user() + return redirect(url_for('login')) + return decorated_view \ No newline at end of file diff --git a/admin/src/wordpress_saml_onlycerts.py b/admin/src/wordpress_saml_onlycerts.py index b1e64cd..2cbc39c 100644 --- a/admin/src/wordpress_saml_onlycerts.py +++ b/admin/src/wordpress_saml_onlycerts.py @@ -126,4 +126,4 @@ class WordpressSaml(): self.db.update("""DELETE FROM wp_options WHERE option_name = 'onelogin_saml_advanced_settings_sp_x509cert'""") self.db.update("""DELETE FROM wp_options WHERE option_name = 'onelogin_saml_advanced_settings_sp_privatekey'""") -nw=WordpressSaml() \ No newline at end of file +nw=WordpressSaml() diff --git a/docker/haproxy/haproxy.conf b/docker/haproxy/haproxy.conf index 93e2a0a..d5fc9ff 100644 --- a/docker/haproxy/haproxy.conf +++ b/docker/haproxy/haproxy.conf @@ -166,6 +166,10 @@ backend be_wp acl existing-x-forwarded-proto req.hdr(X-Forwarded-Proto) -m found http-request add-header X-Forwarded-Host %[req.hdr(Host)] unless existing-x-forwarded-host http-request add-header X-Forwarded-Proto https unless existing-x-forwarded-proto + + http-request set-header X-SSL %[ssl_fc] + reqadd X-Forwarded-Proto:\ https + #http-request set-header X-Forwarded-Proto https server wp isard-apps-wordpress:80 check port 80 inter 5s rise 2 fall 10 resolvers mydns init-addr none