mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
parent
3188af9be3
commit
e99f75f0ca
@ -1109,6 +1109,7 @@ signed_url_expiration =
|
||||
account_name =
|
||||
account_key =
|
||||
container_name =
|
||||
sas_token_expiration_days =
|
||||
|
||||
[external_image_storage.local]
|
||||
# does not require any configuration
|
||||
|
@ -226,7 +226,7 @@
|
||||
;google_analytics_ua_id =
|
||||
|
||||
# Google Analytics 4 tracking code, only enabled if you specify an id here
|
||||
;google_analytics_4_id =
|
||||
;google_analytics_4_id =
|
||||
|
||||
# Google Tag Manager ID, only enabled if you specify an id here
|
||||
;google_tag_manager_id =
|
||||
@ -1074,6 +1074,7 @@
|
||||
;account_name =
|
||||
;account_key =
|
||||
;container_name =
|
||||
;sas_token_expiration_days =
|
||||
|
||||
[external_image_storage.local]
|
||||
# does not require any configuration
|
||||
@ -1241,13 +1242,13 @@
|
||||
# Enable or disable loading other base map layers
|
||||
;enable_custom_baselayers = true
|
||||
|
||||
# Move an app plugin referenced by its id (including all its pages) to a specific navigation section
|
||||
# Move an app plugin referenced by its id (including all its pages) to a specific navigation section
|
||||
# Dependencies: needs the `topnav` feature to be enabled
|
||||
[navigation.app_sections]
|
||||
# The following will move an app plugin with the id of `my-app-id` under the `starred` section
|
||||
# my-app-id = admin
|
||||
|
||||
# Move a specific app plugin page (referenced by its `path` field) to a specific navigation section
|
||||
# Move a specific app plugin page (referenced by its `path` field) to a specific navigation section
|
||||
[navigation.app_standalone_pages]
|
||||
# The following will move the page with the path "/a/my-app-id/starred-content" from `my-app-id` to the `starred` section
|
||||
# /a/my-app-id/starred-content = starred
|
@ -1747,6 +1747,10 @@ Storage account key
|
||||
|
||||
Container name where to store "Blob" images with random names. Creating the blob container beforehand is required. Only public containers are supported.
|
||||
|
||||
### sas_token_expiration_days
|
||||
|
||||
Number of days for SAS token validity. If specified SAS token will be attached to image URL. Allow storing images in private containers.
|
||||
|
||||
<hr>
|
||||
|
||||
## [external_image_storage.local]
|
||||
|
6
go.mod
6
go.mod
@ -44,7 +44,7 @@ require (
|
||||
github.com/go-sql-driver/mysql v1.6.0
|
||||
github.com/go-stack/stack v1.8.1
|
||||
github.com/gobwas/glob v0.2.3
|
||||
github.com/gofrs/uuid v4.3.0+incompatible
|
||||
github.com/gofrs/uuid v4.3.0+incompatible // indirect
|
||||
github.com/gogo/protobuf v1.3.2
|
||||
github.com/golang/mock v1.6.0
|
||||
github.com/golang/snappy v0.0.4
|
||||
@ -240,6 +240,7 @@ require (
|
||||
cloud.google.com/go/kms v1.4.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.13.2
|
||||
github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.4.0
|
||||
github.com/Azure/azure-storage-blob-go v0.15.0
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.20
|
||||
github.com/armon/go-radix v1.0.0
|
||||
github.com/blugelabs/bluge v0.1.9
|
||||
@ -261,11 +262,11 @@ require (
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.7.0
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.7.0
|
||||
gocloud.dev v0.25.0
|
||||
gotest.tools v2.2.0+incompatible
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.100.2 // indirect
|
||||
github.com/Azure/azure-pipeline-go v0.2.3 // indirect
|
||||
github.com/armon/go-metrics v0.3.10 // indirect
|
||||
github.com/bmatcuk/doublestar v1.1.1 // indirect
|
||||
github.com/buildkite/yaml v2.1.0+incompatible // indirect
|
||||
@ -279,6 +280,7 @@ require (
|
||||
github.com/hashicorp/memberlist v0.4.0 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.12 // indirect
|
||||
github.com/mattn/go-ieproxy v0.0.3 // indirect
|
||||
github.com/mitchellh/mapstructure v1.4.3 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
|
4
go.sum
4
go.sum
@ -96,6 +96,7 @@ github.com/Azure/azure-amqp-common-go/v3 v3.2.1/go.mod h1:O6X1iYHP7s2x7NjUKsXVhk
|
||||
github.com/Azure/azure-amqp-common-go/v3 v3.2.2/go.mod h1:O6X1iYHP7s2x7NjUKsXVhkwWrQhxrd+d8/3rRadj4CI=
|
||||
github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4=
|
||||
github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc=
|
||||
github.com/Azure/azure-pipeline-go v0.2.3 h1:7U9HBg1JFK3jHl5qmo4CTZKFTVgMwdFHMVtCdfBE21U=
|
||||
github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k=
|
||||
github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||
github.com/Azure/azure-sdk-for-go v23.2.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||
@ -135,6 +136,8 @@ github.com/Azure/azure-service-bus-go v0.11.5/go.mod h1:MI6ge2CuQWBVq+ly456MY7Xq
|
||||
github.com/Azure/azure-storage-blob-go v0.8.0/go.mod h1:lPI3aLPpuLTeUwh1sViKXFxwl2B6teiRqI0deQUvsw0=
|
||||
github.com/Azure/azure-storage-blob-go v0.13.0/go.mod h1:pA9kNqtjUeQF2zOSu4s//nUdBD+e64lEuc4sVnuOfNs=
|
||||
github.com/Azure/azure-storage-blob-go v0.14.0/go.mod h1:SMqIBi+SuiQH32bvyjngEewEeXoPfKMgWlBDaYf6fck=
|
||||
github.com/Azure/azure-storage-blob-go v0.15.0 h1:rXtgp8tN1p29GvpGgfJetavIG0V7OgcSXPpwp3tx6qk=
|
||||
github.com/Azure/azure-storage-blob-go v0.15.0/go.mod h1:vbjsVbX0dlxnRc4FFMPsS9BsJWPcne7GB7onqlPvz58=
|
||||
github.com/Azure/go-amqp v0.16.0/go.mod h1:9YJ3RhxRT1gquYnzpZO1vcYMMpAdJT+QEg6fwmw9Zlg=
|
||||
github.com/Azure/go-amqp v0.16.4/go.mod h1:9YJ3RhxRT1gquYnzpZO1vcYMMpAdJT+QEg6fwmw9Zlg=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||
@ -1805,6 +1808,7 @@ github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HN
|
||||
github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
|
||||
github.com/mattn/go-ieproxy v0.0.0-20191113090002-7c0f6868bffe/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/gNWuh88E=
|
||||
github.com/mattn/go-ieproxy v0.0.1/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/gNWuh88E=
|
||||
github.com/mattn/go-ieproxy v0.0.3 h1:YkaHmK1CzE5C4O7A3hv3TCbfNDPSCf0RKZFX+VhBeYk=
|
||||
github.com/mattn/go-ieproxy v0.0.3/go.mod h1:6ZpRmhBaYuBX1U2za+9rC9iCGLsSp2tftelZne7CPko=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
|
@ -19,23 +19,26 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Azure/azure-storage-blob-go/azblob"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
type AzureBlobUploader struct {
|
||||
account_name string
|
||||
account_key string
|
||||
container_name string
|
||||
log log.Logger
|
||||
account_name string
|
||||
account_key string
|
||||
container_name string
|
||||
sas_token_expiration_days int
|
||||
log log.Logger
|
||||
}
|
||||
|
||||
func NewAzureBlobUploader(account_name string, account_key string, container_name string) *AzureBlobUploader {
|
||||
func NewAzureBlobUploader(account_name string, account_key string, container_name string, sas_token_expiration_days int) *AzureBlobUploader {
|
||||
return &AzureBlobUploader{
|
||||
account_name: account_name,
|
||||
account_key: account_key,
|
||||
container_name: container_name,
|
||||
log: log.New("azureBlobUploader"),
|
||||
account_name: account_name,
|
||||
account_key: account_key,
|
||||
container_name: container_name,
|
||||
sas_token_expiration_days: sas_token_expiration_days,
|
||||
log: log.New("azureBlobUploader"),
|
||||
}
|
||||
}
|
||||
|
||||
@ -91,9 +94,49 @@ func (az *AzureBlobUploader) Upload(ctx context.Context, imageDiskPath string) (
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("https://%s.blob.core.windows.net/%s/%s", az.account_name, az.container_name, randomFileName)
|
||||
|
||||
if az.sas_token_expiration_days > 0 {
|
||||
url, err = blob.GetBlobSasUrl(ctx, az.container_name, randomFileName, az.sas_token_expiration_days)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
return url, nil
|
||||
}
|
||||
|
||||
// SignWithSharedKey uses an account's SharedKeyCredential to sign this signature values to produce the proper SAS query parameters.
|
||||
func (c *StorageClient) GetBlobSasUrl(ctx context.Context, containerName, blobName string, sasTokenExpiration int) (string, error) {
|
||||
if c.Auth == nil {
|
||||
return "", fmt.Errorf("cannot sign SAS query without Shared Key Credential")
|
||||
}
|
||||
|
||||
// create source blob SAS url
|
||||
credential, err := azblob.NewSharedKeyCredential(c.Auth.Account, c.Auth.Key)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Set the desired SAS signature values and sign them with the shared key credentials to get the SAS query parameters.
|
||||
sasQueryParams, err := azblob.BlobSASSignatureValues{
|
||||
Protocol: azblob.SASProtocolHTTPS, // Users MUST use HTTPS (not HTTP)
|
||||
ExpiryTime: time.Now().UTC().AddDate(0, 0, sasTokenExpiration), // Expiration time
|
||||
ContainerName: containerName,
|
||||
BlobName: blobName,
|
||||
Permissions: azblob.BlobSASPermissions{Add: false, Read: true, Write: false}.String(), // Read only permissions
|
||||
}.NewSASQueryParameters(credential)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Create the URL of the resource you wish to access and append the SAS query parameters.
|
||||
// Since this is a blob SAS, the URL is to the Azure storage blob.
|
||||
qp := sasQueryParams.Encode()
|
||||
blobSasUrl := fmt.Sprintf("https://%s.blob.core.windows.net/%s/%s?%s", c.Auth.Account, containerName, blobName, qp)
|
||||
|
||||
// Return Blob SAS token URL
|
||||
return blobSasUrl, nil
|
||||
}
|
||||
|
||||
// --- AZURE LIBRARY
|
||||
type Error struct {
|
||||
Code int
|
||||
|
@ -110,8 +110,10 @@ func NewImageUploader() (ImageUploader, error) {
|
||||
account_name := azureBlobSec.Key("account_name").MustString("")
|
||||
account_key := azureBlobSec.Key("account_key").MustString("")
|
||||
container_name := azureBlobSec.Key("container_name").MustString("")
|
||||
sas_token_expiration_days := azureBlobSec.Key("sas_token_expiration_days").MustInt(-1)
|
||||
|
||||
return NewAzureBlobUploader(account_name, account_key, container_name, sas_token_expiration_days), nil
|
||||
|
||||
return NewAzureBlobUploader(account_name, account_key, container_name), nil
|
||||
case "local":
|
||||
return NewLocalImageUploader()
|
||||
}
|
||||
|
@ -154,6 +154,8 @@ func TestImageUploaderFactory(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
_, err = azureBlobSec.NewKey("container_name", "container_name")
|
||||
require.NoError(t, err)
|
||||
_, err = azureBlobSec.NewKey("sas_token_expiration_days", "sas_token_expiration_days")
|
||||
require.NoError(t, err)
|
||||
|
||||
uploader, err := NewImageUploader()
|
||||
require.NoError(t, err)
|
||||
@ -163,6 +165,7 @@ func TestImageUploaderFactory(t *testing.T) {
|
||||
require.Equal(t, "account_name", original.account_name)
|
||||
require.Equal(t, "account_key", original.account_key)
|
||||
require.Equal(t, "container_name", original.container_name)
|
||||
require.Equal(t, -1, original.sas_token_expiration_days)
|
||||
})
|
||||
})
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user