I wanted to add security to my Cloud Function so I removed the allUsers
access to call it - so I could instead only call it from a service account within my GCP.
So I have followed the tutorial in the GCP docs exactly:
Cloud Function
async function createTask(taskName, functionToFire, payload, fireAt){
const tasksClient = new CloudTasksClient()
const projectId = JSON.parse(process.env.FIREBASE_CONFIG).projectId
console.log(`${taskName} will fire ${functionToFire} at ${fireAt}...`)
const location = 'us-central1'
const queuePath = tasksClient.queuePath(projectId, location, taskName)
const url = `https://us-central1-${PROJECT_ID}.cloudfunctions.net/task/${functionToFire}`
const serviceAccountEmail = 'cloud-tasks@${PROJECT_ID}.iam.gserviceaccount.com';
// const sendAt = Date.now() / 1000 + 10 // plus 10 seconds of current epoch
const task = {
httpRequest: {
httpMethod: 'POST',
url,
oidcToken: {
serviceAccountEmail
},
body: Buffer.from(JSON.stringify(payload)).toString('base64'),
headers: {
'Content-Type': 'application/json',
},
},
scheduleTime: {
seconds: (fireAt / 1000) // Convert millis to seconds
}
}
await tasksClient.createTask({ parent: queuePath, task })
return 200;
}
Cloud Function permissions
The service account has been given the following permissions on this specific function called task
:
However when the task actually fires, it gives this error:
PERMISSION_DENIED(7): HTTP status code 403
i've also had the following error:
UNAUTHENTICATED(16): HTTP status code 401
I've tested using 2 service accounts - the recommended one using the docs (shown above) and also a service account I created specifically for this called cloud-tasks@${PROJECT_ID}.iam.gserviceaccount.com
.
I also went to the generic IAM page and checked the permissions of these service accounts:
Both return the PERMISSION_DENIED
or UNAUTHENTICATED
errors shown above when the function fires:
Any idea what the problem is? I've tried almost everything.
You forgot to put the audience in your OIDC token definition. You can find the object definition in the nodeJS documentation
...
...
const task = {
httpRequest: {
httpMethod: 'POST',
url,
oidcToken: {
serviceAccountEmail: serviceAccountEmail
//Audience is the raw URL, without extra path or query parameter
audience: https://us-central1-${PROJECT_ID}.cloudfunctions.net/task },
...
...