Directory
Overview
The Directory is the server-wide list of every user and group the server knows, across all metalakes. Each identity carries an origin recording how it got there.
| Origin | Where It Comes From |
|---|---|
| Local | Created in the Directory, with a user name and password stored and managed by Datastrato |
| Provisioned | Sent by your identity provider through SCIM. The identity provider owns it, and the Directory does not add, delete, or change its password |
| JIT | Discovered from the token a user presents at sign-in, for users the identity provider has not provisioned. The identity provider owns it |
Local accounts sign in with a password and are the recovery path when the identity provider is unavailable.
A user name is unique only within its origin. A local user and a provisioned user with the same name are different identities and are not merged.
Local groups can contain local, provisioned, and JIT users.
Directory and authorize
The Directory manages identities. Authorize manages what those identities can do in a metalake.
| Area | What It Covers |
|---|---|
| Directory, for service administrators | Create, disable, and delete local users and groups. List every identity with its origin. Show which metalakes each identity belongs to, read-only |
| Authorize, for metalake owners | Admit a user to the metalake, grant roles to users and groups, and remove members. Authorize cannot create or delete identities |
A user must be admitted to a metalake before a role can be granted there. A group becomes a member of a metalake when a role is granted to it there. See Authorize for roles, grants, and metalake membership.
Deleting a local user removes it from every metalake it belongs to.
Quick start
Creating a local user takes two things: the basic authenticator enabled on the server, and a
service administrator to create the account with.
-
Enable local sign-in. In
my-values.yaml, listbasicamong the authenticators and set the initial administrator account, then apply the values. The install in Install with Helm already does both.my-values.yamlgravitino:
authorization:
enable: true
serviceAdmins: admin
authenticators: "basic"
admin:
username: admin
password: "$ADMIN_PASSWORD"Where users also sign in through an identity provider, list both, with the provider first:
gravitino.authenticators: "oauth,basic". -
Confirm the administrator works. The commands below reuse
ADMIN_PASSWORDand the port forward to the server onlocalhost:8090from Install with Helm.Check the server version as admincurl -s -u "admin:$ADMIN_PASSWORD" \
-H "Accept: application/vnd.gravitino.v1+json" \
http://localhost:8090/api/version | jq '.version.version' -
Create a local user.
Create a local usercurl -s -u "admin:$ADMIN_PASSWORD" -X POST \
-H "Accept: application/vnd.gravitino.v1+json" \
-H "Content-Type: application/json" \
-d '{"user":"{user}","password":"{user_password}"}' \
http://localhost:8090/api/idp/users
The new user can sign in immediately and reaches no metadata until admitted to a metalake, which Granting Access to Metadata covers.
Local users and groups
A local account holds its user name, password hash, and group membership in the server's own relational metadata store, alongside the rest of its metadata. Clients authenticate with HTTP Basic credentials, and nothing outside the server is required.
Local accounts authenticate callers to the server. They do not issue tokens or assertions that other services can consume, so they are not a single sign-on system and not a replacement for Okta, Microsoft Entra ID, or Keycloak. Use them for proofs of concept, isolated deployments, and as the way in when the identity provider is unavailable. For everything else, see Authentication.
Credentials travel in an HTTP header on every request, so run the server behind HTTPS wherever the network is not fully trusted.
The UI reads gravitino.authenticators from the server and presents a user name and password form
when basic is the authenticator in use.
Password and user name rules
The rules below apply to user creation and password changes alike.
| Rule | Value |
|---|---|
| User name | Required, and must not contain a colon |
| Password length | 12 to 64 characters inclusive |
Passwords are reset by an administrator rather than changed by the user, so a password change request carries the new password only and no current password.
User operations
Management endpoints are served under http://{gravitino_host}:8090/api/idp, a path that reflects
the plugin's original name rather than the feature's scope. Every request needs Basic authentication
as a service administrator, an Accept: application/vnd.gravitino.v1+json header, and, where it
carries a body, Content-Type: application/json.
| Operation | Method | Path | Body |
|---|---|---|---|
| Get a user | GET | /api/idp/users/{user} | None |
| Add a user | POST | /api/idp/users | {"user":"alice","password":"{password}"} |
| Reset a password | PUT | /api/idp/users/{user} | {"password":"{new_password}"} |
| Remove a user | DELETE | /api/idp/users/{user} | None |
The add-user body uses the field name user rather than name.
curl -s -u "admin:$ADMIN_PASSWORD" -X POST \
-H "Accept: application/vnd.gravitino.v1+json" \
-H "Content-Type: application/json" \
-d '{"user":"{user}","password":"{user_password}"}' \
http://localhost:8090/api/idp/users
Group operations
| Operation | Method | Path | Body |
|---|---|---|---|
| Get a group | GET | /api/idp/groups/{group} | None |
| Add a group | POST | /api/idp/groups | {"group":"engineering"} |
| Remove a group | DELETE | /api/idp/groups/{group}?force=true | None |
| Change group membership | PUT | /api/idp/groups/{group}/users | {"usersToAdd":["alice"],"usersToRemove":["carol"]} |
The add-group body uses the field name group rather than name. Removing a group that still has
members fails unless force=true. A membership change requires at least one of usersToAdd or
usersToRemove, and accepts both in a single request.
curl -s -u "admin:$ADMIN_PASSWORD" -X PUT \
-H "Accept: application/vnd.gravitino.v1+json" \
-H "Content-Type: application/json" \
-d '{"usersToAdd":["alice","bob"],"usersToRemove":["carol"]}' \
http://localhost:8090/api/idp/groups/engineering/users
Provisioned and JIT users
Provisioned and JIT identities appear in the Directory on their own, one pushed by your identity provider and the other read from a verified token at sign-in. Both are owned by the identity provider, so add, change, and remove them there rather than in the Directory. See SCIM provisioning for provisioned identities and Authentication for the token claims a JIT user is built from.
Metalake membership is not owned by the identity provider. A provisioned or JIT user arrives with none, so admitting them to a metalake is a step taken here.
Granting access to metadata
A user can authenticate as soon as the Directory knows them, and reaches metadata only once admitted to a metalake and granted privileges there. The two are separate steps, and the user name must match the name the user signs in as.
curl -s -u "admin:$ADMIN_PASSWORD" -X POST \
-H "Accept: application/vnd.gravitino.v1+json" \
-H "Content-Type: application/json" \
-d '{"name":"{user}"}' \
http://localhost:8090/api/metalakes/{metalake}/users
When gravitino.authorization.enable is set to true, only service administrators can create
metalakes. See Privileges for roles, privileges, and ownership, and
Manage Metalakes for metalake creation.
Connecting engines
An engine reaches the server by one of two paths, and each takes its own Basic credentials.
Through the Gravitino connector
Configure the connector for each engine, then add the credentials below. See Spark Authentication, Flink Authentication, and Trino Authentication for the rest of the connector setup.
spark.sql.gravitino.authType=basic
spark.sql.gravitino.basic.username={username}
spark.sql.gravitino.basic.password={password}
table.catalog-store.gravitino.gravitino.client.auth.type: basic
table.catalog-store.gravitino.gravitino.client.basic.username: {username}
table.catalog-store.gravitino.gravitino.client.basic.password: {password}
gravitino.client.authType=basic
gravitino.client.basic.username={username}
gravitino.client.basic.password={password}
Trino also needs catalog.management=dynamic in etc/config.properties and a restart before the
catalogs appear.
Through the Iceberg REST endpoint
Engines can connect straight to the Iceberg REST service at http://{gravitino_host}:9001/iceberg/
with no Gravitino connector plugin. See
Connect Spark via Iceberg REST,
Connect Flink via Iceberg REST, and
Connect Trino via Iceberg REST for the rest of the setup.
spark.sql.catalog.{catalog}.rest.auth.type=basic
spark.sql.catalog.{catalog}.rest.auth.basic.username={username}
spark.sql.catalog.{catalog}.rest.auth.basic.password={password}
'rest.auth.type' = 'basic',
'rest.auth.basic.username' = '{username}',
'rest.auth.basic.password' = '{password}'
Trino has no native Basic mode for Iceberg REST and requires Trino 481 or later, so the header is
set directly. Generate the encoded credentials with echo -n '{username}:{password}' | base64.
connector.name=iceberg
iceberg.catalog.type=rest
iceberg.rest-catalog.uri=http://localhost:9001/iceberg
iceberg.rest-catalog.http-headers=Authorization: Basic {base64_credentials}
Related
- Authorize, for admitting identities to a metalake and granting them roles
- SCIM provisioning, for identities pushed by your identity provider
- Authentication, for how a caller proves who they are
- OpenAPI definition, for full request and response schemas of the local account endpoints
- How to Use HTTPS, for protecting credentials in transit
- Privileges, for what an authenticated user is allowed to do