diff --git a/bin/yunoprompt b/bin/yunoprompt new file mode 100755 index 000000000..de05dd6fa --- /dev/null +++ b/bin/yunoprompt @@ -0,0 +1,74 @@ +#!/bin/bash + +# Fetch ips +ip=$(hostname --all-ip-address) + +# Fetch SSH fingerprints +i=0 +for key in /etc/ssh/ssh_host_*_key.pub ; do + output=$(ssh-keygen -l -f $key) + fingerprint[$i]=" - $(echo $output | cut -d' ' -f2) $(echo $output| cut -d' ' -f4)" + i=$(($i + 1)) +done + +# +# Build the logo +# + +LOGO=$(cat << 'EOF' + __ __ __ __ __ _ _______ __ __ _______ _______ _______ + | | | || | | || | | || || | | || || || | + | |_| || | | || |_| || _ || |_| || _ || _____||_ _| + | || |_| || || | | || || | | || |_____ | | + |_ _|| || _ || |_| || _ || |_| ||_____ | | | + | | | || | | || || | | || | _____| | | | + |___| |_______||_| |__||_______||__| |__||_______||_______| |___| +EOF +) + +# ' Put a quote in comment to make vim happy about syntax highlighting :s + +# +# Build the actual message +# + +LOGO_AND_FINGERPRINTS=$(cat << EOF + +$LOGO + + IP: ${ip} + SSH fingerprints: + ${fingerprint[0]} + ${fingerprint[1]} + ${fingerprint[2]} + ${fingerprint[3]} + ${fingerprint[4]} + +EOF +) + +if [[ -f /etc/yunohost/installed ]] +then + echo "$LOGO_AND_FINGERPRINTS" > /etc/issue +else + sleep 5 + chvt 2 + echo "$LOGO_AND_FINGERPRINTS" + echo -e "\e[m Post-installation \e[0m" + echo "Congratulations! YunoHost has been successfully installed.\nTwo more steps are required to activate the services of your server." + read -p "Proceed to post-installation? (y/n) " -n 1 + RESULT=1 + while [ $RESULT -gt 0 ]; do + if [[ $REPLY =~ ^[Nn]$ ]]; then + chvt 1 + exit 0 + fi + echo -e "\n" + /usr/bin/yunohost tools postinstall + let RESULT=$? + if [ $RESULT -gt 0 ]; then + echo -e "\n" + read -p "Retry? (y/n) " -n 1 + fi + done +fi diff --git a/data/helpers.d/psql b/data/helpers.d/psql new file mode 100644 index 000000000..ddacbef8c --- /dev/null +++ b/data/helpers.d/psql @@ -0,0 +1,150 @@ +# Create a master password and set up global settings +# Please always call this script in install and restore scripts +# +# usage: ynh_psql_test_if_first_run +ynh_psql_test_if_first_run() { + if [ -f /etc/yunohost/psql ]; + then + echo "PostgreSQL is already installed, no need to create master password" + else + pgsql=$(ynh_string_random) + pg_hba="" + echo "$pgsql" >> /etc/yunohost/psql + + if [ -e /etc/postgresql/9.4/ ] + then + pg_hba=/etc/postgresql/9.4/main/pg_hba.conf + elif [ -e /etc/postgresql/9.6/ ] + then + pg_hba=/etc/postgresql/9.6/main/pg_hba.conf + else + ynh_die "postgresql shoud be 9.4 or 9.6" + fi + + systemctl start postgresql + sudo --login --user=postgres psql -c"ALTER user postgres WITH PASSWORD '$pgsql'" postgres + + # force all user to connect to local database using passwords + # https://www.postgresql.org/docs/current/static/auth-pg-hba-conf.html#EXAMPLE-PG-HBA.CONF + # Note: we can't use peer since YunoHost create users with nologin + # See: https://github.com/YunoHost/yunohost/blob/unstable/data/helpers.d/user + sed -i '/local\s*all\s*all\s*peer/i \ + local all all password' "$pg_hba" + systemctl enable postgresql + systemctl reload postgresql + fi +} + +# Open a connection as a user +# +# example: ynh_psql_connect_as 'user' 'pass' <<< "UPDATE ...;" +# example: ynh_psql_connect_as 'user' 'pass' < /path/to/file.sql +# +# usage: ynh_psql_connect_as user pwd [db] +# | arg: user - the user name to connect as +# | arg: pwd - the user password +# | arg: db - the database to connect to +ynh_psql_connect_as() { + user="$1" + pwd="$2" + db="$3" + sudo --login --user=postgres PGUSER="$user" PGPASSWORD="$pwd" psql "$db" +} + +# # Execute a command as root user +# +# usage: ynh_psql_execute_as_root sql [db] +# | arg: sql - the SQL command to execute +# | arg: db - the database to connect to +ynh_psql_execute_as_root () { + sql="$1" + sudo --login --user=postgres psql <<< "$sql" +} + +# Execute a command from a file as root user +# +# usage: ynh_psql_execute_file_as_root file [db] +# | arg: file - the file containing SQL commands +# | arg: db - the database to connect to +ynh_psql_execute_file_as_root() { + file="$1" + db="$2" + sudo --login --user=postgres psql "$db" < "$file" +} + +# Create a database, an user and its password. Then store the password in the app's config +# +# After executing this helper, the password of the created database will be available in $db_pwd +# It will also be stored as "psqlpwd" into the app settings. +# +# usage: ynh_psql_setup_db user name [pwd] +# | arg: user - Owner of the database +# | arg: name - Name of the database +# | arg: pwd - Password of the database. If not given, a password will be generated +ynh_psql_setup_db () { + db_user="$1" + db_name="$2" + new_db_pwd=$(ynh_string_random) # Generate a random password + # If $3 is not given, use new_db_pwd instead for db_pwd. + db_pwd="${3:-$new_db_pwd}" + ynh_psql_create_db "$db_name" "$db_user" "$db_pwd" # Create the database + ynh_app_setting_set "$app" psqlpwd "$db_pwd" # Store the password in the app's config +} + +# Create a database and grant privilegies to a user +# +# usage: ynh_psql_create_db db [user [pwd]] +# | arg: db - the database name to create +# | arg: user - the user to grant privilegies +# | arg: pwd - the user password +ynh_psql_create_db() { + db="$1" + user="$2" + pwd="$3" + ynh_psql_create_user "$user" "$pwd" + sudo --login --user=postgres createdb --owner="$user" "$db" +} + +# Drop a database +# +# usage: ynh_psql_drop_db db +# | arg: db - the database name to drop +# | arg: user - the user to drop +ynh_psql_remove_db() { + db="$1" + user="$2" + sudo --login --user=postgres dropdb "$db" + ynh_psql_drop_user "$user" +} + +# Dump a database +# +# example: ynh_psql_dump_db 'roundcube' > ./dump.sql +# +# usage: ynh_psql_dump_db db +# | arg: db - the database name to dump +# | ret: the psqldump output +ynh_psql_dump_db() { + db="$1" + sudo --login --user=postgres pg_dump "$db" +} + + +# Create a user +# +# usage: ynh_psql_create_user user pwd [host] +# | arg: user - the user name to create +ynh_psql_create_user() { + user="$1" + pwd="$2" + sudo --login --user=postgres psql -c"CREATE USER $user WITH PASSWORD '$pwd'" postgres +} + +# Drop a user +# +# usage: ynh_psql_drop_user user +# | arg: user - the user name to drop +ynh_psql_drop_user() { + user="$1" + sudo --login --user=postgres dropuser "$user" +} diff --git a/data/other/yunoprompt.service b/data/other/yunoprompt.service new file mode 100644 index 000000000..3c4df50f9 --- /dev/null +++ b/data/other/yunoprompt.service @@ -0,0 +1,14 @@ +[Unit] +Description=YunoHost boot prompt +After=getty@tty2.service + +[Service] +Type=simple +ExecStart=/usr/bin/yunoprompt +StandardInput=tty +TTYPath=/dev/tty2 +TTYReset=yes +TTYVHangup=yes + +[Install] +WantedBy=default.target diff --git a/debian/changelog b/debian/changelog index 1026796d3..dc6c6276b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -24,6 +24,27 @@ yunohost (3.0.0~beta1) testing; urgency=low -- Alexandre Aubin Thu, 03 May 2018 03:04:45 +0000 +yunohost (2.7.13.3) testing; urgency=low + + * [enh] Add postgresql helpers (#238) + * [enh] Bring back the bootprompt (#363) + * [enh] Allow to disable the backup during the upgrade (#431) + * [fix] Remove warning from equivs (#439) + * [enh] Add SOURCE_EXTRACT (true/false) in ynh_setup_source (#460) + * [enh] More debug output in services.py (#468) + * [enh] Be able to use more variables in template for nginx conf (#462) + * [enh] Upgrade Meltdown / Spectre diagnosis (#464) + * [enh] Check services status via dbus (#469, #478, #479) + * [mod] Cleaning in services.py code (#470, #472) + * [enh] Improvate and translate service descriptions (#476) + * [fix] Fix "untrusted TLS connection" in mail logs (#471) + * [fix] Make apt-get helper not quiet so we can debug (#475) + * [i18n] Improve Occitan, Portuguese, Arabic, French translations + + Contributors : ljf, Maniack, Josue, Aleks, Bram, Quent-in, itxtoledo, ButterflyOfFire, Jibec, ariasuni, Haelwenn + + -- Alexandre Aubin Mon, 28 May 2018 02:23:00 +0000 + yunohost (2.7.13.2) testing; urgency=low * [fix] Fix an error with services marked as None (#466) diff --git a/debian/install b/debian/install index 70add7992..e9c79e963 100644 --- a/debian/install +++ b/debian/install @@ -3,6 +3,7 @@ sbin/* /usr/sbin/ data/bash-completion.d/yunohost /etc/bash_completion.d/ data/actionsmap/* /usr/share/moulinette/actionsmap/ data/hooks/* /usr/share/yunohost/hooks/ +data/other/yunoprompt.service /etc/systemd/system/ data/other/* /usr/share/yunohost/yunohost-config/moulinette/ data/templates/* /usr/share/yunohost/templates/ data/helpers /usr/share/yunohost/ diff --git a/debian/postinst b/debian/postinst index 5b6ed8259..df7112b9d 100644 --- a/debian/postinst +++ b/debian/postinst @@ -24,6 +24,9 @@ do_configure() { "consider to start it by doing 'service yunohost-firewall start'." fi + # Yunoprompt + systemctl enable yunoprompt.service + # remove old PAM config and update it [[ ! -f /usr/share/pam-configs/my_mkhomedir ]] \ || rm /usr/share/pam-configs/my_mkhomedir diff --git a/locales/en.json b/locales/en.json index 44058c744..1c120661d 100644 --- a/locales/en.json +++ b/locales/en.json @@ -339,6 +339,24 @@ "service_conf_up_to_date": "The configuration is already up-to-date for service '{service}'", "service_conf_updated": "The configuration has been updated for service '{service}'", "service_conf_would_be_updated": "The configuration would have been updated for service '{service}'", + "service_description_avahi-daemon": "allows to reach your server using yunohost.local on your local network", + "service_description_dnsmasq": "handles domain name resolution (DNS)", + "service_description_dovecot": "allows e-mail client to access/fetch email (via IMAP and POP3)", + "service_description_fail2ban": "protects against bruteforce and other kind of attacks from the Internet", + "service_description_glances": "monitors system information on your server", + "service_description_metronome": "manage XMPP instant messaging accounts", + "service_description_mysql": "stores applications data (SQL database)", + "service_description_nginx": "serves or provides access to all the websites hosted on your server", + "service_description_nslcd": "handles YunoHost user shell connection", + "service_description_php5-fpm": "runs applications written in PHP with nginx", + "service_description_postfix": "used to send and receive emails", + "service_description_redis-server": "a specialized database used for rapid data access, task queue and communication between programs", + "service_description_rmilter": "checks various parameters in emails", + "service_description_rspamd": "filters spam, and other email-related features", + "service_description_slapd": "stores users, domains and related information", + "service_description_ssh": "allows you to connect remotely to your server via a terminal (SSH protocol)", + "service_description_yunohost-api": "manages interactions between the YunoHost web interface and the system", + "service_description_yunohost-firewall": "manages open and close connexion ports to services", "service_disable_failed": "Unable to disable service '{service:s}'\n\nRecent service logs:{logs:s}", "service_disabled": "The service '{service:s}' has been disabled", "service_enable_failed": "Unable to enable service '{service:s}'\n\nRecent service logs:{logs:s}", diff --git a/src/yunohost/service.py b/src/yunohost/service.py index e0960dc4c..49cfa4c9f 100644 --- a/src/yunohost/service.py +++ b/src/yunohost/service.py @@ -227,6 +227,15 @@ def service_status(names=[]): status = _get_service_information_from_systemd(name) + translation_key = "service_description_%s" % name + description = m18n.n(translation_key) + + # that mean that we don't have a translation for this string + # that's the only way to test for that for now + # if we don't have it, uses the one provided by systemd + if description == translation_key: + description = str(status.get("Description", "")) + result[name] = { 'status': str(status.get("SubState", "unknown")), 'loaded': "enabled" if str(status.get("LoadState", "unknown")) == "loaded" else str(status.get("LoadState", "unknown")), @@ -235,7 +244,7 @@ def service_status(names=[]): "timestamp": str(status.get("ActiveEnterTimestamp", "unknown")), "human": datetime.fromtimestamp(status.get("ActiveEnterTimestamp") / 1000000).strftime("%F %X"), }, - 'description': str(status.get("Description", "")), + 'description': description, 'service_file_path': str(status.get("FragmentPath", "unknown")), } @@ -713,6 +722,10 @@ def _get_files_diff(orig_file, new_file, as_string=False, skip_header=True): def _calculate_hash(path): """Calculate the MD5 hash of a file""" + + if not os.path.exists(path): + return None + hasher = hashlib.md5() try: