Skip to content

Instantly share code, notes, and snippets.

@efrecon
Last active November 14, 2018 10:28
Show Gist options
  • Select an option

  • Save efrecon/d1181fc93f63e54ede2a94ae176a6c29 to your computer and use it in GitHub Desktop.

Select an option

Save efrecon/d1181fc93f63e54ede2a94ae176a6c29 to your computer and use it in GitHub Desktop.

Revisions

  1. efrecon revised this gist Nov 14, 2018. 3 changed files with 89 additions and 0 deletions.
    67 changes: 67 additions & 0 deletions influx-init.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,67 @@
    # UNIX-Style InfluxDB Initialisation

    ## Introduction

    This script aims at easily initialising access rights for users in InfluxDB
    databases in a UNIX:y way. The script will read a configuration file where
    fields are separated by the colon (`:`) sign (e.g. analogical to
    `/etc/password`). The file is able to express and map `rwx`-style permissions
    onto `GRANT`-style privileges with the database, thus simplifying initialisation
    of the authorisations, but also use of users created in other parts of a cloud
    system.

    ## Options

    The script itself takes a few internal options, any other dash-led option will
    be passed further to `influx` at each execution, thus making it easy to pass
    further authentication- or connection- oriented options. A double-dash should
    mark the end of the option list and all arguments after the double-dash will
    be path to access files, which will be used for user creation and access
    rights definitions.

    The options specific to the script are the following:
    * `-i` or `--influx` to give the exact path to the `influx` binary.
    * `--verbose` to turn on verbosity in the script.

    Provided a file called `access.cfg` in the format described below, the
    following command would create users and give them access rights as of the file
    at a remote PostgreSQL instance.

    ```Shell
    influx-init.sh --verbose -- access.cfg
    ```

    ## Configuration

    ### Syntax

    The syntax of the access rights files is as described below. Empty lines will be
    ignored. Lines starting with a hash-sign (`#`) will be ignored. Files *MUST* end
    with an empty line, otherwise the last line will not be parsed. Apart from empty
    or commenting lines, lines should contain 4 fields separated by colon-signs.
    These are described in order below:

    1. List of databases, separated by commas, that the user will have access to.
    The script will attempt to create the databases if they do not already
    exist.

    2. Name of user to be created

    3. Password for user. When the password is empty, a random password of 16
    characters length will be generated for the user and printed out.

    4. Access specification to the databases. These specifications are a
    combination, in any order, of the letters `r`, `w` and `x` where `r` stands
    for read, `w` for writes and `x` for admin rights. These are mapped onto
    InfluxDB `READ` or `WRITE` `GRANT` clauses.

    ### Example

    The following example content for an access specification file would arrange for
    the creation of an administrator with access to all databases and the creation
    of a database called `db` and a user called `user` with read and write access.

    ```
    :admin:FyKzmSYnygbBMrRzcf4drcWC:rwx
    db:user:gZU6JE5A7xz3mVFubNJn4LZ2:rw
    ```
    22 changes: 22 additions & 0 deletions LICENSE
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,22 @@
    Copyright (c) <2018>, <Emmanuel Frécon>
    All rights reserved.

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice, this
    list of conditions and the following disclaimer.
    2. Redistributions in binary form must reproduce the above copyright notice,
    this list of conditions and the following disclaimer in the documentation
    and/or other materials provided with the distribution.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
    ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    Empty file modified influx-init.sh
    100644 → 100755
    Empty file.
  2. efrecon created this gist Nov 14, 2018.
    173 changes: 173 additions & 0 deletions influx-init.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,173 @@
    #!/bin/sh

    ######
    #
    # This script can be used to initialise databases and users in an Influx DB
    # installation. Most dash-led options are passed further to the influx
    # command-line tool. All file paths that follows the -- separator contain
    # user/db configurations that will be understood by this script. In these
    # configuration files, lines starting with a hash-sign and empty lines are
    # ignored. Otherwise, lines should contain a number of colon separated fields,
    # which are understood as follows:
    #
    # * colon separated list of databases accessible by user, empty for none
    # * name of user
    # * password, empty for auto-generated
    # * combination of rwx (read, write, x is for all privileges, i.e. admin rights)
    #
    # Note that leading and trailing whitespaces are removed from user and database
    # names automatically. Autogenerated passwords will be printed out on the
    # standard error.
    #
    # When called without authorisation details, this tool will automatically pick
    # the first administrator that it discovers to perform all further operations on
    # users and databases. This ensures that, when an administrator is the first
    # user declared and InfluxDB is configured to force authorisation, all
    # operations will properly succeed.
    #
    # It is possible to specify a specific binary (full path, different command)
    # with the -i (or --influx) option. Specifying --verbose will allow to print
    # out internal decisions, at the expense of printing out sensitive passwords.
    #
    ######

    # Eat all options so we can pass them to influx when calling it, all remaining
    # stuff should be file names.
    INFLUX="influx"
    OPTS=""
    VERBOSE=0
    while [ $# -gt 0 ]; do
    case "$1" in
    --)
    # End of options, everything that follows will be filenames
    shift
    break
    ;;
    -i|--influx)
    # Capture separate path to binary, just in case
    INFLUX="$2"
    shift 2
    ;;
    --verbose)
    VERBOSE=1
    shift
    ;;
    *)
    # All other options are supposed to take an argument (which isn't
    # entirely true), store them and arrange to capture them for further
    # invokation of influx.
    OPTS="${OPTS} $1 $2"
    shift 2
    ;;
    esac
    done


    verbose() {
    if [ "$VERBOSE" = "1" ]; then printf "%s\n" "$*" 1>&2; fi
    }

    warn() {
    printf "%s\n" "$*" 1>&2
    }

    callinflux() {
    verbose "InfluxQL (${OPTS}): $1"
    ${INFLUX} ${OPTS} -execute "$1"
    }


    for fname in "$@"; do
    DBS=""
    # See http://mywiki.wooledge.org/BashFAQ/024 for the loop...
    while IFS= read -r line; do
    line=$(echo "${line}" | sed '/^[[:space:]]*$/d' | sed '/^[[:space:]]*#/d')
    if [ -n "${line}" ]; then
    dbs=$(echo -e "${line}"|cut -d: -f1)
    user=$(echo -e "${line}"|cut -d: -f2)
    pass=$(echo -e "${line}"|cut -d: -f3)
    access=$(echo -e "${line}"|cut -d: -f4)

    # Create, amend the user and take care of admin privieges early.
    user=$(echo -e "${user}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')

    if [ -z "${pass}" ]; then
    pass=$(strings /dev/urandom | grep -o '[[:alnum:]]' | head -n 16 | tr -d '\n')
    warn "Generated password '$pass' for $user"
    fi

    if [ -n "${user}" ]; then
    # Create the user if it does not already exist.
    already=$(callinflux "SHOW USERS;" | tail -n +3 | grep ${user})
    if [ -z "${already}" ]; then
    admin=$(echo "${access}" | grep x)
    # Check privileges (represented by an x)
    if [ -z "${admin}" ]; then
    verbose "Creating user ${user}"
    callinflux "CREATE USER \"${user}\" WITH PASSWORD '${pass}';"
    else
    verbose "Creating administrator ${user}"
    callinflux "CREATE USER \"${user}\" WITH PASSWORD '${pass}' WITH ALL PRIVILEGES;"

    hasauth=$(echo -e "${OPTS}"|grep '\-username')
    if [ -z "${hasauth}" ]; then
    verbose "Automatically using ${user} as an administrator for all further calls!"
    OPTS="${OPTS} -username ${user} -password ${pass}"
    fi
    fi
    else
    verbose "Amending password for ${user}"
    callinflux "SET PASSWORD FOR \"${user}\" = '${pass}';"
    admin=$(echo "${access}" | grep x)
    already=$(callinflux "SHOW USERS;" | tail -n +3 | grep ${user} | grep true)
    if [ -z "${admin}" -a -n "${already}" ]; then
    verbose "Revoking privileges for ${user}"
    callinflux "REVOKE ALL PRIVILEGES FROM \"${user}\";"
    fi
    if [ -n "${admin}" -a -z "${already}" ]; then
    verbose "Granting privileges for ${user}"
    callinflux "GRANT ALL PRIVILEGES TO \"${user}\";"
    fi
    fi
    fi

    # Parse the list of databases, separated by comas
    for db in $(echo "${dbs}" | tr "," "\n"); do
    db=$(echo -e "${db}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
    if [ -n "${db}" ]; then
    # Create the database if it does not already exist.
    already=$(callinflux "SHOW DATABASES;" | tail -n +3 | grep ${db})
    if [ -z "${already}" ]; then
    verbose "Creating database ${db}"
    callinflux "CREATE DATABASE ${db};"
    else
    verbose "Database ${db} already exists"
    fi

    # Keep record of databases specified in file
    already=$(echo ${DBS}|grep ${db})
    if [ -z "${already}" ]; then
    DBS="${DBS} ${db}"
    fi

    # Grant R/W privileges to user.
    read=$(echo "${access}" | grep r)
    write=$(echo "${access}" | grep w)
    if [ -n "${read}" ] && [ -n "${write}" ]; then
    verbose "Granting all access to ${db} for ${user}"
    callinflux "GRANT ALL ON \"${db}\" TO \"${user}\";"
    else
    if [ -n "${read}" ]; then
    verbose "Granting read access to ${db} for ${user}"
    callinflux "GRANT READ ON \"${db}\" TO \"${user}\";"
    fi
    if [ -n "${write}" ]; then
    verbose "Granting write access to ${db} for ${user}"
    callinflux "GRANT WRITE ON \"${db}\" TO \"${user}\";"
    fi
    fi
    fi
    done
    fi
    done < ${fname}
    done