-
Notifications
You must be signed in to change notification settings - Fork 300
Commit
fix ci issues wip for potential test for provision on demand job handle the integration test not connecting to a real databricks add azurerm_databricks_workspace to test tf Revert "add azurerm_databricks_workspace to test tf" This reverts commit e1cca89.
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
--- | ||
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. | ||
|
||
## Attributes Reference | ||
|
||
No additional attributes are exported. | ||
|
||
## Import | ||
|
||
This resource does not support importing. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
package synchronization | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"github.com/hashicorp/go-azure-sdk/sdk/odata" | ||
Check failure on line 6 in internal/services/synchronization/synchronization_job_provision_on_demand_resource.go GitHub Actions / golint
Check failure on line 6 in internal/services/synchronization/synchronization_job_provision_on_demand_resource.go GitHub Actions / compatibility-32bit-test
Check failure on line 6 in internal/services/synchronization/synchronization_job_provision_on_demand_resource.go GitHub Actions / tflint
Check failure on line 6 in internal/services/synchronization/synchronization_job_provision_on_demand_resource.go GitHub Actions / tflint
|
||
"net/http" | ||
"time" | ||
|
||
"github.com/hashicorp/go-azure-sdk/sdk/odata" | ||
Check failure on line 10 in internal/services/synchronization/synchronization_job_provision_on_demand_resource.go GitHub Actions / golint
Check failure on line 10 in internal/services/synchronization/synchronization_job_provision_on_demand_resource.go GitHub Actions / golint
Check failure on line 10 in internal/services/synchronization/synchronization_job_provision_on_demand_resource.go GitHub Actions / golint
Check failure on line 10 in internal/services/synchronization/synchronization_job_provision_on_demand_resource.go GitHub Actions / compatibility-32bit-test
Check failure on line 10 in internal/services/synchronization/synchronization_job_provision_on_demand_resource.go GitHub Actions / compatibility-32bit-test
Check failure on line 10 in internal/services/synchronization/synchronization_job_provision_on_demand_resource.go GitHub Actions / tflint
Check failure on line 10 in internal/services/synchronization/synchronization_job_provision_on_demand_resource.go GitHub Actions / tflint
Check failure on line 10 in internal/services/synchronization/synchronization_job_provision_on_demand_resource.go GitHub Actions / tflint
Check failure on line 10 in internal/services/synchronization/synchronization_job_provision_on_demand_resource.go GitHub Actions / test
|
||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" | ||
Check failure on line 11 in internal/services/synchronization/synchronization_job_provision_on_demand_resource.go GitHub Actions / golint
Check failure on line 11 in internal/services/synchronization/synchronization_job_provision_on_demand_resource.go GitHub Actions / compatibility-32bit-test
Check failure on line 11 in internal/services/synchronization/synchronization_job_provision_on_demand_resource.go GitHub Actions / tflint
|
||
|
||
"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/tf/validation" | ||
Check failure on line 19 in internal/services/synchronization/synchronization_job_provision_on_demand_resource.go GitHub Actions / golint
Check failure on line 19 in internal/services/synchronization/synchronization_job_provision_on_demand_resource.go GitHub Actions / golint
Check failure on line 19 in internal/services/synchronization/synchronization_job_provision_on_demand_resource.go GitHub Actions / compatibility-32bit-test
Check failure on line 19 in internal/services/synchronization/synchronization_job_provision_on_demand_resource.go GitHub Actions / compatibility-32bit-test
Check failure on line 19 in internal/services/synchronization/synchronization_job_provision_on_demand_resource.go GitHub Actions / tflint
Check failure on line 19 in internal/services/synchronization/synchronization_job_provision_on_demand_resource.go GitHub Actions / tflint
Check failure on line 19 in internal/services/synchronization/synchronization_job_provision_on_demand_resource.go GitHub Actions / tflint
Check failure on line 19 in internal/services/synchronization/synchronization_job_provision_on_demand_resource.go GitHub Actions / test
|
||
"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: validation.ValidateDiag(validation.IsUUID), | ||
Check failure on line 42 in internal/services/synchronization/synchronization_job_provision_on_demand_resource.go GitHub Actions / golint
Check failure on line 42 in internal/services/synchronization/synchronization_job_provision_on_demand_resource.go GitHub Actions / compatibility-32bit-test
Check failure on line 42 in internal/services/synchronization/synchronization_job_provision_on_demand_resource.go GitHub Actions / tflint
|
||
}, | ||
"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("synchronization_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("parameter").([]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 | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package synchronization_test | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"regexp" | ||
"testing" | ||
|
||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform" | ||
"github.com/hashicorp/terraform-provider-azuread/internal/acceptance" | ||
"github.com/hashicorp/terraform-provider-azuread/internal/clients" | ||
"github.com/hashicorp/terraform-provider-azuread/internal/utils" | ||
) | ||
|
||
type SynchronizationJobProvisionOnDemandResource struct{} | ||
|
||
func TestAccSynchronizationJobProvisionOnDemand_basic(t *testing.T) { | ||
data := acceptance.BuildTestData(t, "azuread_synchronization_job_provision_on_demand", "test") | ||
r := SynchronizationJobProvisionOnDemandResource{} | ||
|
||
data.ResourceTest(t, r, []resource.TestStep{ | ||
{ | ||
//The provisioned app isn't actually integrated so this will never work | ||
Config: r.basic(data), | ||
ExpectError: regexp.MustCompile("CredentialsMissing: Please configure provisioning by providing your admin credentials then retry the provision on-demand."), | ||
}, | ||
}) | ||
} | ||
|
||
func (r SynchronizationJobProvisionOnDemandResource) Exists(ctx context.Context, clients *clients.Client, state *terraform.InstanceState) (*bool, error) { | ||
return utils.Bool(true), nil | ||
} | ||
|
||
func (SynchronizationJobProvisionOnDemandResource) template(data acceptance.TestData) string { | ||
return fmt.Sprintf(` | ||
provider "azuread" {} | ||
data "azuread_client_config" "test" {} | ||
data "azuread_application_template" "test" { | ||
display_name = "Azure Databricks SCIM Provisioning Connector" | ||
} | ||
resource "azuread_application" "test" { | ||
display_name = "acctestSynchronizationJob-%[1]d" | ||
owners = [data.azuread_client_config.test.object_id] | ||
template_id = data.azuread_application_template.test.template_id | ||
} | ||
resource "azuread_service_principal" "test" { | ||
application_id = azuread_application.test.application_id | ||
owners = [data.azuread_client_config.test.object_id] | ||
use_existing = true | ||
} | ||
resource "azuread_synchronization_job" "test" { | ||
service_principal_id = azuread_service_principal.test.id | ||
template_id = "dataBricks" | ||
} | ||
resource "azuread_group" "test" { | ||
display_name = "acctestGroup-%[1]d" | ||
security_enabled = true | ||
} | ||
`, data.RandomInteger) | ||
} | ||
|
||
func (r SynchronizationJobProvisionOnDemandResource) basic(data acceptance.TestData) string { | ||
return fmt.Sprintf(` | ||
%[1]s | ||
resource "azuread_synchronization_job_provision_on_demand" "test" { | ||
service_principal_id = azuread_service_principal.test.id | ||
synchronization_job_id = trimprefix(azuread_synchronization_job.test.id, "${azuread_service_principal.test.id}/job/") | ||
parameter { | ||
rule_id = "03f7d90d-bf71-41b1-bda6-aaf0ddbee5d8" //no api to check this so assuming the rule id is the same globally :finger_crossed: | ||
subject { | ||
object_id = azuread_group.test.id | ||
object_type_name = "Group" | ||
} | ||
} | ||
} | ||
`, r.template(data)) | ||
} |