Merge branch 'feature/internal-admin-api' into 'develop'

Internal admin api views

See merge request isard/isard-sso!40
Josep Maria Viñolas Auquer 2021-08-22 07:50:38 +00:00
commit 31d994d917
7 changed files with 112 additions and 5 deletions

View File

@ -87,6 +87,7 @@ Import all views
from .views import LoginViews from .views import LoginViews
from .views import WebViews from .views import WebViews
from .views import ApiViews from .views import ApiViews
from .views import InternalViews

View File

@ -36,6 +36,11 @@ ram_users={
'id': os.environ["KEYCLOAK_USER"], 'id': os.environ["KEYCLOAK_USER"],
'password': os.environ["KEYCLOAK_PASSWORD"], 'password': os.environ["KEYCLOAK_PASSWORD"],
'role': 'admin', 'role': 'admin',
},
os.environ["WORDPRESS_MARIADB_USER"]: {
'id': os.environ["WORDPRESS_MARIADB_USER"],
'password': os.environ["WORDPRESS_MARIADB_PASSWORD"],
'role': 'manager',
} }
} }

View File

@ -15,8 +15,6 @@ import threading
threads={} threads={}
# q = Queue.Queue() # q = Queue.Queue()
from pprint import pprint
from keycloak.exceptions import KeycloakGetError from keycloak.exceptions import KeycloakGetError
@app.route('/api/resync') @app.route('/api/resync')
@ -99,8 +97,6 @@ def groups(provider=False):
if provider == 'keycloak': if provider == 'keycloak':
return json.dumps(app.admin.delete_keycloak_groups()), 200, {'Content-Type': 'application/json'} return json.dumps(app.admin.delete_keycloak_groups()), 200, {'Content-Type': 'application/json'}
### SYSADM USERS ONLY ### SYSADM USERS ONLY
@app.route('/api/external', methods=['POST', 'PUT', 'GET','DELETE']) @app.route('/api/external', methods=['POST', 'PUT', 'GET','DELETE'])

View File

@ -0,0 +1,83 @@
#!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:
if not group['path'].startswith('/'): continue
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'}
@app.route('/api/internal/roles', methods=['GET'])
@is_internal
def internal_roles():
if request.method == 'GET':
roles=[]
for role in sorted(app.admin.get_roles(), key=lambda k: k['name']):
if role['name'] == 'admin': continue
roles.append({'id':role['id'],
'name':role['name'],
'description':role.get('description','')})
return json.dumps(roles), 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']}

View File

@ -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

View File

@ -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_x509cert'""")
self.db.update("""DELETE FROM wp_options WHERE option_name = 'onelogin_saml_advanced_settings_sp_privatekey'""") self.db.update("""DELETE FROM wp_options WHERE option_name = 'onelogin_saml_advanced_settings_sp_privatekey'""")
nw=WordpressSaml() nw=WordpressSaml()

View File

@ -166,6 +166,10 @@ backend be_wp
acl existing-x-forwarded-proto req.hdr(X-Forwarded-Proto) -m found 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-Host %[req.hdr(Host)] unless existing-x-forwarded-host
http-request add-header X-Forwarded-Proto https unless existing-x-forwarded-proto 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 server wp isard-apps-wordpress:80 check port 80 inter 5s rise 2 fall 10 resolvers mydns init-addr none