From 457f60f8157fa15192ed8e817dcaeb277f741158 Mon Sep 17 00:00:00 2001 From: Manfred Touron Date: Sun, 31 Dec 2017 16:31:25 +0100 Subject: [PATCH 1/4] Use `sshportal server` instead of `sshportal` to start a new server --- CHANGELOG.md | 4 ++ Dockerfile | 1 + examples/mysql/docker-compose.yml | 2 +- main.go | 76 +++++++++++++++++-------------- 4 files changed, 47 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f419916..33108d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## master (unreleased) +Breaking changes: +* Use `sshportal server` instead of `sshportal` to start a new server (nothing to change if using the docker image) + +Changes: * Fix connection failure when sending too many environment variables (fix [#22](https://github.com/moul/sshportal/issues/22)) * Fix panic when entering empty command (fix [#13](https://github.com/moul/sshportal/issues/13)) diff --git a/Dockerfile b/Dockerfile index 00ac0fa..5a29c40 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,3 +8,4 @@ RUN make _docker_install FROM scratch COPY --from=builder /go/bin/sshportal /bin/sshportal ENTRYPOINT ["/bin/sshportal"] +CMD ["server"] diff --git a/examples/mysql/docker-compose.yml b/examples/mysql/docker-compose.yml index 94c78b5..e7f2e1a 100644 --- a/examples/mysql/docker-compose.yml +++ b/examples/mysql/docker-compose.yml @@ -9,7 +9,7 @@ services: condition: service_healthy links: - mysql - command: --db-driver=mysql --debug --db-conn="root:root@tcp(mysql:3306)/db?charset=utf8&parseTime=true&loc=Local" + command: server --db-driver=mysql --debug --db-conn="root:root@tcp(mysql:3306)/db?charset=utf8&parseTime=true&loc=Local" ports: - 2222:2222 diff --git a/main.go b/main.go index 5b6c21c..f8e3030 100644 --- a/main.go +++ b/main.go @@ -45,43 +45,49 @@ func main() { app.Author = "Manfred Touron" app.Version = Version + " (" + GitSha + ")" app.Email = "https://github.com/moul/sshportal" - app.Flags = []cli.Flag{ - cli.StringFlag{ - Name: "bind-address, b", - EnvVar: "SSHPORTAL_BIND", - Value: ":2222", - Usage: "SSH server bind address", - }, - cli.StringFlag{ - Name: "db-driver", - Value: "sqlite3", - Usage: "GORM driver (sqlite3)", - }, - cli.StringFlag{ - Name: "db-conn", - Value: "./sshportal.db", - Usage: "GORM connection string", - }, - cli.BoolFlag{ - Name: "debug, D", - Usage: "Display debug information", - }, - cli.StringFlag{ - Name: "config-user", - Usage: "SSH user that spawns a configuration shell", - Value: "admin", - }, - cli.StringFlag{ - Name: "healthcheck-user", - Usage: "SSH user that returns healthcheck status without checking the SSH key", - Value: "healthcheck", - }, - cli.StringFlag{ - Name: "aes-key", - Usage: "Encrypt sensitive data in database (length: 16, 24 or 32)", + app.Commands = []cli.Command{ + { + Name: "server", + Usage: "Start sshportal server", + Action: server, + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "bind-address, b", + EnvVar: "SSHPORTAL_BIND", + Value: ":2222", + Usage: "SSH server bind address", + }, + cli.StringFlag{ + Name: "db-driver", + Value: "sqlite3", + Usage: "GORM driver (sqlite3)", + }, + cli.StringFlag{ + Name: "db-conn", + Value: "./sshportal.db", + Usage: "GORM connection string", + }, + cli.BoolFlag{ + Name: "debug, D", + Usage: "Display debug information", + }, + cli.StringFlag{ + Name: "config-user", + Usage: "SSH user that spawns a configuration shell", + Value: "admin", + }, + cli.StringFlag{ + Name: "healthcheck-user", + Usage: "SSH user that returns healthcheck status without checking the SSH key", + Value: "healthcheck", + }, + cli.StringFlag{ + Name: "aes-key", + Usage: "Encrypt sensitive data in database (length: 16, 24 or 32)", + }, + }, }, } - app.Action = server if err := app.Run(os.Args); err != nil { log.Fatalf("error: %v", err) } From 9bc545b4bb562d1220c834ff1373ea37675771e8 Mon Sep 17 00:00:00 2001 From: Manfred Touron Date: Mon, 1 Jan 2018 08:58:51 +0100 Subject: [PATCH 2/4] Add `config backup --ignore-events` option --- CHANGELOG.md | 1 + shell.go | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33108d1..3a33f85 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ Breaking changes: Changes: * Fix connection failure when sending too many environment variables (fix [#22](https://github.com/moul/sshportal/issues/22)) * Fix panic when entering empty command (fix [#13](https://github.com/moul/sshportal/issues/13)) +* Add `config backup --ignore-events` option ## v1.6.0 (2017-12-12) diff --git a/shell.go b/shell.go index 203b4d4..86b524e 100644 --- a/shell.go +++ b/shell.go @@ -299,6 +299,7 @@ GLOBAL OPTIONS: Flags: []cli.Flag{ cli.BoolFlag{Name: "indent", Usage: "uses indented JSON"}, cli.BoolFlag{Name: "decrypt", Usage: "decrypt sensitive data"}, + cli.BoolFlag{Name: "ignore-events", Usage: "do not backup events data"}, }, Description: "ssh admin@portal config backup > sshportal.bkp", Action: func(c *cli.Context) error { @@ -360,8 +361,10 @@ GLOBAL OPTIONS: if err := SessionsPreload(db).Find(&config.Sessions).Error; err != nil { return err } - if err := EventsPreload(db).Find(&config.Events).Error; err != nil { - return err + if !c.Bool("ignore-events") { + if err := EventsPreload(db).Find(&config.Events).Error; err != nil { + return err + } } config.Date = time.Now() enc := json.NewEncoder(s) From 9fdb36c6ca542702ee3685ccd19eebdbf75d5881 Mon Sep 17 00:00:00 2001 From: Manfred Touron Date: Mon, 1 Jan 2018 09:07:19 +0100 Subject: [PATCH 3/4] Refactor 'make integration' to be runnable with docker-compose --- Dockerfile | 1 + Makefile | 3 +- examples/integration/Dockerfile | 4 ++ examples/integration/Makefile | 6 ++ examples/integration/_client.sh | 56 ++++++++++++++++ examples/integration/client_test_rsa | 27 ++++++++ examples/integration/docker-compose.yml | 18 +++++ examples/integration/test.sh | 87 ------------------------- 8 files changed, 113 insertions(+), 89 deletions(-) create mode 100644 examples/integration/Dockerfile create mode 100644 examples/integration/Makefile create mode 100755 examples/integration/_client.sh create mode 100644 examples/integration/client_test_rsa create mode 100644 examples/integration/docker-compose.yml delete mode 100755 examples/integration/test.sh diff --git a/Dockerfile b/Dockerfile index 5a29c40..5938ef7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,3 +9,4 @@ FROM scratch COPY --from=builder /go/bin/sshportal /bin/sshportal ENTRYPOINT ["/bin/sshportal"] CMD ["server"] +EXPOSE 2222 diff --git a/Makefile b/Makefile index b3a36a6..1a1cfb8 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,6 @@ GIT_TAG ?= $(shell git describe --tags --always) GIT_BRANCH ?= $(shell git rev-parse --abbrev-ref HEAD) LDFLAGS ?= -X main.GitSha=$(GIT_SHA) -X main.GitTag=$(GIT_TAG) -X main.GitBranch=$(GIT_BRANCH) VERSION ?= $(shell grep 'VERSION =' main.go | cut -d'"' -f2) -PORT ?= 2222 AES_KEY ?= my-dummy-aes-key .PHONY: install @@ -16,7 +15,7 @@ docker.build: .PHONY: integration integration: - PORT="$(PORT)" bash ./examples/integration/test.sh + cd ./examples/integration && make .PHONY: _docker_install _docker_install: diff --git a/examples/integration/Dockerfile b/examples/integration/Dockerfile new file mode 100644 index 0000000..a31269c --- /dev/null +++ b/examples/integration/Dockerfile @@ -0,0 +1,4 @@ +FROM occitech/ssh-client +COPY . /integration +ENTRYPOINT ["/bin/sh", "-c"] +CMD ["/integration/_client.sh"] diff --git a/examples/integration/Makefile b/examples/integration/Makefile new file mode 100644 index 0000000..7cea339 --- /dev/null +++ b/examples/integration/Makefile @@ -0,0 +1,6 @@ +run: + docker-compose down + docker-compose up -d sshportal + docker-compose build client + docker-compose run client /integration/_client.sh + docker-compose down diff --git a/examples/integration/_client.sh b/examples/integration/_client.sh new file mode 100755 index 0000000..8ff513b --- /dev/null +++ b/examples/integration/_client.sh @@ -0,0 +1,56 @@ +#!/bin/sh -e + +mkdir -p ~/.ssh +cp /integration/client_test_rsa ~/.ssh/id_rsa +chmod -R 700 ~/.ssh +cat >~/.ssh/config < backup-1 +ssh sshportal -l admin config restore --confirm < backup-1 +ssh sshportal -l admin config backup --indent --ignore-events > backup-2 +( + cat backup-1 | grep -v '"date":' | grep -v 'tedAt":' > backup-1.clean + cat backup-2 | grep -v '"date":' | grep -v 'tedAt":' > backup-2.clean + set -xe + diff backup-1.clean backup-2.clean +) diff --git a/examples/integration/client_test_rsa b/examples/integration/client_test_rsa new file mode 100644 index 0000000..cdf7baf --- /dev/null +++ b/examples/integration/client_test_rsa @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAxV0ds/oMuOw9QVLFgxaM0Js2IdJKiYLnmKq96IuZ/wMqMea3 +qi1UfNBPUQ2CojwbJGTea8cA9J1Et+a6v1mL66YG8zyxmhdlKHm2KOMnUXSfWPNg +ZArXH7Uj4Nx1k/O1ujfQFAsYTx63kMqwq1lM9JrExLSdp/8D/zQAyF68c82w8UZH +aIpLZJkM/fgh0VJWiw65NYAzuIkJNBgZR8rEBQU7V3lCqFGcSJ88MoqIdVGy0I4b +GGpO9VppDTf+uYGYDthhXlV0nHM45neWL5hzFK6oqbLFLpsaUOY7C3kKv+8+B3lX +p3OfGVoFy7u3evro+yRQEMQ+myS5UBIHaI3qOwIDAQABAoIBABM7/vASV3kSNOoP +2gXrha+y4LStHOyH4HBFe5qVOF3c/hi85ntkTY6YcpJwoaGUAAUs+2w/ib1NMmxF +xT9ux68gkB7WdGyTCR3HttQHR0at+fWeSm+Vit+hNKzub1sK7lQGqnW5mxXi5Xrr +9gnM+y3/g1u0SoUb2lTdyZG9gdo7LnLElzRinraEqTJUowXkqzAhGf1A+Kgp2fkb +/+QP1oiK8QeOFOsITD2UwIVCBRwRl5TjjwfLQ4El6oAWNjcL1ZfSmQLiXZ7U8Smk +Cd+BI+6ZDLA43fBUGDjbg4+2dt2JoKNkS0FfqhCW+Z2A0+ClJ8pwuMqRz8XXaOYr +ONCqOPECgYEA/qyWxSUjEWMvN3tC/mZPEbwHP3m7mbR1KGwhZylWVCmEF7kVC6il +/ICQZUI9ekyGJZ/SKZKwxDe7oeV+vFsus/9FWC5wrp45Xm4kEUwsBr4bWvuNpVOq +jrKecY8NgPZS1X6Uc5BbpiE9/VF2gCdYVVCDXP1NfO2MDhkniXJQUEMCgYEAxmQl +3s/vih9rXllPZcWHafjnFcGU1AIiJD1c+8lAqwCZzm0Bt0Ex4s1t3lp0ew6YBVXN +yGy+BORxOC9FQGTlKZNk/S705+8iAVNc9Sy7XbgN3GY3eat7XYbNpGbQrjiyZ+7I +pdEnoHWQD4NFXHaVsXaVHcBFUovXKoes2PODeqkCgYEAoN/3Ucv2zgoAjqSfmkKY +mhRT48YLOroi9AjyRM95CCs9lRrGb5n2WH4COOTSHwpuByBhSv+uCBVIwqlNGMDk +zLFpZZ3YcoXiqYMb541dlljKwPt8673hVMkCi6uZFSkFBHY0YpgDPPtsxDOMjsHL +7ACzKq+cHlmUimdbcViz4S8CgYEAr2+sVYaHixsRtVNA9PxiLQIgR4rx8zEXw/hH +m5hyiUV0vaiDlewfEzMab0CKNK/JGx6vZQdUWbsxq7+Re8o9JDDlY0b854T+CzIO +x/iQj+XMzBPQBtXvt9sXSsRo0Uft7B6qbIeyhSCxDibFVWjAIzh70N1P8BkdYsyr +uwZMRFECgYEA5QuutlFLI7hMPdBQvsEhjdVwKAj7LvpNemgxDpEoMiQWWm51XzcP +IZjlCwl1UvIE0MxowtvNr5lQuGRN8/88Dajpq+W6eeTSCKi67nn0VZh13cQLKvoX +DRZ6nfC3iLnEYKK+KN/I3NY7JcSjHmW6V8WtrCYAi2D5Ns05XJAG6t8= +-----END RSA PRIVATE KEY----- diff --git a/examples/integration/docker-compose.yml b/examples/integration/docker-compose.yml new file mode 100644 index 0000000..a9b2349 --- /dev/null +++ b/examples/integration/docker-compose.yml @@ -0,0 +1,18 @@ +version: '3.0' + +services: + sshportal: + image: moul/sshportal + environment: + - SSHPORTAL_DEFAULT_ADMIN_INVITE_TOKEN=integration + command: server --debug + ports: + - 2222 + + client: + build: . + depends_on: + - sshportal + #volumes: + # - .:/integration + tty: true diff --git a/examples/integration/test.sh b/examples/integration/test.sh deleted file mode 100755 index d82e9f1..0000000 --- a/examples/integration/test.sh +++ /dev/null @@ -1,87 +0,0 @@ -#!/bin/sh -e -# Setup a new sshportal and performs some checks - -PORT=${PORT:-2222} -SSHPORTAL_DEFAULT_ADMIN_INVITE_TOKEN=integration - -# tempdir -WORK_DIR=`mktemp -d` -if [[ ! "$WORK_DIR" || ! -d "$WORK_DIR" ]]; then - echo "Could not create temp dir" - exit 1 -fi -cd "${WORK_DIR}" - -# pre cleanup -docker_cleanup() { - ( set -x - docker rm -f -v sshportal-integration 2>/dev/null >/dev/null || true - ) -} -tempdir_cleanup() { - rm -rf "${WORK_DIR}" -} -docker_cleanup -trap tempdir_cleanup EXIT - -# start server -( set -xe; - docker run \ - -d \ - -e SSHPORTAL_DEFAULT_ADMIN_INVITE_TOKEN=${SSHPORTAL_DEFAULT_ADMIN_INVITE_TOKEN} \ - --name=sshportal-integration \ - -p${PORT}:2222 \ - moul/sshportal --debug -) -while ! nc -z localhost ${PORT}; do - sleep 1 -done -sleep 3 - -# integration suite -xssh() { - set -e - echo "+ ssh {sshportal} $@" >&2 - ssh -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no localhost -p ${PORT} $@ -} -# login -xssh -l invite:integration - -# hostgroup/usergroup/acl -xssh -l admin hostgroup create -xssh -l admin hostgroup create --name=hg1 -xssh -l admin hostgroup create --name=hg2 --comment=test -xssh -l admin usergroup inspect hg1 hg2 -xssh -l admin hostgroup ls - -xssh -l admin usergroup create -xssh -l admin usergroup create --name=ug1 -xssh -l admin usergroup create --name=ug2 --comment=test -xssh -l admin usergroup inspect ug1 ug2 -xssh -l admin usergroup ls - -xssh -l admin acl create --ug=ug1 --ug=ug2 --hg=hg1 --hg=hg2 --comment=test --action=allow --weight=42 -xssh -l admin acl inspect 2 -xssh -l admin acl ls - -# basic host create -xssh -l admin host create bob@example.org:1234 -xssh -l admin host create test42 -xssh -l admin host create --name=testtest --comment=test --password=test test@test.test -xssh -l admin host create --group=hg1 --group=hg2 hostwithgroups.org -xssh -l admin host inspect example test42 testtest hostwithgroups -xssh -l admin host ls - -# backup/restore -xssh -l admin config backup --indent > backup-1 -xssh -l admin config restore --confirm < backup-1 -xssh -l admin config backup --indent > backup-2 -( - cat backup-1 | grep -v '"date":' > backup-1.clean - cat backup-2 | grep -v '"date":' > backup-2.clean - set -xe - diff backup-1.clean backup-2.clean -) - -# post cleanup -#cleanup From fbb3e7134f512e7f64f36374974b814187608ed0 Mon Sep 17 00:00:00 2001 From: Manfred Touron Date: Mon, 1 Jan 2018 09:08:59 +0100 Subject: [PATCH 4/4] Run integration tests in parallel in CI --- .circleci/config.yml | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2595ac6..cab27f5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,11 +1,12 @@ +defaults: &defaults + working_directory: /go/src/github.com/moul/sshportal + docker: + - image: circleci/golang:1.8 + version: 2 jobs: - build: - docker: - - image: circleci/golang:1.8 - # - image: circleci/mysql:9.4 - - working_directory: /go/src/github.com/moul/sshportal + go.build: + <<: *defaults steps: - checkout - run: make install @@ -14,4 +15,26 @@ jobs: # - run: make integration - run: go get -u github.com/alecthomas/gometalinter - run: gometalinter --install - - run: make lint \ No newline at end of file + - run: make lint + docker.integration: + <<: *defaults + steps: + - checkout + - run: + name: Install Docker Compose + command: | + umask 022 + curl -L https://github.com/docker/compose/releases/download/1.11.2/docker-compose-`uname -s`-`uname -m` > ~/docker-compose + - setup_remote_docker: + docker_layer_caching: true + - run: docker build -t moul/sshportal . + - run: make integration + + +workflows: + version: 2 + build_and_integration: + jobs: + - go.build + - docker.integration + # requires: docker.build?