mirror of
https://github.com/appleboy/drone-ssh.git
synced 2026-06-16 14:49:25 +08:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b34fffdbd3 | |||
| d217773bac | |||
| ae023d7aa6 | |||
| 222545746b | |||
| a5f89304fd | |||
| a9cfc0c134 | |||
| 13ba21acf6 | |||
| e270b033d1 | |||
| aa9314a009 | |||
| 037e0231ac | |||
| ddf1b161aa | |||
| 32510c86bf | |||
| 80cecf1ed3 | |||
| c7dd9890fa | |||
| 905bb4cb1a | |||
| 066b72ac09 | |||
| b33ad90151 | |||
| c4f4d0f112 | |||
| 8b81da22bc |
@@ -13,12 +13,12 @@ name: "CodeQL"
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ master ]
|
branches: [master]
|
||||||
pull_request:
|
pull_request:
|
||||||
# The branches below must be a subset of the branches above
|
# The branches below must be a subset of the branches above
|
||||||
branches: [ master ]
|
branches: [master]
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '41 23 * * 6'
|
- cron: "41 23 * * 6"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
analyze:
|
analyze:
|
||||||
@@ -32,23 +32,23 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
language: [ 'go' ]
|
language: ["go"]
|
||||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||||
# Learn more about CodeQL language support at https://git.io/codeql-language-support
|
# Learn more about CodeQL language support at https://git.io/codeql-language-support
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v2
|
uses: github/codeql-action/init@v2
|
||||||
with:
|
with:
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||||
# By default, queries listed here will override any specified in a config file.
|
# By default, queries listed here will override any specified in a config file.
|
||||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v2
|
uses: github/codeql-action/analyze@v2
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ on:
|
|||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
tags:
|
tags:
|
||||||
- 'v*'
|
- "v*"
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- 'master'
|
- "master"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-docker:
|
build-docker:
|
||||||
@@ -17,42 +17,38 @@ jobs:
|
|||||||
- name: Setup go
|
- name: Setup go
|
||||||
uses: actions/setup-go@v4
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: '^1'
|
go-version: "^1.21"
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Build binary
|
- name: Build binary
|
||||||
run : |
|
run: |
|
||||||
make build_linux_amd64
|
make build_linux_amd64
|
||||||
make build_linux_arm
|
make build_linux_arm
|
||||||
make build_linux_arm64
|
make build_linux_arm64
|
||||||
-
|
|
||||||
name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v2
|
uses: docker/setup-qemu-action@v2
|
||||||
|
|
||||||
-
|
- name: Set up Docker Buildx
|
||||||
name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v2
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
-
|
- name: Login to Docker Hub
|
||||||
name: Login to Docker Hub
|
|
||||||
uses: docker/login-action@v2
|
uses: docker/login-action@v2
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
-
|
- name: Login to GitHub Container Registry
|
||||||
name: Login to GitHub Container Registry
|
|
||||||
uses: docker/login-action@v2
|
uses: docker/login-action@v2
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.repository_owner }}
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
-
|
- name: Docker meta
|
||||||
name: Docker meta
|
|
||||||
id: docker-meta
|
id: docker-meta
|
||||||
uses: docker/metadata-action@v4
|
uses: docker/metadata-action@v4
|
||||||
with:
|
with:
|
||||||
@@ -65,8 +61,7 @@ jobs:
|
|||||||
type=semver,pattern={{major}}.{{minor}}
|
type=semver,pattern={{major}}.{{minor}}
|
||||||
type=semver,pattern={{major}}
|
type=semver,pattern={{major}}
|
||||||
|
|
||||||
-
|
- name: Build and push
|
||||||
name: Build and push
|
|
||||||
uses: docker/build-push-action@v4
|
uses: docker/build-push-action@v4
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ name: Goreleaser
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
- '*'
|
- "*"
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
@@ -12,19 +12,16 @@ jobs:
|
|||||||
goreleaser:
|
goreleaser:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
-
|
- name: Checkout
|
||||||
name: Checkout
|
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
-
|
- name: Setup go
|
||||||
name: Setup go
|
|
||||||
uses: actions/setup-go@v4
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: '^1'
|
go-version: "^1"
|
||||||
|
|
||||||
-
|
- name: Run GoReleaser
|
||||||
name: Run GoReleaser
|
|
||||||
uses: goreleaser/goreleaser-action@v4
|
uses: goreleaser/goreleaser-action@v4
|
||||||
with:
|
with:
|
||||||
# either 'goreleaser' (default) or 'goreleaser-pro'
|
# either 'goreleaser' (default) or 'goreleaser-pro'
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ jobs:
|
|||||||
- name: Setup go
|
- name: Setup go
|
||||||
uses: actions/setup-go@v4
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: '^1'
|
go-version: "^1.21"
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: Setup golangci-lint
|
- name: Setup golangci-lint
|
||||||
@@ -27,14 +27,14 @@ jobs:
|
|||||||
|
|
||||||
testing:
|
testing:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container: golang:1.19-alpine
|
container: golang:1.21-alpine
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: setup sshd server
|
- name: setup sshd server
|
||||||
run: |
|
run: |
|
||||||
apk add git make curl perl bash build-base zlib-dev ucl-dev
|
apk add git make curl perl bash build-base zlib-dev ucl-dev sudo
|
||||||
make ssh-server
|
make ssh-server
|
||||||
|
|
||||||
- name: testing
|
- name: testing
|
||||||
|
|||||||
@@ -29,3 +29,4 @@ release
|
|||||||
drone-ssh
|
drone-ssh
|
||||||
.cover
|
.cover
|
||||||
dist
|
dist
|
||||||
|
bin
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
ignored:
|
||||||
|
- DL3018
|
||||||
|
- DL3008
|
||||||
@@ -178,6 +178,23 @@ Example configuration for passphrase which protecting a private key:
|
|||||||
- echo "you can't see the steps."
|
- echo "you can't see the steps."
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Example configuration for forcing protocol to IPv4 only:
|
||||||
|
|
||||||
|
```diff
|
||||||
|
- name: ssh commands
|
||||||
|
image: ghcr.io/appleboy/drone-ssh
|
||||||
|
settings:
|
||||||
|
host: foo.com
|
||||||
|
username: root
|
||||||
|
password: 1234
|
||||||
|
port: 22
|
||||||
|
+ protocol: tcp4
|
||||||
|
script:
|
||||||
|
- echo hello
|
||||||
|
- echo world
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## Secret Reference
|
## Secret Reference
|
||||||
|
|
||||||
| Key | Description |
|
| Key | Description |
|
||||||
@@ -197,6 +214,7 @@ Example configuration for passphrase which protecting a private key:
|
|||||||
|-----|-------------|
|
|-----|-------------|
|
||||||
| `host` | target hostname or IP |
|
| `host` | target hostname or IP |
|
||||||
| `port` | ssh port of target host |
|
| `port` | ssh port of target host |
|
||||||
|
| `protocol` | IP protocol to use: either tcp, tcp4 or tcp6 |
|
||||||
| `username` | account for target host user |
|
| `username` | account for target host user |
|
||||||
| `password` | password for target host user |
|
| `password` | password for target host user |
|
||||||
| `key` | plain text of user private key |
|
| `key` | plain text of user private key |
|
||||||
@@ -208,6 +226,7 @@ Example configuration for passphrase which protecting a private key:
|
|||||||
| `command_timeout` | Command timeout is the maximum amount of time for the execute commands, default is 10 minutes. |
|
| `command_timeout` | Command timeout is the maximum amount of time for the execute commands, default is 10 minutes. |
|
||||||
| `proxy_host` | proxy hostname or IP |
|
| `proxy_host` | proxy hostname or IP |
|
||||||
| `proxy_port` | ssh port of proxy host |
|
| `proxy_port` | ssh port of proxy host |
|
||||||
|
| `proxy_protocol` | IP protocol to use for the proxy: either tcp, tcp4 or tcp6 |
|
||||||
| `proxy_username` | account for proxy host user |
|
| `proxy_username` | account for proxy host user |
|
||||||
| `proxy_password` | password for proxy host user |
|
| `proxy_password` | password for proxy host user |
|
||||||
| `proxy_key` | plain text of proxy private key |
|
| `proxy_key` | plain text of proxy private key |
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ install: $(GOFILES)
|
|||||||
build: $(EXECUTABLE)
|
build: $(EXECUTABLE)
|
||||||
|
|
||||||
$(EXECUTABLE): $(GOFILES)
|
$(EXECUTABLE): $(GOFILES)
|
||||||
$(GO) build -v -tags '$(TAGS)' -ldflags '$(EXTLDFLAGS)-s -w $(LDFLAGS)' -o $@
|
$(GO) build -v -tags '$(TAGS)' -ldflags '$(EXTLDFLAGS)-s -w $(LDFLAGS)' -o bin/$@
|
||||||
|
|
||||||
build_linux_amd64:
|
build_linux_amd64:
|
||||||
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 $(GO) build -a -tags '$(TAGS)' -ldflags '$(EXTLDFLAGS)-s -w $(LDFLAGS)' -o release/linux/amd64/$(DEPLOY_IMAGE)
|
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 $(GO) build -a -tags '$(TAGS)' -ldflags '$(EXTLDFLAGS)-s -w $(LDFLAGS)' -o release/linux/amd64/$(DEPLOY_IMAGE)
|
||||||
@@ -104,6 +104,15 @@ ssh-server:
|
|||||||
cat tests/.ssh/test.pub >> /home/drone-scp/.ssh/authorized_keys
|
cat tests/.ssh/test.pub >> /home/drone-scp/.ssh/authorized_keys
|
||||||
chmod 600 /home/drone-scp/.ssh/authorized_keys
|
chmod 600 /home/drone-scp/.ssh/authorized_keys
|
||||||
chown -R drone-scp /home/drone-scp/.ssh
|
chown -R drone-scp /home/drone-scp/.ssh
|
||||||
|
# add public key to root user
|
||||||
|
mkdir -p /root/.ssh
|
||||||
|
chmod 700 /root/.ssh
|
||||||
|
cat tests/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys
|
||||||
|
cat tests/.ssh/test.pub >> /root/.ssh/authorized_keys
|
||||||
|
chmod 600 /root/.ssh/authorized_keys
|
||||||
|
# Append the following entry to run ALL command without a password for a user named drone-scp:
|
||||||
|
cat tests/sudoers >> /etc/sudoers.d/sudoers
|
||||||
|
# install ssh and start server
|
||||||
apk add --update openssh openrc
|
apk add --update openssh openrc
|
||||||
rm -rf /etc/ssh/ssh_host_rsa_key /etc/ssh/ssh_host_dsa_key
|
rm -rf /etc/ssh/ssh_host_rsa_key /etc/ssh/ssh_host_dsa_key
|
||||||
sed -i 's/^#PubkeyAuthentication yes/PubkeyAuthentication yes/g' /etc/ssh/sshd_config
|
sed -i 's/^#PubkeyAuthentication yes/PubkeyAuthentication yes/g' /etc/ssh/sshd_config
|
||||||
|
|||||||
+18
-1
@@ -12,9 +12,26 @@ LABEL org.opencontainers.image.source=https://github.com/appleboy/drone-ssh
|
|||||||
LABEL org.opencontainers.image.description="Execute commands on a remote host through SSH"
|
LABEL org.opencontainers.image.description="Execute commands on a remote host through SSH"
|
||||||
LABEL org.opencontainers.image.licenses=MIT
|
LABEL org.opencontainers.image.licenses=MIT
|
||||||
|
|
||||||
RUN apk add --no-cache ca-certificates=20220614-r4 && \
|
RUN apk add --no-cache ca-certificates && \
|
||||||
rm -rf /var/cache/apk/*
|
rm -rf /var/cache/apk/*
|
||||||
|
|
||||||
|
RUN addgroup \
|
||||||
|
-S -g 1000 \
|
||||||
|
deploy && \
|
||||||
|
adduser \
|
||||||
|
-S -H -D \
|
||||||
|
-h /home/deploy \
|
||||||
|
-s /bin/sh \
|
||||||
|
-u 1000 \
|
||||||
|
-G deploy \
|
||||||
|
deploy
|
||||||
|
|
||||||
|
RUN mkdir -p /home/deploy && \
|
||||||
|
chown deploy:deploy /home/deploy
|
||||||
|
|
||||||
|
# deploy:deploy
|
||||||
|
USER 1000:1000
|
||||||
|
|
||||||
COPY release/${TARGETOS}/${TARGETARCH}/drone-ssh /bin/
|
COPY release/${TARGETOS}/${TARGETARCH}/drone-ssh /bin/
|
||||||
|
|
||||||
ENTRYPOINT ["/bin/drone-ssh"]
|
ENTRYPOINT ["/bin/drone-ssh"]
|
||||||
|
|||||||
@@ -3,21 +3,21 @@ module github.com/appleboy/drone-ssh
|
|||||||
go 1.18
|
go 1.18
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/appleboy/easyssh-proxy v1.3.10
|
github.com/appleboy/easyssh-proxy v1.5.0
|
||||||
github.com/joho/godotenv v1.5.1
|
github.com/joho/godotenv v1.5.1
|
||||||
github.com/stretchr/testify v1.8.2
|
github.com/stretchr/testify v1.8.4
|
||||||
github.com/urfave/cli/v2 v2.25.3
|
github.com/urfave/cli/v2 v2.27.1
|
||||||
golang.org/x/crypto v0.8.0
|
golang.org/x/crypto v0.17.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/ScaleFT/sshkeys v1.2.0 // indirect
|
github.com/ScaleFT/sshkeys v1.2.0 // indirect
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a // indirect
|
github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
github.com/xrash/smetrics v0.0.0-20231213231151-1d8dd44e695e // indirect
|
||||||
golang.org/x/sys v0.8.0 // indirect
|
golang.org/x/sys v0.16.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
github.com/ScaleFT/sshkeys v1.2.0 h1:5BRp6rTVIhJzXT3VcUQrKgXR8zWA3sOsNeuyW15WUA8=
|
github.com/ScaleFT/sshkeys v1.2.0 h1:5BRp6rTVIhJzXT3VcUQrKgXR8zWA3sOsNeuyW15WUA8=
|
||||||
github.com/ScaleFT/sshkeys v1.2.0/go.mod h1:gxOHeajFfvGQh/fxlC8oOKBe23xnnJTif00IFFbiT+o=
|
github.com/ScaleFT/sshkeys v1.2.0/go.mod h1:gxOHeajFfvGQh/fxlC8oOKBe23xnnJTif00IFFbiT+o=
|
||||||
github.com/appleboy/easyssh-proxy v1.3.10 h1:iriF68tlrYoxgWhS7t7Wyr0FA+hJlOem5tMfm+RDlx4=
|
github.com/appleboy/easyssh-proxy v1.5.0 h1:OYdSPvYQN3mhnsMH5I2OF1TgwSEcSq33kvjQfTwvZww=
|
||||||
github.com/appleboy/easyssh-proxy v1.3.10/go.mod h1:T81pu/Cxx/zf/7YXhFCFiucBa4xeQ81ci5b0PFnMRJc=
|
github.com/appleboy/easyssh-proxy v1.5.0/go.mod h1:zcEMrStH91/tcUn3gUGP0KpQwUYLm8tX/Ook1AH98uc=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
|
github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
@@ -16,32 +16,27 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
|
|||||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
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/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
|
||||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
github.com/urfave/cli/v2 v2.27.1 h1:8xSQ6szndafKVRmfyeUMxkNUJQMjL1F2zmsZ+qHpfho=
|
||||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/urfave/cli/v2 v2.27.1/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
|
||||||
github.com/urfave/cli/v2 v2.25.3 h1:VJkt6wvEBOoSjPFQvOkv6iWIrsJyCrKGtCtxXWwmGeY=
|
github.com/xrash/smetrics v0.0.0-20231213231151-1d8dd44e695e h1:+SOyEddqYF09QP7vr7CgJ1eti3pY9Fn3LHO1M1r/0sI=
|
||||||
github.com/urfave/cli/v2 v2.25.3/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc=
|
github.com/xrash/smetrics v0.0.0-20231213231151-1d8dd44e695e/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
|
||||||
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=
|
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ=
|
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
|
||||||
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
|
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200219091948-cb0a6d8edb6c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200219091948-cb0a6d8edb6c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
|
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
||||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ=
|
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
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=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|||||||
@@ -51,6 +51,12 @@ func main() {
|
|||||||
EnvVars: []string{"PLUGIN_PORT", "SSH_PORT", "INPUT_PORT"},
|
EnvVars: []string{"PLUGIN_PORT", "SSH_PORT", "INPUT_PORT"},
|
||||||
Value: 22,
|
Value: 22,
|
||||||
},
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "protocol",
|
||||||
|
Usage: "The IP protocol to use. Default to tcp (both IPv4 and IPv6).",
|
||||||
|
EnvVars: []string{"PLUGIN_PROTOCOL", "SSH_PROTOCOL", "INPUT_PROTOCOL"},
|
||||||
|
Value: "tcp",
|
||||||
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "username",
|
Name: "username",
|
||||||
Aliases: []string{"user", "u"},
|
Aliases: []string{"user", "u"},
|
||||||
@@ -141,6 +147,12 @@ func main() {
|
|||||||
EnvVars: []string{"PLUGIN_PROXY_PORT", "PROXY_SSH_PORT", "INPUT_PROXY_PORT"},
|
EnvVars: []string{"PLUGIN_PROXY_PORT", "PROXY_SSH_PORT", "INPUT_PROXY_PORT"},
|
||||||
Value: "22",
|
Value: "22",
|
||||||
},
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "proxy.protocol",
|
||||||
|
Usage: "The IP protocol to use for the proxy. Default to tcp (both IPv4 and IPv6).",
|
||||||
|
EnvVars: []string{"PLUGIN_PROTOCOL", "SSH_PROTOCOL", "INPUT_PROTOCOL"},
|
||||||
|
Value: "tcp",
|
||||||
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "proxy.username",
|
Name: "proxy.username",
|
||||||
Usage: "connect as user of proxy",
|
Usage: "connect as user of proxy",
|
||||||
@@ -203,6 +215,16 @@ func main() {
|
|||||||
EnvVars: []string{"PLUGIN_ENVS_FORMAT", "INPUT_ENVS_FORMAT"},
|
EnvVars: []string{"PLUGIN_ENVS_FORMAT", "INPUT_ENVS_FORMAT"},
|
||||||
Value: envsFormat,
|
Value: envsFormat,
|
||||||
},
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "allenvs",
|
||||||
|
Usage: "pass all environment variable to shell script",
|
||||||
|
EnvVars: []string{"PLUGIN_ALLENVS", "INPUT_ALLENVS"},
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "request-pty",
|
||||||
|
Usage: "request a pseudo-terminal from the server",
|
||||||
|
EnvVars: []string{"PLUGIN_REQUEST_PTY", "INPUT_REQUEST_PTY"},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Override a template
|
// Override a template
|
||||||
@@ -259,6 +281,7 @@ func run(c *cli.Context) error {
|
|||||||
Fingerprint: c.String("fingerprint"),
|
Fingerprint: c.String("fingerprint"),
|
||||||
Host: c.StringSlice("host"),
|
Host: c.StringSlice("host"),
|
||||||
Port: c.Int("port"),
|
Port: c.Int("port"),
|
||||||
|
Protocol: easyssh.Protocol(c.String("protocol")),
|
||||||
Timeout: c.Duration("timeout"),
|
Timeout: c.Duration("timeout"),
|
||||||
CommandTimeout: c.Duration("command.timeout"),
|
CommandTimeout: c.Duration("command.timeout"),
|
||||||
Script: scripts,
|
Script: scripts,
|
||||||
@@ -269,6 +292,8 @@ func run(c *cli.Context) error {
|
|||||||
Sync: c.Bool("sync"),
|
Sync: c.Bool("sync"),
|
||||||
Ciphers: c.StringSlice("ciphers"),
|
Ciphers: c.StringSlice("ciphers"),
|
||||||
UseInsecureCipher: c.Bool("useInsecureCipher"),
|
UseInsecureCipher: c.Bool("useInsecureCipher"),
|
||||||
|
AllEnvs: c.Bool("allenvs"),
|
||||||
|
RequireTty: c.Bool("request-pty"),
|
||||||
Proxy: easyssh.DefaultConfig{
|
Proxy: easyssh.DefaultConfig{
|
||||||
Key: c.String("proxy.ssh-key"),
|
Key: c.String("proxy.ssh-key"),
|
||||||
KeyPath: c.String("proxy.key-path"),
|
KeyPath: c.String("proxy.key-path"),
|
||||||
@@ -278,6 +303,7 @@ func run(c *cli.Context) error {
|
|||||||
Fingerprint: c.String("proxy.fingerprint"),
|
Fingerprint: c.String("proxy.fingerprint"),
|
||||||
Server: c.String("proxy.host"),
|
Server: c.String("proxy.host"),
|
||||||
Port: c.String("proxy.port"),
|
Port: c.String("proxy.port"),
|
||||||
|
Protocol: easyssh.Protocol(c.String("proxy.protocol")),
|
||||||
Timeout: c.Duration("proxy.timeout"),
|
Timeout: c.Duration("proxy.timeout"),
|
||||||
Ciphers: c.StringSlice("proxy.ciphers"),
|
Ciphers: c.StringSlice("proxy.ciphers"),
|
||||||
UseInsecureCipher: c.Bool("proxy.useInsecureCipher"),
|
UseInsecureCipher: c.Bool("proxy.useInsecureCipher"),
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ type (
|
|||||||
Password string
|
Password string
|
||||||
Host []string
|
Host []string
|
||||||
Port int
|
Port int
|
||||||
|
Protocol easyssh.Protocol
|
||||||
Fingerprint string
|
Fingerprint string
|
||||||
Timeout time.Duration
|
Timeout time.Duration
|
||||||
CommandTimeout time.Duration
|
CommandTimeout time.Duration
|
||||||
@@ -42,6 +43,8 @@ type (
|
|||||||
Ciphers []string
|
Ciphers []string
|
||||||
UseInsecureCipher bool
|
UseInsecureCipher bool
|
||||||
EnvsFormat string
|
EnvsFormat string
|
||||||
|
AllEnvs bool
|
||||||
|
RequireTty bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Plugin structure
|
// Plugin structure
|
||||||
@@ -75,6 +78,7 @@ func (p Plugin) exec(host string, wg *sync.WaitGroup, errChannel chan error) {
|
|||||||
User: p.Config.Username,
|
User: p.Config.Username,
|
||||||
Password: p.Config.Password,
|
Password: p.Config.Password,
|
||||||
Port: port,
|
Port: port,
|
||||||
|
Protocol: p.Config.Protocol,
|
||||||
Key: p.Config.Key,
|
Key: p.Config.Key,
|
||||||
KeyPath: p.Config.KeyPath,
|
KeyPath: p.Config.KeyPath,
|
||||||
Passphrase: p.Config.Passphrase,
|
Passphrase: p.Config.Passphrase,
|
||||||
@@ -82,11 +86,13 @@ func (p Plugin) exec(host string, wg *sync.WaitGroup, errChannel chan error) {
|
|||||||
Ciphers: p.Config.Ciphers,
|
Ciphers: p.Config.Ciphers,
|
||||||
Fingerprint: p.Config.Fingerprint,
|
Fingerprint: p.Config.Fingerprint,
|
||||||
UseInsecureCipher: p.Config.UseInsecureCipher,
|
UseInsecureCipher: p.Config.UseInsecureCipher,
|
||||||
|
RequestPty: p.Config.RequireTty,
|
||||||
Proxy: easyssh.DefaultConfig{
|
Proxy: easyssh.DefaultConfig{
|
||||||
Server: p.Config.Proxy.Server,
|
Server: p.Config.Proxy.Server,
|
||||||
User: p.Config.Proxy.User,
|
User: p.Config.Proxy.User,
|
||||||
Password: p.Config.Proxy.Password,
|
Password: p.Config.Proxy.Password,
|
||||||
Port: p.Config.Proxy.Port,
|
Port: p.Config.Proxy.Port,
|
||||||
|
Protocol: p.Config.Proxy.Protocol,
|
||||||
Key: p.Config.Proxy.Key,
|
Key: p.Config.Proxy.Key,
|
||||||
KeyPath: p.Config.Proxy.KeyPath,
|
KeyPath: p.Config.Proxy.KeyPath,
|
||||||
Passphrase: p.Config.Proxy.Passphrase,
|
Passphrase: p.Config.Proxy.Passphrase,
|
||||||
@@ -102,6 +108,10 @@ func (p Plugin) exec(host string, wg *sync.WaitGroup, errChannel chan error) {
|
|||||||
p.log(host, "======END======")
|
p.log(host, "======END======")
|
||||||
|
|
||||||
env := []string{}
|
env := []string{}
|
||||||
|
if p.Config.AllEnvs {
|
||||||
|
allenvs := findEnvs("DRONE_", "PLUGIN_", "INPUT_", "GITHUB_")
|
||||||
|
p.Config.Envs = append(p.Config.Envs, allenvs...)
|
||||||
|
}
|
||||||
for _, key := range p.Config.Envs {
|
for _, key := range p.Config.Envs {
|
||||||
key = strings.ToUpper(key)
|
key = strings.ToUpper(key)
|
||||||
if val, found := os.LookupEnv(key); found {
|
if val, found := os.LookupEnv(key); found {
|
||||||
@@ -152,20 +162,23 @@ loop:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// format string
|
||||||
func (p Plugin) format(format string, args ...string) string {
|
func (p Plugin) format(format string, args ...string) string {
|
||||||
r := strings.NewReplacer(args...)
|
r := strings.NewReplacer(args...)
|
||||||
return r.Replace(format)
|
return r.Replace(format)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// log output to console
|
||||||
func (p Plugin) log(host string, message ...interface{}) {
|
func (p Plugin) log(host string, message ...interface{}) {
|
||||||
if p.Writer == nil {
|
if p.Writer == nil {
|
||||||
p.Writer = os.Stdout
|
p.Writer = os.Stdout
|
||||||
}
|
}
|
||||||
if count := len(p.Config.Host); count == 1 {
|
if count := len(p.Config.Host); count == 1 {
|
||||||
fmt.Fprintf(p.Writer, "%s", fmt.Sprintln(message...))
|
fmt.Fprintf(p.Writer, "%s", fmt.Sprintln(message...))
|
||||||
} else {
|
return
|
||||||
fmt.Fprintf(p.Writer, "%s: %s", host, fmt.Sprintln(message...))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(p.Writer, "%s: %s", host, fmt.Sprintln(message...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exec executes the plugin.
|
// Exec executes the plugin.
|
||||||
@@ -261,3 +274,18 @@ func trimValues(keys []string) []string {
|
|||||||
|
|
||||||
return newKeys
|
return newKeys
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Find all envs from specified prefix
|
||||||
|
func findEnvs(prefix ...string) []string {
|
||||||
|
envs := []string{}
|
||||||
|
for _, e := range os.Environ() {
|
||||||
|
for _, p := range prefix {
|
||||||
|
if strings.HasPrefix(e, p) {
|
||||||
|
e = strings.Split(e, "=")[0]
|
||||||
|
envs = append(envs, e)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return envs
|
||||||
|
}
|
||||||
|
|||||||
+160
@@ -113,6 +113,40 @@ func TestSSHScriptFromKeyFile(t *testing.T) {
|
|||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSSHIPv4Only(t *testing.T) {
|
||||||
|
plugin := Plugin{
|
||||||
|
Config: Config{
|
||||||
|
Host: []string{"localhost", "127.0.0.1"},
|
||||||
|
Username: "drone-scp",
|
||||||
|
Port: 22,
|
||||||
|
Protocol: easyssh.PROTOCOL_TCP4,
|
||||||
|
KeyPath: "./tests/.ssh/id_rsa",
|
||||||
|
Script: []string{"whoami", "ls -al"},
|
||||||
|
CommandTimeout: 60 * time.Second,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
err := plugin.Exec()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSSHIPv6OnlyError(t *testing.T) {
|
||||||
|
plugin := Plugin{
|
||||||
|
Config: Config{
|
||||||
|
Host: []string{"127.0.0.1"},
|
||||||
|
Username: "drone-scp",
|
||||||
|
Port: 22,
|
||||||
|
Protocol: easyssh.PROTOCOL_TCP6,
|
||||||
|
KeyPath: "./tests/.ssh/id_rsa",
|
||||||
|
Script: []string{"whoami", "ls -al"},
|
||||||
|
CommandTimeout: 60 * time.Second,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
err := plugin.Exec()
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
func TestStreamFromSSHCommand(t *testing.T) {
|
func TestStreamFromSSHCommand(t *testing.T) {
|
||||||
plugin := Plugin{
|
plugin := Plugin{
|
||||||
Config: Config{
|
Config: Config{
|
||||||
@@ -789,3 +823,129 @@ func TestPlugin_hostPort(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFindEnvs(t *testing.T) {
|
||||||
|
testEnvs := []string{
|
||||||
|
"INPUT_FOO",
|
||||||
|
"INPUT_BAR",
|
||||||
|
"NO_PREFIX",
|
||||||
|
"INPUT_FOOBAR",
|
||||||
|
}
|
||||||
|
|
||||||
|
origEnviron := os.Environ()
|
||||||
|
os.Clearenv()
|
||||||
|
for _, env := range testEnvs {
|
||||||
|
os.Setenv(env, "dummyValue")
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
os.Clearenv()
|
||||||
|
for _, env := range origEnviron {
|
||||||
|
pair := strings.SplitN(env, "=", 2)
|
||||||
|
os.Setenv(pair[0], pair[1])
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
t.Run("Find single prefix", func(t *testing.T) {
|
||||||
|
expected := []string{"INPUT_FOO", "INPUT_BAR", "INPUT_FOOBAR"}
|
||||||
|
result := findEnvs("INPUT_")
|
||||||
|
if !reflect.DeepEqual(result, expected) {
|
||||||
|
t.Errorf("Expected %v, but got %v", expected, result)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Find multiple prefixes", func(t *testing.T) {
|
||||||
|
expected := []string{"INPUT_FOO", "INPUT_BAR", "NO_PREFIX", "INPUT_FOOBAR"}
|
||||||
|
result := findEnvs("INPUT_", "NO_PREFIX")
|
||||||
|
if !reflect.DeepEqual(result, expected) {
|
||||||
|
t.Errorf("Expected %v, but got %v", expected, result)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Find non-existing prefix", func(t *testing.T) {
|
||||||
|
expected := []string{}
|
||||||
|
result := findEnvs("NON_EXISTING_")
|
||||||
|
if !reflect.DeepEqual(result, expected) {
|
||||||
|
t.Errorf("Expected %v, but got %v", expected, result)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAllEnvs(t *testing.T) {
|
||||||
|
var (
|
||||||
|
buffer bytes.Buffer
|
||||||
|
expected = `
|
||||||
|
======CMD======
|
||||||
|
echo "[${INPUT_1}]"
|
||||||
|
echo "[${GITHUB_2}]"
|
||||||
|
echo "[${PLUGIN_3}]"
|
||||||
|
======END======
|
||||||
|
out: [foobar]
|
||||||
|
out: [foobar]
|
||||||
|
out: [foobar]
|
||||||
|
`
|
||||||
|
)
|
||||||
|
|
||||||
|
os.Setenv("INPUT_1", `foobar`)
|
||||||
|
os.Setenv("GITHUB_2", `foobar`)
|
||||||
|
os.Setenv("PLUGIN_3", `foobar`)
|
||||||
|
|
||||||
|
plugin := Plugin{
|
||||||
|
Config: Config{
|
||||||
|
Host: []string{"localhost"},
|
||||||
|
Username: "drone-scp",
|
||||||
|
Port: 22,
|
||||||
|
KeyPath: "./tests/.ssh/test",
|
||||||
|
Passphrase: "1234",
|
||||||
|
AllEnvs: true,
|
||||||
|
Script: []string{
|
||||||
|
`echo "[${INPUT_1}]"`,
|
||||||
|
`echo "[${GITHUB_2}]"`,
|
||||||
|
`echo "[${PLUGIN_3}]"`,
|
||||||
|
},
|
||||||
|
CommandTimeout: 10 * time.Second,
|
||||||
|
Proxy: easyssh.DefaultConfig{
|
||||||
|
Server: "localhost",
|
||||||
|
User: "drone-scp",
|
||||||
|
Port: "22",
|
||||||
|
KeyPath: "./tests/.ssh/id_rsa",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Writer: &buffer,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := plugin.Exec()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, unindent(expected), unindent(buffer.String()))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSudoCommand(t *testing.T) {
|
||||||
|
var (
|
||||||
|
buffer bytes.Buffer
|
||||||
|
expected = `
|
||||||
|
======CMD======
|
||||||
|
sudo su - -c "whoami"
|
||||||
|
======END======
|
||||||
|
out: root
|
||||||
|
`
|
||||||
|
)
|
||||||
|
|
||||||
|
plugin := Plugin{
|
||||||
|
Config: Config{
|
||||||
|
Host: []string{"localhost"},
|
||||||
|
Username: "drone-scp",
|
||||||
|
Port: 22,
|
||||||
|
KeyPath: "./tests/.ssh/id_rsa",
|
||||||
|
Script: []string{
|
||||||
|
`sudo su - -c "whoami"`,
|
||||||
|
},
|
||||||
|
CommandTimeout: 10 * time.Second,
|
||||||
|
RequireTty: true,
|
||||||
|
},
|
||||||
|
Writer: &buffer,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Nil(t, plugin.Exec())
|
||||||
|
assert.Equal(t, unindent(expected), unindent(buffer.String()))
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
Defaults requiretty
|
||||||
|
drone-scp ALL=(ALL) NOPASSWD:ALL
|
||||||
Reference in New Issue
Block a user