Skip to content

Commit 720730a

Browse files
authored
Merge pull request #24 from trendmicro/feat_custom_rules_beta
feat: Add beta Custom Rules endpoints and tools
2 parents 5571100 + 2c5b794 commit 720730a

File tree

14 files changed

+656
-223
lines changed

14 files changed

+656
-223
lines changed

.github/pull_request_template.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ List the changes made in this PR:
2727

2828
Steps to manually test this PR:
2929

30+
1. `git checkout <branch-name>`
31+
2. `make mcpserver`
32+
3. Move the `v1-mcp-server` binary onto `$PATH`
33+
4. Configure the server with your AI tooling (differs depending on tool used)
34+
5. _Describe specific test steps here..._
35+
3036
---
3137

3238
## Screenshots / Demos (if applicable)

.github/workflows/lint.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ jobs:
1313
name: lint
1414
runs-on: ubuntu-latest
1515
steps:
16-
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
17-
- uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe
16+
- uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd
17+
- uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5
1818
with:
19-
go-version: stable
19+
go-version: 1.26.0
2020
- name: golangci-lint
21-
uses: golangci/golangci-lint-action@4afd733a84b1f43292c63897423277bb7f4313a9
21+
uses: golangci/golangci-lint-action@1e7e51e771db61008b38414a730f564565cf7c20
2222
with:
23-
version: v2.1
23+
version: v2.9

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM golang:1.24.3-alpine AS build
1+
FROM golang:1.26.0-alpine AS build
22
ARG VERSION="dev"
33

44
# Set the working directory

README.md

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,16 +88,22 @@ Alternatively, copy the following into your `settings.json`.
8888

8989
## Tools
9090

91-
### Cloud Posture
91+
### Cloud Posture (Beta)
9292

9393
| Tool | Description | Mode |
9494
| ---- | ----------- | ---- |
95-
| `cloud_posture_accounts_list` | List CSPM Accounts. | `read` |
96-
| `cloud_posture_account_checks_list` | List the checks of an account. | `read` |
97-
| `cloud_posture_account_scan` | Start scanning Cloud Posture account. | `write` |
98-
| `cloud_posture_account_scan_settings_get` | Get the scan settings for an account. | `read` |
99-
| `cloud_posture_account_scan_settings_update` | Update an account's scan settings. | `write` |
100-
| `cloud_posture_template_scanner_run` | Scan an infrastructure as code template using the cloud posture template scanner. | `read` |
95+
| `cloud_posture_accounts_list` | (Beta) List CSPM Accounts. | `read` |
96+
| `cloud_posture_account_checks_list` | (Beta) List the checks of an account. | `read` |
97+
| `cloud_posture_account_scan` | (Beta) Start scanning Cloud Posture account. | `write` |
98+
| `cloud_posture_account_scan_settings_get` | (Beta) Get the scan settings for an account. | `read` |
99+
| `cloud_posture_account_scan_settings_update` | (Beta) Update an account's scan settings. | `write` |
100+
| `cloud_posture_template_scanner_run` | (Beta) Scan an infrastructure as code template using the cloud posture template scanner. | `read` |
101+
| `cloud_posture_custom_rules_list` | (Beta) Displays the custom rules of your company in a paginated list. | `read` |
102+
| `cloud_posture_custom_rule_get` | (Beta) Returns the configuration of the specified custom rule. | `read` |
103+
| `cloud_posture_custom_rule_create` | (Beta) Creates a custom rule for your company. Requires Master Administrator role. | `write` |
104+
| `cloud_posture_custom_rule_update` | (Beta) Updates the specified custom rule. Requires Master Administrator role. | `write` |
105+
| `cloud_posture_custom_rule_delete` | (Beta) Deletes the specified custom rule permanently. Requires Master Administrator role. | `write` |
106+
| `cloud_posture_custom_rule_test` | (Beta) Tests the provided custom rule configuration against an account or mock resource data. Requires Master Administrator role. | `read` |
101107

102108
### Identity and Access Management (IAM)
103109

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module github.com/trendmicro/vision-one-mcp-server
22

3-
go 1.23.0
3+
go 1.26.0
44

55
require (
66
github.com/google/go-querystring v1.2.0

internal/v1client/aisecurity.go

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package v1client
22

33
import (
4-
"bytes"
5-
"encoding/json"
64
"net/http"
75
)
86

@@ -66,23 +64,11 @@ type AISecurityApplyGuardrailsOptions struct {
6664

6765
// AISecurityApplyGuardrails evaluates prompts against AI guard policies.
6866
func (c *V1ApiClient) AISecurityApplyGuardrails(input AISecurityApplyGuardrailsInput, opts AISecurityApplyGuardrailsOptions) (*http.Response, error) {
69-
b, err := json.Marshal(&input)
70-
if err != nil {
71-
return nil, err
72-
}
73-
74-
r, err := c.newRequest(
75-
http.MethodPost,
67+
return c.genericJSONPost(
7668
"v3.0/aiSecurity/applyGuardrails",
77-
bytes.NewReader(b),
78-
withContentTypeJSON(),
69+
input,
7970
withHeader("TMV1-Application-Name", opts.ApplicationName),
8071
withHeader("TMV1-Request-Type", opts.RequestType),
8172
withHeader("Prefer", opts.Prefer),
8273
)
83-
if err != nil {
84-
return nil, err
85-
}
86-
87-
return c.client.Do(r)
8874
}

internal/v1client/cloudposture.go

Lines changed: 67 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,97 +1,32 @@
11
package v1client
22

33
import (
4-
"bytes"
5-
"encoding/json"
64
"fmt"
75
"net/http"
8-
9-
"github.com/google/go-querystring/query"
106
)
117

128
func (c *V1ApiClient) CloudPostureListAccounts(queryParams QueryParameters) (*http.Response, error) {
13-
p, err := query.Values(queryParams)
14-
if err != nil {
15-
return nil, err
16-
}
17-
r, err := c.newRequest(
18-
http.MethodGet,
19-
"beta/cloudPosture/accounts",
20-
http.NoBody,
21-
withUrlParameters(p),
22-
)
23-
if err != nil {
24-
return nil, err
25-
}
26-
27-
return c.client.Do(r)
9+
return c.searchAndFilter("beta/cloudPosture/accounts", "", queryParams)
2810
}
2911

3012
func (c *V1ApiClient) CloudPostureListAccountChecks(filter string, qp QueryParameters) (*http.Response, error) {
31-
p, err := query.Values(qp)
32-
if err != nil {
33-
return nil, err
34-
}
35-
r, err := c.newRequest(
36-
http.MethodGet,
37-
"beta/cloudPosture/checks",
38-
http.NoBody,
39-
withFilter(filter),
40-
withUrlParameters(p),
41-
)
42-
if err != nil {
43-
return nil, err
44-
}
45-
46-
return c.client.Do(r)
13+
return c.searchAndFilter("beta/cloudPosture/checks", filter, qp)
4714
}
4815

4916
func (c *V1ApiClient) CloudPostureScanTemplate(content string, templateType string) (*http.Response, error) {
50-
jsonInput := map[string]any{
17+
body := map[string]any{
5118
"content": content,
5219
"type": templateType,
5320
}
54-
b, err := json.Marshal(jsonInput)
55-
if err != nil {
56-
return nil, err
57-
}
58-
59-
r, err := c.newRequest(
60-
http.MethodPost,
61-
"beta/cloudPosture/scanTemplate",
62-
bytes.NewReader(b),
63-
)
64-
if err != nil {
65-
return nil, err
66-
}
67-
68-
contentTypeJSON(r)
69-
70-
return c.client.Do(r)
21+
return c.genericJSONPost("beta/cloudPosture/scanTemplate", body)
7122
}
7223

7324
func (c *V1ApiClient) CloudPostureScanAccount(accountId string) (*http.Response, error) {
74-
r, err := c.newRequest(
75-
http.MethodPost,
76-
fmt.Sprintf("beta/cloudPosture/accounts/%s/scan", accountId),
77-
http.NoBody,
78-
)
79-
if err != nil {
80-
return nil, err
81-
}
82-
return c.client.Do(r)
25+
return c.genericPost(fmt.Sprintf("beta/cloudPosture/accounts/%s/scan", accountId))
8326
}
8427

8528
func (c *V1ApiClient) CloudPostureGetAccountScanSettings(accountId string) (*http.Response, error) {
86-
r, err := c.newRequest(
87-
http.MethodGet,
88-
fmt.Sprintf("beta/cloudPosture/accounts/%s/scanSetting", accountId),
89-
http.NoBody,
90-
)
91-
if err != nil {
92-
return nil, err
93-
}
94-
return c.client.Do(r)
29+
return c.genericGet(fmt.Sprintf("beta/cloudPosture/accounts/%s/scanSetting", accountId))
9530
}
9631

9732
type UpdateAccountScanSettings struct {
@@ -104,24 +39,70 @@ func (c *V1ApiClient) CloudPostureUpdateAccountScanSettings(
10439
enabled *bool,
10540
interval int,
10641
) (*http.Response, error) {
107-
apiInput := UpdateAccountScanSettings{
42+
body := UpdateAccountScanSettings{
10843
Enabled: enabled,
10944
Interval: interval,
11045
}
111-
b, err := json.Marshal(apiInput)
112-
if err != nil {
113-
return nil, err
114-
}
115-
r, err := c.newRequest(
116-
http.MethodPatch,
117-
fmt.Sprintf("beta/cloudPosture/accounts/%s/scanSetting", accountId),
118-
bytes.NewReader(b),
119-
)
120-
if err != nil {
121-
return nil, err
122-
}
46+
return c.genericJSONPatch(fmt.Sprintf("beta/cloudPosture/accounts/%s/scanSetting", accountId), body)
47+
}
48+
49+
func (c *V1ApiClient) CloudPostureListCustomRules(queryParams QueryParameters) (*http.Response, error) {
50+
return c.searchAndFilter("beta/cloudPosture/customRules", "", queryParams)
51+
}
52+
53+
func (c *V1ApiClient) CloudPostureGetCustomRule(ruleId string) (*http.Response, error) {
54+
return c.genericGet(fmt.Sprintf("beta/cloudPosture/customRules/%s", ruleId))
55+
}
56+
57+
type CustomRuleInput struct {
58+
Name string `json:"name"`
59+
Description string `json:"description,omitempty"`
60+
Categories []string `json:"categories"`
61+
RiskLevel string `json:"riskLevel"`
62+
Provider string `json:"provider"`
63+
ResolutionReferenceLink string `json:"resolutionReferenceLink,omitempty"`
64+
RemediationNote string `json:"remediationNote,omitempty"`
65+
Enabled bool `json:"enabled"`
66+
Service string `json:"service"`
67+
ResourceType string `json:"resourceType"`
68+
Attributes []any `json:"attributes"`
69+
EventRules []any `json:"eventRules"`
70+
Slug string `json:"slug,omitempty"`
71+
}
72+
73+
func (c *V1ApiClient) CloudPostureCreateCustomRule(input CustomRuleInput) (*http.Response, error) {
74+
return c.genericJSONPost("beta/cloudPosture/customRules", input)
75+
}
76+
77+
type CustomRuleUpdateInput struct {
78+
Name string `json:"name,omitempty"`
79+
Description string `json:"description,omitempty"`
80+
Categories []string `json:"categories,omitempty"`
81+
RiskLevel string `json:"riskLevel,omitempty"`
82+
Provider string `json:"provider,omitempty"`
83+
ResolutionReferenceLink string `json:"resolutionReferenceLink,omitempty"`
84+
RemediationNote string `json:"remediationNote,omitempty"`
85+
Enabled *bool `json:"enabled,omitempty"`
86+
Service string `json:"service,omitempty"`
87+
ResourceType string `json:"resourceType,omitempty"`
88+
Attributes []any `json:"attributes,omitempty"`
89+
EventRules []any `json:"eventRules,omitempty"`
90+
}
91+
92+
func (c *V1ApiClient) CloudPostureUpdateCustomRule(ruleId string, input CustomRuleUpdateInput) (*http.Response, error) {
93+
return c.genericJSONPatch(fmt.Sprintf("beta/cloudPosture/customRules/%s", ruleId), input)
94+
}
95+
96+
func (c *V1ApiClient) CloudPostureDeleteCustomRule(ruleId string) (*http.Response, error) {
97+
return c.genericDelete(fmt.Sprintf("beta/cloudPosture/customRules/%s", ruleId))
98+
}
12399

124-
contentTypeJSON(r)
100+
type CustomRuleTestInput struct {
101+
AccountId string `json:"accountId,omitempty"`
102+
Configuration any `json:"configuration"`
103+
Resource any `json:"resource,omitempty"`
104+
}
125105

126-
return c.client.Do(r)
106+
func (c *V1ApiClient) CloudPostureTestCustomRule(input CustomRuleTestInput) (*http.Response, error) {
107+
return c.genericJSONPost("beta/cloudPosture/customRules/test", input)
127108
}

0 commit comments

Comments
 (0)