def buildInitOutputStr(token, expires, rdict): log.debug("in buildInitOutputStr") ut = Utils() expa = ut.expiresAt(expires) bstr = "" xstr = "```" xstr = glue.addToOutStr(xstr, "api", rdict["apiid"]) bstr = glue.addToReqBody(bstr, "api", rdict["apiid"]) xstr = glue.addToOutStr(xstr, "slackid", rdict["slackid"]) bstr = glue.addToReqBody(bstr, "slackid", rdict["slackid"]) xstr = glue.addToOutStr(xstr, "workspaceid", rdict["teamid"]) bstr = glue.addToReqBody(bstr, "workspaceid", rdict["teamid"]) xstr = glue.addToOutStr(xstr, "username", rdict["username"]) bstr = glue.addToReqBody(bstr, "username", rdict["username"]) xstr = glue.addToOutStr(xstr, "usertoken", token) bstr = glue.addToReqBody(bstr, "usertoken", token) xstr = glue.addToOutStr(xstr, "expires", expires) bstr = glue.addToReqBody(bstr, "expires", expires) xstr = glue.addToOutStr(xstr, "stage", rdict["stage"]) bstr = glue.addToReqBody(bstr, "stage", rdict["stage"]) xstr = glue.addToOutStr(xstr, "region", "eu-west-1") bstr = glue.addToReqBody(bstr, "region", "eu-west-1") xstr += "```\n" butf8 = bstr.encode('utf8') benc = base64.urlsafe_b64encode(butf8) bstr = "```chaim -j " + benc.decode('utf8') + "```" bstr += "\n```cca init " + benc.decode('utf8') + "```" return expa, xstr, bstr
def buildCredentials(pms, rdict, noUrl=False): emsg = kdict = None try: ut = Utils() zstart = ut.getNow() log.debug("buildCredentials: checking user and token") userid = checkUserAndToken(pms, rdict) log.debug("buildCredentials: updating last access stamp") pms.lastupdated(userid, stamp=zstart, cli=noUrl) log.debug("buildCredentials: updating slack") slackTimeStamp("token check", zstart, rdict, ut) log.debug("buildCredentials: checking user allowed") accountid = checkUserAllowed(pms, rdict) slackTimeStamp("user authorised", zstart, rdict, ut) if accountid == rdict["accountname"]: # if the original accountname was just the number # obtain the correct name rdict["accountname"] = pms.derivedaccountname ar, aro, rdict = startSTS(pms, rdict, accountid, ut, zstart) slackTimeStamp("role assumed", zstart, rdict, ut) kdict = getUrl(ar, aro, pms, rdict, noUrl, accountid) except Exception as e: emsg = "buildCredentials error: {}: {}".format(type(e).__name__, e) log.error(emsg) raise(CredentialsGenerationFail(emsg)) return [kdict, rdict]
def whosKey(pms, key): """ map a chaim issued key to a slack (or CLI) user :param pms: Permissions object :param key: the key to map """ ut = Utils() row = pms.whosKey(key) if len(row) > 0: log.debug("extracting key") key = row[0][0] log.debug("key got {}".format(key)) log.debug("extracting expires") expires = row[0][1] whenat = ut.expiresAt(expires) log.debug("expires got {}".format(expires)) log.debug("extracting name") username = row[0][2] log.debug("name got {}".format(username)) log.debug("extracting account") account = row[0][3] log.debug("account got {}".format(account)) msg = "\n\nKey {}".format(key) msg += "\nIssued to: {}".format(username) msg += "\nfor account: {}".format(account) msg += "\nExpires at: {}\n\n".format(whenat) else: msg = "Key not found" return msg
def doKeyInit(rdict, pms): """ generate and set user token :param rdict: a dictionary of user details built from the incomming request """ try: log.debug("keyinit incoming request: {}".format(rdict)) if not pms.userActive(rdict["username"]): raise InactiveUser("{} is not an active user.".format(rdict["username"])) log.debug("doKeyInit User {} is ACTIVE".format(rdict["username"])) log.debug("doKeyInit checking token") if not pms.checkToken(rdict["incomingtoken"], rdict["username"], rdict["teamid"]): raise InvalidToken("slack access token is invalid") log.debug("doKeyInit slack token check passed ok") expiredays = 6 if rdict["stage"] != "dev" else 1 ut = Utils() uuid, expires = ut.newUserToken(expiredays) if pms.updateUserToken(rdict["username"], uuid, expires): expat, xstr, bstr = buildInitOutputStr(uuid, expires, rdict) msg = "New Chaim Credentials Expire {}\n{}\n{}".format(expat, xstr, bstr) else: msg = "Failed to write a new user token, sorry." raise InvalidToken(msg) except Exception as e: msg = "doKeyInit error: {}: {}".format(type(e).__name__, e) log.error(msg) return msg return msg
def cleanKeyMap(self, days=30, dryrun=False): afrows = 0 tfr = 0 try: sql = "select count(*) from keymap" rows = self.sid.query(sql) for row in rows: tfr = row[0] ut = Utils() then = ut.getNow() - (days * 24 * 60 * 60) if dryrun: sql = "select count(*) from keymap " else: sql = "delete from keymap " sql += "where expires < {}".format(then) if dryrun: rows = self.sid.query(sql) for row in rows: afrows = row[0] else: afrows = self.rwsid.deleteQuery(sql) except Exception as e: msg = "A cleantKeyMap error occurred: {}: {}".format( type(e).__name__, e) log.error(msg) raise DataNotFound(msg) return [tfr, afrows]
def userAllowed(self, username, account, role): log.debug("userAllowed test: {} {} {}".format(username, account, role)) if self.sid is not None: userid = self.checkIDs("awsusers", "name", "User", username) ut = Utils() if ut.isNumeric(account): accountid = account self.derivedaccountname = self.sid.singleField( "awsaccounts", "name", "id='{}'".format(accountid)) else: accountid = self.checkIDs("awsaccounts", "name", "Account", account) log.debug( "userAllowed: username: {}, account:{}, role: {}, accountid is {}" .format(username, account, role, accountid)) if accountid is None: return [False, None] self.derivedaccountname = account roleid = self.checkIDs("awsroles", "name", "Role", role) sql = "select * from useracctrolemap where " sql += "accountid='{}'".format(accountid) sql += " and " sql += "roleid={}".format(roleid) sql += " and " sql += "userid={}".format(userid) rowa = self.sid.query(sql) if len(rowa): return [True, accountid] else: msg = "Permission not granted to {} in {} for {}".format( username, account, role) raise DataNotFound(msg) else: raise DBNotConnected("No connection to Database")
def checkUserToken(self, username, token): ut = Utils() try: dbtok, dbexp = self.readUserToken(username) if dbtok == token: if dbexp > ut.getNow(): return True return False except Exception as e: log.error("error executing check usertoken query") raise DataNotFound(e)
def durationAndRole(self, fields, cn): if cn > 2: try: self.duration = int(fields[2].strip()) self.rolealias = fields[1].strip() except ValueError: try: self.duration = int(fields[1].strip()) self.rolealias = fields[2].strip() except ValueError: raise BadCommandStr("Failed to parse command") elif cn > 1: self.rolealias = fields[1].strip() if self.duration <= 12 and self.duration >= 1: self.duration = self.duration * 3600 elif self.duration < 900: self.duration = 900 elif self.duration > 43200: self.duration = 43200 ut = Utils() self.durationstr = ut.displayHMS(self.duration)
def checkToken(self, token, username, workspaceid): log.debug("token: {}, username: {}, workspaceid: {}".format( token, username, workspaceid)) ut = Utils() pargs = (self.spath, workspaceid, self.env, "slacktoken") path = self.buildPath(pargs) # path = self.spath + workspaceid + "/" + self.env + "/slacktoken" log.debug("asking for {}".format(path)) slacktoken = self.ps.getParam(path, True) # slacktoken = self.params["slacktoken"] if slacktoken == token: self.fromslack = True self.setSlackApiToken(workspaceid) return True else: clitoken, expires = self.readUserToken(username) if token == clitoken: if expires > ut.getNow(): return True else: raise (IncorrectCredentials("usertoken has expired")) raise (IncorrectCredentials("Invalid token")) return False
def countLastSince(self, months=1): if self.sid is not None: ut = Utils() mnth = ut.displayWord(months, "Month") now = ut.getNow() then = now - (int(months) * 86400 * 30) sql = "select count(id) as cn from awsusers" rows = self.sid.query(sql) log.debug("sql returns {}".format(rows)) allusers = rows[0][0] log.debug("allusers {}".format(allusers)) sql = "select count(lastcli) as cn from awsusers where lastcli > " + str( then) rows = self.sid.query(sql) log.debug("sql returns {}".format(rows)) lastcli = rows[0][0] sql = "select count(lastslack) as cn from awsusers where lastslack > " + str( then) rows = self.sid.query(sql) lastslack = rows[0][0] sql = "select count(lastcli) as cn from awsusers" sql += " where lastcli > " + str(then) + " and lastslack > " + str( then) rows = self.sid.query(sql) lastboth = rows[0][0] active = (int(lastslack) + int(lastcli)) - int(lastboth) inactive = int(allusers) - active msg = "Previous {}".format(mnth) msg += "\n{:<12}{:>5}".format("All:", allusers) msg += "\n{:<12}{:>5}".format("Active:", active) msg += "\n{:<12}{:>5}".format("Inactive:", inactive) msg += "\n{:<12}{:>5}".format("CLI:", lastcli) msg += "\n{:<12}{:>5}".format("Slack:", lastslack) msg += "\n{:<12}{:>5}".format("Both:", lastboth) return msg else: return "DB not connected"
def createNewUser(self, slackname, slackid, workspaceid, email): try: ut = Utils() if not ut.checkIsEmailAddress(email): raise InvalidEmailAddress( "invalid email address: {}".format(email)) cid = None if " " in slackname: raise IncorrectCredentials( "Invalid chaim name: {}".format(slackname)) if self.rwsid is None: raise DBNotConnected("no connection to db for createNewUser") chaimuserid = self.checkIDs("awsusers", "name", "User", slackname, True) if chaimuserid is not None: if self.checkSlackMap(chaimuserid, slackid, workspaceid): raise ChaimUserExists( "Chaim user already exists: {}".format(slackname)) else: cid = chaimuserid else: cid = self.createUser(slackname) if cid is not None: cc = CognitoClient() if cc.adminCreateUser(self.params["poolid"], slackname, email): sql = self.slackMapInsert(cid, slackid, workspaceid) naf = self.rwsid.insertQuery(sql) if naf == 1: return True return False except Exception as e: log.warning( "Failed to create new user {}, Exception {}: {}".format( slackname, type(e).__name__, e)) raise
# chaim is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # chaim is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with chaim. If not, see <http://www.gnu.org/licenses/>. # from chalicelib.utils import Utils ut = Utils() def test_isNumeric_int(): b = ut.isNumeric(7) assert b is True def test_isNumeric_str(): b = ut.isNumeric("7") assert b is True def test_isNumeric_alpha_str(): b = ut.isNumeric("A") assert b is False