Skip to content

Commit

Permalink
feat: proxy and cmdline config
Browse files Browse the repository at this point in the history
  • Loading branch information
natesales committed Jan 28, 2025
1 parent 7d8897c commit 7e9eb2f
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 11 deletions.
2 changes: 1 addition & 1 deletion .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ builds:

nfpms:
- package_name: tinfoil-sev-shim
file_name_template: "{{ .ProjectName }}_{{ .Version }}"
file_name_template: tinfoil-sev-shim
vendor: Tinfoil
maintainer: Tinfoil <[email protected]>
section: utils
Expand Down
69 changes: 59 additions & 10 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import (
"fmt"
"log"
"net/http"
"net/http/httputil"
"net/url"
"os"
"strings"

"github.com/caddyserver/certmagic"
"github.com/google/go-sev-guest/abi"
Expand All @@ -18,13 +22,33 @@ import (
"github.com/tinfoilanalytics/verifier/pkg/attestation"
)

var version = "dev"

var (
listenAddr = flag.String("l", ":443", "listen address")
domain = flag.String("d", "", "TLS domain name")
email = flag.String("e", "", "TLS email address")
staging = flag.Bool("s", false, "use staging CA")
upstream = flag.Int("u", 8080, "upstream port")

email = "[email protected]"
)

// cmdlineParam returns the value of a parameter from the kernel command line
func cmdlineParam(key string) (string, error) {
cmdline, err := os.ReadFile("/proc/cmdline")
if err != nil {
return "", err
}

for _, p := range strings.Split(string(cmdline), " ") {
if strings.HasPrefix(p, key+"=") {
return strings.TrimPrefix(p, key+"="), nil
}
}

return "", fmt.Errorf("missing %s", key)
}

// attestationReport gets a SEV-SNP signed attestation report over a TLS certificate fingerprint
func attestationReport(certFP string) (*attestation.Document, error) {
var userData [64]byte
copy(userData[:], certFP)
Expand All @@ -48,44 +72,69 @@ func attestationReport(certFP string) (*attestation.Document, error) {
}, nil
}

func cors(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "*")
w.Header().Set("Access-Control-Allow-Headers", "*")

if r.Method == "OPTIONS" {
w.WriteHeader(http.StatusOK)
return
}
}

func main() {
flag.Parse()
if *domain == "" {
log.Fatal("domain is required")
}
if *email == "" {
log.Fatal("email is required")

domain, err := cmdlineParam("tinfoil-domain")
if err != nil {
log.Fatal(err)
}

log.Printf("Starting SEV-SNP attestation shim %s domain %s", version, domain)

mux := http.NewServeMux()

certmagic.DefaultACME.Email = *email
// Request TLS certificate
certmagic.DefaultACME.Email = email
if *staging {
certmagic.DefaultACME.CA = certmagic.LetsEncryptStagingCA
} else {
certmagic.DefaultACME.CA = certmagic.LetsEncryptProductionCA
}
tlsConfig, err := certmagic.TLS([]string{*domain})
tlsConfig, err := certmagic.TLS([]string{domain})
if err != nil {
log.Fatalf("Failed to get TLS config: %v", err)
}

// Get certificate from TLS config
cert, err := tlsConfig.GetCertificate(&tls.ClientHelloInfo{
ServerName: *domain,
ServerName: domain,
})
if err != nil {
log.Fatalf("Failed to get certificate: %v", err)
}
certFP := sha256.Sum256(cert.Leaf.Raw)
certFPHex := hex.EncodeToString(certFP[:])

// Request SEV-SNP attestation
log.Printf("Fetching attestation over %s", certFPHex)
att, err := attestationReport(certFPHex)
if err != nil {
log.Fatal(err)
}

mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
cors(w, r)
proxy := httputil.NewSingleHostReverseProxy(&url.URL{
Scheme: "http",
Host: fmt.Sprintf("localhost:%d", *upstream),
})
proxy.ServeHTTP(w, r)
})

mux.HandleFunc("/.well-known/tinfoil-attestation", func(w http.ResponseWriter, r *http.Request) {
cors(w, r)
w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(att)
Expand Down

0 comments on commit 7e9eb2f

Please sign in to comment.