Mastodon subscription/web push API never calls my endpoint - aws-lambda

I'm trying to get an AWS Lambda function to be invoked whenever a (bot) Mastodon account is mentioned. I've set up the lambda, API Gateway, and logging such that I can call my function manually:
curl -XPOST -i https://XXXXXX.execute-api.us-east-1.amazonaws.com/mention-hook -d '{"foo":"bar"}'
Each such (manual) call is logged in CloudWatch, and I can see the payload passed.
I've set up a mastodon account and added an application to it (with push permissions), and I'm able to call the api (by passing the application's access token in the header. I'm using Python to register my push hook:
r = requests.post(server + '/api/v1/push/subscription',
headers={'Authorization': 'Bearer {}'.format(token)},
data={'subscription[endpoint]': 'https://XXXXXX.execute-api.us-east-1.amazonaws.com/mention-hook',
'subscription[keys][p256dh]': pKey,
'subscription[keys][auth]': authKey,
'data[alerts][mention]': True,
'policy': 'all' })
and the response (as well as subsequent GETs to /api/v1/push/subscription) look good to me:
200
b'{"id":60703,"endpoint":"https://XXXXXX.execute-api.us-east-1.amazonaws.com/mention-hook","alerts":{"mention":true},"server_key":"[redacted]"}'
Mentioning this account does generate notifications in the web interface and within mobile clients (via their own proxies), but my lambda never gets called.
I've tried the different options for policy as well as all the different kinds of alerts. I've tried this with several different Mastodon servers (all of which successfully deliver pushes to the proxies for mobile clients). I've simply never seen any Mastodon server call my endpoint.

Related

API Gateway Proxy Integration. Return response of second lambda function

The premise is pretty simple.
The usual application flow is as follows:
API Gateway receives a request.
API Gateway triggers Lambda Function with parameters.
Lambda Function runs the logic.
The Lambda Function's response is automatically forwarded to API Gateway as the response to step 1 (Response to the Received API Request).
Here's the issue I'm having. I need to run two functions before returning the response to the received API request. I need the return statement from the second function in step 4 to be the response sent back
to the client.
Now there are more examples where this is necessary. In the future, we might need to run a few services (such as lambda > Lambda > PostgreSQL > API Response) before responding to the request.
Is there a way to receive a request from a client, then run a host of tasks, assemble the necessary data, then use this data as a response in the original API request? So far step-functions seemed a likely solution but I don't know if it can do this.
Until recently this would've been a pain with Step Functions but around re:invent time last year they announced the ability to orchestrate synchronous express workflows: https://aws.amazon.com/blogs/compute/new-synchronous-express-workflows-for-aws-step-functions/
IMO, this would be the best / easiest way to implement what you're looking for.

Ajax request to cloud run service that requires authentication

I'm having a CORS related issue with google cloud run on a service that
requires authentication.
If I try to execute a curl command through the cli, with a Bearer token,
everything works fine.
Unfortunately if I try to execute the same call through ajax in javascript,
I receive a 403.
const http = new XMLHttpRequest();
const url = 'https://my-app.run.app';
http.open("GET", url);
http.withCredentials = true;
http.setRequestHeader("authorization", 'Bearer ' + id_token);
http.send();
http.onreadystatechange = (e) => {
console.log(http.responseText)
}
The error in the cloud run logs is this :
The request was not authenticated. Either allow unauthenticated invocations or set the proper Authorization header. Read more at https://cloud.google.com/run/docs/securing/authenticating
The container is never hit.
The issue I'm seeing is that, as I'm making the call using ajax, in a web
browser. The web browser is making a pre flight request ( OPTIONS on the
url ) without sending the Authorization header ( which is an expected
behavior )
The problem seems to be that cloud run tries to authenticate the OPTIONS
request and never makes it to my container, which, as far as I understand,
shouldn't be done. (
https://www.w3.org/TR/cors/#cross-origin-request-with-preflight-0 )
Is that a known issue with cloud run ?
How could I make an ajax request to an authenticated cloud run service ?
(Cloud Run PM)
This is a known issue. There are a few options:
Allow unauthenticated requests and do CORS/auth yourself
There is a variation of this that uses Cloud Endpoints running on Cloud Run in front of your compute. Have Endpoints do your end-user auth, then forward the request to your backend.
Serve from the same domain (e.g. use the Firebase Hosting proxy)
We've considered implementing Istio CORSPolicy, which would return CORS headers before the auth check, though we're not committed to this as of now.

API Gateway WebSocket API postConnection timeout

I'm trying to set up a WebSocket API on API Gateway. I'm following the basic tutorial, and I have everything up and running -> Routes for $connect, $disconnect, "test", $default. I am able to connect to the API, store the connectionId in Redis, and retrieve it when accessing from the test route.
The problem is when I try to send back a message from my lambda (single lambda handling all routes). I'm using the following code
const apigwManagementApi = new AWS.ApiGatewayManagementApi({
apiVersion: '2018-11-29',
endpoint: `https://${event.requestContext.domainName}/${event.requestContext.stage}`
});
Then I call
await apigwManagementApi.postToConnection({
ConnectionId: connectionId,
Data: `Echo: ${data}`
}).promise()
This is only called on the "test" route.
All of this is as per their guide. I had to add a patch to be able to make postConnection work, again, as per their tutorial. The problem is when the above method is called I get a Internal Server Error message from the API Gateway and the lambda times out after 3 seconds.
There is very little info on this method. I'm not sure what is causing the internal server error. I have checked the endpoint and the connectionId, both are correct.
What am I doing wrong? Any suggestions?
So the problem wasn't the actual lambda but the fact that it wasn't set up in a VPC that had access to the Internet. So if you're lambda has VPC enabled, make sure you it has a NAT gateway and Internet gateway set up.

How to check Global HTTP batch endpoint is called

I received an email saying that JSON-RPC and Global HTTP Batch serving endpoints being discontinued, and that my project on Google Cloud Platform is calling Global HTTP Batch endpoint.
When I check the API dashboard of the project, however, "Google Cloud Storage JSON API" shows no usage for the last 30 days.
Does that mean the project no longer calls this endpoint?
If not (= if there is still a chance that we call this endpoint), how can I see whether a change that I will make to eliminate the call does actually eliminate the call?
If you are using a client from Google to make your request you are no longer calling the Global HTTP Batch endpoint as they have been updated to use the new API specific Batch endpoint.
You can still use the dev tools from your browser to check the request url from your app.

Create function in Parse Cloud Code that does not require authorisation

I have my own instance of Parse Server running on AWS and until now Cloud Functions have been working great, but with one caveat: they cannot be successfully called publicly, i.e. they require an authorisation key be sent in the REST request header.
I want to set up a Slack Slash Command to my server, and it has to be able to POST a payload without any headers or extra parameters. As a result, my requests are currently unauthorised (returning 403 statuses).
Is there a way to create granular control over a Parse Cloud Function's authorisation (i.e. if it requires master-key header or not), and if not — is there a way of forwarding the request but still through the Parse server?—Or even a way of manipulating the headers of a Slack request? I would rather not have to use another service just for request forwarding.
Thanks!
Two options
Pass in the master key on the client request which should bypass authorization. It's a blunt approach but might be okay in your case (without knowing more details).
Or run a new express endpoint alongside parse and from there call the parse cloud function using the masker key.
var api = new ParseServer(...)
var app = express();
app.use('/parse', api);
app.get('/api/slack', function(req, res) {
//call cloud function passing in master key
// add X-Parse-Master-Key as http header
unirest.post("http://myhost.com:1337/parse/functions/mycloudfunction")
.headers({'X-Parse-Master-Key', MASTER_KEY)
.end(function(response) {
}

Resources