Dashboard Horizon is the OpenStack dashboard that provides users a self-service portal to provision their own resources within the limits set by administrators. These include provisioning users, defining instance flavors, uploading VM images, managing networks, setting up security groups, starting instances, and accessing the instances via a console. The dashboard is based on the Django web framework, therefore secure deployment practices for Django apply directly to horizon. This guide provides a popular set of Django security recommendations, further information can be found by reading the Django deployment and security documentation. The dashboard ships with reasonable default security settings, and has good deployment and configuration documentation.
Basic web server configuration The dashboard should be deployed as a Web Services Gateway Interface (WSGI) application behind an HTTPS proxy such as Apache or nginx. If Apache is not already in use, we recommend nginx since it is lighter weight and easier to configure correctly. When using nginx, we recommend gunicorn as the wsgi host with an appropriate number of synchronous workers. We strongly advise against deployments using fastcgi, scgi, or uWSGI. We strongly advise against the use of synthetic performance benchmarks when choosing a wsgi server. When using Apache, we recommend mod_wsgi to host dashboard.
HTTPS The dashboard should be deployed behind a secure HTTPS server using a valid, trusted certificate from a recognized certificate authority (CA). Private organization-issued certificates are only appropriate when the root of trust is pre-installed in all user browsers. HTTP requests to the dashboard domain should be configured to redirect to the fully qualified HTTPS URL.
HTTP Strict Transport Security (HSTS) It is highly recommended to use HTTP Strict Transport Security (HSTS). NOTE: If you are using an HTTPS proxy in front of your web server, rather than using an HTTP server with HTTPS functionality, follow the Django documentation on modifying the SECURE_PROXY_SSL_HEADER variable. See the chapter on PKI/SSL Everywhere for more specific recommendations and server configurations for HTTPS configurations, including the configuration of HSTS.
Front end caching Since dashboard is rendering dynamic content passed directly from OpenStack API requests, we do not recommend front end caching layers such as varnish. In Django, static media is directly served from Apache or nginx and already benefits from web host caching.
Domain names Many organizations typically deploy web applications at subdomains of an overarching organization domain. It is natural for users to expect a domain of the form openstack.example.org. In this context, there are often many other applications deployed in the same second-level namespace, often serving user-controlled content. This name structure is convenient and simplifies name server maintenance. We strongly recommend deploying horizon to a second-level domain, such as https://example.com, and advise against deploying horizon on a shared subdomain of any level, for example https://openstack.example.org or https://horizon.openstack.example.org. We also advise against deploying to bare internal domains like https://horizon/. This recommendation is based on the limitations browser same-origin-policy. The recommendations in this guide cannot effectively protect users against known attacks if dashboard is deployed on a domain which also hosts user-generated content, such as scripts, images, or uploads of any kind, even if the user-generated content is on a different subdomain. This approach is used by most major web presences, such as googleusercontent.com, fbcdn.com, github.io, and twimg.com, to ensure that user generated content stays separate from cookies and security tokens. Additionally, if you decline to follow this recommendation above about second-level domains, it is vital that you avoid the cookie backed session store and employ HTTP Strict Transport Security (HSTS). When deployed on a subdomain, dashboard's security is only as strong as the weakest application deployed on the same second-level domain.
Static media Dashboard's static media should be deployed to a subdomain of the dashboard domain and served by the web server. The use of an external content delivery network (CDN) is also acceptable. This subdomain should not set cookies or serve user-provided content. The media should also be served with HTTPS. Django media settings are documented at https://docs.djangoproject.com/en/1.5/ref/settings/#static-root. Dashboard's default configuration uses django_compressor to compress and minify css and JavaScript content before serving it. This process should be statically done before deploying dashboard, rather than using the default in-request dynamic compression and copying the resulting files along with deployed code or to the CDN server. Compression should be done in a non-production build environment. If this is not practical, we recommend disabling resource compression entirely. Online compression dependencies (less, nodejs) should not be installed on production machines.
Secret key Dashboard depends on a shared SECRET_KEY setting for some security functions. It should be a randomly generated string at least 64 characters long. It must be shared across all active dashboard instances. Compromise of this key may allow a remote attacker to execute arbitrary code. Rotating this key invalidates existing user sessions and caching. Do not commit this key to public repositories.
Session back-end Horizon's default session back-end (django.contrib.sessions.backends.signed_cookies) stores user data in signed but unencrypted cookies stored in the browser. This approach allows the most simple session backend scaling since each dashboard instance is stateless, but it comes at the cost of storing sensitive access tokens in the client browser and transmitting them with every request. This backend ensures that session data has not been tampered with, but the data itself is not encrypted other than the encryption provided by HTTPS. If your architecture allows it, we recommend using django.contrib.sessions.backends.cache as your session backend with memcache as the cache. Memcache must not be exposed publicly, and should communicate over a secured private channel. If you choose to use the signed cookies backend, refer to the Django documentation understand the security trade-offs. For further details, consult the Django session backend documentation.
Allowed hosts Configure the ALLOWED_HOSTS setting with the domain or domains where the dashboard is available. Failure to configure this setting (especially if not following the recommendation above regarding second level domains) opens the dashboard to a number of serious attacks. Wild card domains should be avoided. For further details, see the Django documentation on settings.
Cookies Session Cookies should be set to HTTPONLY: SESSION_COOKIE_HTTPONLY = True Never configure CSRF or session cookies to have a wild card domain with a leading dot. Horizon's session and CSRF cookie should be secured when deployed with HTTPS: Code CSRF_COOKIE_SECURE = True SESSION_COOKIE_SECURE = True
Password auto complete We recommend that implementers do not change the default password auto complete behavior. Users choose stronger passwords in environments that allow them to use the secure browser password manager. Organizations which forbid the browser password manager should enforce this policy at the desktop level.
Cross Site Request Forgery (CSRF) Django has a dedicated middleware for cross-site request forgery (CSRF). Dashboard is designed to discourage developers from introducing cross-site scripting vulnerabilities with custom dashboards. However, it is important to audit custom dashboards, especially ones that are javascript-heavy for inappropriate use of the @csrf_exempt decorator. Dashboards which do not follow these recommended security settings should be carefully evaluated before restrictions are relaxed.
Cross Site Scripting (XSS) Unlike many similar systems, OpenStack dashboard allows the entire Unicode character set in most fields. This means developers have less latitude to make escaping mistakes that open attack vectors for cross-site scripting (XSS). Dashboard provides tools for developers to avoid creating XSS vulnerabilities, but they only work if developers use them correctly. Audit any custom dashboards, paying particular attention to use of the mark_safe function, use of is_safe with custom template tags, the safe template tag, anywhere auto escape is turned off, and any JavaScript which might evaluate improperly escaped data.
Cross Origin Resource Sharing (CORS) Configure your web server to send a restrictive CORS header with each response, allowing only the dashboard domain and protocol: Access-Control-Allow-Origin: https://example.com/ Never allow the wild card origin.
Horizon image upload We recommend that implementers disable HORIZON_IMAGES_ALLOW_UPLOAD unless they have implemented a plan to prevent resource exhaustion and denial of service.
Upgrading Django security releases are generally well tested and aggressively backwards compatible. In almost all cases, new major releases of Django are also fully backwards compatible with previous releases. Dashboard implementers are strongly encouraged to run the latest stable release of Django with up-to-date security releases.
Debug Make sure DEBUG is set to False in production. In Django, DEBUG displays stack traces and sensitive web server state information on any exception.