refactor: unify internal api authentication
This commit is contained in:
+15
-21
@@ -25,8 +25,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
internalCapabilityAdminQuery = "admin_query"
|
||||
internalCapabilityCultivate = "cultivate"
|
||||
internalSharedCredentialService = "hotgo-admin"
|
||||
|
||||
internalHeaderService = "X-Service-Name"
|
||||
internalHeaderTimestamp = "X-Timestamp"
|
||||
@@ -85,7 +84,7 @@ func serveInternalAdminQuery(wrt http.ResponseWriter, req *http.Request, prefix
|
||||
writeIMError(wrt, req, http.StatusMethodNotAllowed, 30002, imReasonMethodNotAllowed, "method not allowed", nil)
|
||||
return
|
||||
}
|
||||
if !authorizeInternalAPI(wrt, req, internalCapabilityAdminQuery) {
|
||||
if !authorizeInternalAPI(wrt, req) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -363,7 +362,7 @@ func serveInternalLoginLockoutRelease(wrt http.ResponseWriter, req *http.Request
|
||||
writeIMSuccess(wrt, req, map[string]any{"account_hash": accountHash, "status": "released"})
|
||||
}
|
||||
|
||||
func authorizeInternalAPI(wrt http.ResponseWriter, req *http.Request, capability string) bool {
|
||||
func authorizeInternalAPI(wrt http.ResponseWriter, req *http.Request) bool {
|
||||
if !internalAPI.config.Enabled {
|
||||
writeIMError(wrt, req, http.StatusNotFound, 30004, imReasonMalformedRequest, "resource not found", nil)
|
||||
return false
|
||||
@@ -372,15 +371,11 @@ func authorizeInternalAPI(wrt http.ResponseWriter, req *http.Request, capability
|
||||
timestampRaw := strings.TrimSpace(req.Header.Get(internalHeaderTimestamp))
|
||||
nonce := strings.TrimSpace(req.Header.Get(internalHeaderNonce))
|
||||
signature := strings.TrimSpace(req.Header.Get(internalHeaderSignature))
|
||||
service, ok := internalAPI.config.Services[serviceName]
|
||||
if !ok || service.Secret == "" || timestampRaw == "" || nonce == "" || signature == "" {
|
||||
secret := internalSharedSecret()
|
||||
if serviceName == "" || secret == "" || timestampRaw == "" || nonce == "" || signature == "" {
|
||||
writeIMError(wrt, req, http.StatusUnauthorized, 30043, imReasonAuthRequired, "internal signature required", nil)
|
||||
return false
|
||||
}
|
||||
if !internalServiceAllows(service, capability) {
|
||||
writeIMError(wrt, req, http.StatusForbidden, 30005, imReasonPermissionDenied, "permission denied", nil)
|
||||
return false
|
||||
}
|
||||
timestamp, err := strconv.ParseInt(timestampRaw, 10, 64)
|
||||
if err != nil {
|
||||
writeIMError(wrt, req, http.StatusUnauthorized, 30043, imReasonAuthRequired, "invalid internal timestamp", nil)
|
||||
@@ -403,7 +398,7 @@ func authorizeInternalAPI(wrt http.ResponseWriter, req *http.Request, capability
|
||||
timestampRaw,
|
||||
nonce,
|
||||
}, "\n")
|
||||
if !verifyInternalSignature(service.Secret, signingText, signature) {
|
||||
if !verifyInternalSignature(secret, signingText, signature) {
|
||||
writeIMError(wrt, req, http.StatusUnauthorized, 30043, imReasonAuthRequired, "invalid internal signature", nil)
|
||||
return false
|
||||
}
|
||||
@@ -415,6 +410,15 @@ func authorizeInternalAPI(wrt http.ResponseWriter, req *http.Request, capability
|
||||
return true
|
||||
}
|
||||
|
||||
// internalSharedSecret returns the single credential used by all trusted
|
||||
// backend callers. Service names remain request labels for audit and nonce
|
||||
// isolation only; they no longer select separate credentials or capabilities.
|
||||
// Reuse the existing hotgo-admin credential so current deployments require no
|
||||
// additional secret or configuration changes.
|
||||
func internalSharedSecret() string {
|
||||
return strings.TrimSpace(internalAPI.config.Services[internalSharedCredentialService].Secret)
|
||||
}
|
||||
|
||||
func splitInternalPath(tail string) []string {
|
||||
if tail == "" {
|
||||
return nil
|
||||
@@ -765,16 +769,6 @@ func parseInternalUid(raw string) types.Uid {
|
||||
return store.EncodeUid(id)
|
||||
}
|
||||
|
||||
func internalServiceAllows(service internalAPIServiceConfig, capability string) bool {
|
||||
for _, allowed := range service.Allow {
|
||||
allowed = strings.TrimSpace(allowed)
|
||||
if allowed == "*" || allowed == capability {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func hashInternalRequestBody(req *http.Request) (string, error) {
|
||||
if req.Body == nil {
|
||||
sum := sha256.Sum256(nil)
|
||||
|
||||
Reference in New Issue
Block a user