Skip to content

Commit

Permalink
Initial implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
bastjan committed Jan 24, 2024
1 parent 2df2274 commit cbff37a
Show file tree
Hide file tree
Showing 14 changed files with 1,203 additions and 3 deletions.
8 changes: 7 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,11 @@ jobs:
restore-keys: |
${{ runner.os }}-go-
- name: Install expect
run: sudo apt-get -y install expect

- name: Run tests
run: make test
env:
E2E_PASSBOLT_PASSPHRASE: ${{ secrets.E2E_PASSBOLT_PASSPHRASE }}
E2E_PASSBOLT_PRIVATE_KEY: ${{ secrets.E2E_PASSBOLT_PRIVATE_KEY }}
run: make test test-e2e
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ test: ## Run tests
go test ./... -coverprofile cover.tmp.out
cat cover.tmp.out | grep -v "zz_generated.deepcopy.go" > cover.out

.PHONY: test-e2e
test-e2e: build ## Run e2e tests
(cd e2e && ./interactive.tcl)
(cd e2e && ./non-interactive.tcl)

.PHONY: build
build: generate fmt vet $(BIN_FILENAME) ## Build manager binary

Expand Down
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,26 @@
# emergency-credentials-receive

Receives cluster emergency credentials from Passbolt (and S3)

## Install from binary

Install the latest release for your arch and OS with the following command:

```sh
curl -s "https://raw.githubusercontent.com/vshn/emergency-credentials-receive/main/install.sh" | bash
```

## Development

There are E2E tests in the `e2e` directory.
They simulate user inputs using [expect](https://core.tcl-lang.org/expect/index).

To run the tests you need your passbolt private key and the passbolt passphrase.
Or you can use the test credentials from [git.vshn.net](https://git.vshn.net/syn/passbolt-pubkey-sync/-/settings/ci_cd).
Note that the test credentials can only access a very limited set of test clusters.
You can set them as environment variables:

```sh
export E2E_PASSBOLT_PASSPHRASE="..."
export E2E_PASSBOLT_PRIVATE_KEY="$(cat /path/to/private.key)"
```
63 changes: 63 additions & 0 deletions e2e/interactive.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#!/usr/bin/env expect

source ./lib/common.tcl

set timeout 60

set cluster_id "c-appuio-lab-cloudscale-rma-0"
set api_endpoint "https://api.lab-cloudscale-rma-0.appuio.cloud:6443"

set passphrase [getenv_or_die "E2E_PASSBOLT_PASSPHRASE"]
set private_key [getenv_or_die "E2E_PASSBOLT_PRIVATE_KEY"]

proc expect_prompt {prompt} {
expect -exact "$prompt"
expect -exact "> "
sleep .5
}

# The script assumes vi is used to enter the private key
set ::env(EDITOR) "vi"
file delete -force config.yaml
file delete -force "em-$cluster_id"
set ::env(EMR_CONFIG_DIR) [pwd]

log "Starting tool"
spawn ../emergency-credentials-receive
expect -exact "Welcome"

log "Expecting private key prompt in editor"
expect -exact "Paste your Passbolt private key"
sleep .1
send -- "i"
send -- "$private_key"
# Escape key
send -- "\x1b"
send -- ":x\r"

log "Expecting passphrase prompt"
expect_prompt "Passbolt passphrase"
send -- "$passphrase"
send -- "\r"

log "Expecting cluster ID prompt"
expect_prompt "Enter your cluster ID"
send -- "$cluster_id"
send -- "\r"

log "Expecting to have valid credentials"
expect -exact "2 buckets with credentials found"
expect -exact "Emergency credentials found"

log "Expecting API endpoint prompt"
expect_prompt "Provide API endpoint"
send "$api_endpoint"
send -- "\r"
expect eof

test_kubeconfig "em-$cluster_id"

log "Test successful"

file delete -force config.yaml
file delete -force "em-$cluster_id"
26 changes: 26 additions & 0 deletions e2e/lib/common.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

proc log {msg} {
send_user "\n\[TEST\]\t$msg\n"
}

proc test_kubeconfig {kubeconfig} {
log "Testing kubeconfig $kubeconfig"
set ::env(KUBECONFIG) "$kubeconfig"

log "Testing kubeconfig is allowed to get nodes"
spawn kubectl get nodes
expect -- "master*Ready*master"
expect eof

log "Testing kubeconfig is allowed to delete nodes"
spawn kubectl auth can-i delete nodes
expect -- "yes"
expect eof
}

proc getenv_or_die {var} {
if {![info exists ::env($var)]} {
error "Missing environment variable $var"
}
return "$::env($var)"
}
34 changes: 34 additions & 0 deletions e2e/non-interactive.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/usr/bin/env expect

source ./lib/common.tcl

set timeout 60

set cluster_id "c-appuio-lab-cloudscale-rma-0"
set api_endpoint "https://api.lab-cloudscale-rma-0.appuio.cloud:6443"

set passphrase [getenv_or_die "E2E_PASSBOLT_PASSPHRASE"]
set private_key [getenv_or_die "E2E_PASSBOLT_PRIVATE_KEY"]

file delete -force config.yaml
file delete -force "em-$cluster_id"
set ::env(EMR_CONFIG_DIR) [pwd]

log "Starting tool"
set ::env(EMR_PASSPHRASE) "$passphrase"
set ::env(EMR_KUBERNETES_ENDPOINT) "$api_endpoint"
exec -- jq --null-input --arg key "$private_key" {{passbolt_key: $key}} > config.yaml
spawn ../emergency-credentials-receive "$cluster_id"
expect -exact "Welcome"

log "Expecting to have valid credentials"
expect -exact "2 buckets with credentials found"
expect -exact "Emergency credentials found"
expect eof

test_kubeconfig "em-$cluster_id"

log "Test successful"

file delete -force config.yaml
file delete -force "em-$cluster_id"
67 changes: 67 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,70 @@
module github.com/vshn/emergency-credentials-receive

go 1.21.6

require (
github.com/Masterminds/sprig/v3 v3.2.3
github.com/charmbracelet/bubbles v0.17.1
github.com/charmbracelet/bubbletea v0.25.0
github.com/charmbracelet/lipgloss v0.9.1
github.com/cli/cli/v2 v2.42.0
github.com/google/go-jsonnet v0.20.0
github.com/minio/minio-go/v7 v7.0.66
github.com/passbolt/go-passbolt v0.7.0
golang.org/x/term v0.16.0
gopkg.in/yaml.v3 v3.0.1
sigs.k8s.io/yaml v1.1.0
)

require (
github.com/AlecAivazis/survey/v2 v2.3.7 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.2.0 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c // indirect
github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f // indirect
github.com/ProtonMail/gopenpgp/v2 v2.7.4 // indirect
github.com/atotto/clipboard v0.1.4 // indirect
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/cli/safeexec v1.0.1 // indirect
github.com/cloudflare/circl v1.3.6 // indirect
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/uuid v1.5.0 // indirect
github.com/huandu/xstrings v1.3.3 // indirect
github.com/imdario/mergo v0.3.11 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/klauspost/compress v1.17.4 // indirect
github.com/klauspost/cpuid/v2 v2.2.6 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-localereader v0.0.1 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
github.com/minio/md5-simd v1.1.2 // indirect
github.com/minio/sha256-simd v1.0.1 // indirect
github.com/mitchellh/copystructure v1.0.0 // indirect
github.com/mitchellh/reflectwalk v1.0.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
github.com/muesli/cancelreader v0.2.2 // indirect
github.com/muesli/reflow v0.3.0 // indirect
github.com/muesli/termenv v0.15.2 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/rs/xid v1.5.0 // indirect
github.com/shopspring/decimal v1.2.0 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/spf13/cast v1.3.1 // indirect
golang.org/x/crypto v0.18.0 // indirect
golang.org/x/net v0.20.0 // indirect
golang.org/x/sync v0.6.0 // indirect
golang.org/x/sys v0.16.0 // indirect
golang.org/x/text v0.14.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.3.0 // indirect
)
Loading

0 comments on commit cbff37a

Please sign in to comment.