feat(nano): configure hasJoined auth sources via [[auth_source]], Mojang-anchored
Step 2 of Felis-nano: a [[auth_source]] array-of-tables (tag + full hasJoined url, config order = priority) supplies the multiplexer's third-party Yggdrasil roots; cmd/felis prepends Mojang as the sole code-owned identity anchor and wires them into API.AuthSources. With no sources configured the endpoint stays inert (204s), unchanged from step 1. The config deliberately has no identity/trusted field: Mojang is the only source whose self-asserted UUIDs are trusted verbatim, so no misconfiguration can reopen the impersonation hole the per-source UUID rewrite closes. An identity= key is an unknown key and Load rejects it. Validate adds two fail-fast guards: unique tags (namespace collision) and a scheme-qualified url (else the source is silently dead, never validating any login).
This commit is contained in:
3 files changed
+153
No files matched your search
@@ -20,6 +20,26 @@ type Config struct {
|
||||
K8s K8sConfig `toml:"k8s"`
|
||||
Registry RegistryConfig `toml:"registry"`
|
||||
Archive ArchiveConfig `toml:"archive"`
|
||||
// AuthSources is the [[auth_source]] array-of-tables: the third-party Yggdrasil
|
||||
// roots the Felis-nano hasJoined multiplexer federates over, in priority order
|
||||
// (config order = priority, so array-of-tables not a map — a map would lose order
|
||||
// and silently break Mojang-first). Empty = the multiplexer ships off. There is
|
||||
// deliberately NO identity/trusted field here: Mojang is the single code-owned
|
||||
// identity anchor (cmd/felis prepends it) and every configured source is
|
||||
// namespace-rewritten, so no config can mint a source whose self-asserted UUIDs are
|
||||
// trusted verbatim — the impersonation hole that rewrite closes cannot be reopened by
|
||||
// misconfiguration. (An `identity =` key here is an unknown key → Load rejects it.)
|
||||
AuthSources []AuthSourceConfig `toml:"auth_source"`
|
||||
}
|
||||
|
||||
// AuthSourceConfig is one [[auth_source]] entry: a third-party Yggdrasil root the
|
||||
// Felis-nano multiplexer federates over. Tag names the source's per-source UUID
|
||||
// namespace (must be unique — two sources sharing a tag would collide onto one identity);
|
||||
// URL is the full hasJoined endpoint (scheme-qualified) the query string is appended to.
|
||||
// No trusted/identity field, by design — see Config.AuthSources.
|
||||
type AuthSourceConfig struct {
|
||||
Tag string `toml:"tag"`
|
||||
URL string `toml:"url"`
|
||||
}
|
||||
|
||||
// ServerConfig is the [server] table.
|
||||
@@ -231,5 +251,23 @@ func (c *Config) Validate() error {
|
||||
if c.Registry.URL != "" && strings.Contains(c.Registry.URL, "://") {
|
||||
return fmt.Errorf("config: [registry] url %q must be a bare host[:port] with no scheme (e.g. registry.felis.svc:5000); a scheme breaks the user-modpack build lane's derived push target", c.Registry.URL)
|
||||
}
|
||||
// Felis-nano auth sources: each needs a namespace tag and a scheme-qualified hasJoined
|
||||
// URL, and tags must be unique. A blank or duplicate tag collapses two sources into one
|
||||
// UUID namespace (cross-source impersonation — the exact invariant the per-source
|
||||
// rewrite exists to hold); a scheme-less URL makes http.NewRequest fail so the source is
|
||||
// silently dead (never validates any login). Both fail fast at load, not per-login.
|
||||
seenTags := make(map[string]struct{}, len(c.AuthSources))
|
||||
for i, s := range c.AuthSources {
|
||||
if s.Tag == "" {
|
||||
return fmt.Errorf("config: [[auth_source]] #%d has an empty tag; each source's tag is its per-source UUID namespace", i+1)
|
||||
}
|
||||
if _, dup := seenTags[s.Tag]; dup {
|
||||
return fmt.Errorf("config: [[auth_source]] tag %q is used twice — tags are per-source UUID namespaces and must be unique", s.Tag)
|
||||
}
|
||||
seenTags[s.Tag] = struct{}{}
|
||||
if !strings.HasPrefix(s.URL, "http://") && !strings.HasPrefix(s.URL, "https://") {
|
||||
return fmt.Errorf("config: [[auth_source]] %q url %q must be a scheme-qualified http(s):// hasJoined endpoint", s.Tag, s.URL)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in new issue
Block a user