このガイドに従って、今日Google Cloud Functionsを試しています: https://cloud.google.com/functions/docs/quickstart
HTTPトリガーを使用して関数を作成し、データストアに書き込む関数をトリガーするPOST要求を実行できました。
このHTTPエンドポイントを保護する方法があるかどうか疑問に思っていましたか?現在、どこでも/誰からでもリクエストを受け付けるようです。
グーグルで検索すると、ほとんどの結果がFirebaseでのセキュリティ保護について語っています。ただし、ここではFirebaseサービスを使用していません。
私のオプションは、それを開いて、誰もURLエンドポイントを知らないことを望んでいますか(隠蔽によるセキュリティ)、または関数自体に独自の認証チェックを実装しますか?
これをさらに調査し、@ rickaの回答からヒントを得て、Authorizationヘッダーアクセストークンの形式で渡されたJWTトークンを使用して、クラウド機能の認証チェックを実装することにしました。
Nodeでの実装は次のとおりです。
const client = jwksClient({
cache: true,
rateLimit: true,
jwksRequestsPerMinute: 5,
jwksUri: "https://<auth0-account>.auth0.com/.well-known/jwks.json"
});
function verifyToken(token, cb) {
let decodedToken;
try {
decodedToken = jwt.decode(token, {complete: true});
} catch (e) {
console.error(e);
cb(e);
return;
}
client.getSigningKey(decodedToken.header.kid, function (err, key) {
if (err) {
console.error(err);
cb(err);
return;
}
const signingKey = key.publicKey || key.rsaPublicKey;
jwt.verify(token, signingKey, function (err, decoded) {
if (err) {
console.error(err);
cb(err);
return
}
console.log(decoded);
cb(null, decoded);
});
});
}
function checkAuth (fn) {
return function (req, res) {
if (!req.headers || !req.headers.authorization) {
res.status(401).send('No authorization token found.');
return;
}
const parts = req.headers.authorization.split(' ');
if (parts.length != 2) {
res.status(401).send('Bad credential format.');
return;
}
const scheme = parts[0];
const credentials = parts[1];
if (!/^Bearer$/i.test(scheme)) {
res.status(401).send('Bad credential format.');
return;
}
verifyToken(credentials, function (err) {
if (err) {
res.status(401).send('Invalid token');
return;
}
fn(req, res);
});
};
}
jsonwebtoken
を使用してJWTトークンを検証し、jwks-rsa
は、公開鍵を取得します。 Auth0を使用しているので、jwks-rsa
は、公開鍵のリストにアクセスしてそれらを取得します。
checkAuth
関数は、クラウド関数を次のように保護するために使用できます。
exports.get = checkAuth(function (req, res) {
// do things safely here
});
この変更は、私のgithubリポジトリで https://github.com/tnguyen14/functions-datastore/commit/a6b32704f0b0a50cd719df8c1239f993ef74dab6 で確認できます。
JWT /アクセストークンは、さまざまな方法で取得できます。 Auth0の場合、APIドキュメントは https://auth0.com/docs/api/authentication#authorize-client にあります。
これが整ったら、次のような方法でクラウド機能をトリガーできます(httpトリガーで有効にしている場合)。
curl -X POST -H "Content-Type: application/json" \
-H "Authorization: Bearer access-token" \
-d '{"foo": "bar"}' \
"https://<cloud-function-endpoint>.cloudfunctions.net/get"
現在、Google Cloud Function HTTPエンドポイントを保護する方法は2つあるようです。
1)推測しにくい関数名を使用する(例:my-function-vrf55m6f5Dvkrerytf35)
2)関数自体内でパスワード/クレデンシャル/署名済みリクエストを確認します(ヘッダーまたはパラメーターを使用)
おそらく両方を行うのが最善です。
カスタム認証アルゴリズムを作成して、クライアントを検証できます。
アルゴリズムをチェックアウトします。 https://security.stackexchange.com/q/210085/22239
「それを開いたままにして、誰も知らないことを願ってはいけません」。独自のセキュリティチェックを実装することも、Google Function Authorizerモジュールを試すこともできます( https://www.npmjs.com/package/google-function-authorizer )。