def verify(token=None): """ Verify a provided JSON Web Token (JWT) for authentication. :param str token: JSON Web Token (JWT) :returns: True if valid, False if not """ if config.get("genesis", "anonymous"): return if request.headers.get("X-API-Key", None): api_key = request.headers.get("X-API-Key") data = secrets.get_all("api-keys") for x in data: if x["key"] == api_key: user = users.get(name=x["user"]) if not user or not user.admin: resp = jsonify(message="Authorization required") resp.status_code = 401 return resp else: return if not token: token = request.headers.get("Authorization", None) if not token: resp = jsonify(message="Authorization required") resp.status_code = 401 return resp token = token.split() if token[0] != "Bearer" or len(token) > 2: resp = jsonify(message="Malformed token") resp.status_code = 400 return resp token = token[1] try: tjwss = TimedJSONWebSignatureSerializer( secret_key=current_app.config["SECRET_KEY"], expires_in=3600, algorithm_name="HS256") payload = tjwss.loads(token) except SignatureExpired: resp = jsonify(message="Token expired") resp.status_code = 401 return resp except BadSignature: resp = jsonify(message="Malformed token signature") resp.status_code = 401 return resp user = users.get(name=payload["uid"]) if not user or not user.admin: resp = jsonify(message="Authorization required") resp.status_code = 401 return resp
def test_upd_user(self): _add_test_user("testuser") u = users.get(name="testuser") u.first_name = "Notatest" u.last_name = "" u.update(newpasswd="mypass") u = users.get(name="testuser") self.assertEqual(u.first_name, "Notatest") self.assertIn(u.last_name, ["", None]) self.assertTrue(u.verify_passwd("mypass"))
def post(self): data = request.get_json()["ssh_key"] key = {"user": data["user"], "key": data["key"]} user = users.get(name=key["user"]) ssh_path = "/home/{0}/.ssh".format(data["user"]) akeys_path = os.path.join(ssh_path, "authorized_keys") if not os.path.exists(ssh_path): os.makedirs(ssh_path) os.chown(ssh_path, user.uid, 100) os.chmod(ssh_path, 0o700) if not os.path.exists(akeys_path): with open(akeys_path, "w") as f: f.write(data["key"]) if not data["key"].endswith("\n"): f.write("\n") if len(data["key"].split()) == 3: key["id"] = key["user"]+"-"+data["key"].split()[-1] else: key["id"] = key["user"]+"-"+data["key"].split()[1][:10] os.chown(akeys_path, user.uid, 100) os.chmod(akeys_path, 0o600) else: with open(akeys_path, "r+") as f: fc = f.read() if fc and not fc.endswith("\n"): f.write("\n") f.write(data["key"]) if not data["key"].endswith("\n"): f.write("\n") f.seek(0) if len(data["key"].split()) == 3: key["id"] = key["user"]+"-"+data["key"].split()[-1] else: key["id"] = key["user"]+"-"+data["key"].split()[1][:10] return jsonify(ssh_key=key)
def verify(): if config.get("genesis", "anonymous"): return token = request.headers.get("Authorization", None) if not token: resp = jsonify(message="Authorization required") resp.status_code = 401 return resp token = token.split() if token[0] != "Bearer" or len(token) > 2: resp = jsonify(message="Malformed token") resp.status_code = 400 return resp token = token[1] try: tjwss = TimedJSONWebSignatureSerializer(secret_key=current_app.config["SECRET_KEY"], expires_in=3600, algorithm_name="HS256") payload = tjwss.loads(token) except SignatureExpired: resp = jsonify(message="Token expired") resp.status_code = 401 return resp except BadSignature: resp = jsonify(message="Malformed token signature") resp.status_code = 401 return resp user = users.get(name=payload["uid"]) if not user or not user.admin: resp = jsonify(message="Authorization required") resp.status_code = 401 return resp
def remove(self): """Delete domain.""" if self.name in [x.domain for x in users.get()]: emsg = "A user is still using this domain" raise errors.InvalidConfigError(emsg) signals.emit("domains", "pre_remove", self) conns.LDAP.delete_s(self.ldap_id) signals.emit("domains", "post_remove", self)
def delete_user(name): """Delete an arkOS LDAP user""" try: u = users.get(name=name) u.delete() logger.success('ctl:usr:delete', 'Deleted {0}'.format(name)) except Exception as e: raise CLIException(str(e))
def get(self, id): u = users.get(id) if id and not u: abort(404) if isinstance(u, users.User): return jsonify(user=u.serialized) else: return jsonify(users=[x.serialized for x in u])
def get(self, id): u = users.get(id) if id and not u: abort(404) if type(u) == list: return jsonify(users=[x.as_dict() for x in u]) else: return jsonify(user=u.as_dict())
def passwd(name, password): """Change an arkOS LDAP user password""" try: u = users.get(name=name) u.update(password) logger.success('ctl:usr:passwd', 'Password changed for {0}'.format(name)) except Exception as e: raise CLIException(str(e))
def delete(self, id): u = users.get(id) if not u: abort(404) try: u.delete() except errors.InvalidConfigError as e: return jsonify(errors={"msg": str(e)}), 422 return Response(status=204)
def delete(self, id): u = users.get(id) if not u: abort(404) try: u.delete() except Exception, e: resp = jsonify(message="User couldn't be deleted: %s" % str(e)) resp.status_code = 422 return resp
def test_add_user(self): _add_test_user("testuser") u = users.get(name="testuser") self.assertIsNotNone(u) self.assertEqual(u.name, "testuser") self.assertEqual(u.first_name, "Test") self.assertEqual(u.last_name, "User") self.assertEqual(u.domain, "localhost") self.assertTrue(u.admin) self.assertFalse(u.sudo)
def get_refresh_token(): token = request.headers.get("Authorization", None) if not token: resp = jsonify(message="Authorization required") resp.status_code = 401 return resp token = token.split()[1] tjwss = TimedJSONWebSignatureSerializer(secret_key=current_app.config["SECRET_KEY"], expires_in=3600, algorithm_name="HS256") payload = tjwss.loads(token) user = users.get(name=payload["uid"]) return jsonify(token=create_token(user))
def mod_user(name, domain, first_name, last_name, admin, sudo): """Edit an arkOS LDAP user""" try: u = users.get(name=name) u.domain = domain or u.domain u.first_name = first_name or u.first_name u.last_name = last_name if last_name is not None else u.last_name u.admin = admin if admin is not None else u.admin u.sudo = sudo if sudo is not None else u.sudo u.update() logger.success('ctl:usr:mod', 'Modified {0}'.format(name)) except Exception as e: raise CLIException(str(e))
def put(self, id): data = json.loads(request.data)["user"] u = users.get(id) if not u: abort(404) u.first_name = data["first_name"] u.last_name = data["last_name"] u.domain = data["domain"] u.admin = data["admin"] u.sudo = data["sudo"] try: u.update(data.get("passwd")) except Exception, e: resp = jsonify(message="User couldn't be updated: %s" % str(e)) resp.status_code = 422 return resp
def get_token(): data = request.get_json() user, pwd = data.get("username"), data.get("password") if config.get("genesis", "anonymous"): user = AnonymousUser() else: user = users.get(name=user) if user and not user.admin: resp = jsonify(message="Not an admin user") resp.status_code = 401 return resp elif user and user.verify_passwd(pwd): return jsonify(token=create_token(user)) else: resp = jsonify(message="Invalid credentials") resp.status_code = 401 return resp
def get_token(): """Get a new API token.""" data = request.get_json() user, pwd = data.get("username", ""), data.get("password", "") if config.get("genesis", "anonymous"): user = AnonymousUser() else: user = users.get(name=user) if user and not user.admin: resp = jsonify(message="Not an admin user") resp.status_code = 401 return resp elif user and user.verify_passwd(pwd): return jsonify(token=create_token(user)) else: resp = jsonify(message="Invalid credentials") resp.status_code = 401 return resp
def put(self, id): data = request.get_json()["user"] u = users.get(id) if not u: abort(404) try: u.first_name = data["first_name"] u.last_name = data["last_name"] u.domain = data["domain"] u.admin = data["admin"] u.sudo = data["sudo"] u.mail = [str(x) for x in data["mail_addresses"]] u.update(data.get("passwd")) except KeyError as e: raise errors.InvalidConfigError(str(e)) except errors.InvalidConfigError as e: return jsonify(errors={"msg": str(e)}), 422 return jsonify(user=u.serialized)
def get_refresh_token(): """Refresh an existing API token.""" token = request.get_json().get("token", None) if not token: resp = jsonify(message="Authorization required") resp.status_code = 401 return resp v = verify(token) if v: return v if config.get("genesis", "anonymous"): user = AnonymousUser() else: tjwss = TimedJSONWebSignatureSerializer( secret_key=current_app.config["SECRET_KEY"], expires_in=3600, algorithm_name="HS256") payload = tjwss.loads(token) user = users.get(name=payload["uid"]) return jsonify(token=create_token(user))
def list_users(): """List users""" try: data = [x.serialized for x in users.get()] for x in data: click.echo( click.style(x["name"], fg="white", bold=True) + click.style(" ({0})".format(x["id"]), fg="green")) click.echo( click.style(" * Name: ", fg="yellow") + x["first_name"] + (" " + x["last_name"] if x["last_name"] else "")) click.echo( click.style(" * Mail Addresses: ", fg="yellow") + ", ".join(x["mail_addresses"])) click.echo( click.style(" * Types: ", fg="yellow") + ", ".join([ y for y in [ "sudo" if x["sudo"] else None, "admin" if x["admin"] else None ] if y ])) except Exception as e: raise CLIException(str(e))
def remove(self): if self.name in [x.domain for x in users.get()]: raise Exception("A user is still using this domain") signals.emit("domains", "pre_remove", self) conns.LDAP.delete_s("virtualdomain=%s,ou=domains,%s" % (self.name,self.rootdn)) signals.emit("domains", "post_remove", self)
def test_auth_success(self): _add_test_user("testuser") u = users.get(name="testuser") self.assertTrue(u.verify_passwd("testpass"))
def test_auth_fail(self): _add_test_user("testuser") u = users.get(name="testuser") self.assertFalse(u.verify_passwd("falsepass"))
def test_del_user(self): _add_test_user("testuser") u = users.get(name="testuser") u.delete() self.assertIsNone(users.get(name="testuser"))