mirror of
https://github.com/ansible-collections/community.mysql.git
synced 2025-07-22 12:50:24 -07:00
Deprecate REQUIRESSL privilege (#132)
* Deprecate REQUIRESSL privilege * Add missing whitespace * Fix according to PR review * Fix conditional check * Fix privilege string parsing * Add unit tests for the new function * Add integration tests * Fix parentheses indentation * Cover alternative error message * Fix privileges * Limit verification of access denied to pymysql connector * Fix REQUIRE SSL verification tests
This commit is contained in:
parent
6342fb6f23
commit
dc522cc5d3
5 changed files with 220 additions and 13 deletions
115
tests/integration/targets/test_mysql_user/tasks/issue-121.yml
Normal file
115
tests/integration/targets/test_mysql_user/tasks/issue-121.yml
Normal file
|
@ -0,0 +1,115 @@
|
|||
---
|
||||
- vars:
|
||||
mysql_parameters: &mysql_params
|
||||
login_user: '{{ mysql_user }}'
|
||||
login_password: '{{ mysql_password }}'
|
||||
login_host: 127.0.0.1
|
||||
login_port: '{{ mysql_primary_port }}'
|
||||
|
||||
block:
|
||||
|
||||
# ============================================================
|
||||
- shell: pip show pymysql | awk '/Version/ {print $2}'
|
||||
register: pymysql_version
|
||||
|
||||
- name: get server certificate
|
||||
copy:
|
||||
content: "{{ lookup('pipe', \"openssl s_client -starttls mysql -connect localhost:3307 -showcerts 2>/dev/null </dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p'\") }}"
|
||||
dest: /tmp/cert.pem
|
||||
delegate_to: localhost
|
||||
|
||||
- name: get server version
|
||||
mysql_info:
|
||||
<<: *mysql_params
|
||||
filter: version
|
||||
register: db_version
|
||||
|
||||
- set_fact:
|
||||
old_user_mgmt: "{{ db_version.version.major <= 5 and db_version.version.minor <= 6 or db_version.version.major == 10 and db_version.version.minor < 2 | bool }}"
|
||||
|
||||
- name: Drop mysql user if exists
|
||||
mysql_user:
|
||||
<<: *mysql_params
|
||||
name: '{{ item }}'
|
||||
state: absent
|
||||
ignore_errors: yes
|
||||
with_items:
|
||||
- "{{ user_name_1 }}"
|
||||
- "{{ user_name_2 }}"
|
||||
|
||||
- name: create user with REQUIRESSL privilege
|
||||
mysql_user:
|
||||
<<: *mysql_params
|
||||
name: "{{ user_name_1 }}"
|
||||
password: "{{ user_password_1 }}"
|
||||
priv: '*.*:SELECT,CREATE USER,REQUIRESSL,GRANT'
|
||||
|
||||
- name: verify REQUIRESSL is assigned to the user
|
||||
mysql_query:
|
||||
<<: *mysql_params
|
||||
query: "SHOW {{ what }} '{{ user_name_1}}'@'localhost'"
|
||||
register: result
|
||||
vars:
|
||||
what: "{{ 'GRANTS FOR' if old_user_mgmt else 'CREATE USER' }}"
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is succeeded and 'REQUIRE SSL' in (result.query_result | string)
|
||||
|
||||
- name: create user with equivalent ssl requirement in tls_requires (expect unchanged)
|
||||
mysql_user:
|
||||
<<: *mysql_params
|
||||
name: "{{ user_name_1 }}"
|
||||
password: "{{ user_password_1 }}"
|
||||
priv: '*.*:SELECT,CREATE USER,GRANT'
|
||||
tls_requires:
|
||||
SSL:
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is not changed
|
||||
|
||||
- name: create the same user again, with REQUIRESSL privilege once more
|
||||
mysql_user:
|
||||
<<: *mysql_params
|
||||
name: "{{ user_name_1 }}"
|
||||
password: "{{ user_password_1 }}"
|
||||
priv: '*.*:SELECT,CREATE USER,REQUIRESSL,GRANT'
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is not changed
|
||||
|
||||
- name: create user with both REQUIRESSL privilege and an incompatible tls_requires option
|
||||
mysql_user:
|
||||
<<: *mysql_params
|
||||
name: "{{ user_name_1 }}"
|
||||
password: "{{ user_password_1 }}"
|
||||
priv: '*.*:SELECT,CREATE USER,REQUIRESSL,GRANT'
|
||||
tls_requires:
|
||||
X509:
|
||||
|
||||
- name: create same user again without REQUIRESSL privilege
|
||||
mysql_user:
|
||||
<<: *mysql_params
|
||||
name: "{{ user_name_1 }}"
|
||||
password: "{{ user_password_1 }}"
|
||||
priv: '*.*:SELECT,CREATE USER,GRANT'
|
||||
tls_requires:
|
||||
X509:
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that: result is not changed
|
||||
|
||||
- name: Drop mysql user
|
||||
mysql_user:
|
||||
<<: *mysql_params
|
||||
name: '{{ item }}'
|
||||
host: 127.0.0.1
|
||||
state: absent
|
||||
with_items:
|
||||
- "{{ user_name_1 }}"
|
||||
- "{{ user_name_2 }}"
|
|
@ -37,6 +37,8 @@
|
|||
|
||||
block:
|
||||
|
||||
- include: issue-121.yml
|
||||
|
||||
- include: issue-28.yml
|
||||
|
||||
- include: create_user.yml user_name={{user_name_1}} user_password={{ user_password_1 }}
|
||||
|
|
|
@ -4,12 +4,17 @@ from __future__ import (absolute_import, division, print_function)
|
|||
__metaclass__ = type
|
||||
|
||||
import pytest
|
||||
try:
|
||||
from unittest.mock import MagicMock
|
||||
except ImportError:
|
||||
from mock import MagicMock
|
||||
|
||||
from ansible_collections.community.mysql.plugins.modules.mysql_user import (
|
||||
handle_grant_on_col,
|
||||
has_grant_on_col,
|
||||
normalize_col_grants,
|
||||
sort_column_order,
|
||||
handle_requiressl_in_priv_string
|
||||
)
|
||||
from ..utils import dummy_cursor_class
|
||||
|
||||
|
@ -74,6 +79,71 @@ def test_handle_grant_on_col(privileges, start, end, output):
|
|||
assert handle_grant_on_col(privileges, start, end) == output
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'input_tuple,output_tuple',
|
||||
[
|
||||
(('*.*:REQUIRESSL', None), (None, 'SSL')),
|
||||
(('*.*:ALL,REQUIRESSL', None), ('*.*:ALL', 'SSL')),
|
||||
(('*.*:REQUIRESSL,ALL', None), ('*.*:ALL', 'SSL')),
|
||||
(('*.*:ALL,REQUIRESSL,GRANT', None), ('*.*:ALL,GRANT', 'SSL')),
|
||||
(('*.*:ALL,REQUIRESSL,GRANT/a.b:USAGE', None), ('*.*:ALL,GRANT/a.b:USAGE', 'SSL')),
|
||||
(('*.*:REQUIRESSL', 'X509'), (None, 'X509')),
|
||||
(('*.*:ALL,REQUIRESSL', 'X509'), ('*.*:ALL', 'X509')),
|
||||
(('*.*:REQUIRESSL,ALL', 'X509'), ('*.*:ALL', 'X509')),
|
||||
(('*.*:ALL,REQUIRESSL,GRANT', 'X509'), ('*.*:ALL,GRANT', 'X509')),
|
||||
(('*.*:ALL,REQUIRESSL,GRANT/a.b:USAGE', 'X509'), ('*.*:ALL,GRANT/a.b:USAGE', 'X509')),
|
||||
(('*.*:REQUIRESSL', {
|
||||
'subject': '/CN=alice/O=MyDom, Inc./C=US/ST=Oregon/L=Portland',
|
||||
'cipher': 'ECDHE-ECDSA-AES256-SHA384',
|
||||
'issuer': '/CN=org/O=MyDom, Inc./C=US/ST=Oregon/L=Portland'
|
||||
}), (None, {
|
||||
'subject': '/CN=alice/O=MyDom, Inc./C=US/ST=Oregon/L=Portland',
|
||||
'cipher': 'ECDHE-ECDSA-AES256-SHA384',
|
||||
'issuer': '/CN=org/O=MyDom, Inc./C=US/ST=Oregon/L=Portland'
|
||||
})),
|
||||
(('*.*:ALL,REQUIRESSL', {
|
||||
'subject': '/CN=alice/O=MyDom, Inc./C=US/ST=Oregon/L=Portland',
|
||||
'cipher': 'ECDHE-ECDSA-AES256-SHA384',
|
||||
'issuer': '/CN=org/O=MyDom, Inc./C=US/ST=Oregon/L=Portland'
|
||||
}), ('*.*:ALL', {
|
||||
'subject': '/CN=alice/O=MyDom, Inc./C=US/ST=Oregon/L=Portland',
|
||||
'cipher': 'ECDHE-ECDSA-AES256-SHA384',
|
||||
'issuer': '/CN=org/O=MyDom, Inc./C=US/ST=Oregon/L=Portland'
|
||||
})),
|
||||
(('*.*:REQUIRESSL,ALL', {
|
||||
'subject': '/CN=alice/O=MyDom, Inc./C=US/ST=Oregon/L=Portland',
|
||||
'cipher': 'ECDHE-ECDSA-AES256-SHA384',
|
||||
'issuer': '/CN=org/O=MyDom, Inc./C=US/ST=Oregon/L=Portland'
|
||||
}), ('*.*:ALL', {
|
||||
'subject': '/CN=alice/O=MyDom, Inc./C=US/ST=Oregon/L=Portland',
|
||||
'cipher': 'ECDHE-ECDSA-AES256-SHA384',
|
||||
'issuer': '/CN=org/O=MyDom, Inc./C=US/ST=Oregon/L=Portland'
|
||||
})),
|
||||
(('*.*:ALL,REQUIRESSL,GRANT', {
|
||||
'subject': '/CN=alice/O=MyDom, Inc./C=US/ST=Oregon/L=Portland',
|
||||
'cipher': 'ECDHE-ECDSA-AES256-SHA384',
|
||||
'issuer': '/CN=org/O=MyDom, Inc./C=US/ST=Oregon/L=Portland'
|
||||
}), ('*.*:ALL,GRANT', {
|
||||
'subject': '/CN=alice/O=MyDom, Inc./C=US/ST=Oregon/L=Portland',
|
||||
'cipher': 'ECDHE-ECDSA-AES256-SHA384',
|
||||
'issuer': '/CN=org/O=MyDom, Inc./C=US/ST=Oregon/L=Portland'
|
||||
})),
|
||||
(('*.*:ALL,REQUIRESSL,GRANT/a.b:USAGE', {
|
||||
'subject': '/CN=alice/O=MyDom, Inc./C=US/ST=Oregon/L=Portland',
|
||||
'cipher': 'ECDHE-ECDSA-AES256-SHA384',
|
||||
'issuer': '/CN=org/O=MyDom, Inc./C=US/ST=Oregon/L=Portland'
|
||||
}), ('*.*:ALL,GRANT/a.b:USAGE', {
|
||||
'subject': '/CN=alice/O=MyDom, Inc./C=US/ST=Oregon/L=Portland',
|
||||
'cipher': 'ECDHE-ECDSA-AES256-SHA384',
|
||||
'issuer': '/CN=org/O=MyDom, Inc./C=US/ST=Oregon/L=Portland'
|
||||
}))
|
||||
]
|
||||
)
|
||||
def test_handle_requiressl_in_priv_string(input_tuple, output_tuple):
|
||||
"""Tests the handle_requiressl_in_priv_string funciton."""
|
||||
assert handle_requiressl_in_priv_string(MagicMock(), *input_tuple) == output_tuple
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'input_,expected',
|
||||
[
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue