Beispiel #1
0
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)
Beispiel #4
0
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
Beispiel #5
0
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
Beispiel #6
0
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)
Beispiel #8
0
    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"] == []
Beispiel #10
0
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