microstack/snap-overlay/bin/set-default-config.py
Dmitrii Shcherbakov 0ba5358865 Add Secure Clustering
* Add a connection-string based workflow to MicroStack;
  * microstack add-compute command can be run at the Control node in
    order to generate a connection string (an ASCII blob for the user);
  * the connection string contains:
    * an address of the control node;
    * a sha256 fingerprint of the TLS certificate used by the clustering
      service at the control node (which is used during verification
      similar to the Certificate Pinning approach);
    * an application credential id;
    * an application credential secret (short expiration time, reader
      role on the service project, restricted to listing the service
      catalog);
  * a MicroStack admin is expected to have ssh access to all nodes that
    will participate in a cluster - prior trust establishment is on
    them to figure out which is normal since they provision the nodes;
  * a MicroStack admin is expected to securely copy a connection string
    to a compute node via ssh. Since it is short-lived and does not
    carry service secrets, there is no risk of a replay at a later time;
  * If the compute role is specified during microstack.init, a
    connection string is requested and used to perform a request to the
    clustering service and validate the certificate fingerprint. The
    credential ID and secret are POSTed for verification to the
    clustering service which responds with the necessary config data
    for the compute node upon successful authorization.
* Set up TLS termination for the clustering service;
  * run the flask app as a UWSGI daemon behind nginx;
  * configure nginx to use a TLS certificate;
  * generate a self-signed TLS certificate.

This setup does not require PKI to be present for its own purposes of
joining compute nodes to the cluster. However, this does not mean that
PKI will not be used for TLS termination of the OpenStack endpoints.

Control node init workflow (non-interactive):

sudo microstack init --auto --control
microstack add-compute
<the connection string to be used at the compute node>

Compute node init workflow (non-interactive):

sudo microstack init --auto --compute --join <connection-string>

Change-Id: I9596fe1e6e5c1a325cc71fd3bf0c78b660b9a83e
2020-10-15 01:37:33 +03:00

101 lines
3.7 KiB
Python
Executable File

#!/usr/bin/env python3
import os
import socket
from init import shell
from init import credentials
def _get_default_config():
snap_common = os.getenv('SNAP_COMMON')
return {
'config.is-clustered': False,
'config.cluster.tls-cert-path':
f'{snap_common}/etc/cluster/tls/cert.pem',
'config.cluster.tls-key-path':
f'{snap_common}/etc/cluster/tls/key.pem',
'config.cluster.fingerprint': 'null',
'config.cluster.hostname': 'null',
'config.cluster.credential-id': 'null',
'config.cluster.credential-secret': 'null',
'config.post-setup': True,
'config.keystone.region-name': 'microstack',
'config.credentials.key-pair': '/home/{USER}/snap/{SNAP_NAME}'
'/common/.ssh/id_microstack',
'config.network.node-fqdn': socket.getfqdn(),
'config.network.dns-servers': '1.1.1.1',
'config.network.dns-domain': 'microstack.example.',
'config.network.ext-gateway': '10.20.20.1',
'config.network.control-ip': '10.20.20.1',
'config.network.compute-ip': '10.20.20.1',
'config.network.ext-cidr': '10.20.20.1/24',
'config.network.security-rules': True,
'config.network.dashboard-allowed-hosts': '*',
'config.network.ports.dashboard': 80,
'config.network.ports.mysql': 3306,
'config.network.ports.rabbit': 5672,
'config.network.external-bridge-name': 'br-ex',
'config.network.physnet-name': 'physnet1',
'config.cinder.setup-loop-based-cinder-lvm-backend': False,
'config.cinder.loop-device-file-size': '32G',
'config.cinder.lvm-backend-volume-group': 'cinder-volumes',
'config.host.ip-forwarding': False,
'config.host.check-qemu': True,
'config.services.control-plane': True,
'config.services.hypervisor': True,
'config.services.spice-console': True,
'config.cluster.role': 'control',
'config.cluster.password': 'null',
'config.cleanup.delete-bridge': True,
'config.cleanup.remove': True,
'config.logging.custom-config': f'{snap_common}/etc/filebeat'
'/filebeat-microstack.yaml',
'config.logging.datatag': '',
'config.logging.host': 'localhost:5044',
'config.services.extra.enabled': False,
'config.services.extra.filebeat': False,
'config.alerting.custom-config': f'{snap_common}/etc/nrpe'
'/nrpe-microstack.cfg',
'config.services.extra.nrpe': False,
'config.monitoring.ipmi': '',
'config.services.extra.telegraf': False,
'config.monitoring.custom-config': f'{snap_common}/etc/telegraf'
'/telegraf-microstack.conf'
}
def _set_default_config():
shell.config_set(**_get_default_config())
def _setup_secrets():
# If a user runs init multiple times we do not want to generate
# new credentials to keep the init operation idempotent.
existing_creds = shell.config_get('config.credentials')
if isinstance(existing_creds, dict):
existing_cred_keys = existing_creds.keys()
else:
existing_cred_keys = []
shell.config_set(**{
f'config.credentials.{k}': credentials.generate_password() for k in [
'mysql-root-password',
'rabbitmq-password',
'keystone-password',
'nova-password',
'cinder-password',
'neutron-password',
'placement-password',
'glance-password',
'ovn-metadata-proxy-shared-secret',
] if k not in existing_cred_keys
})
if __name__ == '__main__':
_set_default_config()
_setup_secrets()