pico
created pr with
90.1
cmds
checkout latest patchset:
ssh pr.pico.sh print 90 | git am -3checkout any patchset in a patch request:
ssh pr.pico.sh print 90.[rev] | git am -3add changes to patch request:
git format-patch main --stdout | ssh pr.pico.sh pr add 90
Patchset
90.1
feat(auth): authenticate key handler using ssh cert
Eric Bower
2025-12-14T01:49:35ZSemantic diff summary
1 added,
4 modified,
0 signature changed,
0 removed
across 3 analyzed files
+22
-5
pkg/apps/auth/api.go
#
| ... | ... | @@ -245,22 +246,38 @@ func keyHandler(apiConfig *shared.ApiConfig) http.HandlerFunc { | |
| 245 | 246 | ||
| 246 | 247 | space := r.URL.Query().Get("space") | |
| 247 | 248 | ||
| 248 | - | apiConfig.Cfg.Logger.Info( | |
| 249 | - | "handle key", | |
| 249 | + | log := apiConfig.Cfg.Logger.With( | |
| 250 | 250 | "remoteAddress", data.RemoteAddress, | |
| 251 | 251 | "user", data.Username, | |
| 252 | 252 | "space", space, | |
| 253 | 253 | "publicKey", data.PublicKey, | |
| 254 | 254 | ) | |
| 255 | 255 | ||
| 256 | - | user, err := apiConfig.Dbpool.FindUserForKey(data.Username, data.PublicKey) | |
| 256 | + | log.Info("handle key") | |
| 257 | + | ||
| 258 | + | key, _, _, _, err := ssh.ParseAuthorizedKey([]byte(data.PublicKey)) | |
| 257 | 259 | if err != nil { | |
| 258 | - | apiConfig.Cfg.Logger.Error(err.Error()) | |
| 260 | + | log.Error("parse authorized key", "err", err) | |
| 261 | + | http.Error(w, err.Error(), http.StatusBadRequest) | |
| 262 | + | return | |
| 263 | + | } | |
| 264 | + | ||
| 265 | + | pubkey, err := shared.PubkeyCertVerify(key, space) | |
| 266 | + | if err != nil { | |
| 267 | + | log.Error("pubkey cert verify", "err", err) | |
| 268 | + | http.Error(w, err.Error(), http.StatusBadRequest) | |
| 269 | + | return | |
| 270 | + | } | |
| 271 | + | ||
| 272 | + | user, err := apiConfig.Dbpool.FindUserForKey(data.Username, pubkey) | |
| 273 | + | if err != nil { | |
| 274 | + | log.Error("find user for key", "err", err) | |
| 259 | 275 | w.WriteHeader(http.StatusUnauthorized) | |
| 260 | 276 | return | |
| 261 | 277 | } | |
| 262 | 278 | ||
| 263 | 279 | if !apiConfig.HasPlusOrSpace(user, space) { | |
| 280 | + | log.Error("key handler unauthorized") | |
| 264 | 281 | w.WriteHeader(http.StatusUnauthorized) | |
| 265 | 282 | return | |
| 266 | 283 | } |
| ... | ... | @@ -274,7 +291,7 @@ func keyHandler(apiConfig *shared.ApiConfig) http.HandlerFunc { | |
| 274 | 291 | w.WriteHeader(http.StatusOK) | |
| 275 | 292 | err = json.NewEncoder(w).Encode(user) | |
| 276 | 293 | if err != nil { | |
| 277 | - | apiConfig.Cfg.Logger.Error(err.Error()) | |
| 294 | + | log.Error("json encode", "err", err) | |
| 278 | 295 | http.Error(w, err.Error(), http.StatusInternalServerError) | |
| 279 | 296 | } | |
| 280 | 297 | } |
+1
-1
pkg/apps/auth/api_test.go
#
| ... | ... | @@ -97,7 +97,7 @@ func TestKey(t *testing.T) { | |
| 97 | 97 | ||
| 98 | 98 | data := sishData{ | |
| 99 | 99 | Username: testUsername, | |
| 100 | - | PublicKey: "zzz", | |
| 100 | + | PublicKey: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFxVPgEqtWOa5l0QHZV6TQKhV+l46SAXU07c9RuHlGka test@pico", | |
| 101 | 101 | } | |
| 102 | 102 | jso, err := json.Marshal(data) | |
| 103 | 103 | bail(err) |