Merge "Don't create admin user if there is LDAP backend set to read_only"
diff --git a/README.rst b/README.rst
index 14403eb..89593bd 100644
--- a/README.rst
+++ b/README.rst
@@ -305,6 +305,56 @@
virtual_host: '/openstack'
....
+Client-side RabbitMQ TLS configuration:
+
+|
+
+By default system-wide CA certs are used. Nothing should be specified except `ssl.enabled`.
+
+.. code-block:: yaml
+
+ keystone:
+ server:
+ ....
+ message_queue:
+ ssl:
+ enabled: True
+
+Use `cacert_file` option to specify the CA-cert file path explicitly:
+
+.. code-block:: yaml
+
+ keystone:
+ server:
+ ....
+ message_queue:
+ ssl:
+ enabled: True
+ cacert_file: /etc/ssl/rabbitmq-ca.pem
+
+To manage content of the `cacert_file` use the `cacert` option:
+
+.. code-block:: yaml
+
+ keystone:
+ server:
+ ....
+ message_queue:
+ ssl:
+ enabled: True
+ cacert: |
+
+ -----BEGIN CERTIFICATE-----
+ ...
+ -----END CERTIFICATE-------
+
+ cacert_file: /etc/openstack/rabbitmq-ca.pem
+
+
+Notice:
+ * The `message_queue.port` is set to **5671** (AMQPS) by default if `ssl.enabled=True`.
+ * Use `message_queue.ssl.version` if you need to specify protocol version. By default is TLSv1 for python < 2.7.9 and TLSv1_2 for version above.
+
Enable CADF audit notification
.. code-block:: yaml
@@ -614,6 +664,18 @@
policy:
admin_or_token_subject: 'rule:admin_required or rule:token_subject'
+Setting up default admin project name and domain
+
+.. code-block:: yaml
+
+
+ keystone:
+ server:
+ ....
+ admin_project:
+ name: "admin"
+ domain: "default"
+
Usage
=====
diff --git a/_modules/keystone_policy.py b/_modules/keystone_policy.py
index 4e3ae6d..2e79f22 100644
--- a/_modules/keystone_policy.py
+++ b/_modules/keystone_policy.py
@@ -2,10 +2,56 @@
import json
import logging
-import yaml
-
LOG = logging.getLogger(__name__)
+import yaml
+import yaml.constructor
+
+try:
+ # included in standard lib from Python 2.7
+ from collections import OrderedDict
+except ImportError:
+ # try importing the backported drop-in replacement
+ # it's available on PyPI
+ from ordereddict import OrderedDict
+
+# https://stackoverflow.com/questions/5121931/in-python-how-can-you-load-yaml-mappings-as-ordereddicts
+class OrderedDictYAMLLoader(yaml.Loader):
+ """
+ A YAML loader that loads mappings into ordered dictionaries.
+ """
+
+ def __init__(self, *args, **kwargs):
+ yaml.Loader.__init__(self, *args, **kwargs)
+
+ self.add_constructor(u'tag:yaml.org,2002:map', type(self).construct_yaml_map)
+ self.add_constructor(u'tag:yaml.org,2002:omap', type(self).construct_yaml_map)
+
+ def construct_yaml_map(self, node):
+ data = OrderedDict()
+ yield data
+ value = self.construct_mapping(node)
+ data.update(value)
+
+ def construct_mapping(self, node, deep=False):
+ if isinstance(node, yaml.MappingNode):
+ self.flatten_mapping(node)
+ else:
+ raise yaml.constructor.ConstructorError(None, None,
+ 'expected a mapping node, but found %s' % node.id, node.start_mark)
+
+ mapping = OrderedDict()
+ for key_node, value_node in node.value:
+ key = self.construct_object(key_node, deep=deep)
+ try:
+ hash(key)
+ except TypeError, exc:
+ raise yaml.constructor.ConstructorError('while constructing a mapping',
+ node.start_mark, 'found unacceptable key (%s)' % exc, key_node.start_mark)
+ value = self.construct_object(value_node, deep=deep)
+ mapping[key] = value
+ return mapping
+
def __virtual__():
return True
@@ -14,8 +60,7 @@
def rule_list(path, **kwargs):
try:
with io.open(path, 'r') as file_handle:
- rules = yaml.safe_load(file_handle) or {}
- rules = {str(k): str(v) for (k, v) in rules.items()}
+ rules = yaml.load(file_handle, OrderedDictYAMLLoader) or OrderedDict()
except Exception as e:
msg = "Unable to load policy file %s: %s" % (path, repr(e))
LOG.debug(msg)
diff --git a/keystone/files/grafana_dashboards/keystone_prometheus.json b/keystone/files/grafana_dashboards/keystone_prometheus.json
index 1d0e495..6d64799 100755
--- a/keystone/files/grafana_dashboards/keystone_prometheus.json
+++ b/keystone/files/grafana_dashboards/keystone_prometheus.json
@@ -21,8 +21,8 @@
"colorValue": true,
"colors": [
"rgba(245, 54, 54, 0.9)",
- "rgba(237, 129, 40, 0.89)",
- "rgba(50, 172, 45, 0.97)"
+ "rgba(50, 172, 45, 0.97)",
+ "rgba(237, 129, 40, 0.89)"
],
"datasource": null,
"format": "none",
@@ -79,7 +79,7 @@
"step": 60
}
],
- "thresholds": "1,0",
+ "thresholds": "0.5,1.5",
"title": "API Availability",
"type": "singlestat",
"valueFontSize": "80%",
@@ -91,13 +91,18 @@
},
{
"op": "=",
+ "text": "DOWN",
+ "value": "0"
+ },
+ {
+ "op": "=",
"text": "OK",
"value": "1"
},
{
"op": "=",
- "text": "DOWN",
- "value": "0"
+ "text": "UNKNOWN",
+ "value": "2"
}
],
"valueName": "current"
diff --git a/keystone/files/keystonercv3 b/keystone/files/keystonercv3
index 9da173c..bf2b3ad 100644
--- a/keystone/files/keystonercv3
+++ b/keystone/files/keystonercv3
@@ -9,4 +9,5 @@
export OS_PASSWORD={{ server.admin_password }}
export OS_REGION_NAME={{ server.region }}
export OS_INTERFACE=internal
+export OS_ENDPOINT_TYPE="internal"
export OS_CACERT="{{ server.cacert }}"
diff --git a/keystone/files/mitaka/keystone.conf.Debian b/keystone/files/mitaka/keystone.conf.Debian
index a526cee..18d6f2b 100644
--- a/keystone/files/mitaka/keystone.conf.Debian
+++ b/keystone/files/mitaka/keystone.conf.Debian
@@ -1,4 +1,4 @@
-{% from "keystone/map.jinja" import server with context %}
+{% from "keystone/map.jinja" import server, system_cacerts_file with context %}
[DEFAULT]
#
@@ -601,7 +601,7 @@
# Deprecated group/name - [DATABASE]/sql_connection
# Deprecated group/name - [sql]/connection
#connection = <None>
-connection={{ server.database.engine }}://{{ server.database.user }}:{{ server.database.password }}@{{ server.database.host }}/{{ server.database.name }}
+connection={{ server.database.engine }}://{{ server.database.user }}:{{ server.database.password }}@{{ server.database.host }}/{{ server.database.name }}{%- if server.database.get('ssl',{}).get('enabled',False) %}?ssl_ca={{ server.database.ssl.get('cacert_file', system_cacerts_file) }}{% endif %}
# The SQLAlchemy connection string to use to connect to the slave database.
# (string value)
@@ -1577,14 +1577,31 @@
# Allowed values: round-robin, shuffle
#kombu_failover_strategy = round-robin
+{%- set rabbit_port = server.message_queue.get('port', 5671 if server.message_queue.get('ssl',{}).get('enabled', False) else 5672) %}
{%- if server.message_queue.members is defined %}
rabbit_hosts = {% for member in server.message_queue.members -%}
- {{ member.host }}:{{ member.get('port', 5672) }}
+ {{ member.host }}:{{ member.get('port', rabbit_port) }}
{%- if not loop.last -%},{%- endif -%}
{%- endfor -%}
{%- else %}
rabbit_host = {{ server.message_queue.host }}
-rabbit_port = {{ server.message_queue.port }}
+rabbit_port = {{ rabbit_port }}
+{%- endif %}
+
+{%- if server.message_queue.get('ssl',{}).get('enabled', False) %}
+rabbit_use_ssl=true
+
+{%- if server.message_queue.ssl.version is defined %}
+kombu_ssl_version = {{ server.message_queue.ssl.version }}
+{%- elif salt['grains.get']('pythonversion') > [2,7,8] %}
+kombu_ssl_version = TLSv1_2
+{%- endif %}
+
+{%- if server.message_queue.ssl.cacert_file is defined %}
+kombu_ssl_ca_certs = {{ server.message_queue.ssl.cacert_file }}
+{%- else %}
+kombu_ssl_ca_certs={{ system_cacerts_file }}
+{%- endif %}
{%- endif %}
# RabbitMQ HA cluster host:port pairs. (list value)
diff --git a/keystone/files/newton/keystone.conf.Debian b/keystone/files/newton/keystone.conf.Debian
index db95287..83f4b13 100644
--- a/keystone/files/newton/keystone.conf.Debian
+++ b/keystone/files/newton/keystone.conf.Debian
@@ -1,4 +1,4 @@
-{% from "keystone/map.jinja" import server with context %}
+{% from "keystone/map.jinja" import server, system_cacerts_file with context %}
[DEFAULT]
#
@@ -358,14 +358,16 @@
# A URL representing the messaging driver to use and its full configuration.
# (string value)
#transport_url = rabbit://nova:3qVSI7a1m8AdaDQ7BpB0PJu4@192.168.0.4:5673/
+
+{%- set rabbit_port = server.message_queue.get('port', 5671 if server.message_queue.get('ssl',{}).get('enabled', False) else 5672) %}
{%- if server.message_queue.members is defined %}
transport_url = rabbit://{% for member in server.message_queue.members -%}
- {{ server.message_queue.user }}:{{ server.message_queue.password }}@{{ member.host }}:{{ member.get('port', 5672) }}
+ {{ server.message_queue.user }}:{{ server.message_queue.password }}@{{ member.host }}:{{ member.get('port', rabbit_port) }}
{%- if not loop.last -%},{%- endif -%}
{%- endfor -%}
/{{ server.message_queue.virtual_host }}
{%- else %}
-transport_url = rabbit://{{ server.message_queue.user }}:{{ server.message_queue.password }}@{{ server.message_queue.host }}:{{ server.message_queue.port }}/{{ server.message_queue.virtual_host }}
+transport_url = rabbit://{{ server.message_queue.user }}:{{ server.message_queue.password }}@{{ server.message_queue.host }}:{{ rabbit_port }}/{{ server.message_queue.virtual_host }}
{%- endif %}
# DEPRECATED: The messaging driver to use, defaults to rabbit. Other drivers
@@ -374,7 +376,6 @@
# Its value may be silently ignored in the future.
# Reason: Replaced by [DEFAULT]/transport_url
#rpc_backend = rabbit
-rpc_backend = rabbit
{%- endif %}
# The default exchange under which topics are scoped. May be overridden by an
@@ -703,7 +704,7 @@
# Deprecated group/name - [DATABASE]/sql_connection
# Deprecated group/name - [sql]/connection
#connection = <None>
-connection={{ server.database.engine }}+pymysql://{{ server.database.user }}:{{ server.database.password }}@{{ server.database.host }}/{{ server.database.name }}
+connection={{ server.database.engine }}+pymysql://{{ server.database.user }}:{{ server.database.password }}@{{ server.database.host }}/{{ server.database.name }}{%- if server.database.get('ssl',{}).get('enabled',False) %}?ssl_ca={{ server.database.ssl.get('cacert_file', system_cacerts_file) }}{% endif %}
# The SQLAlchemy connection string to use to connect to the slave database.
# (string value)
@@ -1865,6 +1866,26 @@
# From oslo.messaging
#
+{%- if server.notification %}
+
+{%- if server.message_queue.get('ssl',{}).get('enabled', False) %}
+rabbit_use_ssl=true
+
+{%- if server.message_queue.ssl.version is defined %}
+kombu_ssl_version = {{ server.message_queue.ssl.version }}
+{%- elif salt['grains.get']('pythonversion') > [2,7,8] %}
+kombu_ssl_version = TLSv1_2
+{%- endif %}
+
+{%- if server.message_queue.ssl.cacert_file is defined %}
+kombu_ssl_ca_certs = {{ server.message_queue.ssl.cacert_file }}
+{%- else %}
+kombu_ssl_ca_certs={{ system_cacerts_file }}
+{%- endif %}
+{%- endif %}
+
+{%- endif %}
+
# Use durable queues in AMQP. (boolean value)
# Deprecated group/name - [DEFAULT]/amqp_durable_queues
# Deprecated group/name - [DEFAULT]/rabbit_durable_queues
diff --git a/keystone/files/ocata/keystone.conf.Debian b/keystone/files/ocata/keystone.conf.Debian
index 375935c..c15982f 100644
--- a/keystone/files/ocata/keystone.conf.Debian
+++ b/keystone/files/ocata/keystone.conf.Debian
@@ -1,4 +1,4 @@
-{% from "keystone/map.jinja" import server with context %}
+{% from "keystone/map.jinja" import server, system_cacerts_file with context %}
[DEFAULT]
#
@@ -425,14 +425,15 @@
# A URL representing the messaging driver to use and its full configuration.
# (string value)
#transport_url = rabbit://nova:3qVSI7a1m8AdaDQ7BpB0PJu4@192.168.0.4:5673/
+{%- set rabbit_port = server.message_queue.get('port', 5671 if server.message_queue.get('ssl',{}).get('enabled', False) else 5672) %}
{%- if server.message_queue.members is defined %}
transport_url = rabbit://{% for member in server.message_queue.members -%}
- {{ server.message_queue.user }}:{{ server.message_queue.password }}@{{ member.host }}:{{ member.get('port', 5672) }}
+ {{ server.message_queue.user }}:{{ server.message_queue.password }}@{{ member.host }}:{{ member.get('port', rabbit_port) }}
{%- if not loop.last -%},{%- endif -%}
{%- endfor -%}
/{{ server.message_queue.virtual_host }}
{%- else %}
-transport_url = rabbit://{{ server.message_queue.user }}:{{ server.message_queue.password }}@{{ server.message_queue.host }}:{{ server.message_queue.port }}/{{ server.message_queue.virtual_host }}
+transport_url = rabbit://{{ server.message_queue.user }}:{{ server.message_queue.password }}@{{ server.message_queue.host }}:{{ rabbit_port }}/{{ server.message_queue.virtual_host }}
{%- endif %}
# DEPRECATED: The messaging driver to use, defaults to rabbit. Other drivers
@@ -441,7 +442,6 @@
# Its value may be silently ignored in the future.
# Reason: Replaced by [DEFAULT]/transport_url
#rpc_backend = rabbit
-rpc_backend = rabbit
{%- endif %}
# The default exchange under which topics are scoped. May be overridden by an
# exchange name specified in the transport_url option. (string value)
@@ -776,7 +776,7 @@
# Deprecated group/name - [DATABASE]/sql_connection
# Deprecated group/name - [sql]/connection
#connection = <None>
-connection={{ server.database.engine }}+pymysql://{{ server.database.user }}:{{ server.database.password }}@{{ server.database.host }}/{{ server.database.name }}
+connection={{ server.database.engine }}+pymysql://{{ server.database.user }}:{{ server.database.password }}@{{ server.database.host }}/{{ server.database.name }}{%- if server.database.get('ssl',{}).get('enabled',False) %}?ssl_ca={{ server.database.ssl.get('cacert_file', system_cacerts_file) }}{% endif %}
# The SQLAlchemy connection string to use to connect to the slave database.
# (string value)
@@ -1962,6 +1962,27 @@
# From oslo.messaging
#
+
+{%- if server.notification %}
+
+{%- if server.message_queue.get('ssl',{}).get('enabled', False) %}
+rabbit_use_ssl=true
+
+{%- if server.message_queue.ssl.version is defined %}
+kombu_ssl_version = {{ server.message_queue.ssl.version }}
+{%- elif salt['grains.get']('pythonversion') > [2,7,8] %}
+kombu_ssl_version = TLSv1_2
+{%- endif %}
+
+{%- if server.message_queue.ssl.cacert_file is defined %}
+kombu_ssl_ca_certs = {{ server.message_queue.ssl.cacert_file }}
+{%- else %}
+kombu_ssl_ca_certs={{ system_cacerts_file }}
+{%- endif %}
+{%- endif %}
+
+{%- endif %}
+
# Use durable queues in AMQP. (boolean value)
# Deprecated group/name - [DEFAULT]/amqp_durable_queues
# Deprecated group/name - [DEFAULT]/rabbit_durable_queues
@@ -2591,6 +2612,9 @@
# Name of the domain that owns the `admin_project_name`. If left unset, then
# there is no admin project. `[resource] admin_project_name` must also be set
# to use this option. (string value)
+{%- if server.admin_project is defined %}
+admin_project_domain_name = {{ server.admin_project.domain }}
+{%- endif %}
#admin_project_domain_name = <None>
# This is a special project which represents cloud-level administrator
@@ -2601,6 +2625,9 @@
# means of cross-project role assignments. `[resource]
# admin_project_domain_name` must also be set to use this option. (string
# value)
+{%- if server.admin_project is defined %}
+admin_project_name = {{ server.admin_project.name }}
+{%- endif %}
#admin_project_name = <None>
# This controls whether the names of projects are restricted from containing
diff --git a/keystone/files/ocata/keystone.conf.RedHat b/keystone/files/ocata/keystone.conf.RedHat
index 663854e..7f4d9f1 100644
--- a/keystone/files/ocata/keystone.conf.RedHat
+++ b/keystone/files/ocata/keystone.conf.RedHat
@@ -2560,6 +2560,9 @@
# Name of the domain that owns the `admin_project_name`. If left unset, then
# there is no admin project. `[resource] admin_project_name` must also be set
# to use this option. (string value)
+{%- if server.admin_project is defined %}
+admin_project_domain_name = {{ server.admin_project.domain }}
+{%- endif %}
#admin_project_domain_name = <None>
# This is a special project which represents cloud-level administrator
@@ -2570,6 +2573,9 @@
# means of cross-project role assignments. `[resource]
# admin_project_domain_name` must also be set to use this option. (string
# value)
+{%- if server.admin_project is defined %}
+admin_project_name = {{ server.admin_project.name }}
+{%- endif %}
#admin_project_name = <None>
# This controls whether the names of projects are restricted from containing
@@ -3058,4 +3064,4 @@
# unless you are providing a custom entry point. (string value)
#driver = sql
[extra_headers]
-Distribution = Ubuntu
\ No newline at end of file
+Distribution = Ubuntu
diff --git a/keystone/map.jinja b/keystone/map.jinja
index 1a40274..01dc3f4 100644
--- a/keystone/map.jinja
+++ b/keystone/map.jinja
@@ -1,3 +1,7 @@
+{%- set system_cacerts_file = salt['grains.filter_by']({
+ 'Debian': '/etc/ssl/certs/ca-certificates.crt',
+ 'RedHat': '/etc/pki/tls/certs/ca-bundle.crt'
+})%}
{% set server = salt['grains.filter_by']({
'Debian': {
@@ -58,6 +62,7 @@
{% set monitoring = salt['grains.filter_by']({
'default': {
'error_log_rate': 0.2,
+ 'http_response_time_p90': 0.3,
'failed_auths': {
'percentage': 50,
'all_auths_rate': 0.1,
diff --git a/keystone/meta/grafana.yml b/keystone/meta/grafana.yml
index 75c3ee7..cf147a0 100644
--- a/keystone/meta/grafana.yml
+++ b/keystone/meta/grafana.yml
@@ -7,7 +7,7 @@
datasource: influxdb
format: json
template: keystone/files/grafana_dashboards/keystone_influxdb.json
- main:
+ main_influxdb:
datasource: influxdb
row:
ost-control-plane:
@@ -23,6 +23,21 @@
cluster_status:
rawQuery: true
query: SELECT last(value) FROM cluster_status WHERE cluster_name = 'keystone' AND environment_label = '$environment' AND $timeFilter GROUP BY time($interval) fill(null)
+ main_prometheus:
+ datasource: prometheus
+ row:
+ ost-control-plane:
+ title: OpenStack Control Plane
+ panel:
+ keystone:
+ title: Keystone
+ links:
+ - dashboard: Keystone
+ title: Keystone
+ type: dashboard
+ target:
+ cluster_status:
+ expr: avg(openstack_api_check_status{service=~\"keystone.*public.*\"})
service_level:
datasource: influxdb
row:
diff --git a/keystone/meta/prometheus.yml b/keystone/meta/prometheus.yml
index 572908f..fc3568f 100644
--- a/keystone/meta/prometheus.yml
+++ b/keystone/meta/prometheus.yml
@@ -5,15 +5,26 @@
alert:
KeystoneAPIDown:
if: >-
- max(openstack_api_check_status{service=~"keystone.+"}) by (service) == 0
+ openstack_api_check_status{service=~"keystone.*"} == 0
for: 2m
labels:
severity: down
service: "{{ $labels.service }}"
annotations:
- summary: "Endpoint check for '{{ $labels.service}}' is down"
+ summary: "Endpoint check for '{{ $labels.service }}' is down"
description: >-
- Endpoint check for '{{ $labels.service}}' is down for 2 minutes
+ Endpoint check for '{{ $labels.service }}' is down for 2 minutes
+ KeystoneAPIServiceDown:
+ if: >-
+ http_response_status{service=~"keystone.*"} == 0
+ for: 2m
+ labels:
+ severity: down
+ service: "{{ $labels.service }}"
+ annotations:
+ summary: "HTTP check for '{{ $labels.service }}' down"
+ description: >-
+ The HTTP check for '{{ $labels.service }}' is down on {{ $labels.host }} for 2 minutes.
KeystoneErrorLogsTooHigh:
{%- endraw %}
{%- set log_threshold = monitoring.error_log_rate|float %}
@@ -38,5 +49,17 @@
annotations:
summary: 'Too many failed authentications in Keystone'
description: 'The rate of failed authentications in Keystone over the last 5 minutes is too high (current value={{ $value }}, threshold={%- endraw %}{{ auth_threshold }}).'
+ KeystoneAPITooSlow:
+ {%- set response_time_threshold = monitoring.http_response_time_p90|float %}
+ if: >-
+ max by(host) (openstack_keystone_http_response_times_upper_90{http_method=~"^(GET|POST)$",http_status="2xx"}) >= {{ response_time_threshold }}
+{%- raw %}
+ for: 2m
+ labels:
+ severity: warning
+ service: keystone
+ annotations:
+ summary: 'Keystone API too slow'
+ description: 'The 90th percentile of the Keystone API response times for GET and POST requests is too high on node {{ $labels.host }} (current value={{ $value }}s, threshold={%- endraw %}{{ response_time_threshold }}s).'
{%- endif %}
diff --git a/keystone/server.sls b/keystone/server.sls
index 1548796..60f162d 100644
--- a/keystone/server.sls
+++ b/keystone/server.sls
@@ -1,4 +1,4 @@
-{%- from "keystone/map.jinja" import server with context %}
+{%- from "keystone/map.jinja" import server, system_cacerts_file with context %}
{%- if server.enabled %}
keystone_packages:
@@ -227,6 +227,9 @@
- onlyif: /bin/false
{%- endif %}
- watch:
+ {%- if server.notification and server.message_queue.get('ssl',{}).get('enabled', False) %}
+ - file: rabbitmq_ca
+ {%- endif %}
- file: /etc/keystone/keystone.conf
{%- endif %}
@@ -256,7 +259,7 @@
{%- if not grains.get('noservices', False) %}
keystone_syncdb:
cmd.run:
- - name: keystone-manage db_sync; sleep 1
+ - name: keystone-manage db_sync && sleep 1
- timeout: 120
- require:
- service: {{ keystone_service }}
@@ -434,4 +437,37 @@
{%- endfor %}
{%- endif %} {# end noservices #}
+{%- if server.database.get('ssl',{}).get('enabled',False) %}
+mysql_ca:
+{%- if server.database.ssl.cacert is defined %}
+ file.managed:
+ - name: {{ server.database.ssl.cacert_file }}
+ - contents_pillar: keystone:server:database:ssl:cacert
+ - mode: 0444
+ - makedirs: true
+ - require_in:
+ - file: /etc/keystone/keystone.conf
+{%- else %}
+ file.exists:
+ - name: {{ server.database.ssl.get('cacert_file', system_cacerts_file) }}
+ - require_in:
+ - file: /etc/keystone/keystone.conf
+{% endif %}
+{% endif %}
+
+
+{%- if server.notification and server.message_queue.get('ssl',{}).get('enabled', False) %}
+rabbitmq_ca:
+{%- if server.message_queue.ssl.cacert is defined %}
+ file.managed:
+ - name: {{ server.message_queue.ssl.cacert_file }}
+ - contents_pillar: keystone:server:message_queue:ssl:cacert
+ - mode: 0444
+ - makedirs: true
+{%- else %}
+ file.exists:
+ - name: {{ server.message_queue.ssl.get('cacert_file', system_cacerts_file) }}
+{%- endif %}
+{%- endif %}
+
{%- endif %}
diff --git a/tests/pillar/ssl.sls b/tests/pillar/ssl.sls
new file mode 100644
index 0000000..f60e5ed
--- /dev/null
+++ b/tests/pillar/ssl.sls
@@ -0,0 +1,53 @@
+# Test case with enabled SSL of the following communication paths:
+# - messaging (rabbitmq)
+
+keystone:
+ server:
+ enabled: true
+ version: liberty
+ service_token: token
+ service_tenant: service
+ admin_tenant: admin
+ admin_name: admin
+ admin_password: passw0rd
+ admin_email: root@localhost
+ bind:
+ address: 0.0.0.0
+ private_address: 127.0.0.1
+ private_port: 35357
+ public_address: 127.0.0.1
+ public_port: 5000
+ region: RegionOne
+ database:
+ engine: mysql
+ host: 127.0.0.1
+ name: keystone
+ password: passw0rd
+ user: keystone
+ ssl:
+ enabled: True
+ tokens:
+ engine: cache
+ expiration: 86400
+ location: /etc/keystone/fernet-keys/
+ notification: true
+ notification_format: cadf
+ message_queue:
+ engine: rabbitmq
+ host: 127.0.0.1
+ port: 5671
+ user: openstack
+ password: passw0rd
+ virtual_host: '/openstack'
+ ha_queues: true
+ ssl:
+ enabled: True
+ cache:
+ engine: memcached
+ members:
+ - host: 127.0.0.1
+ port: 11211
+ - host: 127.0.0.1
+ port: 11211
+ - host: 127.0.0.1
+ port: 11211