Share Platform Resources Across Teams
For the complete documentation index, see llms.txt. For a full content snapshot, see llms-full.txt. Append.mdto anykestra.io/docs/*URL for plain Markdown.
Available on:Enterprise EditionCloud
Publish the resources a platform team owns as assets, so other teams can find them, build on them, and show up in their lineage without being able to change them.
When a platform team provisions shared buckets, databases, or clusters, other teams usually learn about them from a wiki page or a chat message. They then hardcode names in their flows, and nobody can tell which teams depend on which resource. If the platform team registers each resource as an asset, consuming flows pick resources from a live list and declare them as inputs, so the dependencies graph shows every team that uses a resource.
Prerequisites
- A Kestra Enterprise Edition or Cloud instance.
- Two namespaces:
company.platformfor the platform team andcompany.marketingfor a consuming team. - Permission to edit the
company.platformnamespace, to set its allowed namespaces.
Choose namespaced or Global assets
Decide first where the shared assets live. The choice changes who can see them and which flows can change them:
Namespaced in company.platform | Global (no namespace) | |
|---|---|---|
| Who sees them in the UI | Users with ASSET permissions on company.platform | Every user with an ASSET permission in the tenant |
| Which flows can write them | Flows whose namespace company.platform allows | Any flow in the tenant |
| Best for | Resources that one team owns and wants to protect | Catalog entries that every team must see, such as a shared warehouse |
This guide uses namespaced assets so the platform team keeps control over writes. To create Global assets instead, omit namespace on the outputs in the next step. See Namespace and Global assets.
Register the shared resources
This flow in company.platform registers two S3 buckets. Replace the log task with the task that provisions the bucket, and keep the assets block:
id: register_shared_bucketsnamespace: company.platform
tasks: - id: for_each_bucket type: io.kestra.plugin.core.flow.Loop values: - marketing-exports - finance-exports tasks: - id: register_bucket type: io.kestra.plugin.core.log.Log message: "Provisioned s3://acme-{{ item.value }}" assets: outputs: - id: "s3.acme-{{ item.value }}" namespace: company.platform type: company.platform.S3Bucket displayName: "acme-{{ item.value }}" metadata: provider: aws region: eu-west-1 path: "s3://acme-{{ item.value }}" provided_by: platformNotice the conventions that let other teams find and reuse the assets:
- The IDs follow one pattern,
s3.<bucket name>, so consumers can predict them. - The custom type
company.platform.S3Bucketnames the kind of resource. Consumers filter on it. provided_by: platformmarks every asset the platform team publishes, whatever its type.
Reference the resources from a consuming team
This flow in company.marketing lets the user pick a platform bucket, then exports campaign results to it:
id: export_campaign_resultsnamespace: company.marketing
inputs: - id: bucket type: SELECT expression: '{{ assets(type="company.platform.S3Bucket", metadata={"provided_by": "platform"}) | jq(".[].id") }}'
tasks: - id: export type: io.kestra.plugin.core.log.Log message: "Exporting campaign results to {{ inputs.bucket }}" assets: inputs: - id: "{{ inputs.bucket }}" outputs: - id: marketing.campaign_results_export namespace: company.marketing type: io.kestra.plugin.ee.assets.File metadata: bucket: "{{ inputs.bucket }}"Notice these choices:
- The
bucketinput lists the platform buckets at execution time, so nobody types a bucket name by hand. A bucket the platform team registers later appears in the list without a change to this flow. - The
assets()call filters on the type and theprovided_bymetadata key instead of anamespaceargument. See the assets() reference. - The bucket is declared as an input with only its
id. Referencing an asset as an input records lineage and usage without changing the asset.
Don’t add a type to an input that references a shared asset. A typed input changes the stored asset’s type when the two differ, which rewrites the platform team’s asset.
Protect the resources from writes by other teams
By default, every namespace allows every other namespace, so a flow in company.marketing can also declare s3.acme-marketing-exports as an output and change its metadata.
To stop that, restrict the namespaces that can access company.platform:
- Open the
company.platformnamespace and go to the Edit tab. - Under allowed namespaces, select only
company.platform. - Save.
Flows outside company.platform can no longer write the platform’s assets. If a consuming flow declares one as an output, Kestra rejects the write and the task ends in WARNING, or in FAILED if the task sets assetFailureBehavior: FAIL. Input references keep working.
To let one team write the platform’s assets on purpose, add its namespace to the allowed list. Allowed namespaces also control access to the namespace’s flows and other resources, so the team gets that access too. See Allowed namespaces and Cross-namespace writes.
Global assets have no namespace, so this check doesn’t apply to them. Any flow in the tenant can write a Global asset.
Verify the result
- The Assets list shows
s3.acme-marketing-exportsands3.acme-finance-exportsincompany.platform, with thecompany.platform.S3Buckettype. - When you run
export_campaign_results, thebucketinput offers both buckets. - After a run, the bucket’s Dependencies tab shows
export_campaign_resultsreading it and writingmarketing.campaign_results_export. Its Executions tab lists the run.
Next steps
- Asset declaration reference
- Asset best practices for ID and metadata conventions across teams
- Manage assets in the UI, API, and CLI
Was this page helpful?