From e5a93b6da653acb44db79a9842e8031c2bd30774 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Thu, 17 Apr 2025 20:15:27 +0000 Subject: [PATCH 1/2] fix: don't use `uuid.UUID` for id fields --- owner.go | 20 +++++++++++++-- types/owner.go | 68 ++++++-------------------------------------------- 2 files changed, 25 insertions(+), 63 deletions(-) diff --git a/owner.go b/owner.go index 3e5bfaa..5402a53 100644 --- a/owner.go +++ b/owner.go @@ -6,12 +6,28 @@ import ( "github.com/aquasecurity/trivy/pkg/iac/terraform" tfcontext "github.com/aquasecurity/trivy/pkg/iac/terraform/context" "github.com/zclconf/go-cty/cty" + "github.com/zclconf/go-cty/cty/gocty" + "golang.org/x/xerrors" ) func workspaceOwnerHook(dfs fs.FS, input Input) (func(ctx *tfcontext.Context, blocks terraform.Blocks, inputVars map[string]cty.Value), error) { - ownerValue, err := input.Owner.ToCtyValue() + ownerValue, err := gocty.ToCtyValue(input.Owner, cty.Object(map[string]cty.Type{ + "id": cty.String, + "name": cty.String, + "full_name": cty.String, + "email": cty.String, + "ssh_public_key": cty.String, + "groups": cty.List(cty.String), + "login_type": cty.String, + "rbac_roles": cty.List(cty.Object( + map[string]cty.Type{ + "name": cty.String, + "org_id": cty.String, + }, + )), + })) if err != nil { - return nil, err + return nil, xerrors.Errorf("failed to convert owner value", err) } return func(ctx *tfcontext.Context, blocks terraform.Blocks, inputVars map[string]cty.Value) { diff --git a/types/owner.go b/types/owner.go index 2676091..e2a3230 100644 --- a/types/owner.go +++ b/types/owner.go @@ -1,18 +1,12 @@ package types -import ( - "github.com/google/uuid" - "github.com/zclconf/go-cty/cty" - "github.com/zclconf/go-cty/cty/gocty" -) - // Based on https://github.com/coder/terraform-provider-coder/blob/9a745586b23a9cb5de2f65a2dcac12e48b134ffa/provider/workspace_owner.go#L72 type WorkspaceOwner struct { - ID uuid.UUID `json:"id"` - Name string `json:"name"` - FullName string `json:"full_name"` - Email string `json:"email"` - SSHPublicKey string `json:"ssh_public_key"` + ID string `json:"id"` + Name string `json:"name"` + FullName string `json:"full_name"` + Email string `json:"email"` + SSHPublicKey string `json:"ssh_public_key"` // SSHPrivateKey is intentionally omitted for now, due to the security risk // that exposing it poses. // SSHPrivateKey string `json:"ssh_private_key"` @@ -27,55 +21,7 @@ type WorkspaceOwner struct { RBACRoles []WorkspaceOwnerRBACRole `json:"rbac_roles"` } -func (o *WorkspaceOwner) ToCtyValue() (cty.Value, error) { - if o.Groups == nil { - o.Groups = []string{} - } - convertedGroups, err := gocty.ToCtyValue(o.Groups, cty.List(cty.String)) - if err != nil { - return cty.Value{}, err - } - - roleValues := make([]cty.Value, 0, len(o.RBACRoles)) - for _, role := range o.RBACRoles { - roleValue, err := role.ToCtyValue() - if err != nil { - return cty.Value{}, err - } - roleValues = append(roleValues, roleValue) - } - var convertedRoles cty.Value = cty.ListValEmpty(WorkspaceOwnerRBACRole{}.CtyType()) - if len(roleValues) > 0 { - convertedRoles = cty.ListVal(roleValues) - } - - return cty.ObjectVal(map[string]cty.Value{ - "id": cty.StringVal(o.ID.String()), - "name": cty.StringVal(o.Name), - "full_name": cty.StringVal(o.FullName), - "email": cty.StringVal(o.Email), - "ssh_public_key": cty.StringVal(o.SSHPublicKey), - "groups": convertedGroups, - "login_type": cty.StringVal(o.LoginType), - "rbac_roles": convertedRoles, - }), nil -} - type WorkspaceOwnerRBACRole struct { - Name string `json:"name"` - OrgID uuid.UUID `json:"org_id"` -} - -func (_ WorkspaceOwnerRBACRole) CtyType() cty.Type { - return cty.Object(map[string]cty.Type{ - "name": cty.String, - "org_id": cty.String, - }) -} - -func (r *WorkspaceOwnerRBACRole) ToCtyValue() (cty.Value, error) { - return cty.ObjectVal(map[string]cty.Value{ - "name": cty.StringVal(r.Name), - "org_id": cty.StringVal(r.OrgID.String()), - }), nil + Name string `json:"name"` + OrgID string `json:"org_id"` } From 931c717b0d745a54c4d003a59b8a68e703fc14bb Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Thu, 17 Apr 2025 20:26:44 +0000 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=A7=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- owner.go | 19 ++------------ types/owner.go | 61 +++++++++++++++++++++++++++++++++++---------- types/owner_test.go | 11 ++++---- 3 files changed, 55 insertions(+), 36 deletions(-) diff --git a/owner.go b/owner.go index 5402a53..a300a30 100644 --- a/owner.go +++ b/owner.go @@ -6,26 +6,11 @@ import ( "github.com/aquasecurity/trivy/pkg/iac/terraform" tfcontext "github.com/aquasecurity/trivy/pkg/iac/terraform/context" "github.com/zclconf/go-cty/cty" - "github.com/zclconf/go-cty/cty/gocty" "golang.org/x/xerrors" ) -func workspaceOwnerHook(dfs fs.FS, input Input) (func(ctx *tfcontext.Context, blocks terraform.Blocks, inputVars map[string]cty.Value), error) { - ownerValue, err := gocty.ToCtyValue(input.Owner, cty.Object(map[string]cty.Type{ - "id": cty.String, - "name": cty.String, - "full_name": cty.String, - "email": cty.String, - "ssh_public_key": cty.String, - "groups": cty.List(cty.String), - "login_type": cty.String, - "rbac_roles": cty.List(cty.Object( - map[string]cty.Type{ - "name": cty.String, - "org_id": cty.String, - }, - )), - })) +func workspaceOwnerHook(_ fs.FS, input Input) (func(ctx *tfcontext.Context, blocks terraform.Blocks, inputVars map[string]cty.Value), error) { + ownerValue, err := input.Owner.ToCtyValue() if err != nil { return nil, xerrors.Errorf("failed to convert owner value", err) } diff --git a/types/owner.go b/types/owner.go index e2a3230..e714d5f 100644 --- a/types/owner.go +++ b/types/owner.go @@ -1,27 +1,62 @@ package types +import ( + "github.com/zclconf/go-cty/cty" + "github.com/zclconf/go-cty/cty/gocty" + "golang.org/x/xerrors" +) + // Based on https://github.com/coder/terraform-provider-coder/blob/9a745586b23a9cb5de2f65a2dcac12e48b134ffa/provider/workspace_owner.go#L72 type WorkspaceOwner struct { - ID string `json:"id"` - Name string `json:"name"` - FullName string `json:"full_name"` - Email string `json:"email"` - SSHPublicKey string `json:"ssh_public_key"` + ID string `json:"id" cty:"id"` + Name string `json:"name" cty:"name"` + FullName string `json:"full_name" cty:"full_name"` + Email string `json:"email" cty:"email"` + SSHPublicKey string `json:"ssh_public_key" cty:"ssh_public_key"` // SSHPrivateKey is intentionally omitted for now, due to the security risk // that exposing it poses. - // SSHPrivateKey string `json:"ssh_private_key"` - Groups []string `json:"groups"` + // SSHPrivateKey string `json:"ssh_private_key" cty:"ssh_private_key"` + Groups []string `json:"groups" cty:"groups"` // SessionToken is intentionally omitted for now, due to the security risk // that exposing it poses. - // SessionToken string `json:"session_token"` + // SessionToken string `json:"session_token" cty:"session_token"` // OIDCAccessToken is intentionally omitted for now, due to the security risk // that exposing it poses. - // OIDCAccessToken string `json:"oidc_access_token"` - LoginType string `json:"login_type"` - RBACRoles []WorkspaceOwnerRBACRole `json:"rbac_roles"` + // OIDCAccessToken string `json:"oidc_access_token" cty:"oidc_access_token"` + LoginType string `json:"login_type" cty:"login_type"` + RBACRoles []WorkspaceOwnerRBACRole `json:"rbac_roles" cty:"rbac_roles"` } type WorkspaceOwnerRBACRole struct { - Name string `json:"name"` - OrgID string `json:"org_id"` + Name string `json:"name" cty:"name"` + OrgID string `json:"org_id" cty:"org_id"` +} + +func (o *WorkspaceOwner) ToCtyValue() (cty.Value, error) { + if o.Groups == nil { + o.Groups = make([]string, 0) + } + if o.RBACRoles == nil { + o.RBACRoles = make([]WorkspaceOwnerRBACRole, 0) + } + + ownerValue, err := gocty.ToCtyValue(o, cty.Object(map[string]cty.Type{ + "id": cty.String, + "name": cty.String, + "full_name": cty.String, + "email": cty.String, + "ssh_public_key": cty.String, + "groups": cty.List(cty.String), + "login_type": cty.String, + "rbac_roles": cty.List(cty.Object( + map[string]cty.Type{ + "name": cty.String, + "org_id": cty.String, + }, + )), + })) + if err != nil { + return cty.Value{}, xerrors.Errorf("failed to convert owner value", err) + } + return ownerValue, nil } diff --git a/types/owner_test.go b/types/owner_test.go index a2a3585..d8fb549 100644 --- a/types/owner_test.go +++ b/types/owner_test.go @@ -3,13 +3,12 @@ package types import ( "testing" - "github.com/google/uuid" "github.com/stretchr/testify/require" ) func TestToCtyValue(t *testing.T) { owner := WorkspaceOwner{ - ID: uuid.MustParse("f6457744-3e16-45b2-b3b0-80c2df491c99"), + ID: "f6457744-3e16-45b2-b3b0-80c2df491c99", Name: "Nissa", FullName: "Nissa, Worldwaker", Email: "nissa@coder.com", @@ -18,14 +17,14 @@ func TestToCtyValue(t *testing.T) { LoginType: "password", RBACRoles: []WorkspaceOwnerRBACRole{ {Name: "User Admin"}, - {Name: "Organization User Admin", OrgID: uuid.MustParse("5af9253a-ecde-4a71-b8f5-c8d15be9e52b")}, + {Name: "Organization User Admin", OrgID: "5af9253a-ecde-4a71-b8f5-c8d15be9e52b"}, }, } ownerValue, err := owner.ToCtyValue() require.NoError(t, err) - require.Equal(t, owner.ID.String(), ownerValue.AsValueMap()["id"].AsString()) + require.Equal(t, owner.ID, ownerValue.AsValueMap()["id"].AsString()) require.Equal(t, owner.Name, ownerValue.AsValueMap()["name"].AsString()) require.Equal(t, owner.SSHPublicKey, ownerValue.AsValueMap()["ssh_public_key"].AsString()) for i, it := range owner.Groups { @@ -34,13 +33,13 @@ func TestToCtyValue(t *testing.T) { for i, it := range owner.RBACRoles { roleValueMap := ownerValue.AsValueMap()["rbac_roles"].AsValueSlice()[i].AsValueMap() require.Equal(t, it.Name, roleValueMap["name"].AsString()) - require.Equal(t, it.OrgID.String(), roleValueMap["org_id"].AsString()) + require.Equal(t, it.OrgID, roleValueMap["org_id"].AsString()) } } func TestToCtyValueWithNilLists(t *testing.T) { owner := WorkspaceOwner{ - ID: uuid.MustParse("f6457744-3e16-45b2-b3b0-80c2df491c99"), + ID: "f6457744-3e16-45b2-b3b0-80c2df491c99", Name: "Nissa", FullName: "Nissa, Worldwaker", Email: "nissa@coder.com",