Compare commits

...

13 Commits

Author SHA1 Message Date
Manfred Touron
79cbaa3afe Merge pull request #262 from moul/fix/email-validator
feat: New Email validator
2021-03-28 22:46:58 +02:00
Darko Djalevski
2def328f6a fix: fix email validating in shell input
fix: test cases

fix feedback

fix: validate email with custom validator in shell input
2021-03-28 22:25:25 +02:00
Manfred Touron
ab9c53f1b0 chore: maintenance (#260) 2021-03-26 17:26:10 +01:00
Manfred Touron
614418e7be Merge pull request #243 from matteyeux/master
Fix typo in "shell commands" section in README.md
2021-03-26 16:29:29 +01:00
Manfred Touron
a5bade8761 Merge pull request #249 from jwessel/fix_host_inspect
fix: host inspect causes db errors with later operations
2021-03-26 16:28:44 +01:00
Manfred Touron
7404704bfe Merge pull request #254 from jwessel/feat_userkey_create
feat: Allow user multiple keys with userkey create
2021-03-26 16:27:43 +01:00
Manfred Touron
84a0a31eda Merge pull request #253 from jwessel/feat_postgres
feat: Add postgres support
2021-03-26 16:26:05 +01:00
Manfred Touron
40bbea590c Merge pull request #248 from jwessel/master
feat: Allow removal by user for 'userkey rm'
2021-03-26 16:18:27 +01:00
Jason Wessel
28a5fd1846 feat: Allow user multiple keys with userkey create
And end user may have more than one ssh key, the userkey create
command should be able to accept more than one key so you can do
something like:

   curl https://github.com/USER.keys | ssh sshportal -p 2222 -l admin userkey create USER

The userkey create command also does not work properly from an
interactive shell due to the use of bufio.  This patch adds the
ability to use either the interactive shell or direct ssh command to
input one or more keys.

Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
2021-03-09 09:29:10 -06:00
Jason Wessel
19605f0054 feat: Add postgres support
Postgres is more picky about submitting a string to the id column in a
table.  Postgres requires the use of only integers for the array of
values in a select statement containing: where id IN (...array...)

This patch fixes all the following class of problems:

   SELECT * FROM "ssh_keys" WHERE
   "ssh_keys"."deleted_at" IS NULL AND ((id IN ('host')) OR (name IN
   ('host'))) ORDER BY "ssh_keys"."id" ASC LIMIT 1 [0 rows affected or
   returned ] error: pq: invalid input syntax for
   type integer: "host"

Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
2021-03-09 08:57:08 -06:00
Jason Wessel
c1c4c556b4 feat: Allow removal by user for 'userkey rm'
The userkey rm command implies that it can remove a key by user or the
id key, but it only works against the data base id of the key.  This
patch allows the userkey rm command to work with the user name, so
that all the keys for the user can be cleared out in one command.

Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
2021-03-08 11:22:38 -06:00
Jason Wessel
3c32177213 fix: host inspect causes db errors with later operations
The most simple case with a fresh install of sshportal using the
following commands put the shell into a unrecoverable state.

config> host create test1@test1
1
config> host inspect 1
config> host create test2@test2
error: can't preload field Groups for dbmodels.SSHKey

The issue is caused because the global db handle is replaced with the
inspect command.

Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
2021-03-01 07:37:15 -08:00
matteyeux
05225a4b25 Fix typo in "shell commands" section in README.md 2021-02-15 11:27:12 +01:00
15 changed files with 212 additions and 100 deletions

View File

@@ -1,25 +1,15 @@
<!-- Thanks for filling an issue!
### Actual Result / Problem
If this is a BUG REPORT, please:
- Fill in as much of the template below as you can
When I do Foo, Bar happens...
If this is a FEATURE REQUEST, please:
- Describe *in detail* the feature/behavior/change you would like to see
-->
### Expected Result / Suggestion
**What happened**:
I expect that Foobar happens...
**What you expected to happen**:
### Some context
**How to reproduce it (as minimally and precisely as possible)**:
**Anything else we need to know?**:
<!--
**Environment**:
- sshportal --version
- ssh sshportal info
- OS (e.g. from /etc/os-release):
- install method (e.g. go/docker/brew/...):
- others:
-->
Any screenshot to share?
`sshportal --version`?
`ssh sshportal info`?
OS/Go version?
...

View File

@@ -1,7 +1 @@
<!-- Thanks for sending a pull request! Here are some tips for you -->
**What this PR does / why we need it**:
**Which issue this PR fixes**: fixes #xxx, fixes #xxx...
**Special notes for your reviewer**:
<!-- thank you for your contribution! ❤️ -->

2
AUTHORS generated
View File

@@ -8,6 +8,7 @@ bozzo <bozzo@users.noreply.github.com>
dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
fossabot <badges@fossa.io>
ImgBotApp <ImgBotHelp@gmail.com>
Jason Wessel <jason.wessel@windriver.com>
Jean-Louis Férey <jeanlouis.ferey@orange.com>
jerard@alfa-safety.fr <jrrdev@users.noreply.github.com>
Jess <jessachandler@gmail.com>
@@ -20,6 +21,7 @@ Manuel <manuel.sabban@nbs-system.com>
Manuel Sabban <manu@sabban.eu>
Manuel Sabban <msa@nbs-system.com>
Mathieu Pasquet <mathieu.pasquet@alterway.fr>
matteyeux <matteyeux@users.noreply.github.com>
Mikael Rapp <micke.rapp@gmail.com>
MitaliBo <mitali.bisht14@gmail.com>
moul-bot <bot@moul.io>

View File

@@ -366,7 +366,7 @@ user update [-h] [--name=<value>] [--email=<value>] [--set-admin] [--unset-admin
# usergroup management
usergroup help
hostgroup create [-h] [--name=<value>] [--comment=<value>]
usergroup create [-h] [--name=<value>] [--comment=<value>]
usergroup inspect [-h] USERGROUP...
usergroup ls [-h] [--latest] [--quiet]
usergroup rm [-h] USERGROUP...

View File

@@ -96,7 +96,8 @@ moul.io/sshportal dependencies: (generated by github.com/tailscale/depaware)
hash from crypto+
html from github.com/asaskevich/govalidator+
io from bufio+
io/ioutil from crypto/tls+
io/fs from crypto/rand+
io/ioutil from crypto/x509+
log from github.com/gliderlabs/ssh+
math from crypto/rsa+
math/big from crypto/dsa+

11
go.mod generated
View File

@@ -3,31 +3,24 @@ module moul.io/sshportal
require (
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
github.com/creack/pty v1.1.11 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/docker/docker v1.13.1
github.com/dustin/go-humanize v1.0.0
github.com/gliderlabs/ssh v0.3.2
github.com/go-sql-driver/mysql v1.5.0
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e // indirect
github.com/jinzhu/gorm v1.9.16
github.com/kr/pty v1.1.8
github.com/lib/pq v1.8.0 // indirect
github.com/mattn/go-colorable v0.1.8 // indirect
github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d
github.com/olekukonko/tablewriter v0.0.5
github.com/pkg/errors v0.9.1
github.com/reiver/go-oi v1.0.0
github.com/reiver/go-telnet v0.0.0-20180421082511-9ff0b2ab096e
github.com/sabban/bastion v0.0.0-20180110125408-b9d3c9b1f4d3
github.com/smartystreets/assertions v0.0.0-20190401211740-f487f9de1cd3 // indirect
github.com/smartystreets/goconvey v1.6.4
github.com/stretchr/testify v1.4.0 // indirect
github.com/tailscale/depaware v0.0.0-20201214215404-77d1e9757027
github.com/urfave/cli v1.22.5
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f // indirect
golang.org/x/tools v0.0.0-20201211185031-d93e913c1a58
gopkg.in/gormigrate.v1 v1.6.0
moul.io/srand v1.6.1
)

46
go.sum generated
View File

@@ -6,15 +6,12 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFI
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef h1:46PFijGLmAjMPwCCCo7Jf0W6f9slllCkkv7vyc1yOSg=
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.7 h1:6pwm8kMQKCmgUg0ZHTm5+/YvRK0s3THD/28+T6/kk4A=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
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/denisenkom/go-mssqldb v0.0.0-20181014144952-4e0d7dc8888f/go.mod h1:xN/JuLBIz4bjkxNmByTiV1IbhfnYb6oo99phBn4Eqhc=
github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6ROGeiHFAP8WJdI2RoxALQYgdllERc3N5N2DM=
github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
@@ -34,9 +31,8 @@ github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZ
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg=
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/jinzhu/gorm v1.9.2/go.mod h1:Vla75njaFJ8clLU1W44h34PjIkijhjHIYnZxMqCdxqo=
github.com/jinzhu/gorm v1.9.16 h1:+IyIjPEABKRpsu/F8OvDPy9fyQlgsg2luMV2ZIH5i5o=
github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs=
@@ -55,8 +51,6 @@ github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4=
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.8.0 h1:9xohqzkUwzR4Ga4ivdTcawVS89YSDVxXMa3xJX3cGzg=
github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
@@ -64,13 +58,14 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/go-sqlite3 v1.14.0 h1:mLyGNKR8+Vv9CAU7PphKa2hkEqxxhn8i32J6FPj1/QA=
github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U=
github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/pkg/diff v0.0.0-20200914180035-5b29258ca4f7 h1:+/+DxvQaYifJ+grD4klzrS5y+KJXldn/2YTl5JG+vZ8=
github.com/pkg/diff v0.0.0-20200914180035-5b29258ca4f7/go.mod h1:zO8QMzTeZd5cpnIkz/Gn6iK0jDfGicM1nynOkkPIl28=
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=
@@ -83,32 +78,44 @@ github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sabban/bastion v0.0.0-20180110125408-b9d3c9b1f4d3 h1:yxUGvEatvDMO6gkhwx82Va+Czdyui9LiCw6a5YB/2f8=
github.com/sabban/bastion v0.0.0-20180110125408-b9d3c9b1f4d3/go.mod h1:1Q04m7wmv/IMoZU9t8UkH+n9McWn4i3H9v9LnMgqloo=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v0.0.0-20190401211740-f487f9de1cd3 h1:hBSHahWMEgzwRyS6dRpxY0XyjZsHyQ61s084wo5PJe0=
github.com/smartystreets/assertions v0.0.0-20190401211740-f487f9de1cd3/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/tailscale/depaware v0.0.0-20201214215404-77d1e9757027 h1:lK99QQdH3yBWY6aGilF+IRlQIdmhzLrsEmF6JgN+Ryw=
github.com/tailscale/depaware v0.0.0-20201214215404-77d1e9757027/go.mod h1:p9lPsd+cx33L3H9nNoecRRxPssFKUwwI50I3pZ0yT+8=
github.com/urfave/cli v1.22.5 h1:lNq9sAHXK2qfdI8W+GRItjCEkI+2oR4d+MEHy1CKXoU=
github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20181112202954-3d3f9f413869/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9 h1:umElSU9WZirRdgu2yFHY0ayQkEnKiOC1TtM3fWXFnoU=
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0 h1:8pl+sMODzuvGJkmj2W4kZihvVb5mKm8pB/X44PIQHv8=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -117,7 +124,16 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20201211185031-d93e913c1a58 h1:1Bs6RVeBFtLZ8Yi1Hk07DiOqzvwLD/4hln4iahvFlag=
golang.org/x/tools v0.0.0-20201211185031-d93e913c1a58/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

11
internal/tools/tools.go Normal file
View File

@@ -0,0 +1,11 @@
// +build tools
package tools
import (
// required by depaware
_ "github.com/tailscale/depaware/depaware"
// required by goimports
_ "golang.org/x/tools/cover"
)

View File

@@ -5,6 +5,7 @@ import (
"encoding/json"
"errors"
"fmt"
"io"
"net/url"
"os"
"regexp"
@@ -24,6 +25,7 @@ import (
"golang.org/x/crypto/ssh/terminal"
"moul.io/sshportal/pkg/crypto"
"moul.io/sshportal/pkg/dbmodels"
"moul.io/sshportal/pkg/utils"
)
var banner = `
@@ -510,7 +512,6 @@ GLOBAL OPTIONS:
"host_groups",
"host_host_groups",
"hosts",
//"migrations",
"sessions",
"settings",
"ssh_keys",
@@ -521,6 +522,7 @@ GLOBAL OPTIONS:
"user_user_groups",
"user_user_roles",
"users",
// "migrations",
}
for _, tableName := range tableNames {
/* #nosec */
@@ -828,12 +830,14 @@ GLOBAL OPTIONS:
}
var hosts []*dbmodels.Host
db = db.Preload("Groups")
if myself.HasRole("admin") {
db = db.Preload("SSHKey")
}
if err := dbmodels.HostsByIdentifiers(db, c.Args()).Find(&hosts).Error; err != nil {
return err
if err := dbmodels.HostsByIdentifiers(db.Preload("Groups").Preload("SSHKey"), c.Args()).Find(&hosts).Error; err != nil {
return err
}
} else {
if err := dbmodels.HostsByIdentifiers(db.Preload("Groups"), c.Args()).Find(&hosts).Error; err != nil {
return err
}
}
if c.Bool("decrypt") {
@@ -1456,7 +1460,6 @@ GLOBAL OPTIONS:
key.Name,
key.Type,
fmt.Sprintf("%d", key.Length),
//key.Fingerprint,
fmt.Sprintf("%d", len(key.Hosts)),
humanize.Time(key.UpdatedAt),
humanize.Time(key.CreatedAt),
@@ -1621,9 +1624,11 @@ GLOBAL OPTIONS:
return err
}
// FIXME: validate email
email := c.Args().First()
valid := utils.ValidateEmail(email)
if !valid {
return errors.New("invalid email")
}
name := strings.Split(email, "@")[0]
if c.String("name") != "" {
name = c.String("name")
@@ -2026,34 +2031,58 @@ GLOBAL OPTIONS:
return err
}
fmt.Fprintf(s, "Enter key:\n")
reader := bufio.NewReader(s)
text, _ := reader.ReadString('\n')
key, comment, _, _, err := ssh.ParseAuthorizedKey([]byte(text))
if err != nil {
return err
var reader *bufio.Reader
var term *terminal.Terminal
if len(sshCommand) == 0 { // interactive mode
term = terminal.NewTerminal(s, "Paste your key(s) and end with a blank line> ")
} else {
fmt.Fprintf(s, "Enter key(s):\n")
reader = bufio.NewReader(s)
}
userkey := dbmodels.UserKey{
User: &user,
Key: key.Marshal(),
Comment: comment,
AuthorizedKey: string(gossh.MarshalAuthorizedKey(key)),
}
if c.String("comment") != "" {
userkey.Comment = c.String("comment")
}
for {
var text string
var errReadline error
if len(sshCommand) == 0 { // interactive mode
text, errReadline = term.ReadLine()
} else {
text, errReadline = reader.ReadString('\n')
}
if errReadline != nil && errReadline != io.EOF {
return errReadline
}
if text != "" && text != "\n" {
key, comment, _, _, err := ssh.ParseAuthorizedKey([]byte(text))
if err != nil {
return err
}
if _, err := govalidator.ValidateStruct(userkey); err != nil {
return err
}
userkey := dbmodels.UserKey{
User: &user,
Key: key.Marshal(),
Comment: comment,
AuthorizedKey: string(gossh.MarshalAuthorizedKey(key)),
}
if c.String("comment") != "" {
userkey.Comment = c.String("comment")
}
// save the userkey in database
if err := db.Create(&userkey).Error; err != nil {
return err
if _, err := govalidator.ValidateStruct(userkey); err != nil {
return err
}
// save the userkey in database
if err := db.Create(&userkey).Error; err != nil {
return err
}
fmt.Fprintf(s, "%d\n", userkey.ID)
if errReadline == io.EOF {
return nil
}
} else {
break
}
}
fmt.Fprintf(s, "%d\n", userkey.ID)
return nil
},
}, {
@@ -2141,7 +2170,16 @@ GLOBAL OPTIONS:
if err := myself.CheckRoles([]string{"admin"}); err != nil {
return err
}
if err := dbmodels.UserKeysByIdentifiers(db, c.Args()).Find(&dbmodels.UserKey{}).Error; err != nil {
var user dbmodels.User
if err := dbmodels.UsersByIdentifiers(db, c.Args()).First(&user).Error; err != nil {
return err
}
if err := dbmodels.UserKeysByUserID(db, []string{fmt.Sprint(user.ID)}).Find(&dbmodels.UserKey{}).Error; err != nil {
return err
}
return dbmodels.UserKeysByUserID(db, []string{fmt.Sprint(user.ID)}).Delete(&dbmodels.UserKey{}).Error
}
return dbmodels.UserKeysByIdentifiers(db, c.Args()).Delete(&dbmodels.UserKey{}).Error
},
},
@@ -2302,7 +2340,7 @@ GLOBAL OPTIONS:
if cliErr.ExitCode() != 0 {
fmt.Fprintf(s, "error: %v\n", err)
}
//s.Exit(cliErr.ExitCode())
// s.Exit(cliErr.ExitCode())
} else {
fmt.Fprintf(s, "error: %v\n", err)
}

View File

@@ -79,7 +79,7 @@ func scannerSplitFunc(data []byte, atEOF bool) (advance int, token []byte, err e
func telnetHandler(host *dbmodels.Host) ssh.Handler {
return func(s ssh.Session) {
// FIXME: log session in db
//actx := s.Context().Value(authContextKey).(*authContext)
// actx := s.Context().Value(authContextKey).(*authContext)
caller := bastionTelnetCaller{ssh: s}
if err := telnet.DialToAndCall(host.DialAddr(), caller); err != nil {
fmt.Fprintf(s, "error: %v", err)

View File

@@ -167,6 +167,25 @@ const (
BastionSchemeTelnet BastionScheme = "telnet"
)
// Generic Helper
func GenericNameOrID(db *gorm.DB, identifiers []string) *gorm.DB {
var ids []string
var names []string
for _, s := range identifiers {
if _, err := strconv.Atoi(s); err == nil {
ids = append(ids, s)
} else {
names = append(names, s)
}
}
if len(ids) > 0 && len(names) > 0 {
return db.Where("id IN (?)", ids).Or("name IN (?)", names)
} else if len(ids) > 0 {
return db.Where("id IN (?)", ids)
}
return db.Where("name IN (?)", names)
}
// Host helpers
func (host *Host) DialAddr() string {
@@ -268,7 +287,7 @@ func HostsPreload(db *gorm.DB) *gorm.DB {
return db.Preload("Groups").Preload("SSHKey")
}
func HostsByIdentifiers(db *gorm.DB, identifiers []string) *gorm.DB {
return db.Where("id IN (?)", identifiers).Or("name IN (?)", identifiers)
return GenericNameOrID(db, identifiers)
}
func HostByName(db *gorm.DB, name string) (*Host, error) {
var host Host
@@ -308,7 +327,7 @@ func SSHKeysPreload(db *gorm.DB) *gorm.DB {
return db.Preload("Hosts")
}
func SSHKeysByIdentifiers(db *gorm.DB, identifiers []string) *gorm.DB {
return db.Where("id IN (?)", identifiers).Or("name IN (?)", identifiers)
return GenericNameOrID(db, identifiers)
}
// HostGroup helpers
@@ -317,7 +336,7 @@ func HostGroupsPreload(db *gorm.DB) *gorm.DB {
return db.Preload("ACLs").Preload("Hosts")
}
func HostGroupsByIdentifiers(db *gorm.DB, identifiers []string) *gorm.DB {
return db.Where("id IN (?)", identifiers).Or("name IN (?)", identifiers)
return GenericNameOrID(db, identifiers)
}
// UserGroup helpers
@@ -326,7 +345,7 @@ func UserGroupsPreload(db *gorm.DB) *gorm.DB {
return db.Preload("ACLs").Preload("Users")
}
func UserGroupsByIdentifiers(db *gorm.DB, identifiers []string) *gorm.DB {
return db.Where("id IN (?)", identifiers).Or("name IN (?)", identifiers)
return GenericNameOrID(db, identifiers)
}
// User helpers
@@ -335,7 +354,21 @@ func UsersPreload(db *gorm.DB) *gorm.DB {
return db.Preload("Groups").Preload("Keys").Preload("Roles")
}
func UsersByIdentifiers(db *gorm.DB, identifiers []string) *gorm.DB {
return db.Where("id IN (?)", identifiers).Or("email IN (?)", identifiers).Or("name IN (?)", identifiers)
var ids []string
var names []string
for _, s := range identifiers {
if _, err := strconv.Atoi(s); err == nil {
ids = append(ids, s)
} else {
names = append(names, s)
}
}
if len(ids) > 0 && len(names) > 0 {
db.Where("id IN (?)", identifiers).Or("email IN (?)", identifiers).Or("name IN (?)", identifiers)
} else if len(ids) > 0 {
return db.Where("id IN (?)", ids)
}
return db.Where("email IN (?)", identifiers).Or("name IN (?)", identifiers)
}
func (u *User) HasRole(name string) bool {
for _, role := range u.Roles {
@@ -371,14 +404,14 @@ func UserKeysPreload(db *gorm.DB) *gorm.DB {
func UserKeysByIdentifiers(db *gorm.DB, identifiers []string) *gorm.DB {
return db.Where("id IN (?)", identifiers)
}
func UserKeysByUserID(db *gorm.DB, identifiers []string) *gorm.DB {
return db.Where("user_id IN (?)", identifiers)
}
// UserRole helpers
//func UserRolesPreload(db *gorm.DB) *gorm.DB {
// return db.Preload("Users")
//}
func UserRolesByIdentifiers(db *gorm.DB, identifiers []string) *gorm.DB {
return db.Where("id IN (?)", identifiers).Or("name IN (?)", identifiers)
return GenericNameOrID(db, identifiers)
}
// Session helpers
@@ -425,7 +458,6 @@ func (e *Event) Log(db *gorm.DB) {
}
func (e *Event) SetAuthor(user *User) *Event {
//e.Author = user
e.AuthorID = user.ID
return e
}

View File

@@ -0,0 +1,13 @@
package utils
import "regexp"
var emailRegex = regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$")
// ValidateEmail validates email.
func ValidateEmail(e string) bool {
if len(e) < 3 && len(e) > 254 {
return false
}
return emailRegex.MatchString(e)
}

View File

@@ -0,0 +1,22 @@
package utils
import (
"testing"
)
func TestValidateEmail(t *testing.T) {
goodEmail := "goodemail@email.com"
badEmail := "b@2323.22"
got := ValidateEmail(goodEmail)
if got == false {
t.Errorf("got1= %v; want true", got)
}
got2 := ValidateEmail(badEmail)
if got2 == false {
t.Errorf("got2= %v; want false", got2)
}
}

View File

@@ -59,7 +59,7 @@ func ensureLogDirectory(location string) error {
}
func server(c *serverConfig) (err error) {
var db = (*gorm.DB)(nil)
var db *gorm.DB
// try to setup the local DB
if db, err = gorm.Open(c.dbDriver, c.dbURL); err != nil {

View File

@@ -60,7 +60,7 @@ func testServer(c *cli.Context) error {
_, _ = io.Copy(s, f) // #nosec
cmdErr = cmd.Wait()
} else {
//cmd.Stdin = s
// cmd.Stdin = s
cmd.Stdout = s
cmd.Stderr = s
cmdErr = cmd.Run()