diff --git a/salt/auth/ldap.py b/salt/auth/ldap.py index 3be2e276cc..5b37b8c6db 100644 --- a/salt/auth/ldap.py +++ b/salt/auth/ldap.py @@ -298,12 +298,14 @@ def auth(username, password): log.error('LDAP authentication requires python-ldap module') return False + bind = None + # If bind credentials are configured, verify that we receive a valid bind if _config('binddn', mandatory=False) and _config('bindpw', mandatory=False): - bind = _bind_for_search(anonymous=_config('anonymous', mandatory=False)) + search_bind = _bind_for_search(anonymous=_config('anonymous', mandatory=False)) # If username & password are not None, attempt to verify they are valid - if bind and username and password: + if search_bind and username and password: bind = _bind(username, password, anonymous=_config('auth_by_group_membership_only', mandatory=False) and _config('anonymous', mandatory=False)) diff --git a/salt/pillar/git_pillar.py b/salt/pillar/git_pillar.py index b89801d4a6..aecd8cb668 100644 --- a/salt/pillar/git_pillar.py +++ b/salt/pillar/git_pillar.py @@ -327,6 +327,8 @@ mountpoint to ``web/`` (and restart the ``salt-master`` daemon). :conf_master:`git_pillar_includes` is not disabled. - Content from mounted git_pillar repos can only be referenced by a top file in the same pillar environment. + - Salt versions prior to 2018.3.4 ignore the ``root`` parameter when + ``mountpoint`` is set. ''' from __future__ import absolute_import, print_function, unicode_literals diff --git a/salt/utils/gitfs.py b/salt/utils/gitfs.py index 2bd2cf8d01..7de529014c 100644 --- a/salt/utils/gitfs.py +++ b/salt/utils/gitfs.py @@ -2988,6 +2988,7 @@ class GitPillar(GitBase): points at the correct path ''' lcachelink = salt.utils.path.join(repo.linkdir, repo._mountpoint) + lcachedest = salt.utils.path.join(repo.cachedir, repo.root()).rstrip(os.sep) wipe_linkdir = False create_link = False try: @@ -3021,11 +3022,11 @@ class GitPillar(GitBase): ) wipe_linkdir = True else: - if ldest != repo.cachedir: + if ldest != lcachedest: log.debug( 'Destination of %s (%s) does not match ' 'the expected value (%s)', - lcachelink, ldest, repo.cachedir + lcachelink, ldest, lcachedest ) # Since we know that the parent dirs of the # link are set up properly, all we need to do @@ -3070,16 +3071,16 @@ class GitPillar(GitBase): if create_link: try: - os.symlink(repo.cachedir, lcachelink) + os.symlink(lcachedest, lcachelink) log.debug( 'Successfully linked %s to cachedir %s', - lcachelink, repo.cachedir + lcachelink, lcachedest ) return True except OSError as exc: log.error( 'Failed to create symlink to %s at path %s: %s', - repo.cachedir, lcachelink, exc.__str__() + lcachedest, lcachelink, exc.__str__() ) return False except GitLockError: diff --git a/tests/integration/pillar/test_git_pillar.py b/tests/integration/pillar/test_git_pillar.py index 98c0950ead..dc58f75c12 100644 --- a/tests/integration/pillar/test_git_pillar.py +++ b/tests/integration/pillar/test_git_pillar.py @@ -436,6 +436,30 @@ class GitPythonMixin(object): ''') self.assertEqual(ret, expected) + def test_root_and_mountpoint_parameters(self): + ''' + Test root and mountpoint parameters + ''' + expected = { + 'from_subdir': True + } + + ret = self.get_pillar('''\ + file_ignore_regex: [] + file_ignore_glob: [] + git_pillar_provider: gitpython + cachedir: {cachedir} + extension_modules: {extmods} + ext_pillar: + - git: + - master {url}: + - mountpoint: mounted + - root: subdir + - top_mounted {url}: + - env: base + ''') + self.assertEqual(ret, expected) + @destructiveTest @skipIf(NO_MOCK, NO_MOCK_REASON) @@ -1493,6 +1517,102 @@ class TestPygit2SSH(GitPillarSSHTestBase): ''') self.assertEqual(ret, expected) + @requires_system_grains + def test_root_and_mountpoint_parameters(self, grains): + ''' + Test root and mountpoint parameters + ''' + expected = { + 'from_subdir': True + } + + # Test with passphraseless key and global credential options + ret = self.get_pillar('''\ + file_ignore_regex: [] + file_ignore_glob: [] + git_pillar_provider: pygit2 + git_pillar_pubkey: {pubkey_nopass} + git_pillar_privkey: {privkey_nopass} + cachedir: {cachedir} + extension_modules: {extmods} + ext_pillar: + - git: + - master {url}: + - mountpoint: mounted + - root: subdir + - top_mounted {url}: + - env: base + ''') + self.assertEqual(ret, expected) + + # Test with passphraseless key and per-repo credential options + ret = self.get_pillar('''\ + file_ignore_regex: [] + file_ignore_glob: [] + git_pillar_provider: pygit2 + cachedir: {cachedir} + extension_modules: {extmods} + ext_pillar: + - git: + - master {url}: + - mountpoint: mounted + - root: subdir + - pubkey: {pubkey_nopass} + - privkey: {privkey_nopass} + - top_mounted {url}: + - pubkey: {pubkey_nopass} + - privkey: {privkey_nopass} + - env: base + ''') + self.assertEqual(ret, expected) + + if grains['os_family'] == 'Debian': + # passphrase-protected currently does not work here + return + + # Test with passphrase-protected key and global credential options + ret = self.get_pillar('''\ + file_ignore_regex: [] + file_ignore_glob: [] + git_pillar_provider: pygit2 + git_pillar_pubkey: {pubkey_withpass} + git_pillar_privkey: {privkey_withpass} + git_pillar_passphrase: {passphrase} + cachedir: {cachedir} + extension_modules: {extmods} + ext_pillar: + - git: + - master {url}: + - mountpoint: mounted + - root: subdir + - top_mounted {url}: + - env: base + ''') + self.assertEqual(ret, expected) + + # Test with passphrase-protected key and per-repo credential options + ret = self.get_pillar('''\ + file_ignore_regex: [] + file_ignore_glob: [] + git_pillar_provider: pygit2 + cachedir: {cachedir} + extension_modules: {extmods} + ext_pillar: + - git: + - master {url}: + - mountpoint: mounted + - root: subdir + - pubkey: {pubkey_withpass} + - privkey: {privkey_withpass} + - passphrase: {passphrase} + - top_mounted {url}: + - pubkey: {pubkey_withpass} + - privkey: {privkey_withpass} + - passphrase: {passphrase} + - env: base + ''') + self.assertEqual(ret, expected) + @skipIf(NO_MOCK, NO_MOCK_REASON) @skipIf(_windows_or_mac(), 'minion is windows or mac') @@ -1818,6 +1938,30 @@ class TestPygit2HTTP(GitPillarHTTPTestBase): ''') self.assertEqual(ret, expected) + def test_root_and_mountpoint_parameters(self): + ''' + Test root and mountpoint parameters + ''' + expected = { + 'from_subdir': True + } + + ret = self.get_pillar('''\ + file_ignore_regex: [] + file_ignore_glob: [] + git_pillar_provider: pygit2 + cachedir: {cachedir} + extension_modules: {extmods} + ext_pillar: + - git: + - master {url}: + - mountpoint: mounted + - root: subdir + - top_mounted {url}: + - env: base + ''') + self.assertEqual(ret, expected) + @skipIf(NO_MOCK, NO_MOCK_REASON) @skipIf(_windows_or_mac(), 'minion is windows or mac') @@ -2360,3 +2504,30 @@ class TestPygit2AuthenticatedHTTP(GitPillarHTTPTestBase): 'nested_list': ['master'], 'nested_dict': {'master': True}}} ) + + def test_root_and_mountpoint_parameters(self): + ''' + Test root and mountpoint parameters + ''' + expected = { + 'from_subdir': True + } + + ret = self.get_pillar('''\ + file_ignore_regex: [] + file_ignore_glob: [] + git_pillar_provider: pygit2 + git_pillar_user: {user} + git_pillar_password: {password} + git_pillar_insecure_auth: True + cachedir: {cachedir} + extension_modules: {extmods} + ext_pillar: + - git: + - master {url}: + - mountpoint: mounted + - root: subdir + - top_mounted {url}: + - env: base + ''') + self.assertEqual(ret, expected) diff --git a/tests/unit/auth/test_ldap.py b/tests/unit/auth/test_ldap.py index bd398961c6..279896b814 100644 --- a/tests/unit/auth/test_ldap.py +++ b/tests/unit/auth/test_ldap.py @@ -86,3 +86,24 @@ class LDAPAuthTestCase(TestCase): with patch.dict(salt.auth.ldap.__opts__, self.opts): with patch('salt.auth.ldap.auth', return_value=Bind): self.assertIn('saltusers', salt.auth.ldap.groups('saltuser', password='password')) + + def test_auth_nopass(self): + opts = self.opts.copy() + opts['auth.ldap.bindpw'] = 'p@ssw0rd!' + with patch.dict(salt.auth.ldap.__opts__, opts): + with patch('salt.auth.ldap._bind_for_search', return_value=Bind): + self.assertFalse(salt.auth.ldap.auth('foo', None)) + + def test_auth_nouser(self): + opts = self.opts.copy() + opts['auth.ldap.bindpw'] = 'p@ssw0rd!' + with patch.dict(salt.auth.ldap.__opts__, opts): + with patch('salt.auth.ldap._bind_for_search', return_value=Bind): + self.assertFalse(salt.auth.ldap.auth(None, 'foo')) + + def test_auth_nouserandpass(self): + opts = self.opts.copy() + opts['auth.ldap.bindpw'] = 'p@ssw0rd!' + with patch.dict(salt.auth.ldap.__opts__, opts): + with patch('salt.auth.ldap._bind_for_search', return_value=Bind): + self.assertFalse(salt.auth.ldap.auth(None, None))