EDIT: I have added my lambda function code at the end.
Using LocalStack hosted in Docker on Windows 11, I have successfully bootstrapped my environment and deployed my ASP.NET Core (net8.0) Lambda Function there.
Afterwards, following the instructions here, I first executed the required command to add permissions, as follows:
awslocal lambda add-permission --function-name MyFunction-0899f6ad --action lambda:InvokeFunctionUrl --principal "*" --function-url-auth-type "NONE" --statement-id url
Which returned successfully, as follows:
{
"Statement": "{\"Sid\": \"url\", \"Effect\": \"Allow\", \"Action\": \"lambda:InvokeFunctionUrl\", \"Resource\": \"arn:aws:lambda:us-east-1:000000000000:function:MyFunction-0899f6ad\", \"Principal\": \"*\", \"Condition\": {\"StringEquals\": {\"lambda:FunctionUrlAuthType\": \"NONE\"}}}"
}
Then, I executed the command to create a function URL, as follows:
awslocal lambda create-function-url-config --function-name "MyFunction-0899f6ad" --auth-type NONE
This, also, returned successfully, as shown below:
{
"FunctionUrl": "http://xl3t3h8j6txijxlulho47p2rqibxlpz0.lambda-url.us-east-1.localhost.localstack.cloud:4566/",
"FunctionArn": "arn:aws:lambda:us-east-1:000000000000:function:MyFunction-0899f6ad",
"AuthType": "NONE",
"CreationTime": "2024-04-12T21:08:20.399288+0000"
}
But when I try to hit the above URL (http://xl3t3h8j6txijxlulho47p2rqibxlpz0.lambda-url.us-east-1.localhost.localstack.cloud:4566/
) either via Postman or a browser, I receive a 404 Not Found Error.
I have verified that all my required AWS services are up and running in LocalStack in Docker.
I have also verified that everything looks good in the LocalStack Web Application. Here are the CloudWatch logs:
2024-04-12 17:09:16
[2024/04/12/[$LATEST]699c28b024c9837acfad81f139d73eb4]
warn: Microsoft.AspNetCore.DataProtection.Repositories.EphemeralXmlRepository[50]
2024-04-12 17:09:16
[2024/04/12/[$LATEST]699c28b024c9837acfad81f139d73eb4]
Using an in-memory repository. Keys will not be persisted to storage.
2024-04-12 17:09:16
[2024/04/12/[$LATEST]699c28b024c9837acfad81f139d73eb4]
warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[59]
2024-04-12 17:09:16
[2024/04/12/[$LATEST]699c28b024c9837acfad81f139d73eb4]
Neither user profile nor HKLM registry available. Using an ephemeral key repository. Protected data will be unavailable when application exits.
2024-04-12 17:09:16
[2024/04/12/[$LATEST]699c28b024c9837acfad81f139d73eb4]
warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
2024-04-12 17:09:16
[2024/04/12/[$LATEST]699c28b024c9837acfad81f139d73eb4]
No XML encryptor configured. Key {88bef046-948e-4af3-b778-24a58a700cd0} may be persisted to storage in unencrypted form.
2024-04-12 17:09:16
[2024/04/12/[$LATEST]699c28b024c9837acfad81f139d73eb4]
START RequestId: 0ddab432-a721-4c3a-8725-b9737621cb07 Version: $LATEST
2024-04-12 17:09:16
[2024/04/12/[$LATEST]699c28b024c9837acfad81f139d73eb4]
END RequestId: 0ddab432-a721-4c3a-8725-b9737621cb07
2024-04-12 17:09:16
[2024/04/12/[$LATEST]699c28b024c9837acfad81f139d73eb4]
REPORT RequestId: 0ddab432-a721-4c3a-8725-b9737621cb07 Duration: 205.81 ms Billed Duration: 206 ms Memory Size: 128 MB Max Memory Used: 128 MB
2024-04-12 17:09:36
[2024/04/12/[$LATEST]699c28b024c9837acfad81f139d73eb4]
START RequestId: b44086d8-4844-4c1b-a393-81aaa676798c Version: $LATEST
2024-04-12 17:09:36
[2024/04/12/[$LATEST]699c28b024c9837acfad81f139d73eb4]
END RequestId: b44086d8-4844-4c1b-a393-81aaa676798c
2024-04-12 17:09:36
[2024/04/12/[$LATEST]699c28b024c9837acfad81f139d73eb4]
REPORT RequestId: b44086d8-4844-4c1b-a393-81aaa676798c Duration: 9.56 ms Billed Duration: 10 ms Memory Size: 128 MB Max Memory Used: 128 MB
2024-04-12 17:11:21
[2024/04/12/[$LATEST]699c28b024c9837acfad81f139d73eb4]
START RequestId: 33a351f8-35ea-4688-ad64-59aea7f3aea2 Version: $LATEST
2024-04-12 17:11:21
[2024/04/12/[$LATEST]699c28b024c9837acfad81f139d73eb4]
END RequestId: 33a351f8-35ea-4688-ad64-59aea7f3aea2
2024-04-12 17:11:21
[2024/04/12/[$LATEST]699c28b024c9837acfad81f139d73eb4]
REPORT RequestId: 33a351f8-35ea-4688-ad64-59aea7f3aea2 Duration: 8.19 ms Billed Duration: 9 ms Memory Size: 128 MB Max Memory Used: 128 MB
2024-04-12 17:12:56
[2024/04/12/[$LATEST]699c28b024c9837acfad81f139d73eb4]
START RequestId: 53cdeac9-1f70-40ea-8d11-4751ec0ca42d Version: $LATEST
2024-04-12 17:12:56
[2024/04/12/[$LATEST]699c28b024c9837acfad81f139d73eb4]
END RequestId: 53cdeac9-1f70-40ea-8d11-4751ec0ca42d
2024-04-12 17:12:56
[2024/04/12/[$LATEST]699c28b024c9837acfad81f139d73eb4]
REPORT RequestId: 53cdeac9-1f70-40ea-8d11-4751ec0ca42d Duration: 3.96 ms Billed Duration: 4 ms Memory Size: 128 MB Max Memory Used: 128 MB
2024-04-12 17:13:23
[2024/04/12/[$LATEST]699c28b024c9837acfad81f139d73eb4]
START RequestId: 819f2f74-7c10-409a-8e9e-38202df929e5 Version: $LATEST
2024-04-12 17:13:23
[2024/04/12/[$LATEST]699c28b024c9837acfad81f139d73eb4]
END RequestId: 819f2f74-7c10-409a-8e9e-38202df929e5
2024-04-12 17:13:23
[2024/04/12/[$LATEST]699c28b024c9837acfad81f139d73eb4]
REPORT RequestId: 819f2f74-7c10-409a-8e9e-38202df929e5 Duration: 12.34 ms Billed Duration: 13 ms Memory Size: 128 MB Max Memory Used: 128 MB
2024-04-12 17:16:40
[2024/04/12/[$LATEST]699c28b024c9837acfad81f139d73eb4]
START RequestId: e1c81b4a-dc58-41a0-9ecb-897b571b8094 Version: $LATEST
2024-04-12 17:16:40
[2024/04/12/[$LATEST]699c28b024c9837acfad81f139d73eb4]
END RequestId: e1c81b4a-dc58-41a0-9ecb-897b571b8094
2024-04-12 17:16:40
[2024/04/12/[$LATEST]699c28b024c9837acfad81f139d73eb4]
REPORT RequestId: e1c81b4a-dc58-41a0-9ecb-897b571b8094 Duration: 6.71 ms Billed Duration: 7 ms Memory Size: 128 MB Max Memory Used: 128 MB
And here is the information on my function's "Details" page:
Details for Lambda
MyFunction-0899f6ad
Function Name
arn:aws:lambda:us-east-1:000000000000:function:MyFunction-0899f6ad
Function Arn
arn:aws:iam::000000000000:role/MyFunction-17d12553
Role
600
Timeout
$LATEST
Version
cde72793-cf8e-48bb-a4c0-202ded2b0608
Revision Id
Active
State
Successful
Last Update Status
Zip
Package Type
x86_64
Architectures
Details for Lambda
http://s3.localhost.localstack.cloud:4566/awslambda-us-east-1-tasks/snapshots/000000000000/MyFunction-0899f6ad-66cdcb02-1278-47d2-8a0c-8bbc5ae22992?AWSAccessKeyId=949334387222&Signature=JkhKoBO9inXHkp%2FGAblHO5IuYSA%3D&Expires=1712961682
Location
dotnet8
Runtime
Integrations.Documentation.Auth.POC.Api
Handler
2601123
Code Size
RAUmZJbQhcqmGtscrTjO+d2n8HJ+IGd2DoqLhd55Ado=
Code Sha256
My Lambda function, which is created as an ASP.NET Core Minimal API and utilizing AddAWSLambdaHosting
, is defined in Program.cs
as follows (To protect my company, I have replaced org-identifying information with XXXX):
using Amazon.Runtime;
using Integrations.Documentation.Auth.POC.Lib.Services;
using Integrations.Documentation.Auth.POC.Lib.Util;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Mvc;
using XXXX.Utilities.Auth;
using XXXX.Utilities.Auth.AspNetCore;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.IdentityModel.Logging;
namespace Integrations.Documentation.Auth.POC.Api
{
public class Program
{
public static void Main(string[] args)
{
IConfigurationBuilder configBuilder = new ConfigurationBuilder().AddJsonFile("appsettings.Development.json", false, true);
IConfigurationRoot config = configBuilder.Build();
var profileName = config.GetSection("AWS").GetValue<string>("Profile") ?? "";
var builder = WebApplication.CreateSlimBuilder(args);
builder.WebHost.UseKestrelHttpsConfiguration();
builder.Services.AddAWSLambdaHosting(LambdaEventSource.HttpApi);
Action<PortalAuthOptions> configurePortalAuthOptions = options =>
{
config.GetSection(nameof(PortalAuthOptions)).Bind(options);
options.ApplicationName = Privileges.ApplicationName;
options.PrivilegeNamesType = typeof(Privileges);
};
Action<CookieAuthenticationOptions> overrideCookieOptions = options =>
{
options.ForwardChallenge = OpenIdConnectDefaults.AuthenticationScheme;
};
Action<OpenIdConnectOptions> overrideOidcOptions = options =>
{
options.RequireHttpsMetadata = false;
};
builder.Services.AddAWSCredentials(profileName);
builder.Services.AddAuthentication()
.AddPortalOpenIdConnect(
configurePortalAuthOptions,
overrideOidcOptions,
overrideCookieOptions);
builder.Services.AddAuthorizationBuilder()
.AddPolicy("Cookie", policy =>
{
policy.AddAuthenticationSchemes(
CookieAuthenticationDefaults.AuthenticationScheme)
.RequireAuthenticatedUser()
.Build();
});
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapGet("/dhtoken", async (
HttpRequest request,
[FromServices] AWSCredentials credentials,
[FromServices] ICurrentPortalUser user) =>
{
if (!user.HasPrivilege(Privileges.IntegrationDocAuth.Read))
{
//Send them to a page indicating that they don't have privileges:
return Results.Forbid();
}
var dhService = new DeveloperHubTokenService(credentials, config);
var resp = await dhService.GetSignedDeveloperHubToken("DeveloperHub-XXXX");
var dhUrl = $"https://xxxx.developerhub.io?jwt={resp}";
//Send user to dhUrl.
return Results.Redirect(dhUrl);
})
.RequireAuthorization("Cookie");
app.Run();
}
}
}
(I should mention that the above app works as expected on my machine when I run it in Visual Studio as a minimal API.)
Any ideas why I'm getting the errors that I'm seeing?
create-function-url-config
is anhttp
endpoint, when I call the endpoint while viewing the Developer Tools Network tab, it is doing a 404 temporary redirect to thehttps
version of the endpoint (which of course hasn't been configured in LocalStack). So I'm thinking that I either need to remove the code that causes the https redirect, or I need to (somehow) tell thecreate-function-url-config
command to create an https endpoint.--no-verify-ssl
which prevented the request from being redirected to anhttps
endpoint - but still I receive the same error.