authorizer.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. package azure
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "github.com/Azure/azure-sdk-for-go/sdk/azidentity"
  6. "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob"
  7. "github.com/opencost/opencost/pkg/cloud"
  8. )
  9. const AccessKeyAuthorizerType = "AzureAccessKey"
  10. const DefaultAzureCredentialHolderAuthorizerType = "DefaultAzureCredentialHolder"
  11. type Authorizer interface {
  12. cloud.Authorizer
  13. GetBlobClient(urlTemplate string) (*azblob.Client, error)
  14. }
  15. // SelectAuthorizerByType is an implementation of AuthorizerSelectorFn and acts as a register for Authorizer types
  16. func SelectAuthorizerByType(typeStr string) (Authorizer, error) {
  17. switch typeStr {
  18. case AccessKeyAuthorizerType:
  19. return &AccessKey{}, nil
  20. case DefaultAzureCredentialHolderAuthorizerType:
  21. return &DefaultAzureCredentialHolder{}, nil
  22. default:
  23. return nil, fmt.Errorf("azure: provider authorizer type '%s' is not valid", typeStr)
  24. }
  25. }
  26. type AccessKey struct {
  27. AccessKey string `json:"accessKey"`
  28. Account string `json:"account"`
  29. }
  30. func (ak *AccessKey) MarshalJSON() ([]byte, error) {
  31. fmap := make(map[string]any, 3)
  32. fmap[cloud.AuthorizerTypeProperty] = AccessKeyAuthorizerType
  33. fmap["accessKey"] = ak.AccessKey
  34. fmap["account"] = ak.Account
  35. return json.Marshal(fmap)
  36. }
  37. func (ak *AccessKey) Validate() error {
  38. if ak.AccessKey == "" {
  39. return fmt.Errorf("AccessKey: missing access key")
  40. }
  41. if ak.Account == "" {
  42. return fmt.Errorf("AccessKey: missing account")
  43. }
  44. return nil
  45. }
  46. func (ak *AccessKey) Equals(config cloud.Config) bool {
  47. if config == nil {
  48. return false
  49. }
  50. thatConfig, ok := config.(*AccessKey)
  51. if !ok {
  52. return false
  53. }
  54. if ak.AccessKey != thatConfig.AccessKey {
  55. return false
  56. }
  57. if ak.Account != thatConfig.Account {
  58. return false
  59. }
  60. return true
  61. }
  62. func (ak *AccessKey) Sanitize() cloud.Config {
  63. return &AccessKey{
  64. AccessKey: cloud.Redacted,
  65. Account: ak.Account,
  66. }
  67. }
  68. func (ak *AccessKey) GetBlobClient(urlTemplate string) (*azblob.Client, error) {
  69. // Create a default request pipeline using your storage account name and account key.
  70. serviceURL := fmt.Sprintf(urlTemplate, ak.Account, "")
  71. credential, err := azblob.NewSharedKeyCredential(ak.Account, ak.AccessKey)
  72. if err != nil {
  73. return nil, err
  74. }
  75. client, err := azblob.NewClientWithSharedKeyCredential(serviceURL, credential, nil)
  76. return client, err
  77. }
  78. type DefaultAzureCredentialHolder struct {
  79. Account string `json:"account"`
  80. }
  81. func (dac *DefaultAzureCredentialHolder) MarshalJSON() ([]byte, error) {
  82. fmap := make(map[string]any, 2)
  83. fmap[cloud.AuthorizerTypeProperty] = DefaultAzureCredentialHolderAuthorizerType
  84. fmap["account"] = dac.Account
  85. return json.Marshal(fmap)
  86. }
  87. func (dac *DefaultAzureCredentialHolder) Validate() error {
  88. if dac.Account == "" {
  89. return fmt.Errorf("AccessKey: missing account")
  90. }
  91. return nil
  92. }
  93. func (dac *DefaultAzureCredentialHolder) Equals(config cloud.Config) bool {
  94. if config == nil {
  95. return false
  96. }
  97. thatConfig, ok := config.(*DefaultAzureCredentialHolder)
  98. if !ok {
  99. return false
  100. }
  101. if dac.Account != thatConfig.Account {
  102. return false
  103. }
  104. return true
  105. }
  106. func (dac *DefaultAzureCredentialHolder) Sanitize() cloud.Config {
  107. return &DefaultAzureCredentialHolder{}
  108. }
  109. func (dac *DefaultAzureCredentialHolder) GetBlobClient(urlTemplate string) (*azblob.Client, error) {
  110. serviceURL := fmt.Sprintf(urlTemplate, dac.Account, "")
  111. // Create a default request pipeline using your storage account name and account key.
  112. cred, err := azidentity.NewDefaultAzureCredential(nil)
  113. if err != nil {
  114. return nil, err
  115. }
  116. client, err := azblob.NewClient(serviceURL, cred, nil)
  117. return client, err
  118. }