def check_access(session, actor, target): return ( actor.name == target.name or user_is_user_admin(session, actor) or (target.role_user and can_manage_role_user(session, actor, tuser=target)) or (target.is_service_account and can_manage_service_account(session, target, actor)) )
def post(self, group_id=None, name=None, account_id=None, accountname=None): group = Group.get(self.session, group_id, name) if not group: return self.notfound() service_account = ServiceAccount.get(self.session, account_id, accountname) if not service_account: return self.notfound() if not can_manage_service_account(self.session, service_account, self.current_user): return self.forbidden() form = ServiceAccountEditForm(self.request.arguments, obj=service_account) if not form.validate(): return self.render( "service-account-edit.html", service_account=service_account, group=group, form=form, alerts=self.get_form_alerts(form.errors) ) try: edit_service_account(self.session, self.current_user, service_account, form.data["description"], form.data["machine_set"]) except BadMachineSet as e: form.machine_set.errors.append(str(e)) return self.render( "service-account-edit.html", service_account=service_account, group=group, form=form, alerts=self.get_form_alerts(form.errors) ) return self.redirect("/groups/{}/service/{}".format( group.name, service_account.user.username))
def check_access(session, actor, target): # type: (Session, User, User) -> bool return ( actor.name == target.name or (target.role_user and can_manage_role_user(session, actor, tuser=target)) or (target.is_service_account and can_manage_service_account(session, target, actor)) )
def get_service_account_view_template_vars(session, actor, user, group, graph): ret = get_user_view_template_vars(session, actor, user, graph) ret.update(get_group_view_template_vars(session, actor, group, graph)) ret["can_control"] = can_manage_service_account(session, user=actor, tuser=user) ret["log_entries"] = sorted(set(get_log_entries_by_user(session, user) + group.my_log_entries()), key=lambda x: x.log_time, reverse=True) return ret
def check_access(session, actor, target): # type: (Session, User, User) -> bool return (actor.name == target.name or (target.role_user and can_manage_role_user(session, actor, tuser=target)) or (target.is_service_account and can_manage_service_account(session, target, actor)))
def get_user_view_template_vars(session, actor, user, graph): # type: (Session, User, User, GroupGraph) -> Dict[str, Any] # TODO(cbguder): get around circular dependencies from grouper.fe.handlers.user_disable import UserDisable from grouper.fe.handlers.user_enable import UserEnable ret = {} # type: Dict[str, Any] if user.is_service_account: ret["can_control"] = can_manage_service_account( session, user.service_account, actor ) or user_is_user_admin(session, actor) ret["can_disable"] = ret["can_control"] ret["can_enable"] = user_is_user_admin(session, actor) ret["can_enable_preserving_membership"] = user_is_user_admin(session, actor) ret["account"] = user.service_account else: ret["can_control"] = user.name == actor.name or user_is_user_admin(session, actor) ret["can_disable"] = UserDisable.check_access(session, actor, user) ret["can_enable_preserving_membership"] = UserEnable.check_access(session, actor, user) ret["can_enable"] = UserEnable.check_access_without_membership(session, actor, user) if user.id == actor.id: ret["num_pending_group_requests"] = user_requests_aggregate(session, actor).count() _, ret["num_pending_perm_requests"] = get_requests( session, status="pending", limit=1, offset=0, owner=actor ) else: ret["num_pending_group_requests"] = None ret["num_pending_perm_requests"] = None try: user_md = graph.get_user_details(user.name) except NoSuchUser: # Either user is probably very new, so they have no metadata yet, or # they're disabled, so we've excluded them from the in-memory graph. user_md = {} shell_metadata = get_user_metadata_by_key(session, user.id, USER_METADATA_SHELL_KEY) ret["shell"] = shell_metadata.data_value if shell_metadata else "No shell configured" github_username = get_user_metadata_by_key(session, user.id, USER_METADATA_GITHUB_USERNAME_KEY) ret["github_username"] = github_username.data_value if github_username else "(Unset)" ret["open_audits"] = user_open_audits(session, user) group_edge_list = get_groups_by_user(session, user) if user.enabled else [] ret["groups"] = [ {"name": g.name, "type": "Group", "role": ge._role} for g, ge in group_edge_list ] ret["passwords"] = user_passwords(session, user) ret["public_keys"] = get_public_keys_of_user(session, user.id) ret["log_entries"] = get_log_entries_by_user(session, user) ret["user_tokens"] = user.tokens if user.is_service_account: service_account = user.service_account ret["permissions"] = service_account_permissions(session, service_account) else: ret["permissions"] = user_md.get("permissions", []) for permission in ret["permissions"]: permission["granted_on"] = datetime.fromtimestamp(permission["granted_on"]) return ret
def check_access(session, actor, target): return (actor.name == target.name or user_is_user_admin(session, actor) or (target.role_user and can_manage_role_user(session, actor, tuser=target)) or (target.is_service_account and can_manage_service_account(session, target, actor)))
def get_user_view_template_vars(session, actor, user, graph): # TODO(cbguder): get around circular dependencies from grouper.fe.handlers.user_disable import UserDisable from grouper.fe.handlers.user_enable import UserEnable ret = {} if user.is_service_account: ret["can_control"] = ( can_manage_service_account(session, user.service_account, actor) or user_is_user_admin(session, actor) ) ret["can_disable"] = ret["can_control"] ret["can_enable"] = user_is_user_admin(session, actor) ret["account"] = user.service_account else: ret["can_control"] = (user.name == actor.name or user_is_user_admin(session, actor)) ret["can_disable"] = UserDisable.check_access(session, actor, user) ret["can_enable"] = UserEnable.check_access(session, actor, user) if user.id == actor.id: ret["num_pending_group_requests"] = user_requests_aggregate(session, actor).count() _, ret["num_pending_perm_requests"] = get_requests_by_owner(session, actor, status='pending', limit=1, offset=0) else: ret["num_pending_group_requests"] = None ret["num_pending_perm_requests"] = None try: user_md = graph.get_user_details(user.name) except NoSuchUser: # Either user is probably very new, so they have no metadata yet, or # they're disabled, so we've excluded them from the in-memory graph. user_md = {} shell = (get_user_metadata_by_key(session, user.id, USER_METADATA_SHELL_KEY).data_value if get_user_metadata_by_key(session, user.id, USER_METADATA_SHELL_KEY) else "No shell configured") ret["shell"] = shell ret["open_audits"] = user_open_audits(session, user) group_edge_list = get_groups_by_user(session, user) if user.enabled else [] ret["groups"] = [{'name': g.name, 'type': 'Group', 'role': ge._role} for g, ge in group_edge_list] ret["passwords"] = user_passwords(session, user) ret["public_keys"] = get_public_keys_of_user(session, user.id) for key in ret["public_keys"]: key.tags = get_public_key_tags(session, key) key.pretty_permissions = ["{} ({})".format(perm.name, perm.argument if perm.argument else "unargumented") for perm in get_public_key_permissions(session, key)] ret["log_entries"] = get_log_entries_by_user(session, user) ret["user_tokens"] = user.tokens if user.is_service_account: service_account = user.service_account ret["permissions"] = service_account_permissions(session, service_account) else: ret["permissions"] = user_md.get('permissions', []) return ret
def get_service_account_view_template_vars(session, actor, user, group, graph): ret = get_user_view_template_vars(session, actor, user, graph) ret.update(get_group_view_template_vars(session, actor, group, graph)) ret["can_control"] = can_manage_service_account(session, user=actor, tuser=user) ret["log_entries"] = sorted( set(get_log_entries_by_user(session, user) + group.my_log_entries()), key=lambda x: x.log_time, reverse=True) return ret
def post(self, group_id=None, name=None, account_id=None, accountname=None): group = Group.get(self.session, group_id, name) if not group: return self.notfound() service_account = ServiceAccount.get(self.session, account_id, accountname) if not service_account: return self.notfound() if not can_manage_service_account(self.session, service_account, self.current_user): return self.forbidden() form = ServiceAccountEditForm(self.request.arguments, obj=service_account) if not form.validate(): return self.render( "service-account-edit.html", service_account=service_account, group=group, form=form, alerts=self.get_form_alerts(form.errors), ) try: edit_service_account( self.session, self.current_user, service_account, form.data["description"], form.data["machine_set"], ) except BadMachineSet as e: form.machine_set.errors.append(str(e)) return self.render( "service-account-edit.html", service_account=service_account, group=group, form=form, alerts=self.get_form_alerts(form.errors), ) return self.redirect("/groups/{}/service/{}".format( group.name, service_account.user.username))
def get(self, group_id=None, name=None, account_id=None, accountname=None): group = Group.get(self.session, group_id, name) if not group: return self.notfound() service_account = ServiceAccount.get(self.session, account_id, accountname) if not service_account: return self.notfound() if not can_manage_service_account(self.session, service_account, self.current_user): return self.forbidden() form = ServiceAccountEditForm(obj=service_account) self.render( "service-account-edit.html", service_account=service_account, group=group, form=form )
def get(self, *args: Any, **kwargs: Any) -> None: name = self.get_path_argument("name") accountname = self.get_path_argument("accountname") group = Group.get(self.session, name=name) if not group: return self.notfound() service_account = ServiceAccount.get(self.session, name=accountname) if not service_account: return self.notfound() if not can_manage_service_account(self.session, service_account, self.current_user): return self.forbidden() form = ServiceAccountEditForm(obj=service_account) self.render( "service-account-edit.html", service_account=service_account, group=group, form=form )
def get(self, group_id=None, name=None, account_id=None, accountname=None): group = Group.get(self.session, group_id, name) if not group: return self.notfound() service_account = ServiceAccount.get(self.session, account_id, accountname) if not service_account: return self.notfound() if not can_manage_service_account(self.session, service_account, self.current_user): return self.forbidden() form = ServiceAccountEditForm(obj=service_account) self.render("service-account-edit.html", service_account=service_account, group=group, form=form)
def check_access(session, actor, target): return actor.name == target.name or ( target.role_user and can_manage_service_account(session, actor, tuser=target) )
def check_access(session, actor, target): if user_has_permission(session, actor, USER_ADMIN): return True return can_manage_service_account(session, target, actor)
def test_service_accounts( session, standard_graph, graph, users, groups, permissions # noqa: F811 ): # Create a service account. service_account = ServiceAccount.get(session, name="*****@*****.**") assert service_account.description == "some service account" assert service_account.machine_set == "some machines" assert service_account.user.name == "*****@*****.**" assert service_account.user.enabled == True assert service_account.user.is_service_account == True accounts = get_service_accounts(session, groups["team-sre"]) assert len(accounts) == 1 assert accounts[0].user.name == "*****@*****.**" assert is_service_account(session, service_account.user) # Duplicates should raise an exception. with pytest.raises(DuplicateServiceAccount): create_service_account(session, users["*****@*****.**"], "*****@*****.**", "dup", "dup", groups["team-sre"]) # zorkian should be able to manage the account, as should gary, but oliver (not a member of the # group) should not. assert can_manage_service_account(session, service_account, users["*****@*****.**"]) assert can_manage_service_account(session, service_account, users["*****@*****.**"]) assert not can_manage_service_account(session, service_account, users["*****@*****.**"]) # Check that the user appears in the graph. graph.update_from_db(session) metadata = graph.user_metadata["*****@*****.**"] assert metadata["enabled"] assert metadata["service_account"]["description"] == "some service account" assert metadata["service_account"]["machine_set"] == "some machines" assert metadata["service_account"]["owner"] == "team-sre" group_details = graph.get_group_details("team-sre") assert group_details["service_accounts"] == ["*****@*****.**"] # Grant a permission to the service account and check it in the graph. grant_permission_to_service_account(session, service_account, permissions["team-sre"], "*") graph.update_from_db(session) user_details = graph.get_user_details("*****@*****.**") assert user_details["permissions"][0]["permission"] == "team-sre" assert user_details["permissions"][0]["argument"] == "*" # Diabling the service account should remove the link to the group. disable_service_account(session, users["*****@*****.**"], service_account) assert service_account.user.enabled == False assert get_service_accounts(session, groups["team-sre"]) == [] # The user should also be gone from the graph and have its permissions removed. graph.update_from_db(session) group_details = graph.get_group_details("team-sre") assert "service_accounts" not in group_details metadata = graph.user_metadata["*****@*****.**"] assert not metadata["enabled"] assert "owner" not in metadata["service_account"] user_details = graph.get_user_details("*****@*****.**") assert user_details["permissions"] == [] # We can re-enable and attach to a different group. new_group = groups["security-team"] enable_service_account(session, users["*****@*****.**"], service_account, new_group) assert service_account.user.enabled == True assert get_service_accounts(session, groups["team-sre"]) == [] accounts = get_service_accounts(session, new_group) assert len(accounts) == 1 assert accounts[0].user.name == "*****@*****.**" # Check that this is reflected in the graph and the user has no permissions. graph.update_from_db(session) group_details = graph.get_group_details("security-team") assert group_details["service_accounts"] == ["*****@*****.**"] metadata = graph.user_metadata["*****@*****.**"] assert metadata["service_account"]["owner"] == "security-team" user_details = graph.get_user_details("*****@*****.**") assert user_details["permissions"] == []
def check_access(session, actor, target): return actor.name == target.name or (target.role_user and can_manage_service_account( session, actor, tuser=target))
def get_user_view_template_vars(session, actor, user, graph): # type: (Session, User, User, GroupGraph) -> Dict[str, Any] # TODO(cbguder): get around circular dependencies from grouper.fe.handlers.user_disable import UserDisable from grouper.fe.handlers.user_enable import UserEnable ret = {} # type: Dict[str, Any] if user.is_service_account: ret["can_control"] = can_manage_service_account( session, user.service_account, actor ) or user_is_user_admin(session, actor) ret["can_disable"] = ret["can_control"] ret["can_enable"] = user_is_user_admin(session, actor) ret["can_enable_preserving_membership"] = user_is_user_admin(session, actor) ret["account"] = user.service_account else: ret["can_control"] = user.name == actor.name or user_is_user_admin(session, actor) ret["can_disable"] = UserDisable.check_access(session, actor, user) ret["can_enable_preserving_membership"] = UserEnable.check_access(session, actor, user) ret["can_enable"] = UserEnable.check_access_without_membership(session, actor, user) if user.id == actor.id: ret["num_pending_group_requests"] = user_requests_aggregate(session, actor).count() _, ret["num_pending_perm_requests"] = get_requests( session, status="pending", limit=1, offset=0, owner=actor ) else: ret["num_pending_group_requests"] = None ret["num_pending_perm_requests"] = None try: user_md = graph.get_user_details(user.name) except NoSuchUser: # Either user is probably very new, so they have no metadata yet, or # they're disabled, so we've excluded them from the in-memory graph. user_md = {} shell = ( get_user_metadata_by_key(session, user.id, USER_METADATA_SHELL_KEY).data_value if get_user_metadata_by_key(session, user.id, USER_METADATA_SHELL_KEY) else "No shell configured" ) ret["shell"] = shell github_username = get_user_metadata_by_key(session, user.id, USER_METADATA_GITHUB_USERNAME_KEY) ret["github_username"] = github_username.data_value if github_username else "(Unset)" ret["open_audits"] = user_open_audits(session, user) group_edge_list = get_groups_by_user(session, user) if user.enabled else [] ret["groups"] = [ {"name": g.name, "type": "Group", "role": ge._role} for g, ge in group_edge_list ] ret["passwords"] = user_passwords(session, user) ret["public_keys"] = get_public_keys_of_user(session, user.id) ret["log_entries"] = get_log_entries_by_user(session, user) ret["user_tokens"] = user.tokens if user.is_service_account: service_account = user.service_account ret["permissions"] = service_account_permissions(session, service_account) else: ret["permissions"] = user_md.get("permissions", []) for permission in ret["permissions"]: permission["granted_on"] = datetime.fromtimestamp(permission["granted_on"]) return ret
def test_service_accounts(setup): # type: (SetupTest) -> None """Tests remaining non-usecase service account functions.""" with setup.transaction(): setup.create_service_account("*****@*****.**", "team-sre", "some machines", "some service account") setup.add_user_to_group("*****@*****.**", "team-sre", "owner") setup.add_user_to_group("*****@*****.**", "admins") setup.grant_permission_to_group(USER_ADMIN, "", "admins") setup.add_user_to_group("*****@*****.**", "team-sre") setup.create_user("*****@*****.**") setup.grant_permission_to_service_account("team-sre", "*", "*****@*****.**") setup.create_group("security-team") group = Group.get(setup.session, name="team-sre") assert group accounts = get_service_accounts(setup.session, group) assert len(accounts) == 1 service_account = accounts[0] assert service_account.user.name == "*****@*****.**" assert service_account.user.is_service_account # zorkian should be able to manage the account, as should gary, but oliver (not a member of the # group) should not. zorkian_user = User.get(setup.session, name="*****@*****.**") assert zorkian_user gary_user = User.get(setup.session, name="*****@*****.**") assert gary_user oliver_user = User.get(setup.session, name="*****@*****.**") assert oliver_user assert can_manage_service_account(setup.session, service_account, zorkian_user) assert can_manage_service_account(setup.session, service_account, gary_user) assert not can_manage_service_account(setup.session, service_account, oliver_user) # Diabling the service account should remove the link to the group. disable_service_account(setup.session, zorkian_user, service_account) assert service_account.user.enabled == False assert get_service_accounts(setup.session, group) == [] # The user should also be gone from the graph and have its permissions removed. setup.graph.update_from_db(setup.session) group_details = setup.graph.get_group_details("team-sre") assert "service_accounts" not in group_details metadata = setup.graph.user_metadata["*****@*****.**"] assert not metadata["enabled"] assert "owner" not in metadata["service_account"] user_details = setup.graph.get_user_details("*****@*****.**") assert user_details["permissions"] == [] # We can re-enable and attach to a different group. new_group = Group.get(setup.session, name="security-team") assert new_group enable_service_account(setup.session, zorkian_user, service_account, new_group) assert service_account.user.enabled == True assert get_service_accounts(setup.session, group) == [] accounts = get_service_accounts(setup.session, new_group) assert len(accounts) == 1 assert accounts[0].user.name == "*****@*****.**" # Check that this is reflected in the graph and the user has no permissions. setup.graph.update_from_db(setup.session) group_details = setup.graph.get_group_details("security-team") assert group_details["service_accounts"] == ["*****@*****.**"] metadata = setup.graph.user_metadata["*****@*****.**"] assert metadata["service_account"]["owner"] == "security-team" user_details = setup.graph.get_user_details("*****@*****.**") assert user_details["permissions"] == []
def check_access(session: Session, actor: User, target: ServiceAccount) -> bool: if user_has_permission(session, actor, USER_ADMIN): return True return can_manage_service_account(session, target, actor)
def get_user_view_template_vars(session, actor, user, graph): # TODO(cbguder): get around circular dependencies from grouper.fe.handlers.user_disable import UserDisable from grouper.fe.handlers.user_enable import UserEnable ret = {} if user.is_service_account: ret["can_control"] = (can_manage_service_account( session, user.service_account, actor) or user_is_user_admin(session, actor)) ret["can_disable"] = ret["can_control"] ret["can_enable"] = user_is_user_admin(session, actor) ret["account"] = user.service_account else: ret["can_control"] = (user.name == actor.name or user_is_user_admin(session, actor)) ret["can_disable"] = UserDisable.check_access(session, actor, user) ret["can_enable"] = UserEnable.check_access(session, actor, user) if user.id == actor.id: ret["num_pending_group_requests"] = user_requests_aggregate( session, actor).count() _, ret["num_pending_perm_requests"] = get_requests_by_owner( session, actor, status='pending', limit=1, offset=0) else: ret["num_pending_group_requests"] = None ret["num_pending_perm_requests"] = None try: user_md = graph.get_user_details(user.name) except NoSuchUser: # Either user is probably very new, so they have no metadata yet, or # they're disabled, so we've excluded them from the in-memory graph. user_md = {} shell = (get_user_metadata_by_key(session, user.id, USER_METADATA_SHELL_KEY).data_value if get_user_metadata_by_key(session, user.id, USER_METADATA_SHELL_KEY) else "No shell configured") ret["shell"] = shell ret["open_audits"] = user_open_audits(session, user) group_edge_list = get_groups_by_user(session, user) if user.enabled else [] ret["groups"] = [{ 'name': g.name, 'type': 'Group', 'role': ge._role } for g, ge in group_edge_list] ret["passwords"] = user_passwords(session, user) ret["public_keys"] = get_public_keys_of_user(session, user.id) for key in ret["public_keys"]: key.tags = get_public_key_tags(session, key) key.pretty_permissions = [ "{} ({})".format( perm.name, perm.argument if perm.argument else "unargumented") for perm in get_public_key_permissions(session, key) ] ret["log_entries"] = get_log_entries_by_user(session, user) ret["user_tokens"] = user.tokens if user.is_service_account: service_account = user.service_account ret["permissions"] = service_account_permissions( session, service_account) else: ret["permissions"] = user_md.get('permissions', []) return ret