Is there a way to create firewall rules for my Google Cloud Functions HTTP endpoints?

血红的双手。 提交于 2019-12-19 04:21:07

问题


Just wanted to check if this is in the roadmap of already available and I have just missed these. While building my Functions for an important project, I want to apply some firewall rules to limit network access for some of my Google Cloud Functions (HTTP endpoint triggers) because of reasons that are manifold (security, avoid high price if sudden charge caused by spammy requests, etc.)

Is this available or in the pipeline? If not, how would you limit access to a particular function to only allow a few Google Compute Engines, other GCF, and other Google Cloud Services (Firestore, Storage, PubSub.)


回答1:


More than firewall rules what you should be looking at is to authenticate your requests to your Cloud Functions with Access Tokens.

Here there is a good example on how to do this.

Basically you will be creating an HTTP triggered Cloud Function.

First create a bucket, mine is called auth-123 .Then drop to a Cloud shell and define the project name and the bucket as environment variables:

jordim@yrmv-191108:~$ export BUCKET=auth-123
jordim@yrmv-191108:~$ export PROJECT=yrmv-191108

Create a couple of service accounts

jordim@yrmv-191108:~$ gcloud iam service-accounts create alpha-account --
display-name "Account 1"
jordim@yrmv-191108:~$ gcloud iam service-accounts create beta-account --display-name "Account 2"
Created service account [beta-account].

Now to create the function! On a folder on your cloud shell create first a package.json with the dependencies:

jordim@yrmv-191108:~/cloudfunction$ cat > package.json
{
  "dependencies": {
    "googleapis": "21.2"
  }
}

And now the function itself:

const Google = require('googleapis');
const BUCKET = 'auth-123'; // Replace with name of your bucket

/**
 * Cloud Function.
 *
 * @param {Object} req Cloud Function request context.
 * @param {Object} res Cloud Function response context.
 */
exports.secureFunction = function secureFunction(req, res) {
    var accessToken = getAccessToken(req.get('Authorization'));
    var oauth = new Google.auth.OAuth2();
    oauth.setCredentials({access_token: accessToken});

    var permission = 'storage.buckets.get';
    var gcs = Google.storage('v1');
    gcs.buckets.testIamPermissions(
        {bucket: BUCKET, permissions: [permission], auth: oauth}, {},
        function (err, response) {
            if (response && response['permissions'] && response['permissions'].includes(permission)) {
                authorized(res);
            } else {
                res.status(403).send("The request is forbidden.");
            }
        });



function authorized(res) {
            res.send("The request was successfully authorized.");
            // The code to execute goes here! :)
}
}


function getAccessToken(header) {
    if (header) {
        var match = header.match(/^Bearer\s+([^\s]+)$/); //We are looking for an HTTP request with the content Bearer: + a token
        if (match) {
            return match[1];
        }
    }

    return null;
}

In this case we are checking that the account launching the request has the permission storage.buckets.get, but it can be changed to any other just by changing the the variable permission.

Then you deploy the function:

jordim@yrmv-191108:~/cloudfunction$ gcloud beta  functions deploy secureFunction --stage-bucket $BUCKET --trigger-http

Now you have a cloud function that only triggers its content if it receives a request from an authorized account. Let's make tokens for the accounts we created before:

   jordim@yrmv-191108:~/cloudfunction$ gcloud iam service-accounts keys create --iam-account alpha-account@$PROJECT.iam.gserviceaccount.com ./alpha-account.json
    jordim@yrmv-191108:~/cloudfunction$ export ALPHA_ACCOUNT_TOKEN=$(GOOGLE_APPLICATION_CREDENTIALS=./alpha-account.json gcloud auth application-default print-access-token)


jordim@yrmv-191108:~/cloudfunction$ gcloud iam service-accounts keys create --iam-account beta-account@$PROJECT.iam.gserviceaccount.com ./beta-account.json
created key [4a9251d7611e74da8b4565657b52b7c940606630] of type [json] as [./beta-account.json] for [beta-account@yrmv-191108.iam.gserviceaccount.com]
jordim@yrmv-191108:~/cloudfunction$ export BETA_ACCOUNT_TOKEN=$(GOOGLE_APPLICATION_CREDENTIALS=./beta-account.json gcloud auth application-default print-access-token)

We have the auth tokens on a json now and also exported them as an env var for easy testing. Let's give permission to ALPHA user and not give it to BETA user:

jordim@yrmv-191108:~/cloudfunction$ gsutil acl ch -u alpha-account@$PROJECT.iam.gserviceaccount.com:R gs://auth-123

And now to test:

jordim@yrmv-191108:~/cloudfunction$ curl https://us-central1-yrmv-191108.cloudfunctions.net/secureFunction -H "Authorization: Bearer $ALPHA_ACCOUNT_TOKEN"
The request was successfully authorized.

jordim@yrmv-191108:~/cloudfunction$ curl https://us-central1-yrmv-191108.cloudfunctions.net/secureFunction -H "Authorization: Bearer $BETA_ACCOUNT_TOKEN"
The request is forbidden

You can apply this logic to any of your cloud functions, and unless the request comes with a valid token on its header the amount of resources used for rejecting it is minimal.



来源:https://stackoverflow.com/questions/48182967/is-there-a-way-to-create-firewall-rules-for-my-google-cloud-functions-http-endpo

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!