mirror of
https://github.com/jech/galene.git
synced 2024-11-25 10:05:58 +01:00
Add the galene-link utility.
This commit is contained in:
parent
37ef768ac0
commit
c4d46d20aa
3 changed files with 123 additions and 8 deletions
115
galene-link/galene-link.go
Normal file
115
galene-link/galene-link.go
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net/url"
|
||||||
|
"path"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/golang-jwt/jwt/v4"
|
||||||
|
|
||||||
|
"github.com/jech/galene/group"
|
||||||
|
"github.com/jech/galene/token"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var username, kid, server string
|
||||||
|
var valid int
|
||||||
|
var tokenOnly bool
|
||||||
|
flag.StringVar(&group.Directory, "groups", "./groups/",
|
||||||
|
"group description `directory`")
|
||||||
|
flag.StringVar(&username, "user", "", "username")
|
||||||
|
flag.StringVar(&kid, "kid", "", "`id` of key to use")
|
||||||
|
flag.IntVar(&valid, "valid", 86400, "`seconds` validity")
|
||||||
|
flag.StringVar(&server, "server", "https://galene.org:8443",
|
||||||
|
"server `url`")
|
||||||
|
flag.BoolVar(&tokenOnly, "token", false, "generate token only")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
if flag.NArg() != 1 {
|
||||||
|
log.Fatal("One argument (the group URL) required")
|
||||||
|
}
|
||||||
|
groupname := flag.Arg(0)
|
||||||
|
|
||||||
|
desc, err := group.GetDescription(groupname)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Get group description: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
serverURL, err := url.Parse(server)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Couldn't parse server URL")
|
||||||
|
}
|
||||||
|
pth := path.Join(path.Join(serverURL.Path, "group"), groupname) + "/"
|
||||||
|
groupURL := &url.URL{
|
||||||
|
Scheme: serverURL.Scheme,
|
||||||
|
Host: serverURL.Host,
|
||||||
|
Path: pth,
|
||||||
|
}
|
||||||
|
|
||||||
|
keys := desc.AuthKeys
|
||||||
|
var key map[string]interface{}
|
||||||
|
for _, k := range keys {
|
||||||
|
kid2, _ := k["kid"].(string)
|
||||||
|
if kid == "" || kid == kid2 {
|
||||||
|
key = k
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if key == nil {
|
||||||
|
log.Fatal("Couldn't find key")
|
||||||
|
}
|
||||||
|
|
||||||
|
alg, ok := key["alg"].(string)
|
||||||
|
var method jwt.SigningMethod
|
||||||
|
if ok {
|
||||||
|
method = jwt.GetSigningMethod(alg)
|
||||||
|
}
|
||||||
|
if method == nil {
|
||||||
|
log.Fatal("Couldn't determine key signing method")
|
||||||
|
}
|
||||||
|
|
||||||
|
kstring, err := token.ParseKey(key)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Couldn't parse key")
|
||||||
|
}
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
end := now.Add(time.Second * time.Duration(valid))
|
||||||
|
token := jwt.NewWithClaims(
|
||||||
|
method,
|
||||||
|
&jwt.MapClaims{
|
||||||
|
"sub": username,
|
||||||
|
"aud": groupURL.String(),
|
||||||
|
"exp": &jwt.NumericDate{end},
|
||||||
|
"nbf": &jwt.NumericDate{now},
|
||||||
|
"iat": &jwt.NumericDate{now},
|
||||||
|
"permissions": []string{"present"},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
s, err := token.SignedString(kstring)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Couldn't sign token: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tokenOnly {
|
||||||
|
fmt.Println(s)
|
||||||
|
} else {
|
||||||
|
query := url.Values{}
|
||||||
|
if username != "" {
|
||||||
|
query.Add("username", username)
|
||||||
|
}
|
||||||
|
query.Add("token", s)
|
||||||
|
outURL := &url.URL{
|
||||||
|
Scheme: groupURL.Scheme,
|
||||||
|
Host: groupURL.Host,
|
||||||
|
Path: groupURL.Path,
|
||||||
|
RawQuery: query.Encode(),
|
||||||
|
}
|
||||||
|
fmt.Println(outURL.String())
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,7 +24,7 @@ func parseBase64(k string, d map[string]interface{}) ([]byte, error) {
|
||||||
return vv, nil
|
return vv, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseKey(key map[string]interface{}) (interface{}, error) {
|
func ParseKey(key map[string]interface{}) (interface{}, error) {
|
||||||
kty, ok := key["kty"].(string)
|
kty, ok := key["kty"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("kty not found")
|
return nil, errors.New("kty not found")
|
||||||
|
@ -99,7 +99,7 @@ func getKey(header map[string]interface{}, keys []map[string]interface{}) (inter
|
||||||
kid2, _ := k["kid"].(string)
|
kid2, _ := k["kid"].(string)
|
||||||
alg2, _ := k["alg"].(string)
|
alg2, _ := k["alg"].(string)
|
||||||
if (kid == "" || kid == kid2) && alg == alg2 {
|
if (kid == "" || kid == kid2) && alg == alg2 {
|
||||||
return parseKey(k)
|
return ParseKey(k)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, errors.New("key not found")
|
return nil, errors.New("key not found")
|
||||||
|
|
|
@ -21,13 +21,13 @@ func TestHS256(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unmarshal: %v", err)
|
t.Fatalf("Unmarshal: %v", err)
|
||||||
}
|
}
|
||||||
k, err := parseKey(j)
|
k, err := ParseKey(j)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("parseKey: %v", err)
|
t.Fatalf("ParseKey: %v", err)
|
||||||
}
|
}
|
||||||
kk, ok := k.([]byte)
|
kk, ok := k.([]byte)
|
||||||
if !ok || len(kk) != 32 {
|
if !ok || len(kk) != 32 {
|
||||||
t.Errorf("parseKey: got %v", kk)
|
t.Errorf("ParseKey: got %v", kk)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,13 +44,13 @@ func TestES256(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unmarshal: %v", err)
|
t.Fatalf("Unmarshal: %v", err)
|
||||||
}
|
}
|
||||||
k, err := parseKey(j)
|
k, err := ParseKey(j)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("parseKey: %v", err)
|
t.Fatalf("ParseKey: %v", err)
|
||||||
}
|
}
|
||||||
kk, ok := k.(*ecdsa.PublicKey)
|
kk, ok := k.(*ecdsa.PublicKey)
|
||||||
if !ok || kk.Params().Name != "P-256" {
|
if !ok || kk.Params().Name != "P-256" {
|
||||||
t.Errorf("parseKey: got %v", kk)
|
t.Errorf("ParseKey: got %v", kk)
|
||||||
}
|
}
|
||||||
if !kk.IsOnCurve(kk.X, kk.Y) {
|
if !kk.IsOnCurve(kk.X, kk.Y) {
|
||||||
t.Errorf("point is not on curve")
|
t.Errorf("point is not on curve")
|
||||||
|
|
Loading…
Reference in a new issue