Skip to content

Comments

feat(aws): add support for Lambda Function URLs#284

Open
Sharayu1418 wants to merge 2 commits intospcl:masterfrom
Sharayu1418:feature/lambda-function-urls
Open

feat(aws): add support for Lambda Function URLs#284
Sharayu1418 wants to merge 2 commits intospcl:masterfrom
Sharayu1418:feature/lambda-function-urls

Conversation

@Sharayu1418
Copy link

@Sharayu1418 Sharayu1418 commented Feb 19, 2026

Summary

  • Adds support for AWS Lambda Function URLs as an alternative to API Gateway for HTTP triggers
  • Function URLs provide a simpler alternative without the 29-second timeout limit of API Gateway
  • Keeps API Gateway as the default for backward compatibility

Changes

  • New FunctionURLTrigger class in sebs/aws/triggers.py - HTTP trigger implementation using Lambda Function URLs
  • New configuration options in sebs/aws/config.py:
    • use-function-url (bool, default: false) - Enable Function URLs instead of API Gateway
    • function-url-auth-type ("NONE" | "AWS_IAM", default: "NONE") - Authentication type
  • Function URL caching - Created URLs are cached similar to HTTP APIs
  • Cleanup support - Added delete_function_url() method for resource cleanup
  • Updated trigger creation in sebs/aws/aws.py to check config flag and create appropriate trigger type

Summary by CodeRabbit

  • New Features

    • Support for AWS Lambda Function URLs as an alternative HTTP trigger, including invoke (sync/async) and serialization for config.
    • Added ability to remove/delete Lambda Function URLs.
  • Configuration

    • New options to enable/disable Function URL usage and to set Function URL authentication (NONE or AWS_IAM).
    • Function URL entries are persisted and loaded from deployment configuration.

@coderabbitai
Copy link

coderabbitai bot commented Feb 19, 2026

📝 Walkthrough

Walkthrough

Adds support for AWS Lambda Function URLs: new configuration keys, config-side management of Function URLs, a FunctionURLTrigger implementation, integration into trigger deserialization, and AWS operations to create/delete Function URLs with conditional trigger creation.

Changes

Cohort / File(s) Summary
Configuration
config/example.json, sebs/aws/config.py
Added aws.resources keys: use-function-url, function-url-auth-type; introduced FunctionURLAuthType enum, AWSResources.FunctionURL type, serialization/deserialization, cache and runtime logic for creating/retrieving/deleting Function URLs.
AWS orchestration
sebs/aws/aws.py
Added AWS.delete_function_url(func_name: str) -> bool; updated create_trigger to conditionally create a FunctionURLTrigger (when enabled) or fall back to existing API Gateway HTTP trigger flow.
Triggers & Function integration
sebs/aws/triggers.py, sebs/aws/function.py
Added FunctionURLTrigger class (sync/async invoke, serialize/deserialize) and registered it in trigger deserialization mapping.
Minor/public API surface
(exports/imports) sebs/aws/function.py, sebs/aws/triggers.py
Updated public imports to expose the new FunctionURLTrigger and related types; adjusted trigger type mappings.

Sequence Diagrams

sequenceDiagram
    participant Client
    participant AWS
    participant AWSResources
    participant Lambda
    participant FunctionURL as "Function URL (HTTP)"

    Client->>AWS: create_trigger(function, http_config)
    AWS->>AWSResources: check use_function_url
    alt use_function_url = true
        AWSResources->>Lambda: ensure_function_url(function)
        Lambda-->>AWSResources: function_url (url, name, auth)
        AWS->>AWS: instantiate FunctionURLTrigger
        AWS-->>Client: return FunctionURLTrigger
        Client->>FunctionURL: HTTP invoke (sync/async)
        FunctionURL-->>Client: ExecutionResult
    else use_function_url = false
        AWS->>Lambda: create_api_gateway_trigger(function)
        Lambda-->>AWS: api_endpoint
        AWS-->>Client: return HTTPTrigger (API Gateway)
        Client->>API Gateway: HTTP invoke
        API Gateway->>Lambda: proxy invoke
        Lambda-->>Client: ExecutionResult
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I dug a tunnel through configs and code,
found URLs shining on a new road.
Hopped in triggers, permissions in tow,
Function URLs now set to go! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.09% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title 'feat(aws): add support for Lambda Function URLs' clearly and specifically describes the main change—adding Lambda Function URL support to the AWS module.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (2)
sebs/aws/config.py (1)

388-393: return True inside try block; consider else.

Per the TRY300 hint, moving return True (and the preceding cache-cleanup) to the else clause of the try/except improves clarity and makes it unambiguous that the positive path only runs when no exception was raised.

♻️ Proposed refactor
         try:
             lambda_client.delete_function_url_config(FunctionName=function_name)
             self.logging.info(f"Deleted Function URL for {function_name}")
 
             try:
                 lambda_client.remove_permission(
                     FunctionName=function_name,
                     StatementId="FunctionURLAllowPublicAccess",
                 )
             except lambda_client.exceptions.ResourceNotFoundException:
                 pass
 
             if function_name in self._function_urls:
                 del self._function_urls[function_name]
-
-            return True
         except lambda_client.exceptions.ResourceNotFoundException:
             self.logging.info(f"No Function URL found for {function_name}")
             return False
+        else:
+            return True
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@sebs/aws/config.py` around lines 388 - 393, The positive return and cache
cleanup currently occur inside the try block and should be moved into an else
clause so they only run when no exception is raised: after calling the AWS
operation that may raise lambda_client.exceptions.ResourceNotFoundException, put
the cache removal (del self._function_urls[function_name] if present) and the
return True inside an else: block tied to that try/except, leaving the except to
only log via self.logging.info(f"No Function URL found for {function_name}").
sebs/aws/triggers.py (1)

152-155: ThreadPoolExecutor created per async_invoke call is never shut down.

A new pool is allocated on each call with no pool.shutdown(), leaking threads until GC. This mirrors the pre-existing pattern in HTTPTrigger.async_invoke (lines 114–118). Consider sharing a single class-level executor or calling pool.shutdown(wait=False) after submitting:

♻️ Proposed fix
 def async_invoke(self, payload: dict) -> concurrent.futures.Future:
     pool = concurrent.futures.ThreadPoolExecutor()
     fut = pool.submit(self.sync_invoke, payload)
+    pool.shutdown(wait=False)
     return fut
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@sebs/aws/triggers.py` around lines 152 - 155, The async_invoke implementation
creates a new ThreadPoolExecutor on every call (in async_invoke) and never shuts
it down, leaking threads; change this to reuse a single executor (e.g., add a
class-level or instance attribute like _executor and initialize a
ThreadPoolExecutor once) and have async_invoke submit to that shared executor
(calling self.sync_invoke), or if you prefer per-call pools call
pool.shutdown(wait=False) after submitting; reference async_invoke, sync_invoke
and ThreadPoolExecutor (and mirror the fix used in HTTPTrigger.async_invoke) to
locate and update the code.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@sebs/aws/aws.py`:
- Around line 439-444: The delete_function_url method is never invoked, leaving
entries in the in-memory/on-disk _function_urls cache orphaned when
delete_function removes the Lambda on AWS; update delete_function to call
delete_function_url(func_name) after a successful AWS delete (or in its
cleanup/finally block) so the cache and on-disk state are removed (handle and
log any exceptions from delete_function_url and preserve the original
delete_function return semantics), referencing the existing delete_function and
delete_function_url methods and the _function_urls cache for where to apply the
change.

In `@sebs/aws/config.py`:
- Around line 464-469: The code directly sets ret._function_url_auth_type which
bypasses the property setter validation; change that line to use the property
setter (ret.function_url_auth_type = dct.get("function-url-auth-type", "NONE"))
so the value is validated (must be "NONE" or "AWS_IAM"); ensure the setter on
the class (function_url_auth_type property) enforces/raises on invalid values so
bad config entries are rejected instead of silently stored.
- Around line 349-357: Change the broad except Exception block around the
Function URL creation to catch specific, retryable errors (e.g.,
botocore.exceptions.ClientError or the specific boto3 error types) instead of
all exceptions, use self.logging.exception(...) to log the full traceback
(replace self.logging.error(e)), and when giving up raise a RuntimeError(...)
from e to preserve the original exception chain; also ensure non-retryable
exceptions are re-raised immediately rather than counted toward retries
(reference the retry loop surrounding the Function URL creation and the
variables retries, self.logging, and the raised RuntimeError).

In `@sebs/aws/triggers.py`:
- Around line 148-150: sync_invoke currently calls _http_invoke which always
posts unsigned HTTP requests, so Function URLs using AWS_IAM will 403; update
sync_invoke (or _http_invoke) to check self.auth_type and, for "AWS_IAM", sign
the HTTP request with AWS SigV4 (use botocore.auth.SigV4Auth via the existing
boto3/session credentials to add the required headers) before performing the
pycurl POST, or alternatively raise a clear exception for unsupported auth
types; reference sync_invoke, _http_invoke and the self.auth_type attribute when
making the change.

---

Nitpick comments:
In `@sebs/aws/config.py`:
- Around line 388-393: The positive return and cache cleanup currently occur
inside the try block and should be moved into an else clause so they only run
when no exception is raised: after calling the AWS operation that may raise
lambda_client.exceptions.ResourceNotFoundException, put the cache removal (del
self._function_urls[function_name] if present) and the return True inside an
else: block tied to that try/except, leaving the except to only log via
self.logging.info(f"No Function URL found for {function_name}").

In `@sebs/aws/triggers.py`:
- Around line 152-155: The async_invoke implementation creates a new
ThreadPoolExecutor on every call (in async_invoke) and never shuts it down,
leaking threads; change this to reuse a single executor (e.g., add a class-level
or instance attribute like _executor and initialize a ThreadPoolExecutor once)
and have async_invoke submit to that shared executor (calling self.sync_invoke),
or if you prefer per-call pools call pool.shutdown(wait=False) after submitting;
reference async_invoke, sync_invoke and ThreadPoolExecutor (and mirror the fix
used in HTTPTrigger.async_invoke) to locate and update the code.

Comment on lines +439 to +444
def delete_function_url(self, func_name: str) -> bool:
"""
Delete the Function URL associated with a Lambda function.
Returns True if deleted successfully, False if it didn't exist.
"""
return self.config.resources.delete_function_url(func_name, self.session)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

rg -n --type=py "delete_function_url" -C3

Repository: spcl/serverless-benchmarks

Length of output: 1532


🏁 Script executed:

rg -n --type=py "\.delete_function_url\("

Repository: spcl/serverless-benchmarks

Length of output: 171


🏁 Script executed:

rg -n --type=py "def delete_function" -A15 sebs/aws/aws.py

Repository: spcl/serverless-benchmarks

Length of output: 1035


🏁 Script executed:

sed -n '365,390p' sebs/aws/config.py

Repository: spcl/serverless-benchmarks

Length of output: 1037


Integrate delete_function_url into the delete_function cleanup flow.

The method is well-implemented with proper cache cleanup (del self._function_urls[function_name]), but it has no callers in the codebase. When delete_function is called at line 432, it only invokes the AWS API but never calls delete_function_url, leaving the in-memory and on-disk _function_urls cache entry orphaned. This causes stale cache lookups in subsequent runs. Either invoke delete_function_url from delete_function, or document that cache cleanup must be called separately.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@sebs/aws/aws.py` around lines 439 - 444, The delete_function_url method is
never invoked, leaving entries in the in-memory/on-disk _function_urls cache
orphaned when delete_function removes the Lambda on AWS; update delete_function
to call delete_function_url(func_name) after a successful AWS delete (or in its
cleanup/finally block) so the cache and on-disk state are removed (handle and
log any exceptions from delete_function_url and preserve the original
delete_function return semantics), referencing the existing delete_function and
delete_function_url methods and the _function_urls cache for where to apply the
change.

return self._function_name

@property
def auth_type(self) -> str:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are the available authentication types? "None" and "IAM"? Is there any other alternative?

I think it would be cleaner with a string-based enum instead of a plain string :) This will also make it easier to create asserts (see other comments) and implement if conditions.


@function_url_auth_type.setter
def function_url_auth_type(self, value: str):
if value not in ("NONE", "AWS_IAM"):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, but please use Enums here.

return cached_url

lambda_client = boto3_session.client(
service_name="lambda", region_name=cast(str, self._region)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the cast necessary here? Shouldn't _region be a string?


if auth_type == "NONE":
try:
lambda_client.add_permission(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use logging to print a warning here - function now has unrestricted public access. Users should be aware of that.

FunctionUrlAuthType="NONE",
)
except lambda_client.exceptions.ResourceConflictException:
pass
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When does this exception happen - if we try to add a permissions to the function that already exists? That should be safe but can we add a comment explaining this to make it clear it is safe to ignore this exception

retries = 0
while retries < 5:
try:
response = lambda_client.create_function_url_config(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't get the logic of this code and there's no comment explaining it:
(1) When can the ResourceConflictException happen if we previously had ResourceNotFoundException?
(2) What other exceptions can happen that force us to repeat? IIRC, boto3 typically creates specific exception types that describe situations, e.g., another resource update is pending or too many requests. We should capture them explicitly to not blindly repeat loop iterations, when the error type indicates that all future requests to create function URLs will also fail.

self.logging.error(e)
raise RuntimeError("Failed to create Function URL!")
else:
self.logging.info("Function URL creation failed, retrying...")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please inform user of the increasing sleep time (linear back-off).

self.logging.info(f"Deleted Function URL for {function_name}")

try:
lambda_client.remove_permission(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be conditional on the authentication type?

@mcopik
Copy link
Collaborator

mcopik commented Feb 19, 2026

@Sharayu1418 Thank you for the contribution, it is much appreciated! I left few comments :)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (5)
sebs/aws/config.py (3)

31-37: raise in except block should chain the original error.

The raise ValueError(...) inside the except ValueError discards the original traceback. Use raise ... from to preserve it.

Proposed fix
         try:
             return FunctionURLAuthType(value)
         except ValueError:
-            raise ValueError(
+            raise ValueError(
                 f"Invalid auth type '{value}'. Must be one of: "
                 f"{[e.value for e in FunctionURLAuthType]}"
-            )
+            ) from None
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@sebs/aws/config.py` around lines 31 - 37, The except block in the
FunctionURLAuthType conversion swallows the original ValueError traceback;
modify the except in the function that calls FunctionURLAuthType (the try/except
handling the variable `value`) to re-raise the new ValueError using exception
chaining (i.e., `raise ValueError(...) from e`) so the original exception is
preserved; locate the try/except that returns FunctionURLAuthType(value) and
change the `raise ValueError(...)` to chain from the caught exception.

403-416: logging.exception(e) — the exception argument is redundant.

logging.exception already captures the active exception context automatically. Passing e causes the exception's str() to appear twice in the log (once as the message, once as the traceback). Pass a descriptive string instead.

Proposed fix
                     if retries == 5:
-                        self.logging.error("Failed to create Function URL after 5 retries!")
-                        self.logging.exception(e)
+                        self.logging.exception(
+                            "Failed to create Function URL after 5 retries!"
+                        )
                         raise RuntimeError("Failed to create Function URL!") from e
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@sebs/aws/config.py` around lines 403 - 416, The self.logging.exception call
is passing the exception object e redundantly; replace self.logging.exception(e)
with a descriptive message (e.g. self.logging.exception("Failed to create
Function URL after 5 retries")) or use self.logging.error("Failed to create
Function URL after 5 retries", exc_info=True) so the stacktrace is still logged;
update the block handling lambda_client.exceptions.TooManyRequestsException
where retries == 5 to log a clear message without passing the exception object.

356-360: Existing Function URL's auth type may silently differ from the configured auth type.

When a pre-existing Function URL is found via get_function_url_config, its AuthType is used as-is (line 360), even if self._function_url_auth_type is set differently. This is probably the correct behavior (respect what's deployed), but a warning when they diverge would help operators notice the mismatch.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@sebs/aws/config.py` around lines 356 - 360, When an existing Function URL is
discovered via lambda_client.get_function_url_config and you parse its auth type
with FunctionURLAuthType.from_string into auth_type, compare that auth_type to
the configured self._function_url_auth_type and emit a warning if they differ
(include func.name and both values in the message) so operators are notified of
the mismatch; update the block where response =
lambda_client.get_function_url_config(...) and auth_type is set to perform this
comparison and call self.logging.warning with clear context when they diverge.
sebs/aws/triggers.py (2)

164-168: New ThreadPoolExecutor created per invocation — pre-existing pattern, but shutdown is inconsistent with HTTPTrigger.

FunctionURLTrigger.async_invoke calls pool.shutdown(wait=False) on line 167, which is good practice to allow cleanup. However, HTTPTrigger.async_invoke (line 117) does not. Consider aligning both for consistency — either add shutdown to HTTPTrigger as well, or remove it here.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@sebs/aws/triggers.py` around lines 164 - 168, The async_invoke implementation
in FunctionURLTrigger calls pool.shutdown(wait=False) but
HTTPTrigger.async_invoke does not, causing inconsistency; update
HTTPTrigger.async_invoke to mirror FunctionURLTrigger by creating the
ThreadPoolExecutor, submitting self.sync_invoke (or the equivalent HTTP sync
method) and calling pool.shutdown(wait=False) after submit, or alternatively
remove the shutdown call from FunctionURLTrigger.async_invoke so both
implementations match — modify the HTTPTrigger.async_invoke or
FunctionURLTrigger.async_invoke (referencing the async_invoke methods and the
use of ThreadPoolExecutor and pool.shutdown) to make the behavior consistent
across triggers.

170-185: Align serialization key naming convention between HTTPTrigger and FunctionURLTrigger.

HTTPTrigger uses hyphens (api-id) while FunctionURLTrigger and AWSResources.FunctionURL both use underscores (function_name, auth_type). Additionally, AWSResources.serialize() uses hyphens for function URL keys (function-urls, use-function-url, function-url-auth-type), creating inconsistency between the parent class and nested FunctionURL serialization.

Change both FunctionURLTrigger.serialize()/deserialize() and AWSResources.FunctionURL.serialize()/deserialize() to use hyphens for consistency with the rest of the codebase.

Proposed changes

In sebs/aws/triggers.py:

     def serialize(self) -> dict:
         return {
             "type": "FunctionURL",
             "url": self.url,
-            "function_name": self.function_name,
-            "auth_type": self.auth_type.value,
+            "function-name": self.function_name,
+            "auth-type": self.auth_type.value,
         }

     `@staticmethod`
     def deserialize(obj: dict) -> Trigger:
-        auth_type_str = obj.get("auth_type", "NONE")
+        auth_type_str = obj.get("auth-type", "NONE")
         return FunctionURLTrigger(
             obj["url"],
-            obj["function_name"],
+            obj["function-name"],
             FunctionURLAuthType.from_string(auth_type_str),
         )

In sebs/aws/config.py, update AWSResources.FunctionURL.serialize()/deserialize() similarly.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@sebs/aws/triggers.py` around lines 170 - 185, The FunctionURLTrigger and
AWSResources.FunctionURL serializers/deserializers must use hyphenated keys to
match HTTPTrigger and AWSResources conventions: update
FunctionURLTrigger.serialize() to output keys "function-name" and "auth-type"
(instead of "function_name"/"auth_type") and change its deserialize() to read
those hyphenated keys and pass the value through
FunctionURLAuthType.from_string; likewise update
AWSResources.FunctionURL.serialize()/deserialize() to produce/consume
"function-name", "auth-type" and any function-URL list keys to use hyphens
(matching AWSResources.serialize() use of "function-urls", "use-function-url",
"function-url-auth-type"); ensure all renamed keys are consistently used across
both serialize and deserialize methods.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@sebs/aws/config.py`:
- Around line 344-349: The current NotImplementedError check for
FunctionURLAuthType.AWS_IAM runs only when creating a new URL and can be
bypassed for cached or externally-created URLs; move the AWS_IAM guard so it
executes after resolving the URL object (i.e. after function_url() returns its
value or after get_function_url_config() path) to ensure any returned URL with
auth_type == FunctionURLAuthType.AWS_IAM raises immediately; alternatively
ensure FunctionURLTrigger.sync_invoke contains the definitive guard, but if
keeping it here, inspect the resolved object’s auth_type and raise
NotImplementedError for AWS_IAM before returning the URL.

---

Nitpick comments:
In `@sebs/aws/config.py`:
- Around line 31-37: The except block in the FunctionURLAuthType conversion
swallows the original ValueError traceback; modify the except in the function
that calls FunctionURLAuthType (the try/except handling the variable `value`) to
re-raise the new ValueError using exception chaining (i.e., `raise
ValueError(...) from e`) so the original exception is preserved; locate the
try/except that returns FunctionURLAuthType(value) and change the `raise
ValueError(...)` to chain from the caught exception.
- Around line 403-416: The self.logging.exception call is passing the exception
object e redundantly; replace self.logging.exception(e) with a descriptive
message (e.g. self.logging.exception("Failed to create Function URL after 5
retries")) or use self.logging.error("Failed to create Function URL after 5
retries", exc_info=True) so the stacktrace is still logged; update the block
handling lambda_client.exceptions.TooManyRequestsException where retries == 5 to
log a clear message without passing the exception object.
- Around line 356-360: When an existing Function URL is discovered via
lambda_client.get_function_url_config and you parse its auth type with
FunctionURLAuthType.from_string into auth_type, compare that auth_type to the
configured self._function_url_auth_type and emit a warning if they differ
(include func.name and both values in the message) so operators are notified of
the mismatch; update the block where response =
lambda_client.get_function_url_config(...) and auth_type is set to perform this
comparison and call self.logging.warning with clear context when they diverge.

In `@sebs/aws/triggers.py`:
- Around line 164-168: The async_invoke implementation in FunctionURLTrigger
calls pool.shutdown(wait=False) but HTTPTrigger.async_invoke does not, causing
inconsistency; update HTTPTrigger.async_invoke to mirror FunctionURLTrigger by
creating the ThreadPoolExecutor, submitting self.sync_invoke (or the equivalent
HTTP sync method) and calling pool.shutdown(wait=False) after submit, or
alternatively remove the shutdown call from FunctionURLTrigger.async_invoke so
both implementations match — modify the HTTPTrigger.async_invoke or
FunctionURLTrigger.async_invoke (referencing the async_invoke methods and the
use of ThreadPoolExecutor and pool.shutdown) to make the behavior consistent
across triggers.
- Around line 170-185: The FunctionURLTrigger and AWSResources.FunctionURL
serializers/deserializers must use hyphenated keys to match HTTPTrigger and
AWSResources conventions: update FunctionURLTrigger.serialize() to output keys
"function-name" and "auth-type" (instead of "function_name"/"auth_type") and
change its deserialize() to read those hyphenated keys and pass the value
through FunctionURLAuthType.from_string; likewise update
AWSResources.FunctionURL.serialize()/deserialize() to produce/consume
"function-name", "auth-type" and any function-URL list keys to use hyphens
(matching AWSResources.serialize() use of "function-urls", "use-function-url",
"function-url-auth-type"); ensure all renamed keys are consistently used across
both serialize and deserialize methods.

Comment on lines +344 to +349
# Check for unsupported auth type before attempting to create
if self._function_url_auth_type == FunctionURLAuthType.AWS_IAM:
raise NotImplementedError(
"AWS_IAM authentication for Function URLs is not yet supported. "
"SigV4 request signing is required for AWS_IAM auth type. "
"Please use auth_type='NONE' or implement SigV4 signing."
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

AWS_IAM guard is only at creation time — a cached AWS_IAM URL will bypass this check.

If a Function URL with AWS_IAM auth was created outside this tool (or in a future version), function_url() returns it from the cache at line 340-342 or from the get_function_url_config path at lines 356-360 without ever hitting the NotImplementedError guard. The caller (and ultimately FunctionURLTrigger.sync_invoke) will fail later with an unsigned request producing a 403.

Consider moving the guard to after the URL object is resolved (or rely solely on the trigger-side guard in FunctionURLTrigger.sync_invoke, which already exists), rather than only blocking the creation path.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@sebs/aws/config.py` around lines 344 - 349, The current NotImplementedError
check for FunctionURLAuthType.AWS_IAM runs only when creating a new URL and can
be bypassed for cached or externally-created URLs; move the AWS_IAM guard so it
executes after resolving the URL object (i.e. after function_url() returns its
value or after get_function_url_config() path) to ensure any returned URL with
auth_type == FunctionURLAuthType.AWS_IAM raises immediately; alternatively
ensure FunctionURLTrigger.sync_invoke contains the definitive guard, but if
keeping it here, inspect the resolved object’s auth_type and raise
NotImplementedError for AWS_IAM before returning the URL.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants