pico
created pr with
84.1
added 84.2
1: 659964e ! 1: af4cda9 feat: access control using ssh certs
-: ------- > 2: d9a74df chore: logging and cleanup
added 84.3
1: af4cda9 < -: ------- feat: access control using ssh certs
2: d9a74df ! 1: bb8ef88 feat: access control using ssh certs
cmds
checkout latest patchset:
ssh pr.pico.sh print 84 | git am -3checkout any patchset in a patch request:
ssh pr.pico.sh print 84.[rev] | git am -3add changes to patch request:
git format-patch main --stdout | ssh pr.pico.sh pr add 84
Patchset
84.1
feat: access control using ssh certs
Eric Bower
2025-12-01T05:17:10ZSemantic diff summary
0 added,
15 modified,
1 signature changed,
0 removed
across 9 analyzed files
(2 files skipped: unsupported file type)
+2
-1
Makefile
#
| ... | ... | @@ -142,10 +142,11 @@ migrate: | |
| 142 | 142 | $(DOCKER_CMD) exec -i $(DB_CONTAINER) psql -U $(PGUSER) -d $(PGDATABASE) < ./sql/migrations/20250320_add_tunnel_id_to_tuns_event_logs_table.sql | |
| 143 | 143 | $(DOCKER_CMD) exec -i $(DB_CONTAINER) psql -U $(PGUSER) -d $(PGDATABASE) < ./sql/migrations/20250410_add_index_analytics_visits_host_list.sql | |
| 144 | 144 | $(DOCKER_CMD) exec -i $(DB_CONTAINER) psql -U $(PGUSER) -d $(PGDATABASE) < ./sql/migrations/20250418_add_project_post_idx_analytics.sql | |
| 145 | + | $(DOCKER_CMD) exec -i $(DB_CONTAINER) psql -U $(PGUSER) -d $(PGDATABASE) < ./sql/migrations/20251130_add_expires_at_to_public_keys.sql | |
| 145 | 146 | .PHONY: migrate | |
| 146 | 147 | ||
| 147 | 148 | latest: | |
| 148 | - | $(DOCKER_CMD) exec -i $(DB_CONTAINER) psql -U $(PGUSER) -d $(PGDATABASE) < ./sql/migrations/20250418_add_project_post_idx_analytics.sql | |
| 149 | + | $(DOCKER_CMD) exec -i $(DB_CONTAINER) psql -U $(PGUSER) -d $(PGDATABASE) < ./sql/migrations/20251130_add_expires_at_to_public_keys.sql | |
| 149 | 150 | .PHONY: latest | |
| 150 | 151 | ||
| 151 | 152 | psql: |
+1
-1
pkg/apps/feeds/ssh.go
#
| ... | ... | @@ -46,7 +46,7 @@ func StartSshServer() { | |
| 46 | 46 | } | |
| 47 | 47 | handler := filehandlers.NewFileHandlerRouter(cfg, dbh, fileMap) | |
| 48 | 48 | ||
| 49 | - | sshAuth := shared.NewSshAuthHandler(dbh, logger) | |
| 49 | + | sshAuth := shared.NewSshAuthHandler(dbh, logger, "feeds") | |
| 50 | 50 | ||
| 51 | 51 | // Create a new SSH server | |
| 52 | 52 | server, err := pssh.NewSSHServerWithConfig( |
+1
-1
pkg/apps/pastes/ssh.go
#
| ... | ... | @@ -45,7 +45,7 @@ func StartSshServer() { | |
| 45 | 45 | "fallback": filehandlers.NewScpPostHandler(dbh, cfg, hooks), | |
| 46 | 46 | } | |
| 47 | 47 | handler := filehandlers.NewFileHandlerRouter(cfg, dbh, fileMap) | |
| 48 | - | sshAuth := shared.NewSshAuthHandler(dbh, logger) | |
| 48 | + | sshAuth := shared.NewSshAuthHandler(dbh, logger, "pastes") | |
| 49 | 49 | ||
| 50 | 50 | // Create a new SSH server | |
| 51 | 51 | server, err := pssh.NewSSHServerWithConfig( |
+1
-1
pkg/apps/pgs/ssh.go
#
+1
-1
pkg/apps/pico/ssh.go
#
+1
-1
pkg/apps/pipe/ssh.go
#
| ... | ... | @@ -46,7 +46,7 @@ func StartSshServer() { | |
| 46 | 46 | Access: syncmap.New[string, []string](), | |
| 47 | 47 | } | |
| 48 | 48 | ||
| 49 | - | sshAuth := shared.NewSshAuthHandler(dbh, logger) | |
| 49 | + | sshAuth := shared.NewSshAuthHandler(dbh, logger, "pipe") | |
| 50 | 50 | ||
| 51 | 51 | // Create a new SSH server | |
| 52 | 52 | server, err := pssh.NewSSHServerWithConfig( |
+1
-1
pkg/apps/prose/ssh.go
#
| ... | ... | @@ -59,7 +59,7 @@ func StartSshServer() { | |
| 59 | 59 | } | |
| 60 | 60 | handler := filehandlers.NewFileHandlerRouter(cfg, dbh, fileMap) | |
| 61 | 61 | ||
| 62 | - | sshAuth := shared.NewSshAuthHandler(dbh, logger) | |
| 62 | + | sshAuth := shared.NewSshAuthHandler(dbh, logger, "prose") | |
| 63 | 63 | ||
| 64 | 64 | // Create a new SSH server | |
| 65 | 65 | server, err := pssh.NewSSHServerWithConfig( |
+9
-0
pkg/db/db.go
#
| ... | ... | @@ -36,6 +36,15 @@ type PublicKey struct { | |
| 36 | 36 | Name string `json:"name" db:"name"` | |
| 37 | 37 | Key string `json:"public_key" db:"public_key"` | |
| 38 | 38 | CreatedAt *time.Time `json:"created_at" db:"created_at"` | |
| 39 | + | ExpiresAt *time.Time `json:"expires_at" db:"expires_at"` | |
| 40 | + | } | |
| 41 | + | ||
| 42 | + | func (pk *PublicKey) IsValid() bool { | |
| 43 | + | if pk.ExpiresAt == nil { | |
| 44 | + | return true | |
| 45 | + | } | |
| 46 | + | now := time.Now() | |
| 47 | + | return pk.ExpiresAt.After(now) | |
| 39 | 48 | } | |
| 40 | 49 | ||
| 41 | 50 | type User struct { |
+7
-7
pkg/db/postgres/storage.go
#
| ... | ... | @@ -135,11 +135,11 @@ var ( | |
| 135 | 135 | ) | |
| 136 | 136 | ||
| 137 | 137 | const ( | |
| 138 | - | sqlSelectPublicKey = `SELECT id, user_id, name, public_key, created_at FROM public_keys WHERE public_key = $1` | |
| 139 | - | sqlSelectPublicKeys = `SELECT id, user_id, name, public_key, created_at FROM public_keys WHERE user_id = $1 ORDER BY created_at ASC` | |
| 138 | + | sqlSelectPublicKey = `SELECT id, user_id, name, public_key, created_at, expires_at FROM public_keys WHERE public_key = $1` | |
| 139 | + | sqlSelectPublicKeys = `SELECT id, user_id, name, public_key, created_at, expires_at FROM public_keys WHERE user_id = $1 ORDER BY created_at ASC` | |
| 140 | 140 | sqlSelectUser = `SELECT id, name, created_at FROM app_users WHERE id = $1` | |
| 141 | 141 | sqlSelectUserForName = `SELECT id, name, created_at FROM app_users WHERE name = $1` | |
| 142 | - | sqlSelectUserForNameAndKey = `SELECT app_users.id, app_users.name, app_users.created_at, public_keys.id as pk_id, public_keys.public_key, public_keys.created_at as pk_created_at FROM app_users LEFT JOIN public_keys ON public_keys.user_id = app_users.id WHERE app_users.name = $1 AND public_keys.public_key = $2` | |
| 142 | + | sqlSelectUserForNameAndKey = `SELECT app_users.id, app_users.name, app_users.created_at, public_keys.id as pk_id, public_keys.public_key, public_keys.created_at as pk_created_at, public_keys.expires_at FROM app_users LEFT JOIN public_keys ON public_keys.user_id = app_users.id WHERE app_users.name = $1 AND public_keys.public_key = $2` | |
| 143 | 143 | sqlSelectUsers = `SELECT id, name, created_at FROM app_users ORDER BY name ASC` | |
| 144 | 144 | ||
| 145 | 145 | sqlSelectUserForToken = ` |
| ... | ... | @@ -450,7 +450,7 @@ func (me *PsqlDB) FindPublicKeyForKey(key string) (*db.PublicKey, error) { | |
| 450 | 450 | ||
| 451 | 451 | for rs.Next() { | |
| 452 | 452 | pk := &db.PublicKey{} | |
| 453 | - | err := rs.Scan(&pk.ID, &pk.UserID, &pk.Name, &pk.Key, &pk.CreatedAt) | |
| 453 | + | err := rs.Scan(&pk.ID, &pk.UserID, &pk.Name, &pk.Key, &pk.CreatedAt, &pk.ExpiresAt) | |
| 454 | 454 | if err != nil { | |
| 455 | 455 | return nil, err | |
| 456 | 456 | } |
| ... | ... | @@ -486,7 +486,7 @@ func (me *PsqlDB) FindPublicKey(pubkeyID string) (*db.PublicKey, error) { | |
| 486 | 486 | ||
| 487 | 487 | for rs.Next() { | |
| 488 | 488 | pk := &db.PublicKey{} | |
| 489 | - | err := rs.Scan(&pk.ID, &pk.UserID, &pk.Name, &pk.Key, &pk.CreatedAt) | |
| 489 | + | err := rs.Scan(&pk.ID, &pk.UserID, &pk.Name, &pk.Key, &pk.CreatedAt, &pk.ExpiresAt) | |
| 490 | 490 | if err != nil { | |
| 491 | 491 | return nil, err | |
| 492 | 492 | } |
| ... | ... | @@ -513,7 +513,7 @@ func (me *PsqlDB) FindKeysForUser(user *db.User) ([]*db.PublicKey, error) { | |
| 513 | 513 | } | |
| 514 | 514 | for rs.Next() { | |
| 515 | 515 | pk := &db.PublicKey{} | |
| 516 | - | err := rs.Scan(&pk.ID, &pk.UserID, &pk.Name, &pk.Key, &pk.CreatedAt) | |
| 516 | + | err := rs.Scan(&pk.ID, &pk.UserID, &pk.Name, &pk.Key, &pk.CreatedAt, &pk.ExpiresAt) | |
| 517 | 517 | if err != nil { | |
| 518 | 518 | return keys, err | |
| 519 | 519 | } |
| ... | ... | @@ -678,7 +678,7 @@ func (me *PsqlDB) FindUserForNameAndKey(name string, key string) (*db.User, erro | |
| 678 | 678 | pk := &db.PublicKey{} | |
| 679 | 679 | ||
| 680 | 680 | r := me.Db.QueryRow(sqlSelectUserForNameAndKey, strings.ToLower(name), key) | |
| 681 | - | err := r.Scan(&user.ID, &user.Name, &user.CreatedAt, &pk.ID, &pk.Key, &pk.CreatedAt) | |
| 681 | + | err := r.Scan(&user.ID, &user.Name, &user.CreatedAt, &pk.ID, &pk.Key, &pk.CreatedAt, &pk.ExpiresAt) | |
| 682 | 682 | if err != nil { | |
| 683 | 683 | return nil, err | |
| 684 | 684 | } |