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 post(self): if "@" not in self.request.arguments["name"][0]: self.request.arguments["name"][0] += "@" + settings.service_account_email_domain form = ServiceAccountCreateForm(self.request.arguments) if not form.validate(): return self.render( "service-account-create.html", form=form, alerts=self.get_form_alerts(form.errors) ) if form.data["name"].split("@")[-1] != settings.service_account_email_domain: form.name.errors.append("All service accounts must have a username ending in {}" .format(settings.service_account_email_domain)) return self.render( "service-account-create.html", form=form, alerts=self.get_form_alerts(form.errors) ) try: create_service_account(self.session, self.current_user, form.data["name"], form.data["description"], form.data["canjoin"]) except IntegrityError: self.session.rollback() form.name.errors.append("A user or group with name {} already exists" .format(form.data["name"])) return self.render( "service-account-create.html", form=form, alerts=self.get_form_alerts(form.errors) ) return self.redirect("/service/{}?refresh=yes".format(form.data["name"]))
def post(self, group_id=None, name=None): group = Group.get(self.session, group_id, name) if not group: return self.notfound() if "@" not in self.request.arguments["name"][0]: self.request.arguments["name"][ 0] += "@" + settings.service_account_email_domain if not can_create_service_account(self.session, self.current_user, group): return self.forbidden() form = ServiceAccountCreateForm(self.request.arguments) if not form.validate(): return self.render( "service-account-create.html", form=form, group=group, alerts=self.get_form_alerts(form.errors), ) if form.data["name"].split( "@")[-1] != settings.service_account_email_domain: form.name.errors.append( "All service accounts must have a username ending in {}". format(settings.service_account_email_domain)) return self.render( "service-account-create.html", form=form, group=group, alerts=self.get_form_alerts(form.errors), ) try: create_service_account( self.session, self.current_user, form.data["name"], form.data["description"], form.data["machine_set"], group, ) except DuplicateServiceAccount: form.name.errors.append( "A user with name {} already exists".format(form.data["name"])) except BadMachineSet as e: form.machine_set.errors.append(str(e)) if form.name.errors or form.machine_set.errors: return self.render( "service-account-create.html", form=form, group=group, alerts=self.get_form_alerts(form.errors), ) url = "/groups/{}/service/{}?refresh=yes".format( group.name, form.data["name"]) return self.redirect(url)
def service_accounts(session, users, groups): service_accounts = { "*****@*****.**": create_service_account( session, users["*****@*****.**"], "*****@*****.**", "some service account", "some machines", groups["team-sre"] ), } session.commit() return service_accounts
def service_accounts(session, users, groups): service_accounts = { "*****@*****.**": create_service_account(session, users["*****@*****.**"], "*****@*****.**", "some service account", "some machines", groups["team-sre"]), } session.commit() return service_accounts
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 post(self, group_id=None, name=None): group = Group.get(self.session, group_id, name) if not group: return self.notfound() if "@" not in self.request.arguments["name"][0]: self.request.arguments["name"][0] += "@" + settings.service_account_email_domain form = ServiceAccountCreateForm(self.request.arguments) if not form.validate(): return self.render( "service-account-create.html", form=form, group=group, alerts=self.get_form_alerts(form.errors) ) if form.data["name"].split("@")[-1] != settings.service_account_email_domain: form.name.errors.append("All service accounts must have a username ending in {}" .format(settings.service_account_email_domain)) return self.render( "service-account-create.html", form=form, group=group, alerts=self.get_form_alerts(form.errors) ) try: create_service_account(self.session, self.current_user, form.data["name"], form.data["description"], form.data["machine_set"], group) except DuplicateServiceAccount: form.name.errors.append("A user with name {} already exists".format(form.data["name"])) except BadMachineSet as e: form.machine_set.errors.append(str(e)) if form.name.errors or form.machine_set.errors: return self.render( "service-account-create.html", form=form, group=group, alerts=self.get_form_alerts(form.errors) ) url = "/groups/{}/service/{}?refresh=yes".format(group.name, form.data["name"]) return self.redirect(url)
def post(self): if "@" not in self.request.arguments["name"][0]: self.request.arguments["name"][ 0] += "@" + settings.service_account_email_domain form = ServiceAccountCreateForm(self.request.arguments) if not form.validate(): return self.render("service-account-create.html", form=form, alerts=self.get_form_alerts(form.errors)) if form.data["name"].split( "@")[-1] != settings.service_account_email_domain: form.name.errors.append( "All service accounts must have a username ending in {}". format(settings.service_account_email_domain)) return self.render("service-account-create.html", form=form, alerts=self.get_form_alerts(form.errors)) try: create_service_account(self.session, self.current_user, form.data["name"], form.data["description"], form.data["canjoin"]) except IntegrityError: self.session.rollback() form.name.errors.append( "A user or group with name {} already exists".format( form.data["name"])) return self.render("service-account-create.html", form=form, alerts=self.get_form_alerts(form.errors)) return self.redirect("/service/{}?refresh=yes".format( form.data["name"]))
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 standard_graph(session, graph, users, groups, permissions): """Setup a standard graph used for many tests. In graph form: +-----------------------+ | | | team-sre | | * gary (o) +---------------------------------+ | * zay | | | * zorkian | | | * service (s) | +-----------v-----------+ | | | | +-----------------------+ | serving-team | +-----------------------+ +---------> * zorkian (o) | | | | | | | tech-ops | | +-----------+-----------+ | * zay (o) | | | | * gary +-----------+ | | * figurehead (np) | | | | | +-----------------------+ | +-----------------------+ +-----------v-----------+ | | | | | security-team | | team-infra | | * oliver (o) +---------------------> * gary (o) | | * figurehead | | | | | +-----------+-----------+ +-----------------------+ | +-----------------------+ | | | | | sad-team | | | * zorkian (o) | | | * oliver | +-----------v-----------+ | | | | +-----------------------+ | all-teams | +-----------------------+ | * testuser (o) | | | | | | audited-team | +-----------------------+ | * zorkian (o) | | | +-----------------------+ +-----------------------+ | | | auditors | | * zorkian (o) | | | +-----------------------+ +-----------------------+ | | | user-admins | | * tyleromeara (o) | | * cbguder (o) | | | +-----------------------+ +-----------------------+ | | | group-admins | | * cbguder (o) | | | +-----------------------+ Arrows denote member of the source in the destination group. (o) for owners, (np) for non-permissioned owners, (s) for service accounts. """ add_member(groups["team-sre"], users["*****@*****.**"], role="owner") add_member(groups["team-sre"], users["*****@*****.**"]) add_member(groups["team-sre"], users["*****@*****.**"]) grant_permission(groups["team-sre"], permissions["ssh"], argument="*") grant_permission(groups["team-sre"], permissions["team-sre"], argument="*") add_member(groups["serving-team"], users["*****@*****.**"], role="owner") add_member(groups["serving-team"], groups["team-sre"]) add_member(groups["serving-team"], groups["tech-ops"]) grant_permission(groups["serving-team"], permissions["audited"]) add_member(groups["tech-ops"], users["*****@*****.**"], role="owner") add_member(groups["tech-ops"], users["*****@*****.**"]) add_member(groups["tech-ops"], users["*****@*****.**"], role="np-owner") grant_permission(groups["tech-ops"], permissions["ssh"], argument="shell") add_member(groups["security-team"], users["*****@*****.**"], role="owner") add_member(groups["security-team"], users["*****@*****.**"], role="member") add_member(groups["sad-team"], users["*****@*****.**"], role="owner") add_member(groups["sad-team"], users["*****@*****.**"]) add_member(groups["audited-team"], users["*****@*****.**"], role="owner") grant_permission(groups["audited-team"], permissions["audited"]) add_member(groups["team-infra"], users["*****@*****.**"], role="owner") add_member(groups["team-infra"], groups["serving-team"]) add_member(groups["team-infra"], groups["security-team"]) grant_permission(groups["team-infra"], permissions["sudo"], argument="shell") add_member(groups["auditors"], users["*****@*****.**"], role="owner") grant_permission(groups["auditors"], permissions[AUDIT_MANAGER]) grant_permission(groups["auditors"], permissions[PERMISSION_AUDITOR]) add_member(groups["all-teams"], users["*****@*****.**"], role="owner") add_member(groups["all-teams"], groups["team-infra"]) add_member(groups["user-admins"], users["*****@*****.**"], role="owner") add_member(groups["user-admins"], users["*****@*****.**"], role="owner") grant_permission(groups["user-admins"], permissions[USER_ADMIN]) add_member(groups["group-admins"], users["*****@*****.**"], role="owner") grant_permission(groups["group-admins"], permissions[GROUP_ADMIN]) create_service_account(session, users["*****@*****.**"], "*****@*****.**", "some service account", "some machines", groups["team-sre"]) session.commit() graph.update_from_db(session) return graph