Cookiecutter-zope-instance and enviroment variables - split sensitive data in an extra file

My goal: the configfile should go to VCS without the passwords.

My Question: Is it possible to split the yaml file for the zope config?

I run the following command to create my zope/plone config:

cookiecutter -f --no-input --config-file instance.yaml https://github.com/plone/cookiecutter-zope-instance
# instance.yaml
default_context:
  initial_user_name: "admin"
  initial_user_password: "admin"
  debug_mode: "true"
  verbose_security: "true"
  load_zcml:
    package_includes: [
        "my.addon"
    ]
  environment: {
    "TZ": "Europe/Berlin",
    "ENABLE_PRINTING_MAILHOST": "false",
    "CHAMELEON_CACHE": "{{ cookiecutter.location_clienthome }}/cache",
    "MAILHOST_QUEUE": "{{ cookiecutter.location_clienthome }}/mailqueue",
    "LDAP_PASSWORD": "123",
    "MAIL_ESMTP_PWD": "123",
    "DB_SQL_PW": "123",    
  }
  db_storage: direct

In the buildout-way, it was possible to extend a secret.cfg, which holds all passwords. Has anyone a hint.

I solved this by generating it in my custom entry point in a step like so:

./bin/python dockerinstance.py
make VENV=off VENV_FOLDER=. INSTANCE_YAML=dockerinstance.yaml instance

with dockerinstance.py a hacky script:

import os
import yaml


# prefix all environment variables like so:
# (after prefix a valid cookiecutter-zope-instance key is needed)
PREFIX = "INSTANCE_"

# load base instance.yaml
with open("instance.yaml", "r") as fio:
    instance = yaml.safe_load(fio)
cfg = instance["default_context"]

# set values from enviroment
for envkey, value in os.environ.items():
    if not envkey.startswith(PREFIX):
        continue
    key = envkey[len(PREFIX) :].lower()
    print(f"Set from env {envkey}: {key}={value}")
    cfg[key] = value


# write file
with open("dockerinstance.yaml", "w") as fio:
    yaml.dump(instance, fio)

Then I can use environment variables in my docker swarm yaml file like so:

services:
  plone:
    environment:
      INSTANCE_client_home: /data
      INSTANCE_wsgi_listen: 0.0.0.0:8080
      INSTANCE_wsgi_fast_listen: ""
      INSTANCE_wsgi_threads: 2
      INSTANCE_debug_mode: "false"
      INSTANCE_initial_user_name: ${INITIAL_USER_NAME?unset}
      INSTANCE_initial_user_password: ${INITIAL_USER_PASSWORD?unset}
      INSTANCE_db_storage: relstorage
      INSTANCE_db_blobs_mode: cache
      INSTANCE_db_cache_size: ${ZODB_CACHE_SIZE_OBJECTS?unset}
      INSTANCE_db_cache_size_bytes: ${ZODB_CACHE_SIZE_BYTES?unset}
      INSTANCE_db_relstorage: postgresql
      INSTANCE_db_relstorage_postgresql_dsn: host='db' dbname='plone' user='plone' password='${DB_PASSWORD?unset}'
      INSTANCE_db_relstorage_cache_local_mb: ${RELSTORAGE_LOCAL_MB?unset}

This is not thought all to the end, but as a rough plan something like this in an enhanced way should go into the mainline for cookiecutter-plone-starter at some point.

don't store them, cookiecutter will ask the missing values from command line prompt.

$ cookiecutter -f  https://github.com/plone/cookiecutter-zope-instance
target [instance]

then use a file with the missing answers:

cookiecutter -f https://github.com/plone/cookiecutter-zope-instance < /tmp/aaa.txt

aaa.txt:
yes
instancename

2 Likes

cookiecutter 2.1.2 (next release) will make it possible using command line overwrite of a single dict value.