Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
8f0829a
feat: Add the object/parent/creator relation knobs needed by the init…
kekcleader Oct 10, 2025
f7353b4
feat: Workspace initializer now pulls account + accountinfo data, wai…
kekcleader Oct 10, 2025
19b6d16
feat: Workspace initializer test exercises org/account success paths …
kekcleader Oct 10, 2025
ebcd29f
Merge remote-tracking branch 'origin/main' into feat/move-fga-subrout…
kekcleader Oct 13, 2025
455c8aa
fix: logic reimplementation
kekcleader Oct 15, 2025
8dd0b4b
Merge branch 'main' into feat/move-fga-subroutine-from-account-operator
kekcleader Oct 15, 2025
a2102a8
fix: initializerCfg instead of appCfg
kekcleader Oct 15, 2025
7a94d01
fix: gRPC client creation: use DialContext
kekcleader Oct 15, 2025
1697335
fix: switched the FGA tuple writes to use the ctxWithTimeout
kekcleader Oct 15, 2025
f9b8138
fix: updated validateCreator in workspace_initializer.go to block bot…
kekcleader Oct 15, 2025
19346fd
fix: abort dialContext, use NewClient instead
kekcleader Oct 15, 2025
1616699
fix: Use TLS (and auth) for OpenFGA; avoid insecure transport
kekcleader Oct 15, 2025
f323426
fix: added a fail-fast validation to reject the incompatible config
kekcleader Oct 15, 2025
674e8bf
fix: cleaned up the initializer
kekcleader Oct 16, 2025
6689413
fix: cleared the config
kekcleader Oct 16, 2025
31b9770
fix: removed annotations
kekcleader Oct 16, 2025
3f7ce21
feat: FGA logic is in a separate subroutine
kekcleader Oct 16, 2025
344775c
feat: tests for workspace_fga and some others
kekcleader Oct 16, 2025
bd6958f
fix: Replaced deprecated Requeue with RequeueAfter; Creator tuple wr…
kekcleader Oct 16, 2025
d044b76
fix: gPRC init, KCP API calls, Creator tulpe improvements
kekcleader Oct 16, 2025
25e8d84
feat: removed local replace directive and use pseudo-version of accou…
kekcleader Oct 17, 2025
a0ae414
Merge branch 'main' into feat/move-fga-subroutine-from-account-operator
kekcleader Oct 17, 2025
65edbc4
feat: new fga tests
kekcleader Oct 17, 2025
76b5344
Merge branch 'feat/move-fga-subroutine-from-account-operator' of gith…
kekcleader Oct 17, 2025
acf8f0d
fix: removed unused orgsClient field from workspaceFGASubroutine
kekcleader Oct 17, 2025
3bf3e05
Merge branch 'main' into feat/move-fga-subroutine-from-account-operator
kekcleader Oct 20, 2025
27f38db
chore: removed commented lines
kekcleader Oct 20, 2025
6831c92
Merge branch 'main' into feat/move-fga-subroutine-from-account-operator
kekcleader Oct 20, 2025
38c7508
fix: Validate that owner cluster is specified
kekcleader Oct 20, 2025
d6254ea
Merge branch 'feat/move-fga-subroutine-from-account-operator' of gith…
kekcleader Oct 20, 2025
b8b1b91
feat: move FGA initialization to security-operator initializer
kekcleader Oct 21, 2025
bb1b94a
fix: Added store populated by accountinfo; write creator fga tuples; …
kekcleader Oct 22, 2025
8c0d9e4
fix: fixed tests
kekcleader Oct 23, 2025
c7507f4
fix: Protect against nil w.fga to avoid a crash if wiring is misconfi…
kekcleader Oct 23, 2025
afe0e76
fix: Changed the error handling of workspaceClient.Get to distinguish…
kekcleader Oct 23, 2025
728f0ca
fix: removed specific contexts with timeout
kekcleader Oct 23, 2025
f88b94b
fix: removed leftovers
kekcleader Oct 23, 2025
e8230cb
Enabled FGA authorization for non-org accounts; some other changes
kekcleader Oct 23, 2025
f394f31
Merge branch 'main' into feat/move-fga-subroutine-from-account-operator
kekcleader Oct 23, 2025
c849a54
fix: Removed duplicate relation definitions
kekcleader Oct 23, 2025
ef99bc1
fix: Cleaned up the code from debug messages and unused lines
kekcleader Oct 23, 2025
3eaeeb3
Merge branch 'main' into feat/move-fga-subroutine-from-account-operator
kekcleader Oct 24, 2025
67c2364
fix: updated test data
kekcleader Oct 24, 2025
7779cce
fix: authorization_model.go uses the same simplified inheritance logi…
kekcleader Oct 24, 2025
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
20 changes: 19 additions & 1 deletion cmd/initializer.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@ import (

helmv2 "github.com/fluxcd/helm-controller/api/v2"
sourcev1 "github.com/fluxcd/source-controller/api/v1"
openfgav1 "github.com/openfga/api/proto/openfga/v1"

"github.com/kcp-dev/logicalcluster/v3"
"github.com/kcp-dev/multicluster-provider/initializingworkspaces"
pmcontext "github.com/platform-mesh/golang-commons/context"
"github.com/spf13/cobra"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/client-go/rest"
Expand Down Expand Up @@ -98,7 +101,22 @@ var initializerCmd = &cobra.Command{
initializerCfg.IDP.AdditionalRedirectURLs = []string{}
}

if err := controller.NewLogicalClusterReconciler(log, orgClient, initializerCfg, inClusterClient, mgr).
if initializerCfg.FGA.Target == "" {
log.Error().Msg("FGA target is empty; set fga-target in configuration")
os.Exit(1)
}

// gRPC client initialization: mTLS is handled by the service mesh (Istio)
conn, err := grpc.NewClient(initializerCfg.FGA.Target, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
log.Error().Err(err).Msg("unable to create OpenFGA gRPC client")
os.Exit(1)
}
defer func() { _ = conn.Close() }()

fga := openfgav1.NewOpenFGAServiceClient(conn)

if err := controller.NewLogicalClusterReconciler(log, orgClient, initializerCfg, inClusterClient, mgr, fga).
SetupWithManager(mgr, defaultCfg); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "LogicalCluster")
os.Exit(1)
Expand Down
88 changes: 77 additions & 11 deletions data/coreModule.fga
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,90 @@ type role
relations
define assignee: [user,user:*]

type account
type core_platform-mesh_io_account
relations
define parent: [core_platform-mesh_io_account]

define parent: [account]
define owner: [role#assignee]
define member: [role#assignee] or owner
define owner: [role#assignee] or owner from parent
define member: [role#assignee] or owner or member from parent

define get: member or get from parent
define update: member or update from parent
define delete: owner or delete from parent
define get: member
define update: member
define patch: member
define delete: owner

define create_core_platform-mesh_io_accounts: member
define list_core_platform-mesh_io_accounts: member
define watch_core_platform-mesh_io_accounts: member

# org and account specific
define watch: member or watch from parent
define watch: member

# org specific
define create: member or create from parent
define list: member or list from parent
define create_core_namespaces: member
define list_core_namespaces: member
define watch_core_namespaces: member

define create_core_platform-mesh_io_accountinfos: member
define list_core_platform-mesh_io_accountinfos: member
define watch_core_platform-mesh_io_accountinfos: member

define create_apis_kcp_io_apibindings: owner
define list_apis_kcp_io_apibindings: member
define watch_apis_kcp_io_apibindings: member

# IAM specific
define manage_iam_roles: owner
define get_iam_roles: member
define get_iam_users: member

type core_namespace
relations
define parent: [core_platform-mesh_io_account]

define member: member from parent
define owner: owner from parent

define get: member
define watch: member

define update: member
define patch: member
define delete: member

# IAM specific
define manage_iam_roles: owner
define get_iam_roles: member
define get_iam_users: member

type core_platform-mesh_io_accountinfo
relations
define parent: [core_platform-mesh_io_account]

define member: member from parent
define owner: owner from parent

define get: member
define watch: member

# IAM specific
define manage_iam_roles: owner
define get_iam_roles: member
define get_iam_users: member

type apis_kcp_io_apibinding
relations
define parent: [core_platform-mesh_io_account]

define member: member from parent
define owner: owner from parent

define get: member
define watch: member
define update: owner
define patch: owner
define delete: owner

# IAM specific
define manage_iam_roles: owner
define get_iam_roles: member
define get_iam_users: member
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ require (
github.com/kcp-dev/multicluster-provider v0.2.0
github.com/openfga/api/proto v0.0.0-20250909173124-0ac19aac54f2
github.com/openfga/language/pkg/go v0.2.0-beta.2.0.20251003203216-7c0d09a1cc5a
github.com/platform-mesh/account-operator v0.5.9
github.com/platform-mesh/account-operator v0.5.5-0.20251017120838-b8c73d0b347e
github.com/platform-mesh/golang-commons v0.7.4
github.com/rs/zerolog v1.34.0
github.com/spf13/cobra v1.10.1
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,8 @@ github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4
github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/platform-mesh/account-operator v0.5.9 h1:7Taz/4ZeOaHcQbdW5LPNFXv8PVCg0KyEmxGbe0oiQPg=
github.com/platform-mesh/account-operator v0.5.9/go.mod h1:3wJaOforqD5TBUDRzhMA8EmWCIDpktR80r210g5hLnQ=
github.com/platform-mesh/account-operator v0.5.5-0.20251017120838-b8c73d0b347e h1:eG3p5jn92yKjXBfkU4E+t/qvfeqZNnYvjwlX3aFknyc=
github.com/platform-mesh/account-operator v0.5.5-0.20251017120838-b8c73d0b347e/go.mod h1:Kg2hxWCRggF86d9zrjhHGvEo42B+sfL+Go2PVBs9uvo=
github.com/platform-mesh/golang-commons v0.7.4 h1:ZIY9ExAZ+BbH1xcn96zw2wR8rlsDST7Soow8yaHG2Mc=
github.com/platform-mesh/golang-commons v0.7.4/go.mod h1:GJe0jJcS9hfT7ajo7sbOe5p2Uw0GuVLeQhZEffKM9os=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
Expand Down
5 changes: 4 additions & 1 deletion internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ type InviteConfig struct {
// Config struct to hold the app config
type Config struct {
FGA struct {
Target string `mapstructure:"fga-target"`
Target string `mapstructure:"fga-target"`
ObjectType string `mapstructure:"fga-object-type" default:"core_platform-mesh_io_account"`
ParentRelation string `mapstructure:"fga-parent-relation" default:"parent"`
CreatorRelation string `mapstructure:"fga-creator-relation" default:"owner"`
} `mapstructure:",squash"`
APIExportEndpointSliceName string `mapstructure:"api-export-endpoint-slice-name"`
CoreModulePath string `mapstructure:"core-module-path"`
Expand Down
4 changes: 3 additions & 1 deletion internal/controller/initializer_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"

kcpcorev1alpha1 "github.com/kcp-dev/kcp/sdk/apis/core/v1alpha1"
openfgav1 "github.com/openfga/api/proto/openfga/v1"
platformeshconfig "github.com/platform-mesh/golang-commons/config"
"github.com/platform-mesh/golang-commons/controller/lifecycle/builder"
lifecyclecontrollerruntime "github.com/platform-mesh/golang-commons/controller/lifecycle/multicluster"
Expand All @@ -26,11 +27,12 @@ type LogicalClusterReconciler struct {
lifecycle *lifecyclecontrollerruntime.LifecycleManager
}

func NewLogicalClusterReconciler(log *logger.Logger, orgClient client.Client, cfg config.Config, inClusterClient client.Client, mgr mcmanager.Manager) *LogicalClusterReconciler {
func NewLogicalClusterReconciler(log *logger.Logger, orgClient client.Client, cfg config.Config, inClusterClient client.Client, mgr mcmanager.Manager, fga openfgav1.OpenFGAServiceClient) *LogicalClusterReconciler {
return &LogicalClusterReconciler{
log: log,
lifecycle: builder.NewBuilder("logicalcluster", "LogicalClusterReconciler", []lifecyclesubroutine.Subroutine{
subroutine.NewWorkspaceInitializer(orgClient, cfg, mgr),
subroutine.NewWorkspaceFGASubroutine(mgr, fga, cfg.FGA.ObjectType, cfg.FGA.ParentRelation, cfg.FGA.CreatorRelation),
subroutine.NewWorkspaceAuthConfigurationSubroutine(orgClient, inClusterClient, cfg),
subroutine.NewRealmSubroutine(inClusterClient, &cfg, cfg.BaseDomain),
subroutine.NewInviteSubroutine(orgClient, mgr),
Expand Down
15 changes: 12 additions & 3 deletions internal/subroutine/authorization_model.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const (

var (
privilegedGroupVersions = []string{"rbac.authorization.k8s.io/v1"}
groupVersions = []string{"authentication.k8s.io/v1", "authorization.k8s.io/v1", "v1"}
groupVersions = []string{"authentication.k8s.io/v1", "authorization.k8s.io/v1", "v1"}

privilegedTemplate = template.Must(template.New("model").Parse(`module internal_core_types_{{ .Name }}

Expand All @@ -56,13 +56,15 @@ extend type core_namespace
type {{ .Group }}_{{ .Singular }}
relations
define parent: [{{ if eq .Scope "Namespaced" }}core_namespace{{ else }}core_platform-mesh_io_account{{ end }}]
define member: [role#assignee] or owner or member from parent
define owner: [role#assignee] or owner from parent
define member: member from parent
define owner: owner from parent

define get: member
define update: owner
define delete: owner
define patch: owner
define statusPatch: member
define statusUpdate: member
define watch: member

define manage_iam_roles: owner
Expand Down Expand Up @@ -216,6 +218,13 @@ func (a *authorizationModelSubroutine) Process(ctx context.Context, instance run

}

// DEBUG: Log the model being written
modelJSON, _ := protojson.Marshal(authorizationModel)
modelDSL, err := language.TransformJSONStringToDSL(string(modelJSON))
if err == nil && modelDSL != nil {
log.Info().Str("store", store.Name).Str("model", *modelDSL).Msg("Writing authorization model")
}

res, err := a.fga.WriteAuthorizationModel(ctx, &openfgav1.WriteAuthorizationModelRequest{
StoreId: store.Status.StoreID,
TypeDefinitions: authorizationModel.TypeDefinitions,
Expand Down
10 changes: 6 additions & 4 deletions internal/subroutine/authorization_model_generation.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,12 @@ extend type core_namespace
type {{ .Group }}_{{ .Singular }}
relations
define parent: [{{ if eq .Scope "Namespaced" }}core_namespace{{ else }}core_platform-mesh_io_account{{ end }}]
define member: [role#assignee] or owner or member from parent
define owner: [role#assignee] or owner from parent

define member: member from parent
define owner: owner from parent

define statusUpdate: member
define statusPatch: member

define get: member
define update: member
define delete: member
Expand All @@ -70,7 +73,6 @@ type {{ .Group }}_{{ .Singular }}
define manage_iam_roles: owner
define get_iam_roles: member
define get_iam_users: member

`))

type modelInput struct {
Expand Down
14 changes: 9 additions & 5 deletions internal/subroutine/authorization_model_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,12 @@ type core_namespace
define get_iam_roles: member
define get_iam_users: member
define manage_iam_roles: owner
define member: [role#assignee] or owner or member from parent
define owner: [role#assignee] or owner from parent
define member: member from parent
define owner: owner from parent
define parent: [core_platform-mesh_io_account]
define patch: member
define statusPatch: member
define statusUpdate: member
define update: member
define watch: member
`
Expand Down Expand Up @@ -220,7 +222,7 @@ func TestAuthorizationModelProcess(t *testing.T) {
Contents: extensionModel,
},
{
Name: "internal_core_types_namespaces.fga",
Name: "internal_core_types_namespaces.fga",
Contents: `module namespaces

extend type core_platform-mesh_io_account
Expand All @@ -232,13 +234,15 @@ extend type core_platform-mesh_io_account
type core_namespace
relations
define parent: [core_platform-mesh_io_account]
define member: [role#assignee] or owner or member from parent
define owner: [role#assignee] or owner from parent
define member: member from parent
define owner: owner from parent

define get: member
define update: member
define delete: member
define patch: member
define statusPatch: member
define statusUpdate: member
define watch: member

define manage_iam_roles: owner
Expand Down
Loading