| name | openmetadata-ops |
| description | Administer OpenMetadata platform including users, teams, bots, roles, policies, and security. Use when managing access control, configuring SSO, creating service accounts, setting up team hierarchies, or troubleshooting authentication issues. |
OpenMetadata Operations
Guide for administering OpenMetadata platform: users, teams, bots, roles, policies, security configuration, and operational tasks.
When to Use This Skill
- Managing users and team hierarchies
- Creating and configuring bots (service accounts)
- Setting up roles and policies (RBAC/ABAC)
- Configuring SSO and authentication providers
- Managing JWT tokens and API access
- Troubleshooting authentication and authorization issues
This Skill Does NOT Cover
- Building OpenMetadata SDKs (see
openmetadata-sdk-dev) - Using SDKs/APIs to build integrations (see
openmetadata-dev) - Deploying OpenMetadata infrastructure (Kubernetes, Docker)
- Database administration for OpenMetadata backend
Team Hierarchy
Team Types
OpenMetadata uses a hierarchical team structure:
Organization (root)
├── Business Unit
│ ├── Division
│ │ ├── Department
│ │ │ └── Group ← Only Groups can own Data Assets
│ │ └── Group
│ └── Department
│ └── Group
└── Business Unit
└── Group
| Level | Purpose | Can Own Assets |
|---|---|---|
| Organization | Company root, auto-created | No |
| Business Unit | Top-tier organizational unit | No |
| Division | Mid-tier under Business Unit | No |
| Department | Team under Division | No |
| Group | Lowest level, contains users | Yes |
Create Team
Via UI:
- Navigate to Settings → Teams
- Click Add Team
- Select team type (BusinessUnit, Division, Department, Group)
- Set parent team
- Add team name, display name, description
Via API:
curl -X PUT "http://localhost:8585/api/v1/teams" \
-H "Authorization: Bearer ${JWT_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"name": "data-engineering",
"displayName": "Data Engineering",
"description": "Data platform team",
"teamType": "Group",
"parents": [{"id": "parent-team-uuid", "type": "team"}]
}'
Team Policies
Assign policies to teams for inherited permissions:
curl -X PATCH "http://localhost:8585/api/v1/teams/${TEAM_ID}" \
-H "Authorization: Bearer ${JWT_TOKEN}" \
-H "Content-Type: application/json-patch+json" \
-d '[
{
"op": "add",
"path": "/policies/-",
"value": {"id": "policy-uuid", "type": "policy"}
}
]'
User Management
Add User
Via UI:
- Navigate to Settings → Users
- Click Add User
- Enter email, name, select teams
- Assign roles
Via API:
curl -X PUT "http://localhost:8585/api/v1/users" \
-H "Authorization: Bearer ${JWT_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"name": "john.doe",
"email": "john.doe@company.com",
"displayName": "John Doe",
"teams": [{"id": "team-uuid", "type": "team"}],
"roles": [{"id": "role-uuid", "type": "role"}]
}'
Assign Role to User
curl -X PATCH "http://localhost:8585/api/v1/users/${USER_ID}" \
-H "Authorization: Bearer ${JWT_TOKEN}" \
-H "Content-Type: application/json-patch+json" \
-d '[
{
"op": "add",
"path": "/roles/-",
"value": {"id": "data-steward-role-uuid", "type": "role"}
}
]'
Generate User Access Token
Users can generate personal access tokens:
- Go to Profile → Access Token
- Click Generate New Token
- Set expiration (optional)
- Copy token immediately (shown only once)
Bots (Service Accounts)
What Are Bots?
Bots are service accounts for automated processes:
- Ingestion pipelines
- External integrations
- Scheduled jobs
- CI/CD automation
Built-in Bots
| Bot | Purpose | Default Role |
|---|---|---|
ingestion-bot |
Metadata ingestion pipelines | Ingestion Bot Role |
automator-bot |
Automation workflows | Automator Role |
Create Custom Bot
Via UI:
- Navigate to Settings → Integrations → Bots
- Click Add Bot
- Enter bot name and description
- Select or create role
- Copy generated JWT token
Via API:
# Create bot
curl -X PUT "http://localhost:8585/api/v1/bots" \
-H "Authorization: Bearer ${ADMIN_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"name": "ci-cd-bot",
"displayName": "CI/CD Bot",
"description": "Bot for CI/CD pipeline metadata updates",
"botUser": {
"name": "ci-cd-bot",
"email": "ci-cd-bot@openmetadata.org",
"isBot": true
}
}'
Get Bot JWT Token
Via UI:
- Navigate to Settings → Integrations → Bots
- Select the bot
- Click Revoke & Regenerate Token or view existing token
Via API:
# Get bot details including auth mechanism
curl "http://localhost:8585/api/v1/bots/name/ingestion-bot?fields=botUser" \
-H "Authorization: Bearer ${ADMIN_TOKEN}"
Bot Token Validation
Validate bot tokens at jwt.io or programmatically:
import jwt
def validate_bot_token(token: str, public_key: str) -> dict:
"""Validate and decode bot JWT token."""
try:
payload = jwt.decode(
token,
public_key,
algorithms=["RS256"],
issuer="open-metadata.org",
)
assert payload.get("isBot") == True
return payload
except jwt.ExpiredSignatureError:
raise ValueError("Token expired - regenerate in UI")
except jwt.InvalidTokenError as e:
raise ValueError(f"Invalid token: {e}")
Bot Token Rotation
Rotate bot tokens periodically:
- Navigate to Settings → Integrations → Bots
- Select the bot
- Click Revoke & Regenerate Token
- Update all systems using the old token
- Verify ingestion pipelines are working
Roles and Policies
Access Control Model
OpenMetadata uses hybrid RBAC + ABAC:
Authorization Decision = f(User, Resource, Operation)
Where:
- User = Identity + Roles + Teams
- Resource = Entity Type + Attributes (owner, domain, tags)
- Operation = Create, Edit, Delete, ViewAll, EditOwner, etc.
Built-in Roles
| Role | Description | Key Permissions |
|---|---|---|
| Admin | Full platform access | All operations on all resources |
| Data Consumer | Read-only access | ViewBasic on most entities |
| Data Steward | Governance operations | Edit descriptions, tags, glossary |
| Ingestion Bot Role | Pipeline operations | Create/edit services and entities |
Create Custom Role
Via UI:
- Navigate to Settings → Roles
- Click Add Role
- Enter name and description
- Add policies to the role
Via API:
curl -X PUT "http://localhost:8585/api/v1/roles" \
-H "Authorization: Bearer ${ADMIN_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"name": "DataEngineer",
"displayName": "Data Engineer",
"description": "Role for data engineering team",
"policies": [
{"id": "policy-uuid-1", "type": "policy"},
{"id": "policy-uuid-2", "type": "policy"}
]
}'
Policy Structure
Policies contain rules that define permissions:
{
"name": "TableEditPolicy",
"rules": [
{
"name": "AllowEditTables",
"resources": ["table"],
"operations": ["Create", "Edit", "Delete"],
"effect": "allow",
"condition": "isOwner()"
}
]
}
Common Policy Rules
| Rule | Effect | Description |
|---|---|---|
isOwner() |
Condition | User/team owns the resource |
inTeam('team-name') |
Condition | User belongs to team |
hasDomain('domain') |
Condition | Resource is in domain |
hasTag('tag-fqn') |
Condition | Resource has specific tag |
Create Policy
curl -X PUT "http://localhost:8585/api/v1/policies" \
-H "Authorization: Bearer ${ADMIN_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"name": "TeamOwnershipPolicy",
"displayName": "Team Ownership Policy",
"description": "Allow team members to edit owned resources",
"rules": [
{
"name": "EditOwnedResources",
"resources": ["table", "dashboard", "pipeline"],
"operations": ["Edit", "EditDescription", "EditTags"],
"effect": "allow",
"condition": "isOwner()"
}
]
}'
Operations Reference
| Operation | Description |
|---|---|
Create |
Create new entities |
Delete |
Delete entities |
ViewAll |
View all entity fields including sensitive data |
ViewBasic |
View basic fields (name, description, tags) |
Edit |
Edit entity properties |
EditDescription |
Edit description only |
EditTags |
Edit tags and classifications |
EditOwner |
Change entity owner |
EditLineage |
Modify lineage edges |
EditCustomFields |
Modify custom properties |
Authentication Configuration
Supported Providers
| Provider | Type | Notes |
|---|---|---|
| OpenMetadata (built-in) | JWT | Development only |
| OIDC | Google Workspace SSO | |
| Okta | OIDC | Okta SSO |
| Azure AD | OIDC | Microsoft Entra ID |
| Auth0 | OIDC | Auth0 SSO |
| AWS Cognito | OIDC | AWS Cognito User Pools |
| OneLogin | OIDC | OneLogin SSO |
| Keycloak | OIDC | Self-hosted OIDC |
| Custom OIDC | OIDC | Any OIDC-compliant provider |
Note: OpenMetadata does not support multiple auth providers simultaneously.
Configure SSO (Example: Okta)
1. Create Okta Application:
- Sign in to Okta Admin Console
- Navigate to Applications → Create App Integration
- Select OIDC - OpenID Connect and Web Application
- Set redirect URI:
http://localhost:8585/callback
2. Configure OpenMetadata:
# openmetadata.yaml
authenticationConfiguration:
provider: okta
publicKeyUrls:
- https://your-domain.okta.com/oauth2/default/v1/keys
authority: https://your-domain.okta.com/oauth2/default
clientId: <your-client-id>
callbackUrl: http://localhost:8585/callback
3. Configure Frontend:
# openmetadata.yaml (continued)
authorizerConfiguration:
className: org.openmetadata.service.security.DefaultAuthorizer
containerRequestFilter: org.openmetadata.service.security.JwtFilter
adminPrincipals:
- admin@company.com
principalDomain: company.com
LDAP/Active Directory
For LDAP integration, use an OIDC proxy like Keycloak:
- Deploy Keycloak
- Configure LDAP User Federation in Keycloak
- Configure OpenMetadata to use Keycloak as OIDC provider
Custom Properties Administration
Create Custom Property Type
Via UI:
- Navigate to Settings → Custom Properties
- Select entity type (Table, Dashboard, etc.)
- Click Add Property
- Configure name, type, description
Via API:
curl -X PUT "http://localhost:8585/api/v1/metadata/types/name/table/customProperties" \
-H "Authorization: Bearer ${ADMIN_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"name": "dataClassification",
"description": "Data classification level",
"propertyType": {
"id": "enum-type-uuid",
"type": "type"
},
"customPropertyConfig": {
"config": {
"values": ["Public", "Internal", "Confidential", "Restricted"]
}
}
}'
List Custom Properties
curl "http://localhost:8585/api/v1/metadata/types/name/table?fields=customProperties" \
-H "Authorization: Bearer ${ADMIN_TOKEN}"
Troubleshooting
Authentication Issues
Problem: 401 Unauthorized
Check JWT token validity:
# Decode token at jwt.io or: echo $JWT_TOKEN | cut -d. -f2 | base64 -d | jq .Verify token expiration (
expclaim)Check issuer matches configuration
Problem: Bot ingestion failing
Verify bot has
Ingestion Bot Role:curl "http://localhost:8585/api/v1/bots/name/ingestion-bot?fields=botUser" \ -H "Authorization: Bearer ${ADMIN_TOKEN}"Check role policies weren't modified
Regenerate bot token if expired
Authorization Issues
Problem: 403 Forbidden
Check user's roles:
curl "http://localhost:8585/api/v1/users/name/john.doe?fields=roles,teams" \ -H "Authorization: Bearer ${ADMIN_TOKEN}"Verify role has required policy
Check policy conditions (isOwner, inTeam, etc.)
Problem: User can't see entities
- Verify
ViewBasicorViewAllpermission - Check team hierarchy - user must be in a Group
- Verify entity isn't soft-deleted
Common Fixes
| Issue | Solution |
|---|---|
| Token expired | Regenerate token in UI |
| Missing permissions | Add policy to role |
| User not in team | Add user to Group-type team |
| Bot not working | Check role assignment, regenerate token |
| SSO login failing | Verify redirect URI, check OIDC config |
Operational Tasks
Backup Considerations
Critical data to back up:
- Database (MySQL/PostgreSQL)
- Elasticsearch indices
- JWT signing keys
- Configuration files
Audit Logging
OpenMetadata tracks changes via:
- Entity version history
- Change events in Elasticsearch
- API audit logs
Query audit events:
curl "http://localhost:8585/api/v1/events?entityType=table×tamp=1704067200000" \
-H "Authorization: Bearer ${ADMIN_TOKEN}"
Health Checks
# API health
curl "http://localhost:8585/api/v1/system/health"
# Elasticsearch health
curl "http://localhost:8585/api/v1/search/health"
Best Practices
Security
- Never use built-in auth in production - always configure SSO
- Rotate bot tokens periodically (every 90 days recommended)
- Use least-privilege roles - create specific policies per team
- Audit admin access regularly
Team Structure
- Use Groups for ownership - only Groups can own assets
- Mirror org structure - Business Unit → Division → Department → Group
- Assign domain owners - use domains for cross-team governance
Bot Management
- Create purpose-specific bots - don't reuse ingestion-bot
- Document bot purposes in descriptions
- Monitor bot token usage in audit logs
- Disable unused bots rather than deleting
References
- OpenMetadata Security Guide
- Roles and Policies
- Team Management
- SSO Configuration
openmetadata-dev- Using SDKs/APIs for integrationsopenmetadata-sdk-dev- Implementing SDKs for new languages