def create_service_account(session, actor, name, description, machine_set, owner): # type: (Session, User, str, str, str, Group) -> ServiceAccount """Creates a service account and its underlying user. Also adds the service account to the list of accounts managed by the owning group. Throws: BadMachineSet: if some plugin rejected the machine set DuplicateServiceAccount: if a user with the given name already exists """ user = User(username=name, is_service_account=True) service_account = ServiceAccount(user=user, description=description, machine_set=machine_set) if machine_set is not None: _check_machine_set(service_account, machine_set) try: user.add(session) service_account.add(session) session.flush() except IntegrityError: session.rollback() raise DuplicateServiceAccount("User {} already exists".format(name)) # Counter is updated here and the session is committed, so we don't need an additional update # or commit for the account creation. add_service_account(session, owner, service_account) AuditLog.log(session, actor.id, "create_service_account", "Created new service account.", on_group_id=owner.id, on_user_id=service_account.user_id) return service_account
def create_service_account(self, name, owner, machine_set, description, initial_metadata=None): # type: (str, str, str, str, Optional[Dict[str,str]]) -> None group = Group.get(self.session, name=owner) if not group: raise GroupNotFoundException(owner) # Create the service account in the database. user = SQLUser(username=name, is_service_account=True) service = SQLServiceAccount(user=user, machine_set=machine_set, description=description) user.add(self.session) service.add(self.session) # Flush the account to allocate an ID. self.session.flush() # Set initial user metadata fields if present. if initial_metadata is not None: for key, value in initial_metadata.items(): # TODO: move this to use the hexagonal architecture model. set_user_metadata(self.session, user.id, key, value) # Create the linkage to the owner. GroupServiceAccount(group_id=group.id, service_account=service).add(self.session)
def service_accounts(session, users, groups): user = User(username="******", is_service_account=True) service_account = ServiceAccount(user=user, description="some service account", machine_set="some machines") user.add(session) service_account.add(session) session.flush() add_service_account(session, groups["team-sre"], service_account) return {"*****@*****.**": service_account}
def test_add_domain(setup): # type: (SetupTest) -> None with setup.transaction(): setup.add_user_to_group("*****@*****.**", "some-group") mock_ui = MagicMock() usecase = setup.usecase_factory.create_create_service_account_usecase("*****@*****.**", mock_ui) usecase.create_service_account("service", "some-group", "machine-set", "description") service = ServiceAccount.get(setup.session, name="*****@*****.**") assert service is not None assert service.machine_set == "machine-set" assert service.description == "description" assert ServiceAccount.get(setup.session, name="service") is None
def test_create(setup): # type: (SetupTest) -> None with setup.transaction(): setup.add_user_to_group("*****@*****.**", "some-group") setup.add_user_to_group("*****@*****.**", "other-group") run_ctl( setup, "service_account", "--actor", "*****@*****.**", "create", "*****@*****.**", "some-group", "foo +bar -(org)", "this is a service account.\n\n it is for testing", ) service_account = ServiceAccount.get(setup.session, name="*****@*****.**") assert service_account is not None assert service_account.user.name == "*****@*****.**" assert service_account.machine_set == "foo +bar -(org)" assert service_account.description == "this is a service account.\n\n it is for testing" group = Group.get(setup.session, name="some-group") assert group assert get_service_accounts(setup.session, group) == [service_account] # If the account already exists, creating it again returns an error and does nothing. with pytest.raises(SystemExit): run_ctl( setup, "service_account", "--actor", "*****@*****.**", "create", "*****@*****.**", "other-group", "foo", "another test", ) service_account = ServiceAccount.get(setup.session, name="*****@*****.**") assert service_account is not None assert service_account.machine_set == "foo +bar -(org)" assert service_account.description == "this is a service account.\n\n it is for testing" group = Group.get(setup.session, name="some-group") assert group assert get_service_accounts(setup.session, group) == [service_account]
def test_create_as_service_account(setup): """Test that a service account can create another service account.""" with setup.transaction(): setup.create_group("some-group") setup.create_service_account("*****@*****.**", "another-group") setup.grant_permission_to_service_account(USER_ADMIN, "", "*****@*****.**") run_ctl( setup, "service_account", "--actor", "*****@*****.**", "create", "*****@*****.**", "some-group", "foo +bar -(org)", "this is a service account.\n\n it is for testing", ) service_account = ServiceAccount.get(setup.session, name="*****@*****.**") assert service_account is not None assert service_account.user.name == "*****@*****.**" assert service_account.machine_set == "foo +bar -(org)" assert service_account.description == "this is a service account.\n\n it is for testing" group = Group.get(setup.session, name="some-group") assert get_service_accounts(setup.session, group) == [service_account]
def test_success(setup): # type: (SetupTest) -> None with setup.transaction(): setup.grant_permission_to_group(USER_ADMIN, "", "admins") setup.add_user_to_group("*****@*****.**", "admins") setup.create_user("*****@*****.**") setup.create_group("some-group") mock_ui = MagicMock() usecase = setup.usecase_factory.create_convert_user_to_service_account_usecase( "*****@*****.**", mock_ui) usecase.convert_user_to_service_account("*****@*****.**", "some-group") assert mock_ui.mock_calls == [ call.converted_user_to_service_account("*****@*****.**", "some-group") ] # Check the User after the conversion service_account_user = User.get(setup.session, name="*****@*****.**") assert service_account_user assert service_account_user.is_service_account assert service_account_user.enabled # Check the ServiceAccount that should have been created service_account = ServiceAccount.get(setup.session, name="*****@*****.**") assert service_account assert service_account.description == "" assert service_account.machine_set == "" assert service_account.user_id == service_account_user.id # Check that the ServiceAccount is owned by the correct Group group = Group.get(setup.session, name="some-group") group_service_account = GroupServiceAccount.get( setup.session, service_account_id=service_account.id) assert group assert group_service_account assert group_service_account.group_id == group.id
def service_account_command(args, settings, session_factory): # type: (Namespace, CtlSettings, SessionFactory) -> None session = session_factory.create_session() actor_user = User.get(session, name=args.actor_name) if not actor_user: logging.fatal('Actor user "{}" is not a valid Grouper user'.format( args.actor_name)) return if args.subcommand == "create": name = args.name if ServiceAccount.get(session, name=name): logging.info("{}: Already exists. Doing nothing.".format(name)) return owner_group = Group.get(session, name=args.owner_group) if not owner_group: logging.fatal('Owner group "{}" does not exist.'.format( args.owner_group)) return logging.info("{}: No such service account, creating...".format(name)) description = args.description machine_set = args.machine_set create_service_account(session, actor_user, name, description, machine_set, owner_group) return
def test_service_accounts(session, standard_graph, users, http_client, base_url): # noqa: F811 api_url = url(base_url, "/service_accounts") resp = yield http_client.fetch(api_url) body = json.loads(resp.body) assert resp.code == 200 assert body["status"] == "ok" assert sorted(body["data"]["service_accounts"]) == sorted( [u.name for u in itervalues(users) if u.role_user] + ["*****@*****.**"] ) # Retrieve a single service account and check its metadata. api_url = url(base_url, "/service_accounts/[email protected]") resp = yield http_client.fetch(api_url) body = json.loads(resp.body) assert resp.code == 200 assert body["status"] == "ok" data = body["data"]["user"] assert "service_account" in data assert data["service_account"]["description"] == "some service account" assert data["service_account"]["machine_set"] == "some machines" assert data["service_account"]["owner"] == "team-sre" assert body["data"]["permissions"] == [] # Delegate a permission to the service account and check for it. service_account = ServiceAccount.get(session, name="*****@*****.**") permission = get_permission(session, "team-sre") grant_permission_to_service_account(session, service_account, permission, "*") standard_graph.update_from_db(session) resp = yield http_client.fetch(api_url) body = json.loads(resp.body) assert resp.code == 200 assert body["status"] == "ok" perms = body["data"]["permissions"] assert perms[0]["permission"] == "team-sre" assert perms[0]["argument"] == "*"
def post(self, group_id=None, name=None, account_id=None, accountname=None, mapping_id=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 self.check_access(self.session, self.current_user, service_account): return self.forbidden() mapping = ServiceAccountPermissionMap.get(self.session, mapping_id) if not mapping: return self.notfound() permission = mapping.permission argument = mapping.argument mapping.delete(self.session) Counter.incr(self.session, "updates") self.session.commit() AuditLog.log(self.session, self.current_user.id, "revoke_permission", "Revoked permission with argument: {}".format(argument), on_permission_id=permission.id, on_group_id=group.id, on_user_id=service_account.user.id) return self.redirect("/groups/{}/service/{}?refresh=yes".format( group.name, service_account.user.username))
def post(self, group_id=None, name=None, account_id=None, accountname=None, mapping_id=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 self.check_access(self.session, self.current_user, service_account): return self.forbidden() mapping = ServiceAccountPermissionMap.get(self.session, mapping_id) if not mapping: return self.notfound() permission = mapping.permission argument = mapping.argument mapping.delete(self.session) Counter.incr(self.session, "updates") self.session.commit() AuditLog.log( self.session, self.current_user.id, "revoke_permission", "Revoked permission with argument: {}".format(argument), on_permission_id=permission.id, on_group_id=group.id, on_user_id=service_account.user.id, ) return self.redirect( "/groups/{}/service/{}?refresh=yes".format(group.name, service_account.user.username) )
def enable_service_account(self, name): # type: (str) -> None service_account = SQLServiceAccount.get(self.session, name=name) if not service_account: raise ServiceAccountNotFoundException(name) service_account.user.enabled = True
def post(self, user_id=None, name=None): service_account = ServiceAccount.get(self.session, user_id, name) if not service_account: return self.notfound() if not self.check_access(self.session, self.current_user, service_account): return self.forbidden() form = self.get_form() if not form.validate(): return self.render( "service-account-enable.html", form=form, user=service_account.user, alerts=self.get_form_alerts(form.errors), ) owner = Group.get(self.session, name=form.data["owner"]) if owner is None: form.owner.errors.append("Group not found.") return self.render( "service-account-enable.html", form=form, user=service_account.user, alerts=self.get_form_alerts(form.errors), ) enable_service_account(self.session, self.current_user, service_account, owner) return self.redirect( "/groups/{}/service/{}?refresh=yes".format(owner.name, service_account.user.username) )
def post(self, user_id=None, name=None): service_account = ServiceAccount.get(self.session, user_id, name) if not service_account: return self.notfound() if not self.check_access(self.session, self.current_user, service_account): return self.forbidden() form = self.get_form() if not form.validate(): return self.render("service-account-enable.html", form=form, user=service_account.user, alerts=self.get_form_alerts(form.errors)) owner = Group.get(self.session, name=form.data["owner"]) if owner is None: form.owner.errors.append("Group not found.") return self.render("service-account-enable.html", form=form, user=service_account.user, alerts=self.get_form_alerts(form.errors)) enable_service_account(self.session, self.current_user, service_account, owner) return self.redirect("/groups/{}/service/{}?refresh=yes".format( owner.name, service_account.user.username))
def test_success(setup): # type: (SetupTest) -> None with setup.transaction(): setup.add_user_to_group("*****@*****.**", "some-group") mock_ui = MagicMock() usecase = setup.usecase_factory.create_create_service_account_usecase("*****@*****.**", mock_ui) usecase.create_service_account( "*****@*****.**", "some-group", "machine-set", "description" ) assert mock_ui.mock_calls == [ call.created_service_account("*****@*****.**", "some-group") ] # Check the User and ServiceAccount that were created. user = User.get(setup.session, name="*****@*****.**") assert user is not None assert user.is_service_account assert user.enabled service = ServiceAccount.get(setup.session, name="*****@*****.**") assert service is not None assert service.machine_set == "machine-set" assert service.description == "description" # Check that the ServiceAccount is owned by the correct Group. group = Group.get(setup.session, name="some-group") assert group is not None linkage = GroupServiceAccount.get(setup.session, service_account_id=service.id) assert linkage is not None assert linkage.group_id == group.id
def get(self, *args: Any, **kwargs: Any) -> None: name = self.get_path_argument("name") accountname = self.get_path_argument("accountname") self.handle_refresh() 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() # We don't need the group to be valid to find the service account, but ensure that the # group is the owner of the service account so that we don't generate confusing URLs and # broken information on the view page. if service_account.owner.group_id != group.id: return self.notfound() user = service_account.user self.render( "service-account.html", service_account=service_account, group=group, user=user, **get_user_view_template_vars(self.session, self.current_user, user, self.graph) )
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 create_service_account(self, name, owner, machine_set, description): # type: (str, str, str, str) -> None group = Group.get(self.session, name=owner) if not group: raise GroupNotFoundException(group) # Create the service account in the database. user = SQLUser(username=name, is_service_account=True) service = SQLServiceAccount(user=user, machine_set=machine_set, description=description) user.add(self.session) service.add(self.session) # Flush the account to allocate an ID, and then create the linkage to the owner. self.session.flush() GroupServiceAccount(group_id=group.id, service_account=service).add(self.session)
def test_grant_permission(session, standard_graph, groups, permissions): grant_permission(groups["sad-team"], permissions["ssh"], argument="host +other-host") with pytest.raises(AssertionError): grant_permission(groups["sad-team"], permissions["ssh"], argument="question?") account = ServiceAccount.get(session, name="*****@*****.**") grant_permission_to_service_account(session, account, permissions["ssh"], argument="*") with pytest.raises(AssertionError): grant_permission_to_service_account( session, account, permissions["ssh"], argument="question?")
def get(self, user_id=None, name=None): service_account = ServiceAccount.get(self.session, user_id, name) if not service_account: return self.notfound() if not self.check_access(self.session, self.current_user, service_account): return self.forbidden() form = self.get_form() return self.render("service-account-enable.html", form=form, user=service_account.user)
def mark_disabled_user_as_service_account(self, name, description="", mdbset=""): # type: (str, str, str) -> None """Transform a disabled user into a disabled, ownerless service account. WARNING: This function encodes the fact that the user and service account repos are in fact the same thing, as it assumes that a service account is just a user that is marked in a special way. This is a temporary breaking of the abstractions and will have to be cleaned up once the repositories are properly separate. """ user = SQLUser.get(self.session, name=name) if not user: raise UserNotFoundException(name) service_account = SQLServiceAccount( user_id=user.id, description=description, machine_set=mdbset ) service_account.add(self.session) user.is_service_account = True
def test_grant_permission(session, standard_graph, groups, permissions): # noqa: F811 grant_permission(groups["sad-team"], permissions["ssh"], argument="host +other-host") with pytest.raises(AssertionError): grant_permission(groups["sad-team"], permissions["ssh"], argument="question?") account = ServiceAccount.get(session, name="*****@*****.**") grant_permission_to_service_account(session, account, permissions["ssh"], argument="*") with pytest.raises(AssertionError): grant_permission_to_service_account( session, account, permissions["ssh"], argument="question?" )
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() user = service_account.user if not self.check_access(self.session, self.current_user, service_account): return self.forbidden() grantable = group.my_permissions() form = self.get_form(grantable) if not form.validate(): return self.render( "service-account-permission-grant.html", form=form, user=user, group=group, alerts=self.get_form_alerts(form.errors) ) permission = Permission.get(self.session, form.data["permission"]) if not permission: return self.notfound() allowed = False for perm in grantable: if perm[1] == permission.name: if matches_glob(perm[3], form.data["argument"]): allowed = True break if not allowed: form.argument.errors.append( "The group {} does not have that permission".format(group.name)) return self.render( "service-account-permission-grant.html", form=form, user=user, group=group, alerts=self.get_form_alerts(form.errors) ) try: grant_permission_to_service_account( self.session, service_account, permission, form.data["argument"]) except IntegrityError: self.session.rollback() return self.render( "service-account-permission-grant.html", form=form, user=user, alerts=self.get_form_alerts(form.errors) ) AuditLog.log(self.session, self.current_user.id, "grant_permission", "Granted permission with argument: {}".format(form.data["argument"]), on_permission_id=permission.id, on_group_id=group.id, on_user_id=service_account.user.id) return self.redirect("/groups/{}/service/{}?refresh=yes".format( group.name, service_account.user.username))
def disable_service_account(self, service_account): # type: (str) -> None service_obj = ServiceAccount.get(self.session, name=service_account) assert service_obj service_obj.user.enabled = False service_obj.owner.delete(self.session) permissions = self.session.query( ServiceAccountPermissionMap).filter_by( service_account_id=service_obj.id) for permission in permissions: permission.delete(self.session)
def disable_service_account(self, service_account): # type: (str) -> None service_obj = ServiceAccount.get(self.session, name=service_account) assert service_obj service_obj.user.enabled = False service_obj.owner.delete(self.session) permissions = self.session.query(ServiceAccountPermissionMap).filter_by( service_account_id=service_obj.id ) for permission in permissions: permission.delete(self.session)
def create_service_account(self, service_account, owner, description="", machine_set=""): # type: (str, str, str, str) -> None self.create_group(owner) group_obj = Group.get(self.session, name=owner) assert group_obj if User.get(self.session, name=service_account): return user = User(username=service_account) user.add(self.session) service_account_obj = ServiceAccount( user_id=user.id, description=description, machine_set=machine_set ) service_account_obj.add(self.session) user.is_service_account = True self.session.flush() owner_map = GroupServiceAccount( group_id=group_obj.id, service_account_id=service_account_obj.id ) owner_map.add(self.session)
def mark_disabled_user_as_service_account(self, name, description="", mdbset=""): # type: (str, str, str) -> None """Transform a disabled user into a disabled, ownerless service account. WARNING: This function encodes the fact that the user and service account repos are in fact the same thing, as it assumes that a service account is just a user that is marked in a special way. This is a temporary breaking of the abstractions and will have to be cleaned up once the repositories are properly separate. """ user = SQLUser.get(self.session, name=name) if not user: raise UserNotFoundException(name) service_account = SQLServiceAccount(user_id=user.id, description=description, machine_set=mdbset) service_account.add(self.session) user.is_service_account = True
def get(self, group_id=None, name=None, account_id=None, accountname=None): self.handle_refresh() 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() user = service_account.user self.render( "service-account.html", service_account=service_account, group=group, user=user, **get_user_view_template_vars(self.session, self.current_user, user, self.graph) )
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 self.check_access(self.session, self.current_user, service_account): return self.forbidden() disable_service_account(self.session, self.current_user, service_account) return self.redirect("/groups/{}?refresh=yes".format(group.name))
def get(self, *args: Any, **kwargs: Any) -> None: name = self.get_path_argument("name") service_account = ServiceAccount.get(self.session, name=name) if not service_account: return self.notfound() if not self.check_access(self.session, self.current_user, service_account): return self.forbidden() form = self.get_form() return self.render("service-account-enable.html", form=form, user=service_account.user)
def create_service_account(self, service_account, owner, description="", machine_set=""): # type: (str, str, str, str) -> None self.create_group(owner) group_obj = Group.get(self.session, name=owner) assert group_obj if User.get(self.session, name=service_account): return user = User(username=service_account) user.add(self.session) service_account_obj = ServiceAccount(user_id=user.id, description=description, machine_set=machine_set) service_account_obj.add(self.session) user.is_service_account = True self.session.flush() owner_map = GroupServiceAccount( group_id=group_obj.id, service_account_id=service_account_obj.id) owner_map.add(self.session)
def grant_permission_to_service_account(self, permission, argument, service): # type: (str, str, str) -> None sql_service = ServiceAccount.get(self.session, name=service) if not sql_service or not sql_service.user.enabled: raise ServiceAccountNotFoundException(service) sql_permission = Permission.get(self.session, name=permission) if not sql_permission: raise PermissionNotFoundException(permission) mapping = ServiceAccountPermissionMap( permission_id=sql_permission.id, service_account_id=sql_service.id, argument=argument) mapping.add(self.session)
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() user = service_account.user if not self.check_access(self.session, self.current_user, service_account): return self.forbidden() form = self.get_form(group.my_permissions()) return self.render( "service-account-permission-grant.html", form=form, user=user, group=group )
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, group_id=None, name=None, account_id=None, accountname=None): self.handle_refresh() 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() user = service_account.user self.render("service-account.html", service_account=service_account, group=group, user=user, **get_user_view_template_vars(self.session, self.current_user, user, self.graph))
def assign_service_account_to_group(self, name, groupname): # type: (str, str) -> None service_account = SQLServiceAccount.get(self.session, name=name) if not service_account: raise ServiceAccountNotFoundException(name) group = Group.get(self.session, name=groupname) if not group: raise GroupNotFoundException(groupname) existing_relationship = GroupServiceAccount.get( self.session, service_account_id=service_account.id) if existing_relationship: existing_relationship.group_id = group.id else: group_service_account = GroupServiceAccount( group_id=group.id, service_account_id=service_account.id) group_service_account.add(self.session)
def test_admin_can_create(setup): # type: (SetupTest) -> None with setup.transaction(): setup.create_group("some-group") setup.add_user_to_group("*****@*****.**", "admins") setup.grant_permission_to_group(USER_ADMIN, "", "admins") mock_ui = MagicMock() usecase = setup.usecase_factory.create_create_service_account_usecase("*****@*****.**", mock_ui) usecase.create_service_account("*****@*****.**", "some-group", "", "") assert mock_ui.mock_calls == [ call.created_service_account("*****@*****.**", "some-group") ] service = ServiceAccount.get(setup.session, name="*****@*****.**") assert service is not None assert service.machine_set == "" assert service.description == ""
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 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() user = service_account.user if not self.check_access(self.session, self.current_user, service_account): return self.forbidden() form = self.get_form(group.my_permissions()) return self.render("service-account-permission-grant.html", form=form, user=user, group=group)
def post(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 self.check_access(self.session, self.current_user, service_account): return self.forbidden() disable_service_account(self.session, self.current_user, service_account) return self.redirect("/groups/{}?refresh=yes".format(group.name))
def assign_service_account_to_group(self, name, groupname): # type: (str, str) -> None service_account = SQLServiceAccount.get(self.session, name=name) if not service_account: raise ServiceAccountNotFoundException(name) group = Group.get(self.session, name=groupname) if not group: raise GroupNotFoundException(groupname) existing_relationship = GroupServiceAccount.get( self.session, service_account_id=service_account.id ) if existing_relationship: existing_relationship.group_id = group.id else: group_service_account = GroupServiceAccount( group_id=group.id, service_account_id=service_account.id ) group_service_account.add(self.session)
def service_account_command(args, settings, session_factory): # type: (Namespace, CtlSettings, SessionFactory) -> None session = session_factory.create_session() actor_user = User.get(session, name=args.actor_name) if not actor_user: logging.fatal('Actor user "{}" is not a valid Grouper user'.format(args.actor_name)) return if args.subcommand == "create": name = args.name if ServiceAccount.get(session, name=name): logging.info("{}: Already exists. Doing nothing.".format(name)) return owner_group = Group.get(session, name=args.owner_group) if not owner_group: logging.fatal('Owner group "{}" does not exist.'.format(args.owner_group)) return logging.info("{}: No such service account, creating...".format(name)) description = args.description machine_set = args.machine_set create_service_account(session, actor_user, name, description, machine_set, owner_group) return
def get(self, *args, **kwargs): # type: (*Any, **Any) -> None group_id = kwargs.get("group_id") # type: Optional[int] name = kwargs.get("name") # type: Optional[str] account_id = kwargs.get("account_id") # type: Optional[int] accountname = kwargs.get("accountname") # type: Optional[str] self.handle_refresh() 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() user = service_account.user self.render( "service-account.html", service_account=service_account, group=group, user=user, **get_user_view_template_vars(self.session, self.current_user, user, self.graph) )
def test_success(setup): # type: (SetupTest) -> None with setup.transaction(): setup.grant_permission_to_group(USER_ADMIN, "", "admins") setup.add_user_to_group("*****@*****.**", "admins") setup.create_user("*****@*****.**") setup.create_group("some-group") mock_ui = MagicMock() usecase = setup.usecase_factory.create_convert_user_to_service_account_usecase( "*****@*****.**", mock_ui ) usecase.convert_user_to_service_account("*****@*****.**", "some-group") assert mock_ui.mock_calls == [ call.converted_user_to_service_account("*****@*****.**", "some-group") ] # Check the User after the conversion service_account_user = User.get(setup.session, name="*****@*****.**") assert service_account_user assert service_account_user.is_service_account assert service_account_user.enabled # Check the ServiceAccount that should have been created service_account = ServiceAccount.get(setup.session, name="*****@*****.**") assert service_account assert service_account.description == "" assert service_account.machine_set == "" assert service_account.user_id == service_account_user.id # Check that the ServiceAccount is owned by the correct Group group = Group.get(setup.session, name="some-group") group_service_account = GroupServiceAccount.get( setup.session, service_account_id=service_account.id ) assert group assert group_service_account assert group_service_account.group_id == group.id
def test_service_account_create(groups, service_accounts, session, tmpdir, users): # noqa: F811 machine_set = "foo +bar -(org)" description = "this is a service account.\n\n it is for testing" security_team_group = Group.get(session, name="security-team") good_actor_username = "******" good_service_account_name = "*****@*****.**" assert ServiceAccount.get(session, name=good_service_account_name) is None assert get_service_accounts(session, security_team_group) == [] # no-op if non-existing actor call_main( session, tmpdir, "service_account", "--actor", "*****@*****.**", "create", good_service_account_name, security_team_group.groupname, machine_set, description, ) # ... or if bad account name call_main( session, tmpdir, "service_account", "--actor", good_actor_username, "create", "bad-service-account-name", security_team_group.groupname, machine_set, description, ) # ... or non-existing owner group call_main( session, tmpdir, "service_account", "--actor", good_actor_username, "create", good_service_account_name, "non-such-owner-group", machine_set, description, ) # make sure no change was made assert ServiceAccount.get(session, name=good_service_account_name) is None assert get_service_accounts(session, security_team_group) == [] # now it works call_main( session, tmpdir, "service_account", "--actor", good_actor_username, "create", good_service_account_name, security_team_group.groupname, machine_set, description, ) service_account = ServiceAccount.get(session, name=good_service_account_name) assert service_account, "non-existing account should be created" assert service_account.user.name == good_service_account_name assert service_account.machine_set == machine_set assert service_account.description == description assert get_service_accounts(session, security_team_group) == [service_account] # no-op if account name already exists call_main( session, tmpdir, "service_account", "--actor", good_actor_username, "create", good_service_account_name, security_team_group.groupname, machine_set, description, ) service_account = ServiceAccount.get(session, name=good_service_account_name) assert service_account, "non-account should be created" assert service_account.user.name == good_service_account_name assert service_account.machine_set == machine_set assert service_account.description == description assert get_service_accounts(session, security_team_group) == [service_account] # actor can be a service account as well call_main( session, tmpdir, "service_account", "--actor", "*****@*****.**", "create", "*****@*****.**", security_team_group.groupname, machine_set + "2", description + "2", ) service_account_2 = ServiceAccount.get(session, name="*****@*****.**") assert service_account_2, "non-existing account should be created" assert service_account_2.user.name == "*****@*****.**" assert service_account_2.machine_set == (machine_set + "2") assert service_account_2.description == (description + "2") assert set(get_service_accounts(session, security_team_group)) == set( [service_account, service_account_2] )