diff --git a/defaults/main.yml b/defaults/main.yml index 160e6a8..c221f0f 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -22,6 +22,12 @@ open_asfa_db_volume: 'asfa_pg_data' open_asfa_db_allowed_hosts: - '127.0.0.1/8' open_asfa_db_constraints: '[node.labels.pg_data==asfa_server_test]' +open_asfa_pgadmin_image: 'dpage/pgadmin4' +open_asfa_pgadmin_data_vol: 'asfa_test_pgadmin_data' +open_asfa_pgadmin_constraints: '[node.labels.pgadmin_data==asfa_server_test]' +open_asfa_pgadmin_email: 'noreply@example.com' +#open_asfa_pgadmin_default_pwd: 'Use a vault' +open_asfa_pgadmin_inactivity_timeout: '1200' open_asfa_psql_db_data: - { db_host: '{{ open_asfa_db_host }}', pgsql_version: '{{ open_asfa_db_pg_version }}', name: '{{ open_asfa_db_name }}', encoding: 'UTF8', user: '{{ open_asfa_db_user }}', roles: 'CREATEDB,NOSUPERUSER', pwd: '{{ open_asfa_db_pwd }}', allowed_hosts: '{{ open_asfa_db_allowed_hosts }}' } diff --git a/tasks/main.yml b/tasks/main.yml index 184c87b..dec87e1 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -7,6 +7,12 @@ - name: Install the DB initialization script template: src=pg-create-user-db.sh.j2 dest={{ open_asfa_compose_dir }}/pg-create-user-db.sh owner=root group=root mode='0555' + - name: Install the pgadmin configuration files + template: src={{ item }}.j2 dest={{ open_asfa_compose_dir }}/{{ item }} owner=root group=root mode='0444' + loop: + - pgadmin_config_local.py + - pgadmin_servers.json + run_once: True when: - open_asfa_db_docker_host == ansible_fqdn @@ -21,9 +27,14 @@ #node.labels.pg_data==asfa_server_test labels: pg_data: 'asfa_server_test' + pgadmin_data: 'asfa_server_test' labels_state: 'merge' when: open_asfa_db_as_container + - name: Install the docker compose file + template: src=open-asfa-db-docker-compose.yml.j2 dest={{ open_asfa_compose_dir }}/docker-open-asfa-stack-db-test.yml owner=root group=root mode='0400' + when: open_asfa_db_as_container + - name: Install the docker compose file template: src=open-asfa-docker-compose.yml.j2 dest={{ open_asfa_compose_dir }}/docker-open-asfa-stack-test.yml owner=root group=root mode='0400' @@ -32,6 +43,7 @@ name: open-asfa-test state: present compose: + - '{{ open_asfa_compose_dir }}/docker-open-asfa-stack-db-test.yml' - '{{ open_asfa_compose_dir }}/docker-open-asfa-stack-test.yml' run_once: True diff --git a/templates/open-asfa-db-docker-compose.yml.j2 b/templates/open-asfa-db-docker-compose.yml.j2 new file mode 100644 index 0000000..a0635b8 --- /dev/null +++ b/templates/open-asfa-db-docker-compose.yml.j2 @@ -0,0 +1,66 @@ +version: '3.6' + +networks: +{% if open_asfa_behind_haproxy %} + haproxy-public: + external: true +{% endif %} + {{ open_asfa_docker_network }}: + +volumes: + {{ open_asfa_db_volume }}: + {{ open_asfa_pgadmin_data_vol }}: + +services: + pg: + image: {{ open_asfa_db_image }} + networks: + - {{ open_asfa_docker_network }} + volumes: + - {{ open_asfa_db_volume }}:/var/lib/postgresql/data/pg_data + - {{ open_asfa_compose_dir }}/pg-create-user-db.sh:/docker-entrypoint-initdb.d/pg-create-user-db.sh:ro + environment: + POSTGRES_PASSWORD: {{ open_asfa_db_pwd }} + POSTGRES_DB: postgres + POSTGRES_USER: postgres + POSTGRES_PORT: {{ open_asfa_db_port }} + PGDATA: /var/lib/postgresql/data/pg_data + deploy: + placement: + constraints: {{ open_asfa_db_constraints }} + restart_policy: + condition: on-failure + delay: 5s + max_attempts: 3 + window: 120s + logging: + driver: 'journald' + pgadmin: + image: {{ open_asfa_pgadmin_image }} + networks: + - {{ open_asfa_docker_network }} +{% if open_asfa_behind_haproxy %} + - haproxy-public +{% endif %} + volumes: + - {{ open_asfa_pgadmin_data_vol }}:/var/lib/pgadmin + - {{ open_asfa_compose_dir }}/pgadmin_config_local.py:/pgadmin4/config_local.py:ro + - {{ open_asfa_compose_dir }}/pgadmin_servers.json:/pgadmin4/servers.json:ro + environment: + PGADMIN_DEFAULT_EMAIL: {{ open_asfa_pgadmin_email }} + PGADMIN_DEFAULT_PASSWORD: {{ open_asfa_pgadmin_default_pwd }} + PGADMIN_DISABLE_POSTFIX: disable + #PGADMIN_ENABLE_TLS: enable + PGADMIN_LISTEN_ADDRESS: 0.0.0.0 + PGADMIN_LISTEN_PORT: 5050 + GUNICORN_THREADS: 20 + deploy: + placement: + constraints: {{ open_asfa_pgadmin_constraints }} + restart_policy: + condition: on-failure + delay: 5s + max_attempts: 3 + window: 120s + logging: + driver: 'journald' diff --git a/templates/open-asfa-docker-compose.yml.j2 b/templates/open-asfa-docker-compose.yml.j2 index b438597..47bd8f2 100644 --- a/templates/open-asfa-docker-compose.yml.j2 +++ b/templates/open-asfa-docker-compose.yml.j2 @@ -7,9 +7,6 @@ networks: {% endif %} {{ open_asfa_docker_network }}: -volumes: - {{ open_asfa_db_volume }}: - services: {{ open_asfa_docker_service_server_name }}: image: {{ open_asfa_docker_server_image }} @@ -61,30 +58,3 @@ services: window: 120s logging: driver: 'journald' -{% if open_asfa_db_as_container %} - pg: - image: {{ open_asfa_db_image }} - networks: - - {{ open_asfa_docker_network }} -# ports: -# - {{ open_asfa_db_port }} - volumes: - - {{ open_asfa_db_volume }}:/var/lib/postgresql/data/pg_data - - {{ open_asfa_compose_dir }}/pg-create-user-db.sh:/docker-entrypoint-initdb.d/pg-create-user-db.sh:ro - environment: - POSTGRES_PASSWORD: {{ open_asfa_db_pwd }} - POSTGRES_DB: postgres - POSTGRES_USER: postgres - POSTGRES_PORT: {{ open_asfa_db_port }} - PGDATA: /var/lib/postgresql/data/pg_data - deploy: - placement: - constraints: {{ open_asfa_db_constraints }} - restart_policy: - condition: on-failure - delay: 5s - max_attempts: 3 - window: 120s - logging: - driver: 'journald' -{% endif %} diff --git a/templates/pgadmin_config_local.py.j2 b/templates/pgadmin_config_local.py.j2 new file mode 100644 index 0000000..224e466 --- /dev/null +++ b/templates/pgadmin_config_local.py.j2 @@ -0,0 +1,220 @@ +# -*- coding: utf-8 -*- + +# Application version suffix, e.g. 'beta1', 'dev'. Usually an empty string +# for GA releases. +APP_SUFFIX = '' + +########################################################################## +# Server settings +########################################################################## + +SERVER_MODE = True + +# Enable X-Frame-Option protection. +# Set to one of "SAMEORIGIN", "ALLOW-FROM origin" or "" to disable. +# Note that "DENY" is NOT supported (and will be silently ignored). +# See https://tools.ietf.org/html/rfc7034 for more info. +X_FRAME_OPTIONS = "SAMEORIGIN" + +# The Content-Security-Policy header allows you to restrict how resources +# such as JavaScript, CSS, or pretty much anything that the browser loads. +# see https://content-security-policy.com/#source_list for more info +# e.g. "default-src https: data: 'unsafe-inline' 'unsafe-eval';" +CONTENT_SECURITY_POLICY = "default-src http: data: blob: 'unsafe-inline' " \ + "'unsafe-eval';" + +# STRICT_TRANSPORT_SECURITY_ENABLED when set to True will set the +# Strict-Transport-Security header +STRICT_TRANSPORT_SECURITY_ENABLED = False + +# The X-Content-Type-Options header forces the browser to honor the response +# content type instead of trying to detect it, which can be abused to +# generate a cross-site scripting (XSS) attack. +# e.g. nosniff +X_CONTENT_TYPE_OPTIONS = "nosniff" + +# The browser will try to prevent reflected XSS attacks by not loading the +# page if the request contains something that looks like JavaScript and the +# response contains the same data. e.g. '1; mode=block' +X_XSS_PROTECTION = "1; mode=block" + +# This param is used to validate ALLOWED_HOSTS for the application +# This will be used to avoid Host Header Injection attack +# ALLOWED_HOSTS = ['225.0.0.0/8', '226.0.0.0/7', '228.0.0.0/6'] +# ALLOWED_HOSTS = ['127.0.0.1', '192.168.0.1'] +# if ALLOWED_HOSTS= [] then it will accept all ips (and application will be +# vulnerable to Host Header Injection attack) +ALLOWED_HOSTS = [] + +SECURITY_PASSWORD_HASH = 'pbkdf2_sha512' + +########################################################################## +# Log settings +########################################################################## + +# Debug mode? +DEBUG = False + +########################################################################## +# User account and settings storage +########################################################################## + +# Allow database connection passwords to be saved if the user chooses. +# Set to False to disable password saving. +ALLOW_SAVE_PASSWORD = True + +########################################################################## +# Session expiration support +########################################################################## +# SESSION_EXPIRATION_TIME is the interval in Days. Session will be +# expire after the specified number of *days*. +SESSION_EXPIRATION_TIME = 1 + +# CHECK_SESSION_FILES_INTERVAL is interval in Hours. Application will check +# the session files for cleanup after specified number of *hours*. +CHECK_SESSION_FILES_INTERVAL = 12 + +# USER_INACTIVITY_TIMEOUT is interval in Seconds. If the pgAdmin screen is left +# unattended for seconds then the user will +# be logged out. When set to 0, the timeout will be disabled. +# If pgAdmin doesn't detect any activity in the time specified (in seconds), +# the user will be forcibly logged out from pgAdmin. Set to zero to disable +# the timeout. +# Note: This is applicable only for SERVER_MODE=True. +USER_INACTIVITY_TIMEOUT = {{ open_asfa_pgadmin_inactivity_timeout }} + +# OVERRIDE_USER_INACTIVITY_TIMEOUT when set to True will override +# USER_INACTIVITY_TIMEOUT when long running queries in the Query Tool +# or Debugger are running. When the queries complete, the inactivity timer +# will restart in this case. If set to False, user inactivity may cause +# transactions or in-process debugging sessions to be aborted. +OVERRIDE_USER_INACTIVITY_TIMEOUT = True + +########################################################################## + +# These settings are used when running in web server mode for confirming +# and resetting passwords etc. +# See: http://pythonhosted.org/Flask-Mail/ for more info +# MAIL_SERVER = 'localhost' +# MAIL_PORT = 25 +# MAIL_USE_SSL = False +# MAIL_USE_TLS = False +# MAIL_USERNAME = '' +# MAIL_PASSWORD = '' +# MAIL_DEBUG = False + +# Flask-Security overrides Flask-Mail's MAIL_DEFAULT_SENDER setting, so +# that should be set as such: +SECURITY_EMAIL_SENDER = '{{ open_asfa_pgadmin_email }}' + +# Check for new versions of the application? +UPGRADE_CHECK_ENABLED = False + + +########################################################################## +# SSH Tunneling supports only for Python 2.7 and 3.4+ +########################################################################## +SUPPORT_SSH_TUNNEL = False + +########################################################################## +# Allows pgAdmin4 to create session cookies based on IP address, so even +# if a cookie is stolen, the attacker will not be able to connect to the +# server using that stolen cookie. +# Note: This can cause problems when the server is deployed in dynamic IP +# address hosting environments, such as Kubernetes or behind load +# balancers. In such cases, this option should be set to False. +########################################################################## +ENHANCED_COOKIE_PROTECTION = True + +# +SESSION_COOKIE_SAMESITE = 'Lax' +SESSION_COOKIE_SECURE = False +SESSION_COOKIE_HTTPONLY = True + +########################################################################## +# External Authentication Sources +########################################################################## + +# Default setting is internal +# External Supported Sources: ldap, kerberos +# Multiple authentication can be achieved by setting this parameter to +# ['ldap', 'internal']. pgAdmin will authenticate the user with ldap first, +# in case of failure internal authentication will be done. + +AUTHENTICATION_SOURCES = ['internal'] + +########################################################################## +# LDAP Configuration +########################################################################## + +# After ldap authentication, user will be added into the SQLite database +# automatically, if set to True. +# Set it to False, if user should not be added automatically, +# in this case Admin has to add the user manually in the SQLite database. +LDAP_AUTO_CREATE_USER = True + +# Connection timeout +LDAP_CONNECTION_TIMEOUT = 10 + +# Server connection details (REQUIRED) +# example: ldap://: or ldap://: +LDAP_SERVER_URI = 'ldap://:' + +# The LDAP attribute containing user names. In OpenLDAP, this may be 'uid' +# whilst in AD, 'sAMAccountName' might be appropriate. (REQUIRED) +LDAP_USERNAME_ATTRIBUTE = '' + +########################################################################## +# 3 ways to configure LDAP as follows (Choose anyone): + +# 1. Dedicated User binding + +# LDAP Bind User DN Example: cn=username,dc=example,dc=com +# Set this parameter to allow the connection to bind using a dedicated user. +# After the connection is made, the pgadmin login user will be further +# authenticated by the username and password provided +# at the login screen. +LDAP_BIND_USER = None + +# LDAP Bind User Password +LDAP_BIND_PASSWORD = None + +# OR #################### +# 2. Anonymous Binding + +# Set this parameter to allow the anonymous bind. +# After the connection is made, the pgadmin login user will be further +# authenticated by the username and password provided + +LDAP_ANONYMOUS_BIND = False + +# OR #################### +# 3. Bind as pgAdmin user + +# BaseDN (REQUIRED) +# AD example: +# (&(objectClass=user)(memberof=CN=MYGROUP,CN=Users,dc=example,dc=com)) +# OpenLDAP example: CN=Users,dc=example,dc=com +LDAP_BASE_DN = '' + +########################################################################## + +# Search ldap for further authentication (REQUIRED) +# It can be optional while bind as pgAdmin user +LDAP_SEARCH_BASE_DN = '' + +# Filter string for the user search. +# For OpenLDAP, '(cn=*)' may well be enough. +# For AD, you might use '(objectClass=user)' (REQUIRED) +LDAP_SEARCH_FILTER = '(objectclass=*)' + +# Search scope for users (one of BASE, LEVEL or SUBTREE) +LDAP_SEARCH_SCOPE = 'SUBTREE' + +# Use TLS? If the URI scheme is ldaps://, this is ignored. +LDAP_USE_STARTTLS = False + +# TLS/SSL certificates. Specify if required, otherwise leave empty +LDAP_CA_CERT_FILE = '' +LDAP_CERT_FILE = '' +LDAP_KEY_FILE = '' diff --git a/templates/pgadmin_servers.json.j2 b/templates/pgadmin_servers.json.j2 new file mode 100644 index 0000000..ac3add6 --- /dev/null +++ b/templates/pgadmin_servers.json.j2 @@ -0,0 +1,14 @@ +{ + "Servers": { + "1": { + "Name": "Open Asfa Test DB", + "Group": "Open Asfa", + "Port": 5432, + "Username": "{{ open_asfa_db_user }}", + "Host": "pg", + "SSLMode": "prefer", + "MaintenanceDB": "postgres", + "DBRestriction": "{{ open_asfa_db_name }}" + } + } +}