Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
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
31 changes: 31 additions & 0 deletions knowledge_base/job_read_secret/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Databricks job that reads a secret from a secret scope

This example demonstrates how to define a secret scope and a job with a task that reads from it in a Databricks Asset Bundle.

It includes and deploys an example secret scope, and a job with a task in a bundle that reads a secret from the secret scope to a Databricks workspace.

For more information about Databricks secrets, see the [documentation](https://docs.databricks.com/aws/en/security/secrets).

## Prerequisites

* Databricks CLI v0.252.0 or above

## Usage

Modify `databricks.yml`:
* Update the `host` field under `workspace` to the Databricks workspace to deploy to

Run `databricks bundle deploy` to deploy the bundle.

Run a script to write a secret to the secret scope:

```
SECRET_SCOPE_NAME=$(databricks bundle summary -o json | jq -r '.resources.secret_scopes.my_secret_scope.name')

databricks secrets put-secret ${SECRET_SCOPE_NAME} example-key --string-value example-value --profile ${DATABRICKS_PROFILE}
```

Run the job:
```
databricks bundle run example_python_job
```
47 changes: 47 additions & 0 deletions knowledge_base/job_read_secret/databricks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
bundle:
name: job-read-secret-example

# workspace:
# host: https://myworkspace.cloud.databricks.com

resources:
secret_scopes:
my_secret_scope:
name: secrets-scope-1
permissions:
- level: CAN_VIEW
group_name: users
- level: CAN_MANAGE
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Admins should have these permissions by default. Is there a reason to explicitly specify them?

Copy link
Copy Markdown
Contributor Author

@anton-107 anton-107 May 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

admins do not have MANAGE permissions by default, only the user creating the scope does

Copy link
Copy Markdown
Contributor

@shreyas-goenka shreyas-goenka May 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this only limited to read permissions?:
https://arc.net/l/quote/fotmmsku

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm referring to permissions that are listed by secret scopes ACL - the only initial permission a new secret scope is getting, is that its create can MANAGE it. For other permissions to show up there, they need to be explicitly declared in the permissions section

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, but do admins have MANAGE permission by default on the scope anyways? The docs seem to imply so.

Note: This is not blocking, an additional permissions block can't really hurt customers. I was curious about the intention though.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the API doc does not say so: https://docs.databricks.com/api/workspace/secrets/createscope

only the initial_manage_principal is getting the MANAGE permission, and when created with DABS, it is always the caller

group_name: admins
jobs:
example_python_job:
name: "example-python-job"
parameters:
- name: "scope_name"
default: ${resources.secret_scopes.my_secret_scope.name}
tasks:
- task_key: example_python_task
spark_python_task:
python_file: "src/example_spark_python_task.py"
parameters:
- --scope_name={{job.parameters.scope_name}}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could simplify this.

Suggested change
- --scope_name={{job.parameters.scope_name}}
- --scope_name=${resources.secret_scopes.my_secret_scope.name}

This way the secret scope name is directly interpolated and you don't have to pass that as a job parameter.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer to keep it this way in the example since this seems to be more idiomatic with the jobs docs and it also documents this particular way (not quite straightforward) to achieve this result


# Defines the targets for this bundle.
# Targets allow you to deploy the same bundle to different Databricks workspaces.
targets:
prod: {
# No overrides
}
dev:
# This target is for development purposes.
# It defaults to the current Databricks workspace.
default: true
mode: development
resources:
secret_scopes:
my_secret_scope:
name: ${workspace.current_user.short_name}-my-secrets
jobs:
example_python_job:
name: "${workspace.current_user.short_name}-example-python-job"

33 changes: 33 additions & 0 deletions knowledge_base/job_read_secret/src/example_spark_python_task.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/usr/bin/env python

import os
from datetime import datetime
import argparse


def main():
# Get current timestamp
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

# Print job information
print(f"Example Python job started at: {now}")

# Read a secret from a passed secret scope
try:
parser = argparse.ArgumentParser()
parser.add_argument("-s", "--scope_name", help="Name of the secret scope")
args = parser.parse_args()
scope_name = args.scope_name

secret_value = dbutils.secrets.get(scope=scope_name, key="example-key")
print(
f"Successfully retrieved secret. First few characters: {secret_value[:3]}***"
)
except Exception as e:
print(f"Could not access secret: {str(e)}")

print("Example Python job completed successfully")


if __name__ == "__main__":
main()