Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Azure blob storage backend #638

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 53 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Easy and fast file sharing from the command-line. This code contains the server with everything you need to create your own instance.

Transfer.sh currently supports the s3 (Amazon S3), gdrive (Google Drive), storj (Storj) providers, and local file system (local).
Transfer.sh currently supports the s3 (Amazon S3), gdrive (Google Drive), storj (Storj), azure (Azure Blob Storage) providers, and local file system (local).

## Disclaimer

Expand Down Expand Up @@ -113,7 +113,7 @@ proxy-path | path prefix when service is run behind a proxy
proxy-port | port of the proxy when the service is run behind a proxy | | PROXY_PORT |
email-contact | email contact for the front end | | EMAIL_CONTACT |
ga-key | google analytics key for the front end | | GA_KEY |
provider | which storage provider to use | (s3, storj, gdrive or local) |
provider | which storage provider to use | (s3, storj, gdrive, azure or local) |
uservoice-key | user voice key for the front end | | USERVOICE_KEY |
aws-access-key | aws access key | | AWS_ACCESS_KEY |
aws-secret-key | aws access key | | AWS_SECRET_KEY |
Expand All @@ -138,6 +138,8 @@ max-upload-size | max upload size in kilobytes
purge-days | number of days after the uploads are purged automatically | | PURGE_DAYS |
purge-interval | interval in hours to run the automatic purge for (not applicable to S3 and Storj) | | PURGE_INTERVAL |
random-token-length | length of the random token for the upload path (double the size for delete path) | 6 | RANDOM_TOKEN_LENGTH |
azure-storage-account | Azure storage account name | | AZURE_STORAGE_ACCOUNT |
azure-storage-container | Azure storage container name | | AZURE_STORAGE_CONTAINER |

If you want to use TLS using lets encrypt certificates, set lets-encrypt-hosts to your domain, set tls-listener to :443 and enable force-https.

Expand Down Expand Up @@ -244,6 +246,55 @@ You need to create an OAuth Client id from console.cloud.google.com, download th

```go run main.go --provider gdrive --basedir /tmp/ --gdrive-client-json-filepath /[credential_dir] --gdrive-local-config-path [directory_to_save_config] ```

## Azure Blob Storage Usage

For the usage with Azure Blob Storage, you need to specify the following options:
- provider `--provider azure`
- azure-storage-account _(either via flag or environment variable `AZURE_STORAGE_ACCOUNT`)_
- azure-storage-container _(either via flag or environment variable `AZURE_STORAGE_CONTAINER`)_

The [Default Credential Chain](https://learn.microsoft.com/en-us/azure/developer/go/sdk/authentication/credential-chains#defaultazurecredential-overview) is used to authenticate.

> The simplest way to authenticate is by adding yourself as a contributor to the storage account and authenticating with `az login` before running the program.
>
> Another option is to provide the environment with [service principal](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#readme-service-principal-with-secret) credentials.

### Usage example

```bash
AZURE_STORAGE_ACCOUNT=<your_storage_account>
AZURE_STORAGE_CONTAINER=<your_container_name>

# Sign into Azure
az login

# Create a storage account
az storage account create \
--name $AZURE_STORAGE_ACCOUNT \
--resource-group <your_resource_group> \
--location <your_location> \
--sku Standard_LRS

# Create a blob container within that storage account
az storage container create \
--name $AZURE_STORAGE_CONTAINER \
--account-name $AZURE_STORAGE_ACCOUNT \
--public-access off \
--fail-on-exist true

# Grant yourself or a service principal the correct role
az role assignment create \
--role "Storage Blob Data Contributor" \
--assignee <your_user_or_group_id> \
--scope /subscriptions/<your_subscription_id>/resourceGroups/<your_resource_group>/providers/Microsoft.Storage/storageAccounts/$AZURE_STORAGE_ACCOUNT

# Start transfer.sh
go run main.go \
--provider azure \
--azure-storage-account $AZURE_STORAGE_ACCOUNT \
--azure-storage-container $AZURE_STORAGE_CONTAINER
```

## Shell functions

### Bash, ash and zsh (multiple files uploaded as zip archive)
Expand Down
24 changes: 23 additions & 1 deletion cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ var globalFlags = []cli.Flag{
},
&cli.StringFlag{
Name: "provider",
Usage: "s3|gdrive|local",
Usage: "s3|gdrive|azure|local",
Value: "",
EnvVars: []string{"PROVIDER"},
},
Expand Down Expand Up @@ -307,6 +307,18 @@ var globalFlags = []cli.Flag{
Value: 10,
EnvVars: []string{"RANDOM_TOKEN_LENGTH"},
},
&cli.StringFlag{
Name: "azure-storage-account",
Usage: "Azure storage account name",
Value: "",
EnvVars: []string{"AZURE_STORAGE_ACCOUNT"},
},
&cli.StringFlag{
Name: "azure-storage-container",
Usage: "Azure storage container name",
Value: "",
EnvVars: []string{"AZURE_STORAGE_CONTAINER"},
},
}

// Cmd wraps cli.app
Expand Down Expand Up @@ -495,6 +507,16 @@ func New() *Cmd {
} else {
options = append(options, server.UseStorage(store))
}
case "azure":
if storageAccountName := c.String("azure-storage-account"); storageAccountName == "" {
return errors.New("azure-storage-account not set.")
} else if containerName := c.String("azure-storage-container"); containerName == "" {
return errors.New("azure-storage-container not set.")
} else if store, err := storage.NewAzureBlobStorage(c.Context, storageAccountName, containerName, logger); err != nil {
return err
} else {
options = append(options, server.UseStorage(store))
}
case "gdrive":
chunkSize := c.Int("gdrive-chunk-size") * 1024 * 1024

Expand Down
22 changes: 15 additions & 7 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ module github.com/dutchcoders/transfer.sh
go 1.18

require (
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.1
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.0
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8
github.com/ProtonMail/gopenpgp/v2 v2.5.2
github.com/PuerkitoBio/ghost v0.0.0-20160324114900-206e6e460e14
Expand All @@ -26,10 +28,10 @@ require (
github.com/tg123/go-htpasswd v1.2.1
github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce
github.com/urfave/cli/v2 v2.25.3
golang.org/x/crypto v0.21.0
golang.org/x/net v0.23.0
golang.org/x/crypto v0.32.0
golang.org/x/net v0.34.0
golang.org/x/oauth2 v0.7.0
golang.org/x/text v0.14.0
golang.org/x/text v0.21.0
google.golang.org/api v0.114.0
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c
storj.io/common v0.0.0-20230301105927-7f966760c100
Expand All @@ -39,6 +41,9 @@ require (
require (
cloud.google.com/go/compute v1.19.1 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2 // indirect
github.com/GehirnInc/crypt v0.0.0-20200316065508-bb7000b8a962 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.3 // indirect
Expand All @@ -62,9 +67,10 @@ require (
github.com/flynn/noise v1.0.0 // indirect
github.com/garyburd/redigo v1.6.4 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect
github.com/googleapis/gax-go/v2 v2.7.1 // indirect
github.com/gorilla/css v1.0.0 // indirect
Expand All @@ -75,18 +81,20 @@ require (
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect
github.com/rogpeppe/go-internal v1.9.0 // indirect
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
github.com/rogpeppe/go-internal v1.12.0 // indirect
github.com/spacemonkeygo/monkit/v3 v3.0.19 // indirect
github.com/vivint/infectious v0.0.0-20200605153912-25a574ae18a3 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
github.com/zeebo/blake3 v0.2.3 // indirect
github.com/zeebo/errs v1.3.0 // indirect
go.opencensus.io v0.24.0 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.18.0 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/sys v0.29.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
google.golang.org/grpc v1.56.3 // indirect
Expand Down
Loading