Policy¶
A Policy defines access control rules, data governance policies, and compliance requirements for data assets in OpenMetadata. Policies enable organizations to manage permissions, enforce data handling rules, and maintain compliance with regulations like GDPR, HIPAA, and SOC2.
Overview¶
Policies in OpenMetadata provide a centralized mechanism for:
- Access Control: Define who can access what data and what operations they can perform
- Data Governance: Enforce rules for data classification, retention, and usage
- Compliance Management: Ensure adherence to regulatory requirements
- Audit Trail: Track policy changes and enforcement history
- Role-Based Access: Apply policies based on user roles and team membership
Policies can be applied to: - Individual data assets (Tables, Dashboards, Topics, etc.) - Asset collections (Databases, Schemas, Services) - Teams and users - Domains and data products
Hierarchy¶
graph LR
A[Organization] --> B[Policy]
B --> C1[Rule]
B --> C2[Rule]
B --> C3[Rule]
style A fill:#667eea,color:#fff
style B fill:#4facfe,color:#fff,stroke:#4c51bf,stroke-width:3px
style C1 fill:#00f2fe,color:#333
style C2 fill:#00f2fe,color:#333
style C3 fill:#00f2fe,color:#333
click A "#organization" "Organization"
click B "#policy" "Policy"
click C1 "#rule" "Rule" Click on any node to learn more about that entity.
Relationships¶
Policies have relationships with various entities in the metadata ecosystem:
graph TD
subgraph Policy Structure
A[Policy:<br/>Data Access Policy] --> B1[Rule:<br/>Read Access]
A --> B2[Rule:<br/>Write Access]
A --> B3[Rule:<br/>Delete Access]
end
subgraph Applied To
A -.->|applies to| C1[Table:<br/>customer_data]
A -.->|applies to| C2[Database:<br/>production]
A -.->|applies to| C3[Domain:<br/>Customer Analytics]
end
subgraph Subjects
A -.->|affects| D1[Team:<br/>Data Science]
A -.->|affects| D2[Role:<br/>Data Analyst]
A -.->|affects| D3[User:<br/>john.doe]
end
subgraph Governance
A -.->|owned by| E1[User:<br/>Chief Data Officer]
A -.->|tagged with| E2[Tag:<br/>PII]
A -.->|tagged with| E3[Tag:<br/>Compliance]
A -.->|in domain| E4[Domain:<br/>Governance]
end
subgraph Related Policies
A -.->|depends on| F1[Policy:<br/>Base Access Policy]
A -.->|conflicts with| F2[Policy:<br/>Legacy Policy]
end
subgraph Enforcement
A -.->|triggers| G1[Alert:<br/>Policy Violation]
A -.->|logged in| G2[AuditLog]
end
style A fill:#4facfe,color:#fff,stroke:#4c51bf,stroke-width:3px
style B1 fill:#00f2fe,color:#333
style B2 fill:#00f2fe,color:#333
style B3 fill:#00f2fe,color:#333
style C1 fill:#764ba2,color:#fff
style C2 fill:#764ba2,color:#fff
style C3 fill:#764ba2,color:#fff
style D1 fill:#43e97b,color:#333
style D2 fill:#43e97b,color:#333
style D3 fill:#43e97b,color:#333
style E1 fill:#43e97b,color:#333
style E2 fill:#fa709a,color:#fff
style E3 fill:#fa709a,color:#fff
style E4 fill:#f093fb,color:#333
style F1 fill:#667eea,color:#fff
style F2 fill:#667eea,color:#fff
style G1 fill:#f5576c,color:#fff
style G2 fill:#ffd700,color:#333
click A "#policy" "Policy"
click B1 "#rule" "Rule"
click C1 "../../data-assets/databases/table/" "Table"
click C2 "../../data-assets/databases/database/" "Database"
click C3 "../../domains/domain/" "Domain"
click D1 "../../teams-users/team/" "Team"
click D2 "../../teams-users/role/" "Role"
click D3 "../../teams-users/user/" "User"
click E1 "../../teams-users/user/" "Owner"
click E2 "./tag/" "Tag"
click E4 "../../domains/domain/" "Domain"
click F1 "#policy" "Policy"
click G1 "../../data-quality/alert/" "Alert" Key Relationships:
- Policy Structure: Contains multiple Rules that define specific permissions
- Applied To: Can be applied to Tables, Databases, Dashboards, Topics, Domains, Data Products, etc.
- Subjects: Affects Teams, Roles, and Users who are granted or denied access
- Governance: Owned by users, tagged for classification, organized by domain
- Related Policies: Can depend on or conflict with other policies
- Enforcement: Triggers alerts on violations, creates audit logs
Schema Specifications¶
{
"$id": "https://open-metadata.org/schema/entity/policies/policy.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Policy",
"description": "A `Policy` defines control that needs to be applied across different Data Entities.",
"type": "object",
"javaType": "org.openmetadata.schema.entity.policies.Policy",
"javaInterfaces": [
"org.openmetadata.schema.EntityInterface"
],
"definitions": {
"rules": {
"description": "A set of rules associated with the Policy.",
"type": "array",
"items": {
"$ref": "accessControl/rule.json"
}
}
},
"properties": {
"id": {
"description": "Unique identifier that identifies this Policy.",
"$ref": "../../type/basic.json#/definitions/uuid"
},
"name": {
"description": "Name that uniquely identifies this Policy.",
"$ref": "../../type/basic.json#/definitions/entityName"
},
"fullyQualifiedName": {
"description": "Name that uniquely identifies a Policy.",
"$ref": "../../type/basic.json#/definitions/entityName"
},
"displayName": {
"description": "Display name for this Policy.",
"type": "string"
},
"description": {
"description": "A short description of the Policy, comprehensible to regular users.",
"$ref": "../../type/basic.json#/definitions/markdown"
},
"owners": {
"description": "Owners of this Policy.",
"$ref": "../../type/entityReferenceList.json",
"default": null
},
"href": {
"description": "Link to the resource corresponding to this entity.",
"$ref": "../../type/basic.json#/definitions/href"
},
"enabled": {
"description": "Is the policy enabled.",
"type": "boolean",
"default": true
},
"version": {
"description": "Metadata version of the Policy.",
"$ref": "../../type/entityHistory.json#/definitions/entityVersion"
},
"updatedAt": {
"description": "Last update time corresponding to the new version of the Policy in Unix epoch time milliseconds.",
"$ref": "../../type/basic.json#/definitions/timestamp"
},
"updatedBy": {
"description": "User who made the update.",
"type": "string"
},
"impersonatedBy": {
"description": "Bot user that performed the action on behalf of the actual user.",
"$ref": "../../type/basic.json#/definitions/impersonatedBy"
},
"changeDescription": {
"description": "Change that led to this version of the Policy.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"incrementalChangeDescription": {
"description": "Change that lead to this version of the entity.",
"$ref": "../../type/entityHistory.json#/definitions/changeDescription"
},
"rules": {
"description": "Set of rules that the policy contains.",
"$ref": "#/definitions/rules"
},
"teams": {
"description": "Teams that use this policy directly and not through roles.",
"$ref": "../../type/entityReferenceList.json"
},
"roles": {
"description": "Roles that use this policy.",
"$ref": "../../type/entityReferenceList.json"
},
"location": {
"description": "Location to which a policy is applied. This field is relevant only for `lifeCycle` policies.",
"$ref": "../../type/entityReference.json",
"default": null
},
"allowDelete": {
"description": "Some system policies can't be deleted",
"type": "boolean"
},
"allowEdit": {
"description": "Some system roles can't be edited",
"type": "boolean"
},
"deleted": {
"description": "When `true` indicates the entity has been soft deleted.",
"type": "boolean",
"default": false
},
"provider": {
"$ref": "../../type/basic.json#/definitions/providerType"
},
"disabled": {
"description": "System policy can't be deleted. Use this flag to disable them.",
"type": "boolean"
},
"domains": {
"description": "Domains the asset belongs to. When not set, the asset inherits the domain from the parent it belongs to.",
"$ref": "../../type/entityReferenceList.json"
}
},
"required": [
"id",
"name",
"rules"
],
"additionalProperties": false
}
@prefix om: <https://open-metadata.org/schema/> .
@prefix om-entity: <https://open-metadata.org/schema/entity/> .
@prefix om-policy: <https://open-metadata.org/schema/entity/policies/> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix dcat: <http://www.w3.org/ns/dcat#> .
@prefix dcterms: <http://purl.org/dc/terms/> .
@prefix skos: <http://www.w3.org/2004/02/skos/core#> .
@prefix prov: <http://www.w3.org/ns/prov#> .
# Policy Class Definition
om-policy:Policy a owl:Class ;
rdfs:label "Policy" ;
rdfs:comment "A Policy defines control that needs to be applied across different Data Entities" ;
rdfs:subClassOf om-entity:Entity ;
rdfs:isDefinedBy om: .
# Rule Class Definition
om-policy:Rule a owl:Class ;
rdfs:label "Rule" ;
rdfs:comment "Describes an Access Control Rule for OpenMetadata Metadata Operations" ;
rdfs:isDefinedBy om: .
# Effect Class
om-policy:Effect a owl:Class ;
rdfs:label "Effect" ;
rdfs:comment "Effect of the rule - allow or deny" ;
rdfs:isDefinedBy om: .
# Properties
om-policy:enabled a owl:DatatypeProperty ;
rdfs:label "enabled" ;
rdfs:comment "Is the policy enabled" ;
rdfs:domain om-policy:Policy ;
rdfs:range xsd:boolean .
om-policy:disabled a owl:DatatypeProperty ;
rdfs:label "disabled" ;
rdfs:comment "System policy can't be deleted. Use this flag to disable them" ;
rdfs:domain om-policy:Policy ;
rdfs:range xsd:boolean .
om-policy:allowDelete a owl:DatatypeProperty ;
rdfs:label "allow delete" ;
rdfs:comment "Some system policies can't be deleted" ;
rdfs:domain om-policy:Policy ;
rdfs:range xsd:boolean .
om-policy:allowEdit a owl:DatatypeProperty ;
rdfs:label "allow edit" ;
rdfs:comment "Some system roles can't be edited" ;
rdfs:domain om-policy:Policy ;
rdfs:range xsd:boolean .
om-policy:hasRule a owl:ObjectProperty ;
rdfs:label "has rule" ;
rdfs:comment "Set of rules that the policy contains" ;
rdfs:domain om-policy:Policy ;
rdfs:range om-policy:Rule .
om-policy:hasTeam a owl:ObjectProperty ;
rdfs:label "has team" ;
rdfs:comment "Teams that use this policy directly and not through roles" ;
rdfs:domain om-policy:Policy ;
rdfs:range om-entity:Team .
om-policy:hasRole a owl:ObjectProperty ;
rdfs:label "has role" ;
rdfs:comment "Roles that use this policy" ;
rdfs:domain om-policy:Policy ;
rdfs:range om-entity:Role .
om-policy:location a owl:ObjectProperty ;
rdfs:label "location" ;
rdfs:comment "Location to which a policy is applied. This field is relevant only for lifeCycle policies" ;
rdfs:domain om-policy:Policy ;
rdfs:range om-entity:Location .
om-policy:hasDomain a owl:ObjectProperty ;
rdfs:label "has domain" ;
rdfs:comment "Domains the asset belongs to" ;
rdfs:domain om-policy:Policy ;
rdfs:range om-entity:Domain .
om-policy:hasOwner a owl:ObjectProperty ;
rdfs:label "has owner" ;
rdfs:comment "Owners of this Policy" ;
rdfs:domain om-policy:Policy ;
rdfs:range om-entity:EntityReference .
om-policy:impersonatedBy a owl:DatatypeProperty ;
rdfs:label "impersonated by" ;
rdfs:comment "Bot user that performed the action on behalf of the actual user" ;
rdfs:domain om-policy:Policy ;
rdfs:range xsd:string .
om-policy:provider a owl:DatatypeProperty ;
rdfs:label "provider" ;
rdfs:comment "Provider type for the policy" ;
rdfs:domain om-policy:Policy ;
rdfs:range xsd:string .
# Rule Properties
om-policy:ruleName a owl:DatatypeProperty ;
rdfs:label "rule name" ;
rdfs:comment "Name of this Rule" ;
rdfs:domain om-policy:Rule ;
rdfs:range xsd:string .
om-policy:ruleEffect a owl:ObjectProperty ;
rdfs:label "rule effect" ;
rdfs:comment "Effect of the rule (allow or deny)" ;
rdfs:domain om-policy:Rule ;
rdfs:range om-policy:Effect .
om-policy:operations a owl:DatatypeProperty ;
rdfs:label "operations" ;
rdfs:comment "List of operation names related to the resources" ;
rdfs:domain om-policy:Rule ;
rdfs:range xsd:string .
om-policy:resources a owl:DatatypeProperty ;
rdfs:label "resources" ;
rdfs:comment "Resources/objects related to this rule" ;
rdfs:domain om-policy:Rule ;
rdfs:range xsd:string .
om-policy:condition a owl:DatatypeProperty ;
rdfs:label "condition" ;
rdfs:comment "Expression in SpEL used for matching of a Rule based on entity, resource, and environmental attributes" ;
rdfs:domain om-policy:Rule ;
rdfs:range xsd:string .
# Effect Individuals
om-policy:Allow a om-policy:Effect ;
rdfs:label "Allow" ;
skos:definition "Allow the specified operations" .
om-policy:Deny a om-policy:Effect ;
rdfs:label "Deny" ;
skos:definition "Deny the specified operations" .
{
"@context": {
"@vocab": "https://open-metadata.org/schema/entity/policies/",
"rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
"rdfs": "http://www.w3.org/2000/01/rdf-schema#",
"owl": "http://www.w3.org/2002/07/owl#",
"xsd": "http://www.w3.org/2001/XMLSchema#",
"dcat": "http://www.w3.org/ns/dcat#",
"dcterms": "http://purl.org/dc/terms/",
"skos": "http://www.w3.org/2004/02/skos/core#",
"prov": "http://www.w3.org/ns/prov#",
"om": "https://open-metadata.org/schema/",
"Policy": {
"@id": "om:Policy",
"@type": "@id"
},
"id": {
"@id": "om:id",
"@type": "xsd:string"
},
"name": {
"@id": "om:name",
"@type": "xsd:string"
},
"fullyQualifiedName": {
"@id": "om:fullyQualifiedName",
"@type": "xsd:string"
},
"displayName": {
"@id": "om:displayName",
"@type": "xsd:string"
},
"description": {
"@id": "dcterms:description",
"@type": "xsd:string"
},
"enabled": {
"@id": "om:enabled",
"@type": "xsd:boolean"
},
"disabled": {
"@id": "om:disabled",
"@type": "xsd:boolean"
},
"allowDelete": {
"@id": "om:allowDelete",
"@type": "xsd:boolean"
},
"allowEdit": {
"@id": "om:allowEdit",
"@type": "xsd:boolean"
},
"rules": {
"@id": "om:hasRule",
"@type": "@id",
"@container": "@set"
},
"owners": {
"@id": "om:hasOwner",
"@type": "@id",
"@container": "@set"
},
"teams": {
"@id": "om:hasTeam",
"@type": "@id",
"@container": "@set"
},
"roles": {
"@id": "om:hasRole",
"@type": "@id",
"@container": "@set"
},
"location": {
"@id": "om:location",
"@type": "@id"
},
"domains": {
"@id": "om:hasDomain",
"@type": "@id",
"@container": "@set"
},
"provider": {
"@id": "om:provider",
"@type": "xsd:string"
},
"impersonatedBy": {
"@id": "om:impersonatedBy",
"@type": "xsd:string"
},
"version": {
"@id": "om:version",
"@type": "xsd:string"
},
"updatedAt": {
"@id": "dcterms:modified",
"@type": "xsd:dateTime"
},
"updatedBy": {
"@id": "prov:wasAttributedTo",
"@type": "xsd:string"
},
"href": {
"@id": "om:href",
"@type": "xsd:anyURI"
},
"changeDescription": {
"@id": "om:changeDescription",
"@type": "@id"
},
"incrementalChangeDescription": {
"@id": "om:incrementalChangeDescription",
"@type": "@id"
},
"deleted": {
"@id": "om:deleted",
"@type": "xsd:boolean"
}
}
}
Use Cases¶
Access Control Policy¶
Define who can access specific databases and what operations they can perform:
{
"name": "ProductionDatabaseAccess",
"displayName": "Production Database Access Policy",
"description": "Controls access to production databases",
"enabled": true,
"rules": [
{
"name": "DataAnalystReadAccess",
"description": "Allow data analysts to read from production databases",
"effect": "allow",
"operations": ["ViewBasic", "ViewAll", "ViewDataProfile"],
"resources": ["database:production.*"],
"condition": "hasRole('DataAnalyst')"
},
{
"name": "DenyProductionWrite",
"description": "Deny write access to production for analysts",
"effect": "deny",
"operations": ["EditAll", "Delete"],
"resources": ["database:production.*"],
"condition": "hasRole('DataAnalyst')"
}
],
"owners": [
{
"type": "user",
"name": "chief.data.officer"
}
]
}
Data Masking Policy¶
Automatically mask PII data for certain user roles:
{
"name": "PIIMaskingPolicy",
"displayName": "PII Data Masking Policy",
"description": "Masks PII data for non-privileged users",
"enabled": true,
"rules": [
{
"name": "MaskSensitiveColumns",
"description": "Mask columns tagged as PII",
"effect": "allow",
"operations": ["ViewSampleData"],
"resources": ["column:*.*.*.{email,ssn,phone,address}"],
"condition": "hasTag('PII.Sensitive') AND NOT hasRole('DataSteward')"
}
],
"owners": [
{
"type": "team",
"name": "DataGovernance"
}
]
}
Compliance Policy¶
Ensure compliance with GDPR data retention requirements:
{
"name": "GDPRRetentionPolicy",
"displayName": "GDPR Data Retention Policy",
"description": "Enforces GDPR data retention requirements",
"enabled": true,
"rules": [
{
"name": "DeleteCustomerDataAfter7Years",
"description": "Delete customer data after 7 years",
"effect": "allow",
"operations": ["Delete"],
"resources": ["table:*.customer_*"],
"condition": "dataAge > 2555 DAYS AND hasTag('PII')"
},
{
"name": "AlertOnRetentionViolation",
"description": "Alert when retention period is exceeded",
"effect": "deny",
"operations": ["ViewAll"],
"resources": ["table:*.customer_*"],
"condition": "dataAge > 2555 DAYS AND hasTag('PII')"
}
],
"owners": [
{
"type": "user",
"name": "compliance.officer"
}
],
"domains": [
{
"type": "domain",
"name": "Governance"
}
]
}
Domain-Based Access¶
Control access based on data domains:
{
"name": "DomainBasedAccess",
"displayName": "Domain-Based Access Policy",
"description": "Users can only access data in their domain",
"enabled": true,
"rules": [
{
"name": "SalesDomainAccess",
"description": "Sales team can access Sales domain data",
"effect": "allow",
"operations": ["ViewAll", "EditDescription", "EditTags"],
"resources": ["domain:Sales.*"],
"condition": "inTeam('Sales')"
},
{
"name": "DenyCrossDomainAccess",
"description": "Deny access to data outside user's domain",
"effect": "deny",
"operations": ["ViewAll"],
"resources": ["*"],
"condition": "NOT inUserDomain(resource.domain)"
}
],
"owners": [
{
"type": "team",
"name": "DataGovernance"
}
]
}
Policy Operations¶
Supported operations that can be controlled by policies:
View Operations¶
ViewBasic: View basic metadata (name, description)ViewAll: View all metadata including tags and ownershipViewUsage: View usage statisticsViewTests: View test resultsViewQueries: View sample queriesViewDataProfile: View data profile and statisticsViewProfilerGlobalConfiguration: View profiler global configurationViewSampleData: View sample dataViewTestCaseFailedRowsSample: View test case failed rows sampleViewCustomFields: View custom fieldsViewScim: View SCIM information
Create Operations¶
Create: Create new entitiesBulkCreate: Create multiple entities at onceCreateIngestionPipelineAutomator: Create ingestion pipeline automatorsCreateTests: Create test casesCreateScim: Create SCIM entries
Edit Operations¶
EditAll: Edit all metadataEditDescription: Edit descriptionEditDisplayName: Edit display nameEditTags: Edit tagsEditGlossaryTerms: Edit glossary termsEditOwners: Edit ownershipEditTier: Edit tierEditCustomFields: Edit custom propertiesEditLineage: Edit lineage informationEditEntityRelationship: Edit entity relationshipsEditReviewers: Edit reviewersEditDataProfile: Edit data profileEditQueries: Edit queriesEditSampleData: Edit sample dataEditTests: Edit testsEditUsage: Edit usage informationEditUsers: Edit usersEditTeams: Edit teamsEditLifeCycle: Edit lifecycleEditKnowledgePanel: Edit knowledge panelEditPage: Edit pageEditCertification: Edit certificationEditStatus: Edit statusEditIngestionPipelineStatus: Edit ingestion pipeline statusEditUserNotificationTemplate: Edit user notification templates
Bulk Operations¶
BulkUpdate: Update multiple entities at once
Administrative Operations¶
Delete: Delete the entityDeleteTestCaseFailedRowsSample: Delete test case failed rows sampleDeleteScim: Delete SCIM entriesEditPolicy: Edit policiesEditRole: Edit rolesDeploy: Deploy entitiesTrigger: Trigger operationsKill: Kill running operationsGenerateToken: Generate authentication tokensEditScim: Edit SCIM informationImpersonate: Impersonate usersAll: All operations
Policy Evaluation¶
Policies are evaluated in the following order:
- Explicit Deny: If any rule explicitly denies access, access is denied
- Explicit Allow: If any rule explicitly allows access, access is allowed
- Default Deny: If no rule matches, access is denied by default
Condition Expressions¶
Rules can include condition expressions using Spring Expression Language (SpEL) based on entity, resource, and environmental attributes:
hasRole('RoleName'): Check if user has a specific roleinTeam('TeamName'): Check if user is in a specific teamhasTag('TagName'): Check if resource has a specific tagdataAge > N DAYS: Check age of datainUserDomain(resource.domain): Check if resource is in user's domain- Boolean operators:
AND,OR,NOT - Comparison operators:
>,<,>=,<=,==,!= - String matching and other SpEL capabilities
Best Practices¶
1. Principle of Least Privilege¶
Grant only the minimum permissions necessary for users to perform their jobs.
2. Use Policy Hierarchy¶
Create base policies and extend them with specific rules rather than duplicating rules.
3. Document Policy Intent¶
Always include clear descriptions explaining why a policy exists and what it aims to achieve.
4. Regular Policy Reviews¶
Periodically review policies to ensure they remain relevant and effective.
5. Test Before Enabling¶
Test policies in a non-production environment before enabling them in production.
6. Use Tags for Classification¶
Tag policies with their purpose (AccessControl, Compliance, etc.) for easier management.
7. Monitor Policy Violations¶
Set up alerts to monitor policy violations and take corrective action.
8. Version Control¶
Maintain version history of policy changes for audit and rollback purposes.
Custom Properties¶
This entity supports custom properties through the extension field. Common custom properties include:
- Data Classification: Sensitivity level
- Cost Center: Billing allocation
- Retention Period: Data retention requirements
- Application Owner: Owning application/team
See Custom Properties for details on defining and using custom properties.
API Operations¶
Create Policy¶
POST /api/v1/policies
Content-Type: application/json
{
"name": "SamplePolicy",
"description": "Sample access control policy",
"enabled": true,
"rules": [...]
}
Get Policy by ID¶
Update Policy¶
PATCH /api/v1/policies/{id}
Content-Type: application/json-patch+json
[
{
"op": "add",
"path": "/rules/-",
"value": {
"name": "NewRule",
"effect": "allow",
"operations": ["ViewAll"]
}
}
]
Delete Policy¶
List Policies¶
Enable/Disable Policy¶
PATCH /api/v1/policies/{id}
Content-Type: application/json-patch+json
[
{
"op": "replace",
"path": "/enabled",
"value": false
}
]