univention-app/inst

477 строки
21 KiB
Bash

#!/bin/bash
# @copyright Copyright (c) 2020 Arthur Schiwon <blizzz@arthur-schiwon.de>
#
# @author Arthur Schiwon <blizzz@arthur-schiwon.de>
#
# @license GNU AGPL version 3 or any later version
#
# This program 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.
#
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
VERSION=3
SERVICE="Nextcloud"
ARGS=("$@")
getarg() { # by Univention
local found=0
for arg in "${ARGS[@]}"; do
if [ "$found" -eq 1 ]; then
echo "$arg"
break
fi
if [ "$arg" = "$1" ]; then
found=1
fi
done
}
ERROR_FILE=$(getarg "--error-file")
. /usr/share/univention-join/joinscripthelper.lib
. /usr/share/univention-appcenter/joinscripthelper.sh
. /usr/share/univention-lib/ldap.sh
joinscript_init
eval "$(ucr shell)"
NC_PERMCONFDIR="/var/lib/univention-appcenter/apps/nextcloud/data/integration"
NC_ADMIN_PWD_FILE="$NC_PERMCONFDIR/admin.secret"
NC_MEMBER_OF=0
HOST="https://${hostname}.${domainname}/nextcloud"
IS_UPDATE=false
NC_LDAP_BIND_DN="$appcenter_apps_nextcloud_hostdn"
NC_LDAP_BIND_PW_FILE="$(joinscript_container_file /etc/machine.secret)"
NC_LDAP_BIND_PW="$(< $NC_LDAP_BIND_PW_FILE)"
NC_ADDITIONAL_CURL_ARGS=
NC_OFFICE_SUITE="oo_community" # fallback
nextcloud_main() {
if [ -e "$NC_PERMCONFDIR/initial_config_done" ] ; then
IS_UPDATE=true
fi
ucs_addServiceToLocalhost "${SERVICE}" "$@"
nextcloud_appliance_detection
if [ "$JS_LAST_EXECUTED_VERSION" = 1 ]; then
nextcloud_update_ldap_bind_account
fi
nextcloud_ensure_ucr
nextcloud_attempt_memberof_support
joinscript_register_schema "$@"
nextcloud_ensure_extended_attributes "$@"
nextcloud_configure_saml "$@"
nextcloud_configure_ldap_backend
nextcloud_modify_users "$@"
nextcloud_add_Administrator_to_admin_group
nextcloud_mark_initial_conig_done
detect_collabora
detect_onlyoffice
ensure_office
joinscript_save_current_version
exit 0
}
error_msg() {
if [ -n "$1" ]; then
IN="$@"
else
read IN # from stdin
fi
if [ -n "$ERROR_FILE" ]; then
echo "$IN" | tee -a "$ERROR_FILE" >&2
else
echo "$IN" >&2
fi
}
die() {
error_msg "$@"
exit 1
}
nextcloud_appliance_detection() {
appliance_id=$(ucr get umc/web/appliance/id)
if [ "$appliance_id" = "nextcloud" ] || [ "$appliance_id" = "collabora" ] || [ "$appliance_id" = "collabora-online" ] || [ "$appliance_id" = "onlyoffice-ds" ]; then
# On appliance mode, the server works with a preliminary, unknown cert
NC_ADDITIONAL_CURL_ARGS="--insecure"
echo "Appliance mode has been detected for $appliance_id."
fi
}
# ensures that UCR variables are set. They can be used to pre-set Nextcloud settings before install
nextcloud_ensure_ucr() {
ucr set nextcloud/ucs/modifyUsersFilter?"(&(|(&(objectClass=posixAccount) (objectClass=shadowAccount)) (objectClass=univentionMail) (objectClass=sambaSamAccount) (objectClass=simpleSecurityObject) (&(objectClass=person) (objectClass=organizationalPerson) (objectClass=inetOrgPerson))) (!(uidNumber=0)) (!(|(uid=*$) (uid=nextcloud-systemuser) (uid=join-backup) (uid=join-slave))) (!(objectClass=nextcloudUser)))" \
nextcloud/ucs/userEnabled?"1" \
nextcloud/ucs/userQuota?"" \
nextcloud/ucs/debug?"0" \
nextcloud/ldap/cacheTTL?"600" \
nextcloud/ldap/homeFolderAttribute?"" \
nextcloud/ldap/userSearchAttributes?"uid;givenName;sn;employeeNumber;mailPrimaryAddress" \
nextcloud/ldap/userDisplayName?"displayName" \
nextcloud/ldap/groupDisplayName?"cn" \
nextcloud/ldap/base?"$ldap_base" \
nextcloud/ldap/baseUsers?"$ldap_base" \
nextcloud/ldap/baseGroups?"$ldap_base" \
nextcloud/ldap/filterLogin?"(&(objectclass=nextcloudUser)(nextcloudEnabled=1)(uid=%uid))" \
nextcloud/ldap/filterUsers?"(&(objectclass=nextcloudUser)(nextcloudEnabled=1))" \
nextcloud/ldap/filterGroups?"(&(objectclass=nextcloudGroup)(nextcloudEnabled=1))" \
eval "$(ucr shell)"
}
# installs the memberof-overlay and saves the state in NC_MEMBER_OF
nextcloud_attempt_memberof_support() {
NC_MEMBER_OF=`dpkg-query -W -f='${Status}\n' univention-ldap-overlay-memberof | grep Installed | grep "^i" -c`
}
# update ldap bind account to nextcloud user
nextcloud_update_ldap_bind_account() {
local data
local admin_password=`cat "$NC_ADMIN_PWD_FILE"`
local configid="s01" # reasonable fall back. in v1 of the join script the configid was not saved.
if [ -e "$NC_PERMCONFDIR/ldap-config-id" ]; then
configid=`cat "$NC_PERMCONFDIR/ldap-config-id"`
fi
data="configData[ldapAgentName]="`nextcloud_urlEncode "$NC_LDAP_BIND_DN"`
data+="&configData[ldapAgentPassword]="`nextcloud_urlEncode "$NC_LDAP_BIND_PW"`
nextcloud_curl -X PUT -d "$data" \
-H "OCS-APIREQUEST: true" -u "nc_admin:$admin_password" $NC_ADDITIONAL_CURL_ARGS \
"$HOST/ocs/v2.php/apps/user_ldap/api/v1/config/$configid"
}
# configures the LDAP backend at Nextcloud using its OCS API
nextcloud_configure_ldap_backend() {
if [ $IS_UPDATE = true ] ; then
echo "Not attempting to set LDAP configuration, because NC is already installed and set up."
nextcloud_update_ldap_backend_password_if_necessary
return
fi
local NC_ADMIN_PWD=`cat "$NC_ADMIN_PWD_FILE"`
data="configData[ldapHost]="`nextcloud_urlEncode "$ldap_server_name"`
data+="&configData[ldapPort]="`nextcloud_urlEncode "$ldap_server_port"`
data+="&configData[ldapTLS]=1"
data+="&configData[ldapAgentName]="`nextcloud_urlEncode "$NC_LDAP_BIND_DN"`
data+="&configData[ldapAgentPassword]="`nextcloud_urlEncode "$NC_LDAP_BIND_PW"`
data+="&configData[ldapBase]="`nextcloud_urlEncode "$nextcloud_ldap_base"`
data+="&configData[ldapBaseUsers]="`nextcloud_urlEncode "$nextcloud_ldap_baseUsers"`
data+="&configData[ldapBaseGroups]="`nextcloud_urlEncode "$nextcloud_ldap_baseGroups"`
data+="&configData[ldapUserFilter]="`nextcloud_urlEncode "$nextcloud_ldap_filterUsers"`
data+="&configData[ldapUserFilterMode]=1"
data+="&configData[ldapLoginFilter]="`nextcloud_urlEncode "$nextcloud_ldap_filterLogin"`
data+="&configData[ldapLoginFilterMode]=1"
data+="&configData[ldapLoginFilterUsername]=1"
data+="&configData[ldapGroupFilter]="`nextcloud_urlEncode "$nextcloud_ldap_filterGroups"`
data+="&configData[ldapGroupFilterMode]=1"
data+="&configData[ldapGroupFilterObjectclass]=nextcloudGroup"
data+="&configData[ldapUserDisplayName]="`nextcloud_urlEncode "$nextcloud_ldap_userDisplayName"`
data+="&configData[ldapGroupDisplayName]="`nextcloud_urlEncode "$nextcloud_ldap_groupDisplayName"`
data+="&configData[ldapEmailAttribute]=mail"
data+="&configData[ldapQuotaAttribute]=nextcloudQuota"
data+="&configData[homeFolderNamingRule]="`nextcloud_urlEncode "$nextcloud_ldap_homeFolderAttribute"`
data+="&configData[ldapGroupMemberAssocAttr]=uniqueMember"
data+="&configData[ldapCacheTTL]="`nextcloud_urlEncode "$nextcloud_ldap_cacheTTL"`
data+="&configData[ldapConfigurationActive]=1"
data+="&configData[ldapAttributesForUserSearch]="`nextcloud_urlEncode "$nextcloud_ldap_userSearchAttributes"`
data+="&configData[ldapExpertUsernameAttr]=uid"
data+="&configData[ldapExpertUUIDUserAttr]="
data+="&configData[useMemberOfToDetectMembership]=$NC_MEMBER_OF"
data+="&configData[ldapNestedGroups]=0"
data+="&configData[turnOnPasswordChange]=0"
data+="&configData[ldapExperiencedAdmin]=1"
RESULT=`nextcloud_curl -X POST -H "OCS-APIREQUEST: true" -u "nc_admin:$NC_ADMIN_PWD" \
$NC_ADDITIONAL_CURL_ARGS \
"$HOST/ocs/v2.php/apps/user_ldap/api/v1/config"` \
|| die "Failed to request an LDAP config id from Nextcloud"
STATUS=`echo $RESULT | grep "<statuscode>200</statuscode>" -c`
if [ ! $STATUS -eq 1 ] ; then
die "Could not create LDAP Config at Nextcloud"
fi
CONFIGID=`echo $RESULT | grep -oP '(?<=<configID>).*?(?=</configID>)'`
echo "$CONFIGID" > "$NC_PERMCONFDIR/ldap-config-id"
nextcloud_curl -X PUT -d "$data" -H "OCS-APIREQUEST: true" -u "nc_admin:$NC_ADMIN_PWD" \
$NC_ADDITIONAL_CURL_ARGS \
"$HOST/ocs/v2.php/apps/user_ldap/api/v1/config/$CONFIGID" \
|| die "Configuring LDAP Backend failed"
}
nextcloud_update_ldap_backend_password_if_necessary() {
# when the original user is configured, update the password to ensure it is set correctly even on a reinstall
# that kept the data and config from the previous installation
CONFIGID=$(< "$NC_PERMCONFDIR/ldap-config-id")
if [[ -z "$CONFIGID" ]]; then
return
fi
LDAP_CON_STATE=$(univention-app shell nextcloud sudo -u www-data /var/www/html/occ ldap:test-config $CONFIGID)
if [[ "$LDAP_CON_STATE" != "The configuration is valid and the connection could be established!" ]] ; then
echo "Updating LDAP bind credentials"
univention-app shell nextcloud sudo -u www-data /var/www/html/occ ldap:set-config "$CONFIGID" ldapAgentName "$NC_LDAP_BIND_DN"
univention-app shell nextcloud sudo -u www-data /var/www/html/occ ldap:set-config "$CONFIGID" ldapAgentPassword "$NC_LDAP_BIND_PW"
fi
}
nextcloud_add_Administrator_to_admin_group() {
if [ $IS_UPDATE = true ] ; then
echo "Not attempting to add Administrator to admin group, because NC is already installed and set up."
return
fi
. /usr/share/univention-lib/base.sh
local NC_ADMIN_PWD=`cat "$NC_ADMIN_PWD_FILE"`
local ADMIN_NAME="$(custom_username Administrator)"
# triggers the mapping
RESULT=`nextcloud_curl -X GET -H "OCS-APIREQUEST: true" -u "nc_admin:$NC_ADMIN_PWD" $NC_ADDITIONAL_CURL_ARGS \
"$HOST/ocs/v2.php/cloud/users?search=$ADMIN_NAME"` \
|| die "Failed to fetch Administrator user in Nextcloud"
STATUS=`echo $RESULT | grep "<element>$ADMIN_NAME</element>" -c`
if [ ! $STATUS -eq 1 ] ; then
echo "Could not add Administrator to admin group, because user was not found:"
echo $RESULT
return
fi
RESULT=`nextcloud_curl -X POST -d "groupid=admin" -H "OCS-APIREQUEST: true" -u "nc_admin:$NC_ADMIN_PWD" $NC_ADDITIONAL_CURL_ARGS \
"$HOST/ocs/v2.php/cloud/users/$ADMIN_NAME/groups"` \
|| die "Failed to add Administrator to admin group at Nextcloud"
STATUS=`echo $RESULT | grep "<statuscode>200</statuscode>" -c`
if [ ! $STATUS -eq 1 ] ; then
echo "Could not add Administrator to admin group, because adding as group member failed:"
echo $RESULT
return
fi
}
nextcloud_urlEncode() {
python -c 'import urllib, sys; print urllib.quote(sys.argv[1], sys.argv[2])' \
"$1" ""
}
# adds extended attributes to UCS so admins can enable or disable Nextcloud access for users and groups
nextcloud_ensure_extended_attributes () {
univention-directory-manager container/cn create "$@" --ignore_exists \
--position "cn=custom attributes,cn=univention,$ldap_base" \
--set name=nextcloud
univention-directory-manager settings/extended_attribute create "$@" \
--position "cn=nextcloud,cn=custom attributes,cn=univention,$ldap_base" --set module="users/user" \
--set ldapMapping='nextcloudEnabled' \
--set objectClass='nextcloudUser' \
--set name='nextcloudUserEnabled' \
--set shortDescription='Access to Nextcloud' \
--set longDescription='Whether user may access Nextcloud' \
--set translationShortDescription='"de_DE" "Zugang für Nextloud"' \
--set translationLongDescription='"de_DE" "Der Benutzer kann auf Nextcloud zugreifen"' \
--set tabName='Nextcloud' \
--set translationTabName='"de_DE" "Nextcloud"' \
--set overwriteTab='0' \
--set valueRequired='0' \
--set CLIName='nextcloudEnabled' \
--set syntax='boolean' \
--set default="1" \
--set tabAdvanced='1' \
--set mayChange='1' \
--set multivalue='0' \
--set deleteObjectClass='0' \
--set tabPosition='1' \
--set overwritePosition='0' \
--set doNotSearch='0' \
--set hook='None' || \
univention-directory-manager settings/extended_attribute modify "$@" \
--dn "cn=nextcloudUserEnabled,cn=nextcloud,cn=custom attributes,cn=univention,$ldap_base" \
--set tabAdvanced='1' \
--set default="1" || die "Could not modify nextcloudUserEnabled extended attribute"
univention-directory-manager settings/extended_attribute create "$@" \
--position "cn=nextcloud,cn=custom attributes,cn=univention,$ldap_base" --set module="users/user" \
--set ldapMapping='nextcloudQuota' \
--set objectClass='nextcloudUser' \
--set name='nextcloudUserQuota' \
--set shortDescription='Nextcloud Quota' \
--set longDescription='Amount of storage available to the user (ex: 512 MB or 12 GB)' \
--set translationShortDescription='"de_DE" "Nextcloud Quota"' \
--set translationLongDescription='"de_DE" "Der verfügbare Speicherplatz für den Benutzer (z.B. 512 MB oder 12 GB)"' \
--set tabName='Nextcloud' \
--set translationTabName='"de_DE" "Nextcloud"' \
--set overwriteTab='0' \
--set valueRequired='0' \
--set CLIName='nextcloudQuota' \
--set syntax='string' \
--set default="" \
--set tabAdvanced='1' \
--set mayChange='1' \
--set multivalue='0' \
--set deleteObjectClass='0' \
--set tabPosition='1' \
--set overwritePosition='0' \
--set doNotSearch='0' \
--set hook='None' || \
univention-directory-manager settings/extended_attribute modify "$@" \
--dn "cn=nextcloudUserQuota,cn=nextcloud,cn=custom attributes,cn=univention,$ldap_base" \
--set tabAdvanced='1' || die "Could not modify nextcloudUserQuota extended attribute"
univention-directory-manager settings/extended_attribute create "$@" \
--position "cn=nextcloud,cn=custom attributes,cn=univention,$ldap_base" --set module="groups/group" \
--set ldapMapping='nextcloudEnabled' \
--set objectClass='nextcloudGroup' \
--set name='nextcloudGroupEnabled' \
--set shortDescription='Available in Nextcloud' \
--set longDescription='The group is available in Nextcloud' \
--set translationShortDescription='"de_DE" "In Nextcloud verfügbar"' \
--set translationLongDescription='"de_DE" "Die Gruppe ist in Nextcloud verfügbar"' \
--set tabName='Nextcloud' \
--set translationTabName='"de_DE" "Nextcloud"' \
--set overwriteTab='0' \
--set valueRequired='0' \
--set CLIName='nextcloudEnabled' \
--set syntax='boolean' \
--set default="0" \
--set tabAdvanced='0' \
--set mayChange='1' \
--set multivalue='0' \
--set deleteObjectClass='0' \
--set tabPosition='1' \
--set overwritePosition='0' \
--set doNotSearch='0' \
--set hook='None' || \
univention-directory-manager settings/extended_attribute modify "$@" \
--dn "cn=nextcloudGroupEnabled,cn=nextcloud,cn=custom attributes,cn=univention,$ldap_base" \
--set tabAdvanced='1' || die "Could not modify nextcloudGroupEnabled extended attribute"
}
nextcloud_configure_saml() {
udm saml/serviceprovider create "$@" \
--ignore_exists \
--position "cn=saml-serviceprovider,cn=univention,$ldap_base" \
--set isActivated=TRUE \
--set Identifier="https://$hostname.$domainname/nextcloud/apps/user_saml/saml/metadata" \
--set NameIDFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" \
--set simplesamlAttributes=TRUE \
--set AssertionConsumerService="https://$hostname.$domainname/nextcloud/apps/user_saml/saml/acs" \
--set simplesamlNameIDAttribute="uid" \
--set singleLogoutService="https://$hostname.$domainname/nextcloud/apps/user_saml/saml/sls" || die
IDP_CERT=$(curl -s https://"${ucs_server_sso_fqdn:-ucs-sso.$domainname}"/simplesamlphp/saml2/idp/certificate | sed -ne '
/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p # got the range, ok
/-END CERTIFICATE-/q # bailing out soon as the cert end seen
')
SETCMD="univention-app shell nextcloud sudo -u www-data /var/www/html/occ config:app:set user_saml"
$SETCMD idp-x509cert --value="$IDP_CERT"
$SETCMD type --value="saml"
$SETCMD general-require_provisioned_account --value="1"
$SETCMD general-allow_multiple_user_back_ends --value="1"
$SETCMD general-uid_mapping --value="uid"
$SETCMD idp-singleLogoutService.url --value="https://$ucs_server_sso_fqdn/simplesamlphp/saml2/idp/SingleLogoutService.php"
$SETCMD idp-singleSignOnService.url --value="https://$ucs_server_sso_fqdn/simplesamlphp/saml2/idp/SSOService.php"
$SETCMD idp-entityId --value="https://$ucs_server_sso_fqdn/simplesamlphp/saml2/idp/metadata.php"
}
# Enables all Users that fit the filter to access Nextcloud
nextcloud_modify_users() {
if [ $IS_UPDATE = true ] || [ -z "$nextcloud_ucs_modifyUsersFilter" ] ; then
echo "Not attempting to modify users."
return
fi
SP_DN=$(univention-ldapsearch -LLL SAMLServiceProviderIdentifier=https://$hostname.$domainname/nextcloud/apps/user_saml/saml/metadata dn | cut -d ' ' -f 2)
for dn in $(udm users/user list "$@" --filter "$nextcloud_ucs_modifyUsersFilter" | sed -ne 's/^DN: //p') ; do
echo "modifying $dn .."
udm users/user modify "$@" --dn "$dn" \
--set nextcloudEnabled="$nextcloud_ucs_userEnabled" \
--set nextcloudQuota="$nextcloud_ucs_userQuota" \
--append serviceprovider="$SP_DN"
done
}
nextcloud_mark_initial_conig_done() {
touch "$NC_PERMCONFDIR/initial_config_done" || die "Could not touch initial config flag"
}
nextcloud_curl() {
local result
local curlCode
result=$(curl -s "$@")
curlCode=$?
#echo "curl exit code $curlCode params $@" > /dev/stderr
if [ ! ${curlCode} -eq 0 ]; then
debugOutput=""
if [ "$nextcloud_ucs_debug" -eq 1 ]; then
debugOutput=", parameters were\n\t$@"
fi
error_msg "curl failed with error $curlCode$debugOutput"
exit ${curlCode}
fi
echo "$result"
}
detect_collabora () {
# When Collabora (CODE) or Collabora Online is already installed on the UCS system when Nextcloud is going to be installed,
# the richdocuments app is enabled and the WOPI URL is configured to the local system, if not already configured.
# If the app is not present, the richdocuments app is disabled
FQDN="$(ucr get hostname).$(ucr get domainname)"
echo "Check for richdocuments app"
if [ "$(ucr get appcenter/apps/collabora/status)" = "installed" ] || [ "$(ucr get appcenter/apps/collabora-online/status)" = "installed" ] ; then
NC_OFFICE_SUITE=collabora
univention-app shell nextcloud sudo -u www-data /var/www/html/occ app:enable richdocuments
occCode=$?
if [ ${occCode} -eq 0 ] && [ "$(univention-app shell nextcloud sudo -u www-data /var/www/html/occ config:app:get richdocuments wopi_url)" = "" ] ; then
univention-app shell nextcloud sudo -u www-data /var/www/html/occ config:app:set richdocuments wopi_url --value="https://$FQDN/"
fi
fi
}
detect_onlyoffice () {
# When ONLYOFFICE is already installed on the UCS system when Nextcloud is going to be installed,
# the onlyoffice app is enabled and the DocumentServerUrl is configured to the local system, if not already configured.
# If the app is not present, the onlyoffice app is disabled
FQDN="$(ucr get hostname).$(ucr get domainname)"
echo "Check for onlyoffice app"
if [ "$(ucr get appcenter/apps/onlyoffice-ds/status)" = "installed" ] ; then
NC_OFFICE_SUITE=onlyoffice
univention-app shell nextcloud sudo -u www-data /var/www/html/occ app:enable onlyoffice
occCode=$?
if [ ${occCode} -eq 0 ] && [ "$(univention-app shell nextcloud sudo -u www-data /var/www/html/occ config:app:get onlyoffice DocumentServerUrl)" = "" ] ; then
univention-app shell nextcloud sudo -u www-data /var/www/html/occ config:app:set onlyoffice DocumentServerUrl --value="https://$FQDN/onlyoffice-documentserver"
fi
fi
}
ensure_office () {
if [[ "$NC_OFFICE_SUITE" = "oo_community" ]] && [[ "$IS_UPDATE" = false ]] ; then
echo -n "No office suite present – installing Community Document Server"
nohup univention-app shell nextcloud sudo -u www-data /var/www/html/occ app:enable documentserver_community &
PID=$!
while ps --pid ${PID} > /dev/null; do
echo -n .
sleep 3
done
echo
univention-app shell nextcloud sudo -u www-data /var/www/html/occ app:enable onlyoffice
fi
}
if [ "$JS_LAST_EXECUTED_VERSION" = 2 ]; then
ucr commit /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/default-ssl.conf
joinscript_save_current_version
else
nextcloud_main "$@"
fi