File: //usr/lib/python2.7/site-packages/salt/modules/mac_assistive.py
# -*- coding: utf-8 -*-
'''
This module allows you to manage assistive access on macOS minions with 10.9+
.. versionadded:: 2016.3.0
.. code-block:: bash
salt '*' assistive.install /usr/bin/osascript
'''
# Import Python Libs
from __future__ import absolute_import, unicode_literals, print_function
import re
import logging
# Import salt libs
import salt.utils.platform
import salt.utils.stringutils
from salt.exceptions import CommandExecutionError
from salt.utils.versions import LooseVersion as _LooseVersion
log = logging.getLogger(__name__)
__virtualname__ = 'assistive'
def __virtual__():
'''
Only work on Mac OS
'''
if not salt.utils.platform.is_darwin():
return False, 'Must be run on macOS'
if _LooseVersion(__grains__['osrelease']) < salt.utils.stringutils.to_str('10.9'):
return False, 'Must be run on macOS 10.9 or newer'
return __virtualname__
def install(app_id, enable=True):
'''
Install a bundle ID or command as being allowed to use
assistive access.
app_id
The bundle ID or command to install for assistive access.
enabled
Sets enabled or disabled status. Default is ``True``.
CLI Example:
.. code-block:: bash
salt '*' assistive.install /usr/bin/osascript
salt '*' assistive.install com.smileonmymac.textexpander
'''
ge_el_capitan = True if _LooseVersion(__grains__['osrelease']) >= salt.utils.stringutils.to_str('10.11') else False
ge_mojave = True if _LooseVersion(__grains__['osrelease']) >= salt.utils.stringutils.to_str('10.14') else False
client_type = _client_type(app_id)
enable_str = '1' if enable else '0'
cmd = 'sqlite3 "/Library/Application Support/com.apple.TCC/TCC.db" ' \
'"INSERT or REPLACE INTO access VALUES(\'kTCCServiceAccessibility\',\'{0}\',{1},{2},1,NULL{3}{4})"'.\
format(app_id,
client_type,
enable_str,
',NULL' if ge_el_capitan else '',
",NULL,NULL,NULL,NULL,''" if ge_mojave else '')
call = __salt__['cmd.run_all'](
cmd,
output_loglevel='debug',
python_shell=False
)
if call['retcode'] != 0:
comment = ''
if 'stderr' in call:
comment += call['stderr']
if 'stdout' in call:
comment += call['stdout']
raise CommandExecutionError('Error installing app: {0}'.format(comment))
return True
def installed(app_id):
'''
Check if a bundle ID or command is listed in assistive access.
This will not check to see if it's enabled.
app_id
The bundle ID or command to check installed status.
CLI Example:
.. code-block:: bash
salt '*' assistive.installed /usr/bin/osascript
salt '*' assistive.installed com.smileonmymac.textexpander
'''
for a in _get_assistive_access():
if app_id == a[0]:
return True
return False
def enable(app_id, enabled=True):
'''
Enable or disable an existing assistive access application.
app_id
The bundle ID or command to set assistive access status.
enabled
Sets enabled or disabled status. Default is ``True``.
CLI Example:
.. code-block:: bash
salt '*' assistive.enable /usr/bin/osascript
salt '*' assistive.enable com.smileonmymac.textexpander enabled=False
'''
enable_str = '1' if enabled else '0'
for a in _get_assistive_access():
if app_id == a[0]:
cmd = 'sqlite3 "/Library/Application Support/com.apple.TCC/TCC.db" ' \
'"UPDATE access SET allowed=\'{0}\' WHERE client=\'{1}\'"'.format(enable_str, app_id)
call = __salt__['cmd.run_all'](
cmd,
output_loglevel='debug',
python_shell=False
)
if call['retcode'] != 0:
comment = ''
if 'stderr' in call:
comment += call['stderr']
if 'stdout' in call:
comment += call['stdout']
raise CommandExecutionError('Error enabling app: {0}'.format(comment))
return True
return False
def enabled(app_id):
'''
Check if a bundle ID or command is listed in assistive access and
enabled.
app_id
The bundle ID or command to retrieve assistive access status.
CLI Example:
.. code-block:: bash
salt '*' assistive.enabled /usr/bin/osascript
salt '*' assistive.enabled com.smileonmymac.textexpander
'''
for a in _get_assistive_access():
if app_id == a[0] and a[1] == '1':
return True
return False
def remove(app_id):
'''
Remove a bundle ID or command as being allowed to use assistive access.
app_id
The bundle ID or command to remove from assistive access list.
CLI Example:
.. code-block:: bash
salt '*' assistive.remove /usr/bin/osascript
salt '*' assistive.remove com.smileonmymac.textexpander
'''
cmd = 'sqlite3 "/Library/Application Support/com.apple.TCC/TCC.db" ' \
'"DELETE from access where client=\'{0}\'"'.format(app_id)
call = __salt__['cmd.run_all'](
cmd,
output_loglevel='debug',
python_shell=False
)
if call['retcode'] != 0:
comment = ''
if 'stderr' in call:
comment += call['stderr']
if 'stdout' in call:
comment += call['stdout']
raise CommandExecutionError('Error removing app: {0}'.format(comment))
return True
def _client_type(app_id):
'''
Determine whether the given ID is a bundle ID or a
a path to a command
'''
return '1' if app_id[0] == '/' else '0'
def _get_assistive_access():
'''
Get a list of all of the assistive access applications installed,
returns as a ternary showing whether each app is enabled or not.
'''
cmd = 'sqlite3 "/Library/Application Support/com.apple.TCC/TCC.db" "SELECT * FROM access"'
call = __salt__['cmd.run_all'](
cmd,
output_loglevel='debug',
python_shell=False
)
if call['retcode'] != 0:
comment = ''
if 'stderr' in call:
comment += call['stderr']
if 'stdout' in call:
comment += call['stdout']
raise CommandExecutionError('Error: {0}'.format(comment))
out = call['stdout']
return re.findall(r'kTCCServiceAccessibility\|(.*)\|[0-9]{1}\|([0-9]{1})\|[0-9]{1}\|', out, re.MULTILINE)