feat(api): 内部面 token 按调用方拆分为 velocity/limbo/build/ops 并按路由限定调用方,审计来源区分调用方,安装器生成并下发各自 Secret,新增 felis rotate-token 轮换命令

This commit is contained in:
Lemon-miaow committed 2026-09-25 15:21:41 +08:00
1 parent d3769b5c31
commit a883c1fe07
38 files changed
+1359 -209

No files matched your search

+5 -4
View File
@@ -323,21 +323,22 @@ func buildEnv(server *v1alpha1.MinecraftServer) []corev1.EnvVar {
}
// The login system server is the ONE workload that authenticates to the
// felis-api internal face (its felis-limbo plugin mints bind codes and polls
// link status), so it — and only it — receives the service token. Injected
// link status), so it — and only it — receives a token: felis-limbo-token,
// which the api serves on those routes alone. Injected
// from a Secret in this namespace, never inlined into the CRD (the same
// discipline as RCON_PASSWORD above; the CRD's EnvVar type has no valueFrom
// precisely so a user server cannot mount an arbitrary secret). Require both
// the reserved name and the setup-owned system-role label: the label prevents
// a legacy user server named "login" from receiving the token after upgrade.
// The Secret must exist in this (minecraft) namespace; `felis setup` replicates
// it there from the control namespace before creating this server.
// The Secret must exist in this (minecraft) namespace; the installer applies it
// there and `felis setup` replicates it from the control namespace.
if server.Name == naming.SystemLoginServer &&
server.Labels[v1alpha1.LabelSystemRole] == naming.SystemLoginServer {
env = append(env, corev1.EnvVar{
Name: envServiceToken,
ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{Name: naming.ServiceTokenSecretName},
LocalObjectReference: corev1.LocalObjectReference{Name: naming.LimboTokenSecretName},
Key: naming.ServiceTokenSecretKey,
},
},
+6 -5
View File
@@ -227,9 +227,10 @@ func TestBuildStatefulSetAddsHealthPort(t *testing.T) {
}
}
// The login system server (and ONLY it) receives the service token, sourced from a
// Secret via secretKeyRef — never a literal — so its felis-limbo plugin can
// authenticate to the felis-api internal face.
// The login system server (and ONLY it) receives the login gate's own token,
// sourced from a Secret via secretKeyRef — never a literal — so its felis-limbo
// plugin can authenticate to the felis-api internal face as the limbo caller. It
// must not be the proxy's felis-service-token, which opens every game route.
func TestBuildEnvInjectsServiceTokenForLogin(t *testing.T) {
s := &v1alpha1.MinecraftServer{}
s.Name = naming.SystemLoginServer
@@ -245,8 +246,8 @@ func TestBuildEnvInjectsServiceTokenForLogin(t *testing.T) {
t.Fatalf("%s must be sourced from a secretKeyRef", envServiceToken)
}
ref := tok.ValueFrom.SecretKeyRef
if ref.Name != naming.ServiceTokenSecretName || ref.Key != naming.ServiceTokenSecretKey {
t.Errorf("secretKeyRef = %s/%s, want %s/%s", ref.Name, ref.Key, naming.ServiceTokenSecretName, naming.ServiceTokenSecretKey)
if ref.Name != "felis-limbo-token" || ref.Key != "token" {
t.Errorf("secretKeyRef = %s/%s, want felis-limbo-token/token", ref.Name, ref.Key)
}
}