From 97dc065d160d23d53826f8993f38f6155e96567a Mon Sep 17 00:00:00 2001 From: Bernd Verst Date: Mon, 6 Nov 2023 12:41:51 -0800 Subject: [PATCH 1/9] Fix incorrect Eventhubs error message Signed-off-by: Bernd Verst --- internal/component/azure/eventhubs/metadata.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/component/azure/eventhubs/metadata.go b/internal/component/azure/eventhubs/metadata.go index 494e03b37d..e003f3b69b 100644 --- a/internal/component/azure/eventhubs/metadata.go +++ b/internal/component/azure/eventhubs/metadata.go @@ -107,9 +107,9 @@ func parseEventHubsMetadata(meta map[string]string, isBinding bool, log logger.L } } - // If both storageConnectionString and storageAccountKey are specified, show a warning because the connection string will take priority + // If both storageConnectionString and storageAccountName are specified, show a warning because the connection string will take priority if m.StorageConnectionString != "" && m.StorageAccountName != "" { - log.Warn("Property storageAccountKey is ignored when storageConnectionString is present") + log.Warn("Property storageAccountName is ignored when storageConnectionString is present") } // Entity management is only possible when using Azure AD From cf4cc2352f16113fb56510427c8d6f6673fa3c88 Mon Sep 17 00:00:00 2001 From: Bernd Verst Date: Mon, 6 Nov 2023 13:11:51 -0800 Subject: [PATCH 2/9] Fix 3204: consul to accept hostnames again (#3211) Signed-off-by: Bernd Verst --- nameresolution/consul/consul.go | 8 +++++++- nameresolution/consul/consul_test.go | 29 ++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/nameresolution/consul/consul.go b/nameresolution/consul/consul.go index a92630591b..66533b4c30 100644 --- a/nameresolution/consul/consul.go +++ b/nameresolution/consul/consul.go @@ -323,7 +323,13 @@ func formatAddress(address string, port string) (addr string, err error) { return fmt.Sprintf("[%s]:%s", address, port), nil } - return "", fmt.Errorf("invalid ip address %s", address) + // addr is not a valid IP address + // use net.JoinHostPort to format address if address is a valid hostname + if _, err := net.LookupHost(address); err == nil { + return net.JoinHostPort(address, port), nil + } + + return "", fmt.Errorf("invalid ip address or unreachable hostname: %s", address) } // getConfig configuration from metadata, defaults are best suited for self-hosted mode. diff --git a/nameresolution/consul/consul_test.go b/nameresolution/consul/consul_test.go index 8f269ffde3..3f36c3394b 100644 --- a/nameresolution/consul/consul_test.go +++ b/nameresolution/consul/consul_test.go @@ -845,6 +845,35 @@ func TestResolveID(t *testing.T) { assert.Equal(t, "[2001:db8:3333:4444:5555:6666:7777:8888]:50005", addr) }, }, + { + "should get localhost (hostname) from service", + nr.ResolveRequest{ + ID: "test-app", + }, + func(t *testing.T, req nr.ResolveRequest) { + t.Helper() + mock := mockClient{ + mockHealth: mockHealth{ + serviceResult: []*consul.ServiceEntry{ + { + Service: &consul.AgentService{ + Address: "localhost", + Port: 8600, + Meta: map[string]string{ + "DAPR_PORT": "50005", + }, + }, + }, + }, + }, + } + resolver := newResolver(logger.NewLogger("test"), testConfig, &mock, ®istry{}, make(chan struct{})) + + addr, _ := resolver.ResolveID(context.Background(), req) + + assert.Equal(t, "localhost:50005", addr) + }, + }, { "should get random address from service", nr.ResolveRequest{ From 4e1210796b0686ee08cfc260fb9b8cf607d44525 Mon Sep 17 00:00:00 2001 From: Bernd Verst Date: Mon, 6 Nov 2023 14:19:40 -0800 Subject: [PATCH 3/9] Azure BlobStorage components: Add `disableEntityManagement` metadata option (#3213) Signed-off-by: Bernd Verst --- bindings/azure/blobstorage/metadata.yaml | 7 +++++- .../component/azure/blobstorage/client.go | 23 +++++++++++-------- .../component/azure/blobstorage/metadata.go | 7 +++--- state/azure/blobstorage/v1/metadata.yaml | 5 ++++ state/azure/blobstorage/v2/metadata.yaml | 5 ++++ 5 files changed, 33 insertions(+), 14 deletions(-) diff --git a/bindings/azure/blobstorage/metadata.yaml b/bindings/azure/blobstorage/metadata.yaml index 047d4fa0bb..0c436bb02e 100644 --- a/bindings/azure/blobstorage/metadata.yaml +++ b/bindings/azure/blobstorage/metadata.yaml @@ -87,4 +87,9 @@ metadata: example: '3' description: | Specifies the maximum number of HTTP requests that will be made to retry blob operations. - A value of zero means that no additional attempts will be made after a failure. \ No newline at end of file + A value of zero means that no additional attempts will be made after a failure. + - name: disableEntityManagement + description: "Disable entity management. Skips the attempt to create the specified storage container. This is useful when operating with minimal Azure AD permissions." + example: "true" + default: '"false"' + type: bool \ No newline at end of file diff --git a/internal/component/azure/blobstorage/client.go b/internal/component/azure/blobstorage/client.go index 858cd2b7ff..72374e3a33 100644 --- a/internal/component/azure/blobstorage/client.go +++ b/internal/component/azure/blobstorage/client.go @@ -62,16 +62,19 @@ func CreateContainerStorageClient(parentCtx context.Context, log logger.Logger, return nil, nil, err } - // Create the container if it doesn't already exist - var accessLevel *azblob.PublicAccessType - if m.PublicAccessLevel != "" && m.PublicAccessLevel != "none" { - accessLevel = &m.PublicAccessLevel - } - ctx, cancel := context.WithTimeout(parentCtx, 30*time.Second) - defer cancel() - err = m.EnsureContainer(ctx, client, accessLevel) - if err != nil { - return nil, nil, fmt.Errorf("failed to create Azure Storage container %s: %w", m.ContainerName, err) + // if entity management is disabled, do not attempt to create the container + if !m.DisableEntityManagement { + // Create the container if it doesn't already exist + var accessLevel *azblob.PublicAccessType + if m.PublicAccessLevel != "" && m.PublicAccessLevel != "none" { + accessLevel = &m.PublicAccessLevel + } + ctx, cancel := context.WithTimeout(parentCtx, 30*time.Second) + defer cancel() + err = m.EnsureContainer(ctx, client, accessLevel) + if err != nil { + return nil, nil, fmt.Errorf("failed to create Azure Storage container %s: %w", m.ContainerName, err) + } } return client, m, nil diff --git a/internal/component/azure/blobstorage/metadata.go b/internal/component/azure/blobstorage/metadata.go index 2f8b3132e0..ecd9c512d1 100644 --- a/internal/component/azure/blobstorage/metadata.go +++ b/internal/component/azure/blobstorage/metadata.go @@ -25,9 +25,10 @@ import ( ) type BlobStorageMetadata struct { - ContainerClientOpts `json:",inline" mapstructure:",squash"` - DecodeBase64 bool `json:"decodeBase64,string" mapstructure:"decodeBase64" mdonly:"bindings"` - PublicAccessLevel azblob.PublicAccessType + ContainerClientOpts `json:",inline" mapstructure:",squash"` + DecodeBase64 bool `json:"decodeBase64,string" mapstructure:"decodeBase64" mdonly:"bindings"` + PublicAccessLevel azblob.PublicAccessType + DisableEntityManagement bool `json:"disableEntityManagement,string" mapstructure:"disableEntityManagement"` } type ContainerClientOpts struct { diff --git a/state/azure/blobstorage/v1/metadata.yaml b/state/azure/blobstorage/v1/metadata.yaml index 0555701acb..411951fcb0 100644 --- a/state/azure/blobstorage/v1/metadata.yaml +++ b/state/azure/blobstorage/v1/metadata.yaml @@ -74,3 +74,8 @@ metadata: description: | Specifies the maximum number of HTTP requests that will be made to retry blob operations. A value of zero means that no additional attempts will be made after a failure. + - name: disableEntityManagement + description: "Disable entity management. Skips the attempt to create the specified storage container. This is useful when operating with minimal Azure AD permissions." + example: "true" + default: '"false"' + type: bool \ No newline at end of file diff --git a/state/azure/blobstorage/v2/metadata.yaml b/state/azure/blobstorage/v2/metadata.yaml index 1135047019..ba52673110 100644 --- a/state/azure/blobstorage/v2/metadata.yaml +++ b/state/azure/blobstorage/v2/metadata.yaml @@ -74,3 +74,8 @@ metadata: description: | Specifies the maximum number of HTTP requests that will be made to retry blob operations. A value of zero means that no additional attempts will be made after a failure. + - name: disableEntityManagement + description: "Disable entity management. Skips the attempt to create the specified storage container. This is useful when operating with minimal Azure AD permissions." + example: "true" + default: '"false"' + type: bool \ No newline at end of file From 6a0b625a6c8fe56bc5cc264f5346b2e4d316d430 Mon Sep 17 00:00:00 2001 From: Bernd Verst Date: Wed, 8 Nov 2023 16:04:25 -0800 Subject: [PATCH 4/9] Allow Azure Auth order to be specified via azureAuthMethods metadata Signed-off-by: Bernd Verst --- internal/authentication/azure/auth.go | 176 ++++++++++++------ internal/authentication/azure/auth_test.go | 74 ++++++++ .../azure/metadata-properties.go | 3 + 3 files changed, 197 insertions(+), 56 deletions(-) diff --git a/internal/authentication/azure/auth.go b/internal/authentication/azure/auth.go index bd35d4844c..097a5c01ed 100644 --- a/internal/authentication/azure/auth.go +++ b/internal/authentication/azure/auth.go @@ -105,94 +105,158 @@ func (s EnvironmentSettings) GetAzureEnvironment() (*cloud.Configuration, error) } } -// GetTokenCredential returns an azcore.TokenCredential retrieved from, in order: -// 1. Client credentials -// 2. Client certificate -// 3. Workload identity -// 4. MSI (we use a timeout of 1 second when no compatible managed identity implementation is available) -// 5. Azure CLI -// -// This order and timeout (with the exception of the additional step 5) matches the DefaultAzureCredential. -func (s EnvironmentSettings) GetTokenCredential() (azcore.TokenCredential, error) { - // Create a chain - var creds []azcore.TokenCredential - errs := make([]error, 0, 3) - - // 1. Client credentials +func (s EnvironmentSettings) addClientCredentialsProvider(creds *[]azcore.TokenCredential, errs *[]error) { if c, e := s.GetClientCredentials(); e == nil { cred, err := c.GetTokenCredential() if err == nil { - creds = append(creds, cred) + *creds = append(*creds, cred) } else { - errs = append(errs, err) + *errs = append(*errs, err) } } +} - // 2. Client certificate +func (s EnvironmentSettings) addClientCertificateProvider(creds *[]azcore.TokenCredential, errs *[]error) { if c, e := s.GetClientCert(); e == nil { cred, err := c.GetTokenCredential() if err == nil { - creds = append(creds, cred) + *creds = append(*creds, cred) } else { - errs = append(errs, err) + *errs = append(*errs, err) } } +} - // 3. Workload identity +func (s EnvironmentSettings) addWorkloadIdentityProvider(creds *[]azcore.TokenCredential, errs *[]error) { // workload identity requires values for AZURE_AUTHORITY_HOST, AZURE_CLIENT_ID, AZURE_FEDERATED_TOKEN_FILE, AZURE_TENANT_ID // The workload identity mutating admissions webhook in Kubernetes injects these values into the pod. // These environment variables are read using the default WorkloadIdentityCredentialOptions - workloadCred, err := azidentity.NewWorkloadIdentityCredential(nil) if err == nil { - creds = append(creds, workloadCred) + *creds = append(*creds, workloadCred) } else { - errs = append(errs, err) + *errs = append(*errs, err) } +} - // 4. MSI with timeout of 1 second (same as DefaultAzureCredential) - { - c := s.GetMSI() - msiCred, err := c.GetTokenCredential() +func (s EnvironmentSettings) addManagedIdentityProvider(timeout time.Duration, creds *[]azcore.TokenCredential, errs *[]error) { + c := s.GetMSI() + msiCred, err := c.GetTokenCredential() - useTimeout := true - if _, ok := os.LookupEnv(identityEndpoint); ok { - // App Service & Service Fabric + useTimeout := true + if _, ok := os.LookupEnv(identityEndpoint); ok { + // App Service, Functions, Service Fabric and Container Apps + useTimeout = false + } else { + if _, ok := os.LookupEnv(arcIMDSEndpoint); ok { + // Azure Arc useTimeout = false } else { - if _, ok := os.LookupEnv(arcIMDSEndpoint); ok { - // Azure Arc + if _, ok := os.LookupEnv(msiEndpoint); ok { + // Cloud Shell + useTimeout = false + } else if isVirtualMachineWithManagedIdentity() { + // Azure VM with MSI enabled useTimeout = false - } else { - if _, ok := os.LookupEnv(msiEndpoint); ok { - // Cloud Shell - useTimeout = false - } else if isVirtualMachineWithManagedIdentity() { - // Azure VM with MSI enabled - useTimeout = false - } } } + } - // We need to use a timeout for MSI on environments where it is not available because the request for the default IMDS endpoint can hang for several minutes. - if useTimeout { - msiCred = &timeoutWrapper{cred: msiCred, authmethod: "managed identity", timeout: 1 * time.Second} - } + // We need to use a timeout for MSI on environments where it is not available because the request for the default IMDS endpoint can hang for several minutes. + if useTimeout { + msiCred = &timeoutWrapper{cred: msiCred, authmethod: "managed identity", timeout: timeout} + } - if err == nil { - creds = append(creds, msiCred) - } else { - errs = append(errs, err) - } + if err == nil { + *creds = append(*creds, msiCred) + } else { + *errs = append(*errs, err) } +} - // 5. AzureCLICredential - { - cred, credErr := azidentity.NewAzureCLICredential(nil) - if credErr == nil { - creds = append(creds, &timeoutWrapper{cred: cred, authmethod: "Azure CLI", timeout: 30 * time.Second}) - } else { - errs = append(errs, credErr) +func (s EnvironmentSettings) addCLIProvider(timeout time.Duration, creds *[]azcore.TokenCredential, errs *[]error) { + cred, credErr := azidentity.NewAzureCLICredential(nil) + if credErr == nil { + *creds = append(*creds, &timeoutWrapper{cred: cred, authmethod: "Azure CLI", timeout: 30 * time.Second}) + } else { + *errs = append(*errs, credErr) + } +} + +func (s EnvironmentSettings) addProviderByAuthMethodName(authMethod string, creds *[]azcore.TokenCredential, errs *[]error) { + switch authMethod { + case "serviceprincipal": + s.addClientCredentialsProvider(creds, errs) + case "certificate": + s.addClientCertificateProvider(creds, errs) + case "workloadidentity": + s.addWorkloadIdentityProvider(creds, errs) + case "managedidentity": + s.addManagedIdentityProvider(1*time.Second, creds, errs) + case "cli": + s.addCLIProvider(30*time.Second, creds, errs) + } +} + +func getAzureAuthMethods() [6]string { + return [...]string{"serviceprincipal", "certificate", "workloadidentity", "managedidentity", "cli", "none"} +} + +// GetTokenCredential returns an azcore.TokenCredential retrieved from the order specified via +// the azureAuthMethods component metadata property which denotes a comma-separated list of auth methods to try in order. +// The possible values contained are (case-insensitive): +// ServicePrincipal, Certificate, WorkloadIdentity, ManagedIdentity, CLI +// The string "None" can be used to disable Azure authentication. +// +// If the azureAuthMethods property is not present, the following order is used (which with the exception of step 5 +// matches the DefaultAzureCredential order): +// 1. Client credentials +// 2. Client certificate +// 3. Workload identity +// 4. MSI (we use a timeout of 1 second when no compatible managed identity implementation is available) +// 5. Azure CLI +func (s EnvironmentSettings) GetTokenCredential() (azcore.TokenCredential, error) { + // Create a chain + var creds []azcore.TokenCredential + errs := make([]error, 0, 3) + + authMethods, ok := s.GetEnvironment("AzureAuthMethods") + if !ok || strings.TrimSpace(authMethods) == "" { + // 1. Client credentials + s.addClientCredentialsProvider(&creds, &errs) + + // 2. Client certificate + s.addClientCertificateProvider(&creds, &errs) + + // 3. Workload identity + s.addWorkloadIdentityProvider(&creds, &errs) + + // 4. MSI with timeout of 1 second (same as DefaultAzureCredential) + s.addManagedIdentityProvider(1*time.Second, &creds, &errs) + + // 5. AzureCLICredential + s.addCLIProvider(30*time.Second, &creds, &errs) + } else { + authMethodIdentifiers := getAzureAuthMethods() + authMethods := strings.Split(strings.ToLower(strings.TrimSpace(authMethods)), ",") + for _, authMethod := range authMethods { + authMethod = strings.TrimSpace(authMethod) + found := false + for _, authMethodIdentifier := range authMethodIdentifiers { + if authMethod == authMethodIdentifier { + found = true + if authMethod != "none" { + s.addProviderByAuthMethodName(authMethod, &creds, &errs) + break + } else { + // If authMethod is "none", we don't add any provider and return an error + return nil, fmt.Errorf("all Azure auth methods have been disabled with auth method 'None'") + } + } + } + if !found { + return nil, fmt.Errorf("invalid Azure auth method: %v", authMethod) + } } } diff --git a/internal/authentication/azure/auth_test.go b/internal/authentication/azure/auth_test.go index c699900d1b..f6cedbff1a 100644 --- a/internal/authentication/azure/auth_test.go +++ b/internal/authentication/azure/auth_test.go @@ -221,6 +221,80 @@ func TestAuthorizorWithMSI(t *testing.T) { assert.NotNil(t, spt) } +func TestFallbackToMSIbutAzureAuthDisallowed(t *testing.T) { + os.Setenv("MSI_ENDPOINT", "test") + defer os.Unsetenv("MSI_ENDPOINT") + settings, err := NewEnvironmentSettings( + map[string]string{ + "azureClientId": fakeClientID, + "vaultName": "vaultName", + "azureAuthMethods": "None", + }, + ) + assert.NoError(t, err) + + _, err = settings.GetTokenCredential() + assert.Error(t, err) + assert.ErrorContains(t, err, "all Azure auth methods have been disabled") +} + +func TestFallbackToMSIandInAllowedList(t *testing.T) { + os.Setenv("MSI_ENDPOINT", "test") + defer os.Unsetenv("MSI_ENDPOINT") + settings, err := NewEnvironmentSettings( + map[string]string{ + "azureClientId": fakeClientID, + "vaultName": "vaultName", + "azureAuthMethods": "serviceprincipal,certificate,workloadidentity,managedIdentity", + }, + ) + assert.NoError(t, err) + + testCertConfig := settings.GetMSI() + assert.NotNil(t, testCertConfig) + + spt, err := settings.GetTokenCredential() + assert.NoError(t, err) + assert.NotNil(t, spt) +} + +func TestFallbackToMSIandNotInAllowedList(t *testing.T) { + os.Setenv("MSI_ENDPOINT", "test") + defer os.Unsetenv("MSI_ENDPOINT") + settings, err := NewEnvironmentSettings( + map[string]string{ + "azureClientId": fakeClientID, + "vaultName": "vaultName", + "azureAuthMethods": "serviceprincipal,certificate,workloadidentity", + }, + ) + assert.NoError(t, err) + + _, err = settings.GetTokenCredential() + assert.Error(t, err) + assert.ErrorContains(t, err, "no suitable token provider for Azure AD") +} + +func TestFallbackToMSIandInvalidAuthMethod(t *testing.T) { + os.Setenv("MSI_ENDPOINT", "test") + defer os.Unsetenv("MSI_ENDPOINT") + settings, err := NewEnvironmentSettings( + map[string]string{ + "azureClientId": fakeClientID, + "vaultName": "vaultName", + "azureAuthMethods": "serviceprincipal,certificate,workloadidentity,managedIdentity,cli,SUPERAUTH", + }, + ) + assert.NoError(t, err) + + testCertConfig := settings.GetMSI() + assert.NotNil(t, testCertConfig) + + _, err = settings.GetTokenCredential() + assert.Error(t, err) + assert.ErrorContains(t, err, "invalid Azure auth method: superauth") +} + func TestAuthorizorWithMSIAndUserAssignedID(t *testing.T) { os.Setenv("MSI_ENDPOINT", "test") defer os.Unsetenv("MSI_ENDPOINT") diff --git a/internal/authentication/azure/metadata-properties.go b/internal/authentication/azure/metadata-properties.go index aaf22221e7..dc2c0fa3d2 100644 --- a/internal/authentication/azure/metadata-properties.go +++ b/internal/authentication/azure/metadata-properties.go @@ -35,6 +35,9 @@ var MetadataKeys = map[string][]string{ //nolint:gochecknoglobals // Identifier for the Azure environment // Allowed values (case-insensitive): AzurePublicCloud/AzurePublic, AzureChinaCloud/AzureChina, AzureUSGovernmentCloud/AzureUSGovernment "AzureEnvironment": {"azureEnvironment", "azureCloud"}, + // Identifier for the Azure authentication methods to try (in order), comma-separated + // Allowed values (case-insensitive): ServicePrincipal, Certificate, WorkloadIdentity, ManagedIdentity, CLI, None + "AzureAuthMethods": {"azureAuthMethods", "azureADAuthMethods"}, // Metadata keys for storage components From 20d74fc7591e3169062c2f92cbd431d02000f59d Mon Sep 17 00:00:00 2001 From: Bernd Verst Date: Thu, 9 Nov 2023 10:52:23 -0800 Subject: [PATCH 5/9] Update internal/authentication/azure/auth_test.go Co-authored-by: Alessandro (Ale) Segala <43508+ItalyPaleAle@users.noreply.github.com> Signed-off-by: Bernd Verst --- internal/authentication/azure/auth_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/authentication/azure/auth_test.go b/internal/authentication/azure/auth_test.go index f6cedbff1a..16e314e464 100644 --- a/internal/authentication/azure/auth_test.go +++ b/internal/authentication/azure/auth_test.go @@ -288,7 +288,7 @@ func TestFallbackToMSIandInvalidAuthMethod(t *testing.T) { assert.NoError(t, err) testCertConfig := settings.GetMSI() - assert.NotNil(t, testCertConfig) + require.NotNil(t, testCertConfig) _, err = settings.GetTokenCredential() assert.Error(t, err) From fb905e40386f9690421dc6f3b07849c34db7c651 Mon Sep 17 00:00:00 2001 From: Bernd Verst Date: Thu, 9 Nov 2023 10:52:30 -0800 Subject: [PATCH 6/9] Update internal/authentication/azure/auth_test.go Co-authored-by: Alessandro (Ale) Segala <43508+ItalyPaleAle@users.noreply.github.com> Signed-off-by: Bernd Verst --- internal/authentication/azure/auth_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/authentication/azure/auth_test.go b/internal/authentication/azure/auth_test.go index 16e314e464..ed43fb0590 100644 --- a/internal/authentication/azure/auth_test.go +++ b/internal/authentication/azure/auth_test.go @@ -285,7 +285,7 @@ func TestFallbackToMSIandInvalidAuthMethod(t *testing.T) { "azureAuthMethods": "serviceprincipal,certificate,workloadidentity,managedIdentity,cli,SUPERAUTH", }, ) - assert.NoError(t, err) + require.NoError(t, err) testCertConfig := settings.GetMSI() require.NotNil(t, testCertConfig) From 9f955e52cc6f09f9be1b447a7730c8b75e23c718 Mon Sep 17 00:00:00 2001 From: luigirende Date: Thu, 9 Nov 2023 19:18:27 +0100 Subject: [PATCH 7/9] AWS S3 Binding - Add Content-Type in the metadata request (#3216) Signed-off-by: luigirende Signed-off-by: luiren Signed-off-by: Alessandro (Ale) Segala <43508+ItalyPaleAle@users.noreply.github.com> Co-authored-by: luiren Co-authored-by: Alessandro (Ale) Segala <43508+ItalyPaleAle@users.noreply.github.com> --- bindings/aws/s3/s3.go | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/bindings/aws/s3/s3.go b/bindings/aws/s3/s3.go index 81fb6ad059..12b0d05173 100644 --- a/bindings/aws/s3/s3.go +++ b/bindings/aws/s3/s3.go @@ -48,7 +48,8 @@ const ( metadataFilePath = "filePath" metadataPresignTTL = "presignTTL" - metadataKey = "key" + metatadataContentType = "Content-Type" + metadataKey = "key" defaultMaxResults = 1000 presignOperation = "presign" @@ -172,6 +173,11 @@ func (s *AWSS3) create(ctx context.Context, req *bindings.InvokeRequest) (*bindi s.logger.Debugf("s3 binding error: key not found. generating key %s", key) } + var contentType *string + contentTypeStr := strings.TrimSpace(req.Metadata[metatadataContentType]) + if contentTypeStr != "" { + contentType = &contentTypeStr + } var r io.Reader if metadata.FilePath != "" { r, err = os.Open(metadata.FilePath) @@ -187,9 +193,10 @@ func (s *AWSS3) create(ctx context.Context, req *bindings.InvokeRequest) (*bindi } resultUpload, err := s.uploader.UploadWithContext(ctx, &s3manager.UploadInput{ - Bucket: ptr.Of(metadata.Bucket), - Key: ptr.Of(key), - Body: r, + Bucket: ptr.Of(metadata.Bucket), + Key: ptr.Of(key), + Body: r, + ContentType: contentType, }) if err != nil { return nil, fmt.Errorf("s3 binding error: uploading failed: %w", err) From 1c99146fa1600bee2dda352c06ccf420396252b8 Mon Sep 17 00:00:00 2001 From: Bernd Verst Date: Thu, 9 Nov 2023 12:12:13 -0800 Subject: [PATCH 8/9] rename auth methods and provide shortnames Signed-off-by: Bernd Verst --- internal/authentication/azure/auth.go | 14 +++++++------- internal/authentication/azure/auth_test.go | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/internal/authentication/azure/auth.go b/internal/authentication/azure/auth.go index 097a5c01ed..13ac55e6df 100644 --- a/internal/authentication/azure/auth.go +++ b/internal/authentication/azure/auth.go @@ -185,21 +185,21 @@ func (s EnvironmentSettings) addCLIProvider(timeout time.Duration, creds *[]azco func (s EnvironmentSettings) addProviderByAuthMethodName(authMethod string, creds *[]azcore.TokenCredential, errs *[]error) { switch authMethod { - case "serviceprincipal": + case "clientcredentials", "creds": s.addClientCredentialsProvider(creds, errs) - case "certificate": + case "clientcertificate", "cert": s.addClientCertificateProvider(creds, errs) - case "workloadidentity": + case "workloadidentity", "wi": s.addWorkloadIdentityProvider(creds, errs) - case "managedidentity": + case "managedidentity", "mi": s.addManagedIdentityProvider(1*time.Second, creds, errs) - case "cli": + case "commandlineinterface", "cli": s.addCLIProvider(30*time.Second, creds, errs) } } -func getAzureAuthMethods() [6]string { - return [...]string{"serviceprincipal", "certificate", "workloadidentity", "managedidentity", "cli", "none"} +func getAzureAuthMethods() []string { + return []string{"clientcredentials", "creds", "clientcertificate", "cert", "workloadidentity", "wi", "managedidentity", "mi", "commandlineinterface", "cli", "none"} } // GetTokenCredential returns an azcore.TokenCredential retrieved from the order specified via diff --git a/internal/authentication/azure/auth_test.go b/internal/authentication/azure/auth_test.go index ed43fb0590..2e99f4ced9 100644 --- a/internal/authentication/azure/auth_test.go +++ b/internal/authentication/azure/auth_test.go @@ -245,7 +245,7 @@ func TestFallbackToMSIandInAllowedList(t *testing.T) { map[string]string{ "azureClientId": fakeClientID, "vaultName": "vaultName", - "azureAuthMethods": "serviceprincipal,certificate,workloadidentity,managedIdentity", + "azureAuthMethods": "clientcredentials,clientcertificate,workloadidentity,managedIdentity", }, ) assert.NoError(t, err) @@ -265,7 +265,7 @@ func TestFallbackToMSIandNotInAllowedList(t *testing.T) { map[string]string{ "azureClientId": fakeClientID, "vaultName": "vaultName", - "azureAuthMethods": "serviceprincipal,certificate,workloadidentity", + "azureAuthMethods": "clientcredentials,clientcertificate,workloadidentity", }, ) assert.NoError(t, err) @@ -282,7 +282,7 @@ func TestFallbackToMSIandInvalidAuthMethod(t *testing.T) { map[string]string{ "azureClientId": fakeClientID, "vaultName": "vaultName", - "azureAuthMethods": "serviceprincipal,certificate,workloadidentity,managedIdentity,cli,SUPERAUTH", + "azureAuthMethods": "clientcredentials,clientcertificate,workloadidentity,managedIdentity,cli,SUPERAUTH", }, ) require.NoError(t, err) From 69bf7145015b440e19fe96a6892986c274ab8173 Mon Sep 17 00:00:00 2001 From: Bernd Verst Date: Thu, 9 Nov 2023 12:20:36 -0800 Subject: [PATCH 9/9] entraID auth Signed-off-by: Bernd Verst --- internal/authentication/azure/metadata-properties.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/authentication/azure/metadata-properties.go b/internal/authentication/azure/metadata-properties.go index dc2c0fa3d2..650fb4e44a 100644 --- a/internal/authentication/azure/metadata-properties.go +++ b/internal/authentication/azure/metadata-properties.go @@ -36,8 +36,8 @@ var MetadataKeys = map[string][]string{ //nolint:gochecknoglobals // Allowed values (case-insensitive): AzurePublicCloud/AzurePublic, AzureChinaCloud/AzureChina, AzureUSGovernmentCloud/AzureUSGovernment "AzureEnvironment": {"azureEnvironment", "azureCloud"}, // Identifier for the Azure authentication methods to try (in order), comma-separated - // Allowed values (case-insensitive): ServicePrincipal, Certificate, WorkloadIdentity, ManagedIdentity, CLI, None - "AzureAuthMethods": {"azureAuthMethods", "azureADAuthMethods"}, + // Allowed values (case-insensitive): ClientCredentials, creds, ClientCertificate, cert, WorkloadIdentity, wi, ManagedIdentity, mi, CommandLineInterface, cli, None + "AzureAuthMethods": {"azureAuthMethods", "azureADAuthMethods", "entraIDAuthMethods", "microsoftEntraIDAuthMethods"}, // Metadata keys for storage components