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
21 changes: 1 addition & 20 deletions cmd/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,22 +134,6 @@ func StartServer(logger *slog.Logger, cfg *config.Frontier) error {
}
}()

// load resource config
if cfg.App.ResourcesConfigPath != "" {
logger.Warn("app.resources_config_path is deprecated and will be removed after a deprecation window; " +
"manage permissions and roles with 'frontier reconcile' instead")
}
resourceBlobFS, err := blob.NewStore(ctx, cfg.App.ResourcesConfigPath, cfg.App.ResourcesConfigPathSecret)
if err != nil {
return err
}
defer func() {
logger.Debug("cleaning up resource blob")
if err := resourceBlobFS.Close(); err != nil {
logger.Warn("resource blob cleanup failed", "err", err)
}
}()

// load billing plans
Comment thread
rohilsurana marked this conversation as resolved.
billingBlobFS, err := blob.NewStore(ctx, cfg.Billing.PlansPath, "")
if err != nil {
Expand Down Expand Up @@ -182,7 +166,7 @@ func StartServer(logger *slog.Logger, cfg *config.Frontier) error {
return err
}

deps, err := buildAPIDependencies(logger, cfg, dbClient, spiceDBClient, resourceBlobFS, billingPlanRepository)
deps, err := buildAPIDependencies(logger, cfg, dbClient, spiceDBClient, billingPlanRepository)
if err != nil {
return err
}
Expand Down Expand Up @@ -361,7 +345,6 @@ func buildAPIDependencies(
cfg *config.Frontier,
dbc *db.Client,
sdb *spicedb.SpiceDB,
resourceBlobBucket blob.Bucket,
planBlobRepository *blob.PlanRepository,
) (api.Deps, error) {
// Load additional traits from config file if specified
Expand Down Expand Up @@ -596,11 +579,9 @@ func buildAPIDependencies(

usageService := usage.NewService(creditService)

resourceSchemaRepository := blob.NewSchemaConfigRepository(resourceBlobBucket)
bootstrapService := bootstrap.NewBootstrapService(
logger,
cfg.App.Admin,
resourceSchemaRepository,
namespaceService,
roleService,
permissionService,
Expand Down
14 changes: 0 additions & 14 deletions config/sample.config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -63,20 +63,6 @@ app:
host: "127.0.0.1"
# WARNING: identity_proxy_header bypass all authorization checks and shouldn't be used in production
identity_proxy_header: X-Frontier-Email
# DEPRECATED: will be removed after a deprecation window. Manage permissions
# and roles with 'frontier reconcile' instead (see docs/rfcs/0001-declarative-reconcile.md).
# full path prefixed with scheme where resources config yaml files are kept
# e.g.:
# local storage file "file:///tmp/resources_config"
# GCS Bucket "gs://frontier/resources_config"
resources_config_path: file:///tmp/resources_config\
# secret required to access resources config
# e.g.:
# system environment variable "env://TEST_RULESET_SECRET"
# local file "file:///opt/auth.json"
# secret string "val://user:password"
# optional
resources_config_path_secret: env://TEST_RESOURCE_CONFIG_SECRET

# cross-origin resource sharing configuration
cors:
Expand Down
8 changes: 8 additions & 0 deletions docs/content/docs/authz/custom-resources.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ order: 7

# Custom Resources and Permissions

> **Note:** The boot-time `resources_config_path` loader described below has been
> removed. Frontier no longer reads a resource config file at startup. Create and
> update custom permissions and roles through the admin API (`CreatePermission`,
> `CreateRole`) or the `frontier reconcile` flow instead. See
> [the declarative reconcile RFC](https://github.com/raystack/frontier/blob/main/docs/rfcs/0001-declarative-reconcile.md).
> The mechanics below still explain the schema that bootstrap applies from the
> base schema plus the permissions already in the database.

Frontier lets services register their own resource types (for example `compute/machine`).
Once registered, Frontier can answer permission checks on those resources the same way it
does for built-in types like projects and organizations.
Expand Down
12 changes: 0 additions & 12 deletions docs/content/docs/configurations.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,6 @@ app:
metrics_port: 9000
# WARNING: identity_proxy_header bypass all authorization checks and shouldn't be used in production
identity_proxy_header: X-Frontier-Email
# full path prefixed with scheme where resources config yaml files are kept
# e.g.:
# local storage file "file:///tmp/resources_config"
# GCS Bucket "gs://frontier/resources_config"
resources_config_path: file:///tmp/resources_config\
# secret required to access resources config
# e.g.:
# system environment variable "env://TEST_RULESET_SECRET"
# local file "file:///opt/auth.json"
# secret string "val://user:password"
# optional
resources_config_path_secret: env://TEST_RESOURCE_CONFIG_SECRET

# cross-origin resource sharing configuration
cors:
Expand Down
14 changes: 0 additions & 14 deletions docs/content/docs/reference/configurations.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,6 @@ app:
profiler: false
# WARNING: identity_proxy_header bypass all authorization checks and shouldn't be used in production
identity_proxy_header: X-Frontier-Email
# full path prefixed with scheme where resources config yaml files are kept
# e.g.:
# local storage file "file:///tmp/resources_config"
# GCS Bucket "gs://frontier/resources_config"
resources_config_path: file:///tmp/resources_config\
# secret required to access resources config
# e.g.:
# system environment variable "env://TEST_RULESET_SECRET"
# local file "file:///opt/auth.json"
# secret string "val://user:password"
# optional
resources_config_path_secret: env://TEST_RESOURCE_CONFIG_SECRET

# cross-origin resource sharing configuration
cors:
Expand Down Expand Up @@ -255,8 +243,6 @@ This page contains reference for all the application configurations for Frontier
| **app.metrics_port** | Port number for metrics reporting. | 9000 | Yes |
| **app.host** | Host address for the Frontier application. | 127.0.0.1 | Yes |
| **app.identity_proxy_header** | Header key used for identity proxy. | | |
| **app.resources_config_path** | Full path prefixed with the scheme where resources config YAML files are stored.<br/>Either new resources can be added dynamically via the apis, or can be passed in this YAML file | | No |
| **app.resources_config_path_secret** | Secret required to access resources config. | | No |
| **app.disable_orgs_listing** | If set to true, disallows non-admin APIs to list all organizations. | | No |
| **app.disable_users_listing** | If set to true, disallows non-admin APIs to list all users. | | No |
| **app.cors_origin** | Origin value from where CORS is allowed. | | Yes(for Admin UI) |
Expand Down
4 changes: 2 additions & 2 deletions internal/api/v1beta1connect/permission.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ func (h *ConnectHandler) UpdatePermission(ctx context.Context, request *connect.
}

// DeletePermission deletes a permission and the tuples that reference it.
// Built-in permissions (defined by the base schema or config) are rejected,
// Built-in permissions (defined by the base schema) are rejected,
// because bootstrap recreates them on the next boot. So only permissions added
// through the API can be deleted.
func (h *ConnectHandler) DeletePermission(ctx context.Context, request *connect.Request[frontierv1beta1.DeletePermissionRequest]) (*connect.Response[frontierv1beta1.DeletePermissionResponse], error) {
Expand Down Expand Up @@ -179,7 +179,7 @@ func (h *ConnectHandler) DeletePermission(ctx context.Context, request *connect.
}
if _, isBuiltin := builtin[slug]; isBuiltin {
return nil, connect.NewError(connect.CodeFailedPrecondition,
errors.New("cannot delete a built-in permission (defined by the base schema or service config); it is recreated on the next boot"))
errors.New("cannot delete a built-in permission (defined by the base schema); it is recreated on the next boot"))
}

// A namespace exists in SpiceDB only as long as it has a permission. If this
Expand Down
44 changes: 11 additions & 33 deletions internal/bootstrap/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,6 @@ type RelationService interface {
Delete(ctx context.Context, rel relation.Relation) error
}

type FileService interface {
GetDefinition(ctx context.Context) (*schema.ServiceDefinition, error)
}

type AuthzEngine interface {
WriteSchema(ctx context.Context, schema string) error
}
Expand Down Expand Up @@ -87,7 +83,6 @@ type AdminConfig struct {
type Service struct {
logger *slog.Logger
adminConfig AdminConfig
schemaConfig FileService
namespaceService NamespaceService
roleService RoleService
permissionService PermissionService
Expand All @@ -108,7 +103,6 @@ type Service struct {
func NewBootstrapService(
logger *slog.Logger,
config AdminConfig,
schemaConfig FileService,
namespaceService NamespaceService,
roleService RoleService,
actionService PermissionService,
Expand All @@ -126,7 +120,6 @@ func NewBootstrapService(
return &Service{
logger: logger,
adminConfig: config,
schemaConfig: schemaConfig,
namespaceService: namespaceService,
roleService: roleService,
permissionService: actionService,
Expand All @@ -144,25 +137,18 @@ func NewBootstrapService(
}

func (s Service) MigrateSchema(ctx context.Context) error {
customServiceDefinition, err := s.schemaConfig.GetDefinition(ctx)
if err != nil {
return err
}

return s.AppendSchema(ctx, *customServiceDefinition)
// Custom permissions are managed through the reconcile flow now. Boot only
// re-applies the base schema merged with the permissions already in the
// database (AppendSchema keeps existing ones), so no config file is read.
return s.AppendSchema(ctx, schema.ServiceDefinition{})
}

// BuiltinPermissions returns the permissions that come from the base schema and
// the config files — the ones bootstrap recreates on every boot. It looks only
// at the base schema and config, not at the permissions already in the database.
// BuiltinPermissions returns the permissions that come from the base schema —
// the ones bootstrap recreates on every boot and that cannot be deleted through
// the API. It looks only at the base schema, not at the permissions already in
// the database.
func (s Service) BuiltinPermissions(ctx context.Context) (map[string]struct{}, error) {
custom, err := s.schemaConfig.GetDefinition(ctx)
if err != nil {
return nil, err
}
custom.Permissions = filterDefaultAppNamespacePermissions(custom.Permissions)

defs, err := ApplyServiceDefinitionOverAZSchema(custom, GetBaseAZSchema())
defs, err := ApplyServiceDefinitionOverAZSchema(&schema.ServiceDefinition{}, GetBaseAZSchema())
Comment thread
rohilsurana marked this conversation as resolved.
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -269,16 +255,8 @@ func (s Service) MigrateRoles(ctx context.Context) error {
}
Comment thread
rohilsurana marked this conversation as resolved.
}

// migrate user defined roles to org
serviceDefinition, err := s.schemaConfig.GetDefinition(ctx)
if err != nil {
return err
}
for _, defRole := range serviceDefinition.Roles {
if err = s.migrateRole(ctx, defaultOrgID, defRole); err != nil {
return err
}
}
// Custom roles are managed through the reconcile flow now; boot no longer
// creates them from a config file.

// backfill PAT wildcard tuples for all existing roles
if err = s.migratePATRelations(ctx); err != nil {
Expand Down
58 changes: 0 additions & 58 deletions internal/store/blob/schema_repository.go

This file was deleted.

Loading
Loading