frigate-hass-integration
frigate-hass-integration copied to clipboard
Support expiring unauthenticated access to the notifications proxy endpoint
Version of the custom_component
1.1.2
Configuration
N/A
Describe the bug
Not a bug per se. It seems the integration exposes an API through a proxy server that is then reachable through HOME_ASSISTANT_URL/api/frigate
However, if HOME_ASSISTANT_URL is reachable through the internet, it seems the frigate API becomes also reachable, along with event snapshots. It seems that the exposed URL does not piggyback on Home Assistant auth to protect these URLs.
Is there an out-of-the-box way to vend access to snapshots (e.g. for hassio automation notifications) securely? Is it possible to sign snapshot URLs and have the signature be valid only for a limited time?
Debug log
N/A
There are multiple views/proxies the integration uses to allow communication to the backend. Of those, (recordings & snapshots -- as referenced in the bug) are already authenticated. The only (effectively) unauthenticated API exposed is for notifications (ref).
That unauthenticated endpoint was added before my time on the project, so @blakeblackshear may be able to comment on the reasoning (likely related to making notifications simple). From https://github.com/blakeblackshear/frigate-hass-integration/issues/44 , which touches on this, you'd need to guess the random notification ID to actually have access to anything (akin to similarly being able to guess webhook endpoints).
Note that you can disable the unauthenticated notifications endpoint by choosing the appropriate option if this makes you uncomfortable:

Thank you Dermot,
My goal is to include a link to the clip in a notification, as well as the snapshot. I see three possible ways to achieve this
- Unauthenticated notification event proxy
- Auth through reverse proxy
- Signed paths
The unauthenticated event proxy would expose clips and snapshots to the internet. While it is true that it is hard to guess these urls, I would rather not rely on security through obscurity.
As #44 mentioned, one could setup a reverse proxy with auth, and I do have an nginx instance running, but I am not sure if that would actually work for my use case. To display the snapshot in the notification, the mobile OS (Android in my case) would have to be able to authenticate, which would likely be through a cookie check. Having it work reliably is not trivial unless I am missing something.
I think the easiest solution here would be to be able to pass Hassio signed paths as part of the notification. This would let the recipient of the notification display the snapshot correctly, as well as let them download/play the clip by tapping on the notification.
If there are better ways to achieve this, please let me know. Thank you!
Yes, I think you're right. Of your 3 options, (1) is how it is today, I suspect (2) could be a pain to make work without too much inconvenience, and (3) should be doable via HA access tokens -- the same as you can access a regular camera snapshot from HA, using the token= or entity_picture= attributes (those tokens expire after 5m, we could decide if we want to do likewise).
A good outcome here could be to make (3) work, then retire the unauthenticated endpoint and option entirely. I'll let Blake chime in in case I'm missing some reason why this needs to remain unauthenticated.
Another option I had thought of would be to only allow events within the last 5 minutes to proxy. Since the timestamp is in the event id, it would be easy to check.
I'm fine with option 3 as long as it doesn't make notifications difficult to implement. Is there a simple syntax in jinja for creating signed paths? I do think I saw somewhere that the homeassistant apps will create signed paths for relative urls in some cases automatically. I think the vast majority of users are fine with the entropy of having to guess a combination of the microsecond and an event id with 36^6 possible combinations.
Ideally, the URLs are signed so that only the notification recipient can access them; however, allowing access for a limited (configurable) amount of time based on the timestamp would be a good mitigation.
I'll kick the tires and see what the effort is to get either approach working, and submit a PR if/when it does. Thank you both!
I was able to prevent access for event ids that are older than 10 minutes – I will make this configurable before submitting a PR.
The signed URL change is quite a bit more involved, so I wanted to check with you folks if there's a smart way to do this, given I don't have experience with HASS development.
The links are sent out by the automation itself, so that's where we would sign them. However, I don't see a smart way to access the sign api from an automation. Also, since the automation is merely listening to a mqtt event sent directly by Frigate, there is no good place to sign the URLs before then.
What I thought of doing is to create a python script that would act as a service to sign these URLs, but again there doesn't seem to be a good way to return a value from a HASS service either.
Any ideas on how to simplify this?
Sorry, I don't know of a way to access signing from within an automations. I suspect you'll only be able to do that from Javascript or Python, but you could try asking on the HA discord in case someone there has a better idea (e.g. if the companion app will sign URLs it might be ideal as it's signing after receipt but before usage).
If you can't find anything else, one (non-trivial) way around this could be to listen to the frigate/events topic in the integration, and fire Home Assistant events that include URLs the integration would sign. This has the slight advantage that it wouldn't break any existing notifications -- new users (or users who care about more complete security) could write automations against those HA events instead of direct from the MQTT topic, and you could provide an option to disable non-signed calls to the notification endpoint. Depending on the volume of events, this could yield a substantial amount of wasted signing, though. Alternatively it could 'proxy' the MQTT events on 'frigate/events_signed' ... but unclear if either of these options is really worth all the extra complexity that would involve in the codebase.
@gmrandom FYI: In order to implement https://github.com/dermotduffy/frigate-hass-card/issues/147 right now I am planning to use this same NotificationView in HomeAssistant on arbitrary (incl. old) media. My requests are always signed. As such, if you do implement a PR for this, I'd appreciate if you could apply that 'prevention' only to unauthenticated requests.
(An alternative would be for me to add a separate authenticated view, though, although the above is simpler right now since the integration already supports it).
Thanks for the heads-up @dermotduffy I have been lagging with implementing this because of lack of time. I'll try to get to it within a week.
@gmrandom No worries at all, totally understand.
Posted a PR above. Hopefully the changes respect the general package design, otherwise let me know. I tried to stick to the codestyle as much as possible, but let me know if you want anything tweaked.
Apologies about the three PRs, my Git local setup was incorrect so I had to fix it and recreate the branches a couple times.