Skip to content

Commit dc02642

Browse files
authored
feat(agent): add agent access key resource and data source (#470)
* feat: configuring datasource for agent access keys * feat: implementing agent access key resource with update, create, read and delete * feat: configuring acctests, docs and changing CODEOWNERS for agentaccesskey related features * chore: fix typo on agentaccesskey docs * chore: fix linter * fix: linter for unused error validation Marshaling agentAccessKey object * feat: refactor to implement new set of APIs * chore: change docs to new format * chore: fix arg reference naming * chore: fix naming convention for docs * feat: add access_key in agent access key data source output * chore: add platform team to list of CODEOWNERS for agentaccesskey * chore: refactor ID and removing print
1 parent 59b1d26 commit dc02642

12 files changed

+685
-7
lines changed

.gitignore

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ website/node_modules
2626
*.iml
2727
*.test
2828
*.iml
29-
29+
.tool-versions
3030
vendor/
3131

3232
website/vendor
@@ -48,4 +48,7 @@ oanc
4848
.vscode/settings.json
4949

5050
# goland .run
51-
.run/
51+
.run/
52+
53+
# Local test folder
54+
local-terraform-test/

CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
/sysdig/internal/client/v2/client.go @filiptubic @mbarbieri @draraksysdig
1818
/sysdig/internal/client/v2/config.go @filiptubic @mbarbieri @draraksysdig
1919
/sysdig/internal/client/v2/ibm.go @filiptubic @mbarbieri @draraksysdig
20+
/sysdig/internal/client/v2/agentaccesskey.go @igoreulalio @filiptubic @mbarbieri @draraksysdig
2021
/main.go @filiptubic @mbarbieri @draraksysdig
2122
/.goreleaser.yml @filiptubic @mbarbieri @draraksysdig
2223
/.github/ @filiptubic @mbarbieri @draraksysdig
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package sysdig
2+
3+
import (
4+
"context"
5+
"strconv"
6+
"time"
7+
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
9+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
10+
)
11+
12+
func dataSourceSysdigAgentAccessKey() *schema.Resource {
13+
timeout := 5 * time.Minute
14+
15+
return &schema.Resource{
16+
ReadContext: dataSourceSysdigAgentAccessKeyRead,
17+
18+
Timeouts: &schema.ResourceTimeout{
19+
Read: schema.DefaultTimeout(timeout),
20+
},
21+
22+
Schema: map[string]*schema.Schema{
23+
"id": {
24+
Type: schema.TypeInt,
25+
Required: true,
26+
},
27+
"reservation": {
28+
Type: schema.TypeInt,
29+
Computed: true,
30+
},
31+
"limit": {
32+
Type: schema.TypeInt,
33+
Computed: true,
34+
},
35+
"team_id": {
36+
Type: schema.TypeInt,
37+
Computed: true,
38+
},
39+
"metadata": {
40+
Type: schema.TypeMap,
41+
Computed: true,
42+
},
43+
"enabled": {
44+
Type: schema.TypeBool,
45+
Computed: true,
46+
},
47+
"date_disabled": {
48+
Type: schema.TypeString,
49+
Computed: true,
50+
},
51+
"date_created": {
52+
Type: schema.TypeString,
53+
Computed: true,
54+
},
55+
"access_key": {
56+
Type: schema.TypeString,
57+
Computed: true,
58+
},
59+
},
60+
}
61+
}
62+
63+
// Retrieves the information of a resource form the file and loads it in Terraform
64+
func dataSourceSysdigAgentAccessKeyRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
65+
client, err := meta.(SysdigClients).commonClientV2()
66+
if err != nil {
67+
return diag.FromErr(err)
68+
}
69+
70+
agentKeyId := d.Get("id").(int)
71+
agentAccessKey, err := client.GetAgentAccessKeyByID(ctx, strconv.Itoa(agentKeyId))
72+
if err != nil {
73+
return diag.FromErr(err)
74+
}
75+
d.SetId(strconv.Itoa(agentAccessKey.ID))
76+
_ = d.Set("reservation", agentAccessKey.Reservation)
77+
_ = d.Set("limit", agentAccessKey.Limit)
78+
_ = d.Set("team_id", agentAccessKey.TeamID)
79+
_ = d.Set("metadata", agentAccessKey.Metadata)
80+
_ = d.Set("enabled", agentAccessKey.Enabled)
81+
_ = d.Set("date_disabled", agentAccessKey.DateDisabled)
82+
_ = d.Set("date_created", agentAccessKey.DateCreated)
83+
_ = d.Set("access_key", agentAccessKey.AgentAccessKey)
84+
85+
return nil
86+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
//go:build tf_acc_sysdig_monitor || tf_acc_sysdig_secure
2+
3+
package sysdig_test
4+
5+
import (
6+
"fmt"
7+
"strconv"
8+
"testing"
9+
10+
"github.com/draios/terraform-provider-sysdig/sysdig"
11+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
12+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
13+
)
14+
15+
func TestAccAgentAccessKeyDataSource(t *testing.T) {
16+
limit := 1
17+
reservation := 0
18+
resource.ParallelTest(t, resource.TestCase{
19+
PreCheck: preCheckAnyEnv(t, SysdigMonitorApiTokenEnv, SysdigSecureApiTokenEnv),
20+
ProviderFactories: map[string]func() (*schema.Provider, error){
21+
"sysdig": func() (*schema.Provider, error) {
22+
return sysdig.Provider(), nil
23+
},
24+
},
25+
Steps: []resource.TestStep{
26+
{
27+
Config: getAgentAccessKey(limit, reservation, true),
28+
Check: resource.ComposeAggregateTestCheckFunc(
29+
resource.TestCheckResourceAttr("data.sysdig_agent_access_key.data", "limit", strconv.Itoa(limit)),
30+
resource.TestCheckResourceAttr("data.sysdig_agent_access_key.data", "reservation", strconv.Itoa(reservation)),
31+
resource.TestCheckResourceAttr("data.sysdig_agent_access_key.data", "enabled", strconv.FormatBool(true)),
32+
resource.TestCheckResourceAttr("data.sysdig_agent_access_key.data", "metadata.test", "yes"),
33+
resource.TestCheckResourceAttr("data.sysdig_agent_access_key.data", "metadata.acceptance_test", "true"),
34+
),
35+
},
36+
{
37+
Config: getAgentAccessKey(limit, reservation, false),
38+
Check: resource.ComposeAggregateTestCheckFunc(
39+
resource.TestCheckResourceAttr("data.sysdig_agent_access_key.data", "limit", strconv.Itoa(limit)),
40+
resource.TestCheckResourceAttr("data.sysdig_agent_access_key.data", "reservation", strconv.Itoa(reservation)),
41+
resource.TestCheckResourceAttr("data.sysdig_agent_access_key.data", "enabled", strconv.FormatBool(false)),
42+
resource.TestCheckResourceAttr("data.sysdig_agent_access_key.data", "metadata.test", "yes"),
43+
resource.TestCheckResourceAttr("data.sysdig_agent_access_key.data", "metadata.acceptance_test", "true"),
44+
),
45+
},
46+
},
47+
})
48+
}
49+
50+
func getAgentAccessKey(limit int, reservation int, enabled bool) string {
51+
return fmt.Sprintf(`
52+
resource "sysdig_agent_access_key" "my_agent_access_key" {
53+
limit = %d
54+
reservation = %d
55+
enabled = %t
56+
metadata = {
57+
"test" = "yes"
58+
"acceptance_test" = "true"
59+
}
60+
}
61+
62+
data "sysdig_agent_access_key" "data" {
63+
id = sysdig_agent_access_key.my_agent_access_key.id
64+
}
65+
`, limit, reservation, enabled)
66+
}
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
package v2
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"net/http"
7+
)
8+
9+
const (
10+
GetAgentAccessKeyByIdPath = "%s/platform/v1/access-keys/%s"
11+
CreateAgentAccessKeyPath = "%s/platform/v1/access-keys"
12+
DeleteAgentAccessKeyPath = "%s/platform/v1/access-keys/%s"
13+
PutAgentAccessKeyPath = "%s/platform/v1/access-keys/%s"
14+
)
15+
16+
type AgentAccessKeyInterface interface {
17+
Base
18+
GetAgentAccessKeyByID(ctx context.Context, id string) (*AgentAccessKey, error)
19+
CreateAgentAccessKey(ctx context.Context, agentAccessKey *AgentAccessKey) (*AgentAccessKey, error)
20+
DeleteAgentAccessKey(ctx context.Context, id string) error
21+
UpdateAgentAccessKey(ctx context.Context, agentAccessKey *AgentAccessKey, id string) (*AgentAccessKey, error)
22+
}
23+
24+
func (client *Client) GetAgentAccessKeyByID(ctx context.Context, id string) (*AgentAccessKey, error) {
25+
response, err := client.requester.Request(ctx, http.MethodGet, client.GetAgentAccessKeyByIdUrl(id), nil)
26+
if err != nil {
27+
return nil, err
28+
}
29+
defer response.Body.Close()
30+
31+
if response.StatusCode != http.StatusOK {
32+
err = client.ErrorFromResponse(response)
33+
return nil, err
34+
}
35+
36+
agentAccessKey, err := Unmarshal[AgentAccessKey](response.Body)
37+
if err != nil {
38+
return nil, err
39+
}
40+
41+
return &agentAccessKey, nil
42+
}
43+
44+
func (client *Client) CreateAgentAccessKey(ctx context.Context, agentAccessKey *AgentAccessKey) (*AgentAccessKey, error) {
45+
payload, err := Marshal(agentAccessKey)
46+
if err != nil {
47+
return nil, err
48+
}
49+
response, err := client.requester.Request(ctx, http.MethodPost, client.PostAgentAccessKeyUrl(), payload)
50+
if err != nil {
51+
return nil, err
52+
}
53+
defer response.Body.Close()
54+
55+
if response.StatusCode != http.StatusCreated {
56+
err = client.ErrorFromResponse(response)
57+
return nil, err
58+
}
59+
60+
createdAgentAccessKey, err := Unmarshal[AgentAccessKey](response.Body)
61+
62+
if err != nil {
63+
return nil, err
64+
}
65+
66+
return &createdAgentAccessKey, nil
67+
}
68+
69+
func (client *Client) UpdateAgentAccessKey(ctx context.Context, agentAccessKey *AgentAccessKey, id string) (*AgentAccessKey, error) {
70+
71+
payload, err := Marshal(agentAccessKey)
72+
if err != nil {
73+
return nil, err
74+
}
75+
response, err := client.requester.Request(ctx, http.MethodPut, client.PutAgentAccessKeyUrl(id), payload)
76+
if err != nil {
77+
return nil, err
78+
}
79+
defer response.Body.Close()
80+
81+
if response.StatusCode != http.StatusOK {
82+
err = client.ErrorFromResponse(response)
83+
return nil, err
84+
}
85+
86+
updatedAgentAccessKey, err := Unmarshal[AgentAccessKey](response.Body)
87+
if err != nil {
88+
return nil, err
89+
}
90+
91+
return &updatedAgentAccessKey, nil
92+
}
93+
94+
func (client *Client) DeleteAgentAccessKey(ctx context.Context, id string) error {
95+
response, err := client.requester.Request(ctx, http.MethodDelete, client.DeleteAgentAccessKeyUrl(id), nil)
96+
if err != nil {
97+
return err
98+
}
99+
defer response.Body.Close()
100+
101+
if response.StatusCode != http.StatusNoContent && response.StatusCode != http.StatusOK && response.StatusCode != http.StatusNotFound {
102+
return client.ErrorFromResponse(response)
103+
}
104+
105+
return nil
106+
}
107+
108+
func (client *Client) GetAgentAccessKeyByIdUrl(id string) string {
109+
return fmt.Sprintf(GetAgentAccessKeyByIdPath, client.config.url, id)
110+
}
111+
112+
func (client *Client) PostAgentAccessKeyUrl() string {
113+
return fmt.Sprintf(CreateAgentAccessKeyPath, client.config.url)
114+
}
115+
116+
func (client *Client) PutAgentAccessKeyUrl(id string) string {
117+
return fmt.Sprintf(PutAgentAccessKeyPath, client.config.url, id)
118+
}
119+
120+
func (client *Client) DeleteAgentAccessKeyUrl(id string) string {
121+
return fmt.Sprintf(DeleteAgentAccessKeyPath, client.config.url, id)
122+
}

sysdig/internal/client/v2/client.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ type Common interface {
4343
TeamInterface
4444
NotificationChannelInterface
4545
IdentityContextInterface
46+
AgentAccessKeyInterface
4647
}
4748

4849
type MonitorCommon interface {

sysdig/internal/client/v2/model.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,6 +1001,26 @@ type SilenceRule struct {
10011001
ID int `json:"id,omitempty"`
10021002
}
10031003

1004+
type AgentAccessKey struct {
1005+
ID int `json:"id,omitempty"`
1006+
Reservation int `json:"agentReservation"`
1007+
Limit int `json:"agentLimit"`
1008+
TeamID int `json:"teamId,omitempty"`
1009+
AgentAccessKey string `json:"accessKey,omitempty"`
1010+
Metadata map[string]string `json:"metadata,omitempty"`
1011+
Enabled bool `json:"isEnabled"`
1012+
DateCreated string `json:"dateCreated,omitempty"`
1013+
DateDisabled string `json:"dateDisabled,omitempty"`
1014+
}
1015+
1016+
type AgentAccessKeyReadWrapper struct {
1017+
CustomerAccessKey []AgentAccessKey `json:"customerAccessKeys"`
1018+
}
1019+
1020+
type AgentAccessKeyWriteWrapper struct {
1021+
CustomerAccessKey AgentAccessKey `json:"customerAccessKey"`
1022+
}
1023+
10041024
type OrganizationSecure struct {
10051025
cloudauth.CloudOrganization
10061026
}

sysdig/provider.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ func (p *SysdigProvider) Provider() *schema.Provider {
120120
"sysdig_group_mapping_config": resourceSysdigGroupMappingConfig(),
121121
"sysdig_custom_role": resourceSysdigCustomRole(),
122122
"sysdig_team_service_account": resourceSysdigTeamServiceAccount(),
123+
"sysdig_agent_access_key": resourceSysdigAgentAccessKey(),
123124

124125
"sysdig_secure_aws_ml_policy": resourceSysdigSecureAWSMLPolicy(),
125126
"sysdig_secure_custom_policy": resourceSysdigSecureCustomPolicy(),
@@ -219,11 +220,11 @@ func (p *SysdigProvider) Provider() *schema.Provider {
219220
"sysdig_secure_posture_policies": dataSourceSysdigSecurePosturePolicies(),
220221
"sysdig_secure_custom_role_permissions": dataSourceSysdigSecureCustomRolePermissions(),
221222

222-
"sysdig_current_user": dataSourceSysdigCurrentUser(),
223-
"sysdig_user": dataSourceSysdigUser(),
224-
"sysdig_secure_connection": dataSourceSysdigSecureConnection(),
225-
"sysdig_custom_role": dataSourceSysdigCustomRole(),
226-
223+
"sysdig_current_user": dataSourceSysdigCurrentUser(),
224+
"sysdig_user": dataSourceSysdigUser(),
225+
"sysdig_secure_connection": dataSourceSysdigSecureConnection(),
226+
"sysdig_custom_role": dataSourceSysdigCustomRole(),
227+
"sysdig_agent_access_key": dataSourceSysdigAgentAccessKey(),
227228
"sysdig_fargate_workload_agent": dataSourceSysdigFargateWorkloadAgent(),
228229
"sysdig_monitor_notification_channel_pagerduty": dataSourceSysdigMonitorNotificationChannelPagerduty(),
229230
"sysdig_monitor_notification_channel_email": dataSourceSysdigMonitorNotificationChannelEmail(),

0 commit comments

Comments
 (0)