Full dependency inventory across Rust/Go/npm plus Docker base images and vendored assets (776 rows, 502 unique deps), classified against AGPLv3 compatibility with real citations rather than assumptions. enterprise/ relicensed from its commercial-license stub to AGPLv3, matching core -- the one real flag (Redpanda's BSL 1.1) was evaluated against primary sources and accepted as-is rather than triggering a broker swap. CI enforcement wired up (.github/workflows/license- compliance.yml, this repo's first CI workflow), a root LICENSE file added, and every doc/comment referencing the old commercial-license boundary updated to describe it as architectural only. See /docs/compliance/ for the full report, inventory, and policy.
66 lines
2.3 KiB
Go
66 lines
2.3 KiB
Go
// Package tenantresolver is ingest's HTTP client for resolving an
|
|
// agent-presented ingest credential to a tenant -- calls enterprise-
|
|
// auth's POST /internal/authorize-ingest over the network, never
|
|
// importing enterprise/ (both ingest and enterprise/ are AGPLv3 as of
|
|
// Phase 6; the import boundary is architectural, not a licensing wall --
|
|
// same "network boundary, not import boundary" shape api/authz.HTTPAuthorizer
|
|
// already uses for the query path, and enterprise-auth's own doc
|
|
// comment on POST /internal/authorize-ingest). nil (no resolver
|
|
// configured) is grpcserver.Server's documented no-op default --
|
|
// single-tenant deployments never construct one, and every record's
|
|
// TenantID stays empty, exactly like before per-tenant ingest
|
|
// credentials existed.
|
|
package tenantresolver
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"time"
|
|
)
|
|
|
|
type HTTPResolver struct {
|
|
baseURL string
|
|
http *http.Client
|
|
}
|
|
|
|
func New(baseURL string) *HTTPResolver {
|
|
return &HTTPResolver{baseURL: baseURL, http: &http.Client{Timeout: 3 * time.Second}}
|
|
}
|
|
|
|
type authorizeIngestResponse struct {
|
|
TenantID string `json:"tenant_id"`
|
|
}
|
|
|
|
// ResolveTenant implements grpcserver.TenantResolver. Forwards only the
|
|
// bearer token itself, nothing else about the caller's request -- same
|
|
// "forward exactly the credential, never the rest of the request"
|
|
// discipline api/authz.HTTPAuthorizer already follows.
|
|
func (r *HTTPResolver) ResolveTenant(ctx context.Context, token string) (string, error) {
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodPost, r.baseURL+"/internal/authorize-ingest", nil)
|
|
if err != nil {
|
|
return "", fmt.Errorf("tenantresolver: building request: %w", err)
|
|
}
|
|
req.Header.Set("Authorization", "Bearer "+token)
|
|
|
|
resp, err := r.http.Do(req)
|
|
if err != nil {
|
|
return "", fmt.Errorf("tenantresolver: calling enterprise-auth: %w", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
return "", fmt.Errorf("tenantresolver: enterprise-auth returned status %d", resp.StatusCode)
|
|
}
|
|
|
|
var body authorizeIngestResponse
|
|
if err := json.NewDecoder(resp.Body).Decode(&body); err != nil {
|
|
return "", fmt.Errorf("tenantresolver: decoding response: %w", err)
|
|
}
|
|
if body.TenantID == "" {
|
|
return "", fmt.Errorf("tenantresolver: enterprise-auth returned an empty tenant_id")
|
|
}
|
|
return body.TenantID, nil
|
|
}
|