示例#1
0
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
示例#2
0
    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)
示例#3
0
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}
示例#4
0
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
示例#5
0
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]
示例#6
0
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]
示例#7
0
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
示例#8
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
示例#9
0
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"] == "*"
示例#10
0
    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)
        )
示例#12
0
    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
示例#13
0
    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
示例#14
0
    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))
示例#16
0
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
示例#17
0
    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)
        )
示例#18
0
    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))
示例#19
0
    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)
示例#20
0
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?")
示例#21
0
    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)
示例#22
0
    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
示例#23
0
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))
示例#25
0
 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)
示例#26
0
文件: setup.py 项目: dropbox/grouper
 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)
示例#27
0
文件: setup.py 项目: dropbox/grouper
    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 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)
示例#29
0
    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
示例#30
0
    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))
示例#32
0
    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)
示例#33
0
    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)
示例#34
0
    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)
示例#35
0
    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
        )
示例#37
0
    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
        )
示例#38
0
    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))
示例#39
0
    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)
示例#40
0
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 == ""
示例#41
0
    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
        )
示例#42
0
    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)
示例#43
0
    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)
示例#44
0
    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))
示例#45
0
    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)
示例#46
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
示例#47
0
    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
示例#49
0
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]
    )