Skip to content

Commit ca124ca

Browse files
committed
feat: Ajouter un workflow GitHub pour construire et scanner l'image Docker SFTP
1 parent ae12225 commit ca124ca

8 files changed

Lines changed: 610 additions & 0 deletions

File tree

.github/workflows/build-sftp.yml

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
name: Build SFTP Docker Image
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
paths:
8+
- sftp/**
9+
- .github/workflows/build-sftp.yml
10+
pull_request:
11+
branches:
12+
- main
13+
paths:
14+
- sftp/**
15+
- .github/workflows/build-sftp.yml
16+
17+
18+
env:
19+
REGISTRY: ghcr.io
20+
IMAGE_NAME: yieldstudio/sftp
21+
22+
jobs:
23+
build:
24+
runs-on: ubuntu-latest
25+
permissions:
26+
contents: read
27+
packages: write
28+
id-token: write
29+
steps:
30+
- name: Checkout code
31+
uses: actions/checkout@v4
32+
33+
- name: Set up QEMU
34+
uses: docker/setup-qemu-action@v3
35+
36+
- name: Set up Docker Buildx
37+
uses: docker/setup-buildx-action@v3
38+
39+
- name: Log into registry ${{ env.REGISTRY }}
40+
if: github.event_name != 'pull_request'
41+
uses: docker/login-action@v3
42+
with:
43+
registry: ${{ env.REGISTRY }}
44+
username: ${{ github.actor }}
45+
password: ${{ secrets.GITHUB_TOKEN }}
46+
47+
- name: Extract Docker metadata
48+
id: meta
49+
uses: docker/metadata-action@v4
50+
with:
51+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
52+
tags: |
53+
type=ref,event=branch,prefix=
54+
type=ref,event=tag,prefix=v
55+
type=sha,prefix=
56+
type=raw
57+
58+
- name: Build docker image
59+
uses: docker/build-push-action@v6
60+
with:
61+
context: ./sftp
62+
file: ./sftp/Dockerfile
63+
platforms: linux/amd64,linux/arm64
64+
cache-from: type=gha,scope=sftp
65+
cache-to: type=gha,scope=sftp,mode=max
66+
push: ${{ github.event_name != 'pull_request' }}
67+
tags: |
68+
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
69+
${{ steps.meta.outputs.tags }}
70+
labels: ${{ steps.meta.outputs.labels }}
71+
72+
scan:
73+
if: github.event_name != 'pull_request'
74+
needs:
75+
- build
76+
runs-on: ubuntu-latest
77+
steps:
78+
- name: Checkout Code
79+
uses: actions/checkout@v4
80+
81+
- name: Get Short SHA
82+
id: get_short_sha
83+
run: echo "SHORT_SHA=$(echo $GITHUB_SHA | cut -c1-7)" >> $GITHUB_ENV
84+
85+
- name: Run Trivy Vulnerability Scan
86+
uses: aquasecurity/trivy-action@0.31.0
87+
with:
88+
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.SHORT_SHA }}
89+
format: 'sarif'
90+
output: 'trivy-results.sarif'
91+
ignore-unfixed: true
92+
severity: 'CRITICAL,HIGH,MEDIUM'
93+
vuln-type: 'os,library'
94+
95+
- name: Upload Trivy scan results to GitHub Security tab
96+
uses: github/codeql-action/upload-sarif@v3
97+
if: always()
98+
with:
99+
sarif_file: 'trivy-results.sarif'
100+
101+

sftp/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.DS_Store
2+
docker-compose.yaml

sftp/Dockerfile

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
FROM alpine:latest
2+
3+
# Steps done in one RUN layer:
4+
# - Install upgrades and new packages
5+
# - OpenSSH needs /var/run/sshd to run
6+
# - Remove generic host keys, entrypoint generates unique keys
7+
RUN apk update && apk upgrade && \
8+
apk add bash shadow openssh-server-pam openssh-sftp-server s3fs-fuse && \
9+
rm -rf /var/cache/apk/* && \
10+
ln -s /usr/sbin/sshd.pam /usr/sbin/sshd && \
11+
mkdir -p /var/run/sshd && \
12+
rm -f /etc/ssh/ssh_host_*key*
13+
14+
COPY --chmod=755 common/ /
15+
16+
EXPOSE 22
17+
18+
ENTRYPOINT ["docker-sftp-entrypoint"]

sftp/README.md

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
# SFTP
2+
3+
Easy to use SFTP ([SSH File Transfer Protocol](https://en.wikipedia.org/wiki/SSH_File_Transfer_Protocol)) server with [OpenSSH](https://en.wikipedia.org/wiki/OpenSSH).
4+
5+
# Usage
6+
7+
- Define users in (1) command arguments, (2) `SFTP_USERS` environment variable
8+
or (3) in file mounted as `/etc/sftp/users.conf` (syntax:
9+
`user:pass[:e][:uid[:gid[:dir1[,dir2]...]]] ...`, see below for examples)
10+
- Set UID/GID manually for your users if you want them to make changes to
11+
your mounted volumes with permissions matching your host filesystem.
12+
- Directory names at the end will be created under user's home directory with
13+
write permission, if they aren't already present.
14+
- Mount volumes
15+
- The users are chrooted to their home directory, so you can mount the
16+
volumes in separate directories inside the user's home directory
17+
(/home/user/**mounted-directory**) or just mount the whole **/home** directory.
18+
Just remember that the users can't create new files directly under their
19+
own home directory, so make sure there are at least one subdirectory if you
20+
want them to upload files.
21+
- For consistent server fingerprint, mount your own host keys (i.e. `/etc/ssh/ssh_host_*`)
22+
23+
# Examples
24+
25+
## Simplest docker run example
26+
27+
```
28+
docker run -p 22:22 -d yieldstudio/sftp foo:pass:::upload
29+
```
30+
31+
User "foo" with password "pass" can login with sftp and upload files to a folder called "upload". No mounted directories or custom UID/GID. Later you can inspect the files and use `--volumes-from` to mount them somewhere else (or see next example).
32+
33+
## Sharing a directory from your computer
34+
35+
Let's mount a directory and set UID:
36+
37+
```
38+
docker run \
39+
-v <host-dir>/upload:/home/foo/upload \
40+
-p 2222:22 -d yieldstudio/sftp \
41+
foo:pass:1001
42+
```
43+
44+
### Using Docker Compose:
45+
46+
```
47+
sftp:
48+
image: yieldstudio/sftp
49+
volumes:
50+
- <host-dir>/upload:/home/foo/upload
51+
ports:
52+
- "2222:22"
53+
command: foo:pass:1001
54+
```
55+
56+
### Logging in
57+
58+
The OpenSSH server runs by default on port 22, and in this example, we are forwarding the container's port 22 to the host's port 2222. To log in with the OpenSSH client, run: `sftp -P 2222 foo@<host-ip>`
59+
60+
## Store users in config
61+
62+
```
63+
docker run \
64+
-v <host-dir>/users.conf:/etc/sftp/users.conf:ro \
65+
-v mySftpVolume:/home \
66+
-p 2222:22 -d yieldstudio/sftp
67+
```
68+
69+
<host-dir>/users.conf:
70+
71+
```
72+
foo:123:1001:100
73+
bar:abc:1002:100
74+
baz:xyz:1003:100
75+
```
76+
77+
## Providing your own SSH host key (recommended)
78+
79+
This container will generate new SSH host keys at first run. To avoid that your users get a MITM warning when you recreate your container (and the host keys changes), you can mount your own host keys.
80+
81+
```
82+
docker run \
83+
-v <host-dir>/ssh_host_ed25519_key:/etc/ssh/ssh_host_ed25519_key \
84+
-v <host-dir>/ssh_host_rsa_key:/etc/ssh/ssh_host_rsa_key \
85+
-v <host-dir>/share:/home/foo/share \
86+
-p 2222:22 -d yieldstudio/sftp \
87+
foo::1001
88+
```
89+
90+
You can also setup the host keys with `SSH_ED25519_KEY` and `SSH_RSA_KEY` environment variables (base64 encoded).
91+
92+
```
93+
docker run \
94+
-e SSH_ED25519_KEY=$(cat <host-dir>/ssh_host_ed25519_key | base64) \
95+
-e SSH_RSA_KEY=$(cat <host-dir>/ssh_host_rsa_key | base64) \
96+
-v <host-dir>/share:/home/foo/share \
97+
-p 2222:22 -d yieldstudio/sftp \
98+
foo::1001
99+
```
100+
101+
Tip: you can generate your keys with these commands:
102+
103+
```
104+
ssh-keygen -t ed25519 -f ssh_host_ed25519_key < /dev/null
105+
ssh-keygen -t rsa -b 4096 -f ssh_host_rsa_key < /dev/null
106+
```
107+
108+
**NOTE:** Using `mount` requires that your container runs with the `CAP_SYS_ADMIN` capability turned on. [See this answer for more information](https://github.com/yieldstudio/sftp/issues/60#issuecomment-332909232).
109+
110+
## S3FS Mounting
111+
112+
You can mount an S3 bucket using s3fs. You need to provide your AWS credentials and the bucket name as environment variables. You also need to install s3fs in the container. You can do this by creating a custom Dockerfile that extends the yieldstudio/sftp image.
113+
114+
```
115+
docker run \
116+
-e ENABLE_S3FS=true \
117+
-e AWS_S3_BUCKET=<your-bucket-name> \
118+
-e AWS_S3_ACCESS_KEY_ID=<your-access-key-id> \
119+
-e AWS_S3_SECRET_ACCESS_KEY=<your-secret-access-key> \
120+
-p 2222:22 -d yieldstudio/sftp \
121+
foo::1001
122+
```
123+
124+
### Scaleway S3
125+
126+
If you are using Scaleway S3, you need to provide the endpoint as well.
127+
128+
```
129+
docker run \
130+
-e ENABLE_S3FS=true \
131+
-e AWS_S3_BUCKET=<your-bucket-name> \
132+
-e AWS_S3_ACCESS_KEY_ID=<your-access-key-id> \
133+
-e AWS_S3_SECRET_ACCESS_KEY=<your-secret-access-key> \
134+
-e AWS_S3_URL="https://s3.<region>.scw.cloud" \
135+
-e S3FS_ARGS="allow_other,use_path_request_style,nocopyapi,parallel_count=15,multipart_size=128" \
136+
-e SFTP_USERS="foo::1001" \
137+
-p 2222:22 -d yieldstudio/sftp
138+
```

sftp/common/etc/ssh/sshd_config

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Secure defaults
2+
# See: https://stribika.github.io/2015/01/04/secure-secure-shell.html
3+
Protocol 2
4+
HostKey /etc/ssh/ssh_host_ed25519_key
5+
HostKey /etc/ssh/ssh_host_rsa_key
6+
7+
# Faster connection
8+
# See: https://github.com/atmoz/sftp/issues/11
9+
UseDNS no
10+
11+
# Limited access
12+
PermitRootLogin no
13+
X11Forwarding no
14+
AllowTcpForwarding no
15+
16+
# Force sftp and chroot jail
17+
Subsystem sftp internal-sftp
18+
ForceCommand internal-sftp
19+
ChrootDirectory %h
20+
21+
# Enable this for more logs
22+
#LogLevel VERBOSE
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/bin/bash
2+
3+
if [ -d "$1" ]; then
4+
mkdir -p "$2"
5+
fi
6+
mount --bind $3 "$1" "$2"

0 commit comments

Comments
 (0)