-
Notifications
You must be signed in to change notification settings - Fork 300
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fixed #1031 adds provision on demand
- Loading branch information
Showing
4 changed files
with
282 additions
and
0 deletions.
There are no files selected for viewing
105 changes: 105 additions & 0 deletions
105
docs/resources/synchronization_job_provision_on_demand.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
--- | ||
subcategory: "Synchronization" | ||
--- | ||
|
||
# Resource: azuread_synchronization_job_provision_on_demand | ||
|
||
Manages synchronization job on demand provisioning associated with a service principal (enterprise application) within Azure Active Directory. | ||
|
||
## API Permissions | ||
|
||
The following API permissions are required in order to use this resource. | ||
|
||
When authenticated with a service principal, this resource requires one of the following application roles: `Synchronization.ReadWrite.All` | ||
|
||
## Example Usage | ||
|
||
*Basic example* | ||
|
||
```terraform | ||
data "azuread_client_config" "current" {} | ||
resource "azuread_group" "example" { | ||
display_name = "example" | ||
owners = [data.azuread_client_config.current.object_id] | ||
security_enabled = true | ||
} | ||
data "azuread_application_template" "example" { | ||
display_name = "Azure Databricks SCIM Provisioning Connector" | ||
} | ||
resource "azuread_application" "example" { | ||
display_name = "example" | ||
template_id = data.azuread_application_template.example.template_id | ||
feature_tags { | ||
enterprise = true | ||
gallery = true | ||
} | ||
} | ||
resource "azuread_service_principal" "example" { | ||
application_id = azuread_application.example.application_id | ||
use_existing = true | ||
} | ||
resource "azuread_synchronization_secret" "example" { | ||
service_principal_id = azuread_service_principal.example.id | ||
credential { | ||
key = "BaseAddress" | ||
value = "https://adb-example.azuredatabricks.net/api/2.0/preview/scim" | ||
} | ||
credential { | ||
key = "SecretToken" | ||
value = "some-token" | ||
} | ||
} | ||
resource "azuread_synchronization_job" "example" { | ||
service_principal_id = azuread_service_principal.example.id | ||
template_id = "dataBricks" | ||
enabled = true | ||
} | ||
resource "azuread_synchronization_job_provision_on_demand" "example" { | ||
service_principal_id = azuread_service_principal.example.id | ||
synchronization_job_id = azuread_synchronization_job.example.id | ||
parameter { | ||
# see specific synchronization schema for rule id https://learn.microsoft.com/en-us/graph/api/synchronization-synchronizationschema-get?view=graph-rest-beta | ||
rule_id = "" | ||
subject { | ||
object_id = azuread_group.example.object_id | ||
object_type_name = "Group" | ||
} | ||
} | ||
} | ||
``` | ||
|
||
## Argument Reference | ||
|
||
The following arguments are supported: | ||
|
||
|
||
- `synchronization_job_id` (Required) Identifier of the synchronization template this job is based on. | ||
- `parameter` (Required) One or more `parameter` blocks as documented below. | ||
- `service_principal_id` (Required) The object ID of the service principal for the synchronization job. | ||
|
||
--- | ||
|
||
`parameter` block supports the following: | ||
|
||
* `rule_id` (Required) The identifier of the synchronizationRule to be applied. This rule ID is defined in the schema for a given synchronization job or template. | ||
* `subject` (Required) One or more `subject` blocks as documented below. | ||
|
||
--- | ||
|
||
`subject` block supports the following: | ||
|
||
* `object_id` (String) The identifier of an object to which a synchronizationJob is to be applied. | ||
* `object_type_name` (String) The type of the object to which a synchronizationJob is to be applied. | ||
|
||
## Import | ||
|
||
This resource does not support importing. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
141 changes: 141 additions & 0 deletions
141
internal/services/serviceprincipals/synchronization_job_provision_on_demand_resource.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
package serviceprincipals | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"github.com/hashicorp/go-azure-sdk/sdk/odata" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" | ||
"net/http" | ||
"time" | ||
|
||
"github.com/hashicorp/go-uuid" | ||
|
||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" | ||
"github.com/hashicorp/terraform-provider-azuread/internal/clients" | ||
"github.com/hashicorp/terraform-provider-azuread/internal/tf" | ||
"github.com/hashicorp/terraform-provider-azuread/internal/validate" | ||
"github.com/manicminer/hamilton/msgraph" | ||
) | ||
|
||
func synchronizationJobProvisionOnDemandResource() *schema.Resource { | ||
return &schema.Resource{ | ||
CreateContext: synchronizationProvisionOnDemandResourceCreate, | ||
ReadContext: synchronizationProvisionOnDemandResourceRead, | ||
DeleteContext: synchronizationProvisionOnDemandResourceDelete, | ||
|
||
Timeouts: &schema.ResourceTimeout{ | ||
Create: schema.DefaultTimeout(15 * time.Minute), | ||
Read: schema.DefaultTimeout(5 * time.Minute), | ||
Delete: schema.DefaultTimeout(5 * time.Minute), | ||
}, | ||
SchemaVersion: 0, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"service_principal_id": { | ||
Description: "The object ID of the service principal for which this synchronization job should be provisioned", | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
ValidateDiagFunc: validate.UUID, | ||
}, | ||
"synchronization_job_id": { | ||
Description: "The identifier for the synchronization jop.", | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
"parameter": { | ||
Description: "Represents the objects that will be provisioned and the synchronization rules executed. The resource is primarily used for on-demand provisioning.", | ||
Type: schema.TypeList, | ||
Required: true, | ||
ForceNew: true, | ||
Elem: &schema.Resource{ | ||
Schema: map[string]*schema.Schema{ | ||
"rule_id": { | ||
Description: "The identifier of the synchronizationRule to be applied. This rule ID is defined in the schema for a given synchronization job or template.", | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
"subject": { | ||
Description: "The identifiers of one or more objects to which a synchronizationJob is to be applied.", | ||
Type: schema.TypeList, | ||
Required: true, | ||
ForceNew: true, | ||
Elem: &schema.Resource{ | ||
Schema: map[string]*schema.Schema{ | ||
"object_id": { | ||
Description: "The identifier of an object to which a synchronization Job is to be applied. Can be one of the following: (1) An onPremisesDistinguishedName for synchronization from Active Directory to Azure AD. (2) The user ID for synchronization from Azure AD to a third-party. (3) The Worker ID of the Workday worker for synchronization from Workday to either Active Directory or Azure AD.", | ||
Type: schema.TypeString, | ||
Required: true, | ||
}, | ||
"object_type_name": { | ||
Description: "The type of the object to which a synchronization Job is to be applied. Can be one of the following: `user` for synchronizing between Active Directory and Azure AD, `User` for synchronizing a user between Azure AD and a third-party application, `Worker` for synchronization a user between Workday and either Active Directory or Azure AD, `Group` for synchronizing a group between Azure AD and a third-party application.", | ||
Type: schema.TypeString, | ||
Required: true, | ||
ValidateFunc: validation.StringInSlice([]string{"Group", "user", "User", "Worker"}, false), | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func synchronizationProvisionOnDemandResourceCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { | ||
client := meta.(*clients.Client).ServicePrincipals.SynchronizationJobClient | ||
spClient := meta.(*clients.Client).ServicePrincipals.ServicePrincipalsClient | ||
objectId := d.Get("service_principal_id").(string) | ||
jobId := d.Get("job_id").(string) | ||
|
||
tf.LockByName(servicePrincipalResourceName, objectId) | ||
defer tf.UnlockByName(servicePrincipalResourceName, objectId) | ||
|
||
servicePrincipal, status, err := spClient.Get(ctx, objectId, odata.Query{}) | ||
if err != nil { | ||
if status == http.StatusNotFound { | ||
return tf.ErrorDiagPathF(nil, "service_principal_id", "Service principal with object ID %q was not found", objectId) | ||
} | ||
return tf.ErrorDiagPathF(err, "service_principal_id", "Retrieving service principal with object ID %q", objectId) | ||
} | ||
if servicePrincipal == nil || servicePrincipal.ID() == nil { | ||
return tf.ErrorDiagF(errors.New("nil service principal or service principal with nil ID was returned"), "API error retrieving service principal with object ID %q", objectId) | ||
} | ||
|
||
job, status, err := client.Get(ctx, jobId, objectId) | ||
if err != nil { | ||
if status == http.StatusNotFound { | ||
return tf.ErrorDiagPathF(nil, "job_id", "Job with object ID %q was not found for service principle %q", jobId, objectId) | ||
} | ||
return tf.ErrorDiagPathF(err, "job_id", "Retrieving job with object ID %q for service principle %q", jobId, objectId) | ||
} | ||
if job == nil || job.ID == nil { | ||
return tf.ErrorDiagF(errors.New("nil job or job with nil ID was returned"), "API error retrieving job with object ID %q/%s", objectId, jobId) | ||
} | ||
// Create a new synchronization job | ||
synchronizationProvisionOnDemand := &msgraph.SynchronizationJobProvisionOnDemand{ | ||
Parameters: expandSynchronizationJobApplicationParameters(d.Get("parameters").([]interface{})), | ||
} | ||
|
||
_, err = client.ProvisionOnDemand(ctx, jobId, synchronizationProvisionOnDemand, *servicePrincipal.ID()) | ||
if err != nil { | ||
return tf.ErrorDiagF(err, "Creating synchronization job for service principal ID %q", *servicePrincipal.ID()) | ||
} | ||
|
||
id, _ := uuid.GenerateUUID() | ||
d.SetId(id) | ||
|
||
return synchronizationProvisionOnDemandResourceRead(ctx, d, meta) | ||
} | ||
|
||
func synchronizationProvisionOnDemandResourceRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { | ||
return nil | ||
} | ||
|
||
func synchronizationProvisionOnDemandResourceDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { | ||
return nil | ||
} |