Skip to content

Commit

Permalink
NoLogPasswordsRule: catch password_lock false positives and migrate t…
Browse files Browse the repository at this point in the history
…ests (#1562)

* catch password_lock false positives and migrate tests

Signed-off-by: Thomas Sjögren <konstruktoid@users.noreply.github.com>

* fix codespell issues

Signed-off-by: Thomas Sjögren <konstruktoid@users.noreply.github.com>
  • Loading branch information
konstruktoid committed May 20, 2021
1 parent 8bef056 commit 379f7eb
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 62 deletions.
19 changes: 0 additions & 19 deletions examples/playbooks/no-log-passwords-failure.yml

This file was deleted.

14 changes: 0 additions & 14 deletions examples/playbooks/no-log-passwords-success.yml

This file was deleted.

173 changes: 168 additions & 5 deletions src/ansiblelint/rules/NoLogPasswordsRule.py
Expand Up @@ -12,6 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.

"""NoLogPasswordsRule used with ansible-lint."""
import sys
from typing import TYPE_CHECKING, Any, Dict, Union

from ansiblelint.rules import AnsibleLintRule
Expand All @@ -24,6 +26,8 @@


class NoLogPasswordsRule(AnsibleLintRule):
"""Describe and test the NoLogPasswordsRule."""

id = "no-log-password"
shortdesc = "password should not be logged."
description = (
Expand All @@ -38,14 +42,173 @@ def matchtask(
self, task: Dict[str, Any], file: 'Optional[Lintable]' = None
) -> Union[bool, str]:

for param in task["action"].keys():
if 'password' in param:
has_password = True
break
else:
if task["action"]["__ansible_module__"] == 'user' and (
(
task['action'].get('password_lock')
or task['action'].get('password_lock') is False
)
and not task['action'].get('password')

This comment has been minimized.

Copy link
@noonedeadpunk

noonedeadpunk May 20, 2021

Contributor

this has different effect from what was intended. This will catch only password while originaly it was catching *password* which is relevant for bunch of modules and collections, for example https://docs.ansible.com/ansible/latest/collections/community/mysql/mysql_user_module.html has login_password which might be used without password itself

):
has_password = False
else:
for param in task["action"].keys():
if 'password' in param:
has_password = True
break
else:
has_password = False

# No no_log and no_log: False behave the same way
# and should return a failure (return True), so we
# need to invert the boolean
return bool(has_password and not convert_to_boolean(task.get('no_log', False)))


if "pytest" in sys.modules:
import pytest

NO_LOG_UNUSED = '''
- hosts: all
tasks:
- name: Fail when no_log is not used
user:
name: bidule
password: "wow"
state: absent
'''

NO_LOG_FALSE = '''
- hosts: all
tasks:
- name: Fail when no_log is set to False
user:
name: bidule
user_password: "wow"
state: absent
no_log: False
'''

NO_LOG_NO = '''
- hosts: all
tasks:
- name: Fail when no_log is set to no
user:
name: bidule
password: "wow"
state: absent
no_log: no
'''

PASSWORD_WITH_LOCK = '''
- hosts: all
tasks:
- name: Fail when password is set and password_lock is true
user:
name: lint
password: "wow"
password_lock: true
'''

NO_LOG_YES = '''
- hosts: all
tasks:
- name: Succeed when no_log is set to yes
user:
name: bidule
password: "wow"
state: absent
no_log: yes
'''

NO_LOG_TRUE = '''
- hosts: all
tasks:
- name: Succeed when no_log is set to True
user:
name: bidule
user_password: "wow"
state: absent
no_log: True
'''

PASSWORD_LOCK_YES = '''
- hosts: all
tasks:
- name: Succeed when only password locking account
user:
name: lint
password_lock: yes
'''

PASSWORD_LOCK_FALSE = '''
- hosts: all
tasks:
- name: Succeed when password_lock is false and password is not used
user:
name: lint
password_lock: False
'''

@pytest.mark.parametrize(
'rule_runner', (NoLogPasswordsRule,), indirect=['rule_runner']
)
def test_no_log_unused(rule_runner: Any) -> None:
"""The task does not use no_log."""
results = rule_runner.run_playbook(NO_LOG_UNUSED)
assert len(results) == 1

@pytest.mark.parametrize(
'rule_runner', (NoLogPasswordsRule,), indirect=['rule_runner']
)
def test_no_log_false(rule_runner: Any) -> None:
"""The task sets no_log to false."""
results = rule_runner.run_playbook(NO_LOG_FALSE)
assert len(results) == 1

@pytest.mark.parametrize(
'rule_runner', (NoLogPasswordsRule,), indirect=['rule_runner']
)
def test_no_log_no(rule_runner: Any) -> None:
"""The task sets no_log to no."""
results = rule_runner.run_playbook(NO_LOG_NO)
assert len(results) == 1

@pytest.mark.parametrize(
'rule_runner', (NoLogPasswordsRule,), indirect=['rule_runner']
)
def test_password_with_lock(rule_runner: Any) -> None:
"""The task sets a password but also lock the user."""
results = rule_runner.run_playbook(PASSWORD_WITH_LOCK)
assert len(results) == 1

@pytest.mark.parametrize(
'rule_runner', (NoLogPasswordsRule,), indirect=['rule_runner']
)
def test_no_log_yes(rule_runner: Any) -> None:
"""The task sets no_log to yes."""
results = rule_runner.run_playbook(NO_LOG_YES)
assert len(results) == 0

@pytest.mark.parametrize(
'rule_runner', (NoLogPasswordsRule,), indirect=['rule_runner']
)
def test_no_log_true(rule_runner: Any) -> None:
"""The task sets no_log to true."""
results = rule_runner.run_playbook(NO_LOG_TRUE)
assert len(results) == 0

@pytest.mark.parametrize(
'rule_runner', (NoLogPasswordsRule,), indirect=['rule_runner']
)
def test_password_lock_yes(rule_runner: Any) -> None:
"""The task only locks the user."""
results = rule_runner.run_playbook(PASSWORD_LOCK_YES)
assert len(results) == 0

@pytest.mark.parametrize(
'rule_runner', (NoLogPasswordsRule,), indirect=['rule_runner']
)
def test_password_lock_false(rule_runner: Any) -> None:
"""The task does not actually lock the user."""
results = rule_runner.run_playbook(PASSWORD_LOCK_FALSE)
assert len(results) == 0
24 changes: 0 additions & 24 deletions test/TestNoLogPasswordsRule.py

This file was deleted.

0 comments on commit 379f7eb

Please sign in to comment.