103 lines
2.7 KiB
Go
103 lines
2.7 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"runtime/debug"
|
|
|
|
jwt "github.com/dgrijalva/jwt-go"
|
|
)
|
|
|
|
func signingKey() []byte {
|
|
if k := os.Getenv("JWT_KEY"); k != "" {
|
|
return []byte(k)
|
|
}
|
|
return []byte("demo-only-not-for-real-use")
|
|
}
|
|
|
|
type versionInfo struct {
|
|
Service string `json:"service"`
|
|
Commit string `json:"commit"`
|
|
GoVersion string `json:"go_version"`
|
|
Deps map[string]string `json:"deps"`
|
|
JWTLibrary string `json:"jwt_library"`
|
|
}
|
|
|
|
func main() {
|
|
mux := http.NewServeMux()
|
|
mux.HandleFunc("/", index)
|
|
mux.HandleFunc("/version", version)
|
|
mux.HandleFunc("/healthz", func(w http.ResponseWriter, _ *http.Request) {
|
|
w.WriteHeader(http.StatusOK)
|
|
fmt.Fprintln(w, "ok")
|
|
})
|
|
mux.HandleFunc("/verify", verifyToken)
|
|
|
|
port := os.Getenv("PORT")
|
|
if port == "" {
|
|
port = "8080"
|
|
}
|
|
log.Printf("demo-secure listening on :%s", port)
|
|
if err := http.ListenAndServe(":"+port, mux); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func index(w http.ResponseWriter, _ *http.Request) {
|
|
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
|
fmt.Fprintf(w, `<!doctype html>
|
|
<html><head><title>demo-secure</title></head>
|
|
<body style="font-family:sans-serif;max-width:40em;margin:3em auto">
|
|
<h1>demo-secure</h1>
|
|
<p>A minimal Go service used to demonstrate the RHADS supply chain:
|
|
RHDH onboarding → RHTAS signing → RHTPA scanning → patch.</p>
|
|
<ul>
|
|
<li><a href="/version">/version</a> — dependency info</li>
|
|
<li><a href="/healthz">/healthz</a> — liveness</li>
|
|
<li><code>POST /verify</code> with a Bearer token — exercises the JWT library</li>
|
|
</ul>
|
|
</body></html>`)
|
|
}
|
|
|
|
func version(w http.ResponseWriter, _ *http.Request) {
|
|
info := versionInfo{
|
|
Service: "demo-secure",
|
|
Commit: os.Getenv("GIT_COMMIT"),
|
|
Deps: map[string]string{},
|
|
}
|
|
if bi, ok := debug.ReadBuildInfo(); ok {
|
|
info.GoVersion = bi.GoVersion
|
|
for _, d := range bi.Deps {
|
|
info.Deps[d.Path] = d.Version
|
|
if d.Path == "github.com/dgrijalva/jwt-go" || d.Path == "github.com/golang-jwt/jwt/v5" {
|
|
info.JWTLibrary = fmt.Sprintf("%s@%s", d.Path, d.Version)
|
|
}
|
|
}
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_ = json.NewEncoder(w).Encode(info)
|
|
}
|
|
|
|
func verifyToken(w http.ResponseWriter, r *http.Request) {
|
|
tok := r.Header.Get("Authorization")
|
|
if len(tok) > 7 && tok[:7] == "Bearer " {
|
|
tok = tok[7:]
|
|
}
|
|
if tok == "" {
|
|
http.Error(w, "missing bearer token", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
parsed, err := jwt.Parse(tok, func(t *jwt.Token) (interface{}, error) {
|
|
return signingKey(), nil
|
|
})
|
|
if err != nil || !parsed.Valid {
|
|
http.Error(w, "invalid token", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_ = json.NewEncoder(w).Encode(parsed.Claims)
|
|
}
|