mirror of
https://github.com/valitydev/salt.git
synced 2024-11-08 01:18:58 +00:00
Add a lexical parser for MySQL grants to the MySQL module. Change the behavior of the grant-checker to use this new method by default and fallback to the strict method if it fails.
This commit is contained in:
parent
67ca15ecc2
commit
c4453b3307
@ -34,6 +34,9 @@ import sys
|
||||
# Import salt libs
|
||||
import salt.utils
|
||||
|
||||
#import shlex which should be distributed with Python
|
||||
import shlex
|
||||
|
||||
# Import third party libs
|
||||
try:
|
||||
import MySQLdb
|
||||
@ -148,6 +151,59 @@ def _connect(**kwargs):
|
||||
return dbc
|
||||
|
||||
|
||||
def _grant_to_tokens(grant):
|
||||
'''
|
||||
|
||||
This should correspond fairly closely to the YAML rendering of a mysql_grants state which comes out
|
||||
as follows:
|
||||
|
||||
OrderedDict([('whatever_identifier', OrderedDict([('mysql_grants.present',
|
||||
[OrderedDict([('database', 'testdb.*')]), OrderedDict([('user', 'testuser')]),
|
||||
OrderedDict([('grant', 'ALTER, SELECT, LOCK TABLES')]), OrderedDict([('host', 'localhost')])])]))])
|
||||
|
||||
:param grant: An un-parsed MySQL GRANT statement str, like
|
||||
"GRANT SELECT, ALTER, LOCK TABLES ON `testdb`.* TO 'testuser'@'localhost'"
|
||||
:return:
|
||||
A Python dict with the following keys/values:
|
||||
- user: MySQL User
|
||||
- host: MySQL host
|
||||
- grant: [grant1, grant2] (ala SELECT, USAGE, etc)
|
||||
- database: MySQL DB
|
||||
'''
|
||||
exploded_grant = shlex.split(grant)
|
||||
grant_tokens = []
|
||||
position_tracker = 1 # Skip the initial 'GRANT' word token
|
||||
phrase = 'grants'
|
||||
|
||||
for token in exploded_grant[position_tracker:]:
|
||||
if phrase == 'grants':
|
||||
cleaned_token = token.rstrip(',')
|
||||
grant_tokens.append(cleaned_token)
|
||||
position_tracker += 1
|
||||
|
||||
if phrase == 'db':
|
||||
database = token.strip('`')
|
||||
phrase = 'tables'
|
||||
|
||||
if phrase == 'user':
|
||||
user, host = token.split('@')
|
||||
|
||||
if token == 'ON':
|
||||
phrase = 'db'
|
||||
|
||||
if token == 'TO':
|
||||
phrase = 'user'
|
||||
|
||||
return {
|
||||
'user': user,
|
||||
'host': host,
|
||||
'grant': grant_tokens,
|
||||
'database': database,
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
def query(database, query, **connection_args):
|
||||
'''
|
||||
Run an arbitrary SQL query and return the results or
|
||||
@ -1080,14 +1136,30 @@ def grant_exists(grant,
|
||||
)
|
||||
|
||||
grants = user_grants(user, host, **connection_args)
|
||||
if grants is not False and target in grants:
|
||||
log.debug('Grant exists.')
|
||||
return True
|
||||
|
||||
for grant in grants:
|
||||
try:
|
||||
target_tokens = None
|
||||
if not target_tokens: # Avoid the overhead of re-calc in loop
|
||||
target_tokens = _grant_to_tokens(target)
|
||||
grant_tokens = _grant_to_tokens(grant)
|
||||
if grant_tokens['user'] == target_tokens['user'] and \
|
||||
grant_tokens['database'] == target_tokens['database'] and \
|
||||
grant_tokens['host'] == target_tokens['host']:
|
||||
if set(grant_tokens['grant']) == set(target_tokens['grant']):
|
||||
return True
|
||||
|
||||
except Exception as exc: # Fallback to strict parsing
|
||||
log.debug("OH NO CAUGHT EXCEPTION: {0}".format(exc))
|
||||
if grants is not False and target in grants:
|
||||
log.debug('Grant exists.')
|
||||
return True
|
||||
|
||||
log.debug('Grant does not exist, or is perhaps not ordered properly?')
|
||||
return False
|
||||
|
||||
|
||||
|
||||
def grant_add(grant,
|
||||
database,
|
||||
user,
|
||||
|
Loading…
Reference in New Issue
Block a user