From bc996c9e5bfe66c3651e4521feaeb68917145c47 Mon Sep 17 00:00:00 2001 From: Xe Iaso Date: Sun, 12 Jan 2025 16:35:30 -0500 Subject: [PATCH] add cmd/didweb Signed-off-by: Xe Iaso --- cmd/didweb/.gitignore | 3 + cmd/didweb/README.md | 3 + cmd/didweb/atproto-recommended-credentials.go | 52 +++ cmd/didweb/did.go | 24 ++ cmd/didweb/main.go | 359 ++++++++++++++++++ cmd/oidctest/main.go | 140 +++++++ go.mod | 20 +- go.sum | 29 ++ kube/alrest/uptime-kuma/ingress.yaml | 21 + 9 files changed, 647 insertions(+), 4 deletions(-) create mode 100644 cmd/didweb/.gitignore create mode 100644 cmd/didweb/README.md create mode 100644 cmd/didweb/atproto-recommended-credentials.go create mode 100644 cmd/didweb/did.go create mode 100644 cmd/didweb/main.go create mode 100644 cmd/oidctest/main.go diff --git a/cmd/didweb/.gitignore b/cmd/didweb/.gitignore new file mode 100644 index 00000000..7fd64493 --- /dev/null +++ b/cmd/didweb/.gitignore @@ -0,0 +1,3 @@ +*.keys +did.json +atproto-did \ No newline at end of file diff --git a/cmd/didweb/README.md b/cmd/didweb/README.md new file mode 100644 index 00000000..779eb514 --- /dev/null +++ b/cmd/didweb/README.md @@ -0,0 +1,3 @@ +# didweb + +This is a heavily forked and modified version of [didweb](https://github.com/afternooncurry/bsky-did-web), but made to be much more understandable. diff --git a/cmd/didweb/atproto-recommended-credentials.go b/cmd/didweb/atproto-recommended-credentials.go new file mode 100644 index 00000000..2b870c00 --- /dev/null +++ b/cmd/didweb/atproto-recommended-credentials.go @@ -0,0 +1,52 @@ +package main + +import ( + "context" + "encoding/json" + "net/http" + + "github.com/bluesky-social/indigo/xrpc" + "github.com/whyrusleeping/go-did" + "within.website/x/web" +) + +type RecommendedCredentials struct { + AlsoKnownAs []string `json:"alsoKnownAs"` + VerificationMethods struct { + Atproto did.DID `json:"atproto"` + } `json:"verificationMethods"` + RotationKeys []string `json:"rotationKeys"` + Services struct { + AtprotoPds struct { + Type string `json:"type"` + Endpoint string `json:"endpoint"` + } `json:"atproto_pds"` + } `json:"services"` +} + +func IdentityGetRecommendedDidCredentials(ctx context.Context, cli *xrpc.Client) (*RecommendedCredentials, error) { + req, err := http.NewRequestWithContext(ctx, http.MethodGet, cli.Host+"/xrpc/com.atproto.identity.getRecommendedDidCredentials", nil) + if err != nil { + return nil, err + } + + req.Header.Add("Authorization", "Bearer "+cli.Auth.AccessJwt) + req.Header.Add("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return nil, web.NewError(http.StatusOK, resp) + } + + var result RecommendedCredentials + if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { + return nil, err + } + + return &result, nil +} diff --git a/cmd/didweb/did.go b/cmd/didweb/did.go new file mode 100644 index 00000000..62f5a6a6 --- /dev/null +++ b/cmd/didweb/did.go @@ -0,0 +1,24 @@ +package main + +import "github.com/whyrusleeping/go-did" + +type Document struct { + Context []string `json:"@context"` + Id did.DID `json:"id"` + AlsoKnownAs []string `json:"alsoKnownAs"` + VerificationMethod []*VerificationMethod `json:"verificationMethod"` + Service []*Service `json:"service"` +} + +type VerificationMethod struct { + ID string `json:"id"` + Type string `json:"type"` + Controller string `json:"controller"` + PublicKeyMultibase string `json:"publicKeyMultibase"` +} + +type Service struct { + ID did.DID `json:"id"` + Type string `json:"type"` + ServiceEndpoint string `json:"serviceEndpoint"` +} diff --git a/cmd/didweb/main.go b/cmd/didweb/main.go new file mode 100644 index 00000000..8396df53 --- /dev/null +++ b/cmd/didweb/main.go @@ -0,0 +1,359 @@ +package main + +import ( + "bufio" + "context" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "encoding/hex" + "encoding/json" + "flag" + "fmt" + "log" + "log/slog" + "net/http" + "os" + "slices" + "strings" + "time" + + "github.com/bluesky-social/indigo/api/atproto" + "github.com/bluesky-social/indigo/xrpc" + "github.com/golang-jwt/jwt/v5" + "github.com/google/uuid" + "github.com/multiformats/go-multibase" + "github.com/whyrusleeping/go-did" + "within.website/x/internal" + "within.website/x/web" +) + +var ( + curveName = flag.String("curve-name", "p256", "elliptic curve to use") + handleName = flag.String("handle-name", "", "The bluesky handle you want to use") + pdsHostname = flag.String("pds-hostname", "", "The Personal Data Server hostname for this account") +) + +func main() { + internal.HandleStartup() + + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Minute) + defer cancel() + + crv, ok := getCurve(*curveName) + if !ok { + log.Fatalf("invalid curve: %s", *curveName) + } + + if *handleName == "" { + log.Fatal("pass --handle-name") + } + + if *pdsHostname == "" { + log.Fatal("pass --pds-hostname (no scheme)") + } + + privkey, err := generateKey(crv) + if err != nil { + log.Fatalf("can't make privkey: %v", err) + } + + privkeyString := serializePrivateKey(privkey) + + pubkeyString, err := serializePublicKey(crv, privkey) + if err != nil { + log.Fatalf("can't serialize public key: %v", err) + } + + fmt.Printf("------\nFor did:web:%s:\npublic: %s\nprivate: %s\n", *handleName, pubkeyString, privkeyString) + + handleDID, err := did.ParseDID("did:web:" + *handleName) + if err != nil { + log.Fatalf("can't parse your DID: %v", err) + } + + pdsDID, err := did.ParseDID("did:web:" + *pdsHostname) + if err != nil { + log.Fatalf("can't parse PDS did: %v", err) + } + + serviceDID, err := did.ParseDID("#atproto_pds") + if err != nil { + log.Fatalf("[unexpected] can't parse service DID: %v", err) + } + + didDoc := Document{ + Context: []string{ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/multikey/v1", + "https://w3id.org/security/suites/secp256k1-2019/v1", + }, + Id: handleDID, + AlsoKnownAs: []string{"at://" + *handleName}, + VerificationMethod: []*VerificationMethod{ + { + ID: handleDID.String() + "#atproto", + Type: "Multikey", + Controller: handleDID.String(), + PublicKeyMultibase: pubkeyString, + }, + }, + Service: []*Service{ + { + ID: serviceDID, + Type: "AtprotoPersonalDataServer", + ServiceEndpoint: "https://" + *pdsHostname, + }, + }, + } + + fout, err := os.Create("did.json") + if err != nil { + log.Fatalf("can't make did.json: %v", err) + } + + enc := json.NewEncoder(fout) + enc.SetIndent("", " ") + if err := enc.Encode(didDoc); err != nil { + fout.Close() + log.Fatalf("can't encode DID doc: %v", err) + } + + if err := fout.Close(); err != nil { + log.Fatalf("can't close did.json: %v", err) + } + + fmt.Printf("upload did.json to https://%[1]s/.well-known/did.json and press enter ...\n(hint: make sure %[1]s points to where you uploaded it to!)\n", *handleName) + bufio.NewReader(os.Stdin).ReadBytes('\n') + + if err := waitUntilDIDWorks(ctx, *handleName, pubkeyString); err != nil { + log.Fatalf("%s doesn't work: %v", handleDID.String(), err) + } + + fmt.Println("DID validated!") + + if err := os.WriteFile("atproto-did", []byte(handleDID.String()), 0600); err != nil { + log.Fatalf("can't write atproto-did: %v", err) + } + + fmt.Printf("upload atproto-did to https://%s/.well-known/atproto-did in it, then press enter\n", handleDID.Value()) + bufio.NewReader(os.Stdin).ReadBytes('\n') + + cli, err := mkAccount(ctx, privkey, &handleDID, &pdsDID) + if err != nil { + log.Fatalf("can't make account: %v", err) + } + + credSuggestions, err := IdentityGetRecommendedDidCredentials(ctx, cli) + if err != nil { + fmt.Printf("access token: %s\n", cli.Auth.AccessJwt) + fmt.Println("You will need to do things manually, sorry") + log.Fatalf("can't get suggested credentials: %v", err) + } + + // give the PDS authority over the identity + didDoc.VerificationMethod[0].PublicKeyMultibase = credSuggestions.VerificationMethods.Atproto.Value() + + fout, err = os.Create("did.json") + if err != nil { + log.Fatalf("can't make did.json: %v", err) + } + + enc = json.NewEncoder(fout) + enc.SetIndent("", " ") + if err := enc.Encode(didDoc); err != nil { + fout.Close() + log.Fatalf("can't encode DID doc: %v", err) + } + + if err := fout.Close(); err != nil { + log.Fatalf("can't close did.json: %v", err) + } + + fmt.Printf("re-upload did.json to https://%[1]s/.well-known/did.json and press enter ...\n", *handleName) + bufio.NewReader(os.Stdin).ReadBytes('\n') + + if err := waitUntilDIDWorks(ctx, *handleName, credSuggestions.VerificationMethods.Atproto.Value()); err != nil { + log.Fatalf("%s doesn't work: %v", handleDID.String(), err) + } + + if err := atproto.ServerActivateAccount(ctx, cli); err != nil { + log.Fatalf("can't activate account: %v", err) + } + + fmt.Println("have fun skeeting!") +} + +func getCurve(name string) (elliptic.Curve, bool) { + switch name { + case "p256": + return elliptic.P256(), true + default: + return nil, false + } +} + +func generateKey(crv elliptic.Curve) (*ecdsa.PrivateKey, error) { + privkey, err := ecdsa.GenerateKey(crv, rand.Reader) + if err != nil { + return nil, err + } + + return privkey, nil +} + +func serializePrivateKey(privkey *ecdsa.PrivateKey) string { + return hex.EncodeToString(privkey.D.Bytes()) +} + +func serializePublicKey(crv elliptic.Curve, privkey *ecdsa.PrivateKey) (string, error) { + // varint encoded version of 0x1200, see https://atproto.com/specs/cryptography#public-key-encoding + var varintP256 = []byte{0x80, 0x24} + + b := slices.Concat(varintP256, elliptic.MarshalCompressed(crv, privkey.PublicKey.X, privkey.PublicKey.Y)) + pubkey, err := multibase.Encode(multibase.Base58BTC, b) + if err != nil { + return "", err + } + + return pubkey, nil +} + +func fetchDIDWeb(ctx context.Context, domain string) (*did.Document, error) { + req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("https://%s/.well-known/did.json", domain), nil) + if err != nil { + return nil, fmt.Errorf("can't construct request for domain %s: %w", domain, err) + } + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return nil, fmt.Errorf("can't connect to domain %s: %w", domain, err) + } + + if resp.StatusCode != http.StatusOK { + return nil, web.NewError(http.StatusOK, resp) + } + + var result did.Document + if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { + return nil, fmt.Errorf("can't decode DID document on %s: %w", domain, err) + } + + return &result, nil +} + +func waitUntilDIDWorks(ctx context.Context, domain, wantPubkey string) error { + t := time.NewTicker(time.Second) + defer t.Stop() + errCount := 0 + + for range t.C { + if errCount >= 30 { + return fmt.Errorf("gave up after %d tries", errCount) + } + + doc, err := fetchDIDWeb(ctx, domain) + if err != nil { + errCount++ + slog.Error("can't load did doc", "domain", domain, "err", err) + continue + } + + var multiKey *did.VerificationMethod + for _, vm := range doc.VerificationMethod { + if vm.Type == "Multikey" { + multiKey = &vm + } + } + + if multiKey == nil { + return fmt.Errorf("invalid DID, need Multikey verification method") + } + + if theirKey := *multiKey.PublicKeyMultibase; theirKey != wantPubkey { + return fmt.Errorf("wrong public key: want %s, got %s", wantPubkey, theirKey) + } + + return nil + } + + return fmt.Errorf("how did you get here?") +} + +func makeJWTFor(privkey *ecdsa.PrivateKey, lxm, aud, iss string, exp time.Duration) (string, error) { + type myClaims struct { + jwt.RegisteredClaims + Lexicon string `json:"lxm"` // Atproto XRPC lexicon method for the scope of this JWT + } + + jwt.MarshalSingleStringAsArray = false + claims := myClaims{ + Lexicon: lxm, + RegisteredClaims: jwt.RegisteredClaims{ + Issuer: iss, + Audience: jwt.ClaimStrings{aud}, + ExpiresAt: jwt.NewNumericDate(time.Now().Add(exp)), + IssuedAt: jwt.NewNumericDate(time.Now()), + ID: uuid.NewString(), + }, + } + + token := jwt.NewWithClaims(jwt.SigningMethodES256, claims) + tokenString, err := token.SignedString(privkey) + if err != nil { + return "", err + } + + return tokenString, nil +} + +func mkAccount(ctx context.Context, privkey *ecdsa.PrivateKey, handle, pds *did.DID) (*xrpc.Client, error) { + didJWT, err := makeJWTFor(privkey, "com.atproto.server.createAccount", pds.String(), handle.String(), 180*time.Second) + if err != nil { + return nil, err + } + + cli := &xrpc.Client{ + Auth: &xrpc.AuthInfo{ + AccessJwt: didJWT, + Handle: handle.Value(), + Did: handle.String(), + }, + Host: "https://" + pds.Value(), + } + + fmt.Printf("hint: generate an invite code with:\n$ sudo pdsadmin create-invite-code\n\n") + + inviteCode := input("PDS invite code") + email := input("email") + password := input("password") + + inp := &atproto.ServerCreateAccount_Input{ + Did: &[]string{handle.String()}[0], + Email: &email, + Handle: handle.Value(), + InviteCode: &inviteCode, + Password: &password, + } + + resp, err := atproto.ServerCreateAccount(ctx, cli, inp) + if err != nil { + return nil, err + } + + cli.Auth.AccessJwt = resp.AccessJwt + cli.Auth.RefreshJwt = resp.RefreshJwt + cli.Auth.Did = resp.Did + cli.Auth.Handle = resp.Handle + + return cli, nil +} + +func input(prompt string) string { + fmt.Printf("%s> ", prompt) + text, err := bufio.NewReader(os.Stdin).ReadString('\n') + if err != nil { + panic(err) + } + return strings.TrimSpace(text) +} diff --git a/cmd/oidctest/main.go b/cmd/oidctest/main.go new file mode 100644 index 00000000..654bd255 --- /dev/null +++ b/cmd/oidctest/main.go @@ -0,0 +1,140 @@ +/* +This is an example application to demonstrate querying the user info endpoint. +*/ +package main + +import ( + "crypto/rand" + "encoding/base64" + "encoding/json" + "flag" + "io" + "log" + "net/http" + "time" + + "github.com/coreos/go-oidc/v3/oidc" + "golang.org/x/net/context" + "golang.org/x/oauth2" + "within.website/x/internal" +) + +var ( + clientID = flag.String("oauth2-client-id", "", "OAuth2 Client ID") + clientSecret = flag.String("oauth2-client-secret", "", "OAuth2 Client Secret") + idpURL = flag.String("oauth2-idp-url", "https://idp.xeserv.us", "OAuth2 IDP URL") +) + +func randString(nByte int) (string, error) { + b := make([]byte, nByte) + if _, err := io.ReadFull(rand.Reader, b); err != nil { + return "", err + } + return base64.RawURLEncoding.EncodeToString(b), nil +} + +func setCallbackCookie(w http.ResponseWriter, r *http.Request, name, value string) { + c := &http.Cookie{ + Name: name, + Value: value, + MaxAge: int(time.Hour.Seconds()), + Secure: r.TLS != nil, + HttpOnly: true, + } + http.SetCookie(w, c) +} + +func main() { + internal.HandleStartup() + + ctx := context.Background() + + provider, err := oidc.NewProvider(ctx, *idpURL) + if err != nil { + log.Fatal(err) + } + verifier := provider.Verifier(&oidc.Config{ClientID: *clientID}) + + config := oauth2.Config{ + ClientID: *clientID, + ClientSecret: *clientSecret, + Endpoint: provider.Endpoint(), + RedirectURL: "http://127.0.0.1:5556/auth/callback", + Scopes: []string{oidc.ScopeOpenID, "profile", "email", "groups"}, + } + + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + state, err := randString(16) + if err != nil { + http.Error(w, "Internal error", http.StatusInternalServerError) + return + } + setCallbackCookie(w, r, "state", state) + + http.Redirect(w, r, config.AuthCodeURL(state), http.StatusFound) + }) + + http.HandleFunc("/auth/callback", func(w http.ResponseWriter, r *http.Request) { + state, err := r.Cookie("state") + if err != nil { + http.Error(w, "state not found", http.StatusBadRequest) + return + } + if r.URL.Query().Get("state") != state.Value { + http.Error(w, "state did not match", http.StatusBadRequest) + return + } + + oauth2Token, err := config.Exchange(ctx, r.URL.Query().Get("code")) + if err != nil { + http.Error(w, "Failed to exchange token: "+err.Error(), http.StatusInternalServerError) + return + } + + var extraClaims any = nil + + rawIDToken, ok := oauth2Token.Extra("id_token").(string) + if ok { + idToken, err := verifier.Verify(ctx, rawIDToken) + if err != nil { + http.Error(w, "Failed to verify id_token: "+err.Error(), http.StatusInternalServerError) + return + } + + var claims struct { + Email string `json:"email"` + Verified bool `json:"email_verified"` + Name string `json:"name"` + PreferredUsername string `json:"preferred_username"` + Groups []string `json:"groups"` + } + + if err := idToken.Claims(&claims); err != nil { + http.Error(w, "Failed to unmarshal token claims: "+err.Error(), http.StatusInternalServerError) + } + + extraClaims = claims + } + + userInfo, err := provider.UserInfo(ctx, oauth2.StaticTokenSource(oauth2Token)) + if err != nil { + http.Error(w, "Failed to get userinfo: "+err.Error(), http.StatusInternalServerError) + return + } + + resp := struct { + OAuth2Token *oauth2.Token + UserInfo *oidc.UserInfo + ExtraClaims any + }{oauth2Token, userInfo, extraClaims} + data, err := json.MarshalIndent(resp, "", " ") + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + w.Write(data) + }) + + log.Printf("listening on http://%s/", "127.0.0.1:5556") + log.Fatal(http.ListenAndServe("127.0.0.1:5556", nil)) +} diff --git a/go.mod b/go.mod index 9b1671bc..10d8ee5e 100644 --- a/go.mod +++ b/go.mod @@ -19,6 +19,7 @@ require ( github.com/bwmarrin/discordgo v0.28.1 github.com/c-bata/go-prompt v0.2.6 github.com/cenkalti/backoff/v4 v4.3.0 + github.com/coreos/go-oidc/v3 v3.12.0 github.com/danrusei/gobot-bsky v0.1.0 github.com/disintegration/imaging v1.6.2 github.com/dop251/goja v0.0.0-20230531210528-d7324b2d74f7 @@ -31,6 +32,7 @@ require ( github.com/go-gorm/caches/v4 v4.0.5 github.com/go-interpreter/wagon v0.6.0 github.com/goccy/go-json v0.10.2 + github.com/golang-jwt/jwt/v5 v5.2.1 github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 github.com/google/go-github v17.0.0+incompatible github.com/google/subcommands v1.2.0 @@ -43,6 +45,7 @@ require ( github.com/kr/pretty v0.3.1 github.com/lib/pq v1.10.9 github.com/mattn/go-sqlite3 v1.14.22 + github.com/multiformats/go-multibase v0.2.0 github.com/mymmrac/telego v0.29.2 github.com/nats-io/nats.go v1.38.0 github.com/ncruces/go-sqlite3 v0.16.0 @@ -65,12 +68,15 @@ require ( github.com/thoj/go-ircevent v0.0.0-20210723090443-73e444401d64 github.com/tmc/scp v0.0.0-20170824174625-f7b48647feef github.com/twitchtv/twirp v8.1.3+incompatible + github.com/whyrusleeping/cbor-gen v0.1.3-0.20240904181319-8dc02b38228c + github.com/whyrusleeping/go-did v0.0.0-20230824162731-404d1707d5d6 go.etcd.io/bbolt v1.3.10 go.jetpack.io/tyson v0.1.1 go4.org v0.0.0-20190313082347-94abd6928b1d golang.org/x/crypto v0.31.0 golang.org/x/oauth2 v0.21.0 golang.org/x/sync v0.10.0 + golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9 google.golang.org/grpc v1.64.1 gorm.io/gorm v1.25.10 gorm.io/plugin/prometheus v0.1.0 @@ -100,6 +106,7 @@ require ( github.com/cli/go-gh v0.1.0 // indirect github.com/cloudflare/circl v1.3.8 // indirect github.com/cyphar/filepath-securejoin v0.2.5 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/ebitengine/purego v0.7.1 // indirect github.com/emirpasic/gods v1.18.1 // indirect @@ -110,6 +117,7 @@ require ( github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-git/go-billy/v5 v5.6.0 // indirect github.com/go-git/go-git/v5 v5.13.0 // indirect + github.com/go-jose/go-jose/v4 v4.0.2 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect @@ -148,6 +156,12 @@ require ( github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/klauspost/cpuid/v2 v2.2.7 // indirect github.com/klauspost/pgzip v1.2.6 // indirect + github.com/lestrrat-go/blackmagic v1.0.1 // indirect + github.com/lestrrat-go/httpcc v1.0.1 // indirect + github.com/lestrrat-go/httprc v1.0.4 // indirect + github.com/lestrrat-go/iter v1.0.2 // indirect + github.com/lestrrat-go/jwx/v2 v2.0.12 // indirect + github.com/lestrrat-go/option v1.0.1 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-tty v0.0.3 // indirect @@ -158,7 +172,6 @@ require ( github.com/mr-tron/base58 v1.2.0 // indirect github.com/multiformats/go-base32 v0.1.0 // indirect github.com/multiformats/go-base36 v0.2.0 // indirect - github.com/multiformats/go-multibase v0.2.0 // indirect github.com/multiformats/go-multicodec v0.9.0 // indirect github.com/multiformats/go-multihash v0.2.3 // indirect github.com/multiformats/go-varint v0.0.7 // indirect @@ -172,6 +185,7 @@ require ( github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f // indirect github.com/savsgio/gotils v0.0.0-20240303185622-093b76447511 // indirect + github.com/segmentio/asm v1.2.0 // indirect github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect github.com/shopspring/decimal v1.3.1 // indirect github.com/skeema/knownhosts v1.3.0 // indirect @@ -184,7 +198,6 @@ require ( github.com/valyala/fasthttp v1.52.0 // indirect github.com/valyala/fastjson v1.6.4 // indirect github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11 // indirect - github.com/whyrusleeping/cbor-gen v0.1.3-0.20240904181319-8dc02b38228c // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect gitlab.com/digitalxero/go-conventional-commit v1.0.7 // indirect gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b // indirect @@ -197,7 +210,6 @@ require ( go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect golang.org/x/arch v0.6.0 // indirect - golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240617180043-68d350f18fd4 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect @@ -247,7 +259,7 @@ require ( golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 golang.org/x/image v0.18.0 golang.org/x/mod v0.20.0 // indirect - golang.org/x/net v0.33.0 // indirect + golang.org/x/net v0.33.0 golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect golang.org/x/time v0.5.0 diff --git a/go.sum b/go.sum index 1f53c0f8..d5df88c6 100644 --- a/go.sum +++ b/go.sum @@ -218,6 +218,8 @@ github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/coreos/go-oidc/v3 v3.12.0 h1:sJk+8G2qq94rDI6ehZ71Bol3oUHy63qNYmkiSjrc/Jo= +github.com/coreos/go-oidc/v3 v3.12.0/go.mod h1:gE3LgjOgFoHi9a4ce4/tJczr0Ai2/BoDhf0r5lltWI0= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyphar/filepath-securejoin v0.2.5 h1:6iR5tXJ/e6tJZzzdMc1km3Sa7RRIVBKAK32O2s7AYfo= @@ -228,6 +230,9 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c= @@ -306,6 +311,8 @@ github.com/go-gorm/caches/v4 v4.0.5 h1:Sdj9vxbEM0sCmv5+s5o6GzoVMuraWF0bjJJvUU+7c github.com/go-gorm/caches/v4 v4.0.5/go.mod h1:Ms8LnWVoW4GkTofpDzFH8OfDGNTjLxQDyxBmRN67Ujw= github.com/go-interpreter/wagon v0.6.0 h1:BBxDxjiJiHgw9EdkYXAWs8NHhwnazZ5P2EWBW5hFNWw= github.com/go-interpreter/wagon v0.6.0/go.mod h1:5+b/MBYkclRZngKF5s6qrgWxSLgE9F5dFdO1hAueZLc= +github.com/go-jose/go-jose/v4 v4.0.2 h1:R3l3kkBds16bO7ZFAEEcofK0MkrAJt3jlJznWZG0nvk= +github.com/go-jose/go-jose/v4 v4.0.2/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= @@ -343,6 +350,8 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo= github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= +github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -592,6 +601,19 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= +github.com/lestrrat-go/blackmagic v1.0.1 h1:lS5Zts+5HIC/8og6cGHb0uCcNCa3OUt1ygh3Qz2Fe80= +github.com/lestrrat-go/blackmagic v1.0.1/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU= +github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE= +github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E= +github.com/lestrrat-go/httprc v1.0.4 h1:bAZymwoZQb+Oq8MEbyipag7iSq6YIga8Wj6GOiJGdI8= +github.com/lestrrat-go/httprc v1.0.4/go.mod h1:mwwz3JMTPBjHUkkDv/IGJ39aALInZLrhBp0X7KGUZlo= +github.com/lestrrat-go/iter v1.0.2 h1:gMXo1q4c2pHmC3dn8LzRhJfP1ceCbgSiT9lUydIzltI= +github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4= +github.com/lestrrat-go/jwx/v2 v2.0.12 h1:3d589+5w/b9b7S3DneICPW16AqTyYXB7VRjgluSDWeA= +github.com/lestrrat-go/jwx/v2 v2.0.12/go.mod h1:Mq4KN1mM7bp+5z/W5HS8aCNs5RKZ911G/0y2qUjAQuQ= +github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= +github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU= +github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= @@ -771,6 +793,8 @@ github.com/savsgio/gotils v0.0.0-20240303185622-093b76447511 h1:KanIMPX0QdEdB4R3 github.com/savsgio/gotils v0.0.0-20240303185622-093b76447511/go.mod h1:sM7Mt7uEoCeFSCBM+qBrqvEo+/9vdmj19wzp3yzUhmg= github.com/sebest/xff v0.0.0-20210106013422-671bd2870b3a h1:iLcLb5Fwwz7g/DLK89F+uQBDeAhHhwdzB5fSlVdhGcM= github.com/sebest/xff v0.0.0-20210106013422-671bd2870b3a/go.mod h1:wozgYq9WEBQBaIJe4YZ0qTSFAMxmcwBhQH0fO0R34Z0= +github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys= +github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs= github.com/sendgrid/rest v2.6.9+incompatible h1:1EyIcsNdn9KIisLW50MKwmSRSK+ekueiEMJ7NEoxJo0= github.com/sendgrid/rest v2.6.9+incompatible/go.mod h1:kXX7q3jZtJXK5c5qK83bSGMdV6tsOE70KbHoqJls4lE= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= @@ -853,6 +877,8 @@ github.com/whyrusleeping/cbor-gen v0.1.3-0.20240904181319-8dc02b38228c h1:UsxJNc github.com/whyrusleeping/cbor-gen v0.1.3-0.20240904181319-8dc02b38228c/go.mod h1:pM99HXyEbSQHcosHc0iW7YFmwnscr+t9Te4ibko05so= github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f h1:jQa4QT2UP9WYv2nzyawpKMOCl+Z/jW7djv2/J50lj9E= github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f/go.mod h1:p9UJB6dDgdPgMJZs7UjUOdulKyRr9fqkS+6JKAInPy8= +github.com/whyrusleeping/go-did v0.0.0-20230824162731-404d1707d5d6 h1:yJ9/LwIGIk/c0CdoavpC9RNSGSruIspSZtxG3Nnldic= +github.com/whyrusleeping/go-did v0.0.0-20230824162731-404d1707d5d6/go.mod h1:39U9RRVr4CKbXpXYopWn+FSH5s+vWu6+RmguSPWAq5s= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/xhit/go-str2duration v1.2.0/go.mod h1:3cPSlfZlUHVlneIVfePFWcJZsuwf+P1v2SRTV4cUmp4= @@ -924,6 +950,7 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1164,6 +1191,7 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1179,6 +1207,7 @@ golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= diff --git a/kube/alrest/uptime-kuma/ingress.yaml b/kube/alrest/uptime-kuma/ingress.yaml index 713431cb..8e9b2848 100644 --- a/kube/alrest/uptime-kuma/ingress.yaml +++ b/kube/alrest/uptime-kuma/ingress.yaml @@ -22,6 +22,27 @@ spec: port: number: 80 - path: /status + pathType: Prefix + backend: + service: + name: uptime-kuma + port: + number: 3001 + - path: /assets + pathType: Prefix + backend: + service: + name: uptime-kuma + port: + number: 3001 + - path: /icon.svg + pathType: Prefix + backend: + service: + name: uptime-kuma + port: + number: 3001 + - path: /api/status-page/heartbeat pathType: Prefix backend: service: