Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# ssh-sync-server

SSH Sync Server
SSH Sync Server is a companion to [ssh-sync](https://github.com/therealpaulgg/ssh-sync), which allows syncing SSH configurations and keys between machines.

## Features

- Secure storage of SSH keys and configs
- JWT authentication for secure communication
- Syncing of SSH config files between machines
- Syncing of SSH key files between machines
- Syncing of known_hosts files for consistent host verification
27 changes: 24 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module github.com/therealpaulgg/ssh-sync-server

go 1.23
go 1.23.0

toolchain go1.24.1

require (
Expand Down Expand Up @@ -29,11 +30,11 @@ require (
github.com/lestrrat-go/jwx/v2 v2.0.21
github.com/lestrrat-go/option v1.0.1 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/samber/do v1.5.1
github.com/samber/lo v1.37.0
github.com/sethvargo/go-diceware v0.3.0
github.com/therealpaulgg/ssh-sync v0.3.0
github.com/therealpaulgg/ssh-sync v1.1.2
golang.org/x/crypto v0.35.0 // indirect
golang.org/x/exp v0.0.0-20230111222715-75897c7a292a // indirect
golang.org/x/sync v0.11.0 // indirect
Expand All @@ -46,9 +47,29 @@ require (
)

require (
github.com/atotto/clipboard v0.1.4 // indirect
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/charmbracelet/bubbles v0.20.0 // indirect
github.com/charmbracelet/bubbletea v1.1.0 // indirect
github.com/charmbracelet/lipgloss v0.13.1 // indirect
github.com/charmbracelet/x/ansi v0.3.2 // indirect
github.com/charmbracelet/x/term v0.2.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
github.com/kr/text v0.2.0 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/mattn/go-localereader v0.0.1 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
github.com/muesli/cancelreader v0.2.2 // indirect
github.com/muesli/termenv v0.15.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sahilm/fuzzy v0.1.1 // indirect
github.com/segmentio/asm v1.2.0 // indirect
github.com/urfave/cli/v2 v2.23.7 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
50 changes: 47 additions & 3 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,12 +1,30 @@
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
github.com/charmbracelet/bubbles v0.20.0 h1:jSZu6qD8cRQ6k9OMfR1WlM+ruM8fkPWkHvQWD9LIutE=
github.com/charmbracelet/bubbles v0.20.0/go.mod h1:39slydyswPy+uVOHZ5x/GjwVAFkCsV8IIVy+4MhzwwU=
github.com/charmbracelet/bubbletea v1.1.0 h1:FjAl9eAL3HBCHenhz/ZPjkKdScmaS5SK69JAK2YJK9c=
github.com/charmbracelet/bubbletea v1.1.0/go.mod h1:9Ogk0HrdbHolIKHdjfFpyXJmiCzGwy+FesYkZr7hYU4=
github.com/charmbracelet/lipgloss v0.13.1 h1:Oik/oqDTMVA01GetT4JdEC033dNzWoQHdWnHnQmXE2A=
github.com/charmbracelet/lipgloss v0.13.1/go.mod h1:zaYVJ2xKSKEnTEEbX6uAHabh2d975RJ+0yfkFpRBz5U=
github.com/charmbracelet/x/ansi v0.3.2 h1:wsEwgAN+C9U06l9dCVMX0/L3x7ptvY1qmjMwyfE6USY=
github.com/charmbracelet/x/ansi v0.3.2/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw=
github.com/charmbracelet/x/term v0.2.0 h1:cNB9Ot9q8I711MyZ7myUR5HFWL/lc3OpU8jZ4hwm0x0=
github.com/charmbracelet/x/term v0.2.0/go.mod h1:GVxgxAbjUrmpvIINHIQnJJKpMlHiZ4cktEQCN6GWyF0=
github.com/cockroachdb/cockroach-go/v2 v2.2.0 h1:/5znzg5n373N/3ESjHF5SMLxiW4RKB05Ql//KWfeTFs=
github.com/cockroachdb/cockroach-go/v2 v2.2.0/go.mod h1:u3MiKYGupPPjkn3ozknpMUpxPaNLTFWAya419/zv6eI=
github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
github.com/georgysavva/scany/v2 v2.0.0 h1:RGXqxDv4row7/FYoK8MRXAZXqoWF/NM+NP0q50k3DKU=
github.com/georgysavva/scany/v2 v2.0.0/go.mod h1:sigOdh+0qb/+aOs3TVhehVT10p8qJL7K/Zhyz8vWo38=
github.com/go-chi/chi v1.5.4 h1:QHdzF2szwjqVV4wmByUnTcsbIg7UGaQ0tPF2t5GcAIs=
Expand Down Expand Up @@ -54,19 +72,39 @@ github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNB
github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
github.com/lib/pq v1.10.0 h1:Zx5DJFEYQXio93kgXnQ09fXNiUKsqv4OUEu2UtGcB1E=
github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo=
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.28.0 h1:MirSo27VyNi7RJYP3078AA1+Cyzd2GB66qy3aUHvsWY=
github.com/rs/zerolog v1.28.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sahilm/fuzzy v0.1.1 h1:ceu5RHF8DGgoi+/dR5PsECjCDH1BE3Fnmpo7aVXOdRA=
github.com/sahilm/fuzzy v0.1.1/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
github.com/samber/do v1.5.1 h1:32/S8RgoKYa2wpf8TrakzyOFj0C/QQV4df09x1nza7I=
github.com/samber/do v1.5.1/go.mod h1:DWqBvumy8dyb2vEnYZE7D7zaVEB64J45B0NjTlY/M4k=
github.com/samber/lo v1.37.0 h1:XjVcB8g6tgUp8rsPsJ2CvhClfImrpL04YpQHXeHPhRw=
Expand All @@ -84,8 +122,12 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/therealpaulgg/ssh-sync v0.3.0 h1:XFgcZ3JcccqmPFinWmweNPAYwX2yFiwbCQAJsjaFIq8=
github.com/therealpaulgg/ssh-sync v0.3.0/go.mod h1:vfadGVAZqMe5QLSgWuBwvnLsrJPY3Lr2yRAIMFHaCKk=
github.com/therealpaulgg/ssh-sync v1.1.2 h1:iYOU+uRLOqeCFaiiWG10uuF47aGIa6KXh0jxw3boH1A=
github.com/therealpaulgg/ssh-sync v1.1.2/go.mod h1:lc90qMx77ydUuUw/ezkJb0eRlzeRlCWLWLW/RORbQsI=
github.com/urfave/cli/v2 v2.23.7 h1:YHDQ46s3VghFHFf1DdF+Sh7H4RqhcM+t0TmZRJx4oJY=
github.com/urfave/cli/v2 v2.23.7/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
Expand All @@ -107,8 +149,10 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
Expand Down
1 change: 1 addition & 0 deletions pkg/database/models/ssh_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ type SshConfig struct {
Host string `json:"host" db:"host"`
Values map[string][]string `json:"values" db:"values"`
IdentityFiles []string `json:"identity_files" db:"identity_files"`
KnownHosts []byte `json:"known_hosts" db:"known_hosts"`
}
4 changes: 2 additions & 2 deletions pkg/database/repository/ssh_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func (repo *SshConfigRepo) GetSshConfig(userID uuid.UUID) (*models.SshConfig, er

func (repo *SshConfigRepo) UpsertSshConfig(config *models.SshConfig) (*models.SshConfig, error) {
q := do.MustInvoke[query.QueryService[models.SshConfig]](repo.Injector)
sshConfig, err := q.QueryOne("insert into ssh_configs (user_id, host, values, identity_files) values ($1, $2, $3, $4) on conflict (user_id, host) do update set host = $2, values = $3, identity_files = $4 returning *", config.UserID, config.Host, config.Values, config.IdentityFiles)
sshConfig, err := q.QueryOne("insert into ssh_configs (user_id, host, values, identity_files, known_hosts) values ($1, $2, $3, $4, $5) on conflict (user_id, host) do update set host = $2, values = $3, identity_files = $4, known_hosts = $5 returning *", config.UserID, config.Host, config.Values, config.IdentityFiles, config.KnownHosts)
if err != nil {
return nil, err
}
Expand All @@ -46,7 +46,7 @@ func (repo *SshConfigRepo) UpsertSshConfig(config *models.SshConfig) (*models.Ss

func (repo *SshConfigRepo) UpsertSshConfigTx(config *models.SshConfig, tx pgx.Tx) (*models.SshConfig, error) {
q := do.MustInvoke[query.QueryServiceTx[models.SshConfig]](repo.Injector)
sshConfig, err := q.QueryOne(tx, "insert into ssh_configs (user_id, host, values, identity_files) values ($1, $2, $3, $4) on conflict (user_id, host) do update set host = $2, values = $3, identity_files = $4 returning *", config.UserID, config.Host, config.Values, config.IdentityFiles)
sshConfig, err := q.QueryOne(tx, "insert into ssh_configs (user_id, host, values, identity_files, known_hosts) values ($1, $2, $3, $4, $5) on conflict (user_id, host) do update set host = $2, values = $3, identity_files = $4, known_hosts = $5 returning *", config.UserID, config.Host, config.Values, config.IdentityFiles, config.KnownHosts)
if err != nil {
return nil, err
}
Expand Down
32 changes: 26 additions & 6 deletions pkg/web/router/routes/data.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ import (
"github.com/therealpaulgg/ssh-sync/pkg/dto"
)

// Custom SshConfigDto to include KnownHosts field which is not yet in the client library
type ServerSshConfigDto struct {
Host string `json:"host"`
Values map[string][]string `json:"values"`
IdentityFiles []string `json:"identity_files"`
KnownHosts []byte `json:"known_hosts"`
}

func getData(i *do.Injector) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
user, ok := r.Context().Value(context_keys.UserContextKey).(*models.User)
Expand All @@ -42,7 +50,17 @@ func getData(i *do.Injector) http.HandlerFunc {
return
}
user.Config = config
dto := dto.DataDto{
// Since we're doing our own custom JSON encoding, we need to create a custom response object
// that includes our extended SshConfigDto with KnownHosts field
type DataDtoResponse struct {
ID uuid.UUID `json:"id"`
Username string `json:"username"`
Keys []dto.KeyDto `json:"keys"`
SshConfig []ServerSshConfigDto `json:"ssh_config"`
Machines []dto.MachineDto `json:"machines"`
}

dataResponse := DataDtoResponse{
ID: user.ID,
Username: user.Username,
Keys: lo.Map(user.Keys, func(key models.SshKey, index int) dto.KeyDto {
Expand All @@ -53,15 +71,16 @@ func getData(i *do.Injector) http.HandlerFunc {
Data: key.Data,
}
}),
SshConfig: lo.Map(user.Config, func(conf models.SshConfig, index int) dto.SshConfigDto {
return dto.SshConfigDto{
SshConfig: lo.Map(user.Config, func(conf models.SshConfig, index int) ServerSshConfigDto {
return ServerSshConfigDto{
Host: conf.Host,
Values: conf.Values,
IdentityFiles: conf.IdentityFiles,
KnownHosts: conf.KnownHosts,
}
}),
}
json.NewEncoder(w).Encode(dto)
json.NewEncoder(w).Encode(dataResponse)
}
}

Expand All @@ -87,18 +106,19 @@ func addData(i *do.Injector) http.HandlerFunc {
w.WriteHeader(http.StatusBadRequest)
return
}
var sshConfig []dto.SshConfigDto
var sshConfig []ServerSshConfigDto
if err := json.NewDecoder(bytes.NewBufferString(sshConfigDataRaw)).Decode(&sshConfig); err != nil {
log.Debug().Err(err).Msg("could not decode ssh config")
w.WriteHeader(http.StatusBadRequest)
return
}
sshConfigData := lo.Map(sshConfig, func(conf dto.SshConfigDto, i int) models.SshConfig {
sshConfigData := lo.Map(sshConfig, func(conf ServerSshConfigDto, i int) models.SshConfig {
return models.SshConfig{
UserID: user.ID,
Host: conf.Host,
Values: conf.Values,
IdentityFiles: conf.IdentityFiles,
KnownHosts: conf.KnownHosts,
}
})
user.Config = sshConfigData
Expand Down
31 changes: 21 additions & 10 deletions pkg/web/router/routes/data_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,17 +63,26 @@ func TestGetData(t *testing.T) {
status, http.StatusOK)
}

var dataDto dto.DataDto
err = json.NewDecoder(rr.Body).Decode(&dataDto)
// Use our custom DataDtoResponse type for decoding the response
type DataDtoResponse struct {
ID uuid.UUID `json:"id"`
Username string `json:"username"`
Keys []dto.KeyDto `json:"keys"`
SshConfig []ServerSshConfigDto `json:"ssh_config"`
Machines []dto.MachineDto `json:"machines"`
}

var dataResponse DataDtoResponse
err = json.NewDecoder(rr.Body).Decode(&dataResponse)
if err != nil {
t.Errorf("getData returned unexpected body: got %v want %v, could not decode",
rr.Body.String(), err)
t.Errorf("getData returned unexpected body: got %v want %v, could not decode: %v",
rr.Body.String(), "valid JSON", err)
}

assert.Equal(t, user.ID, dataDto.ID)
assert.Equal(t, "test", dataDto.Keys[0].Filename)
assert.Equal(t, bytes, dataDto.Keys[0].Data)
assert.Equal(t, 0, len(dataDto.SshConfig))
assert.Equal(t, user.ID, dataResponse.ID)
assert.Equal(t, "test", dataResponse.Keys[0].Filename)
assert.Equal(t, bytes, dataResponse.Keys[0].Data)
assert.Equal(t, 0, len(dataResponse.SshConfig))
}

func TestGetDataError(t *testing.T) {
Expand Down Expand Up @@ -124,7 +133,8 @@ func TestAddData(t *testing.T) {
if err != nil {
t.Fatal(err)
}
_ = writer.WriteField("ssh_config", `[{"host":"test"}]`)
// Include known_hosts in test data
_ = writer.WriteField("ssh_config", `[{"host":"test", "values":{}, "identity_files":[], "known_hosts":"dGVzdA=="}]`)
writer.Close()

req, err := http.NewRequest("POST", "/", body)
Expand Down Expand Up @@ -217,7 +227,8 @@ func TestAddDataError(t *testing.T) {
if err != nil {
t.Fatal(err)
}
_ = writer.WriteField("ssh_config", `[{"host":"test"}]`)
// Include known_hosts in test data
_ = writer.WriteField("ssh_config", `[{"host":"test", "values":{}, "identity_files":[], "known_hosts":"dGVzdA=="}]`)
writer.Close()

req, err := http.NewRequest("POST", "/", body)
Expand Down
Loading