Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion cmd/cli/Taskfile.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ tasks:
STORE_ID:
sh: fga store list --api-token={{ .FGA_API_TOKEN }} | jq -r '.stores.[].id'
USER_ID:
sh: ../../openlane-cli user get -z json --host {{ .OPENLANE_API_HOST }} | jq -r '.self.id'
sh: go run main.go user get -z json --host {{ .OPENLANE_API_HOST }} | jq -r '.self.id'
cmds:
- fga tuple write --store-id={{ .STORE_ID }} user:{{ .USER_ID }} system_admin system:openlane_core --api-token={{ .FGA_API_TOKEN }}

Expand Down
71 changes: 71 additions & 0 deletions cmd/cli/cmd/trustcentercompliance/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package trustcentercompliance

import (
"context"

"github.com/spf13/cobra"

"github.com/theopenlane/core/cmd/cli/cmd"
"github.com/theopenlane/core/pkg/openlaneclient"
)

var createCmd = &cobra.Command{
Use: "create",
Short: "create a new trust center compliance",
Run: func(cmd *cobra.Command, args []string) {
err := create(cmd.Context())
cobra.CheckErr(err)
},
}

func init() {
command.AddCommand(createCmd)

createCmd.Flags().StringP("standard-id", "s", "", "standard id for the compliance (required)")
createCmd.Flags().StringP("trust-center-id", "t", "", "trust center id for the compliance")
createCmd.Flags().StringSliceP("tags", "", []string{}, "tags associated with the trust center compliance")
}

// createValidation validates the required fields for the command
func createValidation() (*openlaneclient.CreateTrustCenterComplianceInput, error) {
standardID := cmd.Config.String("standard-id")
if standardID == "" {
return nil, cmd.NewRequiredFieldMissingError("standard id")
}

input := &openlaneclient.CreateTrustCenterComplianceInput{
StandardID: standardID,
}

trustCenterID := cmd.Config.String("trust-center-id")
if trustCenterID != "" {
input.TrustCenterID = &trustCenterID
}

tags := cmd.Config.Strings("tags")
if len(tags) > 0 {
input.Tags = tags
}

return input, nil
}

// create a new trust center compliance
func create(ctx context.Context) error {
// attempt to setup with token, otherwise fall back to JWT with session
client, err := cmd.TokenAuth(ctx, cmd.Config)
if err != nil || client == nil {
// setup http client
client, err = cmd.SetupClientWithAuth(ctx)
cobra.CheckErr(err)
defer cmd.StoreSessionCookies(client)
}

input, err := createValidation()
cobra.CheckErr(err)

o, err := client.CreateTrustCenterCompliance(ctx, *input)
cobra.CheckErr(err)

return consoleOutput(o)
}
54 changes: 54 additions & 0 deletions cmd/cli/cmd/trustcentercompliance/delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package trustcentercompliance

import (
"context"

"github.com/spf13/cobra"

"github.com/theopenlane/core/cmd/cli/cmd"
)

var deleteCmd = &cobra.Command{
Use: "delete",
Short: "delete an existing trust center compliance",
Run: func(cmd *cobra.Command, args []string) {
err := delete(cmd.Context())
cobra.CheckErr(err)
},
}

func init() {
command.AddCommand(deleteCmd)

deleteCmd.Flags().StringP("id", "i", "", "trust center compliance id to delete")
}

// deleteValidation validates the required fields for the command
func deleteValidation() (string, error) {
id := cmd.Config.String("id")
if id == "" {
return "", cmd.NewRequiredFieldMissingError("trust center compliance id")
}

return id, nil
}

// delete an existing trust center compliance in the platform
func delete(ctx context.Context) error {
// attempt to setup with token, otherwise fall back to JWT with session
client, err := cmd.TokenAuth(ctx, cmd.Config)
if err != nil || client == nil {
// setup http client
client, err = cmd.SetupClientWithAuth(ctx)
cobra.CheckErr(err)
defer cmd.StoreSessionCookies(client)
}

id, err := deleteValidation()
cobra.CheckErr(err)

o, err := client.DeleteTrustCenterCompliance(ctx, id)
cobra.CheckErr(err)

return consoleOutput(o)
}
52 changes: 52 additions & 0 deletions cmd/cli/cmd/trustcentercompliance/get.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package trustcentercompliance

import (
"context"

"github.com/spf13/cobra"

"github.com/theopenlane/core/cmd/cli/cmd"
)

var getCmd = &cobra.Command{
Use: "get",
Short: "get an existing trust center compliance",
Run: func(cmd *cobra.Command, args []string) {
err := get(cmd.Context())
cobra.CheckErr(err)
},
}

func init() {
command.AddCommand(getCmd)

getCmd.Flags().StringP("id", "i", "", "trust center compliance id to retrieve")
}

// get an existing trust center compliance in the platform
func get(ctx context.Context) error {
// attempt to setup with token, otherwise fall back to JWT with session
client, err := cmd.TokenAuth(ctx, cmd.Config)
if err != nil || client == nil {
// setup http client
client, err = cmd.SetupClientWithAuth(ctx)
cobra.CheckErr(err)
defer cmd.StoreSessionCookies(client)
}
// filter options
id := cmd.Config.String("id")

// if a trust center compliance ID is provided, filter on that trust center compliance, otherwise get all
if id != "" {
o, err := client.GetTrustCenterComplianceByID(ctx, id)
cobra.CheckErr(err)

return consoleOutput(o)
}

// get all will be filtered for the authorized organization(s)
o, err := client.GetAllTrustCenterCompliances(ctx)
cobra.CheckErr(err)

return consoleOutput(o)
}
103 changes: 103 additions & 0 deletions cmd/cli/cmd/trustcentercompliance/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package trustcentercompliance

import (
"encoding/json"
"strings"

"github.com/spf13/cobra"

"github.com/theopenlane/utils/cli/tables"

"github.com/theopenlane/core/cmd/cli/cmd"
"github.com/theopenlane/core/pkg/openlaneclient"
)

// command represents the base trustcentercompliance command when called without any subcommands
var command = &cobra.Command{
Use: "trustcentercompliance",
Short: "the subcommands for working with trust center compliances",
}

func init() {
cmd.RootCmd.AddCommand(command)
}

// consoleOutput prints the output in the console
func consoleOutput(e any) error {
// check if the output format is JSON and print the trust center compliances in JSON format
if strings.EqualFold(cmd.OutputFormat, cmd.JSONOutput) {
return jsonOutput(e)
}

// check if the output is a slice of trust center compliances
if trustCenterCompliances, ok := e.(*openlaneclient.GetAllTrustCenterCompliances); ok {
var nodes []*openlaneclient.GetAllTrustCenterCompliances_TrustCenterCompliances_Edges_Node

for _, edge := range trustCenterCompliances.TrustCenterCompliances.Edges {
nodes = append(nodes, edge.Node)
}

e = nodes
}

// check if the output is a single trust center compliance
if trustCenterCompliance, ok := e.(*openlaneclient.GetTrustCenterComplianceByID); ok {
e = trustCenterCompliance.TrustCenterCompliance
}

// check if the output is a create trust center compliance response
if createResp, ok := e.(*openlaneclient.CreateTrustCenterCompliance); ok {
e = createResp.CreateTrustCenterCompliance.TrustCenterCompliance
}

// check if the output is a delete trust center compliance response
if deleteResp, ok := e.(*openlaneclient.DeleteTrustCenterCompliance); ok {
deletedTableOutput(deleteResp)
return nil
}

s, err := json.Marshal(e)
cobra.CheckErr(err)

var list []openlaneclient.GetAllTrustCenterCompliances_TrustCenterCompliances_Edges_Node

err = json.Unmarshal(s, &list)
if err != nil {
var in openlaneclient.GetAllTrustCenterCompliances_TrustCenterCompliances_Edges_Node
err = json.Unmarshal(s, &in)
cobra.CheckErr(err)

list = append(list, in)
}

tableOutput(list)

return nil
}

// jsonOutput prints the output in a JSON format
func jsonOutput(out any) error {
s, err := json.Marshal(out)
cobra.CheckErr(err)

return cmd.JSONPrint(s)
}

// tableOutput prints the output in a table format
func tableOutput(out []openlaneclient.GetAllTrustCenterCompliances_TrustCenterCompliances_Edges_Node) {
writer := tables.NewTableWriter(command.OutOrStdout(), "ID", "STANDARD", "TAGS", "CREATED", "UPDATED")
for _, i := range out {
writer.AddRow(i.ID, i.Standard.Name, strings.Join(i.Tags, ", "), *i.CreatedAt, *i.UpdatedAt)
}

writer.Render()
}

// deletedTableOutput prints the deleted id in a table format
func deletedTableOutput(e *openlaneclient.DeleteTrustCenterCompliance) {
writer := tables.NewTableWriter(command.OutOrStdout(), "DeletedID")

writer.AddRow(e.DeleteTrustCenterCompliance.DeletedID)

writer.Render()
}
1 change: 1 addition & 0 deletions cmd/cli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ import (
_ "github.com/theopenlane/core/cmd/cli/cmd/task"
_ "github.com/theopenlane/core/cmd/cli/cmd/template"
_ "github.com/theopenlane/core/cmd/cli/cmd/trustcenter"
_ "github.com/theopenlane/core/cmd/cli/cmd/trustcentercompliance"
_ "github.com/theopenlane/core/cmd/cli/cmd/trustcentersubprocessors"
_ "github.com/theopenlane/core/cmd/cli/cmd/user"
_ "github.com/theopenlane/core/cmd/cli/cmd/usersetting"
Expand Down
15 changes: 15 additions & 0 deletions db/migrations-goose-postgres/20250822040401_tcc.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
-- +goose Up
-- modify "trust_center_compliance_history" table
ALTER TABLE "trust_center_compliance_history" ADD COLUMN "standard_id" character varying NOT NULL, ADD COLUMN "trust_center_id" character varying NULL;
-- modify "trust_center_compliances" table
ALTER TABLE "trust_center_compliances" ADD COLUMN "standard_id" character varying NOT NULL, ADD COLUMN "trust_center_id" character varying NULL, ADD CONSTRAINT "trust_center_compliances_standards_trust_center_compliances" FOREIGN KEY ("standard_id") REFERENCES "standards" ("id") ON UPDATE NO ACTION ON DELETE NO ACTION, ADD CONSTRAINT "trust_center_compliances_trust_centers_trust_center_compliances" FOREIGN KEY ("trust_center_id") REFERENCES "trust_centers" ("id") ON UPDATE NO ACTION ON DELETE SET NULL;
-- create index "trustcentercompliance_standard_id_trust_center_id" to table: "trust_center_compliances"
CREATE UNIQUE INDEX "trustcentercompliance_standard_id_trust_center_id" ON "trust_center_compliances" ("standard_id", "trust_center_id") WHERE (deleted_at IS NULL);

-- +goose Down
-- reverse: create index "trustcentercompliance_standard_id_trust_center_id" to table: "trust_center_compliances"
DROP INDEX "trustcentercompliance_standard_id_trust_center_id";
-- reverse: modify "trust_center_compliances" table
ALTER TABLE "trust_center_compliances" DROP CONSTRAINT "trust_center_compliances_trust_centers_trust_center_compliances", DROP CONSTRAINT "trust_center_compliances_standards_trust_center_compliances", DROP COLUMN "trust_center_id", DROP COLUMN "standard_id";
-- reverse: modify "trust_center_compliance_history" table
ALTER TABLE "trust_center_compliance_history" DROP COLUMN "trust_center_id", DROP COLUMN "standard_id";
3 changes: 2 additions & 1 deletion db/migrations-goose-postgres/atlas.sum
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
h1:8OUTAT6kWh5Z6a4qwGuiseWnE+k6dQy4mkn2tscyPl8=
h1:5jN+xyZIVdYNS2S+SXXHctPXhTl11xIbvIn+fzDp0gQ=
20250414203515_init.sql h1:BeTEtWy9s9mO1t9vLhKE/W3Z/NZS7kklzlmvffjgMys=
20250418204251_control_objective.sql h1:2zhXUjbVshiTwzY0qh87de8Wh8j2tLDO6KRbn6oohx4=
20250421141007_aauid_not_unique_per_machine.sql h1:bMzfq+NBG4IFyOf/YintEKVhmQ6ttnQymzRV8/RiuPo=
Expand Down Expand Up @@ -45,3 +45,4 @@ h1:8OUTAT6kWh5Z6a4qwGuiseWnE+k6dQy4mkn2tscyPl8=
20250808163552_control_implementation_edges.sql h1:8YfsszeS31hWUxiErgURoyKc8/p40bLpeEyjrN0MYmc=
20250819212131_orgsettings_and_subscriptions.sql h1:qjd2SEObD9vLu+FuAx+oTNxcRedZQoPhfZRzZLMH4l0=
20250820212023_remove_product_tier.sql h1:XBx7ebP1TcTb7h7rCgbBwbtR2kQPrl9ZRs/ZJjViPhA=
20250822040401_tcc.sql h1:g38P80H1CkcVMPhmk48xSWrZ9C1UA4EHE1UYZqnlDos=
6 changes: 6 additions & 0 deletions db/migrations/20250822040357_tcc.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
-- Modify "trust_center_compliance_history" table
ALTER TABLE "trust_center_compliance_history" ADD COLUMN "standard_id" character varying NOT NULL, ADD COLUMN "trust_center_id" character varying NULL;
-- Modify "trust_center_compliances" table
ALTER TABLE "trust_center_compliances" ADD COLUMN "standard_id" character varying NOT NULL, ADD COLUMN "trust_center_id" character varying NULL, ADD CONSTRAINT "trust_center_compliances_standards_trust_center_compliances" FOREIGN KEY ("standard_id") REFERENCES "standards" ("id") ON UPDATE NO ACTION ON DELETE NO ACTION, ADD CONSTRAINT "trust_center_compliances_trust_centers_trust_center_compliances" FOREIGN KEY ("trust_center_id") REFERENCES "trust_centers" ("id") ON UPDATE NO ACTION ON DELETE SET NULL;
-- Create index "trustcentercompliance_standard_id_trust_center_id" to table: "trust_center_compliances"
CREATE UNIQUE INDEX "trustcentercompliance_standard_id_trust_center_id" ON "trust_center_compliances" ("standard_id", "trust_center_id") WHERE (deleted_at IS NULL);
3 changes: 2 additions & 1 deletion db/migrations/atlas.sum
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
h1:pCgPmd2ziiWwFGZgl60CISu+f8iRve8mSJpWVmTO4tY=
h1:B0ht6NrdfS2W1EuWRyGWbhB8DpCvWPv1mABYKvdwwt4=
20250414203514_init.sql h1:NmCV8ML7NQDnzWVgI8QwOPofl3cp1WGzZWzPQhilEbY=
20250418204249_control_objective.sql h1:NVX8qKq77/54YdYSQZMyI+HS5RXNahqyyDtNHf9oMnQ=
20250421141003_aauid_not_unique_per_machine.sql h1:/ZFOjmdeEiPZl23+/MIjK1sxFWSi8PrMvV3kJ4iqbW4=
Expand Down Expand Up @@ -45,3 +45,4 @@ h1:pCgPmd2ziiWwFGZgl60CISu+f8iRve8mSJpWVmTO4tY=
20250808163548_control_implementation_edges.sql h1:wCvMCI0eS9HwVgKevhg8yHG74PGTgQ7VfMra7MT7XXQ=
20250819212125_orgsettings_and_subscriptions.sql h1:KEhXsHTi/cKNUIezSXUhYb7Wr73xHEJK6U4iBBDxhoE=
20250820211949_remove_product_tier.sql h1:wQaB/V3qlWxZ3l90b9Gsx8Ac2W4QQ0sdxvRTPrNCS8M=
20250822040357_tcc.sql h1:rDXuxw42aFQz0I9vZFdhVhU3SKG8EF7L214z5Q7DUv8=
5 changes: 3 additions & 2 deletions fga/model/model.fga
Original file line number Diff line number Diff line change
Expand Up @@ -453,10 +453,11 @@ type standard
define audit_log_viewer: ([user, service] or audit_log_viewer from parent) and can_view
define parent_viewer: member from parent
define parent_editor: admin from parent or owner from parent
define viewer: [user, service] or editor
define viewer: [user, service] or editor or can_view from associated_with
define editor: [user, service]
# this is used for organization custom standards that are only available to the organization
define parent: [organization]
define associated_with: [trust_center]

type job_runner
relations
Expand Down Expand Up @@ -494,7 +495,7 @@ type scheduled_job

type trust_center
relations
define can_view: [user, service] or parent_viewer
define can_view: [user:*, service:*] or parent_viewer
define can_edit: [user, service] or parent_editor
define can_delete: [user, service] or parent_deleter
define parent_viewer: can_delete or can_edit or can_view from parent
Expand Down
Loading