Go Side Project - Transfer.sh

Trace transfer.sh open project 有提到我目前正在調整 transfer.sh 這個 open source project,把它修改成內部所需要的一個 service,而之前已經改得差不多了,所以簡單地來介紹一下修改了哪些內容:

需求

  1. 每個 download request 能依需求驗證 IP address 和 user account / password
  2. 能使用外部 service 來驗證 user account
  3. 需能支援 curl cmd tool
  4. 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 介面,看起來有點醜。

source code

r.HandleFunc("/{token}/{filename}",
	s.AssignMetadata(MetadataAllowedIP(s.MetadataBasicAuth(http.HandlerFunc(getHandlerFn)))),
).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
docker 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 )
curl -X POST -H "Content-Type: multipart/form-data" \
-F "user=user" \
-F "password=password" \
-F "file=@./examples.md" "https://<web server>/examples.md"

source code

transfer.sh