Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added an 'Updated Example' for GCS Guest Collection Creation #1012

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import globus_sdk
from globus_sdk.experimental.globus_app import ClientApp

# Confidential Client ID/Secret - <replace these with real client values>
CONFIDENTIAL_CLIENT_ID = "..."
CONFIDENTIAL_CLIENT_SECRET = "..."
CLIENT_APP = ClientApp(
"my-simple-client-collection",
client_id=CONFIDENTIAL_CLIENT_ID,
client_secret=CONFIDENTIAL_CLIENT_SECRET,
)


# Globus Tutorial Collection 1
# https://app.globus.org/file-manager/collections/6c54cade-bde5-45c1-bdea-f4bd71dba2cc
ENDPOINT_HOSTNAME = "https://b7a4f1.75bc.data.globus.org"
STORAGE_GATEWAY_ID = "947460f6-3fcd-4acc-9683-d71e14e5ace1"
MAPPED_COLLECTION_ID = "6c54cade-bde5-45c1-bdea-f4bd71dba2cc"


def main():
gcs_client = globus_sdk.GCSClient(ENDPOINT_HOSTNAME, app=CLIENT_APP)

# Comment out this line if the mapped collection is high assurance
attach_data_access_scope(gcs_client, MAPPED_COLLECTION_ID)

ensure_user_credential(gcs_client)

collection_request = globus_sdk.GuestCollectionDocument(
public=True,
collection_base_path="/",
display_name="example_guest_collection",
mapped_collection_id=MAPPED_COLLECTION_ID,
)

collection = gcs_client.create_collection(collection_request)
print(f"Created guest collection. Collection ID: {collection['id']}")


def attach_data_access_scope(gcs_client, collection_id):
"""Compose and attach a ``data_access`` scope for the supplied collection"""
endpoint_scopes = gcs_client.get_gcs_endpoint_scopes(gcs_client.endpoint_client_id)
collection_scopes = gcs_client.get_gcs_collection_scopes(collection_id)

manage_collections = globus_sdk.Scope(endpoint_scopes.manage_collections)
data_access = globus_sdk.Scope(collection_scopes.data_access, optional=True)

manage_collections.add_dependency(data_access)

gcs_client.add_app_scope(manage_collections)


def ensure_user_credential(gcs_client):
"""
Ensure that the client has a user credential on the client.
This is the mapping between Globus Auth (OAuth2) and the local system's permissions.
"""
try:
# Depending on the endpoint & storage gateway, this request document may need to
# include more complex information such as a local username.
# Consult with the endpoint owner for more detailed info on user mappings and
# other specific requirements.
req = globus_sdk.UserCredentialDocument(storage_gateway_id=STORAGE_GATEWAY_ID)
gcs_client.create_user_credential(req)
derek-globus marked this conversation as resolved.
Show resolved Hide resolved
except globus_sdk.GCSAPIError as err:
# If a User Credential already exists; no need to create it.
derek-globus marked this conversation as resolved.
Show resolved Hide resolved
if err.http_status != 409:
raise


if __name__ == "__main__":
main()
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@

# Tutorial Client ID - <replace this with your own client>
NATIVE_CLIENT_ID = "61338d24-54d5-408f-a10d-66c06b59f6d2"
USER_APP = UserApp("my-simple-transfer", client_id=NATIVE_CLIENT_ID)
USER_APP = UserApp("my-simple-user-collection", client_id=NATIVE_CLIENT_ID)

# Globus Tutorial Collection 1
# https://app.globus.org/file-manager/collections/6c54cade-bde5-45c1-bdea-f4bd71dba2cc
ENDPOINT_HOSTNAME = "https://b7a4f1.75bc.data.globus.org"
STORAGE_GATEWAY_ID = "947460f6-3fcd-4acc-9683-d71e14e5ace1"
MAPPED_COLLECTION_ID = "6c54cade-bde5-45c1-bdea-f4bd71dba2cc"


Expand All @@ -17,6 +18,8 @@ def main():
# Comment out this line if the mapped collection is high assurance
attach_data_access_scope(gcs_client, MAPPED_COLLECTION_ID)

ensure_user_credential(gcs_client)

collection_request = globus_sdk.GuestCollectionDocument(
public=True,
collection_base_path="/",
Expand All @@ -41,5 +44,23 @@ def attach_data_access_scope(gcs_client, collection_id):
gcs_client.add_app_scope(manage_collections)


def ensure_user_credential(gcs_client):
"""
Ensure that the user has a user credential on the client.
This is the mapping between Globus Auth (OAuth2) and the local system's permissions.
"""
try:
# Depending on the endpoint & storage gateway, this request document may need to
# include more complex information such as a local username.
# Consult with the endpoint owner for more detailed info on user mappings and
# other particular requirements.
req = globus_sdk.UserCredentialDocument(storage_gateway_id=STORAGE_GATEWAY_ID)
gcs_client.create_user_credential(req)
derek-globus marked this conversation as resolved.
Show resolved Hide resolved
except globus_sdk.GCSAPIError as err:
# If a User Credential already exists; no need to create it.
derek-globus marked this conversation as resolved.
Show resolved Hide resolved
if err.http_status != 409:
raise


if __name__ == "__main__":
main()
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,60 @@
Creating a Guest Collection
===========================

TODO
Within the Globus Ecosystem, data is managed through the abstraction of *Collections*.
The example included on this page demonstrate how to create specifically a
*Guest Collection* using the Globus Python SDK. Guest collections, formerly known as
kurtmckee marked this conversation as resolved.
Show resolved Hide resolved
"Shares", are collections which provide access to a subdirectory of an existing
collection through a particular user or client's local permissions.

.. literalinclude:: user_guest_collection.py
:caption: ``user_guest_collection.py`` [:download:`download <user_guest_collection.py>`]
:language: python
Guest collections are a great way to set up data automation. They may be scoped down
to a particular directory within an existing "Mapped Collection" and don't implicitly
inherit the same authorization timeout requirements as their parent Mapped Collection.
Once created, they can be shared to other users/entities, in effect giving another
entity access, through you, to some underlying data.

.. Note::
derek-globus marked this conversation as resolved.
Show resolved Hide resolved

While guest collections don't implicitly inherit their parent mapped collection's
authorization timeout in some cases they do or alternatively may be disabled
entirely. This is a decision made by the endpoint owner, not Globus.

Because requirements can vary so drastically between endpoints, we recommend
consulting with the particular endpoint's documentation and/or owner to determine
whether guest collections provide the desired level of access with the desired
minimization of authorization.

.. Note::

The scripts reference a globus hosted "tutorial" mapped collection. This is just
to provide as simple of a functioning example out of the box as possible.

For actual application, replace the ids with the actual relevant collection and
derek-globus marked this conversation as resolved.
Show resolved Hide resolved
storage gateway IDs.


.. tab-set::

.. tab-item:: User-owned Collection

This script demonstrates how to create a guest collection owned by a human.

It will prompt the user to authenticate through a browser and authorize the
script to act on their behalf.

.. literalinclude:: create_guest_collection_user_owned.py
:caption: ``create_guest_collection_user_owned.py`` [:download:`download <create_guest_collection_user_owned.py>`]
:language: python


.. tab-item:: Client-owned Collection

This script demonstrates how to create a guest collection owned by a client (
e.g. a service account).
derek-globus marked this conversation as resolved.
Show resolved Hide resolved

It will automatically request and use client access tokens based on the supplied
client id and secret.
derek-globus marked this conversation as resolved.
Show resolved Hide resolved

.. literalinclude:: create_guest_collection_client_owned.py
:caption: ``create_guest_collection_client_owned.py`` [:download:`download <create_guest_collection_client_owned.py>`]
:language: python
Loading