Skip to content

Commit b33d7dd

Browse files
feat(secure-onboarding) Adding AccountComponent Resource (#504)
* feat(secure-onboarding) Adding AccountComponent Resource Change summary: ---------------- - Adding new Account Component resource with schema and CRUD operations in parity with Cloudauth Account resource. - Adding the respective client and support for new resource type. - Refactored common parsing methods for conversion from/to component metadata. - Added TF ACC tests for the new resource type. * Fix lint * Fix acc test * Add docs for AccountComponent resource * Addressing PR comments
1 parent 4d9d1d3 commit b33d7dd

13 files changed

+713
-161
lines changed

sysdig/common.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,5 @@ const (
6363
SchemaOrganizationalUnitIds = "organizational_unit_ids"
6464
SchemaCloudProviderTenantId = "provider_tenant_id"
6565
SchemaCloudProviderAlias = "provider_alias"
66+
SchemaAccountId = "account_id"
6667
)

sysdig/internal/client/v2/cloudauth.go

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"net/http"
1010

1111
"google.golang.org/protobuf/encoding/protojson"
12+
"google.golang.org/protobuf/proto"
1213
)
1314

1415
const (
@@ -26,7 +27,7 @@ type CloudauthAccountSecureInterface interface {
2627
}
2728

2829
func (client *Client) CreateCloudauthAccountSecure(ctx context.Context, cloudAccount *CloudauthAccountSecure) (*CloudauthAccountSecure, string, error) {
29-
payload, err := client.marshalProto(cloudAccount)
30+
payload, err := client.marshalCloudauthProto(cloudAccount)
3031
if err != nil {
3132
return nil, "", err
3233
}
@@ -42,7 +43,8 @@ func (client *Client) CreateCloudauthAccountSecure(ctx context.Context, cloudAcc
4243
return nil, errStatus, err
4344
}
4445

45-
cloudauthAccount, err := client.unmarshalProto(response.Body)
46+
cloudauthAccount := &CloudauthAccountSecure{}
47+
err = client.unmarshalCloudauthProto(response.Body, cloudauthAccount)
4648
if err != nil {
4749
return nil, "", err
4850
}
@@ -62,7 +64,8 @@ func (client *Client) GetCloudauthAccountSecure(ctx context.Context, accountID s
6264
return nil, errStatus, err
6365
}
6466

65-
cloudauthAccount, err := client.unmarshalProto(response.Body)
67+
cloudauthAccount := &CloudauthAccountSecure{}
68+
err = client.unmarshalCloudauthProto(response.Body, cloudauthAccount)
6669
if err != nil {
6770
return nil, "", err
6871
}
@@ -84,7 +87,7 @@ func (client *Client) DeleteCloudauthAccountSecure(ctx context.Context, accountI
8487

8588
func (client *Client) UpdateCloudauthAccountSecure(ctx context.Context, accountID string, cloudAccount *CloudauthAccountSecure) (
8689
*CloudauthAccountSecure, string, error) {
87-
payload, err := client.marshalProto(cloudAccount)
90+
payload, err := client.marshalCloudauthProto(cloudAccount)
8891
if err != nil {
8992
return nil, "", err
9093
}
@@ -100,7 +103,8 @@ func (client *Client) UpdateCloudauthAccountSecure(ctx context.Context, accountI
100103
return nil, errStatus, err
101104
}
102105

103-
cloudauthAccount, err := client.unmarshalProto(response.Body)
106+
cloudauthAccount := &CloudauthAccountSecure{}
107+
err = client.unmarshalCloudauthProto(response.Body, cloudauthAccount)
104108
if err != nil {
105109
return nil, "", err
106110
}
@@ -119,22 +123,20 @@ func (client *Client) getCloudauthAccountURL(accountID string, decrypt string) s
119123
return fmt.Sprintf(getCloudauthAccountPath, client.config.url, accountID, decrypt)
120124
}
121125

122-
// local function for protojson based marshal/unmarshal of cloudauthAccount proto
123-
func (client *Client) marshalProto(data *CloudauthAccountSecure) (io.Reader, error) {
124-
payload, err := protojson.Marshal(data)
126+
// common func for protojson based marshal/unmarshal of any cloudauth proto
127+
func (client *Client) marshalCloudauthProto(message proto.Message) (io.Reader, error) {
128+
payload, err := protojson.Marshal(message)
125129
return bytes.NewBuffer(payload), err
126130
}
127131

128-
func (client *Client) unmarshalProto(data io.ReadCloser) (*CloudauthAccountSecure, error) {
129-
result := &CloudauthAccountSecure{}
130-
132+
func (client *Client) unmarshalCloudauthProto(data io.ReadCloser, message proto.Message) error {
131133
body, err := io.ReadAll(data)
132134
if err != nil {
133-
return result, err
135+
return err
134136
}
135137

136-
err = protojson.UnmarshalOptions{DiscardUnknown: true}.Unmarshal(body, result)
137-
return result, err
138+
err = protojson.UnmarshalOptions{DiscardUnknown: true}.Unmarshal(body, message)
139+
return err
138140
}
139141

140142
func (client *Client) ErrorAndStatusFromResponse(response *http.Response) (string, error) {
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
package v2
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"net/http"
7+
)
8+
9+
const (
10+
cloudauthAccountComponentsPath = "%s/api/cloudauth/v1/accounts/%s/components" // POST
11+
cloudauthAccountComponentPath = "%s/api/cloudauth/v1/accounts/%s/components/%s/%s" // GET, PUT, DEL
12+
// getCloudauthAccountPath = "%s/api/cloudauth/v1/accounts/%s?decrypt=%s" // does GET require decryption?
13+
)
14+
15+
type CloudauthAccountComponentSecureInterface interface {
16+
Base
17+
CreateCloudauthAccountComponentSecure(ctx context.Context, accountID string, cloudAccountComponent *CloudauthAccountComponentSecure) (*CloudauthAccountComponentSecure, string, error)
18+
GetCloudauthAccountComponentSecure(ctx context.Context, accountID, componentType, componentInstance string) (*CloudauthAccountComponentSecure, string, error)
19+
DeleteCloudauthAccountComponentSecure(ctx context.Context, accountID, componentType, componentInstance string) (string, error)
20+
UpdateCloudauthAccountComponentSecure(ctx context.Context, accountID, componentType, componentInstance string, cloudAccountComponent *CloudauthAccountComponentSecure) (*CloudauthAccountComponentSecure, string, error)
21+
}
22+
23+
func (client *Client) CreateCloudauthAccountComponentSecure(ctx context.Context, accountID string, cloudAccountComponent *CloudauthAccountComponentSecure) (*CloudauthAccountComponentSecure, string, error) {
24+
payload, err := client.marshalCloudauthProto(cloudAccountComponent)
25+
if err != nil {
26+
return nil, "", err
27+
}
28+
29+
response, err := client.requester.Request(ctx, http.MethodPost, client.cloudauthAccountComponentsURL(accountID), payload)
30+
if err != nil {
31+
return nil, "", err
32+
}
33+
defer response.Body.Close()
34+
35+
if response.StatusCode != http.StatusOK && response.StatusCode != http.StatusCreated {
36+
errStatus, err := client.ErrorAndStatusFromResponse(response)
37+
return nil, errStatus, err
38+
}
39+
40+
cloudauthAccountComponent := &CloudauthAccountComponentSecure{}
41+
err = client.unmarshalCloudauthProto(response.Body, cloudauthAccountComponent)
42+
if err != nil {
43+
return nil, "", err
44+
}
45+
return cloudauthAccountComponent, "", nil
46+
}
47+
48+
func (client *Client) GetCloudauthAccountComponentSecure(ctx context.Context, accountID, componentType, componentInstance string) (*CloudauthAccountComponentSecure, string, error) {
49+
response, err := client.requester.Request(ctx, http.MethodGet, client.cloudauthAccountComponentURL(accountID, componentType, componentInstance), nil)
50+
if err != nil {
51+
return nil, "", err
52+
}
53+
defer response.Body.Close()
54+
55+
if response.StatusCode != http.StatusOK {
56+
errStatus, err := client.ErrorAndStatusFromResponse(response)
57+
return nil, errStatus, err
58+
}
59+
60+
cloudauthAccountComponent := &CloudauthAccountComponentSecure{}
61+
err = client.unmarshalCloudauthProto(response.Body, cloudauthAccountComponent)
62+
if err != nil {
63+
return nil, "", err
64+
}
65+
return cloudauthAccountComponent, "", nil
66+
}
67+
68+
func (client *Client) DeleteCloudauthAccountComponentSecure(ctx context.Context, accountID, componentType, componentInstance string) (string, error) {
69+
response, err := client.requester.Request(ctx, http.MethodDelete, client.cloudauthAccountComponentURL(accountID, componentType, componentInstance), nil)
70+
if err != nil {
71+
return "", err
72+
}
73+
defer response.Body.Close()
74+
75+
if response.StatusCode != http.StatusNoContent && response.StatusCode != http.StatusOK {
76+
return client.ErrorAndStatusFromResponse(response)
77+
}
78+
return "", nil
79+
}
80+
81+
func (client *Client) UpdateCloudauthAccountComponentSecure(ctx context.Context, accountID, componentType, componentInstance string, cloudAccountComponent *CloudauthAccountComponentSecure) (
82+
*CloudauthAccountComponentSecure, string, error) {
83+
payload, err := client.marshalCloudauthProto(cloudAccountComponent)
84+
if err != nil {
85+
return nil, "", err
86+
}
87+
88+
response, err := client.requester.Request(ctx, http.MethodPut, client.cloudauthAccountComponentURL(accountID, componentType, componentInstance), payload)
89+
if err != nil {
90+
return nil, "", err
91+
}
92+
defer response.Body.Close()
93+
94+
if response.StatusCode != http.StatusOK {
95+
errStatus, err := client.ErrorAndStatusFromResponse(response)
96+
return nil, errStatus, err
97+
}
98+
99+
cloudauthAccountComponent := &CloudauthAccountComponentSecure{}
100+
err = client.unmarshalCloudauthProto(response.Body, cloudauthAccountComponent)
101+
if err != nil {
102+
return nil, "", err
103+
}
104+
return cloudauthAccountComponent, "", nil
105+
}
106+
107+
func (client *Client) cloudauthAccountComponentsURL(accountID string) string {
108+
return fmt.Sprintf(cloudauthAccountComponentsPath, client.config.url, accountID)
109+
}
110+
111+
func (client *Client) cloudauthAccountComponentURL(accountID string, componentType string, componentInstance string) string {
112+
return fmt.Sprintf(cloudauthAccountComponentPath, client.config.url, accountID, componentType, componentInstance)
113+
}

sysdig/internal/client/v2/cloudauth_test.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
package v2
44

55
import (
6-
cloudauth "github.com/draios/terraform-provider-sysdig/sysdig/internal/client/v2/cloudauth/go"
76
"io"
87
"strings"
98
"testing"
9+
10+
cloudauth "github.com/draios/terraform-provider-sysdig/sysdig/internal/client/v2/cloudauth/go"
1011
)
1112

1213
func TestMarshalProto(t *testing.T) {
@@ -21,7 +22,7 @@ func TestMarshalProto(t *testing.T) {
2122
}
2223
expected := `{"enabled":true, "providerId":"test-project", "provider":"PROVIDER_GCP"}`
2324

24-
payload, err := c.marshalProto(given)
25+
payload, err := c.marshalCloudauthProto(given)
2526
if err != nil {
2627
t.Errorf("failed to marshal payload, err: %v", err)
2728
}
@@ -50,7 +51,8 @@ func TestUnmarshalProto(t *testing.T) {
5051
},
5152
}
5253

53-
unmarshalled, err := c.unmarshalProto(io.NopCloser(strings.NewReader(given)))
54+
unmarshalled := &CloudauthAccountSecure{}
55+
err := c.unmarshalCloudauthProto(io.NopCloser(strings.NewReader(given)), unmarshalled)
5456
if err != nil {
5557
t.Errorf("got error while unmarshaling, err: %v", err)
5658
}

sysdig/internal/client/v2/model.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,10 @@ type CloudauthAccountSecure struct {
605605
cloudauth.CloudAccount
606606
}
607607

608+
type CloudauthAccountComponentSecure struct {
609+
cloudauth.AccountComponent
610+
}
611+
608612
type ScanningPolicy struct {
609613
ID string `json:"id,omitempty"`
610614
Version string `json:"version,omitempty"`

sysdig/internal/client/v2/organization.go

Lines changed: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
11
package v2
22

33
import (
4-
"bytes"
54
"context"
65
"fmt"
7-
"io"
86
"net/http"
9-
10-
"google.golang.org/protobuf/encoding/protojson"
117
)
128

139
const (
@@ -24,7 +20,7 @@ type OrganizationSecureInterface interface {
2420
}
2521

2622
func (client *Client) CreateOrganizationSecure(ctx context.Context, org *OrganizationSecure) (*OrganizationSecure, string, error) {
27-
payload, err := client.marshalOrg(org)
23+
payload, err := client.marshalCloudauthProto(org)
2824
if err != nil {
2925
return nil, "", err
3026
}
@@ -40,7 +36,8 @@ func (client *Client) CreateOrganizationSecure(ctx context.Context, org *Organiz
4036
return nil, errStatus, err
4137
}
4238

43-
organization, err := client.unmarshalOrg(response.Body)
39+
organization := &OrganizationSecure{}
40+
err = client.unmarshalCloudauthProto(response.Body, organization)
4441
if err != nil {
4542
return nil, "", err
4643
}
@@ -59,7 +56,8 @@ func (client *Client) GetOrganizationSecure(ctx context.Context, orgID string) (
5956
return nil, errStatus, err
6057
}
6158

62-
organization, err := client.unmarshalOrg(response.Body)
59+
organization := &OrganizationSecure{}
60+
err = client.unmarshalCloudauthProto(response.Body, organization)
6361
if err != nil {
6462
return nil, "", err
6563
}
@@ -97,7 +95,8 @@ func (client *Client) UpdateOrganizationSecure(ctx context.Context, orgID string
9795
return nil, errStatus, err
9896
}
9997

100-
organization, err := client.unmarshalOrg(response.Body)
98+
organization := &OrganizationSecure{}
99+
err = client.unmarshalCloudauthProto(response.Body, organization)
101100
if err != nil {
102101
return nil, "", err
103102
}
@@ -111,21 +110,3 @@ func (client *Client) organizationsURL() string {
111110
func (client *Client) organizationURL(orgId string) string {
112111
return fmt.Sprintf(organizationPath, client.config.url, orgId)
113112
}
114-
115-
// local function for protojson based marshal/unmarshal of organization proto
116-
func (client *Client) marshalOrg(data *OrganizationSecure) (io.Reader, error) {
117-
payload, err := protojson.Marshal(data)
118-
return bytes.NewBuffer(payload), err
119-
}
120-
121-
func (client *Client) unmarshalOrg(data io.ReadCloser) (*OrganizationSecure, error) {
122-
result := &OrganizationSecure{}
123-
124-
body, err := io.ReadAll(data)
125-
if err != nil {
126-
return result, err
127-
}
128-
129-
err = protojson.UnmarshalOptions{DiscardUnknown: true}.Unmarshal(body, result)
130-
return result, err
131-
}

sysdig/internal/client/v2/organization_test.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
package v2
44

55
import (
6-
cloudauth "github.com/draios/terraform-provider-sysdig/sysdig/internal/client/v2/cloudauth/go"
76
"io"
87
"strings"
98
"testing"
9+
10+
cloudauth "github.com/draios/terraform-provider-sysdig/sysdig/internal/client/v2/cloudauth/go"
1011
)
1112

1213
func TestMarshalOrg(t *testing.T) {
@@ -21,7 +22,7 @@ func TestMarshalOrg(t *testing.T) {
2122
}
2223
expected := `{"managementAccountId":"58ca66a5-ac87-497b-a501-7a4c934b3017", "provider":"PROVIDER_GCP"}`
2324

24-
payload, err := c.marshalOrg(given)
25+
payload, err := c.marshalCloudauthProto(given)
2526
if err != nil {
2627
t.Errorf("failed to marshal payload, err: %v", err)
2728
}
@@ -49,7 +50,8 @@ func TestUnmarshalOrg(t *testing.T) {
4950
},
5051
}
5152

52-
unmarshalled, err := c.unmarshalOrg(io.NopCloser(strings.NewReader(given)))
53+
unmarshalled := &OrganizationSecure{}
54+
err := c.unmarshalCloudauthProto(io.NopCloser(strings.NewReader(given)), unmarshalled)
5355
if err != nil {
5456
t.Errorf("got error while unmarshaling, err: %v", err)
5557
}

sysdig/internal/client/v2/sysdig.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ type SysdigSecure interface {
4646
CloudAccountSecureInterface
4747
CloudauthAccountSecureInterface
4848
OrganizationSecureInterface
49+
CloudauthAccountComponentSecureInterface
4950
}
5051

5152
func (sr *SysdigRequest) Request(ctx context.Context, method string, url string, payload io.Reader) (*http.Response, error) {

sysdig/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ func (p *SysdigProvider) Provider() *schema.Provider {
155155
"sysdig_secure_scanning_policy": resourceSysdigSecureScanningPolicy(),
156156
"sysdig_secure_scanning_policy_assignment": resourceSysdigSecureScanningPolicyAssignment(),
157157
"sysdig_secure_cloud_auth_account": resourceSysdigSecureCloudauthAccount(),
158+
"sysdig_secure_cloud_auth_account_component": resourceSysdigSecureCloudauthAccountComponent(),
158159

159160
"sysdig_monitor_silence_rule": resourceSysdigMonitorSilenceRule(),
160161
"sysdig_monitor_alert_downtime": resourceSysdigMonitorAlertDowntime(),

0 commit comments

Comments
 (0)