Coverage for manila/share/drivers/container/security_service_helper.py: 100%

54 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2026-02-18 22:19 +0000

1# Copyright (c) 2021 NetApp, Inc. 

2# All Rights Reserved. 

3# 

4# Licensed under the Apache License, Version 2.0 (the "License"); you may 

5# not use this file except in compliance with the License. You may obtain 

6# a copy of the License at 

7# 

8# http://www.apache.org/licenses/LICENSE-2.0 

9# 

10# Unless required by applicable law or agreed to in writing, software 

11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 

12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 

13# License for the specific language governing permissions and limitations 

14# under the License. 

15 

16 

17from oslo_log import log as logging 

18 

19from manila import exception 

20from manila.i18n import _ 

21from manila.share import driver 

22from manila import utils as manila_utils 

23 

24# LDAP error codes 

25LDAP_INVALID_CREDENTIALS = 49 

26 

27LOG = logging.getLogger(__name__) 

28 

29 

30class SecurityServiceHelper(driver.ExecuteMixin): 

31 def __init__(self, *args, **kwargs): 

32 self.configuration = kwargs.pop("configuration", None) 

33 super(SecurityServiceHelper, self).__init__(*args, **kwargs) 

34 self.init_execute_mixin() 

35 

36 def setup_security_service(self, share_server_id, security_service): 

37 msg = ("Setting up the security service %(service)s for share server " 

38 "%(server_id)s") 

39 msg_args = { 

40 'service': security_service['id'], 

41 'server_id': share_server_id 

42 } 

43 LOG.debug(msg, msg_args) 

44 self.ldap_bind(share_server_id, security_service) 

45 

46 def update_security_service(self, server_id, current_security_service, 

47 new_security_service): 

48 msg = ("Updating the security service %(service)s for share server " 

49 "%(server_id)s") 

50 msg_args = { 

51 'service': new_security_service['id'], 

52 'server_id': server_id 

53 } 

54 LOG.debug(msg, msg_args) 

55 self.ldap_bind(server_id, new_security_service) 

56 

57 def ldap_bind(self, share_server_id, security_service): 

58 ss_info = self.ldap_get_info(security_service) 

59 cmd = ["docker", "exec", "%s" % share_server_id, "ldapwhoami", "-x", 

60 "-H", "ldap://localhost:389", "-D", 

61 "cn=%s,dc=example,dc=com" % ss_info["ss_user"], "-w", "%s" % 

62 ss_info["ss_password"]] 

63 self.ldap_retry_operation(cmd, run_as_root=True) 

64 

65 def ldap_get_info(self, security_service): 

66 if all(info in security_service for info in ("user", "password")): 

67 ss_user = security_service["user"] 

68 ss_password = security_service["password"] 

69 else: 

70 raise exception.ShareBackendException( 

71 _("LDAP requires user and password to be set for the bind " 

72 "operation.")) 

73 ss_info = { 

74 "ss_user": ss_user, 

75 "ss_password": ss_password, 

76 } 

77 return ss_info 

78 

79 def ldap_retry_operation(self, cmd, run_as_root=True, timeout=30): 

80 interval = 5 

81 retries = int(timeout / interval) or 1 

82 

83 @manila_utils.retry(retry_param=exception.ProcessExecutionError, 

84 interval=interval, 

85 retries=retries, backoff_rate=1) 

86 def try_ldap_operation(): 

87 try: 

88 self._execute(*cmd, run_as_root=run_as_root) 

89 except exception.ProcessExecutionError as e: 

90 if e.exit_code == LDAP_INVALID_CREDENTIALS: 

91 msg = _('LDAP credentials are invalid. ' 

92 'Aborting operation.') 

93 LOG.warning(msg) 

94 raise exception.ShareBackendException(msg=msg) 

95 else: 

96 msg = _('Command has returned execution error.' 

97 ' Will retry the operation.' 

98 ' Error details: %s') % e.stderr 

99 LOG.warning(msg) 

100 raise exception.ProcessExecutionError() 

101 

102 try: 

103 try_ldap_operation() 

104 except exception.ProcessExecutionError as e: 

105 msg = _("Unable to execute LDAP operation with success. " 

106 "Retries exhausted. Error details: %s") % e.stderr 

107 LOG.exception(msg) 

108 raise exception.ShareBackendException(msg=msg)