/
security-policies.go
142 lines (119 loc) · 5.2 KB
/
security-policies.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package datasource
import (
"context"
"errors"
"fmt"
"github.com/Twingate/terraform-provider-twingate/v3/twingate/internal/attr"
"github.com/Twingate/terraform-provider-twingate/v3/twingate/internal/client"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"
)
var ErrSecurityPoliciesDatasourceShouldSetOneOptionalNameAttribute = errors.New("Only one of name, name_regex, name_contains, name_exclude, name_prefix or name_suffix must be set.")
// Ensure the implementation satisfies the desired interfaces.
var _ datasource.DataSource = &securityPolicies{}
func NewSecurityPoliciesDatasource() datasource.DataSource {
return &securityPolicies{}
}
type securityPolicies struct {
client *client.Client
}
type securityPoliciesModel struct {
ID types.String `tfsdk:"id"`
Name types.String `tfsdk:"name"`
NameRegexp types.String `tfsdk:"name_regexp"`
NameContains types.String `tfsdk:"name_contains"`
NameExclude types.String `tfsdk:"name_exclude"`
NamePrefix types.String `tfsdk:"name_prefix"`
NameSuffix types.String `tfsdk:"name_suffix"`
SecurityPolicies []securityPolicyModel `tfsdk:"security_policies"`
}
func (d *securityPolicies) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = TwingateSecurityPolicies
}
func (d *securityPolicies) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
if req.ProviderData == nil {
return
}
client, ok := req.ProviderData.(*client.Client)
if !ok {
resp.Diagnostics.AddError(
"Unexpected Data Source Configure Type",
fmt.Sprintf("Expected *client.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData),
)
return
}
d.client = client
}
func (d *securityPolicies) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = schema.Schema{
Description: "Security Policies are defined in the Twingate Admin Console and determine user and device authentication requirements for Resources.",
Attributes: map[string]schema.Attribute{
attr.ID: schema.StringAttribute{
Computed: true,
Description: computedDatasourceIDDescription,
},
attr.Name: schema.StringAttribute{
Optional: true,
Description: "Returns only security policies that exactly match this name. If no options are passed it will return all security policies. Only one option can be used at a time.",
},
attr.Name + attr.FilterByRegexp: schema.StringAttribute{
Optional: true,
Description: "The regular expression match of the name of the security policy.",
},
attr.Name + attr.FilterByContains: schema.StringAttribute{
Optional: true,
Description: "Match when the value exist in the name of the security policy.",
},
attr.Name + attr.FilterByExclude: schema.StringAttribute{
Optional: true,
Description: "Match when the exact value does not exist in the name of the security policy.",
},
attr.Name + attr.FilterByPrefix: schema.StringAttribute{
Optional: true,
Description: "The name of the security policy must start with the value.",
},
attr.Name + attr.FilterBySuffix: schema.StringAttribute{
Optional: true,
Description: "The name of the security policy must end with the value.",
},
attr.SecurityPolicies: schema.ListNestedAttribute{
Computed: true,
NestedObject: schema.NestedAttributeObject{
Attributes: map[string]schema.Attribute{
attr.ID: schema.StringAttribute{
Computed: true,
Description: "Return a matching Security Policy by its ID. The ID for the Security Policy can be obtained from the Admin API or the URL string in the Admin Console.",
},
attr.Name: schema.StringAttribute{
Computed: true,
Description: "Return a Security Policy that exactly matches this name.",
},
},
},
},
},
}
}
func (d *securityPolicies) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
var data securityPoliciesModel
// Read Terraform configuration data into the model
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}
name, filter := getNameFilter(data.Name, data.NameRegexp, data.NameContains, data.NameExclude, data.NamePrefix, data.NameSuffix)
if countOptionalAttributes(data.Name, data.NameRegexp, data.NameContains, data.NameExclude, data.NamePrefix, data.NameSuffix) > 1 {
addErr(&resp.Diagnostics, ErrSecurityPoliciesDatasourceShouldSetOneOptionalNameAttribute, TwingateSecurityPolicies)
return
}
policies, err := d.client.ReadSecurityPolicies(ctx, name, filter)
if err != nil && !errors.Is(err, client.ErrGraphqlResultIsEmpty) {
addErr(&resp.Diagnostics, err, TwingateSecurityPolicy)
return
}
data.ID = types.StringValue("security-policies-all")
data.SecurityPolicies = convertSecurityPoliciesToTerraform(policies)
// Save data into Terraform state
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}