[GCP] Cloud Functions HTTPS Trigger is NOT SECURE!

Visarut Junsone
Lazy-Dev
Published in
3 min readDec 20, 2023

ในบทความนี้จะไม่ได้สอนการตั้ง Cloud Functions แต่เป็นการพูดถึงการ ตั้ง Cloud Functions ที่ถูก Trigger ด้วย HTTPS ให้มีความปลอดภัยยิ่งขึ้น

Intro

ในช่วงเวลาที่ผ่านมาตัวผมเองได้มีโอกาสศึกษาและทำ Line Bot ที่เกี่ยวข้องกับการใช้ Messaging API ของทาง Line ซึ่งจากตัวอย่างมากมายในโลก Internet จะมีส่วนที่สอนทำ Tutorial โดยใช้ Cloud Functions ที่ Trigger ด้วย HTTPs เพราะ Cloud Functions นั้นเหมาะสำหรับการทำ Event-trigger

ซึ่งหลังจากสร้าง Cloud Functions เราจะได้ URL มาเพื่อใช้งาน แต่…..

คุณรู้หรือไม่ว่าคุณควร Setup บางอย่างเพื่อเพิ่มความ Secure

ไม่เช่นนั้นแล้ว URL ที่คุณได้มาเป็นจะ public ทำให้ใครสามารถเอาไปใช้ก็ได้และค่า Cost server พุ่งสูงลิ่วววววววววววววววววววว

ดังนั้นวันนี้เราจะมาพูดถึงวิธีเพิ่มความปลอดภัยให้ Cloud Functions กัน มีดังนี้

API Key, OAuth และ VPC

แต่จะขอพูดแค่ API Key เพราะส่วนที่เหลือยังไม่ได้ลองทำเองหน่ะสิ้

แรกเริ่มไม่ว่าเราจะทำวิธีไหน ควรที่จะทำ URL ของ Cloud Functions เราให้เป็น private ซะก่อน ซึ่งมี 2 วิธีที่ได้ลองทำมา

ตั้ง Server config ด้วย Code ทำได้โดยการใช้ RuntimeOptions พร้อมกับ คำสั่ง runwith

// This is just a Psudo-code Try to modified it with yourself.

import {RuntimeOptions, runWith} from "firebase-functions";

const serverConfig: RuntimeOptions = {
memory: "128MB",
timeoutSeconds: 60,
minInstances: 0,
maxInstances: 10,
invoker: "private", // <= will automatic create function with require authen.
};

exports.myPrivateFunctions = runWith(serverConfig).https.onRequest((req, res) => {
return "HELLO Lazydev";
});

ตั้งที่หน้า Create Functions ที่ Google Cloud Platform

หลังจากที่ทำการตั้งค่า Cloud Functions ของเราให้เป็น private หรือ ให้ require authentication แล้ว สิ่งที่ต้องทำต่อไปคือการเรียกใช้ Cloud Functions ดังกล่าวด้วย Authen ที่เรากำหนด

Protect with API Key

สิ่งที่ต้องรู้กับการตั้งค่าความปลอดภัยของ Cloud Functions ด้วย API Key มีดังนี้

  1. APIs Gateway
  2. APIs & Service และ Credential

ใช่แล้วครับทุกคน API Key ที่พูดถึงก็คือ Credential ใน APIs & Service นั้นเอง

จากที่ทุกคนอ่านตามมาจากด้านบนนั้น สิ่งที่เราขาดตอนนี้คือ API Gateway นั้นเอง ซึ่งกดสร้างง่ายมากๆ แค่ กด Create Gateway แล้วกรอกข้อมูลต่างๆ

แต่ส่วนที่น่าสนใจที่น่าพูดถึงในการกรอกข้อมูลตรงนั้น มีอยู่ 2 ส่วน

  1. Service Account
    แนะนำให้สร้าง Service Account ที่ allow ให้ Invoke ได้แค่ Cloud Functions เท่านั้น
  2. API Config => API Spec ซึ่งจะแสดงตัวอย่างดังรูปด้านล่าง
swagger: '2.0'
info:
title: <Your_title>
description: Lazy dev portfolio chat bot
version: 1.0.0
schemes:
- https
produces:
- application/json
securityDefinitions:
api_key:
type: apiKey
name: key
in: query
paths:
/api_gateway_path:
post:
summary: this is your summary
consumes:
- application/json
operationId: api_gateway_path
x-google-backend:
address: <Your_Cloud_Functions_URL>
security:
- api_key: []
responses:
'200':
description: Successful response
schema:
type: string

ใน yaml ไฟล์ config นี้ ส่วนที่สำคัญที่ต้องพูดถึงคือ securityDefinitions

securityDefinitions เป็นส่วนที่กำหนดว่าเราจะใช้ Key ในการ Authen ให้กับ API Gateway ซึ่ง name: key นั้นหมายถึง ชื่อตัวแปรของเรา และ in:query เป็นการบอกว่า key ของเราจะเอามาจาก query param

https://<api-gateway-url>?key=<some_value>

หาก in: header นั้นหมายถึง เราจะต้องแนบ key ไปใน header ของ request

อดทนไว้ใกล้จบแล้ว

หลังจากที่คุณสร้าง gateway เสร็จแล้ว คุณสามารถนำชื่อ title ของ config ที่เพิ่งกล่าวไปข้างต้น นำไปหาใน API Library แล้ว กด Enabled มันซะ

ในรูปที่ พาดสีแดง ชื่อจะตรงกับ <Your_title> ใน yaml ไฟล์ที่กล่าวข้างต้น

หลังจากนั้นคุณจะสามารถไปสร้าง key ใน credential ของ Api ที่เราเพิ่งจะ Enabled ใช้งาน เท่านี้ ก็จะสามารถใช้ key ในเป็นตัว authen ได้แล้วว

ในบทความนี้อาจจะไม่ได้อธิบายบางอย่าง อย่างละเอียด ซึ่งอาจจะทำให้มือใหม่ที่ไม่รู้จัก GCP งง อยู่เล็กน้อย แต่คนที่พอจะคุ้นเคยกับหน้าตาของมันบ้างก็คงจะทำตามได้อย่างไม่ยากนัก

และไม่ต้องกลัว คุณผูกบัตรเครดิตแล้วเปิด billing GCP ลองทำตามได้เลย สุดท้ายแล้ว service ที่คุณเปิดใช้งานอยู่แทบจะไม่เสียเงินเลยด้วยซ้ำ ถ้าคุณไม่ได้เปิดใช้ public (แต่อย่าลืมตั้ง private และ เก็บ ลบ อะไรต่างๆ ที่ไม่ใช่ดีๆนะครับ เดี๋ยวโดนชาร์จเงิน)

--

--

Visarut Junsone
Lazy-Dev

I’m Full-Stack Developer. ReactJS Golang C# Javascript C++ PHP and learning a lot more. Not lazy as it name. “Lazy-Dev”