From a3b388a81de4f4be69ff488dd363bd2362fc87f5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 30 Oct 2024 09:03:40 +0000 Subject: [PATCH] feat(socket): allow overwriting stale sockets --- .github/workflows/goreleaser.yml | 6 +++--- .github/workflows/mkdocs.yml | 33 ++++++++++++++++++++++++++------ cmd/plugin.go | 9 ++++++--- docs/configuration.md | 9 ++++++++- docs/quickstart.md | 6 +++--- docs/sign.md | 2 +- pkg/socket/socket.go | 19 +++++++++++++++++- pkg/socket/socket_test.go | 23 ++++++++++++++++++++++ 8 files changed, 89 insertions(+), 18 deletions(-) diff --git a/.github/workflows/goreleaser.yml b/.github/workflows/goreleaser.yml index 7096469..d219fd0 100644 --- a/.github/workflows/goreleaser.yml +++ b/.github/workflows/goreleaser.yml @@ -9,7 +9,7 @@ on: permissions: contents: write packages: write - id-token: write + id-token: write jobs: goreleaser: @@ -27,7 +27,7 @@ jobs: with: go-version: '1.22.6' cache: false - + - uses: sigstore/cosign-installer@v3.7.0 - uses: anchore/sbom-action/download-syft@v0.17.6 - @@ -63,7 +63,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }} - - + - name: Docker Hub Description uses: peter-evans/dockerhub-description@v4 if: startsWith(github.ref, 'refs/tags/v') diff --git a/.github/workflows/mkdocs.yml b/.github/workflows/mkdocs.yml index 8daad9b..34280dd 100644 --- a/.github/workflows/mkdocs.yml +++ b/.github/workflows/mkdocs.yml @@ -12,9 +12,30 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Deploy docs - uses: mhausenblas/mkdocs-deploy-gh-pages@master - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - CONFIG_FILE: mkdocs.yml - REQUIREMENTS: requirements.txt + with: + fetch-depth: 0 + + - run: make docgen + + - name: Configure Git Credentials + run: | + git config user.name github-actions[bot] + git config user.email 41898282+github-actions[bot]@users.noreply.github.com + + - uses: actions/setup-python@v5 + with: + python-version: 3.x + + - run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV + + - uses: actions/cache@v4 + with: + key: mkdocs-material-${{ env.cache_id }} + path: .cache + restore-keys: | + mkdocs-material- + + - run: pip install mkdocs-material + - run: pip install -r requirements.txt + + - run: mkdocs gh-deploy --force diff --git a/cmd/plugin.go b/cmd/plugin.go index d554dfe..bb42ae6 100644 --- a/cmd/plugin.go +++ b/cmd/plugin.go @@ -22,7 +22,8 @@ import ( ) type Options struct { - Socket string `env:"SOCKET" envDefault:"unix:///opt/kms/vaultkms.socket"` + Socket string `env:"SOCKET" envDefault:"unix:///opt/kms/vaultkms.socket"` + ForceSocketOverwrite bool `env:"FORCE_SOCKET_OVERWRITE"` Debug bool `env:"DEBUG"` @@ -61,6 +62,8 @@ func NewPlugin(version string) error { flag := flag.FlagSet{} // then flags, since they have precedence over env vars flag.StringVar(&opts.Socket, "socket", opts.Socket, "Destination path of the socket (required)") + flag.BoolVar(&opts.ForceSocketOverwrite, "force-socket-overwrite", opts.ForceSocketOverwrite, "Force creation of the socket file."+ + "Use with caution deletes whatever exists at -socket!") flag.BoolVar(&opts.Debug, "debug", opts.Debug, "Enable debug logs") @@ -155,9 +158,9 @@ func NewPlugin(version string) error { zap.L().Info("Successfully created unix socket", zap.String("socket", s.Path)) - listener, err := s.Listen() + listener, err := s.Listen(opts.ForceSocketOverwrite) if err != nil { - log.Fatal(err) + log.Fatal(fmt.Errorf("failed to listen on socket: %w. Use -force-socket-overwrite (VAULT_KUBERNETES_KMS_FORCE_SOCKET_OVERWRITE)", err)) } zap.L().Info("Listening for connection") diff --git a/docs/configuration.md b/docs/configuration.md index 42af494..c2968f5 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -126,9 +126,16 @@ List of required and optional CLI args/env vars. **Furthermore, all of Vaults [E * **(Required)**: `-approle-secret-id` (`VAULT_KMS_APPROLE_SECRET_ID`) * **(Optional)**: `-approle-mount` (`VAULT_KMS_APPROLE_MOUNT`); default: `"approle"` -**Optional**: +**General**: * **(Optional)**: `-socket` (`VAULT_KMS_SOCKET`); default: `unix:///opt/kms/vaultkms.socket"` +* **(Optional)**: `-force-socket-overwrite` (`FORCE_SOCKET_OVERWRITE`); default: `false`. + +!!! note + Use `-force-socket-overwrite` with caution. This will delete whatever filetype exists at the value specified in `-socket`. + + When `vault-kubernetes-kms` crashes, it is not guaranteed that the socket-file will always be removed. For those scenarios `-force-socket-overwrite` was introduced to allow a smooth re-deployment of the plugin and not having to manually delete the stale socket file on the control plane node. + * **(Optional)**: `-debug` (`VAULT_KMS_DEBUG`) ### Example Vault Token Auth diff --git a/docs/quickstart.md b/docs/quickstart.md index 8322ba4..3b14f62 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -12,7 +12,7 @@ In order to run this guide, you will need to have `kind`, `kubectl` and `vault` !!! note `vault-kubernetes-kms` is only published as `amd` (x86_64) images. - + You will make sure, you actually pull `amd` images. You can test it, by using `docker run -it ubuntu /usr/bin/uname -p` which, should output `86_64`. If you need `arm` images, raise an issue. @@ -107,7 +107,7 @@ $> kubectl -n kube-system exec etcd-kms-control-plane -- sh -c "ETCDCTL_API=3 et --cert /etc/kubernetes/pki/etcd/server.crt \ --key /etc/kubernetes/pki/etcd/server.key \ --cacert /etc/kubernetes/pki/etcd/ca.crt \ - get /registry/secrets/default/secret-encrypted" | hexdump -C + get /registry/secrets/default/secret-encrypted" | hexdump -C 00000000 2f 72 65 67 69 73 74 72 79 2f 73 65 63 72 65 74 |/registry/secret| 00000010 73 2f 64 65 66 61 75 6c 74 2f 73 65 63 72 65 74 |s/default/secret| 00000020 2d 65 6e 63 72 79 70 74 65 64 0a 6b 38 73 3a 65 |-encrypted.k8s:e| @@ -168,7 +168,7 @@ $> kubectl get secret secret-encrypted -o json | jq '.data | map_values(@base64d $> kind delete cluster -n kms # vault -$> kill $(pgrep -x vault) +$> kill $(pgrep -x vault) ``` ## Some last thoughts diff --git a/docs/sign.md b/docs/sign.md index 6e952a9..e8fd4bf 100644 --- a/docs/sign.md +++ b/docs/sign.md @@ -89,4 +89,4 @@ The following checks were performed on each of these signatures: } } ] -``` \ No newline at end of file +``` diff --git a/pkg/socket/socket.go b/pkg/socket/socket.go index 6807aa0..9d689db 100644 --- a/pkg/socket/socket.go +++ b/pkg/socket/socket.go @@ -2,8 +2,12 @@ package socket import ( "errors" + "fmt" "net" + "os" "strings" + + "go.uber.org/zap" ) // Socket represents a unix socket. @@ -32,6 +36,19 @@ func NewSocket(str string) (*Socket, error) { } // Listen listens on the current socket for connections. -func (s *Socket) Listen() (net.Listener, error) { +func (s *Socket) Listen(force bool) (net.Listener, error) { + // Remove the socket file if it already exists. + if _, err := os.Stat(s.Path); err == nil { + zap.L().Info("Socket already exists", zap.String("path", s.Path)) + + if force { + if err := os.Remove(s.Path); err != nil { + return nil, fmt.Errorf("failed to remove unix socket: %w", err) + } + + zap.L().Info("Socket overwrite is enabled. Successfully removed socket", zap.String("path", s.Path)) + } + } + return net.Listen(s.Network, s.Path) } diff --git a/pkg/socket/socket_test.go b/pkg/socket/socket_test.go index 59c7d05..167dc1f 100644 --- a/pkg/socket/socket_test.go +++ b/pkg/socket/socket_test.go @@ -1,7 +1,9 @@ package socket import ( + "os" "testing" + "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -41,3 +43,24 @@ func TestNewSocket(t *testing.T) { } } } + +func TestForce(t *testing.T) { + s := &Socket{"unix", "/tmp/vaultkms_test.socket"} + + //nolint: errcheck + go s.Listen(false) + + time.Sleep(3 * time.Second) + + _, err := s.Listen(false) + require.Error(t, err, "socket exists, no force, should error") + + time.Sleep(3 * time.Second) + + _, err = s.Listen(true) + require.NoError(t, err, "socket exists, force, should not error") + + t.Cleanup(func() { + os.Remove(s.Path) + }) +}