arrow_backAll Posts·5 Min Read·2024-12-02

Secure OpenStack and Yuyu Billing with TLS

ProjectOpenStackContainerApachePython

Many organizations run private clouds with OpenStack to manage infrastructure more flexibly and efficiently. In day-to-day operations, however, teams still need to control resource usage and reduce human error, especially when developers test in an environment that is too close to production. Separating development and production projects helps protect system stability and keeps resource usage predictable.

The organization also needs a measurable way to track and calculate resource usage. Yuyu provides usage reporting and billing for OpenStack resources, including volumes, flavors, images, and routers. With this data, the team can analyze consumption and identify opportunities to reduce operating costs.

  • OpenStack - Antelope - v2023.1
  • Kolla-Ansible - v2023.1
  • Ansible - v2.14.18
  • Horizon - v2023.1
  • Yuyu - v2023.1
  • Python - 3.10.12

OpenStack and Yuyu topology

  • Create an IP SAN file for the controller node, because Horizon and Yuyu run on the controller.

    bash
    sudo nano /etc/ssl/IP_SANS.txt
    
    bash
    subjectAltName=IP:<IP Server / Node>
    
  • Create a directory for the certificates under /etc/ssl/.

    bash
    ~$ sudo mkdir -p /etc/ssl/
    ~$ sudo mkdir -p /etc/ssl/
    
  • Create certificates for Horizon and Yuyu.

    • Horizon:

      bash
      sudo openssl genrsa -out /etc/ssl/horizon/horizon.key 2048
      
      sudo openssl req -sha512 -new \
        -subj "/C=IN/ST=jateng/L=kendal/0=Horizon Najwan/OU=Horizon Najwan/CN=Horizon Najwan>" \
        -key /etc/ssl/horizon/horizon.key \
        -out /etc/ssl/horizon/horizon.csr
      
      sudo openssl x509 -req -sha512 -days 3650 \
        -key /etc/ssl/horizon/horizon.key \
        -extfile /etc/ssl/IP_SANS.txt \
        -in /etc/ssl/horizon/horizon.csr\
        -out /etc/ssl/horizon/horizon.crt
      
    • Yuyu:

      bash
      sudo openssl genrsa -out /etc/ssl/yuyu/yuyu.key 2048
      
      sudo openssl req -sha512 -new \
        -subj "/C=IN/ST=jateng/L=kendal/0=Yuyu Najwan/OU=Yuyu Najwan/CN=Yuyu Najwan>" \
        -key /etc/ssl/yuyu/yuyu.key \
        -out /etc/ssl/yuyu/yuyu.csr
      
      sudo openssl x509 -req -sha512 -days 3650 \
        -key /etc/ssl/yuyu/yuyu.key \
        -extfile /etc/ssl/IP_SANS.txt \
        -in /etc/ssl/yuyu/yuyu.csr\
        -out /etc/ssl/yuyu/yuyu.crt
      
  • Install the certificates into Ubuntu's trust store so they are trusted by the operating system and by Horizon's Django application.

    bash
    ~$ sudo apt-get install ca-certificates
    ~$ sudo cp /etc/ssl/horizon/horizon.crt /usr/local/share/ca-certificates
    ~$ sudo cp /etc/ssl/yuyu/yuyu.crt /usr/local/share/ca-certificates
    
    ~$ sudo update-ca-certificates
    

OpenStack includes several services that communicate through their respective APIs:

  • Keystone provides identity and access verification.
  • Neutron provides OpenStack networking.
  • Nova provides compute services and creates instances.
  • Glance stores the images used to create instances.
  • Cinder provides volumes for instances.
  • RabbitMQ is the message broker that distributes OpenStack events.

For the complete OpenStack installation procedure, see OpenStack and Kolla-Ansible. Apply the following adjustments before deployment because the cluster must be redeployed after internal TLS is enabled.

  • Update globals.yml to enable TLS for internal OpenStack services and copy the CA into the service containers. Replace {DIR_KOLLA} with {{ node_config }} and {DIR_KOLLA_CERT} with {{ kolla_certificates_dir }}.

    yaml
    openstack_cacert: "/etc/ssl/certs/ca-certificates.crt"
    kolla_enable_tls_internal: "yes"
    kolla_certificates_dir: "{DIR_KOLLA}/certificates"
    kolla_admin_openrc_cacert: "/etc/kolla/certificates/ca/root.crt"
    kolla_copy_ca_into_containers: "yes"
    kolla_enable_tls_backend: "yes"
    kolla_verify_tls_backend: "no"
    kolla_tls_backend_cert: "{DIR_KOLLA_CERT}/backend-cert.pem"
    kolla_tls_backend_key: "{DIR_KOLLA_CERT}/backend-key.pem"
    
  • Before deployment, generate the certificates with:

    bash
    (kolla-venv) student@controller:~$ kolla-ansible -i ./multinode certificates
    

Horizon and Yuyu API are both implemented with Django. To enable TLS, configure Django with the certificate and private-key files. For the base Horizon and Yuyu installation, see Yuyu Billing in OpenStack Horizon.

The following additional steps enable TLS on both services.

A. Horizon

  • Update Horizon's local_settings.py, located here in this example: /var/www/html/horizon/openstack_dashboard/local/.

    python
    WEBROOT = '/'
    YUYU_URL = 'https://{IP HOST}:8182'
    
    SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
    CSRF_COOKIE_SECURE = True
    SESSION_COOKIE_SECURE = True
    
    OPENSTACK_KEYSTONE_URL = 'https://{IP HOST}:5000/v3'
    OPENSTACK_KEYSTONE_DEFAULT_ROLE = 'member'
    OPENSTACK_SSL_NO_VERIFY = False
    OPENSTACK_SSL_CACERT = '/etc/ssl/certs/ca-certificates.crt'
    
    OPENSTACK_KEYSTONE_BACKEND = {
      'name': 'native',
      'can_edit_group': True,
      'can_edit_user': True,
      'can_edit_role': True,
      'can_edit_project': True,
      'can_edit_domain': True,
    }
    
  • When generating the Apache configuration, add the SSL options below.

    bash
    ~# ./manage.py make_web_conf --apache \
      --sslkey  /etc/ssl/horizon/horizon.key \
      --sslcert /etc/ssl/horizon/horizon.crt \
      --cacert /etc/ssl/certs/ca-certificates.crt \
      --ssl > /etc/apache2/sites-available/horizon.conf
    
  • Restart Apache and Memcached.

    bash
    ~# systemctl restart apache2.service memcached
    

B. Yuyu API

  • Update Yuyu API's local_settings.py, located here in this example: /var/yuyu/yuyu/.

    python
    ALLOWED_HOSTS = ['*']
    
    SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
    SECURE_SSL_HOST = True
    SECURE_SSL_REDIRECT = False
    SESSION_COOKIE_SECURE = True
    CSRF_COOKIE_SECURE = True
    
  • Update the Yuyu API service to enable TLS.

    bash
    ~# nano /etc/systemd/system/yuyu_api.service
    
    ExecStart=/var/yuyu/env/bin/gunicorn yuyu.wsgi \
      --workers 2 \
      --keyfile  /etc/ssl/yuyu/yuyu.key \
      --certfile /etc/ssl/yuyu/yuyu.crt \
      --bind 10.18.18.10:8182 \
      --log-file=logs/gunicorn.log
    
  • Restart Yuyu API, Apache, and Memcached.

    bash
    ~# systemctl restart yuyu_api.service spache2.service memcached
    
  • CLI login fails when using the OpenStack openrc file.

    Update export OS_CACERT in the openrc file. If it does not exist, add it with /etc/kolla/certificates/ca/root.crt. You can also use /etc/ssl/certs/ca-certificate.crt after copying the root certificate to /usr/local/share/ca-certificates and running sudo update-ca-certificates.

  • SSLError at /admin/billing_overview/ appears in Horizon.

    Django does not trust the self-signed certificate. Add the Horizon and Yuyu certificates to /usr/local/share/ca-certificates, then update the CA store using the Ubuntu root CA guide.

  • AttributeError at /auth/logout/ appears when signing out of Horizon.

    Use python-memcached version 1.59. Newer versions may cause the logout flow to fail in this setup.

  • Curl reports an Invalid HTTP_HOST header error.

    Add the host IP, such as 10.18.18.10, to ALLOWED_HOSTS in Yuyu's local_settings.py. Use * only when every source IP should be allowed.

  • The Horizon instance console shows Did Not Connect: Potential Security Issue.

    This can happen when the certificate is not publicly trusted or when the instance image is invalid. Select "Click here to show only console" below the "Instance Console" heading to check whether the image is the cause.

Final Result

The final result is similar to the Yuyu Billing in OpenStack Horizon project, with Horizon, Yuyu Billing, and OpenStack services protected by TLS.

This project covers the complete workflow: generating certificates, configuring the services, and troubleshooting common issues. The topology and step-by-step commands are intended to make the implementation easier to follow, especially for engineers who are new to OpenStack security.