Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(secure-onboarding) Fix resource update operation #435

Merged
merged 4 commits into from
Oct 27, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions sysdig/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,5 @@ const (
SchemaCloudProviderType = "provider_type"
SchemaFeature = "feature"
SchemaManagementAccountId = "management_account_id"
SchemaOrganizationIDKey = "organization_id"
)
75 changes: 61 additions & 14 deletions sysdig/resource_sysdig_secure_cloud_auth_account.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
b64 "encoding/base64"
"encoding/json"
"errors"
"fmt"
"reflect"
"strings"
Expand Down Expand Up @@ -153,6 +154,10 @@ func resourceSysdigSecureCloudauthAccount() *schema.Resource {
Optional: true,
Elem: accountComponents,
},
SchemaOrganizationIDKey: {
Type: schema.TypeString,
Computed: true,
},
},
}
}
Expand All @@ -173,6 +178,10 @@ func resourceSysdigSecureCloudauthAccountCreate(ctx context.Context, data *schem
}

data.SetId(cloudauthAccount.Id)
err = data.Set(SchemaOrganizationIDKey, cloudauthAccount.OrganizationId)
if err != nil {
return diag.FromErr(err)
}

return nil
}
Expand Down Expand Up @@ -206,8 +215,23 @@ func resourceSysdigSecureCloudauthAccountUpdate(ctx context.Context, data *schem
return diag.FromErr(err)
}

_, errStatus, err := client.UpdateCloudauthAccountSecure(ctx, data.Id(), cloudauthAccountFromResourceData(data))
existingCloudAccount, errStatus, err := client.GetCloudauthAccountSecure(ctx, data.Id())
if err != nil {
if strings.Contains(errStatus, "404") {
return nil
}
return diag.FromErr(err)
}

newCloudAccount := cloudauthAccountFromResourceData(data)

// validate and reject non-updatable resource schema fields upfront
err = validateCloudauthAccountUpdate(existingCloudAccount, newCloudAccount)
if err != nil {
return diag.FromErr(err)
}

_, errStatus, err = client.UpdateCloudauthAccountSecure(ctx, data.Id(), newCloudAccount)
if err != nil {
if strings.Contains(errStatus, "404") {
return nil
Expand Down Expand Up @@ -236,6 +260,19 @@ func resourceSysdigSecureCloudauthAccountDelete(ctx context.Context, data *schem
return nil
}

/*
This function validates and restricts any fields not allowed to be updated during resource updates.
*/
func validateCloudauthAccountUpdate(existingCloudAccount *v2.CloudauthAccountSecure, newCloudAccount *v2.CloudauthAccountSecure) error {
if existingCloudAccount.Enabled != newCloudAccount.Enabled || existingCloudAccount.Provider != newCloudAccount.Provider ||
existingCloudAccount.ProviderId != newCloudAccount.ProviderId || existingCloudAccount.OrganizationId != newCloudAccount.OrganizationId {
errorInvalidResourceUpdate := fmt.Sprintf("Bad Request. Updating restricted fields not allowed: %s", []string{"enabled", "provider_type", "provider_id", "organization_id"})
return errors.New(errorInvalidResourceUpdate)
}

return nil
}

/*
This function converts a schema set to map for iteration.
*/
Expand Down Expand Up @@ -439,11 +476,12 @@ func cloudauthAccountFromResourceData(data *schema.ResourceData) *v2.CloudauthAc

return &v2.CloudauthAccountSecure{
CloudAccount: cloudauth.CloudAccount{
Enabled: data.Get(SchemaEnabled).(bool),
ProviderId: data.Get(SchemaCloudProviderId).(string),
Provider: cloudauth.Provider(cloudauth.Provider_value[data.Get(SchemaCloudProviderType).(string)]),
Components: accountComponents,
Feature: accountFeatures,
Enabled: data.Get(SchemaEnabled).(bool),
OrganizationId: data.Get(SchemaOrganizationIDKey).(string),
ProviderId: data.Get(SchemaCloudProviderId).(string),
Provider: cloudauth.Provider(cloudauth.Provider_value[data.Get(SchemaCloudProviderType).(string)]),
Components: accountComponents,
Feature: accountFeatures,
},
}
}
Expand Down Expand Up @@ -498,6 +536,19 @@ func featureToResourceData(features *cloudauth.AccountFeatures) []interface{} {
return nil
}

func componentsToResourceData(components []*cloudauth.AccountComponent) []map[string]interface{} {
componentsList := []map[string]interface{}{}

for _, comp := range components {
componentsList = append(componentsList, map[string]interface{}{
SchemaType: comp.Type.String(),
SchemaInstance: comp.Instance,
})
}

return componentsList
}

func cloudauthAccountToResourceData(data *schema.ResourceData, cloudAccount *v2.CloudauthAccountSecure) error {
err := data.Set(SchemaIDKey, cloudAccount.Id)
if err != nil {
Expand All @@ -524,16 +575,12 @@ func cloudauthAccountToResourceData(data *schema.ResourceData, cloudAccount *v2.
return err
}

components := []map[string]interface{}{}

for _, comp := range cloudAccount.Components {
components = append(components, map[string]interface{}{
SchemaType: comp.Type.String(),
SchemaInstance: comp.Instance,
})
err = data.Set(SchemaComponent, componentsToResourceData(cloudAccount.Components))
if err != nil {
return err
}

err = data.Set(SchemaComponent, components)
err = data.Set(SchemaOrganizationIDKey, cloudAccount.OrganizationId)
if err != nil {
return err
}
Expand Down
33 changes: 19 additions & 14 deletions sysdig/resource_sysdig_secure_cloud_auth_account_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,19 +80,6 @@ func TestAccSecureCloudAuthAccountFC(t *testing.T) {
}

func secureCloudAuthAccountWithFC(accountID string) string {
type sample_service_account_key struct {
ProjectId string `json:"project_id"`
PrivateKeyId string `json:"private_key_id"`
PrivateKey string `json:"private_key"`
}
test_service_account_key := &sample_service_account_key{
ProjectId: fmt.Sprintf("sample-1-%s", accountID),
PrivateKeyId: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
PrivateKey: "-----BEGIN PRIVATE KEY-----\nxxxxxxxxxxxxxxxxxxxxxxxxxxx\n-----END PRIVATE KEY-----\n",
}
test_service_account_keyJSON, _ := json.Marshal(test_service_account_key)
test_service_account_key_encoded := b64.StdEncoding.EncodeToString([]byte(string(test_service_account_keyJSON)))

return fmt.Sprintf(`
resource "sysdig_secure_cloud_auth_account" "sample-1" {
provider_id = "sample-1-%s"
Expand Down Expand Up @@ -121,5 +108,23 @@ resource "sysdig_secure_cloud_auth_account" "sample-1" {
ignore_changes = [component]
}
}
`, accountID, test_service_account_key_encoded)
`, accountID, getEncodedServiceAccountKey("sample-1", accountID))
}

func getEncodedServiceAccountKey(resourceName string, accountID string) string {
type sample_service_account_key struct {
Type string `json:"type"`
ProjectId string `json:"project_id"`
PrivateKeyId string `json:"private_key_id"`
PrivateKey string `json:"private_key"`
}
test_service_account_key := &sample_service_account_key{
Type: "service_account",
ProjectId: fmt.Sprintf("%s-%s", resourceName, accountID),
PrivateKeyId: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
PrivateKey: "-----BEGIN PRIVATE KEY-----\nxxxxxxxxxxxxxxxxxxxxxxxxxxx\n-----END PRIVATE KEY-----\n",
}
test_service_account_keyJSON, _ := json.Marshal(test_service_account_key)
test_service_account_key_encoded := b64.StdEncoding.EncodeToString([]byte(string(test_service_account_keyJSON)))
return test_service_account_key_encoded
}
Loading