Skip to content

Commit

Permalink
add access permission expiration support
Browse files Browse the repository at this point in the history
  • Loading branch information
aaschaer committed Dec 20, 2024
1 parent 8b6ba5e commit 974bbc4
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 2 deletions.
12 changes: 12 additions & 0 deletions changelog.d/20241220_115422_aaschaer_permission_expiration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
### Bugfixes

* Fixed principal output parsing for `globus endpoint permission` and `globus endpoint role` commands.

### Enhancements

* Added the `--expiration-date` option to `globus endpoint permission create` and `globus endpoint permission update`.
* Added `Expiration Date` as a text output field for `globus endpoint permission show`.

### Other

* `--permissions` is no longer a required option for `globus endpoint permission update`.
5 changes: 5 additions & 0 deletions src/globus_cli/commands/endpoint/permission/_common.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import click
from globus_cli.termio import formatters


Expand All @@ -18,3 +19,7 @@ def fallback_rendering(self, principal: str, principal_type: str) -> str:
# it could be made multi-environment using `globus_sdk.config.get_webapp_url()`
def render_group_id(self, group_id: str) -> str:
return f"https://app.globus.org/groups/{group_id}"


def expiration_date_option(f: C) -> C:
return click.option("--expiration-date", help="Expiration date for the permission in ISO 8601 format")(f)
4 changes: 4 additions & 0 deletions src/globus_cli/commands/endpoint/permission/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from globus_cli.parsing import ENDPOINT_PLUS_REQPATH, command, security_principal_opts
from globus_cli.termio import Field, display

from ._common import expiration_date_option

@command(
"create",
Expand Down Expand Up @@ -50,6 +51,7 @@
help="A custom message to add to email notifications",
)
@click.argument("endpoint_plus_path", type=ENDPOINT_PLUS_REQPATH)
@expiration_date_option
@LoginManager.requires_login("auth", "transfer")
def create_command(
login_manager: LoginManager,
Expand All @@ -59,6 +61,7 @@ def create_command(
endpoint_plus_path: tuple[uuid.UUID, str | None],
notify_email: str | None,
notify_message: str | None,
expiration_date: str | None,
) -> None:
"""
Create a new access control rule on the target endpoint, granting users new
Expand Down Expand Up @@ -105,6 +108,7 @@ def create_command(
path=path,
notify_email=notify_email,
notify_message=notify_message,
expiration_date=expiration_date,
)

res = transfer_client.add_endpoint_acl_rule(endpoint_id, rule_data)
Expand Down
1 change: 1 addition & 0 deletions src/globus_cli/commands/endpoint/permission/show.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,6 @@ def show_command(
formatter=AclPrincipalFormatter(auth_client=auth_client),
),
Field("Path", "path"),
Field("Expiration Date", "expiration_date"),
],
)
9 changes: 7 additions & 2 deletions src/globus_cli/commands/endpoint/permission/update.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import typing as t
import uuid

Expand All @@ -7,6 +9,8 @@
from globus_cli.parsing import command, endpoint_id_arg
from globus_cli.termio import display

from ._common import expiration_date_option


@command(
"update",
Expand All @@ -25,17 +29,18 @@
@click.argument("rule_id")
@click.option(
"--permissions",
required=True,
type=click.Choice(("r", "rw"), case_sensitive=False),
help="Permissions to add. Read-Only or Read/Write",
)
@expiration_date_option
@LoginManager.requires_login("transfer")
def update_command(
login_manager: LoginManager,
*,
permissions: t.Literal["r", "rw"],
rule_id: str,
endpoint_id: uuid.UUID,
expiration_date: str | None,
) -> None:
"""
Update an existing access control rule's permissions.
Expand All @@ -47,6 +52,6 @@ def update_command(

transfer_client = login_manager.get_transfer_client()

rule_data = assemble_generic_doc("access", permissions=permissions)
rule_data = assemble_generic_doc("access", permissions=permissions, expiration_date=expiration_date)
res = transfer_client.update_endpoint_acl_rule(endpoint_id, rule_id, rule_data)
display(res, text_mode=display.RAW, response_key="message")
2 changes: 2 additions & 0 deletions src/globus_cli/termio/formatters/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ def parse(self, value: t.Any) -> tuple[str, str]:

class PrincipalDictFormatter(PrincipalFormatter):
def parse(self, value: t.Any) -> tuple[str, str]:
if isinstance(value, globus_sdk.GlobusHTTPResponse):
value = value.data
if not isinstance(value, dict):
raise ValueError("cannot format principal from non-dict data")

Expand Down
26 changes: 26 additions & 0 deletions tests/files/api_fixtures/endpoint_acl_operations.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ metadata:
user_id: "25de0aed-aa83-4600-a1be-a62a910af116"
username: "foo@globusid.org"
endpoint_id: "1405823f-0597-4a16-b296-46d4f0ae4b15"
permission_id: "fbe71e48-9fb4-4265-a5b5-4408d8bb5d1b"

auth:
- path: /v2/api/identities
Expand Down Expand Up @@ -32,3 +33,28 @@ transfer:
"access_id": 12345,
"message": "Access rule created successfully."
}
- path: /endpoint/1405823f-0597-4a16-b296-46d4f0ae4b15/access/fbe71e48-9fb4-4265-a5b5-4408d8bb5d1b
method: put
json:
{
"DATA_TYPE": "result",
"code": "Updated",
"message": "Access rule 'fbe71e48-9fb4-4265-a5b5-4408d8bb5d1b' updated successfully",
"request_id": "abc123",
"resource": "/endpoint/1405823f-0597-4a16-b296-46d4f0ae4b15/access/fbe71e48-9fb4-4265-a5b5-4408d8bb5d1b"
}
- path: /endpoint/1405823f-0597-4a16-b296-46d4f0ae4b15/access/fbe71e48-9fb4-4265-a5b5-4408d8bb5d1b
method: get
json:
{
"DATA_TYPE": "access",
"create_time": "2024-12-16T21:30:15+00:00",
"expiration_date": "2025-01-01T00:00:00+00:00",
"id": "fbe71e48-9fb4-4265-a5b5-4408d8bb5d1b",
"path": "/",
"permissions": "rw",
"principal": "25de0aed-aa83-4600-a1be-a62a910af116",
"principal_type": "identity",
"role_id": null,
"role_type": null
}
70 changes: 70 additions & 0 deletions tests/functional/test_permission_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,73 @@ def test_permission_create_username_lookup_fails(run_line):
)
assert "Identity does not exist" in result.stderr
assert "Use --provision-identity" in result.stderr


def test_permission_update(run_line):
meta = load_response_set("cli.endpoint_acl_operations").metadata
endpoint_id = meta["endpoint_id"]
permission_id = meta["permission_id"]

result = run_line(
[
"globus",
"endpoint",
"permission",
"update",
endpoint_id,
permission_id,
"--permissions",
"rw",
"--expiration-date",
"2030-03-30",
],
)
sent_data = json.loads(responses.calls[-1].request.body)
assert sent_data["permissions"] == "rw"
assert sent_data["expiration_date"] == "2030-03-30"


def test_permisison_create_expiration_date(run_line):
meta = load_response_set("cli.endpoint_acl_operations").metadata
endpoint_id = meta["endpoint_id"]

result = run_line(
[
"globus",
"endpoint",
"permission",
"create",
f"{endpoint_id}:/",
"--permissions",
"rw",
"--identity",
"foo@globus.org",
"--expiration-date",
"2030-03-30",
],
)
sent_data = json.loads(responses.calls[-1].request.body)
assert sent_data["expiration_date"] == "2030-03-30"


def test_permission_show(run_line):
meta = load_response_set("cli.endpoint_acl_operations").metadata
endpoint_id = meta["endpoint_id"]
permission_id = meta["permission_id"]

result = run_line(
[
"globus",
"endpoint",
"permission",
"show",
endpoint_id,
permission_id,
],
)

assert f"Rule ID: {permission_id}" in result.stdout
assert "Permissions: rw" in result.stdout
assert "Shared With: foo@globusid.org" in result.stdout
assert "Path: /" in result.stdout
assert "Expiration Date: 2025-01-01T00:00:00+00:00" in result.stdout

0 comments on commit 974bbc4

Please sign in to comment.