Skip to content

Sarra.zaghbib/cws 4408 expose set in terraform for agent rules #2992

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

Draft
wants to merge 12 commits into
base: daniel.zhou/CWS-3394-tf-provider
Choose a base branch
from
100 changes: 0 additions & 100 deletions datadog/data_source_datadog_cloud_workload_security_agent_rules.go

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
package fwprovider

import (
"context"
"crypto/sha256"
"fmt"
"strings"

"github.com/DataDog/datadog-api-client-go/v2/api/datadogV2"
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"

"github.com/terraform-providers/terraform-provider-datadog/datadog/internal/utils"
)

var (
_ datasource.DataSourceWithConfigure = &csmThreatsMultiPolicyAgentRulesDataSource{}
)

type csmThreatsMultiPolicyAgentRulesDataSource struct {
api *datadogV2.CSMThreatsApi
auth context.Context
}

type csmThreatsMultiPolicyAgentRulesDataSourceModel struct {
PolicyId types.String `tfsdk:"policy_id"`
Id types.String `tfsdk:"id"`
AgentRulesIds types.List `tfsdk:"agent_rules_ids"`
AgentRules []csmThreatsMultiPolicyAgentRuleDataSourceModel `tfsdk:"agent_rules"`
}

type csmThreatsMultiPolicyAgentRuleDataSourceModel struct {
Id types.String `tfsdk:"id"`
Name types.String `tfsdk:"name"`
Description types.String `tfsdk:"description"`
Enabled types.Bool `tfsdk:"enabled"`
Expression types.String `tfsdk:"expression"`
ProductTags types.Set `tfsdk:"product_tags"`
}

func NewCSMThreatsMultiPolicyAgentRulesDataSource() datasource.DataSource {
return &csmThreatsMultiPolicyAgentRulesDataSource{}
}

func (r *csmThreatsMultiPolicyAgentRulesDataSource) Configure(_ context.Context, request datasource.ConfigureRequest, response *datasource.ConfigureResponse) {
if request.ProviderData == nil {
return
}

providerData, ok := request.ProviderData.(*FrameworkProvider)
if !ok {
response.Diagnostics.AddError(
"Unexpected Resource Configure Type",
fmt.Sprintf("Expected *FrameworkProvider, got: %T. Please report this issue to the provider developers.", request.ProviderData),
)
return
}

r.api = providerData.DatadogApiInstances.GetCSMThreatsApiV2()
r.auth = providerData.Auth
}

func (r *csmThreatsMultiPolicyAgentRulesDataSource) Metadata(_ context.Context, request datasource.MetadataRequest, response *datasource.MetadataResponse) {
response.TypeName = "csm_threats_multi_policy_agent_rules"
}

func (r *csmThreatsMultiPolicyAgentRulesDataSource) Read(ctx context.Context, request datasource.ReadRequest, response *datasource.ReadResponse) {
var state csmThreatsMultiPolicyAgentRulesDataSourceModel
response.Diagnostics.Append(request.Config.Get(ctx, &state)...)
if response.Diagnostics.HasError() {
return
}

params := datadogV2.NewListCSMThreatsAgentRulesOptionalParameters()
if !state.PolicyId.IsNull() && !state.PolicyId.IsUnknown() {
policyId := state.PolicyId.ValueString()
params.WithPolicyId(policyId)
}

res, _, err := r.api.ListCSMThreatsAgentRules(r.auth, *params)
if err != nil {
response.Diagnostics.Append(utils.FrameworkErrorDiag(err, "error while fetching agent rules"))
return
}

data := res.GetData()
agentRuleIds := make([]string, len(data))
agentRules := make([]csmThreatsMultiPolicyAgentRuleDataSourceModel, len(data))

for idx, agentRule := range res.GetData() {
var agentRuleModel csmThreatsMultiPolicyAgentRuleDataSourceModel
agentRuleModel.Id = types.StringValue(agentRule.GetId())
attributes := agentRule.Attributes
agentRuleModel.Name = types.StringValue(attributes.GetName())
agentRuleModel.Description = types.StringValue(attributes.GetDescription())
agentRuleModel.Enabled = types.BoolValue(attributes.GetEnabled())
agentRuleModel.Expression = types.StringValue(*attributes.Expression)
tags := attributes.GetProductTags()
tagSet := make(map[string]struct{})
for _, tag := range tags {
tagSet[tag] = struct{}{}
}
uniqueTags := make([]string, 0, len(tagSet))
for tag := range tagSet {
uniqueTags = append(uniqueTags, tag)
}

productTags, diags := types.SetValueFrom(ctx, types.StringType, uniqueTags)
if diags.HasError() {
response.Diagnostics.Append(diags...)
continue
}
agentRuleModel.ProductTags = productTags
agentRuleIds[idx] = agentRule.GetId()
agentRules[idx] = agentRuleModel
}

stateId := strings.Join(agentRuleIds, "--")
state.Id = types.StringValue(computeDataSourceID(&stateId))
tfAgentRuleIds, diags := types.ListValueFrom(ctx, types.StringType, agentRuleIds)
response.Diagnostics.Append(diags...)
state.AgentRulesIds = tfAgentRuleIds
state.AgentRules = agentRules

response.Diagnostics.Append(response.State.Set(ctx, &state)...)
}

func (*csmThreatsMultiPolicyAgentRulesDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, response *datasource.SchemaResponse) {
response.Schema = schema.Schema{
Description: "Use this data source to retrieve information about existing Agent rules.",
Attributes: map[string]schema.Attribute{
// Input
"policy_id": schema.StringAttribute{
Description: "Listing only the rules in the policy with this field as the ID",
Optional: true,
},
// Output
"id": schema.StringAttribute{
Description: "The ID of the data source",
Computed: true,
},
"agent_rules_ids": schema.ListAttribute{
Computed: true,
Description: "List of IDs for the Agent rules.",
ElementType: types.StringType,
},
"agent_rules": schema.ListAttribute{
Computed: true,
Description: "List of Agent rules",
ElementType: types.ObjectType{
AttrTypes: map[string]attr.Type{
"id": types.StringType,
"name": types.StringType,
"description": types.StringType,
"enabled": types.BoolType,
"expression": types.StringType,
"product_tags": types.SetType{ElemType: types.StringType},
},
},
},
},
}
}

func computeDataSourceID(ids *string) string {
// Key for hashing
var b strings.Builder
if ids != nil {
b.WriteString(*ids)
}
keyStr := b.String()
h := sha256.New()
h.Write([]byte(keyStr))

return fmt.Sprintf("%x", h.Sum(nil))
}
109 changes: 109 additions & 0 deletions datadog/fwprovider/data_source_datadog_csm_threats_policy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package fwprovider

import (
"context"
"strings"

"github.com/DataDog/datadog-api-client-go/v2/api/datadogV2"
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"

"github.com/terraform-providers/terraform-provider-datadog/datadog/internal/utils"
)

var (
_ datasource.DataSourceWithConfigure = &csmThreatsPoliciesDataSource{}
)

type csmThreatsPoliciesDataSource struct {
api *datadogV2.CSMThreatsApi
auth context.Context
}

type csmThreatsPoliciesDataSourceModel struct {
Id types.String `tfsdk:"id"`
PolicyIds types.List `tfsdk:"policy_ids"`
Policies []csmThreatsPolicyModel `tfsdk:"policies"`
}

func NewCSMThreatsPoliciesDataSource() datasource.DataSource {
return &csmThreatsPoliciesDataSource{}
}

func (r *csmThreatsPoliciesDataSource) Configure(_ context.Context, request datasource.ConfigureRequest, _ *datasource.ConfigureResponse) {
providerData := request.ProviderData.(*FrameworkProvider)
r.api = providerData.DatadogApiInstances.GetCSMThreatsApiV2()
r.auth = providerData.Auth
}

func (*csmThreatsPoliciesDataSource) Metadata(_ context.Context, _ datasource.MetadataRequest, response *datasource.MetadataResponse) {
response.TypeName = "csm_threats_policies"
}

func (r *csmThreatsPoliciesDataSource) Read(ctx context.Context, request datasource.ReadRequest, response *datasource.ReadResponse) {
var state csmThreatsPoliciesDataSourceModel
response.Diagnostics.Append(request.Config.Get(ctx, &state)...)
if response.Diagnostics.HasError() {
return
}

res, _, err := r.api.ListCSMThreatsAgentPolicies(r.auth)
if err != nil {
response.Diagnostics.Append(utils.FrameworkErrorDiag(err, "error while fetching agent rules"))
return
}

data := res.GetData()
policyIds := make([]string, len(data))
policies := make([]csmThreatsPolicyModel, len(data))

for idx, policy := range res.GetData() {
var policyModel csmThreatsPolicyModel
policyModel.Id = types.StringValue(policy.GetId())
attributes := policy.Attributes
policyModel.Name = types.StringValue(attributes.GetName())
policyModel.Description = types.StringValue(attributes.GetDescription())
policyModel.Enabled = types.BoolValue(attributes.GetEnabled())
policyModel.Tags, _ = types.SetValueFrom(ctx, types.StringType, attributes.GetHostTags())
policyIds[idx] = policy.GetId()
policies[idx] = policyModel
}

stateId := strings.Join(policyIds, "--")
state.Id = types.StringValue(computeDataSourceID(&stateId))
tfAgentRuleIds, diags := types.ListValueFrom(ctx, types.StringType, policyIds)
response.Diagnostics.Append(diags...)
state.PolicyIds = tfAgentRuleIds
state.Policies = policies

response.Diagnostics.Append(response.State.Set(ctx, &state)...)
}

func (*csmThreatsPoliciesDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, response *datasource.SchemaResponse) {
response.Schema = schema.Schema{
Description: "Use this data source to retrieve information about existing policies.",
Attributes: map[string]schema.Attribute{
"id": utils.ResourceIDAttribute(),
"policy_ids": schema.ListAttribute{
Computed: true,
Description: "List of IDs for the policies.",
ElementType: types.StringType,
},
"policies": schema.ListAttribute{
Computed: true,
Description: "List of policies",
ElementType: types.ObjectType{
AttrTypes: map[string]attr.Type{
"id": types.StringType,
"tags": types.SetType{ElemType: types.StringType},
"name": types.StringType,
"description": types.StringType,
"enabled": types.BoolType,
},
},
},
},
}
}
Loading