automated wordpress saml
parent
ab559dd35a
commit
be28c1ae30
|
@ -15,4 +15,5 @@ Werkzeug==1.0.1
|
||||||
zope.event==4.4
|
zope.event==4.4
|
||||||
zope.interface==5.1.0
|
zope.interface==5.1.0
|
||||||
psycopg2==2.8.6
|
psycopg2==2.8.6
|
||||||
Flask-SocketIO==2.8.6
|
Flask-SocketIO==2.8.6
|
||||||
|
mysql-connector-python==8.0.25
|
|
@ -1,11 +1,13 @@
|
||||||
from admin import app
|
from admin import app
|
||||||
from .keycloak import Keycloak
|
from .keycloak_client import KeycloakClient
|
||||||
from .moodle import Moodle
|
from .moodle import Moodle
|
||||||
from .nextcloud import Nextcloud
|
from .nextcloud import Nextcloud
|
||||||
|
|
||||||
import logging as log
|
import logging as log
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
import traceback
|
import traceback, os
|
||||||
|
|
||||||
|
from time import sleep
|
||||||
|
|
||||||
from .nextcloud_exc import *
|
from .nextcloud_exc import *
|
||||||
from .helpers import filter_roles_list, filter_roles_listofdicts
|
from .helpers import filter_roles_list, filter_roles_listofdicts
|
||||||
|
@ -13,12 +15,42 @@ from .helpers import filter_roles_list, filter_roles_listofdicts
|
||||||
from flask_socketio import SocketIO, emit, join_room, leave_room, \
|
from flask_socketio import SocketIO, emit, join_room, leave_room, \
|
||||||
close_room, rooms, disconnect, send
|
close_room, rooms, disconnect, send
|
||||||
socketio = SocketIO(app)
|
socketio = SocketIO(app)
|
||||||
|
import json
|
||||||
|
|
||||||
class Admin():
|
class Admin():
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.keycloak=Keycloak(verify=app.config['VERIFY'])
|
ready=False
|
||||||
self.moodle=Moodle(verify=app.config['VERIFY'])
|
while not ready:
|
||||||
self.nextcloud=Nextcloud(verify=app.config['VERIFY'])
|
try:
|
||||||
|
self.keycloak=KeycloakClient(verify=app.config['VERIFY'])
|
||||||
|
ready=True
|
||||||
|
except:
|
||||||
|
log.error(traceback.format_exc())
|
||||||
|
log.error('Could not connect to keycloak, waiting to be online...')
|
||||||
|
sleep(2)
|
||||||
|
log.warning('Keycloak connected.')
|
||||||
|
|
||||||
|
ready=False
|
||||||
|
while not ready:
|
||||||
|
try:
|
||||||
|
self.moodle=Moodle(verify=app.config['VERIFY'])
|
||||||
|
ready=True
|
||||||
|
except:
|
||||||
|
log.error('Could not connect to moodle, waiting to be online...')
|
||||||
|
sleep(2)
|
||||||
|
log.warning('Moodle connected.')
|
||||||
|
|
||||||
|
ready=False
|
||||||
|
while not ready:
|
||||||
|
try:
|
||||||
|
self.nextcloud=Nextcloud(verify=app.config['VERIFY'])
|
||||||
|
ready=True
|
||||||
|
except:
|
||||||
|
log.error('Could not connect to nextcloud, waiting to be online...')
|
||||||
|
sleep(2)
|
||||||
|
log.warning('Nextcloud connected.')
|
||||||
|
|
||||||
|
self.default_setup()
|
||||||
|
|
||||||
self.internal={}
|
self.internal={}
|
||||||
self.resync_data()
|
self.resync_data()
|
||||||
|
@ -26,6 +58,52 @@ class Admin():
|
||||||
'groups':[],
|
'groups':[],
|
||||||
'roles':[]}
|
'roles':[]}
|
||||||
|
|
||||||
|
## This function should be moved to postup.py
|
||||||
|
def default_setup(self):
|
||||||
|
log.warning('Setting defaults...')
|
||||||
|
dduser=os.environ['DDADMIN_USER']
|
||||||
|
ddpassword=os.environ['DDADMIN_PASSWORD']
|
||||||
|
ddmail=os.environ['DDADMIN_EMAIL']
|
||||||
|
|
||||||
|
try:
|
||||||
|
log.warning('KEYCLOAK: Adding group admin and user admin to this group')
|
||||||
|
self.keycloak.add_group('admin')
|
||||||
|
## Add default admin user to group admin (for nextcloud, just in case we go there)
|
||||||
|
admin_uid=self.keycloak_admin.get_user_id('admin')
|
||||||
|
self.keycloak_admin.group_user_add(uid,gid)
|
||||||
|
log.warning('KEYCLOAK: OK')
|
||||||
|
except:
|
||||||
|
log.warning('KEYCLOAK: Seems to be there already')
|
||||||
|
|
||||||
|
try:
|
||||||
|
log.warning('KEYCLOAK: Adding user ddadmin and adding to group and role admin')
|
||||||
|
## Assign group admin to this dduser for nextcloud
|
||||||
|
uid=self.keycloak.add_user(dduser,'DD','Admin',ddmail,ddpassword,group='admin')
|
||||||
|
## Assign role admin to this user for keycloak, moodle and wordpress
|
||||||
|
self.keycloak.assign_realm_roles(uid,'admin')
|
||||||
|
log.warning('KEYCLOAK: OK')
|
||||||
|
except:
|
||||||
|
log.warning('KEYCLOAK: Seems to be there already')
|
||||||
|
|
||||||
|
try:
|
||||||
|
log.warning('NEXTCLOUD: Adding user ddadmin and adding to group admin')
|
||||||
|
self.nextcloud.add_user(dduser,ddpassword,group='admin',email=ddmail,displayname='DD Admin')
|
||||||
|
log.warning('NEXTCLOUD: OK')
|
||||||
|
except ProviderItemExists:
|
||||||
|
log.warning('NEXTCLOUD: Seems to be there already')
|
||||||
|
except:
|
||||||
|
log.error(traceback.format_exc())
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
try:
|
||||||
|
log.warning('MOODLE: Adding user ddadmin and adding to siteadmins')
|
||||||
|
self.moodle.create_user(ddmail,dduser,ddpassword,'DD','Admin')
|
||||||
|
uid=self.moodle.get_user_by('username',dduser)['users'][0]['id']
|
||||||
|
self.moodle.add_user_to_siteadmin(uid)
|
||||||
|
log.warning('MOODLE: OK')
|
||||||
|
except:
|
||||||
|
log.warning('MOODLE: Seems to be there already')
|
||||||
|
|
||||||
def resync_data(self):
|
def resync_data(self):
|
||||||
self.internal={'users':self._get_mix_users(),
|
self.internal={'users':self._get_mix_users(),
|
||||||
'groups':self._get_mix_groups(),
|
'groups':self._get_mix_groups(),
|
||||||
|
@ -146,15 +224,15 @@ class Admin():
|
||||||
return filter_roles_listofdicts(self.keycloak.get_roles())
|
return filter_roles_listofdicts(self.keycloak.get_roles())
|
||||||
|
|
||||||
def get_keycloak_groups(self):
|
def get_keycloak_groups(self):
|
||||||
log.warning('Loading keycloak groups... can take a long time...')
|
log.warning('Loading keycloak groups...')
|
||||||
return self.keycloak.get_groups()
|
return self.keycloak.get_groups()
|
||||||
|
|
||||||
def get_moodle_groups(self):
|
def get_moodle_groups(self):
|
||||||
log.warning('Loading moodle groups... can take a long time...')
|
log.warning('Loading moodle groups...')
|
||||||
return self.moodle.get_cohorts()
|
return self.moodle.get_cohorts()
|
||||||
|
|
||||||
def get_nextcloud_groups(self):
|
def get_nextcloud_groups(self):
|
||||||
log.warning('Loading nextcloud groups... can take a long time...')
|
log.warning('Loading nextcloud groups...')
|
||||||
return self.nextcloud.get_groups_list()
|
return self.nextcloud.get_groups_list()
|
||||||
|
|
||||||
def get_mix_groups(self):
|
def get_mix_groups(self):
|
||||||
|
@ -244,24 +322,24 @@ class Admin():
|
||||||
|
|
||||||
def sync_external(self):
|
def sync_external(self):
|
||||||
for u in self.external['users']:
|
for u in self.external['users']:
|
||||||
log.error('Creating user: '+u['username'])
|
log.info('Creating user: '+u['username'])
|
||||||
self.keycloak.add_user(u['username'],u['first'],u['last'],u['email'],'1Provaprovaprova',group=u['groups'][0])
|
self.keycloak.add_user(u['username'],u['first'],u['last'],u['email'],'1Provaprovaprova',group=u['groups'][0])
|
||||||
|
|
||||||
def sync_to_moodle(self):
|
def sync_to_moodle(self):
|
||||||
for u in self.internal['users']:
|
for u in self.internal['users']:
|
||||||
if not u['moodle']:
|
if not u['moodle']:
|
||||||
log.error('Creating moodle user: '+u['username'])
|
log.info('Creating moodle user: '+u['username'])
|
||||||
self.moodle.create_user(u['email'],u['username'],'-1Provaprovaprova',u['first'],u['last'])
|
self.moodle.create_user(u['email'],u['username'],'-1Provaprovaprova',u['first'],u['last'])
|
||||||
|
|
||||||
def sync_to_nextcloud(self):
|
def sync_to_nextcloud(self):
|
||||||
for u in self.internal['users']:
|
for u in self.internal['users']:
|
||||||
if not u['nextcloud']:
|
if not u['nextcloud']:
|
||||||
log.error('Creating nextcloud user: '+u['username'])
|
log.info('Creating nextcloud user: '+u['username'])
|
||||||
group=u['keycloak_groups'][0] if len(u['keycloak_groups']) else False
|
group=u['keycloak_groups'][0] if len(u['keycloak_groups']) else False
|
||||||
try:
|
try:
|
||||||
self.nextcloud.add_user(u['username'],'-1Provaprovaprova',1000,group,u['email'],u['first']+' '+u['last'])
|
self.nextcloud.add_user(u['username'],'-1Provaprovaprova',1000,group,u['email'],u['first']+' '+u['last'])
|
||||||
except ProviderItemExists:
|
except ProviderItemExists:
|
||||||
log.error('User '+u['username']+' already exists. Skipping...')
|
log.info('User '+u['username']+' already exists. Skipping...')
|
||||||
continue
|
continue
|
||||||
except:
|
except:
|
||||||
log.error(traceback.format_exc())
|
log.error(traceback.format_exc())
|
||||||
|
|
|
@ -14,7 +14,7 @@ from jinja2 import Environment, FileSystemLoader
|
||||||
from keycloak import KeycloakAdmin
|
from keycloak import KeycloakAdmin
|
||||||
from .postgres import Postgres
|
from .postgres import Postgres
|
||||||
|
|
||||||
class Keycloak():
|
class KeycloakClient():
|
||||||
"""https://www.keycloak.org/docs-api/13.0/rest-api/index.html
|
"""https://www.keycloak.org/docs-api/13.0/rest-api/index.html
|
||||||
https://github.com/marcospereirampj/python-keycloak
|
https://github.com/marcospereirampj/python-keycloak
|
||||||
https://gist.github.com/kaqfa/99829941121188d7cef8271f93f52f1f
|
https://gist.github.com/kaqfa/99829941121188d7cef8271f93f52f1f
|
||||||
|
@ -31,7 +31,7 @@ class Keycloak():
|
||||||
self.realm=realm
|
self.realm=realm
|
||||||
self.verify=verify
|
self.verify=verify
|
||||||
|
|
||||||
self.keycloak_pg=Postgres('isard-apps-postgresql','keycloak',app.config['KEYCLOAK_POSTGRES_USER'],app.config['KEYCLOAK_POSTGRES_PASSWORD'])
|
self.keycloak_pg=Postgres('isard-apps-postgresql','keycloak',os.environ['KEYCLOAK_DB_USER'],os.environ['KEYCLOAK_DB_PASSWORD'])
|
||||||
|
|
||||||
def connect(self):
|
def connect(self):
|
||||||
self.keycloak_admin = KeycloakAdmin(server_url=self.url,
|
self.keycloak_admin = KeycloakAdmin(server_url=self.url,
|
||||||
|
@ -39,7 +39,7 @@ class Keycloak():
|
||||||
password=self.password,
|
password=self.password,
|
||||||
realm_name=self.realm,
|
realm_name=self.realm,
|
||||||
verify=self.verify)
|
verify=self.verify)
|
||||||
|
# from keycloak import KeycloakAdmin
|
||||||
# keycloak_admin = KeycloakAdmin(server_url="http://isard-sso-keycloak:8080/auth/",username="admin",password="keycloakkeycloak",realm_name="master",verify=False)
|
# keycloak_admin = KeycloakAdmin(server_url="http://isard-sso-keycloak:8080/auth/",username="admin",password="keycloakkeycloak",realm_name="master",verify=False)
|
||||||
|
|
||||||
######## Example create group and subgroup
|
######## Example create group and subgroup
|
||||||
|
@ -110,7 +110,6 @@ class Keycloak():
|
||||||
|
|
||||||
def add_user(self,username,first,last,email,password,group=False):
|
def add_user(self,username,first,last,email,password,group=False):
|
||||||
# Returns user id
|
# Returns user id
|
||||||
log.error('Creating group: '+str(group))
|
|
||||||
self.connect()
|
self.connect()
|
||||||
username=username.lower()
|
username=username.lower()
|
||||||
try:
|
try:
|
||||||
|
@ -123,22 +122,21 @@ class Keycloak():
|
||||||
"value":password,
|
"value":password,
|
||||||
"temporary":False}]})
|
"temporary":False}]})
|
||||||
except:
|
except:
|
||||||
uid=self.keycloak_admin.get_user_id(username)
|
log.error(traceback.format_exc())
|
||||||
log.error(uid)
|
|
||||||
if group:
|
if group:
|
||||||
|
path = '/'+group if group[1:] != '/' else group
|
||||||
try:
|
try:
|
||||||
gid=self.keycloak_admin.get_group_by_path(path=group,search_in_subgroups=False)['id']
|
gid=self.keycloak_admin.get_group_by_path(path=path,search_in_subgroups=False)['id']
|
||||||
log.error('group created with gid: '+str(gid))
|
|
||||||
except:
|
except:
|
||||||
self.keycloak_admin.create_group({"name":group})
|
self.keycloak_admin.create_group({"name":group})
|
||||||
gid=self.keycloak_admin.get_group_by_path(group)['id']
|
gid=self.keycloak_admin.get_group_by_path(path)['id']
|
||||||
log.error(gid)
|
|
||||||
self.keycloak_admin.group_user_add(uid,gid)
|
self.keycloak_admin.group_user_add(uid,gid)
|
||||||
|
return uid
|
||||||
|
|
||||||
def add_user_role(self,client_id,user_id,role_id,role_name):
|
def add_user_role(self,client_id,user_id,role_id,role_name):
|
||||||
self.connect()
|
self.connect()
|
||||||
return self.keycloak_admin.assign_client_role(client_id="client_id", user_id="user_id", role_id="role_id", role_name="test")
|
return self.keycloak_admin.assign_client_role(client_id=client_id, user_id=user_id, role_id=role_id, role_name="test")
|
||||||
|
|
||||||
def delete_user(self,userid):
|
def delete_user(self,userid):
|
||||||
self.connect()
|
self.connect()
|
||||||
|
@ -196,8 +194,9 @@ class Keycloak():
|
||||||
self.connect()
|
self.connect()
|
||||||
return self.keycloak_admin.get_client_roles(client_id=client_id)
|
return self.keycloak_admin.get_client_roles(client_id=client_id)
|
||||||
|
|
||||||
# def add_client_role(self,client_id,roleName):
|
def add_client_role(self,client_id,name,description=''):
|
||||||
# return self.keycloak_admin.create_client_role(client_id=client_id, {'name': roleName, 'clientRole': True})
|
self.connect()
|
||||||
|
return self.keycloak_admin.create_client_role(client_id, {'name': name, 'description':description, 'clientRole': True})
|
||||||
|
|
||||||
|
|
||||||
## SYSTEM
|
## SYSTEM
|
||||||
|
@ -214,6 +213,15 @@ class Keycloak():
|
||||||
rsa_key = [k for k in self.keycloak_admin.get_keys()['keys'] if k['type']=='RSA'][0]
|
rsa_key = [k for k in self.keycloak_admin.get_keys()['keys'] if k['type']=='RSA'][0]
|
||||||
return {'name':rsa_key['kid'],'certificate':rsa_key['certificate']}
|
return {'name':rsa_key['kid'],'certificate':rsa_key['certificate']}
|
||||||
|
|
||||||
|
## REALM
|
||||||
|
def assign_realm_roles(self, user_id, role):
|
||||||
|
self.connect()
|
||||||
|
try:
|
||||||
|
role=[r for r in self.keycloak_admin.get_realm_roles() if r['name']==role]
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
return self.keycloak_admin.assign_realm_roles(user_id=user_id, client_id=None, roles=role)
|
||||||
|
|
||||||
## CLIENTS
|
## CLIENTS
|
||||||
def delete_client(self,clientid):
|
def delete_client(self,clientid):
|
||||||
self.connect()
|
self.connect()
|
|
@ -121,4 +121,37 @@ class Moodle():
|
||||||
cohorts=self.get_cohorts()
|
cohorts=self.get_cohorts()
|
||||||
for cohort in cohorts:
|
for cohort in cohorts:
|
||||||
if user_id in self.get_cohort_members(cohort['id']): user_cohorts.append(cohort)
|
if user_id in self.get_cohort_members(cohort['id']): user_cohorts.append(cohort)
|
||||||
return user_cohorts
|
return user_cohorts
|
||||||
|
|
||||||
|
def add_user_to_siteadmin(self,user_id):
|
||||||
|
q = """SELECT value FROM mdl_config WHERE name='siteadmins'"""
|
||||||
|
value=self.moodle_pg.select(q)[0][0]
|
||||||
|
if str(user_id) not in value:
|
||||||
|
value=value+','+str(user_id)
|
||||||
|
q = """UPDATE mdl_config SET value = '%s' WHERE name='siteadmins'""" % (value)
|
||||||
|
self.moodle_pg.update(q)
|
||||||
|
log.warning('MOODLE:ADDING THE USER TO ADMINS: This needs a purge cache in moodle!')
|
||||||
|
|
||||||
|
# def add_role_to_user(self, user_id, role='admin', context='missing'):
|
||||||
|
# if role=='admin':
|
||||||
|
# role_id=1
|
||||||
|
# else:
|
||||||
|
# return False
|
||||||
|
# assignments = [{'roleid': role_id, 'userid': user_id, 'contextid': 0}]
|
||||||
|
# self.call('core_role_assign_roles', assignments=assignments)
|
||||||
|
# userid=user_id, role_id=role_id)
|
||||||
|
# 'contextlevel': 1,
|
||||||
|
|
||||||
|
# define('CONTEXT_SYSTEM', 10);
|
||||||
|
# define('CONTEXT_USER', 30);
|
||||||
|
# define('CONTEXT_COURSECAT', 40);
|
||||||
|
# define('CONTEXT_COURSE', 50);
|
||||||
|
# define('CONTEXT_MODULE', 70);
|
||||||
|
# define('CONTEXT_BLOCK', 80);
|
||||||
|
|
||||||
|
# 'contextlevel': , 'instanceid'
|
||||||
|
# $assignment = array( 'roleid' => $role_id, 'userid' => $user_id, 'contextid' => $context_id );
|
||||||
|
# $assignments = array( $assignment );
|
||||||
|
# $params = array( 'assignments' => $assignments );
|
||||||
|
|
||||||
|
# $response = call_moodle( 'core_role_assign_roles', $params, $token );
|
|
@ -0,0 +1,34 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# coding=utf-8
|
||||||
|
import time
|
||||||
|
from admin import app
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
import pprint
|
||||||
|
|
||||||
|
import logging as log
|
||||||
|
import traceback
|
||||||
|
import yaml, json
|
||||||
|
|
||||||
|
import mysql.connector
|
||||||
|
|
||||||
|
class Mysql():
|
||||||
|
|
||||||
|
def __init__(self,host,database,user,password):
|
||||||
|
self.conn = mysql.connector.connect(
|
||||||
|
host=host,
|
||||||
|
database=database,
|
||||||
|
user=user,
|
||||||
|
password=password)
|
||||||
|
|
||||||
|
def select(self,sql):
|
||||||
|
self.cur = self.conn.cursor()
|
||||||
|
self.cur.execute(sql)
|
||||||
|
data=self.cur.fetchall()
|
||||||
|
self.cur.close()
|
||||||
|
return data
|
||||||
|
|
||||||
|
def update(self,sql):
|
||||||
|
self.cur = self.conn.cursor()
|
||||||
|
self.cur.execute(sql)
|
||||||
|
self.conn.commit()
|
||||||
|
self.cur.close()
|
|
@ -126,11 +126,14 @@ class Nextcloud():
|
||||||
# log.error(traceback.format_exc())
|
# log.error(traceback.format_exc())
|
||||||
# raise
|
# raise
|
||||||
|
|
||||||
def add_user(self,userid,userpassword,quota,group=False,email='',displayname=''):
|
def add_user(self,userid,userpassword,quota=False,group=False,email='',displayname=''):
|
||||||
if group:
|
data={'userid':userid,'password':userpassword,'quota':quota,'groups[]':group,'email':email,'displayname':displayname}
|
||||||
data={'userid':userid,'password':userpassword,'quota':quota,'groups[]':group,'email':email,'displayname':displayname}
|
if not group: del data['group']
|
||||||
else:
|
if not quota: del data['quota']
|
||||||
data={'userid':userid,'password':userpassword,'quota':quota,'email':email,'displayname':displayname}
|
# if group:
|
||||||
|
# data={'userid':userid,'password':userpassword,'quota':quota,'groups[]':group,'email':email,'displayname':displayname}
|
||||||
|
# else:
|
||||||
|
# data={'userid':userid,'password':userpassword,'quota':quota,'email':email,'displayname':displayname}
|
||||||
url = self.apiurl + "users?format=json"
|
url = self.apiurl + "users?format=json"
|
||||||
headers = {
|
headers = {
|
||||||
'Content-Type': 'application/x-www-form-urlencoded',
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
|
|
@ -82,6 +82,7 @@ class Postup():
|
||||||
(3, 'core_cohort_delete_cohorts'),
|
(3, 'core_cohort_delete_cohorts'),
|
||||||
(3, 'core_cohort_search_cohorts'),
|
(3, 'core_cohort_search_cohorts'),
|
||||||
(3, 'core_cohort_update_cohorts'),
|
(3, 'core_cohort_update_cohorts'),
|
||||||
|
(3, 'core_role_assign_roles'),
|
||||||
(3, 'core_cohort_get_cohorts');""")
|
(3, 'core_cohort_get_cohorts');""")
|
||||||
|
|
||||||
self.pg.update("""INSERT INTO "mdl_external_services_users" ("externalserviceid", "userid", "iprestriction", "validuntil", "timecreated") VALUES
|
self.pg.update("""INSERT INTO "mdl_external_services_users" ("externalserviceid", "userid", "iprestriction", "validuntil", "timecreated") VALUES
|
||||||
|
|
|
@ -11,7 +11,7 @@ import yaml, json
|
||||||
import psycopg2
|
import psycopg2
|
||||||
|
|
||||||
from admin.lib.postgres import Postgres
|
from admin.lib.postgres import Postgres
|
||||||
from admin.lib.keycloak import Keycloak
|
from admin.lib.keycloak_client import KeycloakClient
|
||||||
|
|
||||||
import string, random
|
import string, random
|
||||||
|
|
||||||
|
@ -102,6 +102,8 @@ class MoodleSaml():
|
||||||
except:
|
except:
|
||||||
print('Error adding saml on keycloak')
|
print('Error adding saml on keycloak')
|
||||||
|
|
||||||
|
self.add_client_roles()
|
||||||
|
|
||||||
def activate_saml_plugin(self):
|
def activate_saml_plugin(self):
|
||||||
## After you need to purge moodle caches: /var/www/html # php admin/cli/purge_caches.php
|
## After you need to purge moodle caches: /var/www/html # php admin/cli/purge_caches.php
|
||||||
return self.pg.update("""UPDATE "mdl_config" SET value = 'email,saml2' WHERE "name" = 'auth'""")
|
return self.pg.update("""UPDATE "mdl_config" SET value = 'email,saml2' WHERE "name" = 'auth'""")
|
||||||
|
@ -110,18 +112,18 @@ class MoodleSaml():
|
||||||
return self.pg.select("""SELECT * FROM "mdl_config" WHERE "name" = 'siteidentifier'""")[0][2]
|
return self.pg.select("""SELECT * FROM "mdl_config" WHERE "name" = 'siteidentifier'""")[0][2]
|
||||||
|
|
||||||
def parse_idp_metadata(self):
|
def parse_idp_metadata(self):
|
||||||
keycloak=Keycloak()
|
keycloak=KeycloakClient()
|
||||||
rsa=keycloak.get_server_rsa_key()
|
rsa=keycloak.get_server_rsa_key()
|
||||||
keycloak=None
|
keycloak=None
|
||||||
return '<md:EntitiesDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Name="urn:keycloak"><md:EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" entityID="https://sso.'+os.environ['DOMAIN']+'/auth/realms/master"><md:IDPSSODescriptor WantAuthnRequestsSigned="true" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"><md:KeyDescriptor use="signing"><ds:KeyInfo><ds:KeyName>'+rsa['name']+'</ds:KeyName><ds:X509Data><ds:X509Certificate>'+rsa['certificate']+'</ds:X509Certificate></ds:X509Data></ds:KeyInfo></md:KeyDescriptor><md:ArtifactResolutionService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://sso.'+os.environ['DOMAIN']+'/auth/realms/master/protocol/saml/resolve" index="0"/><md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://sso.'+os.environ['DOMAIN']+'/auth/realms/master/protocol/saml"/><md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://sso.'+os.environ['DOMAIN']+'/auth/realms/master/protocol/saml"/><md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="https://sso.'+os.environ['DOMAIN']+'/auth/realms/master/protocol/saml"/><md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat><md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</md:NameIDFormat><md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat><md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</md:NameIDFormat><md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://sso.'+os.environ['DOMAIN']+'/auth/realms/master/protocol/saml"/><md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://sso.'+os.environ['DOMAIN']+'/auth/realms/master/protocol/saml"/><md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://sso.'+os.environ['DOMAIN']+'/auth/realms/master/protocol/saml"/><md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="https://sso.'+os.environ['DOMAIN']+'/auth/realms/master/protocol/saml"/></md:IDPSSODescriptor></md:EntityDescriptor></md:EntitiesDescriptor>'
|
return '<md:EntitiesDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Name="urn:keycloak"><md:EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" entityID="https://sso.'+os.environ['DOMAIN']+'/auth/realms/master"><md:IDPSSODescriptor WantAuthnRequestsSigned="true" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"><md:KeyDescriptor use="signing"><ds:KeyInfo><ds:KeyName>'+rsa['name']+'</ds:KeyName><ds:X509Data><ds:X509Certificate>'+rsa['certificate']+'</ds:X509Certificate></ds:X509Data></ds:KeyInfo></md:KeyDescriptor><md:ArtifactResolutionService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://sso.'+os.environ['DOMAIN']+'/auth/realms/master/protocol/saml/resolve" index="0"/><md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://sso.'+os.environ['DOMAIN']+'/auth/realms/master/protocol/saml"/><md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://sso.'+os.environ['DOMAIN']+'/auth/realms/master/protocol/saml"/><md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="https://sso.'+os.environ['DOMAIN']+'/auth/realms/master/protocol/saml"/><md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat><md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</md:NameIDFormat><md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat><md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</md:NameIDFormat><md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://sso.'+os.environ['DOMAIN']+'/auth/realms/master/protocol/saml"/><md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://sso.'+os.environ['DOMAIN']+'/auth/realms/master/protocol/saml"/><md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://sso.'+os.environ['DOMAIN']+'/auth/realms/master/protocol/saml"/><md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="https://sso.'+os.environ['DOMAIN']+'/auth/realms/master/protocol/saml"/></md:IDPSSODescriptor></md:EntityDescriptor></md:EntitiesDescriptor>'
|
||||||
|
|
||||||
def set_keycloak_moodle_saml_plugin(self):
|
def set_keycloak_moodle_saml_plugin(self):
|
||||||
keycloak=Keycloak()
|
keycloak=KeycloakClient()
|
||||||
keycloak.add_moodle_client()
|
keycloak.add_moodle_client()
|
||||||
keycloak=None
|
keycloak=None
|
||||||
|
|
||||||
def delete_keycloak_moodle_saml_plugin(self):
|
def delete_keycloak_moodle_saml_plugin(self):
|
||||||
keycloak=Keycloak()
|
keycloak=KeycloakClient()
|
||||||
keycloak.delete_client('a92d5417-92b6-4678-9cb9-51bc0edcee8c')
|
keycloak.delete_client('a92d5417-92b6-4678-9cb9-51bc0edcee8c')
|
||||||
keycloak=None
|
keycloak=None
|
||||||
|
|
||||||
|
@ -240,9 +242,16 @@ class MoodleSaml():
|
||||||
"manage" : True
|
"manage" : True
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
keycloak=Keycloak()
|
keycloak=KeycloakClient()
|
||||||
keycloak.add_client(client)
|
keycloak.add_client(client)
|
||||||
keycloak=None
|
keycloak=None
|
||||||
|
|
||||||
|
def add_client_roles(self):
|
||||||
|
keycloak=KeycloakClient()
|
||||||
|
keycloak.add_client_role('a92d5417-92b6-4678-9cb9-51bc0edcee8c','admin','Moodle admins')
|
||||||
|
keycloak.add_client_role('a92d5417-92b6-4678-9cb9-51bc0edcee8c','manager','Moodle managers')
|
||||||
|
keycloak.add_client_role('a92d5417-92b6-4678-9cb9-51bc0edcee8c','teacher','Moodle teachers')
|
||||||
|
keycloak.add_client_role('a92d5417-92b6-4678-9cb9-51bc0edcee8c','student','Moodle students')
|
||||||
|
keycloak=None
|
||||||
|
|
||||||
m=MoodleSaml()
|
m=MoodleSaml()
|
||||||
|
|
|
@ -11,7 +11,7 @@ import yaml, json
|
||||||
import psycopg2
|
import psycopg2
|
||||||
|
|
||||||
from admin.lib.postgres import Postgres
|
from admin.lib.postgres import Postgres
|
||||||
from admin.lib.keycloak import Keycloak
|
from admin.lib.keycloak_client import KeycloakClient
|
||||||
|
|
||||||
import string, random
|
import string, random
|
||||||
|
|
||||||
|
@ -20,6 +20,12 @@ app['config']={}
|
||||||
|
|
||||||
class NextcloudSaml():
|
class NextcloudSaml():
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
self.url="http://isard-sso-keycloak:8080/auth/"
|
||||||
|
self.username=os.environ['KEYCLOAK_USER']
|
||||||
|
self.password=os.environ['KEYCLOAK_PASSWORD']
|
||||||
|
self.realm='master'
|
||||||
|
self.verify=True
|
||||||
|
|
||||||
ready=False
|
ready=False
|
||||||
while not ready:
|
while not ready:
|
||||||
try:
|
try:
|
||||||
|
@ -81,6 +87,7 @@ class NextcloudSaml():
|
||||||
try:
|
try:
|
||||||
self.set_nextcloud_saml_plugin()
|
self.set_nextcloud_saml_plugin()
|
||||||
except:
|
except:
|
||||||
|
log.error(traceback.format_exc())
|
||||||
print('Error adding saml on nextcloud')
|
print('Error adding saml on nextcloud')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -88,6 +95,13 @@ class NextcloudSaml():
|
||||||
except:
|
except:
|
||||||
print('Error adding saml on keycloak')
|
print('Error adding saml on keycloak')
|
||||||
|
|
||||||
|
def connect(self):
|
||||||
|
self.keycloak= KeycloakClient(url=self.url,
|
||||||
|
username=self.username,
|
||||||
|
password=self.password,
|
||||||
|
realm=self.realm,
|
||||||
|
verify=self.verify)
|
||||||
|
|
||||||
# def activate_saml_plugin(self):
|
# def activate_saml_plugin(self):
|
||||||
# ## After you need to purge moodle caches: /var/www/html # php admin/cli/purge_caches.php
|
# ## After you need to purge moodle caches: /var/www/html # php admin/cli/purge_caches.php
|
||||||
# return self.pg.update("""UPDATE "mdl_config" SET value = 'email,saml2' WHERE "name" = 'auth'""")
|
# return self.pg.update("""UPDATE "mdl_config" SET value = 'email,saml2' WHERE "name" = 'auth'""")
|
||||||
|
@ -96,20 +110,20 @@ class NextcloudSaml():
|
||||||
# return self.pg.select("""SELECT * FROM "mdl_config" WHERE "name" = 'siteidentifier'""")[0][2]
|
# return self.pg.select("""SELECT * FROM "mdl_config" WHERE "name" = 'siteidentifier'""")[0][2]
|
||||||
|
|
||||||
def parse_idp_cert(self):
|
def parse_idp_cert(self):
|
||||||
keycloak=Keycloak()
|
self.connect()
|
||||||
rsa=keycloak.get_server_rsa_key()
|
rsa=self.keycloak.get_server_rsa_key()
|
||||||
keycloak=None
|
self.keycloak=None
|
||||||
return rsa['certificate']
|
return rsa['certificate']
|
||||||
|
|
||||||
def set_keycloak_nextcloud_saml_plugin(self):
|
def set_keycloak_nextcloud_saml_plugin(self):
|
||||||
keycloak=Keycloak()
|
self.connect()
|
||||||
keycloak.add_nextcloud_client()
|
self.keycloak.add_nextcloud_client()
|
||||||
keycloak=None
|
self.keycloak=None
|
||||||
|
|
||||||
def delete_keycloak_nextcloud_saml_plugin(self):
|
def delete_keycloak_nextcloud_saml_plugin(self):
|
||||||
keycloak=Keycloak()
|
self.connect()
|
||||||
keycloak.delete_client('bef873f0-2079-4876-8657-067de27d01b7')
|
self.keycloak.delete_client('bef873f0-2079-4876-8657-067de27d01b7')
|
||||||
keycloak=None
|
self.keycloak=None
|
||||||
|
|
||||||
def set_nextcloud_saml_plugin(self):
|
def set_nextcloud_saml_plugin(self):
|
||||||
self.pg.update("""INSERT INTO "oc_appconfig" ("appid", "configkey", "configvalue") VALUES
|
self.pg.update("""INSERT INTO "oc_appconfig" ("appid", "configkey", "configvalue") VALUES
|
||||||
|
@ -235,10 +249,8 @@ class NextcloudSaml():
|
||||||
"manage" : True
|
"manage" : True
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
keycloak=Keycloak()
|
self.connect()
|
||||||
keycloak.add_client(client)
|
self.keycloak.add_client(client)
|
||||||
keycloak=None
|
self.keycloak=None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
n=NextcloudSaml()
|
n=NextcloudSaml()
|
|
@ -0,0 +1,295 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# coding=utf-8
|
||||||
|
import time, os
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
import pprint
|
||||||
|
|
||||||
|
import logging as log
|
||||||
|
import traceback
|
||||||
|
import yaml, json
|
||||||
|
|
||||||
|
import psycopg2
|
||||||
|
|
||||||
|
from admin.lib.mysql import Mysql
|
||||||
|
from admin.lib.keycloak_client import KeycloakClient
|
||||||
|
|
||||||
|
import string, random
|
||||||
|
|
||||||
|
app={}
|
||||||
|
app['config']={}
|
||||||
|
|
||||||
|
class WordpressSaml():
|
||||||
|
def __init__(self):
|
||||||
|
self.url="http://isard-sso-keycloak:8080/auth/"
|
||||||
|
self.username=os.environ['KEYCLOAK_USER']
|
||||||
|
self.password=os.environ['KEYCLOAK_PASSWORD']
|
||||||
|
self.realm='master'
|
||||||
|
self.verify=True
|
||||||
|
|
||||||
|
ready=False
|
||||||
|
while not ready:
|
||||||
|
try:
|
||||||
|
self.db=Mysql('isard-apps-mariadb','wordpress','root',os.environ['MARIADB_PASSWORD'])
|
||||||
|
ready=True
|
||||||
|
except:
|
||||||
|
log.warning('Could not connect to wordpress database. Retrying...')
|
||||||
|
time.sleep(2)
|
||||||
|
log.info('Connected to wordpress database.')
|
||||||
|
|
||||||
|
ready=False
|
||||||
|
while not ready:
|
||||||
|
try:
|
||||||
|
with open(os.path.join("./saml_certs/public.cert"),"r") as crt:
|
||||||
|
app['config']['PUBLIC_CERT_RAW']=crt.read()
|
||||||
|
app['config']['PUBLIC_CERT']=self.cert_prepare(app['config']['PUBLIC_CERT_RAW'])
|
||||||
|
ready=True
|
||||||
|
except IOError:
|
||||||
|
log.warning('Could not get public certificate to be used in wordpress. Retrying...')
|
||||||
|
log.warning(' You should generate them: /admin/saml_certs # openssl req -nodes -new -x509 -keyout private.key -out public.cert')
|
||||||
|
time.sleep(2)
|
||||||
|
except:
|
||||||
|
log.error(traceback.format_exc())
|
||||||
|
log.info('Got moodle srt certificate to be used in wordpress.')
|
||||||
|
|
||||||
|
ready=False
|
||||||
|
while not ready:
|
||||||
|
try:
|
||||||
|
with open(os.path.join("./saml_certs/private.key"),"r") as pem:
|
||||||
|
app['config']['PRIVATE_KEY']=self.cert_prepare(pem.read())
|
||||||
|
ready=True
|
||||||
|
except IOError:
|
||||||
|
log.warning('Could not get private key to be used in wordpress. Retrying...')
|
||||||
|
log.warning(' You should generate them: /admin/saml_certs # openssl req -nodes -new -x509 -keyout private.key -out public.cert')
|
||||||
|
time.sleep(2)
|
||||||
|
log.info('Got moodle pem certificate to be used in wordpress.')
|
||||||
|
|
||||||
|
# ## This seems related to the fact that the certificate generated the first time does'nt work.
|
||||||
|
# ## And when regenerating the certificate de privatekeypass seems not to be used and instead it
|
||||||
|
# ## will use always this code as filename: 0f635d0e0f3874fff8b581c132e6c7a7
|
||||||
|
# ## As this bug I'm not able to solve, the process is:
|
||||||
|
# ## 1.- Bring up moodle and regenerate certificates on saml2 plugin in plugins-authentication
|
||||||
|
# ## 2.- Execute this script
|
||||||
|
# ## 3.- Cleanup all caches in moodle (Development tab)
|
||||||
|
# # with open(os.path.join("./moodledata/saml2/"+os.environ['NEXTCLOUD_SAML_PRIVATEKEYPASS'].replace("moodle."+os.environ['DOMAIN'],'')+'.idp.xml'),"w") as xml:
|
||||||
|
# # xml.write(self.parse_idp_metadata())
|
||||||
|
# with open(os.path.join("./moodledata/saml2/0f635d0e0f3874fff8b581c132e6c7a7.idp.xml"),"w") as xml:
|
||||||
|
# xml.write(self.parse_idp_metadata())
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.reset_saml()
|
||||||
|
except:
|
||||||
|
print(traceback.format_exc())
|
||||||
|
print('Error resetting saml on wordpress')
|
||||||
|
try:
|
||||||
|
self.delete_keycloak_wordpress_saml_plugin()
|
||||||
|
except:
|
||||||
|
print('Error resetting saml on keycloak')
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.set_wordpress_saml_plugin()
|
||||||
|
except:
|
||||||
|
print(traceback.format_exc())
|
||||||
|
print('Error adding saml on wordpress')
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.add_keycloak_wordpress_saml()
|
||||||
|
except:
|
||||||
|
print('Error adding saml on keycloak')
|
||||||
|
|
||||||
|
self.add_client_roles()
|
||||||
|
|
||||||
|
def connect(self):
|
||||||
|
self.keycloak= KeycloakClient(url=self.url,
|
||||||
|
username=self.username,
|
||||||
|
password=self.password,
|
||||||
|
realm=self.realm,
|
||||||
|
verify=self.verify)
|
||||||
|
|
||||||
|
# def activate_saml_plugin(self):
|
||||||
|
# ## After you need to purge moodle caches: /var/www/html # php admin/cli/purge_caches.php
|
||||||
|
# return self.db.update("""UPDATE "mdl_config" SET value = 'email,saml2' WHERE "name" = 'auth'""")
|
||||||
|
|
||||||
|
# def get_privatekey_pass(self):
|
||||||
|
# return self.db.select("""SELECT * FROM "mdl_config" WHERE "name" = 'siteidentifier'""")[0][2]
|
||||||
|
|
||||||
|
def cert_prepare(self,cert):
|
||||||
|
return ''.join(cert.split('-----')[2].splitlines())
|
||||||
|
|
||||||
|
def parse_idp_cert(self):
|
||||||
|
self.connect()
|
||||||
|
rsa=self.keycloak.get_server_rsa_key()
|
||||||
|
self.keycloak=None
|
||||||
|
return rsa['certificate']
|
||||||
|
|
||||||
|
def set_keycloak_wordpress_saml_plugin(self):
|
||||||
|
self.connect()
|
||||||
|
self.keycloak.add_wordpress_client()
|
||||||
|
self.keycloak=None
|
||||||
|
|
||||||
|
def delete_keycloak_wordpress_saml_plugin(self):
|
||||||
|
self.connect()
|
||||||
|
self.keycloak.delete_client('630601f8-25d1-4822-8741-c93affd2cd84')
|
||||||
|
self.keycloak=None
|
||||||
|
|
||||||
|
def set_wordpress_saml_plugin(self):
|
||||||
|
# ('active_plugins', 'a:2:{i:0;s:33:\"edwiser-bridge/edwiser-bridge.php\";i:1;s:17:\"onelogin_saml.php\";}', 'yes'),
|
||||||
|
self.db.update("""INSERT INTO wp_options (option_name, option_value, autoload) VALUES
|
||||||
|
('onelogin_saml_enabled', 'on', 'yes'),
|
||||||
|
('onelogin_saml_idp_entityid', 'Saml Login', 'yes'),
|
||||||
|
('onelogin_saml_idp_sso', 'https://sso.%s/auth/realms/master/protocol/saml', 'yes'),
|
||||||
|
('onelogin_saml_idp_slo', 'https://sso.%s/auth/realms/master/protocol/saml', 'yes'),
|
||||||
|
('onelogin_saml_idp_x509cert', '%s', 'yes'),
|
||||||
|
('onelogin_saml_autocreate', 'on', 'yes'),
|
||||||
|
('onelogin_saml_updateuser', 'on', 'yes'),
|
||||||
|
('onelogin_saml_forcelogin', 'on', 'yes'),
|
||||||
|
('onelogin_saml_slo', 'on', 'yes'),
|
||||||
|
('onelogin_saml_keep_local_login', '', 'yes'),
|
||||||
|
('onelogin_saml_alternative_acs', '', 'yes'),
|
||||||
|
('onelogin_saml_account_matcher', 'username', 'yes'),
|
||||||
|
('onelogin_saml_trigger_login_hook', '', 'yes'),
|
||||||
|
('onelogin_saml_multirole', '', 'yes'),
|
||||||
|
('onelogin_saml_trusted_url_domains', '', 'yes'),
|
||||||
|
('onelogin_saml_attr_mapping_username', 'username', 'yes'),
|
||||||
|
('onelogin_saml_attr_mapping_mail', 'email', 'yes'),
|
||||||
|
('onelogin_saml_attr_mapping_firstname', 'givenName', 'yes'),
|
||||||
|
('onelogin_saml_attr_mapping_lastname', 'sn', 'yes'),
|
||||||
|
('onelogin_saml_attr_mapping_nickname', '', 'yes'),
|
||||||
|
('onelogin_saml_attr_mapping_role', 'Role', 'yes'),
|
||||||
|
('onelogin_saml_attr_mapping_rememberme', '', 'yes'),
|
||||||
|
('onelogin_saml_role_mapping_administrator', 'admin', 'yes'),
|
||||||
|
('onelogin_saml_role_mapping_editor', 'manager', 'yes'),
|
||||||
|
('onelogin_saml_role_mapping_author', 'coursecreator', 'yes'),
|
||||||
|
('onelogin_saml_role_mapping_contributor', 'teacher', 'yes'),
|
||||||
|
('onelogin_saml_role_mapping_subscriber', '', 'yes'),
|
||||||
|
('onelogin_saml_role_mapping_multivalued_in_one_attribute_value', 'on', 'yes'),
|
||||||
|
('onelogin_saml_role_mapping_multivalued_pattern', '', 'yes'),
|
||||||
|
('onelogin_saml_role_order_administrator', '', 'yes'),
|
||||||
|
('onelogin_saml_role_order_editor', '', 'yes'),
|
||||||
|
('onelogin_saml_role_order_author', '', 'yes'),
|
||||||
|
('onelogin_saml_role_order_contributor', '', 'yes'),
|
||||||
|
('onelogin_saml_role_order_subscriber', '', 'yes'),
|
||||||
|
('onelogin_saml_customize_action_prevent_local_login', '', 'yes'),
|
||||||
|
('onelogin_saml_customize_action_prevent_reset_password', '', 'yes'),
|
||||||
|
('onelogin_saml_customize_action_prevent_change_password', '', 'yes'),
|
||||||
|
('onelogin_saml_customize_action_prevent_change_mail', '', 'yes'),
|
||||||
|
('onelogin_saml_customize_stay_in_wordpress_after_slo', 'on', 'yes'),
|
||||||
|
('onelogin_saml_customize_links_user_registration', '', 'yes'),
|
||||||
|
('onelogin_saml_customize_links_lost_password', '', 'yes'),
|
||||||
|
('onelogin_saml_customize_links_saml_login', '', 'yes'),
|
||||||
|
('onelogin_saml_advanced_settings_debug', '', 'yes'),
|
||||||
|
('onelogin_saml_advanced_settings_strict_mode', '', 'yes'),
|
||||||
|
('onelogin_saml_advanced_settings_sp_entity_id', '', 'yes'),
|
||||||
|
('onelogin_saml_advanced_idp_lowercase_url_encoding', '', 'yes'),
|
||||||
|
('onelogin_saml_advanced_settings_nameid_encrypted', '', 'yes'),
|
||||||
|
('onelogin_saml_advanced_settings_authn_request_signed', 'on', 'yes'),
|
||||||
|
('onelogin_saml_advanced_settings_logout_request_signed', 'on', 'yes'),
|
||||||
|
('onelogin_saml_advanced_settings_logout_response_signed', 'on', 'yes'),
|
||||||
|
('onelogin_saml_advanced_settings_want_message_signed', '', 'yes'),
|
||||||
|
('onelogin_saml_advanced_settings_want_assertion_signed', '', 'yes'),
|
||||||
|
('onelogin_saml_advanced_settings_want_assertion_encrypted', '', 'yes'),
|
||||||
|
('onelogin_saml_advanced_settings_retrieve_parameters_from_server', '', 'yes'),
|
||||||
|
('onelogin_saml_advanced_nameidformat', 'unspecified', 'yes'),
|
||||||
|
('onelogin_saml_advanced_requestedauthncontext', '', 'yes'),
|
||||||
|
('onelogin_saml_advanced_settings_sp_x509cert', '%s', 'yes'),
|
||||||
|
('onelogin_saml_advanced_settings_sp_privatekey', '%s', 'yes'),
|
||||||
|
('onelogin_saml_advanced_signaturealgorithm', 'http://www.w3.org/2000/09/xmldsig#rsa-sha1', 'yes'),
|
||||||
|
('onelogin_saml_advanced_digestalgorithm', 'http://www.w3.org/2000/09/xmldsig#sha1', 'yes');""" % (os.environ['DOMAIN'],os.environ['DOMAIN'],self.parse_idp_cert(),app['config']['PUBLIC_CERT'],app['config']['PRIVATE_KEY']))
|
||||||
|
|
||||||
|
|
||||||
|
def reset_saml(self):
|
||||||
|
self.db.update("""DELETE FROM wp_options WHERE option_name LIKE 'onelogin_saml_%'""")
|
||||||
|
|
||||||
|
def add_keycloak_wordpress_saml(self):
|
||||||
|
client={"id" : "630601f8-25d1-4822-8741-c93affd2cd84",
|
||||||
|
"clientId" : "php-saml",
|
||||||
|
"surrogateAuthRequired" : False,
|
||||||
|
"enabled" : True,
|
||||||
|
"alwaysDisplayInConsole" : False,
|
||||||
|
"clientAuthenticatorType" : "client-secret",
|
||||||
|
"redirectUris" : [ "https://wp."+os.environ['DOMAIN']+"/wp-login.php?saml_acs" ],
|
||||||
|
"webOrigins" : [ "https://wp."+os.environ['DOMAIN'] ],
|
||||||
|
"notBefore" : 0,
|
||||||
|
"bearerOnly" : False,
|
||||||
|
"consentRequired" : False,
|
||||||
|
"standardFlowEnabled" : True,
|
||||||
|
"implicitFlowEnabled" : False,
|
||||||
|
"directAccessGrantsEnabled" : False,
|
||||||
|
"serviceAccountsEnabled" : False,
|
||||||
|
"publicClient" : False,
|
||||||
|
"frontchannelLogout" : True,
|
||||||
|
"protocol" : "saml",
|
||||||
|
"attributes" : {
|
||||||
|
"saml.force.post.binding" : True,
|
||||||
|
"saml_assertion_consumer_url_post" : "https://wp."+os.environ['DOMAIN']+"/wp-login.php?saml_acs",
|
||||||
|
"saml.server.signature" : True,
|
||||||
|
"saml.server.signature.keyinfo.ext" : False,
|
||||||
|
"saml.signing.certificate" : app['config']['PUBLIC_CERT_RAW'],
|
||||||
|
"saml_single_logout_service_url_redirect" : "https://wp."+os.environ['DOMAIN']+"/wp-login.php?saml_sls",
|
||||||
|
"saml.signature.algorithm" : "RSA_SHA256",
|
||||||
|
"saml_force_name_id_format" : False,
|
||||||
|
"saml.client.signature" : True,
|
||||||
|
"saml.authnstatement" : True,
|
||||||
|
"saml_name_id_format" : "username",
|
||||||
|
"saml_signature_canonicalization_method" : "http://www.w3.org/2001/10/xml-exc-c14n#"
|
||||||
|
},
|
||||||
|
"authenticationFlowBindingOverrides" : { },
|
||||||
|
"fullScopeAllowed" : True,
|
||||||
|
"nodeReRegistrationTimeout" : -1,
|
||||||
|
"protocolMappers" : [ {
|
||||||
|
"id" : "72c6175e-bd07-4c27-abd6-4e4ae38d834b",
|
||||||
|
"name" : "username",
|
||||||
|
"protocol" : "saml",
|
||||||
|
"protocolMapper" : "saml-user-attribute-mapper",
|
||||||
|
"consentRequired" : False,
|
||||||
|
"config" : {
|
||||||
|
"attribute.nameformat" : "Basic",
|
||||||
|
"user.attribute" : "username",
|
||||||
|
"friendly.name" : "username",
|
||||||
|
"attribute.name" : "username"
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"id" : "abd6562f-4732-4da9-987f-b1a6ad6605fa",
|
||||||
|
"name" : "roles",
|
||||||
|
"protocol" : "saml",
|
||||||
|
"protocolMapper" : "saml-role-list-mapper",
|
||||||
|
"consentRequired" : False,
|
||||||
|
"config" : {
|
||||||
|
"single" : True,
|
||||||
|
"attribute.nameformat" : "Basic",
|
||||||
|
"friendly.name" : "Roles",
|
||||||
|
"attribute.name" : "Role"
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"id" : "50aafb71-d91c-4bc7-bb60-e1ae0222aab3",
|
||||||
|
"name" : "email",
|
||||||
|
"protocol" : "saml",
|
||||||
|
"protocolMapper" : "saml-user-property-mapper",
|
||||||
|
"consentRequired" : False,
|
||||||
|
"config" : {
|
||||||
|
"attribute.nameformat" : "Basic",
|
||||||
|
"user.attribute" : "email",
|
||||||
|
"friendly.name" : "email",
|
||||||
|
"attribute.name" : "email"
|
||||||
|
}
|
||||||
|
} ],
|
||||||
|
"defaultClientScopes" : [ "web-origins", "role_list", "roles", "profile", "email" ],
|
||||||
|
"optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ],
|
||||||
|
"access" : {
|
||||||
|
"view" : True,
|
||||||
|
"configure" : True,
|
||||||
|
"manage" : True
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.connect()
|
||||||
|
self.keycloak.add_client(client)
|
||||||
|
self.keycloak=None
|
||||||
|
|
||||||
|
def add_client_roles(self):
|
||||||
|
self.connect()
|
||||||
|
self.keycloak.add_client_role('630601f8-25d1-4822-8741-c93affd2cd84','admin','Moodle admins')
|
||||||
|
self.keycloak.add_client_role('630601f8-25d1-4822-8741-c93affd2cd84','manager','Moodle managers')
|
||||||
|
self.keycloak.add_client_role('630601f8-25d1-4822-8741-c93affd2cd84','teacher','Moodle teachers')
|
||||||
|
self.keycloak.add_client_role('630601f8-25d1-4822-8741-c93affd2cd84','student','Moodle students')
|
||||||
|
self.keycloak=None
|
||||||
|
|
||||||
|
nw=WordpressSaml()
|
|
@ -28,6 +28,8 @@ services:
|
||||||
- KEYCLOAK_PASSWORD=${KEYCLOAK_PASSWORD}
|
- KEYCLOAK_PASSWORD=${KEYCLOAK_PASSWORD}
|
||||||
- PROXY_ADDRESS_FORWARDING=true
|
- PROXY_ADDRESS_FORWARDING=true
|
||||||
- KEYCLOAK_FRONTEND_URL=https://sso.${DOMAIN}/auth/
|
- KEYCLOAK_FRONTEND_URL=https://sso.${DOMAIN}/auth/
|
||||||
|
- DDADMIN_USER=${DDADMIN_USER}
|
||||||
|
- DDADMIN_PASSWORD=${DDADMIN_PASSWORD}
|
||||||
#- KEYCLOAK_LOGLEVEL=ALL
|
#- KEYCLOAK_LOGLEVEL=ALL
|
||||||
#- Dkeycloak.profile.feature.upload_scripts=enabled
|
#- Dkeycloak.profile.feature.upload_scripts=enabled
|
||||||
depends_on:
|
depends_on:
|
||||||
|
|
|
@ -15,3 +15,6 @@
|
||||||
# #curl https://moodle.isardvdi.site/auth/saml2/sp/metadata.php
|
# #curl https://moodle.isardvdi.site/auth/saml2/sp/metadata.php
|
||||||
|
|
||||||
# # Import as client provider
|
# # Import as client provider
|
||||||
|
|
||||||
|
|
||||||
|
# get-roles --cclientid test-client --rolename operations
|
||||||
|
|
Loading…
Reference in New Issue