runner.py (119 lines of code) (raw):
import time
from Crypto import Random
from twitter.common import log
from google.admin import GoogleAdminApi
from google.calendar import GoogleCalendarApi
from google.drive import GoogleDriveApi
from google.gmail import GoogleGmailApi
from google.oauth import GoogleOAuthApi
from helper_functions import HelperFunctions
from ldap_client import LDAPClient
from pagerduty import PagerDutyApi
from duo import DuoAdminApi
config = HelperFunctions().read_config_from_yaml()
NO_SUSPEND_ACTIONS = ["remove_from_oncalls", "org_unit_reset"]
class Runner(object):
def __init__(self, user=None):
Random.atfork()
self.ADMIN_USER = config["google_apps"]["admin_user"]
self.DOMAIN = config["google_apps"]["domain"]
self.use_proxy = config["defaults"]["http_proxy"]["use_proxy"]
self.user = user
self.admin_email = "%s@%s" % (self.ADMIN_USER, self.DOMAIN)
self.user_email = "%s@%s" % (user, self.DOMAIN)
self.google_oauth = GoogleOAuthApi(config=config)
self.oauth_admin = self.google_oauth.get_oauth_token(self.admin_email)
self.oauth_user = self.google_oauth.get_oauth_token(self.user_email)
self.admin_api = GoogleAdminApi(self.oauth_admin, config=config["google_apps"])
self.gmail_api = GoogleGmailApi(self.oauth_user)
self.drive_api = GoogleDriveApi(self.oauth_user)
self.calendar_api = GoogleCalendarApi(self.oauth_user)
self.ldap_client = LDAPClient(config=config["ldap"])
self.is_valid_user = self._is_valid_user()
self.is_suspended_user = self._is_suspended_user()
self.pagerduty_api = PagerDutyApi(config=config["pagerduty"],
use_proxy=self.use_proxy,
proxy_config=config["defaults"]["http_proxy"])
self.duo_api = DuoAdminApi(config=config["duo"],
use_proxy=self.use_proxy,
proxy_config=config["defaults"]["http_proxy"])
def _is_valid_user(self):
"""
Checks whether the user is a valid LDAP user.
:return: bool
Note: Additional check now makes sure the user's name on LDAP matches than on Google Apps.
"""
name_on_gapps = ""
is_valid = self.ldap_client.is_valid_user(user=self.user)
user_info = self.ldap_client.get_user_info(user=self.user)
name_on_ldap = user_info["sn"][0]
if self.oauth_admin is not None:
try:
name_on_gapps = ("{familyName}"
.format(**self.admin_api.get_user_name(self.user_email)))
except (TypeError, UnicodeEncodeError) as e:
log.info("is_valid: %s" % e)
log.info("user: %s - is_valid: %r - name_on_ldap: %s - name_on_gapps: %s" %
(self.user, is_valid, name_on_ldap, name_on_gapps))
if is_valid and name_on_ldap == name_on_gapps:
return True
else:
return False
def _is_suspended_user(self):
"""
Checks whether the user is suspended.
:return: bool
"""
is_suspended = False
if self.is_valid_user:
is_suspended = self.admin_api.is_suspended(self.user_email)
log.info("user: %s - is_suspended: %r" % (self.user, is_suspended))
return is_suspended
def suspend_user(self, suspend):
"""
Suspends or un-suspends a user.
:param: suspend: bool
"""
msg = ""
if self.is_valid_user:
if suspend and self._is_suspended_user():
msg = "%s - User already suspended" % self.user
elif suspend and not self._is_suspended_user():
self.admin_api.suspend(self.user_email)
msg = "%s - User was suspended" % self.user
elif not suspend and self._is_suspended_user():
self.admin_api.un_suspend(self.user_email)
while self._is_suspended_user(): # workaround for google api delays in propagation
time.sleep(8)
msg = "%s - User was un-suspended" % self.user
elif not suspend and not self._is_suspended_user():
msg = "%s - User already un-suspended" % self.user
else:
msg = "%s - Not a valid LDAP user" % self.user
log.info(msg)
return msg
def perform_action(self, api_connector, action, kwargs):
"""
Performs offboarding actions selected from the Web UI form.
:param api_connector: string of the API connector to use
:param action: name of action to be performed
:return: msg log for action performed, along with status
Note: action item must match function names of the equivalent API class.
"""
msg = ""
if self.is_valid_user:
if self.is_suspended_user and action not in NO_SUSPEND_ACTIONS:
self.suspend_user(False)
connector = getattr(self, api_connector)
result = getattr(connector, action)(self.user_email, **kwargs)
if type(result) is dict:
results = []
for k, v in result.items():
if v is True:
results.append("<span class='text-success'>%s</span>" % k)
elif v is False:
results.append("<span class='text-danger'>%s</span>" % k)
else:
results.append(k)
if not results:
results = "<span class='text-success'>SUCCESS</span>"
msg = "<p>%s: %s</p>" % (action.replace("_", " ").upper(), results)
else:
if result is False:
msg_color = "danger"
msg_text = "FAILED"
elif result is True:
msg_color = "success"
msg_text = "SUCCESS"
elif result is None:
msg_color = "danger"
msg_text = "FAILED (EMPTY RESULT)"
else:
msg_color = "success"
msg_text = "SUCCESS"
msg = ("<p>%s: <span class=\"text-%s\">%s</span></p>" %
(action.replace("_", " ").upper(), msg_color, msg_text))
else:
msg = "<p><span class=\"text-danger\">FAILED - INVALID USER</span></p>"
log.info(msg)
return msg