diff --git a/databricks-cluster-policy/README.md b/databricks-cluster-policy/README.md
new file mode 100644
index 00000000..2da77c8f
--- /dev/null
+++ b/databricks-cluster-policy/README.md
@@ -0,0 +1,42 @@
+# README
+
+## Requirements
+
+| Name | Version |
+|------|---------|
+| [terraform](#requirement\_terraform) | >= 0.13 |
+
+## Providers
+
+| Name | Version |
+|------|---------|
+| [databricks](#provider\_databricks) | n/a |
+
+## Modules
+
+No modules.
+
+## Resources
+
+| Name | Type |
+|------|------|
+| [databricks_cluster_policy.custom_cluster_policy](https://registry.terraform.io/providers/databricks/databricks/latest/docs/resources/cluster_policy) | resource |
+| [databricks_cluster_policy.inherited_cluster_policy](https://registry.terraform.io/providers/databricks/databricks/latest/docs/resources/cluster_policy) | resource |
+| [databricks_permissions.can_use_custom_cluster_policy](https://registry.terraform.io/providers/databricks/databricks/latest/docs/resources/permissions) | resource |
+| [databricks_permissions.can_use_inherited_cluster_policy](https://registry.terraform.io/providers/databricks/databricks/latest/docs/resources/permissions) | resource |
+
+## Inputs
+
+| Name | Description | Type | Default | Required |
+|------|-------------|------|---------|:--------:|
+| [databricks\_host](#input\_databricks\_host) | Databricks host name for tagging | `string` | n/a | yes |
+| [databricks\_workspace\_id](#input\_databricks\_workspace\_id) | Databricks workspace\_id for tagging | `string` | n/a | yes |
+| [grantees](#input\_grantees) | Names of groups to be granted use access to the policy - must already exist | `list(string)` | `[]` | no |
+| [policy\_family\_id](#input\_policy\_family\_id) | ID of policy family to inherit from | `string` | `null` | no |
+| [policy\_name](#input\_policy\_name) | Name of cluster policy | `string` | n/a | yes |
+| [policy\_overrides](#input\_policy\_overrides) | Cluster policy overrides | `any` | `{}` | no |
+
+## Outputs
+
+No outputs.
+
\ No newline at end of file
diff --git a/databricks-cluster-policy/main.tf b/databricks-cluster-policy/main.tf
new file mode 100644
index 00000000..60ce2c6c
--- /dev/null
+++ b/databricks-cluster-policy/main.tf
@@ -0,0 +1,63 @@
+locals {
+ # default policy attributes that can be overridden but are otherwise
+ # included for each policy
+ default_policy = {
+ "custom_tags.Cluster_Policy" : {
+ "type" : "fixed",
+ "value" : var.policy_name
+ },
+ "custom_tags.Databricks_Workspace_Id" : {
+ "type" : "fixed",
+ "value" : var.databricks_workspace_id
+ },
+ "custom_tags.Databricks_Host" : {
+ "type" : "fixed",
+ "value" : var.databricks_host
+ },
+ }
+
+ # Workaround for looping over grantees and setting resource count
+ inherited_cluster_policy_grantees = toset([for grantee in var.grantees : grantee if var.policy_family_id != null])
+ custom_cluster_policy_grantees = toset([for grantee in var.grantees : grantee if var.policy_family_id == null])
+}
+
+## Messy implementation below - cannot set policy_family_id and/or policy_family_definiton_overrides
+## if definition is present, and setting them to null still triggers an error from the provider, so
+## we duplicate the setup and set a count on the var being present
+
+### if inherited cluster policy
+resource "databricks_cluster_policy" "inherited_cluster_policy" {
+ count = var.policy_family_id != null ? 1 : 0
+
+ name = var.policy_name
+ policy_family_definition_overrides = jsonencode(merge(local.default_policy, var.policy_overrides))
+ policy_family_id = var.policy_family_id
+}
+
+resource "databricks_permissions" "can_use_inherited_cluster_policy" {
+ for_each = local.inherited_cluster_policy_grantees
+
+ cluster_policy_id = databricks_cluster_policy.inherited_cluster_policy[0].id
+ access_control {
+ group_name = each.value
+ permission_level = "CAN_USE"
+ }
+}
+
+### if custom cluster policy
+resource "databricks_cluster_policy" "custom_cluster_policy" {
+ count = var.policy_family_id == null ? 1 : 0
+
+ name = var.policy_name
+ definition = jsonencode(merge(local.default_policy, var.policy_overrides))
+}
+
+resource "databricks_permissions" "can_use_custom_cluster_policy" {
+ for_each = local.custom_cluster_policy_grantees
+
+ cluster_policy_id = databricks_cluster_policy.custom_cluster_policy[0].id
+ access_control {
+ group_name = each.value
+ permission_level = "CAN_USE"
+ }
+}
\ No newline at end of file
diff --git a/databricks-cluster-policy/outputs.tf b/databricks-cluster-policy/outputs.tf
new file mode 100644
index 00000000..e69de29b
diff --git a/databricks-cluster-policy/variables.tf b/databricks-cluster-policy/variables.tf
new file mode 100644
index 00000000..10d6fbc6
--- /dev/null
+++ b/databricks-cluster-policy/variables.tf
@@ -0,0 +1,32 @@
+variable "policy_name" {
+ description = "Name of cluster policy"
+ type = string
+}
+
+variable "databricks_workspace_id" {
+ description = "Databricks workspace_id for tagging"
+ type = string
+}
+
+variable "databricks_host" {
+ description = "Databricks host name for tagging"
+ type = string
+}
+
+variable "policy_family_id" {
+ description = "ID of policy family to inherit from"
+ type = string
+ default = null
+}
+
+variable "policy_overrides" {
+ description = "Cluster policy overrides"
+ type = any
+ default = {}
+}
+
+variable "grantees" {
+ description = "Names of groups to be granted use access to the policy - must already exist"
+ type = list(string)
+ default = []
+}
\ No newline at end of file
diff --git a/databricks-cluster-policy/versions.tf b/databricks-cluster-policy/versions.tf
new file mode 100644
index 00000000..9cd525d6
--- /dev/null
+++ b/databricks-cluster-policy/versions.tf
@@ -0,0 +1,8 @@
+terraform {
+ required_providers {
+ databricks = {
+ source = "databricks/databricks"
+ }
+ }
+ required_version = ">= 0.13"
+}