在 Trace transfer.sh open project 有提到我目前正在調整 transfer.sh 這個 open source project,把它修改成內部所需要的一個 service,而之前已經改得差不多了,所以簡單地來介紹一下修改了哪些內容:
需求
- 每個 download request 能依需求驗證 IP address 和 user account / password
- 能使用外部 service 來驗證 user account
- 需能支援 curl cmd tool
- k8s deployment
修改項目
1. Middleware Chain
根據需求 1,在 getHandler
前加入 middleware chain,其中包含:
- 從 metadata storage 中取出 metadata 並放到 context 中
- IP address 驗證 (optional)
- HTTP basic authentication (optional)
之所以使用 HTTP basic authentication 是因為部分用戶可能會直接使用 curl 下載,那麼用 HTTP basic authentication 流程較簡單又方便,缺點是在瀏覽器上操作會跳出預設的 basic authentication 介面,看起來有點醜。
1r.HandleFunc("/{token}/{filename}",
2 s.AssignMetadata(MetadataAllowedIP(s.MetadataBasicAuth(http.HandlerFunc(getHandlerFn)))),
3).Methods("GET")
2. Authenticator interface
增加 Authenticator
interface,這樣就可以選擇是要透過 metadata 中的 username / password 來進行驗證,還是要使用 API 連結到其他 service 進行驗證。(目前也只實作 metadata 和API 兩個 Authenticators XD)
另外,在 API Authenticator 也可以自行加入想要的 header,這是因為在 cloud service 間可能會透過 api-key 這種方式來進行 request 驗證,所以 header 設定還是有其必要。
3. Metadata
request 驗證規則會儲存在 metadata 中。原本 project 就有 metadata 的設計,其內容是放置 delete code、到期日期、下載次數等。而在這次修改中則是增加了 AuthTypes
user
password
IP
net
等欄位,讓我們可以進行 IP filter 和 basic authentication。
正也因為 metadata 放入了驗證規則,每次 request 就必須取出對應的 metadata,因此原設計是將 metadata 存放在檔案內,現在看起來會有點不適用。在考量 metadata 的 bytes size 不大,放在 memory 中是一個可行的方式,所以額外增加了 metadata storage,並且實作了 redis storage,來加快 metadata 讀取速度。
4. Cmd Options
由於上面的新增項目,因此也在 cmd options 中增加對應的參數設定,並且也增加 environment variable,方便後續 deploy 。
Parameter | Description | Value | Env |
---|---|---|---|
api-endpoint | the endpoint for api authenticator | API_ENDPOINT | |
api-headers | the HTTP(s) headers for api authenticator | API_HEADERS | |
meta-provider | which storage provider to use | (s3, gdrive, local, redis) | |
redis-addr | The address of redis server | localhost:6379 | REDIS_ADDR |
redis-pwd | The password of redis server | REDIS_PWD |
Usage
Container: cjamhe01385/transfer
提供 container 試用:
- 啟動 container
1docker run --rm -p 8080:8080 cjamhe01385/transfer:latest --listener=":8080" --provider="local" --basedir="/data" --http-auth-user="user" --http-auth-pass="password" --meta-provider="redis" --redis-addr="redis:6379"
- 在上傳檔案同時加入驗證規則 (記得如果 payload 有 password 要使用 HTTPS 唷 <3 )
1curl -X POST -H "Content-Type: multipart/form-data" \
2-F "user=user" \
3-F "password=password" \
4-F "file=@./examples.md" "https://<web server>/examples.md"