TripleBlind User Guide

Asset Owner Operations

Asset Owners position their dataset or algorithm assets on their organization’s Access Point, and have full control over who can use their assets.

Positioning Dataset Assets

Positioning an asset is the process of placing your data file inside your own infrastructure's Access Point and indexing that asset on the TripleBlind Router. Positioning assets is the first step toward monetizing your data or training collaborative and distributed algorithms, while also preserving the privacy of your data.

Positioned data never leaves your organization's firewall. TripleBlind never hosts or has access to your data. The only route to your data is through your own Access Point, which is controlled by your organization. You can position your data either through the TripleBlind web interface or the SDK.

There are two primary types of dataset assets, those that are attached via files and those that are attached via databases. Once positioned, the content in a file-based dataset is static once it has been placed on your Access Point. The content in a database-based dataset is dynamic. The fields are always the same, but the number and content of records comes from the database at the time the algorithm is executed.

File-based Datasets

The following sections describe how to position file-based datasets via the web interface and the SDK.

Web Interface

You can use an intuitive web interface to position your datasets. Tabular CSV data is currently supported. Visit the Explore Assets > Position Dataset page and follow the instructions.

Along with providing the file containing the dataset, you provide the following information:

  • Listing Name
    A descriptor for the dataset. The name is used when listing or searching for your dataset in the Data Explorer. The best names are descriptive, but short.
  • k-Grouping
    Inspired by k-anonymity, TripleBlind supports configuration of a “k-Grouping” safeguard at the dataset-level. See k-Grouping for more information about how TripleBlind honors k-Grouping in various operations.
  • Visibility
    Control whether to list your dataset in the public listing of available datasets or not. If "Public,” users from other organizations will know of the existence and see summaries of the dataset, but they will not be able to see the contents or operate on it without requesting your permission first.
  • Description
    A freeform area to convey in-depth information about the dataset. The description can use Markdown formatting to present images, tables, links and other rich text tools. The Preview tab allows you to see the description as it will appear in the web interface. Good descriptions include technical details about the dataset, as this is the primary way other organizations learn about your dataset.

All of these properties of the dataset can be changed by the owner after the dataset is positioned.

ℹ️Positioning data on your Access Point is convenient through the web interface, but be aware that the content will briefly pass through TripleBlind's servers when you use this method. To keep your data 100% private, use the SDK method to position data.

SDK

File-based datasets can also be positioned using the SDK. This positioning example includes snippets of Python code that highlight important commands, but might not include all setup code needed to run independently.

This code example provides the basic APIs to position and manage data using the TripleBlind library. Any data file (dataset or algorithm) can become an Asset. This example uses a basic comma separated value (CSV) file. The first step is to pull in the library so you can connect to the TripleBlind Router and your own Access Point. This statement needs to be in all scripts using the TripleBlind SDK.

import tripleblind as tb
tb
.session.debug_session_traffic = True

Now use the library to position a local data file on your Access Point. This example uses the file Meteorite_Landings.csv that comes with the SDK.

my_dataset = tb.Asset.position(
# path to the local data file to position
file_handle = tb.util.script_dir() / "data" / "NASA_Meteorite_Landings.csv",
# give your dataset a name
name = "NASA Meteorite Landings",
# describe your data
desc = "A dataset for Meteorite Landings from NASA...",
# Make the dataset discoverable by other users in the Data Explorer
is_discoverable = True,
)
print(f"Successfully created: {my_dataset.name}, ID: {my_dataset.uuid}")

You can find ready-to-run and more detailed Python scripts in the tutorials, examples, and demos directories included with the SDK.

Database Assets

Database Assets contain tabular data. They consist of columns, or fields, and rows, or records. A single record will contain all of the fields, even if it is an empty value. Database assets are dynamic. The fields are always the same, but the number and content of records comes from the database at the time the algorithm is executed. The actual data is not stored on the Access Point, only a set of instructions for connecting to the database and for extracting a data view. Database assets can be positioned using the SDK or the TripleBlind web interface.

Connection Strings

A connection string is like a URL to reach a web page. The string specifies the type of database, login information and the specific portion of the database you want to access.

The exact format of the connection string varies for different database vendors. Typically, it is in the form of dialect+driver://username:password@host:port/database. Currently, TripleBlind supports self-hosted database instances of PostgreSQL, MySQL, SQLite and Microsoft SQL Server. TripleBlind also supports many data warehouse services, including Snowflake and BigQuery, and provides helper classes to assist in creating the connection to these services.

ℹ️You may be concerned about the security of the connection string, as most contain sensitive data, like a database user and password. This sensitive data remains in your control at all times. The Database Asset is registered with the TripleBlind Router, but the actual asset is stored on your Access Point. When you define the asset, the SDK communication that creates it also occurs directly between your workstation and your Access Point. Nothing sensitive is sent to a server controlled by TripleBlind or by a partner that uses your asset.

Using Named Secrets
Connection strings often include sensitive information such as usernames and passwords or credential tokens. These sensitive portions can be protected using named secrets. The name of the secret can be shared within your organization freely, only Access Point administrators are able to create or delete these secret values and they cannot be viewed by anyone once they have been set. See the Secrets Management section under Access Point Administration for more information on how to create named secrets.

When you are given the name of a secret, you can utilize it when creating any Database Asset via the connection string or other parameters documented to support named secrets in the asset’s create() method. The secret name must simply be enclosed in double curly brackets. For example, if your administrator told you the secret names “OUR_SECRET_USERNAME” and OUR_“SECRET_PASSWORD”, you can use these secrets to create an asset like this:


asset = tb.asset.MSSQLDatabase.create(
host="testsqlserver123.database.windows.net",
port=1433,
database="SampleDatabase",
username="{{OUR_SECRET_USERNAME}}",
password="{{OUR_SECRET_PASSWORD}}",
query=SQL_VIEW,
name="MSSQL Demo DB",
desc="MSSQL Database Asset",
is_discoverable=True,
)
Database View

Once you provide the connection to the database, you describe what data you want included in this database asset. This is done by creating a view on the data using an SQL query. Only the result of the query is made available to TripleBlind users.

Snowflake Asset

As an example, we will look at defining an asset for information housed in a 🔗Snowflake cloud data warehouse.

First, connect to your Snowflake dashboard in your browser:

Here we see the database TEST_DATABASE has a table called "PEOPLE" which we want to make available on the TripleBlind platform for controlled access.

ℹ️You might be wondering why you can't just provide direct access as a shared Snowflake database. When you share a database you have control over who gets to your data, but you have no idea what they do with it. TripleBlind can completely restrict the usage to only the exact algorithm you approve, which you also know guarantees the data is never seen in the clear. You will also have a full audit of exactly when your data was accessed.

Creating the Asset

First, pull in the TripleBlind SDK library.

import tripleblind as tb
tb
.util.set_script_dir_current()

Now you need the information needed to establish your connection with the database shown above. You'll need your username and password, plus the account. For Snowflake, the account is the same as the start of the web interface URL, before "snowflakecomputing.com/".

To avoid storing these sensitive details in a script, they are often stored in environment variables. The comments in the following example show the environment variables used by Snowflake, in case you want to take this approach. However, the example provides these values as simple strings.

You will need to use your own Snowflake account information for this example to work.

username = "steve"
password = "password123"
account = "yj91180.us-central1.gcp"
database = "TEST_DATABASE"

The final thing you need to do is create the view you want to expose on the database. This is done with an SQL query. The simplest approach is to include all of the values in a particular table.

try:
tb.asset.SnowflakeDatabase.create(
snowflake_username = username,
snowflake_password = password,
snowflake_account = account,
snowflake_database = database,
query = "SELECT * FROM sant_train LIMIT 500 OFFSET 50;",
name = "Snowflake example dataset",
desc = "Dataset housed in a Snowflake data warehouse",
is_discoverable = True,
)
except tb.TripleblindAssetAlreadyExists:
print("Asset already exists")

Since the query is SQL, you have full control of how much you want to expose in this database asset. You could limit it to only certain fields or portions of the table using a WHERE clause.

Using the Asset

This asset is used just like a CSVDataset⁠—in fact, it is indistinguishable to the process. A preprocessor can be used to eliminate fields you aren't interested in for the particular operation.

Another example would be a Human Resources database that contains hundreds of fields for each employee. However, when you want to train a machine learning model to predict employee churn, you might only care about the fields "hire-date," "birth-date," "gender," "zip code," "salary," and "title." The preprocessor would name these fields, and all of the others will be omitted when training the model.

Back to our example, here are a few simple queries we can run using this asset.

search = tb.TableAsset.find_all("Snowflake example dataset", dataset=True)
table = tb.TableAsset.cast(search[0])
# Generate a simple headcount
result = table.search(
   "gender",
   pattern=["m", "f"],
   match_case=False,
   silent=True,
)
# Generate a quick analysis of employee types
result = table.search(
   "position",
   pattern=["director", "vp", "manager", "clerk"],
   match_case=False,
   silent=True,
)

Connectors

Many popular databases and data warehouse sources may be accessed in a similar manner.

Below are supported connectors. Many use the DatabaseDataset connector class, though a few use specific connectors.

Amazon Redshift

Redshift is a data warehouse that has a specific method for asset creation:

tb.asset.RedshiftDatabase.create(
   host = "default.528655681674.us-east-2.redshift-serverless.amazonaws.com",
   port = 5439,
   database = "RedshiftDB",
   username = "akos",
   password = "my_pass",
   query = "SELECT * FROM public."demo_pii" where n1 > .21;",
   name = "Demo DB",
   desc = "Redshift Database using credentials",
   is_discoverable = True,
)

The Redshift connector supports additional connection 🔗options such as IAM:

tb.asset.RedshiftDatabase.create(
   host = "default.528655681674.us-east-2.redshift-serverless.amazonaws.com",
   port = 5439,
   database = "RedshiftDB",
   options = {
      "iam" : True,
      "access_key_id" : "XXXXXXXXXXXXXXXXXXXXXXXXX",
      "secret_access_key" : "XXXXXXXXXXXXXXXXXXXXXXXXX",
   },
   query = "SELECT * FROM public."demo_pii" where n1 > .21;",
   name = "Demo DB",
   desc = "Redshift Database using IAM",
   is_discoverable = True,
)
Amazon S3
tb.asset.S3Dataset.create(
   bucket_name = "9bec276a-68c7-1234-aa91-ff93c418e600",
   region = "us-east-1",
   object_name = "test_data.csv",
   aws_access_key_id = "XXXXXXXXXXXXXXXXXXXXXXXXX",
   aws_secret_access_key = "XXXXXXXXXXXXXXXXXXXXXXXXX",
   name = "Demo Asset",
   desc = "CSV dataset in an S3 bucket",
   is_discoverable = False,
)
Google BigQuery

The BigQuery authentication mechanism is slightly different. You must provide a GCP project id, which will be billed for any data transfer fee associated with accessing this dataset. The specifics of costs are between you and GCP, but typically something like the first TB per month of data transfer is free.

Access credentials come from Google. See 🔗JSON keyfile authentication documentation for details.

credential_file = "bigquery_credentials.json"

tb.asset.BigQueryDatabase.create(
   gcp_project = "tripleblind-datasets",
   bigquery_dataset = "salary_dataset",
   credentials = credential_file,
   query = "SELECT * FROM `1m_salaries` LIMIT 10;",
   name = "Demo Salaries",
   desc = "Salary information stored in BigQuery",
   is_discoverable = False,
)
Microsoft Azure Blob Storage
tb.asset.AzureBlobStorageDataset.create(
   storage_account_name = "azure_demo_account",
   storage_key = "Your+SecretKey4ADSL+CSVDataNdBaot72ymJa8JBL1B/q9daL+AStOCNjBA==",
   file_system = "demo",
   key = "iris.csv",     # file system name defined in Azure control panel
   name = "Demo DB",
   desc = "CSV dataset in an Azure Blob",
   is_discoverable = True,
)
Microsoft Azure Data Lake

This connector supports Azure Data Lake Storage built on top of Azure Blob Storage.

tb.asset.AzureDataLakeStorageDataset.create(
   storage_account_name = "azure_demo",
   storage_key = "Your+SecretKey4ADSL+CSVDataNdBaot72ymJa8JBL1B/q9daL+AStOCNjBA==",
   file_system = "demo",
   path = "/datasets/csv/iris.csv",
   aws_secret_access_key = "XXXXXXXXXXXXXXXXXXXXXXXXX",
   name = "Demo DB",
   desc = "CSV dataset in an Azure Data Lake",
   is_discoverable = True,
)
Microsoft SQL Server
# via pyodbc
connection_str = "mssql+pyodbc://user:pass@mydsn"
# or pymssql
connection_str = "mssql+pymssql://user:pass@hostname:port/dbname"

tb.asset.DatabaseDataset.create(
   connection = connection_str,
   query = "SELECT * FROM tablename;",
   name = "Oracle example dataset",
)
MongoDB

TripleBlind supports multiple MongoDB connection URI formats. See the MongoDB example in examples/Data_Connectors for more information.

tb.asset.MongoDatabase.create(
   connection_str = f"mongodb://{user}:{password}@{mongo_host}:{mongo_port}/",
   query = {},
   projection = {
      "gpa" : 1,
      "age" : 1,
      "admitted" : 1,
   },
   database = "student_records",
   collection = "college_acceptance",
   name = "Demo College Acceptance",
   desc = "College acceptance dataset stored in MongoDB",
   is_discoverable = False,
)
MySQL
tb.asset.DatabaseDataset.create(
   connection = "mysql://user:pass@host:5432/database",
   query = "SELECT * FROM tablename;",
   name = "MySQL example dataset",
)
Oracle
connection_str = "oracle+cx_oracle://user:pass@tnsname"
# or
connection_str = "oracle://user:pass@host:port/sidname"

tb.asset.DatabaseDataset.create(
   connection = connection_str,
   query ="SELECT * FROM tablename;",
   name = "Oracle example dataset",
)
Postgres
tb.asset.DatabaseDataset.create(
   connection = "postgresql://user:pass@host:5432/database",
   query = "SELECT * FROM tablename;",
   name = "Postgres example dataset",
)
SQLite
# use four slashes before the path
connection_str = "sqlite:////absolute/path/to/foo.db"

tb.asset.DatabaseDataset.create(
   connection = connection_str,
   query = "SELECT * FROM tablename;",
   name = "SQLite example dataset",
)

Support for other databases is possible. Contact our customer support team at 🔗Customer Support to request sources not listed here.

Positioning Database Assets using the TripleBlind Web Interface

Database assets can also be positioned by making use of an easy-to-follow wizard in the TripleBlind web interface. To begin this process, first log in to the web interface using your TripleBlind credentials. Then, navigate to the Assets page and click the New Asset button. You will be presented with a menu of database and file type options to start with.

In this example, we will configure an Amazon Redshift asset. To launch the wizard, click the Redshift icon.


Enter in your hostname, database name, username and password. If using AWS IAM to connect to Redshift, select the IAM radio button and input your access key and secret. Click Next.

On the next step of the wizard, you can input a query that will be used to pull data from the connected Redshift database. This query can be used to limit the data available through the positioned asset to specific columns and rows. After adding the query, click Next.

In the final step of the wizard, you can define the name and description of the asset (leveraging Markdown for formatting or embedding of images). As with the SDK, the k-grouping and visibility can be selected here.

Clicking the Position button will test the connection to the database. An error message will appear in the bottom left corner of the screen if the connection is not successful. Once the connection has been established, the Asset Details screen will be shown for the newly connected database asset. Nice job!

Dataset Information

After positioning a dataset, it will show up in Explore Assets on the TripleBlind web interface. If you have made the dataset public, then it will also show up for other organizations.

The Overview tab for a tabular file-based Dataset Asset contains a 10-record set of representative data of the dataset that allows Asset Users to visualize the shape of the data. As the Asset Owner, you have complete control over what is displayed here (see Managing Assets for more information).

The Data Profile tab for a CSV dataset contains an exploratory data analysis (EDA) report, which provides summaries and statistics about the dataset without revealing the actual contents. Data scientists can use this information to determine the utility of a dataset for their purposes.

Managing Assets

Once an asset is on the Access Point, it can be managed from the web interface or the SDK.

Web Interface

To edit an asset via the web interface, visit the 🔗Explore Assets page and filter by My Assets to see assets that you own. Select an asset to view it, and then click the Edit button.

The asset name, k-Grouping, visibility, description, and default download filename may be modified here.

Datasets are always positioned with every field masked to ensure complete privacy-protection. By default, a masked text field displays values containing random letter characters of varying length, while a masked numerical field displays values randomly generated within the range of the underlying data (and at the appropriate decimal precision).

The Overview includes a 10-record representative mock data table, which you can modify using the tools described below. The field-level configurations described here are also applied to any Blind Sample processes requested by an Asset User for this Dataset.

ℹ️ These modifications only alter the representative mock data table displayed on the Overview tab, and do not change the underlying dataset. When a Process is run on the dataset, the real raw data will be used for the computation. Certain operations (like Blind Join and Blind Query) have restrictions when using datasets with masked fields. See Privacy Assurances and Risk in Getting Started for more information.

Click on the column headers to rename fields to more reader-friendly versions.

Clicking on the mask icons below the column names allows you to selectively unmask fields considered safe for display. This will sample 10 random values from the underlying data and display them “out-of-context” of their originating records. This shuffled sample is not recommended for any field that may contain sensitive information.

If a column has already been unmasked, clicking the mask icon again will allow you to replace field values with realistic, reader-friendly synthetic values. This is useful for masking sensitive identifying information like phone numbers and addresses.

You can also replace any specific values (at the cell-level) with NULL or a custom value (keyed-in directly).

Multiple fields can be masked simultaneously by opening the “Bulk Masking” dialog (click the button to the right of the search bar).

After making your changes, click “Save” to commit your changes and view your shiny new Asset Details page.

SDK

Alternatively, you can manage your assets directly from Python code using our APIs. In the following code snippets, we illustrate how to:

  • rename an asset (Asset.name)
  • update the description (Asset.desc)
  • update the default file name (Asset.filename)
  • change discoverability: (Asset.is_discoverable)
  • retrieve an asset you own (Asset.retrieve())
  • remove an asset (Asset.archive())
  • apply masking types (TableAsset.mask_columns)
  • unmask fields (TableAsset.unmask_columns)

To manage an asset using the SDK, first you need to have an Asset object. You can access an asset, whether you own it or not, from the SDK using one of the following methods:

  • Using the asset UUID, which can be obtained in the web interface
  • Search for the asset by name or a keyword using Asset.find() and Asset.find_all() from the SDK

In the following code example, we search for all datasets that have the keyword "Bank" and then print their names and IDs to see which are of interest to us. Many tasks can consume multiple datasets, such as using datasets from different organizations to build an image classifier.

search_results = tb.Asset.find_all("Customer Database", dataset=True)

if search_results:
   print(f"Found {len(search_results)} dataset(s) with the keyword 'Customer Database':")
   for dataset in search_results:
       print(f"'{dataset.name}', ID: {dataset.uuid}")
else:
   print("No results...")
#### use a dataset of interest using its UUID or subscripts (e.g., search_results[0])
dataset = search_results

Here we connect to the "NASA Meteorite Landings Dataset" asset provided by TripleBlind.

my_dataset = tb.Asset("27e6e5e6-c281-425e-8a82-06e3d0c8dcc9")
print(my_dataset.name)

Next we'll change some properties of the meteorite dataset you created above.

#### rename the asset
print(f"Previous dataset name: {my_dataset.name}")
my_dataset.name = "Meteorite Landings Dataset"
print(f"New dataset name: {my_dataset.name}")

#### update the description
print(f"Previous description: {my_dataset.desc}")
my_dataset.desc = "A new *markdown* description on my dataset."  # markdown tags will show in the web interface
print(f"New description: {my_dataset.desc}")

The filename property is the default name used when retrieving the asset, if no other name is specified. Notice that the name we are using has a ".zip"⁠—that's because the act of positioning data packaged it up, which wraps the dataset in a zip archive along with metadata. For a CSV the data is only a single file, but other dataset packages might have many files, such as an image training set.

#### change the default file name
print(f"Previous file name: {my_dataset.filename}")
my_dataset.filename = "Meteorite_Landings_v1.csv.zip"
print(f"New file name: {my_dataset.filename}")

As the owner of this asset, we can also retrieve it. This is only possible for assets your organization owns.

my_dataset.retrieve(overwrite=True)

You can also archive an Asset. If you set remote_delete = FALSE, the actual data remains on your Access Point. Either way, the Asset is removed from the index on the Router and can no longer be shared with anyone.

my_dataset.archive(remote_delete=True)

If you have permission to manage the dataset, you can use SDK methods to mask or unmask fields programmatically.

table = tb.TableAsset.find(f"Blind_Sample-CSV{run_id}")

# The SSN, Name, and home_phone column names are auto-detected to appropriate
# data masking types, but "addr" isn't and needs to be explicitly configured to
# output samples using address masking.
table.mask_columns(col_names="addr", mask_type=MockType.address)

# By default all values are masked, but we have determined that there are four
# values in this dataset which aren't sensitive and can be viewed. Unmask them.
table.unmask_columns(col_names=["n1", "n2", "n3", "gender"])

ℹ️Assets can either be destroyed or just delisted from the Router via Asset.archive(remote_delete=False). Either way, the audit records remain intact and the dataset can no longer be used for other operations.

Command Line Tools

All of the asset management functionality is available from the tb.py utility that comes with the SDK. It can quickly be used from the command line instead of writing custom Python programs to do simple tasks.

Here are some examples of how you can use this utility. To view the NASA Meteorite Landings dataset, you could run:

python tb.py list "NASA Meteorite Landings"

Or, even simpler, you can run the script directly on Mac and Linux systems:

./tb.py list "NASA Meteorite Landings"

We'll stick with this simpler way for the rest of the examples.

List assets found during the last months of 2020:

./tb.py list --since=11-1-2020 --before=1-1-2021

List data assets belonging to you:

./tb.py list data --mine

Find assets with "Bank" or "bank" in the name, using a regular expression match:

./tb.py list /[Bb]ank/

The same utility can set properties. Here we'll change the description of the dataset:

./tb.py set "NASA Meteorite Landings" desc "Changed from command line!"

Retrieve a copy of an asset you own:

./tb.py retrieve "NASA Meteorite Landings" nasa.csv

And even destroy your dataset:

./tb.py remove "NASA Meteorite Landings" --delete

Create a simple data asset:

./tb.py create nasa.csv --name "NASA Meteorite Landings" --desc "NASA data" --public

ℹ️ If --name and --desc weren't included, you would be prompted for them interactively.

For a full list of capabilities:

./tb.py --help

TIP: You can run these commands within a Jupyter notebook by adding "!" before the command, like this:

! ./tb.py --help

Managing Access to Assets

Granting permission means enabling other organizations to use your data privately to train an algorithm or run some data analysis task. However, your data will never leave your infrastructure and will never be revealed to the organization requesting the job or to TripleBlind. To learn more about our secure and privacy-preserving techniques, visit 🔗tripleblind.com.

When a user outside of your organization wants to use an asset that you own, such as a dataset, you must explicitly grant permission for each use.

Access Requests

To view and grant permission, visit the 🔗Requests page in the web interface.

Asset not accessible

There are situations in which it is not possible to display the metadata of an asset listed within an Access Request, Audit record, or Process history, specifically:

  • The asset belongs to a third-party in the Process, and the third-party asset is not discoverable to the Asset Owner’s organization.
  • An Agreement that was available at the time of the request has expired or been rescinded, and the Asset is no longer discoverable to the Asset Owner’s organization.
  • The asset has been archived on the counterparty’s Access Point (or otherwise made inaccessible), and may no longer be used in computations.

Agreements

Granting permissions can become repetitive when working with a close partner organization that is running multiple trainings or analyses using your dataset. Agreements allow you to automate this process while still retaining control over your data. Each time your assets are accessed, the details are still recorded and logged in audit records. See the 🔗Audit page for audit records pertaining to the assets in your organization.

Agreements are very versatile. They can be established for a specific asset or all assets in your organization, providing access to a single outside organization or all organizations on TripleBlind. You can create Agreements that provide view-only access to the asset(s) they cover or only allow certain pre-selected operations. Finally, you can set limitations on the agreement by setting an expiration date or a cap on the number of uses your counterparty is allowed.

To create an Agreement that covers a single Asset:

  1. Navigate to the asset you wish to create an Agreement for, or click New Agreement and search for it on the Agreements page.
  2. Select the organization that you want to create the Agreement with, or select “All Teams”.
  3. Select the operation you wish to allow on the selected Asset or click “Visibility-only Agreement”.
  4. Establish limitations by setting a usage cap, expiration date, both, or neither.

In the SDK, you can utilize the add_agreement method on the asset you wish to create the Agreement for. In the parameters, you must specify the organization or set it to "ANY" and can also set an expiration date, allowed operation, number of uses and security level. The below example shows positioning an asset and creating an agreement for any org to conduct inference against it. See the tripleblind.asset documentation for more details.

Try:
dataset1 = tb.Asset.position(
file_handle=tb.Package.load(data_dir /
"EXAMPLE_train_cifar_0.zip"),
name=name1,
desc=desc1,
is_discoverable=
True,
)
except tb.TripleblindAssetAlreadyExists:
print(
f"Asset '{name1}' already exists.'")
dataset1 = tb.Asset.find(name1, owned_by=tb.config.example_user1[
"org_id"])
dataset1.add_agreement(with_org="ANY", operation=tb.Operation.BLIND_LEARNING)
print(
"Created Agreement for any to train against this dataset.\n")

Currently, creating an Agreement that allows access to ALL assets within your organization can only be performed using the SDK. This operation makes use of the Agreement.create() method and the asset_restricted=False parameter. As an asset ID is still expected, the ID of any asset positioned to your organization can be passed. Additionally, you must specify an operation. The resulting Agreement shows as being for “All” Assets.

tb.Agreement.create(to_org=1,
asset_id=
"82c8f83a-a952-43c4-b780-279282e62bdc",
asset_restricted=
False,
protocol=tb.job.MEDIAN,
algorithm_security=
"SMPC")

print(
"Created Agreement for any to train against this dataset.\n")