|
|
@ -1,20 +1,14 @@ |
|
|
|
package mockid |
|
|
|
|
|
|
|
import ( |
|
|
|
"crypto/ecdsa" |
|
|
|
"crypto/elliptic" |
|
|
|
"crypto/rsa" |
|
|
|
"crypto/sha1" |
|
|
|
"crypto/sha256" |
|
|
|
"crypto/sha512" |
|
|
|
"encoding/base64" |
|
|
|
"encoding/json" |
|
|
|
"errors" |
|
|
|
"fmt" |
|
|
|
"io" |
|
|
|
"io/ioutil" |
|
|
|
"log" |
|
|
|
mathrand "math/rand" |
|
|
|
"net/http" |
|
|
|
"os" |
|
|
|
"path/filepath" |
|
|
@ -22,11 +16,14 @@ import ( |
|
|
|
"strings" |
|
|
|
"time" |
|
|
|
|
|
|
|
"git.coolaj86.com/coolaj86/go-mockid/mockid/api" |
|
|
|
"git.coolaj86.com/coolaj86/go-mockid/xkeypairs" |
|
|
|
"git.rootprojects.org/root/keypairs" |
|
|
|
"git.rootprojects.org/root/keypairs/keyfetch" |
|
|
|
"github.com/google/uuid" |
|
|
|
) |
|
|
|
|
|
|
|
// Route returns an HTTP Mux containing the full API
|
|
|
|
func Route(jwksPrefix string, privkey keypairs.PrivateKey) http.Handler { |
|
|
|
Init() |
|
|
|
|
|
|
@ -44,12 +41,12 @@ func Route(jwksPrefix string, privkey keypairs.PrivateKey) http.Handler { |
|
|
|
// is this the expiration of the nonce itself? methinks maybe so
|
|
|
|
//res.setHeader("Expires", "Sun, 10 Mar 2019 08:04:45 GMT");
|
|
|
|
// TODO use one of the registered domains
|
|
|
|
//var indexUrl = "https://acme-staging-v02.api.letsencrypt.org/index"
|
|
|
|
//var indexURL = "https://acme-staging-v02.api.letsencrypt.org/index"
|
|
|
|
*/ |
|
|
|
//var port = (state.config.ipc && state.config.ipc.port || state._ipc.port || undefined);
|
|
|
|
//var indexUrl = "http://localhost:" + port + "/index";
|
|
|
|
indexUrl := baseURL + "/index" |
|
|
|
w.Header().Set("Link", "<"+indexUrl+">;rel=\"index\"") |
|
|
|
//var indexURL = "http://localhost:" + port + "/index";
|
|
|
|
indexURL := baseURL + "/index" |
|
|
|
w.Header().Set("Link", "<"+indexURL+">;rel=\"index\"") |
|
|
|
w.Header().Set("Cache-Control", "max-age=0, no-cache, no-store") |
|
|
|
w.Header().Set("Pragma", "no-cache") |
|
|
|
//res.setHeader("Strict-Transport-Security", "max-age=604800");
|
|
|
@ -184,101 +181,11 @@ func Route(jwksPrefix string, privkey keypairs.PrivateKey) http.Handler { |
|
|
|
fmt.Fprintf(w, token) |
|
|
|
}) |
|
|
|
|
|
|
|
getKty := func(r *http.Request) (string, error) { |
|
|
|
tok := make(map[string]interface{}) |
|
|
|
decoder := json.NewDecoder(r.Body) |
|
|
|
err := decoder.Decode(&tok) |
|
|
|
if nil != err && io.EOF != err { |
|
|
|
log.Printf("json decode error: %s", err) |
|
|
|
return "", errors.New("Bad Request: invalid json body") |
|
|
|
} |
|
|
|
defer r.Body.Close() |
|
|
|
|
|
|
|
kty, _ := tok["kty"].(string) |
|
|
|
if "" == kty { |
|
|
|
if 0 == mathrand.Intn(2) { |
|
|
|
kty = "RSA" |
|
|
|
} else { |
|
|
|
kty = "EC" |
|
|
|
} |
|
|
|
} |
|
|
|
return kty, nil |
|
|
|
} |
|
|
|
|
|
|
|
http.HandleFunc("/private.jwk.json", func(w http.ResponseWriter, r *http.Request) { |
|
|
|
log.Printf("%s %s", r.Method, r.URL.Path) |
|
|
|
if "POST" != r.Method { |
|
|
|
http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed) |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
kty, err := getKty(r) |
|
|
|
if nil != err { |
|
|
|
http.Error(w, err.Error(), http.StatusBadRequest) |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
var privkey keypairs.PrivateKey |
|
|
|
if "RSA" == kty { |
|
|
|
keylen := 2048 |
|
|
|
privkey, _ = rsa.GenerateKey(rndsrc, keylen) |
|
|
|
} else { |
|
|
|
privkey, _ = ecdsa.GenerateKey(elliptic.P256(), rndsrc) |
|
|
|
} |
|
|
|
|
|
|
|
jwk := MarshalJWKPrivateKey(privkey) |
|
|
|
w.Write(append(jwk, '\n')) |
|
|
|
}) |
|
|
|
|
|
|
|
http.HandleFunc("/priv.der", func(w http.ResponseWriter, r *http.Request) { |
|
|
|
log.Printf("%s %s\n", r.Method, r.URL.Path) |
|
|
|
if "POST" != r.Method { |
|
|
|
http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed) |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
kty, err := getKty(r) |
|
|
|
if nil != err { |
|
|
|
http.Error(w, err.Error(), http.StatusBadRequest) |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
var privkey keypairs.PrivateKey |
|
|
|
if "RSA" == kty { |
|
|
|
keylen := 2048 |
|
|
|
privkey, _ = rsa.GenerateKey(rndsrc, keylen) |
|
|
|
} else { |
|
|
|
privkey, _ = ecdsa.GenerateKey(elliptic.P256(), rndsrc) |
|
|
|
} |
|
|
|
|
|
|
|
der, _ := MarshalDERPrivateKey(privkey) |
|
|
|
w.Write(der) |
|
|
|
}) |
|
|
|
http.HandleFunc("/private.jwk.json", api.GeneratePrivateJWK) |
|
|
|
|
|
|
|
http.HandleFunc("/priv.pem", func(w http.ResponseWriter, r *http.Request) { |
|
|
|
log.Printf("%s %s\n", r.Method, r.URL.Path) |
|
|
|
if "POST" != r.Method { |
|
|
|
http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed) |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
kty, err := getKty(r) |
|
|
|
if nil != err { |
|
|
|
http.Error(w, err.Error(), http.StatusBadRequest) |
|
|
|
return |
|
|
|
} |
|
|
|
http.HandleFunc("/priv.der", api.GeneratePrivateDER) |
|
|
|
|
|
|
|
var privkey keypairs.PrivateKey |
|
|
|
if "RSA" == kty { |
|
|
|
keylen := 2048 |
|
|
|
privkey, _ = rsa.GenerateKey(rndsrc, keylen) |
|
|
|
} else { |
|
|
|
privkey, _ = ecdsa.GenerateKey(elliptic.P256(), rndsrc) |
|
|
|
} |
|
|
|
|
|
|
|
privpem, _ := MarshalPEMPrivateKey(privkey) |
|
|
|
w.Write(privpem) |
|
|
|
}) |
|
|
|
http.HandleFunc("/priv.pem", api.GeneratePrivatePEM) |
|
|
|
|
|
|
|
http.HandleFunc("/inspect_token", func(w http.ResponseWriter, r *http.Request) { |
|
|
|
token := r.Header.Get("Authorization") |
|
|
@ -404,7 +311,7 @@ func Route(jwksPrefix string, privkey keypairs.PrivateKey) http.Handler { |
|
|
|
|
|
|
|
http.HandleFunc("/key.jwk.json", func(w http.ResponseWriter, r *http.Request) { |
|
|
|
log.Printf("%s %s", r.Method, r.URL.Path) |
|
|
|
jwk := string(MarshalJWKPrivateKey(privkey)) |
|
|
|
jwk := string(xkeypairs.MarshalJWKPrivateKey(privkey)) |
|
|
|
jwk = strings.Replace(jwk, `{"`, `{ "`, 1) |
|
|
|
jwk = strings.Replace(jwk, `",`, `", `, -1) |
|
|
|
jwk = jwk[0 : len(jwk)-1] |
|
|
@ -474,6 +381,7 @@ func getBaseURL(r *http.Request) string { |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
// HTTPError describes an error that should be propagated to the HTTP client
|
|
|
|
type HTTPError struct { |
|
|
|
message string |
|
|
|
code int |
|
|
|