@ -16,6 +16,8 @@
# You should have received a copy of the GNU General Public License
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
import re
try:
try:
import psycopg2
import psycopg2
except ImportError:
except ImportError:
@ -75,42 +77,70 @@ def user_delete(cursor, user):
def has_table_privilege(cursor, user, table, priv):
def has_table_privilege(cursor, user, table, priv):
query = 'SELECT has_table_privilege(%s, %s, %s)'
query = 'SELECT has_table_privilege(%s, %s, %s)'
cursor.execute(query, user, table, priv)
cursor.execute(query, ( user, table, priv))
return cursor.fetchone()[0]
return cursor.fetchone()[0]
def get_table_privileges(cursor, user, table):
if '.' in table:
schema, table = table.split('.', 1)
else:
schema = 'public'
query = '''SELECT privilege_type FROM information_schema.role_table_grants
WHERE grantee=%s AND table_name=%s AND table_schema=%s'''
cursor.execute(query, (user, table, schema))
return set([x[0] for x in cursor.fetchall()])
def grant_table_privilege(cursor, user, table, priv):
def grant_table_privilege(cursor, user, table, priv):
if has_table_privilege(cursor, user, table, priv):
prev_priv = get_table_privileges(cursor, user, table)
return False
query = 'GRANT %s ON TABLE %s TO %s' % (priv, table, user)
query = 'GRANT %s ON TABLE %s TO %s' % (priv, table, user)
cursor.execute(query)
cursor.execute(query)
return True
curr_priv = get_table_privileges(cursor, user, table)
return len(curr_priv) > len(prev_priv)
def revoke_table_privilege(cursor, user, table, priv):
def revoke_table_privilege(cursor, user, table, priv):
if not has_table_privilege(cursor, user, table, priv):
prev_priv = get_table_privileges(cursor, user, table)
return False
query = 'REVOKE %s ON TABLE %s FROM %s' % (priv, table, user)
query = 'REVOKE %s ON TABLE %s FROM %s' % (priv, table, user)
cursor.execute(query)
cursor.execute(query)
return True
curr_priv = get_table_privileges(cursor, user, table)
return len(curr_priv) < len(prev_priv)
def get_database_privileges(cursor, user, db):
priv_map = {
'C':'CREATE',
'T':'TEMPORARY',
'c':'CONNECT',
}
query = 'SELECT datacl FROM pg_database WHERE datname = %s'
cursor.execute(query, (db,))
datacl = cursor.fetchone()[0]
r = re.search('%s=(C?T?c?)/[a-z]+\,?' % user, datacl)
if r is None:
return []
o = []
for v in r.group(1):
o.append(priv_map[v])
return o
def has_database_privilege(cursor, user, db, priv):
def has_database_privilege(cursor, user, db, priv):
query = 'SELECT has_database_privilege(%s, %s, %s)'
query = 'SELECT has_database_privilege(%s, %s, %s)'
cursor.execute(query, user, db, priv)
cursor.execute(query, ( user, db, priv))
return cursor.fetchone()[0]
return cursor.fetchone()[0]
def grant_database_privilege(cursor, user, db, priv):
def grant_database_privilege(cursor, user, db, priv):
if has_database_privilege(cursor, user, db, priv):
prev_priv = get_database_privileges(cursor, user, db)
return False
query = 'GRANT %s ON DATABASE %s TO %s' % (priv, db, user)
query = 'GRANT %s ON DATABASE %s TO %s' % (priv, db, user)
cursor.execute(query)
cursor.execute(query)
return True
curr_priv = get_database_privileges(cursor, user, db)
return len(curr_priv) > len(prev_priv)
def revoke_database_privilege(cursor, user, db, priv):
def revoke_database_privilege(cursor, user, db, priv):
if not has_database_privilege(cursor, user, db, priv):
prev_priv = get_database_privileges(cursor, user, db)
return False
query = 'REVOKE %s ON DATABASE %s FROM %s' % (priv, db, user)
query = 'REVOKE %s ON DATABASE %s FROM %s' % (priv, db, user)
cursor.execute(query)
cursor.execute(query)
return True
curr_priv = get_database_privileges(cursor, user, db)
return len(curr_priv) < len(prev_priv)
def revoke_privileges(cursor, user, privs):
def revoke_privileges(cursor, user, privs):
if privs is None:
if privs is None:
@ -122,7 +152,7 @@ def revoke_privileges(cursor, user, privs):
'table':revoke_table_privilege,
'table':revoke_table_privilege,
'database':revoke_database_privilege
'database':revoke_database_privilege
}[type_]
}[type_]
for name, privileges in privs[type_].iteritem():
for name, privileges in privs[type_].iteritems ():
for privilege in privileges:
for privilege in privileges:
changed = revoke_func(cursor, user, name, privilege)\
changed = revoke_func(cursor, user, name, privilege)\
or changed
or changed
@ -139,7 +169,7 @@ def grant_privileges(cursor, user, privs):
'table':grant_table_privilege,
'table':grant_table_privilege,
'database':grant_database_privilege
'database':grant_database_privilege
}[type_]
}[type_]
for name, privileges in privs[type_].iteritem():
for name, privileges in privs[type_].iteritems ():
for privilege in privileges:
for privilege in privileges:
changed = grant_func(cursor, user, name, privilege)\
changed = grant_func(cursor, user, name, privilege)\
or changed
or changed
@ -161,7 +191,7 @@ def parse_privs(privs, db):
if privs is None:
if privs is None:
return privs
return privs
privs = {
o_ privs = {
'database':{},
'database':{},
'table':{}
'table':{}
}
}
@ -169,15 +199,15 @@ def parse_privs(privs, db):
if ':' not in token:
if ':' not in token:
type_ = 'database'
type_ = 'database'
name = db
name = db
privileges = token
priv_set = set(x.strip() for x in token.split(','))
else:
else:
type_ = 'table'
type_ = 'table'
name, privileges = token.split(':', 1)
name, privileges = token.split(':', 1)
privileges = privileges.split(',' )
priv_set = set(x.strip() for x in privileges.split(',') )
privs[type_][name] = privileges
o_privs[type_][name] = priv_set
return privs
return o_ privs
# ===========================================
# ===========================================
# Module execution.
# Module execution.