2
2
mirror of https://github.com/octoleo/restic.git synced 2024-11-29 00:06:32 +00:00

Merge pull request #3661 from rgammans/azure_sas_support

add SAS authentication option for Azure repos
This commit is contained in:
MichaelEischer 2022-07-23 10:32:03 +02:00 committed by GitHub
commit 827ab02eea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 56 additions and 4 deletions

View File

@ -0,0 +1,14 @@
Enhancement: Allow use of SAS token to authenticate to Azure
Previously restic only supported AccountKeys to authenticate to Azure
storage accounts, which necessitates giving a significant amount of
access.
We added support for Azure SAS tokens which are a more fine-grained
and time-limited manner of granting access. Set the `AZURE_ACCOUNT_NAME`
and `AZURE_ACCOUNT_SAS` environment variables to use a SAS token for
authentication. Note that if `AZURE_ACCOUNT_KEY` is set, it will take
preference.
https://github.com/restic/restic/issues/2295
https://github.com/restic/restic/pull/3661

View File

@ -596,6 +596,10 @@ func parseConfig(loc location.Location, opts options.Options) (interface{}, erro
cfg.AccountKey = options.NewSecretString(os.Getenv("AZURE_ACCOUNT_KEY")) cfg.AccountKey = options.NewSecretString(os.Getenv("AZURE_ACCOUNT_KEY"))
} }
if cfg.AccountSAS.String() == "" {
cfg.AccountSAS = options.NewSecretString(os.Getenv("AZURE_ACCOUNT_SAS"))
}
if err := opts.Apply(loc.Scheme, &cfg); err != nil { if err := opts.Apply(loc.Scheme, &cfg); err != nil {
return nil, err return nil, err
} }

View File

@ -499,6 +499,13 @@ account name and key as follows:
$ export AZURE_ACCOUNT_NAME=<ACCOUNT_NAME> $ export AZURE_ACCOUNT_NAME=<ACCOUNT_NAME>
$ export AZURE_ACCOUNT_KEY=<SECRET_KEY> $ export AZURE_ACCOUNT_KEY=<SECRET_KEY>
or
.. code-block:: console
$ export AZURE_ACCOUNT_NAME=<ACCOUNT_NAME>
$ export AZURE_ACCOUNT_SAS=<SAS_TOKEN>
Afterwards you can initialize a repository in a container called ``foo`` in the Afterwards you can initialize a repository in a container called ``foo`` in the
root path like this: root path like this:

View File

@ -593,6 +593,7 @@ environment variables. The following lists these environment variables:
AZURE_ACCOUNT_NAME Account name for Azure AZURE_ACCOUNT_NAME Account name for Azure
AZURE_ACCOUNT_KEY Account key for Azure AZURE_ACCOUNT_KEY Account key for Azure
AZURE_ACCOUNT_SAS Shared access signatures (SAS) for Azure
GOOGLE_PROJECT_ID Project ID for Google Cloud Storage GOOGLE_PROJECT_ID Project ID for Google Cloud Storage
GOOGLE_APPLICATION_CREDENTIALS Application Credentials for Google Cloud Storage (e.g. $HOME/.config/gs-secret-restic-key.json) GOOGLE_APPLICATION_CREDENTIALS Application Credentials for Google Cloud Storage (e.g. $HOME/.config/gs-secret-restic-key.json)

View File

@ -4,6 +4,7 @@ import (
"context" "context"
"crypto/md5" "crypto/md5"
"encoding/base64" "encoding/base64"
"fmt"
"hash" "hash"
"io" "io"
"net/http" "net/http"
@ -39,10 +40,34 @@ var _ restic.Backend = &Backend{}
func open(cfg Config, rt http.RoundTripper) (*Backend, error) { func open(cfg Config, rt http.RoundTripper) (*Backend, error) {
debug.Log("open, config %#v", cfg) debug.Log("open, config %#v", cfg)
var client storage.Client
client, err := storage.NewBasicClient(cfg.AccountName, cfg.AccountKey.Unwrap()) var err error
if err != nil { if cfg.AccountKey.String() != "" {
return nil, errors.Wrap(err, "NewBasicClient") // We have an account key value, find the BlobServiceClient
// from with a BasicClient
debug.Log(" - using account key")
client, err = storage.NewBasicClient(cfg.AccountName, cfg.AccountKey.Unwrap())
if err != nil {
return nil, errors.Wrap(err, "NewBasicClient")
}
} else if cfg.AccountSAS.String() != "" {
// Get the client using the SAS Token as authentication, this
// is longer winded than above because the SDK wants a URL for the Account
// if your using a SAS token, and not just the account name
// we (as per the SDK ) assume the default Azure portal.
url := fmt.Sprintf("https://%s.blob.core.windows.net/", cfg.AccountName)
debug.Log(" - using sas token")
sas := cfg.AccountSAS.Unwrap()
// strip query sign prefix
if sas[0] == '?' {
sas = sas[1:]
}
client, err = storage.NewAccountSASClientFromEndpointToken(url, sas)
if err != nil {
return nil, errors.Wrap(err, "NewAccountSASClientFromEndpointToken")
}
} else {
return nil, errors.New("no azure authentication information found")
} }
client.HTTPClient = &http.Client{Transport: rt} client.HTTPClient = &http.Client{Transport: rt}

View File

@ -12,6 +12,7 @@ import (
// server. // server.
type Config struct { type Config struct {
AccountName string AccountName string
AccountSAS options.SecretString
AccountKey options.SecretString AccountKey options.SecretString
Container string Container string
Prefix string Prefix string