kych

OAuth 2.0 API for Swiyu to enable Taler integration of Swiyu for KYC (experimental)
Log | Files | Refs | Submodules | README | LICENSE

kych-dbconfig (5453B)


      1 #!/bin/bash
      2 # This file is part of KyCH.
      3 # Copyright (C) 2026 Taler Systems SA
      4 #
      5 # KyCH is free software; you can redistribute it and/or modify it under the
      6 # terms of the GNU Affero General Public License as published by the Free
      7 # Software Foundation; either version 3, or (at your option) any later version.
      8 #
      9 # KyCH is distributed in the hope that it will be useful, but WITHOUT ANY
     10 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11 # A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
     12 # details.
     13 #
     14 # You should have received a copy of the GNU Affero General Public License
     15 # along with KyCH; see the file COPYING.  If not, see
     16 # <http://www.gnu.org/licenses/>
     17 #
     18 #
     19 # Create the PostgreSQL role and database that kych.conf names and load the
     20 # schema into it.  This is the one-time setup step; afterwards the schema is
     21 # kept up to date by kych-dbinit, which the Debian package runs on every
     22 # upgrade.
     23 #
     24 # Error checking on
     25 set -eu
     26 
     27 RESET_DB=0
     28 SKIP_DBINIT=0
     29 DBUSER="kych"
     30 CFGFILE="/etc/kych/kych.conf"
     31 
     32 while getopts 'c:hrsu:' OPTION; do
     33   case "$OPTION" in
     34   c)
     35     CFGFILE="$OPTARG"
     36     ;;
     37   h)
     38     echo 'Supported options:'
     39     echo "  -c FILENAME  -- use configuration FILENAME (default: $CFGFILE)"
     40     echo "  -h           -- print this help text"
     41     echo "  -r           -- reset database (dangerous, destroys all data)"
     42     echo "  -s           -- skip database initialization"
     43     echo "  -u USER      -- kych to be run by USER (default: $DBUSER)"
     44     exit 0
     45     ;;
     46   r)
     47     RESET_DB="1"
     48     ;;
     49   s)
     50     SKIP_DBINIT="1"
     51     ;;
     52   u)
     53     DBUSER="$OPTARG"
     54     ;;
     55   ?)
     56     echo "Unrecognized command line option" 1>&2
     57     exit 1
     58     ;;
     59   esac
     60 done
     61 
     62 if [ "$(id -u)" -ne 0 ]; then
     63   echo "This script must be run as root" 1>&2
     64   exit 1
     65 fi
     66 
     67 if ! id postgres >/dev/null 2>&1; then
     68   echo "Could not find 'postgres' user. Please install PostgreSQL first" 1>&2
     69   exit 1
     70 fi
     71 
     72 if ! id "$DBUSER" >/dev/null 2>&1; then
     73   echo "Could not find '$DBUSER' user. Please set it up first" 1>&2
     74   exit 1
     75 fi
     76 
     77 if ! command -v kych-dbinit >/dev/null 2>&1; then
     78   echo "Required 'kych-dbinit' not found. Please fix your installation." 1>&2
     79   exit 1
     80 fi
     81 
     82 # kych-dbinit understands the full configuration format, including @inline@
     83 # includes and $-expansion, so it is asked where the database is rather than
     84 # this script guessing at it.  This sets PGDATABASE, PGHOST and PGPORT, which
     85 # matters on a host whose PostgreSQL is not on the default port: everything
     86 # below then acts on the same server the daemon will use.
     87 eval "$(kych-dbinit -c "$CFGFILE" --print-connection)"
     88 
     89 if [ -z "${PGDATABASE:-}" ]; then
     90   echo "Could not determine the database from $CFGFILE" 1>&2
     91   exit 1
     92 fi
     93 DBNAME="$PGDATABASE"
     94 
     95 # A database on another host is not ours to create.
     96 case "$PGHOST" in
     97 /* | localhost | 127.0.0.1 | ::1) ;;
     98 *)
     99   echo "DATABASE in $CFGFILE names the server '$PGHOST', which is not this" 1>&2
    100   echo "host.  Create the role and the database there by hand, then load the" 1>&2
    101   echo "schema with 'kych-dbinit -c $CFGFILE'." 1>&2
    102   exit 1
    103   ;;
    104 esac
    105 
    106 # The administrative work is done over the local socket as the postgres user,
    107 # which is what peer authentication there expects; only the port is taken from
    108 # the configuration.  Asking the postgres superuser to authenticate over TCP
    109 # instead would stop to prompt for a password that nobody is there to type,
    110 # which is also why -w is passed to psql throughout.  "sudo -i" resets the
    111 # environment, so PGPORT is passed explicitly.
    112 as_postgres() {
    113   sudo -i -u postgres env PGPORT="$PGPORT" PGCONNECT_TIMEOUT=10 "$@"
    114 }
    115 
    116 # Up front, so that a server which is not running is reported as that and not
    117 # as a series of puzzling failures further down.
    118 if ! as_postgres psql -w -tAc 'SELECT 1' postgres >/dev/null 2>&1; then
    119   echo "Cannot reach PostgreSQL on port $PGPORT as the postgres user over the" 1>&2
    120   echo "local socket.  Check that the server is running and that $CFGFILE" 1>&2
    121   echo "names its port." 1>&2
    122   exit 1
    123 fi
    124 
    125 # The daemon connects over the local socket and authenticates as the
    126 # operating-system user it runs as, which is what peer authentication in a
    127 # stock Debian PostgreSQL expects: the role must have the same name.
    128 if as_postgres psql -w -tAc \
    129   "SELECT 1 FROM pg_roles WHERE rolname = '$DBUSER'" postgres | grep -q 1; then
    130   echo "Database user '$DBUSER' already exists, continuing anyway." 1>&2
    131 else
    132   echo "Setting up database user '$DBUSER'." 1>&2
    133   if ! as_postgres createuser "$DBUSER"; then
    134     echo "Failed to create database user '$DBUSER'" 1>&2
    135     exit 1
    136   fi
    137 fi
    138 
    139 DO_CREATE=1
    140 if as_postgres psql -w -lqtA -F: | cut -d: -f1 | grep -qx "$DBNAME"; then
    141   if [ 1 = "$RESET_DB" ]; then
    142     echo "Deleting existing database '$DBNAME'." 1>&2
    143     if ! as_postgres dropdb "$DBNAME"; then
    144       echo "Failed to delete existing database '$DBNAME'" 1>&2
    145       exit 1
    146     fi
    147   else
    148     echo "Database '$DBNAME' already exists, continuing anyway." 1>&2
    149     DO_CREATE=0
    150   fi
    151 fi
    152 
    153 if [ 1 = "$DO_CREATE" ]; then
    154   echo "Creating database '$DBNAME'." 1>&2
    155   if ! as_postgres createdb -O "$DBUSER" "$DBNAME"; then
    156     echo "Failed to create database '$DBNAME'" 1>&2
    157     exit 1
    158   fi
    159 fi
    160 
    161 if [ 0 = "$SKIP_DBINIT" ]; then
    162   echo "Initializing database '$DBNAME'." 1>&2
    163   if ! sudo -u "$DBUSER" kych-dbinit -c "$CFGFILE"; then
    164     echo "Failed to initialize database schema" 1>&2
    165     exit 1
    166   fi
    167 fi
    168 
    169 echo "Database configuration finished." 1>&2
    170 
    171 exit 0