From 440f7655cb19729f9fad7f14d3744b3c4bc03b49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Falconnier?= Date: Sun, 30 Jun 2024 17:28:48 +0200 Subject: [PATCH] Add zentral_mdm_push_certificate data source --- go.mod | 2 +- go.sum | 4 +- internal/provider/mdm_push_certificate.go | 45 ++++++ .../mdm_push_certificate_data_source.go | 137 ++++++++++++++++++ .../mdm_push_certificate_data_source_test.go | 60 ++++++++ internal/provider/provider.go | 1 + 6 files changed, 246 insertions(+), 3 deletions(-) create mode 100644 internal/provider/mdm_push_certificate.go create mode 100644 internal/provider/mdm_push_certificate_data_source.go create mode 100644 internal/provider/mdm_push_certificate_data_source_test.go diff --git a/go.mod b/go.mod index 19cb98e..690beac 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/hashicorp/terraform-plugin-go v0.23.0 github.com/hashicorp/terraform-plugin-log v0.9.0 github.com/hashicorp/terraform-plugin-sdk/v2 v2.34.0 - github.com/zentralopensource/goztl v0.1.47 + github.com/zentralopensource/goztl v0.1.48 ) require ( diff --git a/go.sum b/go.sum index 1d5e2ed..e007447 100644 --- a/go.sum +++ b/go.sum @@ -204,8 +204,8 @@ github.com/zclconf/go-cty v1.14.4 h1:uXXczd9QDGsgu0i/QFR/hzI5NYCHLf6NQw/atrbnhq8 github.com/zclconf/go-cty v1.14.4/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b h1:FosyBZYxY34Wul7O/MSKey3txpPYyCqVO5ZyceuQJEI= github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= -github.com/zentralopensource/goztl v0.1.47 h1:N4iNAaP6JEoCsXkCEQyJ8Huq81SlKV9ZKvuDhiz/3Ek= -github.com/zentralopensource/goztl v0.1.47/go.mod h1:I3yd+zBFHVeiBz44Ov/74YbMl21k8BpOkPg7Q8sFHUM= +github.com/zentralopensource/goztl v0.1.48 h1:WLu6GRnczCDVf9rLglQb06ebDUbKAELd6a6xpboRtqY= +github.com/zentralopensource/goztl v0.1.48/go.mod h1:I3yd+zBFHVeiBz44Ov/74YbMl21k8BpOkPg7Q8sFHUM= go.abhg.dev/goldmark/frontmatter v0.2.0 h1:P8kPG0YkL12+aYk2yU3xHv4tcXzeVnN+gU0tJ5JnxRw= go.abhg.dev/goldmark/frontmatter v0.2.0/go.mod h1:XqrEkZuM57djk7zrlRUB02x8I5J0px76YjkOzhB4YlU= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= diff --git a/internal/provider/mdm_push_certificate.go b/internal/provider/mdm_push_certificate.go new file mode 100644 index 0000000..eecef90 --- /dev/null +++ b/internal/provider/mdm_push_certificate.go @@ -0,0 +1,45 @@ +package provider + +import ( + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/zentralopensource/goztl" +) + +type mdmPushCertificate struct { + ID types.Int64 `tfsdk:"id"` + ProvisioningUID types.String `tfsdk:"provisioning_uid"` + Name types.String `tfsdk:"name"` + Topic types.String `tfsdk:"topic"` + Certificate types.String `tfsdk:"certificate"` +} + +func mdmPushCertificateForState(mpc *goztl.MDMPushCertificate) mdmPushCertificate { + var provisioningUID types.String + if mpc.ProvisioningUID != nil { + provisioningUID = types.StringValue(*mpc.ProvisioningUID) + } else { + provisioningUID = types.StringNull() + } + + var topic types.String + if mpc.Topic != nil { + topic = types.StringValue(*mpc.Topic) + } else { + topic = types.StringNull() + } + + var certificate types.String + if mpc.Certificate != nil { + certificate = types.StringValue(*mpc.Certificate) + } else { + certificate = types.StringNull() + } + + return mdmPushCertificate{ + ID: types.Int64Value(int64(mpc.ID)), + ProvisioningUID: provisioningUID, + Name: types.StringValue(mpc.Name), + Topic: topic, + Certificate: certificate, + } +} diff --git a/internal/provider/mdm_push_certificate_data_source.go b/internal/provider/mdm_push_certificate_data_source.go new file mode 100644 index 0000000..659d9ba --- /dev/null +++ b/internal/provider/mdm_push_certificate_data_source.go @@ -0,0 +1,137 @@ +package provider + +import ( + "context" + "fmt" + + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/zentralopensource/goztl" +) + +// Ensure provider defined types fully satisfy framework interfaces +var _ datasource.DataSource = &MDMPushCertificateDataSource{} + +func NewMDMPushCertificateDataSource() datasource.DataSource { + return &MDMPushCertificateDataSource{} +} + +// MDMPushCertificateDataSource defines the data source implementation. +type MDMPushCertificateDataSource struct { + client *goztl.Client +} + +func (d *MDMPushCertificateDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_mdm_push_certificate" +} + +func (d *MDMPushCertificateDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = schema.Schema{ + Description: "Allows details of a MDM push certificate to be retrieved by its ID or its name.", + MarkdownDescription: "The data source `zentral_mdm_push_certificate` allows details of a MDM push certificate to be retrieved by its `ID` or its `name`.", + + Attributes: map[string]schema.Attribute{ + "id": schema.Int64Attribute{ + Description: "ID of the MDM push certificate.", + MarkdownDescription: "`ID` of the MDM push certificate.", + Optional: true, + }, + "provisioning_uid": schema.StringAttribute{ + Description: "Provisioning UID of the push certificate.", + MarkdownDescription: "Provisioning `UID` of the push certificate.", + Computed: true, + }, + "name": schema.StringAttribute{ + Description: "Name of the push certificate.", + MarkdownDescription: "Name of the push certificate.", + Optional: true, + }, + "topic": schema.StringAttribute{ + Description: "APNS topic the push certificate.", + MarkdownDescription: "APNS topic of the push certificate.", + Computed: true, + }, + "certificate": schema.StringAttribute{ + Description: "Push certificate in PEM form.", + MarkdownDescription: "Push certificate in `PEM` form.", + Computed: true, + }, + }, + } +} + +func (d *MDMPushCertificateDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { + // Prevent panic if the provider has not been configured. + if req.ProviderData == nil { + return + } + + client, ok := req.ProviderData.(*goztl.Client) + + if !ok { + resp.Diagnostics.AddError( + "Unexpected Data Source Configure Type", + fmt.Sprintf("Expected *goztl.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData), + ) + + return + } + + d.client = client +} + +func (d *MDMPushCertificateDataSource) ValidateConfig(ctx context.Context, req datasource.ValidateConfigRequest, resp *datasource.ValidateConfigResponse) { + var data mdmPushCertificate + diags := req.Config.Get(ctx, &data) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + if data.ID.IsNull() && data.Name.IsNull() { + resp.Diagnostics.AddError( + "Invalid `zentral_mdm_push_certificate` data source", + "`id` or `name` missing", + ) + } else if !data.ID.IsNull() && !data.Name.IsNull() { + resp.Diagnostics.AddError( + "Invalid `zentral_mdm_push_certificate` data source", + "`id` and `name` cannot be both set", + ) + } +} + +func (d *MDMPushCertificateDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + var data mdmPushCertificate + + // Read Terraform push certificate data into the model + resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) + + if resp.Diagnostics.HasError() { + return + } + + var ztlMPC *goztl.MDMPushCertificate + var err error + if data.ID.ValueInt64() > 0 { + ztlMPC, _, err = d.client.MDMPushCertificates.GetByID(ctx, int(data.ID.ValueInt64())) + if err != nil { + resp.Diagnostics.AddError( + "Client Error", + fmt.Sprintf("Unable to get MDM push certificate '%d' by ID, got error: %s", data.ID.ValueInt64(), err), + ) + } + } else { + ztlMPC, _, err = d.client.MDMPushCertificates.GetByName(ctx, data.Name.ValueString()) + if err != nil { + resp.Diagnostics.AddError( + "Client Error", + fmt.Sprintf("Unable to get MDM push certificate '%s' by name, got error: %s", data.Name.ValueString(), err), + ) + } + } + + if ztlMPC != nil { + resp.Diagnostics.Append(resp.State.Set(ctx, mdmPushCertificateForState(ztlMPC))...) + } +} diff --git a/internal/provider/mdm_push_certificate_data_source_test.go b/internal/provider/mdm_push_certificate_data_source_test.go new file mode 100644 index 0000000..b91e00c --- /dev/null +++ b/internal/provider/mdm_push_certificate_data_source_test.go @@ -0,0 +1,60 @@ +package provider + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccMDMPushCertificateDataSource(t *testing.T) { + ds1ResourceName := "data.zentral_mdm_push_certificate.check1_by_name" + ds2ResourceName := "data.zentral_mdm_push_certificate.check2_by_id" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccMDMPushCertificateDataSourceConfig(), + Check: resource.ComposeAggregateTestCheckFunc( + // Read by name + resource.TestCheckResourceAttr( + ds1ResourceName, "id", "4"), + resource.TestCheckResourceAttr( + ds1ResourceName, "provisioning_uid", "TF provider GitHub"), + resource.TestCheckResourceAttr( + ds1ResourceName, "name", "TF provider GitHub"), + resource.TestCheckNoResourceAttr( + ds1ResourceName, "topic"), + resource.TestCheckNoResourceAttr( + ds1ResourceName, "certificate"), + // Read by ID + resource.TestCheckResourceAttr( + ds2ResourceName, "id", "4"), + resource.TestCheckResourceAttr( + ds2ResourceName, "provisioning_uid", "TF provider GitHub"), + resource.TestCheckResourceAttr( + ds2ResourceName, "name", "TF provider GitHub"), + resource.TestCheckNoResourceAttr( + ds2ResourceName, "topic"), + resource.TestCheckNoResourceAttr( + ds2ResourceName, "certificate"), + ), + }, + }, + }) +} + +// TODO: hard coded values of a provisioned push certificate +// on the server used for the integration tests +func testAccMDMPushCertificateDataSourceConfig() string { + return ` +data "zentral_mdm_push_certificate" "check1_by_name" { + name = "TF provider GitHub" +} + +data "zentral_mdm_push_certificate" "check2_by_id" { + id = 4 +} +` +} diff --git a/internal/provider/provider.go b/internal/provider/provider.go index e63374d..b6923a2 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -171,6 +171,7 @@ func (p *ZentralProvider) DataSources(ctx context.Context) []func() datasource.D NewMDMArtifactDataSource, NewMDMBlueprintDataSource, NewMDMFileVaultConfigDataSource, + NewMDMPushCertificateDataSource, NewMDMRecoveryPasswordConfigDataSource, NewMDMSoftwareUpdateEnforcementDataSource, NewMonolithCatalogDataSource,