Skip to content

Commit

Permalink
Merge #247 - Implement *_FILE read ENV from file
Browse files Browse the repository at this point in the history
Pull-request: #247
Signed-off-by: William Desportes <williamdes@wdes.fr>
  • Loading branch information
williamdes committed Dec 26, 2019
2 parents 8edcc52 + 60e766a commit 568e58c
Show file tree
Hide file tree
Showing 13 changed files with 156 additions and 39 deletions.
5 changes: 5 additions & 0 deletions .gitignore
@@ -1 +1,6 @@
config.secret.inc.php
__pycache__
.pytest_cache
.vscode
.history
.venv
2 changes: 1 addition & 1 deletion .travis.yml
Expand Up @@ -15,7 +15,7 @@ before_install:
- docker run --name db_server -e MYSQL_ROOT_PASSWORD=$TESTSUITE_PASSWORD -v $PWD/testing/testing.cnf:/etc/mysql/conf.d/testing.cnf:ro -d $DB

install:
- pip install mechanize html5lib
- pip install mechanize html5lib pytest

_helpers:
- &test-docker-compose
Expand Down
3 changes: 3 additions & 0 deletions Makefile
Expand Up @@ -18,6 +18,9 @@ build-fpm-alpine:
run:
docker-compose -f docker-compose.testing.yml up -d

run-tests:
docker-compose exec phpmyadmin /test-docker.sh phpmyadmin_testing 80 phpmyadmin_testing_db

logs:
docker-compose -f docker-compose.testing.yml logs

Expand Down
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -129,7 +129,7 @@ Set the variable ``PMA_ABSOLUTE_URI`` to the fully-qualified path (``https://pma
* ``PMA_CONFIG_BASE64`` - if set, will override the default config.inc.php with the base64 decoded contents of the variable
* ``PMA_USER_CONFIG_BASE64`` - if set, will override the default config.user.inc.php with the base64 decoded contents of the variable

For usage with Docker secrets, appending ``_FILE`` to any environment variable is allowed:
For usage with Docker secrets, appending ``_FILE`` to the ``PMA_PASSWORD`` environment variable is allowed (it overrides ``PMA_PASSWORD`` if it is set):
```
docker run --name myadmin -d -e PMA_PASSWORD_FILE=/run/secrets/db_password.txt -p 8080:80 phpmyadmin/phpmyadmin
```
Expand Down
18 changes: 18 additions & 0 deletions apache/docker-entrypoint.sh
Expand Up @@ -74,4 +74,22 @@ if [ ! -z "${PMA_USER_CONFIG_BASE64}" ]; then
echo "${PMA_USER_CONFIG_BASE64}" | base64 -d > /etc/phpmyadmin/config.user.inc.php
fi

function get_docker_secret() {
local env_var="${1}"
local env_var_file="${env_var}_FILE"

# Check if the variable with name $env_var_file (which is $PMA_PASSWORD_FILE for example)
# is not empty and export $PMA_PASSWORD as the password in the Docker secrets file

if [[ -n "${!env_var_file}" ]]; then
export "${env_var}"="$(cat "${!env_var_file}")"
fi
}

get_docker_secret PMA_PASSWORD
get_docker_secret MYSQL_ROOT_PASSWORD
get_docker_secret MYSQL_PASSWORD
get_docker_secret PMA_HOSTS_FILE
get_docker_secret PMA_HOST_FILE

exec "$@"
16 changes: 10 additions & 6 deletions docker-compose.testing.yml
@@ -1,26 +1,30 @@
version: '2'
version: '3.1'

services:
db_server:
image: ${DB}
image: ${DB:-mariadb:10.3}
container_name: phpmyadmin_testing_db
environment:
- MYSQL_ROOT_PASSWORD=${TESTSUITE_PASSWORD}
- MYSQL_ROOT_PASSWORD=${TESTSUITE_PASSWORD:-my-secret-pw}
volumes:
- ./testing/testing.cnf:/etc/mysql/conf.d/testing.cnf:ro
tmpfs:
- /var/lib/mysql:rw,noexec,nosuid,size=300m

phpmyadmin:
build:
context: testing/
links:
- db_server:db_server
container_name: phpmyadmin_testing
volumes:
- /sessions
- ./testing/conftest.py:/conftest.py
- ./testing/test-docker.sh:/test-docker.sh
- ./testing/phpmyadmin_test.py:/phpmyadmin_test.py
- ./docker-entrypoint.sh:/docker-entrypoint.sh
ports:
- 8090:80
environment:
- PMA_ARBITRARY=1
- TESTSUITE_PASSWORD=${TESTSUITE_PASSWORD}
- TESTSUITE_PASSWORD=${TESTSUITE_PASSWORD:-my-secret-pw}
depends_on:
- db_server
18 changes: 18 additions & 0 deletions docker-entrypoint.sh
Expand Up @@ -69,4 +69,22 @@ if [ ! -z "${PMA_USER_CONFIG_BASE64}" ]; then
echo "${PMA_USER_CONFIG_BASE64}" | base64 -d > /etc/phpmyadmin/config.user.inc.php
fi

function get_docker_secret() {
local env_var="${1}"
local env_var_file="${env_var}_FILE"

# Check if the variable with name $env_var_file (which is $PMA_PASSWORD_FILE for example)
# is not empty and export $PMA_PASSWORD as the password in the Docker secrets file

if [[ -n "${!env_var_file}" ]]; then
export "${env_var}"="$(cat "${!env_var_file}")"
fi
}

get_docker_secret PMA_PASSWORD
get_docker_secret MYSQL_ROOT_PASSWORD
get_docker_secret MYSQL_PASSWORD
get_docker_secret PMA_HOSTS_FILE
get_docker_secret PMA_HOST_FILE

exec "$@"
18 changes: 18 additions & 0 deletions fpm-alpine/docker-entrypoint.sh
Expand Up @@ -74,4 +74,22 @@ if [ ! -z "${PMA_USER_CONFIG_BASE64}" ]; then
echo "${PMA_USER_CONFIG_BASE64}" | base64 -d > /etc/phpmyadmin/config.user.inc.php
fi

function get_docker_secret() {
local env_var="${1}"
local env_var_file="${env_var}_FILE"

# Check if the variable with name $env_var_file (which is $PMA_PASSWORD_FILE for example)
# is not empty and export $PMA_PASSWORD as the password in the Docker secrets file

if [[ -n "${!env_var_file}" ]]; then
export "${env_var}"="$(cat "${!env_var_file}")"
fi
}

get_docker_secret PMA_PASSWORD
get_docker_secret MYSQL_ROOT_PASSWORD
get_docker_secret MYSQL_PASSWORD
get_docker_secret PMA_HOSTS_FILE
get_docker_secret PMA_HOST_FILE

exec "$@"
18 changes: 18 additions & 0 deletions fpm/docker-entrypoint.sh
Expand Up @@ -74,4 +74,22 @@ if [ ! -z "${PMA_USER_CONFIG_BASE64}" ]; then
echo "${PMA_USER_CONFIG_BASE64}" | base64 -d > /etc/phpmyadmin/config.user.inc.php
fi

function get_docker_secret() {
local env_var="${1}"
local env_var_file="${env_var}_FILE"

# Check if the variable with name $env_var_file (which is $PMA_PASSWORD_FILE for example)
# is not empty and export $PMA_PASSWORD as the password in the Docker secrets file

if [[ -n "${!env_var_file}" ]]; then
export "${env_var}"="$(cat "${!env_var_file}")"
fi
}

get_docker_secret PMA_PASSWORD
get_docker_secret MYSQL_ROOT_PASSWORD
get_docker_secret MYSQL_PASSWORD
get_docker_secret PMA_HOSTS_FILE
get_docker_secret PMA_HOST_FILE

exec "$@"
5 changes: 3 additions & 2 deletions testing/Dockerfile
Expand Up @@ -10,7 +10,8 @@ RUN set -ex; \
curl \
python-pip \
; \
pip install mechanize html5lib; \
pip install setuptools wheel; \
pip install mechanize html5lib pytest; \
rm -rf /var/lib/apt/lists/*

COPY phpmyadmin_test.py test-docker.sh world.sql /
COPY phpmyadmin_test.py test-docker.sh world.sql conftest.py /
28 changes: 28 additions & 0 deletions testing/conftest.py
@@ -0,0 +1,28 @@
import pytest

def pytest_addoption(parser):
parser.addoption("--url")
parser.addoption("--username")
parser.addoption("--password")
parser.addoption("--server")
parser.addoption("--sqlfile")

@pytest.fixture
def url(request):
return request.config.getoption("--url")

@pytest.fixture
def username(request):
return request.config.getoption("--username")

@pytest.fixture
def password(request):
return request.config.getoption("--password")

@pytest.fixture
def server(request):
return request.config.getoption("--server")

@pytest.fixture
def sqlfile(request):
return request.config.getoption("--sqlfile")
58 changes: 31 additions & 27 deletions testing/phpmyadmin_test.py
@@ -1,26 +1,27 @@
#!/usr/bin/env python2
import argparse
import os
import subprocess
import re
import sys

import mechanize
import tempfile
import pytest


def test_content(match, content):
if not match in content:
print(content)
raise Exception('{0} not found in content!'.format(match))
def do_test_content(match, content):
assert(match in content)


def test_phpmyadmin(url, username, password, server=None, sqlfile=None):
def test_phpmyadmin(url, username, password, server, sqlfile):
if sqlfile is None:
if os.path.exists('/world.sql'):
sqlfile = '/world.sql'
elif os.path.exists('./world.sql'):
sqlfile = './world.sql'
else:
sqlfile = './testing/world.sql'
path = os.path.dirname(os.path.realpath(__file__))
sqlfile = path + '/world.sql'
br = mechanize.Browser()

# Ignore robots.txt
Expand All @@ -38,36 +39,39 @@ def test_phpmyadmin(url, username, password, server=None, sqlfile=None):

# Login and check if loggged in
response = br.submit()
test_content('Server version', response.read())
do_test_content('Server version', response.read())

# Open server import
response = br.follow_link(text_regex=re.compile('Import'))
test_content('OpenDocument Spreadsheet', response.read())
do_test_content('OpenDocument Spreadsheet', response.read())

# Upload SQL file
br.select_form('import')
br.form.add_file(open(sqlfile), 'text/plain', sqlfile)
response = br.submit()
test_content('5326 queries executed', response.read())
do_test_content('5326 queries executed', response.read())


def docker_secret(env_name):
dir_path = os.path.dirname(os.path.realpath(__file__))
secret_file = tempfile.mkstemp()

password = "The_super_secret_password"
password_file = open(secret_file[1], 'wb')
password_file.write(str.encode(password))
password_file.close()

def main():
parser = argparse.ArgumentParser()
parser.add_argument('--url', required=True)
parser.add_argument('--username', required=True)
parser.add_argument('--password', required=True)
parser.add_argument('--server')
parser.add_argument('--sqlfile', default=None)
args = parser.parse_args()
test_env = {env_name + '_FILE': secret_file[1]}

test_phpmyadmin(
args.url,
args.username,
args.password,
args.server,
args.sqlfile
)
# Run entrypoint and afterwards echo the environment variables
result = subprocess.Popen(dir_path+ "/../docker-entrypoint.sh 'env'", shell=True, stdout=subprocess.PIPE, env=test_env)
output = result.stdout.read().decode()

assert (env_name + "=" + password) in output

if __name__ == '__main__':
main()
def test_phpmyadmin_secrets():
docker_secret('MYSQL_PASSWORD')
docker_secret('MYSQL_ROOT_PASSWORD')
docker_secret('PMA_PASSWORD')
docker_secret('PMA_HOSTS_FILE')
docker_secret('PMA_HOST_FILE')
4 changes: 2 additions & 2 deletions testing/test-docker.sh
Expand Up @@ -28,6 +28,7 @@ GREEN="\033[0;32m"
RED="\033[0;31m"
NC="\033[0m" # No Color


# Find test script
if [ -f ./phpmyadmin_test.py ] ; then
FILENAME=./phpmyadmin_test.py
Expand Down Expand Up @@ -75,12 +76,11 @@ fi

# Perform tests
ret=0
$FILENAME --url "$PHPMYADMIN_URL" --username root --password $TESTSUITE_PASSWORD $SERVER
pytest -q --url "$PHPMYADMIN_URL" --username root --password "$TESTSUITE_PASSWORD" $SERVER $FILENAME
ret=$?

# Show debug output in case of failure
if [ $ret -ne 0 ] ; then
curl "$PHPMYADMIN_URL"
${COMMAND_HOST} ps faux
echo "Result of ${PHPMYADMIN_DB_HOSTNAME} tests: ${RED}FAILED${NC}"
exit $ret
Expand Down

0 comments on commit 568e58c

Please sign in to comment.