Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add optional external_id field to SCIM users and groups #927

Merged
merged 1 commit into from
Nov 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/data-sources/current_user.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ output "job_url" {
Data source exposes the following attributes:

* `id` - The id of the calling user.
* `external_id` - ID of the user in an external identity provider.
* `user_name` - Name of the [user](../resources/user.md), e.g. `mr.foo@example.com`.
* `home` - Home folder of the [user](../resources/user.md), e.g. `/Users/mr.foo@example.com`.
* `repos` - Personal Repos location of the [user](../resources/user.md), e.g. `/Repos/mr.foo@example.com`.
Expand Down
1 change: 1 addition & 0 deletions docs/data-sources/group.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Data source allows you to pick groups by the following attributes
Data source exposes the following attributes:

* `id` - The id for the group object.
* `external_id` - ID of the group in an external identity provider.
* `members` - Set of [user](../resources/user.md) identifiers, that can be modified with [databricks_group_member](../resources/group_member.md) resource.
* `groups` - Set of [group](../resources/group.md) identifiers, that can be modified with [databricks_group_member](../resources/group_member.md) resource.
* `instance_profiles` - Set of [instance profile](../resources/instance_profile.md) ARNs, that can be modified by [databricks_group_instance_profile](../resources/group_instance_profile.md) resource.
Expand Down
1 change: 1 addition & 0 deletions docs/data-sources/user.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Data source allows you to pick groups by the following attributes
Data source exposes the following attributes:

- `id` - The id of the user.
- `external_id` - ID of the user in an external identity provider.
- `user_name` - Name of the [user](../resources/user.md), e.g. `mr.foo@example.com`.
- `display_name` - Display name of the [user](../resources/user.md), e.g. `Mr Foo`.
- `home` - Home folder of the [user](../resources/user.md), e.g. `/Users/mr.foo@example.com`.
Expand Down
1 change: 1 addition & 0 deletions docs/resources/group.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ resource "databricks_group_member" "vip_member" {
The following arguments are supported:

* `display_name` - (Required) This is the display name for the given group.
* `external_id` - (Optional) ID of the group in an external identity provider.
* `allow_cluster_create` - (Optional) This is a field to allow the group to have [cluster](cluster.md) create privileges. More fine grained permissions could be assigned with [databricks_permissions](permissions.md#Cluster-usage) and [cluster_id](permissions.md#cluster_id) argument. Everyone without `allow_cluster_create` argument set, but with [permission to use](permissions.md#Cluster-Policy-usage) Cluster Policy would be able to create clusters, but within boundaries of that specific policy.
* `allow_instance_pool_create` - (Optional) This is a field to allow the group to have [instance pool](instance_pool.md) create privileges. More fine grained permissions could be assigned with [databricks_permissions](permissions.md#Instance-Pool-usage) and [instance_pool_id](permissions.md#instance_pool_id) argument.
* `allow_sql_analytics_access` - (Optional) This is a field to allow the group to have access to [Databricks SQL](https://databricks.com/product/databricks-sql) feature through [databricks_sql_endpoint](sql_endpoint.md).
Expand Down
1 change: 1 addition & 0 deletions docs/resources/user.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ The following arguments are available:

* `user_name` - (Required) This is the username of the given user and will be their form of access and identity.
* `display_name` - (Optional) This is an alias for the username that can be the full name of the user.
* `external_id` - (Optional) ID of the user in an external identity provider.
* `allow_cluster_create` - (Optional) Allow the user to have [cluster](cluster.md) create privileges. Defaults to false. More fine grained permissions could be assigned with [databricks_permissions](permissions.md#Cluster-usage) and `cluster_id` argument. Everyone without `allow_cluster_create` argument set, but with [permission to use](permissions.md#Cluster-Policy-usage) Cluster Policy would be able to create clusters, but within boundaries of that specific policy.
* `allow_instance_pool_create` - (Optional) Allow the user to have [instance pool](instance_pool.md) create privileges. Defaults to false. More fine grained permissions could be assigned with [databricks_permissions](permissions.md#Instance-Pool-usage) and [instance_pool_id](permissions.md#instance_pool_id) argument.
* `allow_sql_analytics_access` - (Optional) This is a field to allow the group to have access to [Databricks SQL](https://databricks.com/product/sql-analytics) feature through [databricks_sql_endpoint](sql_endpoint.md).
Expand Down
5 changes: 5 additions & 0 deletions identity/data_current_user.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ func DataSourceCurrentUser() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"external_id": {
Type: schema.TypeString,
Computed: true,
},
},
ReadContext: func(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
usersAPI := NewUsersAPI(ctx, m)
Expand All @@ -42,6 +46,7 @@ func DataSourceCurrentUser() *schema.Resource {
d.Set("user_name", me.UserName)
d.Set("home", fmt.Sprintf("/Users/%s", me.UserName))
d.Set("repos", fmt.Sprintf("/Repos/%s", me.UserName))
d.Set("external_id", me.ExternalID)
splits := strings.Split(me.UserName, "@")
norm := nonAlphanumeric.ReplaceAllLiteralString(splits[0], "_")
norm = strings.ToLower(norm)
Expand Down
2 changes: 2 additions & 0 deletions identity/data_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ func DataSourceGroup() *schema.Resource {
Members []string `json:"members,omitempty" tf:"slice_set,computed"`
Groups []string `json:"groups,omitempty" tf:"slice_set,computed"`
InstanceProfiles []string `json:"instance_profiles,omitempty" tf:"slice_set,computed"`
ExternalID string `json:"external_id,omitempty" tf:"computed"`
}

s := common.StructToSchema(entity{}, func(
Expand Down Expand Up @@ -65,6 +66,7 @@ func DataSourceGroup() *schema.Resource {
}
}
}
this.ExternalID = group.ExternalID
sort.Strings(this.Groups)
sort.Strings(this.Members)
sort.Strings(this.InstanceProfiles)
Expand Down
10 changes: 10 additions & 0 deletions identity/data_user.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ func DataSourceUser() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"repos": {
Type: schema.TypeString,
Computed: true,
},
"display_name": {
Type: schema.TypeString,
Computed: true,
Expand All @@ -51,6 +55,10 @@ func DataSourceUser() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"external_id": {
Type: schema.TypeString,
Computed: true,
},
},
ReadContext: func(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
usersAPI := NewUsersAPI(ctx, m)
Expand All @@ -61,6 +69,8 @@ func DataSourceUser() *schema.Resource {
d.Set("user_name", user.UserName)
d.Set("display_name", user.DisplayName)
d.Set("home", fmt.Sprintf("/Users/%s", user.UserName))
d.Set("repos", fmt.Sprintf("/Repos/%s", user.UserName))
d.Set("external_id", user.ExternalID)
splits := strings.Split(user.UserName, "@")
norm := nonAlphanumeric.ReplaceAllLiteralString(splits[0], "_")
norm = strings.ToLower(norm)
Expand Down
3 changes: 2 additions & 1 deletion identity/groups.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func (a GroupsAPI) Patch(groupID string, r patchRequest) error {
return a.client.Scim(a.context, http.MethodPatch, fmt.Sprintf("/preview/scim/v2/Groups/%v", groupID), r, nil)
}

func (a GroupsAPI) UpdateNameAndEntitlements(groupID string, name string, e entitlements) error {
func (a GroupsAPI) UpdateNameAndEntitlements(groupID string, name string, externalID string, e entitlements) error {
g, err := a.Read(groupID)
if err != nil {
return err
Expand All @@ -80,6 +80,7 @@ func (a GroupsAPI) UpdateNameAndEntitlements(groupID string, name string, e enti
Roles: g.Roles,
Members: g.Members,
Schemas: []URN{GroupSchema},
ExternalID: externalID,
}, nil)
}

Expand Down
10 changes: 9 additions & 1 deletion identity/resource_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ func ResourceGroup() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"external_id": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
}
addEntitlementsToSchema(&groupSchema)
return common.Resource{
Expand All @@ -27,6 +32,7 @@ func ResourceGroup() *schema.Resource {
group, err := NewGroupsAPI(ctx, c).Create(ScimGroup{
DisplayName: groupName,
Entitlements: readEntitlementsFromData(d),
ExternalID: d.Get("external_id").(string),
})
if err != nil {
return err
Expand All @@ -40,12 +46,14 @@ func ResourceGroup() *schema.Resource {
return err
}
d.Set("display_name", group.DisplayName)
d.Set("external_id", group.ExternalID)
d.Set("url", c.FormatURL("#setting/accounts/groups/", d.Id()))
return group.Entitlements.readIntoData(d)
},
Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error {
groupName := d.Get("display_name").(string)
return NewGroupsAPI(ctx, c).UpdateNameAndEntitlements(d.Id(), groupName, readEntitlementsFromData(d))
return NewGroupsAPI(ctx, c).UpdateNameAndEntitlements(d.Id(), groupName,
d.Get("external_id").(string), readEntitlementsFromData(d))
},
Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error {
return NewGroupsAPI(ctx, c).Delete(d.Id())
Expand Down
3 changes: 3 additions & 0 deletions identity/resource_user.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ func ResourceUser() *schema.Resource {
UserName string `json:"user_name" tf:"force_new"`
DisplayName string `json:"display_name,omitempty" tf:"computed"`
Active bool `json:"active,omitempty"`
ExternalID string `json:"external_id,omitempty"`
}
userSchema := common.StructToSchema(entity{},
func(m map[string]*schema.Schema) map[string]*schema.Schema {
Expand All @@ -31,6 +32,7 @@ func ResourceUser() *schema.Resource {
DisplayName: u.DisplayName,
Active: u.Active,
Entitlements: readEntitlementsFromData(d),
ExternalID: u.ExternalID,
}, nil
}
return common.Resource{
Expand All @@ -55,6 +57,7 @@ func ResourceUser() *schema.Resource {
d.Set("user_name", user.UserName)
d.Set("display_name", user.DisplayName)
d.Set("active", user.Active)
d.Set("external_id", user.ExternalID)
return user.Entitlements.readIntoData(d)
},
Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error {
Expand Down
2 changes: 2 additions & 0 deletions identity/scim.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ type ScimGroup struct {
Groups []ComplexValue `json:"groups,omitempty"`
Roles []ComplexValue `json:"roles,omitempty"`
Entitlements entitlements `json:"entitlements,omitempty"`
ExternalID string `json:"externalId,omitempty"`
}

// GroupList contains a list of groups fetched from a list api call from SCIM api
Expand Down Expand Up @@ -128,6 +129,7 @@ type ScimUser struct {
Name map[string]string `json:"name,omitempty"`
Roles []ComplexValue `json:"roles,omitempty"`
Entitlements entitlements `json:"entitlements,omitempty"`
ExternalID string `json:"externalId,omitempty"`
}

// UserList contains a list of Users fetched from a list api call from SCIM api
Expand Down