Skip to content

Commit

Permalink
Merge pull request #2 from jvale/azure_sas_token_support
Browse files Browse the repository at this point in the history
Add support for Azure SAS tokens
  • Loading branch information
ruizink authored Sep 25, 2020
2 parents f6c9351 + 3238023 commit e0ec58b
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 11 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Usage of consul-snapshotter:
--azure-blob.container-name string The name of the Azure Blob container to use
--azure-blob.container-path string The path to use inside the Azure Blob container
--azure-blob.storage-access-key string The Azure Blob storage access key to use
--azure-blob.storage-sas-token The Azure Blob storage SAS token to use instead of an access key
--azure-blob.storage-account string The Azure Blob storage account to use
--configdir string The path to look for the configuration file (default ".")
--consul.lock-key string The Key to use in the KV lock (default "consul-snapshotter/.lock")
Expand Down
38 changes: 31 additions & 7 deletions azure/azure.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,41 +7,65 @@ import (
"net/url"
"os"

"github.com/Azure/azure-pipeline-go/pipeline"
"github.com/Azure/azure-storage-blob-go/azblob"
)

type config struct {
accountName string
accountKey string
sasToken string
}

func AzureConfig(accountName, accountKey string) (*config, error) {
func AzureConfig(accountName, accountKey, sasToken string) (*config, error) {
if accountName == "" {
return nil, fmt.Errorf("Azure Account Name not provided")
}
if accountKey == "" {
return nil, fmt.Errorf("Azure Account Access Key not provided")
if accountKey == "" && sasToken == "" {
return nil, fmt.Errorf("Azure Account Access Key or SAS Token must be provided")
}
c := &config{
accountName: accountName,
accountKey: accountKey,
sasToken: sasToken,
}
return c, nil
}

func UploadBlob(srcFile, destFile, containerName string, c *config) (int, error) {

func AuthenticateAccountKey(containerName string, c *config) (pipeline.Pipeline, error) {
// Create a default request pipeline using your storage account name and account key
credential, err := azblob.NewSharedKeyCredential(c.accountName, c.accountKey)
if err != nil {
return 0, fmt.Errorf("Invalid credentials: %s", err)
return nil, fmt.Errorf("Invalid credentials: %s", err)
}
p := azblob.NewPipeline(credential, azblob.PipelineOptions{})

return p, err
}

func AuthenticateSASToken(containerName string, c *config) pipeline.Pipeline {
return azblob.NewPipeline(azblob.NewAnonymousCredential(), azblob.PipelineOptions{})
}

func UploadBlob(srcFile, destFile, containerName string, c *config) (int, error) {
var p pipeline.Pipeline
var queryParameters string

if c.sasToken != "" {
p = AuthenticateSASToken(containerName, c)
queryParameters = "?" + c.sasToken
} else {
var err error
p, err = AuthenticateAccountKey(containerName, c)
if err != nil {
return 0, err
}
}

// TODO: Allow the URL to be a parameter
// Setup the blob service URL endpoint
URL, _ := url.Parse(
fmt.Sprintf("https://%s.blob.core.windows.net/%s", c.accountName, containerName))
fmt.Sprintf("https://%s.blob.core.windows.net/%s%s", c.accountName, containerName, queryParameters))

// Create a ContainerURL object using the container URL and a request pipeline
containerURL := azblob.NewContainerURL(*URL, p)
Expand Down
5 changes: 3 additions & 2 deletions config-sample.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@ consul:
token: ""
lock-key: "consul-snapshotter/.lock"
lock-timeout: "10m"

local:
destination-path: "/tmp/snapshots"

azure-blob:
container-name: "container_name"
container-path: "consul/snapshots"
storage-account: "azure_account"
# storage-access-key: ""
# storage-access-key: "" #
# storage-sas-token: "" # Use either of these, SAS token takes precedence

outputs:
- "local"
Expand Down
6 changes: 5 additions & 1 deletion config.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ type azureOutputConfig struct {
ContainerPath string `json:"container-path"`
StorageAccount string `json:"azure-storage-account"`
StorageAccessKey string `json:"azure-storage-access-key"`
StorageSASToken string `json:"azure-storage-sas-token"`
}

type config struct {
Expand Down Expand Up @@ -90,7 +91,8 @@ func (c *config) loadConfig() error {
regFlagString("azure-blob.container-name", "", "The name of the Azure Blob container to use")
regFlagString("azure-blob.container-path", "", "The path to use inside the Azure Blob container")
regFlagString("azure-blob.storage-account", "", "The Azure Blob storage account to use")
regFlagString("azure-blob.storage-access-key", "", "The Azure Blob storage access key to use")
regFlagString("azure-blob.storage-access-key", "", "The Azure Blob storage access key to use (mutually exclusive with azure-blob.storage-sas-token)")
regFlagString("azure-blob.storage-sas-token", "", "The Azure Blob storage SAS token to use (mutually exclusive with azure-blob.storage-access-key)")
regFlagString("local.destination-path", viper.GetString("local.destination-path"), "The local path where to save the snapshots")
regFlagDuration("local.retention-period", viper.GetDuration("local.retention-period"), "The duration that Local snapshots need to be retained (default \"0s\" - keep forever)")
regFlagBoolP("help", "h", false, "Prints this help message")
Expand All @@ -113,6 +115,7 @@ func (c *config) loadConfig() error {
viper.BindEnv("consul.token", "CONSUL_HTTP_TOKEN")
viper.BindEnv("azure-blob.storage-account", "AZURE_STORAGE_ACCOUNT")
viper.BindEnv("azure-blob.storage-access-key", "AZURE_STORAGE_ACCESS_KEY")
viper.BindEnv("azure-blob.storage-sas-token", "AZURE_STORAGE_SAS_TOKEN")

// load config from file
viper.SetConfigName("config")
Expand All @@ -135,6 +138,7 @@ func (c *config) loadConfig() error {
azureOutputConfig.ContainerPath = viper.GetString("azure-blob.container-path")
azureOutputConfig.StorageAccount = viper.GetString("azure-blob.storage-account")
azureOutputConfig.StorageAccessKey = viper.GetString("azure-blob.storage-access-key")
azureOutputConfig.StorageSASToken = viper.GetString("azure-blob.storage-sas-token")

// Local output config
localOutputConfig := &localOutputConfig{}
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ replace github.com/ruizink/consul-snapshotter/consul => ./consul
replace github.com/ruizink/consul-snapshotter/azure => ./azure

require (
github.com/Azure/azure-pipeline-go v0.2.2
github.com/Azure/azure-storage-blob-go v0.10.0
github.com/hashicorp/consul v1.8.1
github.com/hashicorp/consul/api v1.5.0
Expand Down
1 change: 1 addition & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ func processOutputs(snap string, c *config) {
Filename: outputFileName,
StorageAccount: c.AzureOutputConfig.StorageAccount,
StorageAccessKey: c.AzureOutputConfig.StorageAccessKey,
StorageSASToken: c.AzureOutputConfig.StorageSASToken,
}
o.Save(snap)
}
Expand Down
3 changes: 2 additions & 1 deletion outputs/azure_blob.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ type AzureBlobOutput struct {
Filename string
StorageAccount string
StorageAccessKey string
StorageSASToken string
}

func (o *AzureBlobOutput) Save(snap string) {
destFile := path.Join(o.ContainerPath, o.Filename)
config, err := azure.AzureConfig(o.StorageAccount, o.StorageAccessKey)
config, err := azure.AzureConfig(o.StorageAccount, o.StorageAccessKey, o.StorageSASToken)
if err != nil {
log.Println("Invalid Azure config:", err)
return
Expand Down

0 comments on commit e0ec58b

Please sign in to comment.