Skip to content
Snippets Groups Projects
Commit fddf40ad authored by Diana Gudu's avatar Diana Gudu
Browse files

Merge branch 'adapt-to-bwidm' into 'master'

Adapt to bwidm

See merge request feudal/feudalAdapterLdf!85
parents 22b35332 36ae67f3
No related branches found
No related tags found
1 merge request!85Adapt to bwidm
......@@ -72,7 +72,9 @@ class User:
"filename",
fallback="/tmp/userinfo/userinfo.json",
)
dirname = CONFIG.get("verbose-info-plugin", "dirname", fallback="/tmp/userinfo")
dirname = CONFIG.get(
"verbose-info-plugin", "dirname", fallback="/tmp/userinfo"
)
try:
os.mkdir(dirname)
os.chmod(dirname, 0o0777)
......@@ -100,7 +102,9 @@ class User:
backend.Group(grp) for grp in self.data.groups # type:ignore
]
if CONFIG.get("ldf_adapter", "backend_supports_preferring_existing_user", fallback=False):
if CONFIG.get(
"ldf_adapter", "backend_supports_preferring_existing_user", fallback=False
):
logger.debug("trying to update user from existing")
if self.service_user.exists():
self.update_username_from_existing()
......@@ -225,7 +229,10 @@ class User:
logger.warning(
"Assurance checking is disabled: Users with ANY assurance will be authorised"
)
if not CONFIG.get("assurance", "skip", fallback="No") == "Yes, do as I say!":
if (
not CONFIG.get("assurance", "skip", fallback="No")
== "Yes, do as I say!"
):
if not self.assurance_verifier()(self.data.assurance):
raise Rejection(
message="Your assurance level is insufficient to access this resource"
......@@ -237,10 +244,17 @@ class User:
return self.deploy()
elif target == "not_deployed":
if not CONFIG.get("assurance", "skip", fallback="No") == "Yes, do as I say!":
if (
not CONFIG.get("assurance", "skip", fallback="No")
== "Yes, do as I say!"
):
if not self.assurance_verifier()(self.data.assurance):
if not CONFIG.getboolean("assurance", "verified_undeploy", fallback=False):
logger.warning("Assurance level is insufficient. Undeploying anyway.")
if not CONFIG.getboolean(
"assurance", "verified_undeploy", fallback=False
):
logger.warning(
"Assurance level is insufficient. Undeploying anyway."
)
else:
raise Rejection(
message="Your assurance level is insufficient to access this resource"
......@@ -285,7 +299,9 @@ class User:
what_changed += "."
if new_credentials:
what_changed += " Credentials {} were activated.".format(",".join(new_credentials))
what_changed += " Credentials {} were activated.".format(
",".join(new_credentials)
)
return Deployed(credentials=self.credentials, message=what_changed)
......@@ -445,13 +461,15 @@ class User:
is_new_user = not self.service_user.exists()
unique_id = self.data.unique_id
if is_new_user:
unique_id = self.data.unique_id
username = self.data.username
primary_group_name = None
primary_group_name = self.data.primary_group
# Raise question in case of existing username in case we're interactive
if CONFIG.getboolean("ldf_adapter", "interactive", fallback=False): # interactive
if CONFIG.getboolean(
"ldf_adapter", "interactive", fallback=False
): # interactive
logger.debug("interactive mode")
if self.service_user.name_taken(username):
logger.info(
......@@ -464,9 +482,10 @@ class User:
else: # non-interactive
logger.debug("noninteractive mode")
username_mode = CONFIG.get("username_generator", "mode", fallback="friendly")
username_mode = CONFIG.get(
"username_generator", "mode", fallback="friendly"
)
logger.debug(f"username_mode: {username_mode}")
primary_group_name = self.data.primary_group
pool_prefix = CONFIG.get(
"username_generator", "pool_prefix", fallback=primary_group_name
)
......@@ -488,6 +507,9 @@ class User:
logger.info(f"Chose username '{proposed_name}' for {unique_id}")
logger.debug(f"Primary Group Name: {primary_group_name}")
logger.debug(f"Primary Group from userinfo: {self.data.primary_group}")
# Sanity check to ensure user has a primary group:
if primary_group_name is None:
config_file_name = globalconfig.info["config_files_read"]
......@@ -502,8 +524,8 @@ class User:
self.service_user.create()
else: # The user exists
# Update service_user.name if unique_id already points to a username:
username = self.data.username
logger.info("User {username} for '{unique_id}' already exists.".format(**self.data))
username = self.service_user.get_username()
logger.info(f"User {username} for '{self.data.unique_id}' already exists.")
logger.debug(f"This is a new user: {is_new_user}")
......@@ -518,7 +540,9 @@ class User:
existing_username = self.service_user.get_username()
if existing_username is not None:
if hasattr(self.service_user, "set_username"):
logger.debug(f"Setting username to {existing_username} ({self.data.unique_id})")
logger.debug(
f"Setting username to {existing_username} ({self.data.unique_id})"
)
self.service_user.set_username(existing_username)
logger.debug(f"Found an existing username: {existing_username}")
except AttributeError:
......@@ -534,7 +558,9 @@ class User:
"""
if self.service_user.exists():
self.service_user.username = self.service_user.get_username()
logger.info(f"Deleting user '{self.service_user.username}' ({self.data.unique_id})")
logger.info(
f"Deleting user '{self.service_user.username}' ({self.data.unique_id})"
)
# bwIDM requires prior removal of the user, because ssh-key removal triggers an
# asyncronous process. If user is removed during that, the user might be only partially
# removed...
......@@ -546,7 +572,9 @@ class User:
self.service_user.delete()
return True
else:
logger.info(f"No user existed for {self.data.unique_id} did exist. Nothing to do.")
logger.info(
f"No user existed for {self.data.unique_id} did exist. Nothing to do."
)
return False
def ensure_suspended(self):
......@@ -558,7 +586,9 @@ class User:
if hasattr(self.service_user, "suspend"):
self.service_user.suspend()
return True
logger.debug(f"User {self.data.unique_id} in state {status.state}. Suspending not allowed.")
logger.debug(
f"User {self.data.unique_id} in state {status.state}. Suspending not allowed."
)
return False
def ensure_limited(self):
......@@ -570,7 +600,9 @@ class User:
if hasattr(self.service_user, "limit"):
self.service_user.limit()
return True
logger.debug(f"User {self.data.unique_id} in state {status.state}. Limiting not allowed.")
logger.debug(
f"User {self.data.unique_id} in state {status.state}. Limiting not allowed."
)
return False
def ensure_resumed(self):
......@@ -582,7 +614,9 @@ class User:
if hasattr(self.service_user, "resume"):
self.service_user.resume()
return True
logger.debug(f"User {self.data.unique_id} in state {status.state}. Resuming not allowed.")
logger.debug(
f"User {self.data.unique_id} in state {status.state}. Resuming not allowed."
)
return False
def ensure_unlimited(self):
......@@ -594,7 +628,9 @@ class User:
if hasattr(self.service_user, "unlimit"):
self.service_user.unlimit()
return True
logger.debug(f"User {self.data.unique_id} in state {status.state}. Unlimit not allowed.")
logger.debug(
f"User {self.data.unique_id} in state {status.state}. Unlimit not allowed."
)
return False
def ensure_groups_exist(self):
......@@ -620,7 +656,9 @@ class User:
# problem with some backends
group_list = self.service_groups
if self.service_user.primary_group.name not in [grp.name for grp in self.service_groups]:
if self.service_user.primary_group.name not in [
grp.name for grp in self.service_groups
]:
group_list.append(self.service_user.primary_group)
if group_list[0].name is None:
......
......@@ -38,7 +38,9 @@ class BwIdmConnection:
config["backend.bwidm.auth"]["http_pass"],
)
if not CONFIG["backend.bwidm"].getboolean("log_outgoing_http_requests", fallback=False):
if not CONFIG["backend.bwidm"].getboolean(
"log_outgoing_http_requests", fallback=False
):
logging.getLogger("requests").setLevel(logging.CRITICAL)
logging.getLogger("werkzeug").setLevel(logging.CRITICAL)
logging.getLogger("urllib3").setLevel(logging.CRITICAL)
......@@ -61,9 +63,13 @@ class BwIdmConnection:
fail = kwargs.pop("fail", True)
url_fragments = map(str, url_fragments)
url_fragments = map(lambda frag: requests.utils.quote(frag, safe=""), url_fragments)
url_fragments = map(
lambda frag: requests.utils.quote(frag, safe=""), url_fragments
)
url = reduce(
lambda acc, frag: urljoin(acc, frag) if acc.endswith("/") else urljoin(acc + "/", frag),
lambda acc, frag: urljoin(acc, frag)
if acc.endswith("/")
else urljoin(acc + "/", frag),
url_fragments,
CONFIG["backend.bwidm"]["url"],
)
......@@ -73,7 +79,9 @@ class BwIdmConnection:
if fail:
if not rsp.ok:
logger.error("Server responded with: {}".format(rsp.content.decode("utf-8")))
logger.error(
"Server responded with: {}".format(rsp.content.decode("utf-8"))
)
rsp.raise_for_status()
return rsp
......@@ -111,7 +119,9 @@ class User:
def _is_active(self):
status = self.reg_info()["userStatus"]
logger.debug("User {} is {} on service BWIDM".format(self.info.unique_id, status))
logger.debug(
"User {} is {} on service BWIDM".format(self.info.unique_id, status)
)
return status == self.VALUE_USER_ACTIVE
def _is_registered(self):
......@@ -121,13 +131,17 @@ class User:
"""
# FIXME: Consider putting this request into the global user object (to reduce load on regapp)
ssn = CONFIG["backend.bwidm.service"]["name"]
registrations = BWIDM.get("external-reg", "find", "externalId", self.info.unique_id)
registrations = BWIDM.get(
"external-reg", "find", "externalId", self.info.unique_id
)
# find registrations
number_of_registrations = 0
try:
logger.debug("logging registrations to jsonlog")
jsonlogger.debug(
json.dumps(registrations.json, sort_keys=True, indent=4, separators=(",", ": "))
json.dumps(
registrations.json, sort_keys=True, indent=4, separators=(",", ": ")
)
)
except TypeError:
pass
......@@ -152,7 +166,9 @@ class User:
).json()
other_users_with_name = [
user for user in users_with_name if user["externalId"] != self.info.unique_id
user
for user in users_with_name
if user["externalId"] != self.info.unique_id
]
# logger.debug (F"other_users: {other_users_with_name}")
logger.debug(f"Found {len(other_users_with_name)} with same username")
......@@ -164,7 +180,9 @@ class User:
logger.error(
"Username '{}' is already used by\n {}".format(
self.info.username,
",\n ".join(map(lambda u: u["externalId"], other_users_with_name)),
",\n ".join(
map(lambda u: u["externalId"], other_users_with_name)
),
)
)
else:
......@@ -179,7 +197,8 @@ class User:
"""Safely convert a response to json"""
if resp.status_code != 200:
logger.debug(
"Error %d reading from remote: \n%s\n" % (resp.status_code, str(resp.text))
"Error %d reading from remote: \n%s\n"
% (resp.status_code, str(resp.text))
)
os._exit(1) # or raise or return None?
try:
......@@ -189,27 +208,27 @@ class User:
raise
return resp_json
full_username = None
username = None
bwidmOrgId = ""
resp = BWIDM.get("external-user", "find", "externalId", self.info.unique_id)
resp_json = safe_resp_conversion(resp)
try:
username = resp_json["attributeStore"]["urn:oid:0.9.2342.19200300.100.1.1"]
bwIdmOrgId = resp_json["attributeStore"]["http://bwidm.de/bwidmOrgId"]
full_username = f"{bwIdmOrgId}_{username}"
except KeyError as e:
logger.error("Error: I could not find the username in the database.")
logger.error(" Most likely the user is not registered for this service\n")
logger.error(f" {e}")
logger.error(json.dumps(resp_json, sort_keys=True, indent=4, separators=(",", ": ")))
logger.debug(f"Found existing username: {full_username}")
return full_username
logger.error(
json.dumps(resp_json, sort_keys=True, indent=4, separators=(",", ": "))
)
logger.debug(f"Returning username {username} (without prefix {bwIdmOrgId})")
return username
def set_username(self, username):
"""Update the internal representation of the user with the incoming username"""
logger.debug("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
self.force_username = username
logger.debug("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb")
def create(self):
"""Create or activate user."""
......@@ -218,7 +237,9 @@ class User:
BWIDM.get("external-user", "activate", "externalId", self.info.unique_id)
else:
logger.info("Creating user {unique_id}".format(**self.info))
BWIDM.post("external-user", "create", json={"externalId": self.info.unique_id})
BWIDM.post(
"external-user", "create", json={"externalId": self.info.unique_id}
)
def update(self):
# FIXME: Consider putting this request into the global user object (to reduce load on regapp)
......@@ -226,7 +247,9 @@ class User:
rsp = BWIDM.get("external-reg", "find", "externalId", ext_id)
try:
return next(filter(lambda reg: reg["registryStatus"] == "ACTIVE", rsp.json()))
return next(
filter(lambda reg: reg["registryStatus"] == "ACTIVE", rsp.json())
)
except StopIteration:
return {"lastReconcile": None}
......@@ -312,22 +335,23 @@ class User:
new_groups = [grp.reg_info(short=True) for grp in supplementary_groups]
new_groups += [self.primary_group.reg_info()]
NL = "\n "
logger.debug(
f"Groups according to BWIDM: {NL}{NL.join([g['name'] for g in current_groups])}"
)
# NL = "\n "
logger.debug(
f"Groups according to FEUDAL: {NL}{NL.join([g['name'] for g in new_groups])}"
f"Incoming groups: {NL}{NL.join([g['name'] for g in new_groups])}"
)
# Remove user from groups he should not be a member of
to_be_removed_from = [
g for g in current_groups if g["id"] not in (ng["id"] for ng in new_groups)
g
for g in current_groups
if g["id"] not in (ng["id"] for ng in new_groups)
]
# Only add user to groups she is not already a member of
to_be_added_to = [
g for g in new_groups if g["id"] not in (cg["id"] for cg in current_groups)
g
for g in new_groups
if g["id"] not in (cg["id"] for cg in current_groups)
]
if to_be_removed_from:
......@@ -402,7 +426,9 @@ class User:
"""
current_state = self.reg_info()
new_state = utils.dictmerge(current_state, state_updates)
utils.log_dictdiff(utils.dictdiff(current_state, new_state), log_function=logger.info)
utils.log_dictdiff(
utils.dictdiff(current_state, new_state), log_function=logger.info
)
for k in list(new_state):
if new_state[k] is None:
......@@ -422,7 +448,9 @@ class User:
jsonlogger.debug(f"current_state: {formatted_json}")
logger.debug(" logging new_to jsonlog")
formatted_json = json.dumps(new_state, sort_keys=True, indent=4, separators=(",", ": "))
formatted_json = json.dumps(
new_state, sort_keys=True, indent=4, separators=(",", ": ")
)
jsonlogger.debug(f"new state for regapp: {formatted_json}")
except:
pass
......@@ -430,7 +458,9 @@ class User:
def reg_info(self, json=True, **kwargs):
# FIXME: Cache this functions results!
rsp = BWIDM.get("external-user", "find", "externalId", self.info.unique_id, **kwargs)
rsp = BWIDM.get(
"external-user", "find", "externalId", self.info.unique_id, **kwargs
)
return rsp.json() if json else rsp.content
......@@ -443,7 +473,9 @@ class Group:
# CONFIG['backend.bwidm.service']['name']
return (
b"no such group"
not in BWIDM.get("group-admin", "find", "name", self.name, fail=False).content
not in BWIDM.get(
"group-admin", "find", "name", self.name, fail=False
).content
)
def create(self):
......@@ -453,7 +485,9 @@ class Group:
if self.name != rsp["name"]:
logger.warning(
"Groupname changed from {} to {} by BWIDM".format(self.name, rsp["name"])
"Groupname changed from {} to {} by BWIDM".format(
self.name, rsp["name"]
)
)
self.name = rsp["name"]
......
......@@ -98,7 +98,7 @@ def setup_logging():
else:
stream_handler.setLevel(loglevel_env)
logger.debug(f"Running: ")
logger.debug(f"Running: ----------------------------------------------------------------------------------------------------")
logger.debug(f' {" ".join(sys.argv)} ')
# JSON LOGGER
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment