github.com/Jeffail/benthos/v3@v3.65.0/internal/impl/azure/azure.go (about)

     1  package azure
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"net/url"
     7  	"os"
     8  	"strings"
     9  
    10  	"github.com/Azure/azure-storage-queue-go/azqueue"
    11  )
    12  
    13  const (
    14  	azQueueEndpointExp  = "https://%s.queue.core.windows.net"
    15  	devQueueEndpointExp = "http://localhost:10001/%s"
    16  	azAccountName       = "accountname"
    17  	azAccountKey        = "accountkey"
    18  	devAccountName      = "devstoreaccount1"
    19  	devAccountKey       = "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="
    20  )
    21  
    22  // GetQueueServiceURL creates an Azure Queue URL from storage fields.
    23  func GetQueueServiceURL(storageAccount, storageAccessKey, storageConnectionString string) (*azqueue.ServiceURL, error) {
    24  	if storageAccount == "" && storageConnectionString == "" {
    25  		return nil, errors.New("invalid azure storage account credentials")
    26  	}
    27  	var endpointExp = azQueueEndpointExp
    28  	var err error
    29  	if storageConnectionString != "" {
    30  		if strings.Contains(storageConnectionString, "UseDevelopmentStorage=true;") {
    31  			storageAccount = devAccountName
    32  			storageAccessKey = devAccountKey
    33  			endpointExp = devQueueEndpointExp
    34  			if ap := os.Getenv("AZURITE_QUEUE_ENDPOINT_PORT"); ap != "" {
    35  				endpointExp = strings.ReplaceAll(devQueueEndpointExp, "10001", ap)
    36  			}
    37  		} else {
    38  			storageAccount, storageAccessKey, err = parseConnectionString(storageConnectionString)
    39  			if err != nil {
    40  				return nil, err
    41  			}
    42  			if strings.Contains(storageConnectionString, devAccountName) {
    43  				endpointExp = devQueueEndpointExp
    44  			}
    45  		}
    46  	}
    47  	if storageAccount == "" {
    48  		return nil, fmt.Errorf("invalid azure storage account credentials: %v", err)
    49  	}
    50  	var credential azqueue.Credential
    51  	if storageAccessKey != "" {
    52  		credential, _ = azqueue.NewSharedKeyCredential(storageAccount, storageAccessKey)
    53  	} else {
    54  		credential = azqueue.NewAnonymousCredential()
    55  	}
    56  
    57  	p := azqueue.NewPipeline(credential, azqueue.PipelineOptions{})
    58  	endpoint, _ := url.Parse(fmt.Sprintf(endpointExp, storageAccount))
    59  	serviceURL := azqueue.NewServiceURL(*endpoint, p)
    60  
    61  	return &serviceURL, err
    62  }
    63  
    64  // parseConnectionString extracts the credentials from the connection string.
    65  func parseConnectionString(input string) (storageAccount, storageAccessKey string, err error) {
    66  	// build a map of connection string key/value pairs
    67  	parts := map[string]string{}
    68  	for _, pair := range strings.Split(input, ";") {
    69  		if pair == "" {
    70  			continue
    71  		}
    72  		equalDex := strings.IndexByte(pair, '=')
    73  		if equalDex <= 0 {
    74  			fmt.Println(fmt.Errorf("invalid connection segment %q", pair))
    75  		}
    76  		value := strings.TrimSpace(pair[equalDex+1:])
    77  		key := strings.TrimSpace(strings.ToLower(pair[:equalDex]))
    78  		parts[key] = value
    79  	}
    80  	accountName, ok := parts[azAccountName]
    81  	if !ok {
    82  		return "", "", errors.New("invalid connection string")
    83  	}
    84  	accountKey, ok := parts[azAccountKey]
    85  	if !ok {
    86  		return "", "", errors.New("invalid connection string")
    87  	}
    88  	return accountName, accountKey, nil
    89  }