add --expires-in to signjwt
This commit is contained in:
parent
cfe3820fea
commit
ce39066bc8
31
README.md
31
README.md
|
@ -104,13 +104,22 @@ Copy `examples/mgmt.env` as `.env` in the working directory.
|
||||||
Create a token with the same `SECRET` used with the `mgmt` server,
|
Create a token with the same `SECRET` used with the `mgmt` server,
|
||||||
and add a device by its `subdomain`.
|
and add a device by its `subdomain`.
|
||||||
|
|
||||||
|
To build `signjwt`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go build -mod=vendor -ldflags "-s -w" -o signjwt cmd/signjwt/*.go
|
||||||
|
```
|
||||||
|
|
||||||
|
To generate an `admin` token:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
VERDOR_ID="test-id"
|
VERDOR_ID="test-id"
|
||||||
SECRET="xxxxxxxxxxx"
|
SECRET="xxxxxxxxxxx"
|
||||||
TOKEN=$(go run -mod=vendor cmd/signjwt/*.go \
|
TOKEN=$(./signjwt \
|
||||||
|
--expires-in 15m \
|
||||||
--vendor-id $VENDOR_ID \
|
--vendor-id $VENDOR_ID \
|
||||||
--secret $SECRET \
|
--secret $SECRET \
|
||||||
--machine-id $SECRET
|
--machine-ppid $SECRET
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -240,3 +249,21 @@ EOF
|
||||||
|
|
||||||
python3 -m http.server 3000
|
python3 -m http.server 3000
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Glossary
|
||||||
|
|
||||||
|
```
|
||||||
|
--vendor-id $VENDOR_ID an arbitrary id used as part of authentication
|
||||||
|
--secret $SECRET the secret for creating JWTs
|
||||||
|
--auth-url $AUTH_URL the full url prefix of the server that will validate tokens
|
||||||
|
--tunnel-relay-url $TUNNEL_RELAY_URL the full url of the websocket tunnel server
|
||||||
|
--locals $LOCALS a list of `scheme:domainname:port`
|
||||||
|
for forwarding incoming `domainname` to local `port`
|
||||||
|
--port-forwards $PORT_FORWARDS a list of `remote:local` tcp port-forwarding
|
||||||
|
--verbose $VERBOSE logs everything, including abbreviated data (as hex)
|
||||||
|
$VERBOSE_BYTES logs full data (as hex)
|
||||||
|
$VERBOSE_RAW logs full data (as string)
|
||||||
|
--acme-agree $ACME_AGREE agree to the ACME service agreement
|
||||||
|
--acme-email $ACME_EMAIL the webmaster email for ACME notices
|
||||||
|
--acme-relay-url $ACME_RELAY_URL the server that will relay ACME DNS-01 requests
|
||||||
|
```
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"git.coolaj86.com/coolaj86/go-telebitd/mgmt/authstore"
|
"git.coolaj86.com/coolaj86/go-telebitd/mgmt/authstore"
|
||||||
telebit "git.coolaj86.com/coolaj86/go-telebitd/mplexer"
|
telebit "git.coolaj86.com/coolaj86/go-telebitd/mplexer"
|
||||||
|
@ -16,6 +17,15 @@ import (
|
||||||
_ "github.com/joho/godotenv/autoload"
|
_ "github.com/joho/godotenv/autoload"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var durAbbrs = map[byte]bool{
|
||||||
|
's': true, // second
|
||||||
|
'm': true, // minute
|
||||||
|
'h': true, // hour
|
||||||
|
'd': true, // day
|
||||||
|
'w': true, // week
|
||||||
|
// month and year cannot be measured
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var secret, clientSecret, relaySecret string
|
var secret, clientSecret, relaySecret string
|
||||||
|
|
||||||
|
@ -23,6 +33,7 @@ func main() {
|
||||||
machineID := flag.String("machine-id", "", "spoof the raw machine id")
|
machineID := flag.String("machine-id", "", "spoof the raw machine id")
|
||||||
vendorID := flag.String("vendor-id", "", "a unique identifier for a deploy target environment")
|
vendorID := flag.String("vendor-id", "", "a unique identifier for a deploy target environment")
|
||||||
authURL := flag.String("auth-url", "", "the base url for authentication, if not the same as the tunnel relay")
|
authURL := flag.String("auth-url", "", "the base url for authentication, if not the same as the tunnel relay")
|
||||||
|
humanExp := flag.String("expires-in", "15m", "set the token to expire <x> units after `iat` (issued at)")
|
||||||
getMachinePPID := flag.Bool("machine-ppid-only", false, "just print the machine ppid, not the token")
|
getMachinePPID := flag.Bool("machine-ppid-only", false, "just print the machine ppid, not the token")
|
||||||
flag.StringVar(&secret, "secret", "", "either the remote server or the tunnel relay secret (used for JWT authentication)")
|
flag.StringVar(&secret, "secret", "", "either the remote server or the tunnel relay secret (used for JWT authentication)")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
@ -31,6 +42,34 @@ func main() {
|
||||||
*authURL = os.Getenv("AUTH_URL")
|
*authURL = os.Getenv("AUTH_URL")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
humanExpLen := len(*humanExp)
|
||||||
|
if 0 == humanExpLen {
|
||||||
|
fmt.Fprintf(os.Stderr, "Invalid --expires-in: %q (minimum: 5s)", *humanExp)
|
||||||
|
}
|
||||||
|
expNum, _ := strconv.Atoi((*humanExp)[:humanExpLen-1])
|
||||||
|
expSuffix := (*humanExp)[humanExpLen-1:]
|
||||||
|
switch expSuffix {
|
||||||
|
case "w":
|
||||||
|
expNum *= 7
|
||||||
|
fallthrough
|
||||||
|
case "d":
|
||||||
|
expNum *= 24
|
||||||
|
fallthrough
|
||||||
|
case "h":
|
||||||
|
expNum *= 60
|
||||||
|
fallthrough
|
||||||
|
case "m":
|
||||||
|
expNum *= 60
|
||||||
|
fallthrough
|
||||||
|
case "s":
|
||||||
|
// do nothing
|
||||||
|
default:
|
||||||
|
fmt.Fprintf(os.Stderr, "Invalid --expires-in: %q (minimum: 5s)", *humanExp)
|
||||||
|
}
|
||||||
|
if expNum < 5 {
|
||||||
|
fmt.Fprintf(os.Stderr, "Invalid --expires-in: %q (minimum: 5s)", *humanExp)
|
||||||
|
}
|
||||||
|
|
||||||
if 0 == len(*vendorID) {
|
if 0 == len(*vendorID) {
|
||||||
*vendorID = os.Getenv("VENDOR_ID")
|
*vendorID = os.Getenv("VENDOR_ID")
|
||||||
}
|
}
|
||||||
|
@ -99,7 +138,7 @@ func main() {
|
||||||
fmt.Fprintf(os.Stderr, "[debug] ppid = %s\n", ppid)
|
fmt.Fprintf(os.Stderr, "[debug] ppid = %s\n", ppid)
|
||||||
fmt.Fprintf(os.Stderr, "[debug] pub = %s\n", pub)
|
fmt.Fprintf(os.Stderr, "[debug] pub = %s\n", pub)
|
||||||
|
|
||||||
tok, err := authstore.HMACToken(ppid)
|
tok, err := authstore.HMACToken(ppid, expNum)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
fmt.Fprintf(os.Stderr, "signing error: %s\n", err)
|
fmt.Fprintf(os.Stderr, "signing error: %s\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|
|
@ -14,6 +14,7 @@ AUTH_URL="${AUTH_URL:-"http://localhost:3000/api"}"
|
||||||
|
|
||||||
echo "RELAY_SECRET: $RELAY_SECRET"
|
echo "RELAY_SECRET: $RELAY_SECRET"
|
||||||
TOKEN=$(go run cmd/signjwt/*.go \
|
TOKEN=$(go run cmd/signjwt/*.go \
|
||||||
|
--expires-in 1m \
|
||||||
--vendor-id "$VENDOR_ID" \
|
--vendor-id "$VENDOR_ID" \
|
||||||
--secret "$RELAY_SECRET" \
|
--secret "$RELAY_SECRET" \
|
||||||
--machine-ppid "$RELAY_SECRET"
|
--machine-ppid "$RELAY_SECRET"
|
||||||
|
|
|
@ -51,12 +51,19 @@ func ToPublicKeyString(secret string) string {
|
||||||
return pub
|
return pub
|
||||||
}
|
}
|
||||||
|
|
||||||
func HMACToken(secret string) (token string, err error) {
|
func HMACToken(secret string, maybeExp ...int) (token string, err error) {
|
||||||
keyID := ToPublicKeyString(secret)
|
keyID := ToPublicKeyString(secret)
|
||||||
if dbg.Debug {
|
if dbg.Debug {
|
||||||
fmt.Fprintf(os.Stderr, "[debug] keyID=%s\n", keyID)
|
fmt.Fprintf(os.Stderr, "[debug] keyID=%s\n", keyID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var exp int64
|
||||||
|
if 0 == len(maybeExp) || 0 == maybeExp[0] {
|
||||||
|
exp = time.Now().Add(5 * time.Minute).Unix()
|
||||||
|
} else {
|
||||||
|
exp = time.Now().Add(time.Duration(maybeExp[0]) * time.Second).Unix()
|
||||||
|
}
|
||||||
|
|
||||||
b := make([]byte, 16)
|
b := make([]byte, 16)
|
||||||
_, _ = rand.Read(b)
|
_, _ = rand.Read(b)
|
||||||
claims := &jwt.StandardClaims{
|
claims := &jwt.StandardClaims{
|
||||||
|
@ -64,7 +71,7 @@ func HMACToken(secret string) (token string, err error) {
|
||||||
Subject: "", // TODO
|
Subject: "", // TODO
|
||||||
Issuer: "", // TODO
|
Issuer: "", // TODO
|
||||||
IssuedAt: time.Now().Unix(),
|
IssuedAt: time.Now().Unix(),
|
||||||
ExpiresAt: time.Now().Add(5 * time.Minute).Unix(),
|
ExpiresAt: exp,
|
||||||
}
|
}
|
||||||
|
|
||||||
jwtToken := &jwt.Token{
|
jwtToken := &jwt.Token{
|
||||||
|
|
Loading…
Reference in New Issue