Skip to content

Commit ec77264

Browse files
resource/threat_detection: add web_lock_bind
Add a new resource alicloud_threat_detection_web_lock_bind to bind servers to the web tamper proofing feature. It supports the full WebLockBind schema: protected directory, mode (whitelist/blacklist), defence mode (block/audit), backup dir, inclusive/exclusive file types, exclusive dir and files, plus update-only status and lang fields managed via ModifyWebLockStatus. CRUD maps to the Sas 2018-12-03 APIs: - create: ModifyWebLockStart - read: DescribeWebLockBindList (filtered by Uuid) - update: ModifyWebLockStatus (status, lang) - delete: ModifyWebLockUnbind
1 parent 991dbca commit ec77264

5 files changed

Lines changed: 503 additions & 0 deletions

alicloud/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2103,6 +2103,7 @@ func Provider() terraform.ResourceProvider {
21032103
"alicloud_ga_basic_accelerate_ip_endpoint_relation": resourceAlicloudGaBasicAccelerateIpEndpointRelation(),
21042104
"alicloud_vpc_gateway_route_table_attachment": resourceAliCloudVpcGatewayRouteTableAttachment(),
21052105
"alicloud_threat_detection_web_lock_config": resourceAlicloudThreatDetectionWebLockConfig(),
2106+
"alicloud_threat_detection_web_lock_bind": resourceAlicloudThreatDetectionWebLockBind(),
21062107
"alicloud_threat_detection_backup_policy": resourceAlicloudThreatDetectionBackupPolicy(),
21072108
"alicloud_dms_enterprise_proxy_access": resourceAlicloudDmsEnterpriseProxyAccess(),
21082109
"alicloud_threat_detection_vul_whitelist": resourceAlicloudThreatDetectionVulWhitelist(),
Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
package alicloud
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"time"
7+
8+
"github.com/aliyun/terraform-provider-alicloud/alicloud/connectivity"
9+
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
10+
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
11+
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
12+
)
13+
14+
func resourceAlicloudThreatDetectionWebLockBind() *schema.Resource {
15+
return &schema.Resource{
16+
Create: resourceAlicloudThreatDetectionWebLockBindCreate,
17+
Read: resourceAlicloudThreatDetectionWebLockBindRead,
18+
Update: resourceAlicloudThreatDetectionWebLockBindUpdate,
19+
Delete: resourceAlicloudThreatDetectionWebLockBindDelete,
20+
Importer: &schema.ResourceImporter{
21+
State: schema.ImportStatePassthrough,
22+
},
23+
Schema: map[string]*schema.Schema{
24+
"defence_mode": {
25+
Required: true,
26+
ForceNew: true,
27+
ValidateFunc: validation.StringInSlice([]string{"block", "audit"}, false),
28+
Type: schema.TypeString,
29+
},
30+
"dir": {
31+
Required: true,
32+
ForceNew: true,
33+
Type: schema.TypeString,
34+
},
35+
"exclusive_dir": {
36+
Optional: true,
37+
ForceNew: true,
38+
Type: schema.TypeString,
39+
},
40+
"exclusive_file": {
41+
Optional: true,
42+
ForceNew: true,
43+
Type: schema.TypeString,
44+
},
45+
"exclusive_file_type": {
46+
Optional: true,
47+
ForceNew: true,
48+
Type: schema.TypeString,
49+
},
50+
"inclusive_file_type": {
51+
Optional: true,
52+
ForceNew: true,
53+
Type: schema.TypeString,
54+
},
55+
"lang": {
56+
Optional: true,
57+
ValidateFunc: validation.StringInSlice([]string{"zh", "en"}, false),
58+
Type: schema.TypeString,
59+
},
60+
"local_backup_dir": {
61+
Required: true,
62+
ForceNew: true,
63+
Type: schema.TypeString,
64+
},
65+
"mode": {
66+
Required: true,
67+
ForceNew: true,
68+
ValidateFunc: validation.StringInSlice([]string{"whitelist", "blacklist"}, false),
69+
Type: schema.TypeString,
70+
},
71+
"status": {
72+
Optional: true,
73+
ValidateFunc: validation.StringInSlice([]string{"on", "off"}, false),
74+
Type: schema.TypeString,
75+
},
76+
"uuid": {
77+
Required: true,
78+
ForceNew: true,
79+
Type: schema.TypeString,
80+
},
81+
},
82+
}
83+
}
84+
85+
func resourceAlicloudThreatDetectionWebLockBindCreate(d *schema.ResourceData, meta interface{}) error {
86+
client := meta.(*connectivity.AliyunClient)
87+
request := make(map[string]interface{})
88+
89+
request["DefenceMode"] = d.Get("defence_mode")
90+
request["Dir"] = d.Get("dir")
91+
if v, ok := d.GetOk("exclusive_dir"); ok {
92+
request["ExclusiveDir"] = v
93+
}
94+
if v, ok := d.GetOk("exclusive_file"); ok {
95+
request["ExclusiveFile"] = v
96+
}
97+
if v, ok := d.GetOk("exclusive_file_type"); ok {
98+
request["ExclusiveFileType"] = v
99+
}
100+
if v, ok := d.GetOk("inclusive_file_type"); ok {
101+
request["InclusiveFileType"] = v
102+
}
103+
request["LocalBackupDir"] = d.Get("local_backup_dir")
104+
request["Mode"] = d.Get("mode")
105+
request["Uuid"] = d.Get("uuid")
106+
107+
var response map[string]interface{}
108+
action := "ModifyWebLockStart"
109+
wait := incrementalWait(3*time.Second, 3*time.Second)
110+
err := resource.Retry(client.GetRetryTimeout(d.Timeout(schema.TimeoutCreate)), func() *resource.RetryError {
111+
resp, err := client.RpcPost("Sas", "2018-12-03", action, nil, request, false)
112+
if err != nil {
113+
if NeedRetry(err) {
114+
wait()
115+
return resource.RetryableError(err)
116+
}
117+
return resource.NonRetryableError(err)
118+
}
119+
response = resp
120+
addDebug(action, response, request)
121+
return nil
122+
})
123+
if err != nil {
124+
return WrapErrorf(err, DefaultErrorMsg, "alicloud_threat_detection_web_lock_bind", action, AlibabaCloudSdkGoERROR)
125+
}
126+
127+
d.SetId(fmt.Sprint(request["Uuid"]))
128+
129+
// status and lang are update-only fields (ModifyWebLockStatus); apply them
130+
// after the bind is started so the desired state is reached in one apply.
131+
if v, ok := d.GetOk("status"); ok {
132+
if err := webLockBindUpdateStatus(client, d.Id(), fmt.Sprint(v), d.Get("lang")); err != nil {
133+
return err
134+
}
135+
} else if v, ok := d.GetOk("lang"); ok {
136+
if err := webLockBindUpdateStatus(client, d.Id(), "", fmt.Sprint(v)); err != nil {
137+
return err
138+
}
139+
}
140+
141+
return resourceAlicloudThreatDetectionWebLockBindRead(d, meta)
142+
}
143+
144+
func resourceAlicloudThreatDetectionWebLockBindRead(d *schema.ResourceData, meta interface{}) error {
145+
client := meta.(*connectivity.AliyunClient)
146+
sasService := SasService{client}
147+
148+
object, err := sasService.DescribeThreatDetectionWebLockBind(d.Id())
149+
if err != nil {
150+
if NotFoundError(err) {
151+
log.Printf("[DEBUG] Resource alicloud_threat_detection_web_lock_bind sasService.DescribeThreatDetectionWebLockBind Failed!!! %s", err)
152+
d.SetId("")
153+
return nil
154+
}
155+
return WrapError(err)
156+
}
157+
d.Set("uuid", object["Uuid"])
158+
d.Set("defence_mode", object["DefenceMode"])
159+
d.Set("dir", object["Dir"])
160+
d.Set("exclusive_dir", object["ExclusiveDir"])
161+
d.Set("exclusive_file", object["ExclusiveFile"])
162+
d.Set("exclusive_file_type", object["ExclusiveFileType"])
163+
d.Set("inclusive_file_type", object["InclusiveFileType"])
164+
d.Set("local_backup_dir", object["LocalBackupDir"])
165+
d.Set("mode", object["Mode"])
166+
d.Set("status", object["Status"])
167+
d.Set("lang", object["Lang"])
168+
169+
return nil
170+
}
171+
172+
func resourceAlicloudThreatDetectionWebLockBindUpdate(d *schema.ResourceData, meta interface{}) error {
173+
client := meta.(*connectivity.AliyunClient)
174+
175+
// ModifyWebLockStatus only updates status and lang; all other fields are
176+
// ForceNew and trigger recreation.
177+
if d.HasChange("status") || d.HasChange("lang") {
178+
if err := webLockBindUpdateStatus(client, d.Id(), d.Get("status"), d.Get("lang")); err != nil {
179+
return err
180+
}
181+
}
182+
183+
return resourceAlicloudThreatDetectionWebLockBindRead(d, meta)
184+
}
185+
186+
func resourceAlicloudThreatDetectionWebLockBindDelete(d *schema.ResourceData, meta interface{}) error {
187+
client := meta.(*connectivity.AliyunClient)
188+
189+
request := map[string]interface{}{
190+
"Uuid": d.Id(),
191+
}
192+
193+
action := "ModifyWebLockUnbind"
194+
wait := incrementalWait(3*time.Second, 3*time.Second)
195+
err := resource.Retry(client.GetRetryTimeout(d.Timeout(schema.TimeoutDelete)), func() *resource.RetryError {
196+
resp, err := client.RpcPost("Sas", "2018-12-03", action, nil, request, false)
197+
if err != nil {
198+
if NeedRetry(err) {
199+
wait()
200+
return resource.RetryableError(err)
201+
}
202+
return resource.NonRetryableError(err)
203+
}
204+
addDebug(action, resp, request)
205+
return nil
206+
})
207+
if err != nil {
208+
if NotFoundError(err) {
209+
return nil
210+
}
211+
return WrapErrorf(err, DefaultErrorMsg, d.Id(), action, AlibabaCloudSdkGoERROR)
212+
}
213+
return nil
214+
}
215+
216+
// webLockBindUpdateStatus calls ModifyWebLockStatus to update the protection
217+
// status and/or language of a web lock bind entry.
218+
func webLockBindUpdateStatus(client *connectivity.AliyunClient, id, status, lang interface{}) error {
219+
request := map[string]interface{}{
220+
"Uuid": id,
221+
}
222+
if status != nil && fmt.Sprint(status) != "" {
223+
request["Status"] = status
224+
}
225+
if lang != nil && fmt.Sprint(lang) != "" {
226+
request["Lang"] = lang
227+
}
228+
229+
action := "ModifyWebLockStatus"
230+
wait := incrementalWait(3*time.Second, 3*time.Second)
231+
err := resource.Retry(5*time.Minute, func() *resource.RetryError {
232+
resp, err := client.RpcPost("Sas", "2018-12-03", action, nil, request, false)
233+
if err != nil {
234+
if NeedRetry(err) {
235+
wait()
236+
return resource.RetryableError(err)
237+
}
238+
return resource.NonRetryableError(err)
239+
}
240+
addDebug(action, resp, request)
241+
return nil
242+
})
243+
if err != nil {
244+
return WrapErrorf(err, DefaultErrorMsg, id, action, AlibabaCloudSdkGoERROR)
245+
}
246+
return nil
247+
}
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package alicloud
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/aliyun/terraform-provider-alicloud/alicloud/connectivity"
8+
"github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
9+
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
10+
)
11+
12+
func TestAccAliCloudThreatDetectionWebLockBind_basic(t *testing.T) {
13+
var v map[string]interface{}
14+
resourceId := "alicloud_threat_detection_web_lock_bind.default"
15+
ra := resourceAttrInit(resourceId, AlicloudThreatDetectionWebLockBindMap)
16+
rc := resourceCheckInitWithDescribeMethod(resourceId, &v, func() interface{} {
17+
return &SasService{testAccProvider.Meta().(*connectivity.AliyunClient)}
18+
}, "DescribeThreatDetectionWebLockBind")
19+
rac := resourceAttrCheckInit(rc, ra)
20+
testAccCheck := rac.resourceAttrMapUpdateSet()
21+
rand := acctest.RandIntRange(10000, 99999)
22+
name := fmt.Sprintf("tf-testacc%sThreatDetectionWebLockBind%d", defaultRegionToTest, rand)
23+
testAccConfig := resourceTestAccConfigFunc(resourceId, name, AlicloudThreatDetectionWebLockBindBasicDependence)
24+
resource.Test(t, resource.TestCase{
25+
PreCheck: func() {
26+
testAccPreCheck(t)
27+
},
28+
IDRefreshName: resourceId,
29+
Providers: testAccProviders,
30+
CheckDestroy: rac.checkResourceDestroy(),
31+
Steps: []resource.TestStep{
32+
{
33+
Config: testAccConfig(map[string]interface{}{
34+
"inclusive_file_type": "php;jsp;asp;aspx;js;cgi;html;htm;xml;shtml;shtm;jpg",
35+
"uuid": "${data.alicloud_threat_detection_assets.default.ids.0}",
36+
"mode": "whitelist",
37+
"local_backup_dir": "/usr/local/aegis/bak",
38+
"dir": "/tmp/",
39+
"defence_mode": "audit",
40+
"status": "on",
41+
"lang": "zh",
42+
}),
43+
Check: resource.ComposeTestCheckFunc(
44+
testAccCheck(map[string]string{
45+
"inclusive_file_type": "php;jsp;asp;aspx;js;cgi;html;htm;xml;shtml;shtm;jpg",
46+
"uuid": CHECKSET,
47+
"mode": "whitelist",
48+
"local_backup_dir": "/usr/local/aegis/bak",
49+
"dir": "/tmp/",
50+
"defence_mode": "audit",
51+
"status": "on",
52+
"lang": "zh",
53+
}),
54+
),
55+
},
56+
{
57+
Config: testAccConfig(map[string]interface{}{
58+
"inclusive_file_type": "php;jsp;asp;aspx;js;cgi;html;htm;xml;shtml;shtm;jpg",
59+
"uuid": "${data.alicloud_threat_detection_assets.default.ids.0}",
60+
"mode": "whitelist",
61+
"local_backup_dir": "/usr/local/aegis/bak",
62+
"dir": "/tmp/",
63+
"defence_mode": "audit",
64+
"status": "off",
65+
"lang": "en",
66+
}),
67+
Check: resource.ComposeTestCheckFunc(
68+
testAccCheck(map[string]string{
69+
"inclusive_file_type": "php;jsp;asp;aspx;js;cgi;html;htm;xml;shtml;shtm;jpg",
70+
"uuid": CHECKSET,
71+
"mode": "whitelist",
72+
"local_backup_dir": "/usr/local/aegis/bak",
73+
"dir": "/tmp/",
74+
"defence_mode": "audit",
75+
"status": "off",
76+
"lang": "en",
77+
}),
78+
),
79+
},
80+
{
81+
Config: testAccConfig(map[string]interface{}{
82+
"uuid": "${data.alicloud_threat_detection_assets.default.ids.0}",
83+
"dir": "/tmp/",
84+
"local_backup_dir": "/usr/local/aegis/bak",
85+
"defence_mode": "audit",
86+
"mode": "blacklist",
87+
"exclusive_dir": "/tmp/logs/",
88+
"exclusive_file_type": "log;cache;tmp",
89+
"exclusive_file": "/tmp/protected.db",
90+
"status": "on",
91+
"lang": "zh",
92+
}),
93+
Check: resource.ComposeTestCheckFunc(
94+
testAccCheck(map[string]string{
95+
"uuid": CHECKSET,
96+
"dir": "/tmp/",
97+
"local_backup_dir": "/usr/local/aegis/bak",
98+
"defence_mode": "audit",
99+
"mode": "blacklist",
100+
"exclusive_dir": "/tmp/logs/",
101+
"exclusive_file_type": "log;cache;tmp",
102+
"exclusive_file": "/tmp/protected.db",
103+
"status": "on",
104+
"lang": "zh",
105+
}),
106+
),
107+
},
108+
{
109+
ResourceName: resourceId,
110+
ImportState: true,
111+
ImportStateVerify: true,
112+
ImportStateVerifyIgnore: []string{},
113+
},
114+
},
115+
})
116+
}
117+
118+
var AlicloudThreatDetectionWebLockBindMap = map[string]string{}
119+
120+
func AlicloudThreatDetectionWebLockBindBasicDependence(name string) string {
121+
return fmt.Sprintf(`
122+
variable "name" {
123+
default = "%s"
124+
}
125+
126+
data "alicloud_threat_detection_assets" "default" {
127+
machine_types = "ecs"
128+
}
129+
130+
`, name)
131+
}

0 commit comments

Comments
 (0)