Skip to content

Commit

Permalink
Implement denylisting (#2046)
Browse files Browse the repository at this point in the history
Implement denylisting

Fixes #1964

RELEASE NOTES BEGIN
We have implemented a denylisting mechanism allowing us to denylist namespaces/projects to prevent misuse of our service.
RELEASE NOTES END

Reviewed-by: Jiri Popelka
  • Loading branch information
softwarefactory-project-zuul[bot] authored May 17, 2023
2 parents 7add044 + a14b966 commit 01cbaf4
Show file tree
Hide file tree
Showing 10 changed files with 588 additions and 108 deletions.
34 changes: 29 additions & 5 deletions files/scripts/README.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,52 @@
# Allowlisting an account
# Allowlisting/denylisting an account

You need to login to our OpenShift cluster and list all pods. Use the `allowlist.py` script inside the worker pod to manipulate the allowlist.

## List pending namespaces

List all requests pending approval:

```
$ oc exec packit-worker-0 allowlist.py waiting
$ oc exec packit-worker-short-running-0 allowlist.py waiting
```

Use `oc exec -it ...` instead if you also want to approve a namespace from the waiting list and specify the number of namespace to approve. In order to add to the allowlist manually:
Use `oc exec -it ...` instead if you also want to approve a namespace from the waiting list and specify the number of namespace to approve.

## Manual approval

In order to add to the allowlist manually:

```
$ oc exec -it packit-worker-0 allowlist.py approve <path_to_namespace>
$ oc exec -it packit-worker-short-running-0 allowlist.py approve <path_to_namespace>
```

The `<path_to_namespace>` string should follow the same format which is used in the list of waiting requests, i.e. the domain should be included.
For example, for an organization/user `packit` at Github, `github.com/packit` should be used for the allowlist.
In order to add only a single repository to the allowlist, the `.git` suffix must explicitly be used, e.g. `github.com/packit/ogr.git`.
After approving, close the corresponding issue at [packit-service/notifications](https://github.com/packit/notifications/issues).

## List denied namespaces

List all denied namespaces:

```
$ oc exec packit-worker-short-running-0 allowlist.py denied
```

## Denying

Denying a user:

```
$ oc exec -it packit-worker-short-running-0 allowlist.py deny <path_to_namespace>
```

## Removal

Removing a user or from the allowlist:

```
$ oc exec packit-worker-0 allowlist.py remove <path_to_namespace>
$ oc exec -it packit-worker-short-running-0 allowlist.py remove <path_to_namespace>
```

# Cleaning up the database
Expand Down
28 changes: 26 additions & 2 deletions files/scripts/allowlist.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,15 +118,30 @@ def approve(full_path: Optional[str]):
if full_path is None:
full_path = RepoUrl().convert(construct_path())

is_approved_before = Allowlist.is_approved(full_path)
is_approved_before = Allowlist.is_namespace_or_parent_approved(full_path)

Allowlist.approve_namespace(full_path)
if Allowlist.is_approved(full_path) != is_approved_before:
if Allowlist.is_namespace_or_parent_approved(full_path) != is_approved_before:
click.secho(f"Namespace ‹{full_path}› has been approved.", fg="green")
else:
click.secho(f"Status of namespace ‹{full_path}› has not changed.", fg="yellow")


@cli.command(short_help="Deny namespace.", help=PATH_HELP.format("denied"))
@click.argument("full_path", type=RepoUrl(), required=False)
def deny(full_path: Optional[str]):
if full_path is None:
full_path = RepoUrl().convert(construct_path())

is_denied_before = Allowlist.is_denied(full_path)
if is_denied_before:
click.secho(f"Namespace ‹{full_path}› already denied.", fg="yellow")
return

Allowlist.deny_namespace(full_path)
click.secho(f"Namespace ‹{full_path}› has been denied.", fg="green")


@cli.command(
short_help="Remove namespace from allowlist. Removes the entry.",
help=PATH_HELP.format("removed"),
Expand Down Expand Up @@ -156,5 +171,14 @@ def waiting(ctx):
ctx.invoke(approve, full_path=prompt_variant(waiting_list[choice - 1]))


@cli.command(short_help="Show namespaces that are denied.")
def denied():
click.echo("Denied namespaces:")

denied_list = Allowlist.denied_namespaces()
for i, namespace in enumerate(denied_list, 1):
click.echo(f"{i}. {namespace}")


if __name__ == "__main__":
cli()
6 changes: 5 additions & 1 deletion packit_service/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@
)
NOTIFICATION_REPO = "https://github.com/packit/notifications"


PERMISSIONS_ERROR_WRITE_OR_ADMIN = (
"Only users with write or admin permissions to the repository "
"can trigger Packit-as-a-Service"
Expand Down Expand Up @@ -250,3 +249,8 @@ def from_number(number: int):
"s390x",
"x86_64",
]

DENIED_MSG = (
f"You were denied from using Packit Service. If you think this was done by mistake, "
f"please, [let us know]({CONTACTS_URL})."
)
2 changes: 1 addition & 1 deletion packit_service/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1998,7 +1998,7 @@ def get_namespace(cls, namespace: str) -> Optional["AllowlistModel"]:
return sa_session().query(AllowlistModel).filter_by(namespace=namespace).first()

@classmethod
def get_namespaces_by_status(cls, status: str) -> Iterable["AllowlistModel"]:
def get_by_status(cls, status: str) -> Iterable["AllowlistModel"]:
"""
Get list of namespaces with specific status.
Expand Down
Loading

0 comments on commit 01cbaf4

Please sign in to comment.