Mach5 Role Patterns (Glob Syntax)

This document defines the glob-style authorization pattern language used by the Mach5 authorization system.

Mach5 uses a glob-like syntax to define permissions for namespaces, stores, indexes, pipelines, etc.

Each role is a pattern, not a literal string.

Examples:

namespace:*/index:*/read
store:*/create
namespace:default/connection:iceberg/update

These patterns are compiled to safe, anchored regular expressions and matched against required permission strings.

Special Characters

CharacterMeaningExampleMatches
*Wildcard segment (zero or more characters except / or :)namespace:*namespace:prod
?Single wildcard characterindex:?/readindex:a/read
\XLiteral X (escape)\*literal *
\\Literal backslash\\\

Important: Backslash does not become part of the output. It only means “treat the next character literally.”

Backslash Escaping Rules

InputInterpreted AsNotes
\*literal *not a wildcard
\?literal ?not a wildcard
\\literal backslashneeded if resource names contain \
any other charactertreated literallyauto-escaped for regex

EXACT behavior of escaped characters:

namespace:a\\c         matches "namespace:a\c"
namespace:a\*c         matches "namespace:a*c"
namespace:a\?c         matches "namespace:a?c"

If a user wants the actual backslash, they must double-escape it:

\  -->  \\

Examples (Good vs Bad Patterns)

Good

namespace:*/index:*/read
namespace:default/index:products/update
store:*/delete
namespace:a\\b/read     (literal backslash)
namespace:a\*b/read     (literal *)

Bad (invalid escapes)

namespace:default\   trailing backslash does nothing
namespace:\*foo\     incomplete escape

Security Notes

  • Role patterns cannot inject arbitrary regex (fully escaped).
  • Only * and ? have wildcard meaning.
  • All resource names are 100% safe, even if containing . + ( ) $ [ ] {} etc.

Overview - Authorization Pattern Specification

This specification applies to patterns used in roles such as:

namespace:*/connection:*/create  
store:*/delete  
storeroute:*/read  
namespace:*/entity:*/*  

It describes exactly how patterns behave, how wildcard characters work, and how escaping is handled.

A role pattern is a glob-like string that matches entire permission identifiers such as:

namespace:default/entity:customer/read
namespace:prod/connection:prod-s3/update

Patterns are converted to anchored regular expressions of the form:

^<converted-pattern>$

Meaning: the pattern must match the full permission string exactly.

Glob Syntax

The pattern language consists of:

SymbolMeaning
*wildcard segment (matches any string except / and :)
?wildcard matching exactly one character
\*literal *
\?literal ?
\\literal backslash
any other charactertreated literally (auto-escaped for regex)

1. * Wildcard Segment

* matches any non-empty string without crossing / or : boundaries.

Equivalent regex:

[^/:]*

Examples:

PatternMatchesDoes Not Match
namespace:*namespace:abcnamespace:abc/def
namespace:events_*/*namespace:events_log/readnamespace:system_log/read
namespace:events_user/updatenamespace:system_user/read
entity:*entity:customerentity:

2. ? Single Character Wildcard

? matches exactly one character.

Equivalent regex:

.

Examples:

PatternMatchesDoes Not Match
namespace:he?lonamespace:hello, namespace:hezlonamespace:helo
store:?store:astore:ab

3. Escaping Special Characters

The escape character is \.

Literal You WantPattern Syntax
*\*
?\?
\\\

All escaped characters are treated literally.

Examples:

PatternMatches
namespace:my\*filenamespace:my*file
entity:version\?2entity:version?2
path:folder\\namepath:folder\name

4. Literal Characters

All other characters including regex metacharacters are escaped using regex::escape(). This makes the system regex-safe.

Literal characters include:

. + ( ) [ ] { } ^ $ | /

Example:

Pattern:

namespace:file.(name)[test]{v}+ok

Matches:

namespace:file.(name)[test]{v}+ok

Only that exact string.

5. Anchoring

Every compiled regex is anchored:

^pattern$

Thus:

PatternMatchesDoes Not Match
namespace:*namespace:abcxnamespace:abcx
entity:*/*entity:abc/readentity:abc/read/extra

This prevents partial-match privilege escalation.

6. Trailing Backslash Rule

If a pattern ends with a single \, it is treated as a literal backslash.

Example:

Pattern --> Text
namespace:hello\ --> namespace:hello\

Examples

Permission Examples

namespace:default/entity:customer/create
namespace:default/entity:customer/read
namespace:test/entity:item42/update
store:mystore/delete

Pattern Examples

PatternMatchesReason
namespace:*/entity:*/*namespace:default/entity:customer/readlast * matches read
store:*/deletestore:mystore/deletetypical action pattern
storeroute:\?/*storeroute:?/createliteral ? using \?

Summary Table

TokenMeaning
*segment wildcard (zero or more chars, no / or :)
?single-char wildcard
\*literal *
\?literal ?
\\literal \
all othersliteral (regex-escaped)
anchoredfull-string match

Role Patterns: /admin Access

The /admin suffix allows a user to gain full recursive access to all resources. This complements your existing fine-grained roles:

  • Namespaced entities:
    • namespace:*/index:*, namespace:*/script:*, namespace:*/warehouse:*, etc.
  • Non-namespaced entities:
    • store:*, storeroute:*, etc.

The /admin suffix recursively covers all entities without needing to assign each role individually.

Syntax /admin suffix

namespace:<namespace-pattern>/admin
namespace:*/admin        // matches all namespaces
namespace:prod/admin     // matches only the "prod" namespace
  • Grants full access to all entities under the namespace, including:
    • Namespaced entities: index, script, warehouse, materializedview, notebook, connection, ingestpipeline, etc.
  • Must appear at the very end of the role string (unescaped).
  • Wildcards * ? are allowed in namespace names.

Example:

Role PatternEffective Access
namespace:*/adminAll entities (index, script, warehouse, etc.) in all namespaces
namespace:prod/adminAll entities in the prod namespace only
store:*/adminAll CRUD access on all stores

Important Rules

  1. /admin must appear unescaped at the end of the role string.
  2. Escaping the slash (\/admin) disables recursion and matches the literal string.
  3. Namespace-level /admin grants full access to all namespaced entities.
  4. Works alongside existing granular roles for selective access.
  5. Wildcards * may be used to match multiple namespaces.

Examples

Role PatternMatches Example EntitiesNotes
namespace:*/adminnamespace:prod/index:idx/readFull recursive access for all namespaced entities
namespace:prod/adminnamespace:prod/script:script1/updateFull access only in prod namespace
namespace:prod/connection:main/adminnamespace:prod/connection:main/readFull access for that namespace, and that connection entitity
namespace:*\/adminnamespace:prod/adminOnly literal match, recursion disabled. Avoid this pattern
adminAll entities across all namespacesSuper-admin full access for everything

Summary

  • Use /admin for full recursive access to entities.
  • Namespace-level /admin = full access across the namespace.
  • Wildcards * may be used to cover multiple namespaces.
  • Escaping the slash disables recursion. Avoid such pattern
  • Works alongside existing fine-grained roles to allow selective access.

Real-World Role Examples (Namespaces, Entities, and Actions)

This section provides concrete, real-world example values that match each of the authorization patterns currently stored in Keycloak or can be added as needed. Examples are grouped by domain (namespace, store, storeroute, license, index, etc.).

Each example demonstrates:

  • realistic namespace names
  • realistic entity names
  • CRUD operations
  • multi-segment resource paths
  • how wildcards expand in practice

All examples assume the standard Mach5 permission format:

entity:<name>/<action>
namespace:<name>/entity:<name>/<action>

1. Admin

Role: admin

Matches everything (^.*$).

Examples (all allowed):

namespace:default/index:products/read
store:mystore/delete
license/metered/data/read
namespace:analytics/notebook:model-trainer/update

Role: /admin suffix

Full recursive access within the entity or namespace.

Examples:

namespace:default/admin        --> all entities in default namespace
store:*/admin                  --> full CRUD on store
namespace:analytics/*:*/admin  --> all entities in analytics namespace
namespace:*/index:*/admin      --> all indexes in all namespaces

2. Namespace-level Roles

These roles apply to operations on a namespace itself.

namespace:*/create

Examples matching:

namespace:default/create
namespace:prod/create
namespace:analytics/create
namespace:test-env/create

namespace:*/read

Examples:

namespace:default/read
namespace:prod/read
namespace:research/read

namespace:*/delete

Examples:

namespace:legacy/delete
namespace:unused/delete

3. Store Roles

These roles do not involve namespaces.

store:*/create

Examples:

store:mystore/create
store:customer-cache/create

store:*/read

store:mystore/read
store:transactions/read

store:*/delete

store:temp-store/delete
store:data-lake/delete

4. Store Route Roles

These roles do not involve namespaces.

storeroute:*/create

storeroute:route-a/create
storeroute:bulk-ingest/create

storeroute:*/read

storeroute:route-a/read
storeroute:nightly-sync/read

storeroute:*/delete

storeroute:route-a/delete
storeroute:backup/delete

5. License Roles

These roles do not involve namespaces.

license/*/data/read
license/status/data/read
license/metered/data/read

6. Connections (namespace-scoped)

Pattern format:

namespace:<ns>/connection:<conn>/<action>

namespace:*/connection:*/create

namespace:default/connection:snowflake/create
namespace:prod/connection:kafka/create

namespace:*/connection:*/read

namespace:default/connection:iceberg/read
namespace:research/connection:bigquery/read

namespace:*/connection:*/update

namespace:dataeng/connection:gcs/update

namespace:*/connection:*/delete

namespace:test/connection:s3/delete

namespace:*/connection:*/test/read

Test connection

This role is to allow testing the connection parameters when creating or editing a connection.

namespace:dev/connection:local-s3/test/read

7. Ingest Pipelines

Pattern format:

namespace:<ns>/ingestpipeline:<name>/<action>

Examples:

namespace:default/ingestpipeline:order-events/create
namespace:default/ingestpipeline:order-events/read
namespace:analytics/ingestpipeline:etl-job/update
namespace:prod/ingestpipeline:bulk-loader/delete

8. Materialized Views

Pattern format:

namespace:<ns>/materializedview:<name>/<action>
namespace:default/materializedview:sales-daily/create
namespace:default/materializedview:sales-daily/read
namespace:prod/materializedview:customer-agg/update
namespace:test/materializedview:temp/delete

9. Notebooks

Pattern format:

namespace:<ns>/notebook:<name>/<action>
namespace:default/notebook:model-trainer/create
namespace:ml/notebook:experiment-12/read
namespace:ml/notebook:experiment-12/update
namespace:ml/notebook:obsolete/delete

10. Scripts

Pattern format:

namespace:<ns>/script:<name>/<action>
namespace:default/script:migration/create
namespace:default/script:migration/read
namespace:dataflow/script:cleanup/update
namespace:dataflow/script:cleanup/delete

11. Warehouses

Pattern format:

namespace:<ns>/warehouse:<name>/<action>
namespace:prod/warehouse:s3/create
namespace:prod/warehouse:s3/read
namespace:prod/warehouse:s3/update
namespace:prod/warehouse:s3/delete

12. Index Aliases

Pattern format:

namespace:<ns>/indexalias:<name>/<action>
namespace:default/indexalias:customers/create
namespace:default/indexalias:customers/read
namespace:default/indexalias:customers/update
namespace:default/indexalias:customers/delete

13. Indexes

Pattern Format:

namespace:<ns>/index:<name>/<action>

CRUD on index itself

namespace:default/index:products/create
namespace:default/index:products/read
namespace:default/index:products/update
namespace:default/index:products/delete

Full access on all indexes in default namespace:

namespace:default/index:*/admin

Roles Coverage Guide

Role PatternCoverage / DescriptionNotes
adminFull access to all resources (namespaced & non-namespaced)Super-admin role
namespace:<N>/adminFull recursive access to all entities in namespace <N>Namespace-scoped admin
Including index, script, warehouse, notebook, materialized view, connection, pipeline, etc.
namespace:*/adminSame as above but applies to all namespacesGlobal namespace admin
namespace:<N>/connection:<C>/adminFull access to connection <C> in namespace <N>Connection-scoped admin
Non-namespaced roles (e.g., store:*/admin)Grants access only to specified resource typesNon-namespaced resource admin
namespace:<N>/... (normal roles without /admin)Scoped access only to the specific resource/action definedLeast-privilege access
Escaped admin suffix (e.g., namespace:*\/admin)Literal match only; no recursive admin accessAvoid unless literal suffix is intended

Usage Recommendations

  1. Super admin: Use admin for super-admin users needing access to everything in all namespaces and non-namespaces.

  2. Namespace-level /admin: Use namespace:<namespace>/admin to grant full access within a single namespace, ideal for team leads or environment owners.

  3. Entity-level /admin: Use namespace:<namespace>/connection:<connection>/admin to give full access to a particular namespace entity.

  4. Granular roles: Use specific roles (e.g., namespace:<ns>/index:*/read, store:*/delete) when least-privilege access is desired using the actions create, read, update and delete. Use namespace:analytics/*:*/read to grant read only access for the namespace analytics, ideal for viewer only user like business analyst.

  5. Avoid escaped /admin (\/admin):