diff options
-rw-r--r-- | doc/source/apache-httpd.rst | 12 | ||||
-rw-r--r-- | keystone/catalog/backends/sql.py | 6 | ||||
-rw-r--r-- | keystone/common/openssl.py | 36 | ||||
-rw-r--r-- | keystone/common/sql/core.py | 1 | ||||
-rw-r--r-- | keystone/common/sql/migrate_repo/versions/031_drop_credential_indexes.py | 40 | ||||
-rw-r--r-- | keystone/token/backends/sql.py | 9 | ||||
-rw-r--r-- | keystone/trust/backends/sql.py | 8 | ||||
-rw-r--r-- | tests/test_sql_upgrade.py | 18 |
8 files changed, 107 insertions, 23 deletions
diff --git a/doc/source/apache-httpd.rst b/doc/source/apache-httpd.rst index 41437780..5bc0dbe8 100644 --- a/doc/source/apache-httpd.rst +++ b/doc/source/apache-httpd.rst @@ -87,7 +87,17 @@ Putting it somewhere else requires you set up your SELinux policy accordingly. Keystone Configuration ---------------------- -Make sure you use the ``SQL`` driver for ``tokens``, otherwise the tokens will not be shared between the processes of the Apache HTTPD server. To do that, in ``/etc/keystone/keystone.conf`` make sure you have set:: +Make sure you use either the ``SQL`` or the ``memcached`` driver for ``tokens``, otherwise the tokens will not be shared between the processes of the Apache HTTPD server. + +For ``SQL,`` in ``/etc/keystone/keystone.conf`` make sure you have set:: [token] driver = keystone.token.backends.sql.Token + +For ``memcache,`` in ``/etc/keystone/keystone.conf`` make sure you have set:: + + [token] + driver = keystone.token.backends.memcache.Token + +In both cases, all servers that are storing tokens need a shared backend. This means either that both point +to the same database server, or both point to a common memcached instance. diff --git a/keystone/catalog/backends/sql.py b/keystone/catalog/backends/sql.py index 718d7c53..d7b2123a 100644 --- a/keystone/catalog/backends/sql.py +++ b/keystone/catalog/backends/sql.py @@ -41,12 +41,12 @@ class Endpoint(sql.ModelBase, sql.DictBase): 'legacy_endpoint_id'] id = sql.Column(sql.String(64), primary_key=True) legacy_endpoint_id = sql.Column(sql.String(64)) - interface = sql.Column(sql.String(8), primary_key=True) - region = sql.Column('region', sql.String(255)) + interface = sql.Column(sql.String(8), nullable=False) + region = sql.Column(sql.String(255)) service_id = sql.Column(sql.String(64), sql.ForeignKey('service.id'), nullable=False) - url = sql.Column(sql.Text()) + url = sql.Column(sql.Text(), nullable=False) extra = sql.Column(sql.JsonBlob()) diff --git a/keystone/common/openssl.py b/keystone/common/openssl.py index fa09e37c..90484505 100644 --- a/keystone/common/openssl.py +++ b/keystone/common/openssl.py @@ -51,6 +51,7 @@ class BaseCertificateConfigure(object): self.request_file_name = os.path.join(self.conf_dir, "req.pem") self.ssl_dictionary = {'conf_dir': self.conf_dir, 'ca_cert': conf_obj.ca_certs, + 'default_md': 'default', 'ssl_config': self.ssl_config_file_name, 'ca_private_key': conf_obj.ca_key, 'request_file': self.request_file_name, @@ -60,6 +61,17 @@ class BaseCertificateConfigure(object): 'valid_days': int(conf_obj.valid_days), 'cert_subject': conf_obj.cert_subject, 'ca_password': conf_obj.ca_password} + + try: + # OpenSSL 1.0 and newer support default_md = default, olders do not + openssl_ver = environment.subprocess.Popen( + ['openssl', 'version'], + stdout=environment.subprocess.PIPE).stdout.read() + if "OpenSSL 0." in openssl_ver: + self.ssl_dictionary['default_md'] = 'sha1' + except OSError: + LOG.warn('Failed to invoke ``openssl version``, ' + 'assuming is v1.0 or newer') self.ssl_dictionary.update(kwargs) def _make_dirs(self, file_name): @@ -198,7 +210,7 @@ new_certs_dir = $dir serial = $dir/serial database = $dir/index.txt default_days = 365 -default_md = default # use public key default MD +default_md = %(default_md)s preserve = no email_in_dn = no nameopt = default_ca @@ -218,35 +230,35 @@ emailAddress = optional [ req ] default_bits = 2048 # Size of keys default_keyfile = key.pem # name of generated keys -default_md = default # message digest algorithm -string_mask = nombstr # permitted characters +string_mask = utf8only # permitted characters distinguished_name = req_distinguished_name req_extensions = v3_req +x509_extensions = v3_ca [ req_distinguished_name ] -0.organizationName = Organization Name (company) -organizationalUnitName = Organizational Unit Name (department, division) -emailAddress = Email Address -emailAddress_max = 40 -localityName = Locality Name (city, district) -stateOrProvinceName = State or Province Name (full name) countryName = Country Name (2 letter code) countryName_min = 2 countryName_max = 2 +stateOrProvinceName = State or Province Name (full name) +localityName = Locality Name (city, district) +0.organizationName = Organization Name (company) +organizationalUnitName = Organizational Unit Name (department, division) commonName = Common Name (hostname, IP, or your name) commonName_max = 64 +emailAddress = Email Address +emailAddress_max = 64 [ v3_ca ] basicConstraints = CA:TRUE subjectKeyIdentifier = hash -authorityKeyIdentifier = keyid:always,issuer:always +authorityKeyIdentifier = keyid:always,issuer [ v3_req ] basicConstraints = CA:FALSE -subjectKeyIdentifier = hash +keyUsage = nonRepudiation, digitalSignature, keyEncipherment [ usr_cert ] basicConstraints = CA:FALSE subjectKeyIdentifier = hash -authorityKeyIdentifier = keyid:always,issuer:always +authorityKeyIdentifier = keyid:always """ diff --git a/keystone/common/sql/core.py b/keystone/common/sql/core.py index a2deb58b..67863588 100644 --- a/keystone/common/sql/core.py +++ b/keystone/common/sql/core.py @@ -45,6 +45,7 @@ ModelBase = declarative.declarative_base() # For exporting to other modules Column = sql.Column +Index = sql.Index String = sql.String ForeignKey = sql.ForeignKey DateTime = sql.DateTime diff --git a/keystone/common/sql/migrate_repo/versions/031_drop_credential_indexes.py b/keystone/common/sql/migrate_repo/versions/031_drop_credential_indexes.py new file mode 100644 index 00000000..89ca04f0 --- /dev/null +++ b/keystone/common/sql/migrate_repo/versions/031_drop_credential_indexes.py @@ -0,0 +1,40 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2013 OpenStack Foundation +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import sqlalchemy + + +def upgrade(migrate_engine): + #This migration is relevant only for mysql because for all other + #migrate engines these indexes were successfully dropped. + if migrate_engine.name != 'mysql': + return + meta = sqlalchemy.MetaData(bind=migrate_engine) + table = sqlalchemy.Table('credential', meta, autoload=True) + for index in table.indexes: + index.drop() + + +def downgrade(migrate_engine): + if migrate_engine.name != 'mysql': + return + meta = sqlalchemy.MetaData(bind=migrate_engine) + table = sqlalchemy.Table('credential', meta, autoload=True) + index = sqlalchemy.Index('user_id', table.c['user_id']) + index.create() + index = sqlalchemy.Index('credential_project_id_fkey', + table.c['project_id']) + index.create() diff --git a/keystone/token/backends/sql.py b/keystone/token/backends/sql.py index 0e8a916d..82eab651 100644 --- a/keystone/token/backends/sql.py +++ b/keystone/token/backends/sql.py @@ -17,7 +17,6 @@ import copy import datetime - from keystone.common import sql from keystone import exception from keystone.openstack.common import timeutils @@ -30,9 +29,13 @@ class TokenModel(sql.ModelBase, sql.DictBase): id = sql.Column(sql.String(64), primary_key=True) expires = sql.Column(sql.DateTime(), default=None) extra = sql.Column(sql.JsonBlob()) - valid = sql.Column(sql.Boolean(), default=True) + valid = sql.Column(sql.Boolean(), default=True, nullable=False) user_id = sql.Column(sql.String(64)) - trust_id = sql.Column(sql.String(64), nullable=True) + trust_id = sql.Column(sql.String(64)) + __table_args__ = ( + sql.Index('ix_token_expires', 'expires'), + sql.Index('ix_token_valid', 'valid') + ) class Token(sql.Base, token.Driver): diff --git a/keystone/trust/backends/sql.py b/keystone/trust/backends/sql.py index daa8e3f7..9e92ad71 100644 --- a/keystone/trust/backends/sql.py +++ b/keystone/trust/backends/sql.py @@ -26,11 +26,11 @@ class TrustModel(sql.ModelBase, sql.DictBase): 'project_id', 'impersonation', 'expires_at'] id = sql.Column(sql.String(64), primary_key=True) #user id Of owner - trustor_user_id = sql.Column(sql.String(64), unique=False, nullable=False,) + trustor_user_id = sql.Column(sql.String(64), nullable=False,) #user_id of user allowed to consume this preauth - trustee_user_id = sql.Column(sql.String(64), unique=False, nullable=False) - project_id = sql.Column(sql.String(64), unique=False, nullable=True) - impersonation = sql.Column(sql.Boolean) + trustee_user_id = sql.Column(sql.String(64), nullable=False) + project_id = sql.Column(sql.String(64)) + impersonation = sql.Column(sql.Boolean, nullable=False) deleted_at = sql.Column(sql.DateTime) expires_at = sql.Column(sql.DateTime) extra = sql.Column(sql.JsonBlob()) diff --git a/tests/test_sql_upgrade.py b/tests/test_sql_upgrade.py index 5975fb9d..9540c4cd 100644 --- a/tests/test_sql_upgrade.py +++ b/tests/test_sql_upgrade.py @@ -1238,6 +1238,24 @@ class SqlUpgradeTests(SqlMigrateBase): self.assertEqual(cred.user_id, ec2_credential['user_id']) + def test_drop_credential_indexes(self): + self.upgrade(31) + table = sqlalchemy.Table('credential', self.metadata, autoload=True) + self.assertEqual(len(table.indexes), 0) + + def test_downgrade_30(self): + self.upgrade(31) + self.downgrade(30) + table = sqlalchemy.Table('credential', self.metadata, autoload=True) + index_data = [(idx.name, idx.columns.keys()) + for idx in table.indexes] + if self.engine.name == 'mysql': + self.assertIn(('user_id', ['user_id']), index_data) + self.assertIn(('credential_project_id_fkey', ['project_id']), + index_data) + else: + self.assertEqual(len(index_data), 0) + def populate_user_table(self, with_pass_enab=False, with_pass_enab_domain=False): # Populate the appropriate fields in the user |