Skip to main content

Connections and secrets

A connection keeps the settings and the secret your code needs to reach a system outside the platform: a database, an API, an object store, a message broker, an SFTP server, or just a token you want out of a notebook. Create it once on Connections in Nova, then read it from a Python notebook by name. The value never enters the notebook file, the image or Git.

Open Connections in the left navigation. The page lists what you may see, grouped by scope, with the settings and the names of the secret fields. It records names and settings, not values: Nova does not return a secret value to the page or to the API.

1. What a connection is​

A connection is a named bundle of two kinds of field:

  • Settings — not secret: host, port, database, bucket, endpoint, base URL, region, bootstrap servers. The page shows them to everyone who may see the connection.
  • Secret fields — the values that must stay hidden: user, password, token, access key, private key. You write them when you create the connection; Nova stores them in the platform's secret store and never shows them again — not to you, not to another member of your group, not in the page, the API, the logs or the query history. The page shows only the field names, for example password, user.

There is one deliberate exception: an administrator can perform a break-glass read of a group connection, with a written reason, and the group is told. Section 7 describes it. Personal and managed values have no such path.

Keeping the value in the store means a notebook contains a name, not a password:

import sqlalchemy
import stardelt

crm = stardelt.connection("crm-db")
engine = sqlalchemy.create_engine(crm.sqlalchemy_url(driver="psycopg"))

Rotating the password changes it in one place; the next crm.value(...) or crm.sqlalchemy_url() reads the new value. Nothing secret is copied into a repository, and deleting the connection removes the value from the store.

2. Three scopes​

The page has one section per scope. The text under each heading is the page's own:

Personal — Only you can see and use these, from a Python notebook. They are never used by pipelines or SQL.

Group: <group name> — Every member of the group can use and rotate these from a Python notebook.

Managed — For platform services only. Nobody can read the values.

PersonalGroupManaged
Who creates itYouAny member of the groupAdministrators only
Who may use itOnly youEvery member of the groupPlatform services only; nothing consumes one today
Who sees its name and settingsOnly youEvery member of the group; administrators also see every group's connectionsAdministrators
Who may rotate or delete itYouMembers rotate and delete; an administrator who is not a member may delete but not create or rotateAdministrators
Where it can be used todayA Python notebook onlyA Python notebook onlyNowhere yet: the page and the store prepare it for platform services that are not built

A group connection belongs to one group, chosen from the groups you are a member of. If you are in no group, you cannot create one; the dialog has no group to offer.

An administrator who is not a member of the owning group sees the group section and the row, but the API marks the row as not theirs (member: false). Creating or rotating it is refused with:

an administrator may delete a connection of the group `analytics` but not create or rotate one

The page still offers Rotate on such a row; the dialog opens and the request is refused with that sentence. Deleting works, and the audit record names the administrator rather than a member.

Managed connections are created by an administrator with one or more groups under Used by. No platform service reads one yet: connection tests, federated catalogs and ingestion are not built. The scope exists so those services have a place to read from when they arrive; a managed row is not usable in a notebook.

3. Create a connection​

  1. Open Connections and choose New connection.
  2. Choose the Scope: Personal, Group or Managed.
    • For Group, pick the Owner group.
    • For Managed, type a group under Used by and press Enter. At least one group is required; at most 20 are accepted.
  3. Choose the Type. The form changes to that type's settings and secret fields.
  4. Choose a Name. It is 1 to 40 lower-case letters, digits and dashes, starting with a letter; the dialog repeats the rule under the field.
  5. Fill the Settings and the Secret fields. Required fields are marked; a field left empty is not sent.
  6. For a group or managed connection, Advanced sets the Refresh interval (1m to 24h, default 15m). It is how often the operator refreshes the synced Kubernetes Secret.
  7. Choose Create connection.

Types and their fields​

The labels and required fields are the dialog's. A field without "required" is optional.

TypeSettingsSecret fields
PostgreSQLHost (required), Port (default 5432), DatabaseUser (required), Password (required)
MySQLHost (required), Port (default 3306), DatabaseUser (required), Password (required)
SQL ServerHost (required), Port (default 1433), DatabaseUser (required), Password (required)
OracleHost (required), Port (default 1521), ServiceUser (required), Password (required)
REST APIBase URL (required)Token: Token (required). Client credentials: Client ID (required), Client secret (required)
Object store (S3)Bucket (required), Endpoint, RegionAccess key ID (required), Secret access key (required)
KafkaBootstrap servers (required)User (required), Password (required)
SFTPHost (required), Port (default 22)Password: User (required), Password (required). Private key: User (required), Private key (required)
Other secret (any fields)None fixed: you name the settingsNone fixed: you name the secret fields; at least one is required

Other secret (any fields) is the type for "I just need to keep a secret". Its API value is generic; the dialog shows the hint For any secret that is not one of the types above: name the settings and secret fields yourself. Name up to 32 settings and up to 16 secret fields. A setting name starts with a letter and uses letters, digits, dots, dashes or underscores; a secret field name starts with a letter and uses letters, digits or underscores. A setting whose name contains password, passwd, passphrase, secret, token or credential is refused — it belongs under Secret fields.

If the name is taken​

Names are unique within a scope. A second connection with the same name in the same place answers:

a connection with this name already exists

Choose another name, or open the existing connection and rotate or delete it. The same name in different scopes is allowed: a personal crm-db and a group crm-db can coexist, and the notebook helper then asks which one you mean (section 4). A group connection's name is also the name of the platform resource behind it, so two groups cannot both own a connection with the same name; the second attempt answers the same sentence.

4. Use it in a Python notebook​

The platform's notebook image ships the stardelt helper. It signs in to the secret store with the notebook's own platform token, so there is no password argument and nothing to paste into the notebook. Values are read when you ask for them and are never kept between calls.

The examples below were run in a Python notebook on the dev platform against throwaway connections; values are shown as ….

Find a connection​

import stardelt

crm = stardelt.connection("crm-db")

The helper looks at your personal connections first, then at each of your groups. If the name exists in more than one place, it refuses to guess:

'shared-secret' exists in more than one place (personal, stardelt-users); pass group=... or scope=... to choose.

Pass scope="personal" or group="analytics" to choose:

personal = stardelt.connection("shared-secret", scope="personal")
group = stardelt.connection("shared-secret", group="analytics")

A group you are not a member of is refused:

you are not a member of the group 'analytics'.

A name that does not exist (or that you may not read) answers:

no connection 'no-such-connection' that you may read. Check the name on the Connections page. Connections that administrators manage are used by the platform for you (a catalog, an ingestion template) and are not revealed to notebooks.

Read one field​

crm = stardelt.connection("crm-db")
crm.value("password")
'…'

value(name) reads the store on every call, so a rotation is visible on the next call. It raises KeyError when the field is not one of the connection's fields, and stardelt.ConnectionUnavailable when the connection was removed or you may no longer read it.

A SQLAlchemy URL​

crm = stardelt.connection("crm-db")
crm.sqlalchemy_url()
'postgresql://…:…@db.example.invalid:5432/crm'

sqlalchemy_url(driver=None) is for the database types (PostgreSQL, MySQL, SQL Server, Oracle). It quotes the user and password, and adds the driver after a + when you pass one, for example sqlalchemy_url(driver="psycopg") → postgresql+psycopg://…. It refuses a non-database connection.

A requests session with the token​

api = stardelt.connection("crm-api")
session = api.requests_session()
session.headers["Authorization"]
'Bearer …'

requests_session() is for a REST API connection with a token field. It returns a requests.Session with the Authorization header set and base_url from the connection's Base URL. For the client-credentials variant, read clientId and clientSecret with value() and obtain the token yourself.

Object-store options​

bucket = stardelt.connection("bucket-scratch")
bucket.s3_options()
{'key': '…', 'secret': '…', 'client_kwargs': {'endpoint_url': 'https://s3.example.invalid', 'region_name': 'eu-central-1'}}

s3_options() is for an S3 connection. Pass the result to s3fs or as storage_options to pandas or PyArrow. key and secret are the access key pair; client_kwargs carries the endpoint and region when you set them.

Printing a connection​

Printing the object shows its name, scope, type and the names of its fields, never a value:

print(stardelt.connection("shared-secret", scope="personal"))
Connection('shared-secret', scope=personal, type='generic', keys=['token'])

Managed connections are not readable​

A managed connection has no reader in a notebook, on purpose:

stardelt.connection("platform-s3", scope="managed")
scope must be 'personal' or 'group' (managed connections are not revealed).

If the only connection with a name is managed, the helper says so in the no-connection error. The page's Use in a notebook disclosure appears for personal and group rows only; a managed row has no snippet.

5. Rotate and delete​

Rotate opens a dialog named after the connection. It lists the connection's secret fields and takes new values:

  • A personal or group connection accepts one or more fields; the fields you leave empty keep their current value. The dialog asks for the new value of at least one field.
  • A managed connection cannot be read back, so every field is required. A partial request is refused with a managed connection cannot be read back, so a rotation sends every field.
  • A connection with no secret fields has nothing to rotate.

A successful rotation clears a break-glass notice on a group connection (section 7).

Delete asks once, in a dialog titled Delete <name>?. It names the connection and says what stops working:

  • Personal: that notebooks using it will fail.
  • Group and managed: Notebooks that use it will fail. Pipelines and catalogs that use it will stop working.

Pipelines and catalogs do not consume connections yet (section 8), so today only the notebook part applies. Deleting removes the value from the secret store and, for a group or managed connection, the Connection resource. An administrator who is not a member of the owning group can delete a group connection; the audit record names the administrator.

6. Status​

The Status column says whether the platform has a usable copy of the connection:

StatusMeaning
StoredA personal connection. The value is in the secret store; there is no Kubernetes sync to report.
ReadyA group or managed connection whose secret has been synced into the Kubernetes Secret the platform uses.
Not readyThe resource exists but the sync has not produced a usable Secret. The page shows the operator's sentence under the status.
UnknownThe platform has no sync status for the row yet; the next reconcile fills it.

A newly created group or managed connection typically starts as Not ready with waiting for the first sync from the secret store, then becomes Ready. When a Secret is missing, the page shows the value does not exist in the secret store yet: create the connection in Nova or write the value first. When the store cannot supply the value, it shows could not get secret data from provider; in the checked installation this happened for a group that has no secret store configured yet. Ask an administrator to check the store for that group.

The Changed column is when the connection or its value last changed; hover for the exact time.

7. What administrators can and cannot do​

An administrator sees:

  • their own personal connections;
  • every group's connections, including groups they are not a member of;
  • the Managed section, including managed connections they did not create.

They see names, settings and secret field names. They do not see personal or managed values. The break-glass action refuses those scopes with break-glass covers group connections only. No administrative request returns a personal or managed value; the owner of a personal connection reads it in their own notebook, as in section 4.

For a group connection, an administrator has one emergency action: Break-glass read. It is offered on group rows only and asks for a Reason of at least 20 characters (at most 500). The dialog says:

The group <group> is told that you read this credential, with your reason.

The read is recorded in the audit log.

Rotate the credential afterwards.

The answer is shown once, masked until Show, and the window closes itself in 60 seconds. Closing it, or leaving the tab hidden for more than ten seconds, drops the values. Five reads per administrator are accepted in ten minutes; a sixth is refused and asks you to wait ten minutes.

The owner group sees a banner above its table:

Read by <administrator> on <date and time>: <reason>. Consider rotating the credential.

with a Rotate now button. A rotation clears the banner. The read is recorded in the audit log and the notice is stored on the group's connection; the audit record carries the administrator, the group, the connection, the reason and the outcome, and never a value.

An administrator can create, rotate and delete managed connections, and create and rotate group connections of groups they belong to. For a group they do not belong to they can delete only: the page marks the row Not your group and offers Delete and Break-glass read without Rotate (a request that sends it anyway is refused with the sentence in section 2), and the audit record marks a successful delete as an administrator's action.

8. Not available yet​

  • Scheduled pipelines. No pipeline task kind consumes a connection. A pipeline cannot read a personal, group or managed connection today.
  • SQL. There is deliberately no secret function in SQL: statements are logged, here and in the engine. A database or API source will become a catalog that an administrator sets up from a managed connection, not a value a query can read.
  • Spark notebooks. A Spark session does not receive connection values. stardelt.connection() is for the Python kernel; use it to fetch a value and pass what the job needs explicitly.
  • Managed connections. No platform service reads one yet. Connection tests, federated catalogs and ingestion are not built.

These consumers are not built yet; the page and the notebook helper say what exists today.

9. Troubleshooting​

MessageWhereWhat it meansWhat to do
the secret store is not configuredNova, Connections page and API (503)This installation has no secret store.Ask an administrator to set it up.
the secret store is unavailable: …Nova (502)Nova could not reach the store.Retry. If it persists, ask an administrator to check the store.
the secret store refused the request: …Nova (502)The store refused the operation, usually a policy or permission.Check that you are in the owning group and that the connection still exists; ask an administrator if it persists.
you are not a member of the group `…` Nova (403)You tried to create, rotate or delete a connection of a group you are not in.Use a connection of your own group, or ask a member of that group.
a connection with this name already existsNova (409)The name is taken in that scope.Choose another name, or rotate or delete the existing connection.
no such connectionNova (404)The connection was deleted, or the scope/group in the request is wrong.Refresh the page.
could not record the notice; nothing was returnedNova, break-glass (502)Nova could not write the notice that tells the group, so it returned no value.Retry. If it persists, ask an administrator to check the cluster.
the secret store is not reachable (ConnectionError)NotebookThe notebook cannot reach the store.Restart the server from the hub. If it persists, ask an administrator.
the secret store refused your sign-in (…) — restart this server from the hub to get a fresh token.NotebookThe notebook's platform token is no longer accepted.Restart the server from the hub.
no connection '…' that you may read.NotebookThe name is wrong, the connection is not yours, or it is managed.Check the name on the Connections page.
'…' exists in more than one place (…); pass group=... or scope=... to choose.NotebookThe same name exists in your personal connections and in a group.Pass scope="personal" or group="<group>".
scope must be 'personal' or 'group' (managed connections are not revealed).NotebookYou asked for a managed connection; notebooks cannot read one.Use a personal or group connection.