1

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?

4
  • Can you share your Lambda code for easy debugging? Apr 15 at 5:56
  • @HarshMishra I have added my Lambda code to the main body of my question just now.
    – CB_at_Sw
    Apr 15 at 15:01
  • One thing that I noticed is that, even though the URL generated by create-function-url-config is an http endpoint, when I call the endpoint while viewing the Developer Tools Network tab, it is doing a 404 temporary redirect to the https 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 the create-function-url-config command to create an https endpoint.
    – CB_at_Sw
    Apr 15 at 15:51
  • Disregard my last comment. I removed the function url config and re-ran the command with --no-verify-ssl which prevented the request from being redirected to an https endpoint - but still I receive the same error.
    – CB_at_Sw
    Apr 15 at 16:50

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.