165 lines
6.0 KiB
Python
165 lines
6.0 KiB
Python
#
|
|
# Copyright © 2021,2022 IsardVDI S.L.
|
|
#
|
|
# This file is part of DD
|
|
#
|
|
# DD is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU Affero General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or (at your
|
|
# option) any later version.
|
|
#
|
|
# DD is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
|
# details.
|
|
#
|
|
# You should have received a copy of the GNU Affero General Public License
|
|
# along with DD. If not, see <https://www.gnu.org/licenses/>.
|
|
#
|
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
import json
|
|
import logging as log
|
|
import os
|
|
import pprint
|
|
import random
|
|
import string
|
|
import time
|
|
import traceback
|
|
from datetime import datetime, timedelta
|
|
|
|
import psycopg2
|
|
import yaml
|
|
from admin.lib.keycloak_client import KeycloakClient
|
|
from admin.lib.postgres import Postgres
|
|
|
|
app = {}
|
|
app["config"] = {}
|
|
|
|
|
|
class NextcloudSaml:
|
|
def __init__(self):
|
|
self.url = "http://dd-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.pg = Postgres(
|
|
"dd-apps-postgresql",
|
|
"nextcloud",
|
|
os.environ["NEXTCLOUD_POSTGRES_USER"],
|
|
os.environ["NEXTCLOUD_POSTGRES_PASSWORD"],
|
|
)
|
|
ready = True
|
|
except:
|
|
log.warning("Could not connect to nextcloud database. Retrying...")
|
|
time.sleep(2)
|
|
log.info("Connected to nextcloud database.")
|
|
|
|
ready = False
|
|
while not ready:
|
|
try:
|
|
with open(os.path.join("./saml_certs/public.cert"), "r") as crt:
|
|
app["config"]["PUBLIC_CERT"] = crt.read()
|
|
ready = True
|
|
except IOError:
|
|
log.warning(
|
|
"Could not get public certificate to be used in nextcloud. 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 nextcloud.")
|
|
|
|
ready = False
|
|
while not ready:
|
|
try:
|
|
with open(os.path.join("./saml_certs/private.key"), "r") as pem:
|
|
app["config"]["PRIVATE_KEY"] = pem.read()
|
|
ready = True
|
|
except IOError:
|
|
log.warning(
|
|
"Could not get private key to be used in nextcloud. 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 nextcloud.")
|
|
|
|
# ## 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_certs()
|
|
except:
|
|
print("Error resetting saml on nextcloud")
|
|
|
|
try:
|
|
self.set_nextcloud_saml_plugin_certs()
|
|
except:
|
|
log.error(traceback.format_exc())
|
|
print("Error adding saml on nextcloud")
|
|
|
|
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.pg.update("""UPDATE "mdl_config" SET value = 'email,saml2' WHERE "name" = 'auth'""")
|
|
|
|
# def get_privatekey_pass(self):
|
|
# return self.pg.select("""SELECT * FROM "mdl_config" WHERE "name" = 'siteidentifier'""")[0][2]
|
|
|
|
def parse_idp_cert(self):
|
|
self.connect()
|
|
rsa = self.keycloak.get_server_rsa_key()
|
|
self.keycloak = None
|
|
return rsa["certificate"]
|
|
|
|
def set_nextcloud_saml_plugin_certs(self):
|
|
self.pg.update(
|
|
"""INSERT INTO "oc_appconfig" ("appid", "configkey", "configvalue") VALUES
|
|
('user_saml', 'sp-privateKey', '%s'),
|
|
('user_saml', 'idp-x509cert', '%s'),
|
|
('user_saml', 'sp-x509cert', '%s');"""
|
|
% (
|
|
app["config"]["PRIVATE_KEY"],
|
|
self.parse_idp_cert(),
|
|
app["config"]["PUBLIC_CERT"],
|
|
)
|
|
)
|
|
|
|
def reset_saml_certs(self):
|
|
cfg_list = ["sp-privateKey", "idp-x509cert", "sp-x509cert"]
|
|
for cfg in cfg_list:
|
|
self.pg.update(
|
|
"""DELETE FROM "oc_appconfig" WHERE appid = 'user_saml' AND configkey = '%s'"""
|
|
% (cfg)
|
|
)
|
|
|
|
|
|
n = NextcloudSaml()
|