diff --git a/security-guide/ch_dashboard.xml b/security-guide/ch_dashboard.xml
index a1c56eba..95b127c3 100644
--- a/security-guide/ch_dashboard.xml
+++ b/security-guide/ch_dashboard.xml
@@ -22,228 +22,20 @@
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 lightweight and easier to configure
- correctly.
- When using nginx, we recommend gunicorn as the WSGI host with an appropriate number
- of synchronous workers. When using Apache, we recommend
- mod_wsgi to host the dashboard.
-
-
- HTTPS
-
- Deploy the dashboard behind a secure
- HTTPS server by 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.
- Configure HTTP requests to the dashboard domain to redirect
- to the fully qualified HTTPS URL.
-
-
- HTTP Strict Transport Security (HSTS)
- It is highly recommended to use HTTP Strict Transport
- Security (HSTS).
-
- If you are using an HTTPS proxy in front of your web
- server, rather than using an HTTP server with HTTPS
- functionality, modify the SECURE_PROXY_SSL_HEADER
- variable. Refer to the Django documentation for information about 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 the 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/. These recommendations are based on the
- limitations of browser same-origin-policy.
- Recommendations given in this guide cannot effectively guard against
- known attacks if you deploy the dashboard in a domain that also hosts
- user-generated content, even when this content resides on a separate
- sub-domain. User-generated content can consist of scripts, images, or uploads
- of any type. Most major web presences, including googleusercontent.com,
- fbcdn.com, github.io, and twimg.co, use this approach to segregate
- user-generated content from cookies and security tokens.
- If you do not follow this recommendation regarding
- second-level domains, avoid a cookie-backed session store and
- employ HTTP Strict Transport Security (HSTS). When deployed on
- a subdomain, the dashboard's security is equivalent to the least secure
- application deployed on the same second-level domain.
-
-
- Static media
- The 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 in the Django documentation.
- 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 the 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, Node.js) should not be installed on production
- machines.
-
-
- Secret key
- The dashboard depends on a shared
- setting for some security functions. The secret key should be a
- randomly generated string at least 64 characters long, which 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 back-end
- 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 back end 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 back end 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
- back end, refer to the Django documentation understand the
- security trade-offs.
- For further details, see the Django documentation.
-
-
- Allowed hosts
- Configure the 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.
-
-
- Cross Site Request Forgery (CSRF)
- Django has dedicated middleware for cross-site request forgery (CSRF).
- For further details, see the
- Django documentation.
- 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.
-
-
- 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:
- CSRF_COOKIE_SECURE = True
-SESSION_COOKIE_SECURE = True
-
-
- Cross Site Scripting (XSS)
- Unlike many similar systems, the 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
-
- We recommend that the setting
- is set to False in production environments.
- If is set to True,
- Django will display stack traces and sensitive web server
- state information when exceptions are thrown.
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/security-guide/section_dashboard-allowed-hosts.xml b/security-guide/section_dashboard-allowed-hosts.xml
new file mode 100644
index 00000000..3b5abaf0
--- /dev/null
+++ b/security-guide/section_dashboard-allowed-hosts.xml
@@ -0,0 +1,18 @@
+
+
+
+ Allowed hosts
+ Configure the 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.
+
diff --git a/security-guide/section_dashboard-basic-web-server-configuration.xml b/security-guide/section_dashboard-basic-web-server-configuration.xml
new file mode 100644
index 00000000..7a618904
--- /dev/null
+++ b/security-guide/section_dashboard-basic-web-server-configuration.xml
@@ -0,0 +1,19 @@
+
+
+
+ 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 lightweight and easier to configure
+ correctly.
+ When using nginx, we recommend gunicorn as the WSGI host with an appropriate number
+ of synchronous workers. When using Apache, we recommend
+ mod_wsgi to host the dashboard.
+
diff --git a/security-guide/section_dashboard-cookies.xml b/security-guide/section_dashboard-cookies.xml
new file mode 100644
index 00000000..3e9272ba
--- /dev/null
+++ b/security-guide/section_dashboard-cookies.xml
@@ -0,0 +1,16 @@
+
+
+
+ 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:
+ CSRF_COOKIE_SECURE = True
+ SESSION_COOKIE_SECURE = True
+
diff --git a/security-guide/section_dashboard-cross-origin-resource-sharing-cors.xml b/security-guide/section_dashboard-cross-origin-resource-sharing-cors.xml
new file mode 100644
index 00000000..21ee07d3
--- /dev/null
+++ b/security-guide/section_dashboard-cross-origin-resource-sharing-cors.xml
@@ -0,0 +1,14 @@
+
+
+
+ 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.
+
diff --git a/security-guide/section_dashboard-cross-site-request-forgery-csrf.xml b/security-guide/section_dashboard-cross-site-request-forgery-csrf.xml
new file mode 100644
index 00000000..72559277
--- /dev/null
+++ b/security-guide/section_dashboard-cross-site-request-forgery-csrf.xml
@@ -0,0 +1,19 @@
+
+
+
+ Cross Site Request Forgery (CSRF)
+ Django has dedicated middleware for cross-site request forgery (CSRF).
+ For further details, see the
+ Django documentation.
+ 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.
+
diff --git a/security-guide/section_dashboard-cross-site-scripting-xss.xml b/security-guide/section_dashboard-cross-site-scripting-xss.xml
new file mode 100644
index 00000000..ea2811b9
--- /dev/null
+++ b/security-guide/section_dashboard-cross-site-scripting-xss.xml
@@ -0,0 +1,22 @@
+
+
+
+ Cross Site Scripting (XSS)
+ Unlike many similar systems, the 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.
+
diff --git a/security-guide/section_dashboard-debug.xml b/security-guide/section_dashboard-debug.xml
new file mode 100644
index 00000000..89b7a3ef
--- /dev/null
+++ b/security-guide/section_dashboard-debug.xml
@@ -0,0 +1,14 @@
+
+
+
+ Debug
+ We recommend that the setting
+ is set to False in production environments.
+ If is set to True,
+ Django will display stack traces and sensitive web server
+ state information when exceptions are thrown.
+
diff --git a/security-guide/section_dashboard-domain-names.xml b/security-guide/section_dashboard-domain-names.xml
new file mode 100644
index 00000000..fcf597e9
--- /dev/null
+++ b/security-guide/section_dashboard-domain-names.xml
@@ -0,0 +1,37 @@
+
+
+ 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/. These recommendations are based on the
+ limitations of browser same-origin-policy.
+ Recommendations given in this guide cannot effectively guard against
+ known attacks if you deploy the dashboard in a domain that also hosts
+ user-generated content, even when this content resides on a separate
+ sub-domain. User-generated content can consist of scripts, images, or uploads
+ of any type. Most major web presences, including googleusercontent.com,
+ fbcdn.com, github.io, and twimg.co, use this approach to segregate
+ user-generated content from cookies and security tokens.
+ If you do not follow this recommendation regarding
+ second-level domains, avoid a cookie-backed session store and
+ employ HTTP Strict Transport Security (HSTS). When deployed on
+ a subdomain, the dashboard's security is equivalent to the least secure
+ application deployed on the same second-level domain.
+
diff --git a/security-guide/section_dashboard-front-end-caching.xml b/security-guide/section_dashboard-front-end-caching.xml
new file mode 100644
index 00000000..4b471b0e
--- /dev/null
+++ b/security-guide/section_dashboard-front-end-caching.xml
@@ -0,0 +1,14 @@
+
+
+
+ Front end caching
+ Since the 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.
+
diff --git a/security-guide/section_dashboard-horizon-image-upload.xml b/security-guide/section_dashboard-horizon-image-upload.xml
new file mode 100644
index 00000000..b1558dab
--- /dev/null
+++ b/security-guide/section_dashboard-horizon-image-upload.xml
@@ -0,0 +1,14 @@
+
+
+
+ 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.
+
diff --git a/security-guide/section_dashboard-http-strict-transport-security-hsts.xml b/security-guide/section_dashboard-http-strict-transport-security-hsts.xml
new file mode 100644
index 00000000..c4f97ea6
--- /dev/null
+++ b/security-guide/section_dashboard-http-strict-transport-security-hsts.xml
@@ -0,0 +1,23 @@
+
+
+
+ HTTP Strict Transport Security (HSTS)
+ It is highly recommended to use HTTP Strict Transport
+ Security (HSTS).
+
+ If you are using an HTTPS proxy in front of your web
+ server, rather than using an HTTP server with HTTPS
+ functionality, modify the SECURE_PROXY_SSL_HEADER
+ variable. Refer to the Django documentation for information about 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.
+
diff --git a/security-guide/section_dashboard-https.xml b/security-guide/section_dashboard-https.xml
new file mode 100644
index 00000000..7857ab8b
--- /dev/null
+++ b/security-guide/section_dashboard-https.xml
@@ -0,0 +1,18 @@
+
+
+
+ HTTPS
+
+ Deploy the dashboard behind a secure
+ HTTPS server by 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.
+ Configure HTTP requests to the dashboard domain to redirect
+ to the fully qualified HTTPS URL.
+
diff --git a/security-guide/section_dashboard-secret-key.xml b/security-guide/section_dashboard-secret-key.xml
new file mode 100644
index 00000000..8f77e65f
--- /dev/null
+++ b/security-guide/section_dashboard-secret-key.xml
@@ -0,0 +1,16 @@
+
+
+
+ Secret key
+ The dashboard depends on a shared
+ setting for some security functions. The secret key should be a
+ randomly generated string at least 64 characters long, which 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.
+
diff --git a/security-guide/section_dashboard-session-back-end.xml b/security-guide/section_dashboard-session-back-end.xml
new file mode 100644
index 00000000..37c345d8
--- /dev/null
+++ b/security-guide/section_dashboard-session-back-end.xml
@@ -0,0 +1,30 @@
+
+
+
+ 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 back-end
+ 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 back end 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 back end 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
+ back end, refer to the Django documentation understand the
+ security trade-offs.
+ For further details, see the Django documentation.
+
diff --git a/security-guide/section_dashboard-static-media.xml b/security-guide/section_dashboard-static-media.xml
new file mode 100644
index 00000000..853865a0
--- /dev/null
+++ b/security-guide/section_dashboard-static-media.xml
@@ -0,0 +1,29 @@
+
+
+
+ Static media
+ The 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 in the Django documentation.
+ 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 the 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, Node.js) should not be installed on production
+ machines.
+
diff --git a/security-guide/section_dashboard-upgrading.xml b/security-guide/section_dashboard-upgrading.xml
new file mode 100644
index 00000000..4ca7a3c0
--- /dev/null
+++ b/security-guide/section_dashboard-upgrading.xml
@@ -0,0 +1,15 @@
+
+
+
+ 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.
+