Switch from python-memcache to pymemcache

To support TLS and MTLS this commit replaces python-memcache with
pymemcache.

Change-Id: I8a361af1658722eb2eac5592504925347a57020c
This commit is contained in:
Luca Miccini 2025-02-19 15:51:02 +01:00
parent 557d173eee
commit 4e7ec75b2f
6 changed files with 68 additions and 7 deletions

View File

@ -219,6 +219,7 @@ object is stored.
import copy
import re
import ssl
from keystoneauth1 import access
from keystoneauth1 import adapter
@ -877,6 +878,23 @@ class AuthProtocol(BaseAuthProtocol):
password=self._conf.get('memcache_password'),
)
if self._conf.get('memcache_tls_enabled'):
tls_cafile = self._conf.get('memcache_tls_cafile')
tls_certfile = self._conf.get('memcache_tls_certfile')
tls_keyfile = self._conf.get('memcache_tls_keyfile')
tls_allowed_ciphers = self._conf.get(
'memcache_tls_allowed_ciphers')
tls_context = ssl.create_default_context(cafile=tls_cafile)
if tls_certfile:
tls_context.load_cert_chain(tls_certfile, tls_keyfile)
if tls_allowed_ciphers:
tls_context.set_ciphers(tls_allowed_ciphers)
cache_kwargs['tls_context'] = tls_context
if security_strategy.lower() != 'none':
secret_key = self._conf.get('memcache_secret_key')
return _cache.SecureTokenCache(self.log,

View File

@ -52,11 +52,12 @@ class _EnvCachePool(object):
class _CachePool(list):
"""A lazy pool of cache references."""
def __init__(self, memcached_servers, log, arguments):
def __init__(self, memcached_servers, log, arguments, tls_context=None):
self._memcached_servers = memcached_servers
self._sasl_enabled = arguments.get("sasl_enabled", False)
self._username = arguments.get("username", None)
self._password = arguments.get("password", None)
self._tls_context = tls_context
if not self._memcached_servers:
log.warning(
"Using the in-process token cache is deprecated as of the "
@ -81,8 +82,9 @@ class _CachePool(list):
c = bmemcached.Client(self._memcached_servers,
self._username, self._password)
else:
import memcache
c = memcache.Client(self._memcached_servers, debug=0)
import pymemcache
c = pymemcache.HashClient(self._memcached_servers,
tls_context=self._tls_context)
else:
c = _FakeClient()
@ -140,13 +142,14 @@ class TokenCache(object):
_CACHE_KEY_TEMPLATE = 'tokens/%s'
def __init__(self, log, cache_time=None,
env_cache_name=None, memcached_servers=None,
env_cache_name=None, memcached_servers=None, tls_context=None,
use_advanced_pool=True, dead_retry=None, socket_timeout=None,
**kwargs):
self._LOG = log
self._cache_time = cache_time
self._env_cache_name = env_cache_name
self._memcached_servers = memcached_servers
self._tls_context = tls_context
self._use_advanced_pool = use_advanced_pool
self._arguments = {
'dead_retry': dead_retry,
@ -178,7 +181,7 @@ class TokenCache(object):
"through config option memcache_use_advanced_pool = True")
return _CachePool(self._memcached_servers, self._LOG,
self._arguments)
self._arguments, tls_context=self._tls_context)
def initialize(self, env):
if self._initialized:

View File

@ -124,6 +124,32 @@ _OPTS = [
secret=True,
help='(Optional, mandatory if memcache_security_strategy is'
' defined) This string is used for key derivation.'),
cfg.BoolOpt('memcache_tls_enabled',
default=False,
help='(Optional) Global toggle for TLS usage when comunicating'
' with the caching servers.'),
cfg.StrOpt('memcache_tls_cafile',
help='(Optional) Path to a file of concatenated CA certificates'
' in PEM format necessary to establish the caching server\'s'
' authenticity. If tls_enabled is False, this option is'
' ignored.'),
cfg.StrOpt('memcache_tls_certfile',
help='(Optional) Path to a single file in PEM format containing'
' the client\'s certificate as well as any number of CA'
' certificates needed to establish the certificate\'s'
' authenticity. This file is only required when client side'
' authentication is necessary. If tls_enabled is False, this'
' option is ignored.'),
cfg.StrOpt('memcache_tls_keyfile',
help='(Optional) Path to a single file containing the client\'s'
' private key in. Otherwhise the private key will be taken from'
' the file specified in tls_certfile. If tls_enabled is False,'
' this option is ignored.'),
cfg.StrOpt('memcache_tls_allowed_ciphers',
help='(Optional) Set the available ciphers for sockets created'
' with the TLS context. It should be a string in the OpenSSL'
' cipher list format. If not specified, all OpenSSL enabled'
' ciphers will be available.'),
cfg.IntOpt('memcache_pool_dead_retry',
default=5 * 60,
help='(Optional) Number of seconds memcached server is'

View File

@ -97,8 +97,8 @@ class TestLiveMemcache(base.BaseAuthTokenTestCase):
if MEMCACHED_AVAILABLE is None:
try:
import memcache
c = memcache.Client(MEMCACHED_SERVERS)
import pymemcache
c = pymemcache.HashClient(MEMCACHED_SERVERS)
c.set('ping', 'pong', time=1)
MEMCACHED_AVAILABLE = c.get('ping') == 'pong'
except ImportError:

View File

@ -58,6 +58,11 @@ class OptsTestCase(utils.TestCase):
'memcache_security_strategy',
'memcache_secret_key',
'memcache_use_advanced_pool',
'memcache_tls_enabled',
'memcache_tls_cafile',
'memcache_tls_certfile',
'memcache_tls_keyfile',
'memcache_tls_allowed_ciphers',
'memcache_pool_dead_retry',
'memcache_pool_maxsize',
'memcache_pool_unused_timeout',
@ -106,6 +111,11 @@ class OptsTestCase(utils.TestCase):
'memcache_security_strategy',
'memcache_secret_key',
'memcache_use_advanced_pool',
'memcache_tls_enabled',
'memcache_tls_cafile',
'memcache_tls_certfile',
'memcache_tls_keyfile',
'memcache_tls_allowed_ciphers',
'memcache_pool_dead_retry',
'memcache_pool_maxsize',
'memcache_pool_unused_timeout',

View File

@ -0,0 +1,4 @@
---
other:
- |
python-memcached has been replaced by pymemcache to support TLS and MTLS.