|
Packit |
63bb0d |
package azblob
|
|
Packit |
63bb0d |
|
|
Packit |
63bb0d |
import (
|
|
Packit |
63bb0d |
"bytes"
|
|
Packit |
63bb0d |
"errors"
|
|
Packit |
63bb0d |
"fmt"
|
|
Packit |
63bb0d |
"strings"
|
|
Packit |
63bb0d |
"time"
|
|
Packit |
63bb0d |
)
|
|
Packit |
63bb0d |
|
|
Packit |
63bb0d |
// AccountSASSignatureValues is used to generate a Shared Access Signature (SAS) for an Azure Storage account.
|
|
Packit |
63bb0d |
// For more information, see https://docs.microsoft.com/rest/api/storageservices/constructing-an-account-sas
|
|
Packit |
63bb0d |
type AccountSASSignatureValues struct {
|
|
Packit |
63bb0d |
Version string `param:"sv"` // If not specified, this defaults to SASVersion
|
|
Packit |
63bb0d |
Protocol SASProtocol `param:"spr"` // See the SASProtocol* constants
|
|
Packit |
63bb0d |
StartTime time.Time `param:"st"` // Not specified if IsZero
|
|
Packit |
63bb0d |
ExpiryTime time.Time `param:"se"` // Not specified if IsZero
|
|
Packit |
63bb0d |
Permissions string `param:"sp"` // Create by initializing a AccountSASPermissions and then call String()
|
|
Packit |
63bb0d |
IPRange IPRange `param:"sip"`
|
|
Packit |
63bb0d |
Services string `param:"ss"` // Create by initializing AccountSASServices and then call String()
|
|
Packit |
63bb0d |
ResourceTypes string `param:"srt"` // Create by initializing AccountSASResourceTypes and then call String()
|
|
Packit |
63bb0d |
}
|
|
Packit |
63bb0d |
|
|
Packit |
63bb0d |
// NewSASQueryParameters uses an account's shared key credential to sign this signature values to produce
|
|
Packit |
63bb0d |
// the proper SAS query parameters.
|
|
Packit |
63bb0d |
func (v AccountSASSignatureValues) NewSASQueryParameters(sharedKeyCredential *SharedKeyCredential) (SASQueryParameters, error) {
|
|
Packit |
63bb0d |
// https://docs.microsoft.com/en-us/rest/api/storageservices/Constructing-an-Account-SAS
|
|
Packit |
63bb0d |
if v.ExpiryTime.IsZero() || v.Permissions == "" || v.ResourceTypes == "" || v.Services == "" {
|
|
Packit |
63bb0d |
return SASQueryParameters{}, errors.New("account SAS is missing at least one of these: ExpiryTime, Permissions, Service, or ResourceType")
|
|
Packit |
63bb0d |
}
|
|
Packit |
63bb0d |
if v.Version == "" {
|
|
Packit |
63bb0d |
v.Version = SASVersion
|
|
Packit |
63bb0d |
}
|
|
Packit |
63bb0d |
perms := &AccountSASPermissions{}
|
|
Packit |
63bb0d |
if err := perms.Parse(v.Permissions); err != nil {
|
|
Packit |
63bb0d |
return SASQueryParameters{}, err
|
|
Packit |
63bb0d |
}
|
|
Packit |
63bb0d |
v.Permissions = perms.String()
|
|
Packit |
63bb0d |
|
|
Packit |
63bb0d |
startTime, expiryTime, _ := FormatTimesForSASSigning(v.StartTime, v.ExpiryTime, time.Time{})
|
|
Packit |
63bb0d |
|
|
Packit |
63bb0d |
stringToSign := strings.Join([]string{
|
|
Packit |
63bb0d |
sharedKeyCredential.AccountName(),
|
|
Packit |
63bb0d |
v.Permissions,
|
|
Packit |
63bb0d |
v.Services,
|
|
Packit |
63bb0d |
v.ResourceTypes,
|
|
Packit |
63bb0d |
startTime,
|
|
Packit |
63bb0d |
expiryTime,
|
|
Packit |
63bb0d |
v.IPRange.String(),
|
|
Packit |
63bb0d |
string(v.Protocol),
|
|
Packit |
63bb0d |
v.Version,
|
|
Packit |
63bb0d |
""}, // That right, the account SAS requires a terminating extra newline
|
|
Packit |
63bb0d |
"\n")
|
|
Packit |
63bb0d |
|
|
Packit |
63bb0d |
signature := sharedKeyCredential.ComputeHMACSHA256(stringToSign)
|
|
Packit |
63bb0d |
p := SASQueryParameters{
|
|
Packit |
63bb0d |
// Common SAS parameters
|
|
Packit |
63bb0d |
version: v.Version,
|
|
Packit |
63bb0d |
protocol: v.Protocol,
|
|
Packit |
63bb0d |
startTime: v.StartTime,
|
|
Packit |
63bb0d |
expiryTime: v.ExpiryTime,
|
|
Packit |
63bb0d |
permissions: v.Permissions,
|
|
Packit |
63bb0d |
ipRange: v.IPRange,
|
|
Packit |
63bb0d |
|
|
Packit |
63bb0d |
// Account-specific SAS parameters
|
|
Packit |
63bb0d |
services: v.Services,
|
|
Packit |
63bb0d |
resourceTypes: v.ResourceTypes,
|
|
Packit |
63bb0d |
|
|
Packit |
63bb0d |
// Calculated SAS signature
|
|
Packit |
63bb0d |
signature: signature,
|
|
Packit |
63bb0d |
}
|
|
Packit |
63bb0d |
|
|
Packit |
63bb0d |
return p, nil
|
|
Packit |
63bb0d |
}
|
|
Packit |
63bb0d |
|
|
Packit |
63bb0d |
// The AccountSASPermissions type simplifies creating the permissions string for an Azure Storage Account SAS.
|
|
Packit |
63bb0d |
// Initialize an instance of this type and then call its String method to set AccountSASSignatureValues's Permissions field.
|
|
Packit |
63bb0d |
type AccountSASPermissions struct {
|
|
Packit Service |
3a6627 |
Read, Write, Delete, DeletePreviousVersion, List, Add, Create, Update, Process, Tag, FilterByTags bool
|
|
Packit |
63bb0d |
}
|
|
Packit |
63bb0d |
|
|
Packit |
63bb0d |
// String produces the SAS permissions string for an Azure Storage account.
|
|
Packit |
63bb0d |
// Call this method to set AccountSASSignatureValues's Permissions field.
|
|
Packit |
63bb0d |
func (p AccountSASPermissions) String() string {
|
|
Packit |
63bb0d |
var buffer bytes.Buffer
|
|
Packit |
63bb0d |
if p.Read {
|
|
Packit |
63bb0d |
buffer.WriteRune('r')
|
|
Packit |
63bb0d |
}
|
|
Packit |
63bb0d |
if p.Write {
|
|
Packit |
63bb0d |
buffer.WriteRune('w')
|
|
Packit |
63bb0d |
}
|
|
Packit |
63bb0d |
if p.Delete {
|
|
Packit |
63bb0d |
buffer.WriteRune('d')
|
|
Packit |
63bb0d |
}
|
|
Packit Service |
3a6627 |
if p.DeletePreviousVersion {
|
|
Packit Service |
3a6627 |
buffer.WriteRune('x')
|
|
Packit Service |
3a6627 |
}
|
|
Packit |
63bb0d |
if p.List {
|
|
Packit |
63bb0d |
buffer.WriteRune('l')
|
|
Packit |
63bb0d |
}
|
|
Packit |
63bb0d |
if p.Add {
|
|
Packit |
63bb0d |
buffer.WriteRune('a')
|
|
Packit |
63bb0d |
}
|
|
Packit |
63bb0d |
if p.Create {
|
|
Packit |
63bb0d |
buffer.WriteRune('c')
|
|
Packit |
63bb0d |
}
|
|
Packit |
63bb0d |
if p.Update {
|
|
Packit |
63bb0d |
buffer.WriteRune('u')
|
|
Packit |
63bb0d |
}
|
|
Packit |
63bb0d |
if p.Process {
|
|
Packit |
63bb0d |
buffer.WriteRune('p')
|
|
Packit |
63bb0d |
}
|
|
Packit Service |
3a6627 |
if p.Tag {
|
|
Packit Service |
3a6627 |
buffer.WriteRune('t')
|
|
Packit Service |
3a6627 |
}
|
|
Packit Service |
3a6627 |
if p.FilterByTags {
|
|
Packit Service |
3a6627 |
buffer.WriteRune('f')
|
|
Packit Service |
3a6627 |
}
|
|
Packit |
63bb0d |
return buffer.String()
|
|
Packit |
63bb0d |
}
|
|
Packit |
63bb0d |
|
|
Packit |
63bb0d |
// Parse initializes the AccountSASPermissions's fields from a string.
|
|
Packit |
63bb0d |
func (p *AccountSASPermissions) Parse(s string) error {
|
|
Packit |
63bb0d |
*p = AccountSASPermissions{} // Clear out the flags
|
|
Packit |
63bb0d |
for _, r := range s {
|
|
Packit |
63bb0d |
switch r {
|
|
Packit |
63bb0d |
case 'r':
|
|
Packit |
63bb0d |
p.Read = true
|
|
Packit |
63bb0d |
case 'w':
|
|
Packit |
63bb0d |
p.Write = true
|
|
Packit |
63bb0d |
case 'd':
|
|
Packit |
63bb0d |
p.Delete = true
|
|
Packit |
63bb0d |
case 'l':
|
|
Packit |
63bb0d |
p.List = true
|
|
Packit |
63bb0d |
case 'a':
|
|
Packit |
63bb0d |
p.Add = true
|
|
Packit |
63bb0d |
case 'c':
|
|
Packit |
63bb0d |
p.Create = true
|
|
Packit |
63bb0d |
case 'u':
|
|
Packit |
63bb0d |
p.Update = true
|
|
Packit |
63bb0d |
case 'p':
|
|
Packit |
63bb0d |
p.Process = true
|
|
Packit Service |
3a6627 |
case 'x':
|
|
Packit Service |
3a6627 |
p.Process = true
|
|
Packit Service |
3a6627 |
case 't':
|
|
Packit Service |
3a6627 |
p.Tag = true
|
|
Packit Service |
3a6627 |
case 'f':
|
|
Packit Service |
3a6627 |
p.FilterByTags = true
|
|
Packit |
63bb0d |
default:
|
|
Packit Service |
3a6627 |
return fmt.Errorf("invalid permission character: '%v'", r)
|
|
Packit |
63bb0d |
}
|
|
Packit |
63bb0d |
}
|
|
Packit |
63bb0d |
return nil
|
|
Packit |
63bb0d |
}
|
|
Packit |
63bb0d |
|
|
Packit |
63bb0d |
// The AccountSASServices type simplifies creating the services string for an Azure Storage Account SAS.
|
|
Packit |
63bb0d |
// Initialize an instance of this type and then call its String method to set AccountSASSignatureValues's Services field.
|
|
Packit |
63bb0d |
type AccountSASServices struct {
|
|
Packit |
63bb0d |
Blob, Queue, File bool
|
|
Packit |
63bb0d |
}
|
|
Packit |
63bb0d |
|
|
Packit |
63bb0d |
// String produces the SAS services string for an Azure Storage account.
|
|
Packit |
63bb0d |
// Call this method to set AccountSASSignatureValues's Services field.
|
|
Packit |
63bb0d |
func (s AccountSASServices) String() string {
|
|
Packit |
63bb0d |
var buffer bytes.Buffer
|
|
Packit |
63bb0d |
if s.Blob {
|
|
Packit |
63bb0d |
buffer.WriteRune('b')
|
|
Packit |
63bb0d |
}
|
|
Packit |
63bb0d |
if s.Queue {
|
|
Packit |
63bb0d |
buffer.WriteRune('q')
|
|
Packit |
63bb0d |
}
|
|
Packit |
63bb0d |
if s.File {
|
|
Packit |
63bb0d |
buffer.WriteRune('f')
|
|
Packit |
63bb0d |
}
|
|
Packit |
63bb0d |
return buffer.String()
|
|
Packit |
63bb0d |
}
|
|
Packit |
63bb0d |
|
|
Packit |
63bb0d |
// Parse initializes the AccountSASServices' fields from a string.
|
|
Packit |
63bb0d |
func (a *AccountSASServices) Parse(s string) error {
|
|
Packit |
63bb0d |
*a = AccountSASServices{} // Clear out the flags
|
|
Packit |
63bb0d |
for _, r := range s {
|
|
Packit |
63bb0d |
switch r {
|
|
Packit |
63bb0d |
case 'b':
|
|
Packit |
63bb0d |
a.Blob = true
|
|
Packit |
63bb0d |
case 'q':
|
|
Packit |
63bb0d |
a.Queue = true
|
|
Packit |
63bb0d |
case 'f':
|
|
Packit |
63bb0d |
a.File = true
|
|
Packit |
63bb0d |
default:
|
|
Packit |
63bb0d |
return fmt.Errorf("Invalid service character: '%v'", r)
|
|
Packit |
63bb0d |
}
|
|
Packit |
63bb0d |
}
|
|
Packit |
63bb0d |
return nil
|
|
Packit |
63bb0d |
}
|
|
Packit |
63bb0d |
|
|
Packit |
63bb0d |
// The AccountSASResourceTypes type simplifies creating the resource types string for an Azure Storage Account SAS.
|
|
Packit |
63bb0d |
// Initialize an instance of this type and then call its String method to set AccountSASSignatureValues's ResourceTypes field.
|
|
Packit |
63bb0d |
type AccountSASResourceTypes struct {
|
|
Packit |
63bb0d |
Service, Container, Object bool
|
|
Packit |
63bb0d |
}
|
|
Packit |
63bb0d |
|
|
Packit |
63bb0d |
// String produces the SAS resource types string for an Azure Storage account.
|
|
Packit |
63bb0d |
// Call this method to set AccountSASSignatureValues's ResourceTypes field.
|
|
Packit |
63bb0d |
func (rt AccountSASResourceTypes) String() string {
|
|
Packit |
63bb0d |
var buffer bytes.Buffer
|
|
Packit |
63bb0d |
if rt.Service {
|
|
Packit |
63bb0d |
buffer.WriteRune('s')
|
|
Packit |
63bb0d |
}
|
|
Packit |
63bb0d |
if rt.Container {
|
|
Packit |
63bb0d |
buffer.WriteRune('c')
|
|
Packit |
63bb0d |
}
|
|
Packit |
63bb0d |
if rt.Object {
|
|
Packit |
63bb0d |
buffer.WriteRune('o')
|
|
Packit |
63bb0d |
}
|
|
Packit |
63bb0d |
return buffer.String()
|
|
Packit |
63bb0d |
}
|
|
Packit |
63bb0d |
|
|
Packit |
63bb0d |
// Parse initializes the AccountSASResourceType's fields from a string.
|
|
Packit |
63bb0d |
func (rt *AccountSASResourceTypes) Parse(s string) error {
|
|
Packit |
63bb0d |
*rt = AccountSASResourceTypes{} // Clear out the flags
|
|
Packit |
63bb0d |
for _, r := range s {
|
|
Packit |
63bb0d |
switch r {
|
|
Packit |
63bb0d |
case 's':
|
|
Packit |
63bb0d |
rt.Service = true
|
|
Packit |
63bb0d |
case 'c':
|
|
Packit |
63bb0d |
rt.Container = true
|
|
Packit |
63bb0d |
case 'o':
|
|
Packit |
63bb0d |
rt.Object = true
|
|
Packit |
63bb0d |
default:
|
|
Packit |
63bb0d |
return fmt.Errorf("Invalid resource type: '%v'", r)
|
|
Packit |
63bb0d |
}
|
|
Packit |
63bb0d |
}
|
|
Packit |
63bb0d |
return nil
|
|
Packit |
63bb0d |
}
|