A function app throws a Socket Exception when attempting to read or write from a storage queue
We have a .NET v.6 function app that reads/writes messages from a storage queue but is throwing a System.Net.Sockets.SocketException exception. The inner exception message is *"An attempt was made to access a socket in a way forbidden by its access permissions."
*
The storage queue was added to the same storage account containing the function app.
Any assistance would be most appreciated.
Azure Functions
Azure Queue Storage
-
Tadas Šukys 5 Reputation points
2024-11-21T14:00:33.7533333+00:00 Hi,
It seems that the problem is not directly related to the function app and/or queue service, the issue is at socket level, so it would be really good to get more context. For example, could you provide full exception details including stack trace. What libraries do you use for communication with storage queue services (including version number)? Is that Azure Storage Queues client library or anything else?
-
McDonald, Lloyd 0 Reputation points
2024-11-21T15:01:38.7866667+00:00 Hi Tadas,
I'm using the Azure.Storage.Queues.QueueClient (v.12.17.1) class to read/write to the storage queue.
I'm also using the Azure.Storage.Queues.QueueServiceClient (v.12.17.1) class to get an instance of the storage queue. The QueueServiceClient instance is injected into the constructor of a service class:
public class QueueService : IQueueService { private readonly QueueClient _queueClient; private readonly ILogger<QueueService> _logger; public QueueService(IConfiguration config, ILogger<QueueService> logger, QueueServiceClient queueServiceClient) { _logger = logger; _queueClient = queueServiceClient.GetQueueClient(config.GetValue<string>("StorageQueueName")); } }
The queue service and queue service client are registered with DI in the function app's Startup method:
builder.Services.AddSingleton<IQueueService, QueueService>(); builder.Services.AddAzureClients(builder => { // Use the environment credential by default. builder.UseCredential(new DefaultAzureCredential()); builder.AddQueueServiceClient(Configuration.GetValue<string>("StorageQueueConnection")); });
I suspect the issue may be with the line below, but we don't see the exception in the separate function app instance hosted in our UAT storage account.
builder.UseCredential(new DefaultAzureCredential());
Here's an exception stack trace from our App Insights logging:
equest [8153c211-c229-4c40-95f0-851f7f1d4442] exception Azure.RequestFailedException: An attempt was made to access a socket in a way forbidden by its access permissions. (127.0.0.1:10001)
---> System.Net.Http.HttpRequestException: An attempt was made to access a socket in a way forbidden by its access permissions. (127.0.0.1:10001)
---> System.Net.Sockets.SocketException (10013): An attempt was made to access a socket in a way forbidden by its access permissions.
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.CreateException(SocketError error, Boolean forAsyncThrow)
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ConnectAsync(Socket socket)
at System.Net.Sockets.Socket.ConnectAsync(EndPoint remoteEP, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.ConnectToTcpHostAsync(String host, Int32 port, HttpRequestMessage initialRequest, Boolean async, CancellationToken cancellationToken)
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.StartTStateMachine
at System.Net.Http.HttpConnectionPool.ConnectToTcpHostAsync(String host, Int32 port, HttpRequestMessage initialRequest, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.StartTStateMachine
at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.StartTStateMachine
at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.AddHttp11ConnectionAsync(HttpRequestMessage request)
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.StartTStateMachine
at System.Net.Http.HttpConnectionPool.AddHttp11ConnectionAsync(HttpRequestMessage request)
at System.Net.Http.HttpConnectionPool.<>c__DisplayClass75_0.<CheckForHttp11ConnectionInjection>b__0()
at System.Threading.Tasks.Task`1.InnerInvoke()
at System.Threading.Tasks.Task.<>c.<.cctor>b__272_0(Object obj)
at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
at System.Threading.Tasks.Task.ExecuteEntryUnsafe(Thread threadPoolThread)
at System.Threading.Tasks.Task.ExecuteFromThreadPool(Thread threadPoolThread)
at System.Threading.ThreadPoolWorkQueue.Dispatch()
at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()
at System.Threading.Thread.StartCallback()
--- End of stack trace from previous location ---
at System.Net.Http.HttpConnectionPool.ConnectToTcpHostAsync(String host, Int32 port, HttpRequestMessage initialRequest, Boolean async, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
at System.Net.Http.HttpConnectionPool.ConnectToTcpHostAsync(String host, Int32 port, HttpRequestMessage initialRequest, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.AddHttp11ConnectionAsync(HttpRequestMessage request)
at System.Threading.Tasks.TaskCompletionSourceWithCancellation`1.WaitWithCancellationAsync(CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.GetHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
at System.Net.Http.DiagnosticsHandler.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
at Azure.Core.Pipeline.HttpClientTransport.ProcessSyncOrAsync(HttpMessage message, Boolean async)
--- End of inner exception stack trace ---
at Azure.Core.Pipeline.HttpClientTransport.ProcessSyncOrAsync(HttpMessage message, Boolean async)
at Azure.Core.Pipeline.HttpPipelineTransportPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline)
at Azure.Core.Pipeline.RequestActivityPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)
at Azure.Core.Pipeline.ResponseBodyPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)
at Azure.Core.Pipeline.LoggingPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)
-
McDonald, Lloyd 0 Reputation points
2024-11-21T15:08:41.17+00:00 Hi Tadas,
I'm not sure what happened but I posted a reply with more detail and I don't see it here.
I see it now.
-
Tadas Šukys 5 Reputation points
2024-11-21T15:42:22.2133333+00:00 I don't like this line
Azure.RequestFailedException: An attempt was made to access a socket in a way forbidden by its access permissions. (127.0.0.1:10001)
it seems you're connecting to
127.0.0.1
and it is alocalhost
. Could you please check the connection string - are you pointing correct host? -
McDonald, Lloyd 0 Reputation points
2024-11-21T16:58:53.4266667+00:00 Hi,
The request post does indeed indicate the request origin is my locally hosted azure storage account running in Azurite.
The storage queue connection is stored in an environment variable which I confirmed has the correct connection string for our production environment, but I found the app settings JSON for Prod has the connection string set to my locally hosted azure storage account.
I thought a function app didn't read from the app settings JSON but from the environment settings in the portal's environment variables?
-
Tadas Šukys 5 Reputation points
2024-11-21T17:04:02.4666667+00:00 Yes, as far as I know function app doesn't read from the appsettings file, unless you explicitly have that in your code. So yes, it should take the connection string from the environment variables.
Sign in to comment