diff --git a/owner.go b/owner.go index b3f7b56..3e5bfaa 100644 --- a/owner.go +++ b/owner.go @@ -6,23 +6,14 @@ 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) { - if input.Owner.Groups == nil { - input.Owner.Groups = []string{} - } - ownerGroups, err := gocty.ToCtyValue(input.Owner.Groups, cty.List(cty.String)) + ownerValue, err := input.Owner.ToCtyValue() if err != nil { - return nil, xerrors.Errorf("converting owner groups: %w", err) + return nil, err } - ownerValue := cty.ObjectVal(map[string]cty.Value{ - "groups": ownerGroups, - }) - return func(ctx *tfcontext.Context, blocks terraform.Blocks, inputVars map[string]cty.Value) { for _, block := range blocks.OfType("data") { // TODO: Does it have to be me? diff --git a/types/owner.go b/types/owner.go index 1d6b9f4..2676091 100644 --- a/types/owner.go +++ b/types/owner.go @@ -2,6 +2,8 @@ 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 @@ -25,7 +27,55 @@ 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 +} diff --git a/types/owner_test.go b/types/owner_test.go new file mode 100644 index 0000000..a2a3585 --- /dev/null +++ b/types/owner_test.go @@ -0,0 +1,57 @@ +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"), + Name: "Nissa", + FullName: "Nissa, Worldwaker", + Email: "nissa@coder.com", + SSHPublicKey: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBSHXs/HCgZlpEBOXLvLw4KaOrhy1DM1Vw6M/HPVE/UA\n", + Groups: []string{"Everyone", "Planeswalkers", "Green"}, + LoginType: "password", + RBACRoles: []WorkspaceOwnerRBACRole{ + {Name: "User Admin"}, + {Name: "Organization User Admin", OrgID: uuid.MustParse("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.Name, ownerValue.AsValueMap()["name"].AsString()) + require.Equal(t, owner.SSHPublicKey, ownerValue.AsValueMap()["ssh_public_key"].AsString()) + for i, it := range owner.Groups { + require.Equal(t, it, ownerValue.AsValueMap()["groups"].AsValueSlice()[i].AsString()) + } + 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()) + } +} + +func TestToCtyValueWithNilLists(t *testing.T) { + owner := WorkspaceOwner{ + ID: uuid.MustParse("f6457744-3e16-45b2-b3b0-80c2df491c99"), + Name: "Nissa", + FullName: "Nissa, Worldwaker", + Email: "nissa@coder.com", + SSHPublicKey: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBSHXs/HCgZlpEBOXLvLw4KaOrhy1DM1Vw6M/HPVE/UA\n", + Groups: nil, + LoginType: "password", + RBACRoles: nil, + } + + ownerValue, err := owner.ToCtyValue() + require.NoError(t, err) + require.Empty(t, ownerValue.AsValueMap()["groups"].AsValueSlice()) + require.Empty(t, ownerValue.AsValueMap()["rbac_roles"].AsValueSlice()) +}