Building a Secure API Gateway with Go, Gin, and Cloudflare Zero Trust
Introduction
In today’s world of micro services, managing multiple APIs securely and efficiently is a key challenge. API Gateways have become an essential component of modern infrastructure, acting as a reverse proxy to accept all application programming interface (API) calls, aggregate the various services required to fulfill them, and return the appropriate result.
In this tutorial, we'll explore how to build a secure API Gateway using the Gin framework in Go, authenticate requests with Cloudflare Zero Trust, and deploy the service to Google Cloud Run for a scalable, server less solution.
Why Gin?
Gin is a web framework written in Go that features a Martini-like API with much better performance. It provides easy-to-use routing and a vast ecosystem of middle ware. It’s perfect for building highly performance, reliable micro services and APIs.
Prerequisites
Before we dive in, ensure you have the following tools installed:
Go 1.23 or later
Git
A Google Cloud Platform (GCP) account
Cloudflare account with Zero Trust enabled
Step 1: Setting Up Your Go Environment
1. Install Go
Start by installing Go on your machine. Download it from the official Go website and follow the installation instructions. After installation, verify it by running:
go version
2. Set Up Your Go Workspace
Set up your Go workspace by adding the following lines to your shell configuration file (.bashrc
, .zshrc
, etc.):
export GOPATH=$HOME/go
export PATH=$PATH:$GOPATH/bin
3. Install Git
If you don’t have Git installed, get it from Git’s official site.
Step 2: Creating a Simple API Gateway with Gin
1. Initialize Your Project
Create a new directory for your project and initialize a Go module:
mkdir my-api-gateway
cd my-api-gateway
go mod init my-api-gateway
2. Install Gin
Add Gin to your project:
go get -u github.com/gin-gonic/gin
3. Write Your First API Gateway
Create a main.go
file and add the following code:
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
"github.com/joho/godotenv"
)
func main() {
// Load environment variables from .env file if it exists
err := godotenv.Load()
if err != nil {
log.Println("No .env file found, continuing without loading environment variables from file.")
}
// Set up Gin router with CORS
router := gin.Default()
router.Use(cors.New(cors.Config{
AllowOrigins: []string{"*"},
AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
AllowHeaders: []string{"Origin", "Authorization", "Content-Type"},
ExposeHeaders: []string{"Content-Length"},
AllowCredentials: true,
}))
// Example route
router.GET("/health", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"status": "API Gateway is up and running"})
})
// Start the server
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
router.Run(":" + port)
}
This basic API Gateway simply returns a health check response to ensure the gateway is running.
Step 3: Integrating Cloudflare Zero Trust
Cloudflare Zero Trust adds a layer of security by authenticating requests using Service Tokens. Here’s how you can integrate it:
1. Create a Cloudflare Zero Trust Service Token
Log in to your Cloudflare account, navigate to Access > Service Tokens, and create a new Service Token. Copy the Client ID and Client Secret for later use.
2. Modify the Gateway to Use Cloudflare Service Tokens
Update your main.go
to include Cloudflare authentication:
func main() {
// ... (previous setup)
requiredEnvVars := []string{"CF_ACCESS_CLIENT_ID", "CF_ACCESS_CLIENT_SECRET"}
for _, envVar := range requiredEnvVars {
if os.Getenv(envVar) == "" {
log.Fatalf("Environment variable %s is not set", envVar)
}
}
// Add a protected route
router.GET("/protected", func(c *gin.Context) {
token := fetchCloudflareToken(os.Getenv("CF_ACCESS_CLIENT_ID"), os.Getenv("CF_ACCESS_CLIENT_SECRET"))
if token == "" {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Access granted", "token": token})
})
// Start the server
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
router.Run(":" + port)
}
func fetchCloudflareToken(clientID, clientSecret string) string {
req, _ := http.NewRequest("GET", "https://example.cloudflareaccess.com", nil)
req.Header.Set("CF-Access-Client-Id", clientID)
req.Header.Set("CF-Access-Client-Secret", clientSecret)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil || resp.StatusCode != http.StatusOK {
return ""
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
return string(body)
}
This code adds a protected endpoint that checks for valid Cloudflare authentication.
Step 4: Deploying to Google Cloud Run
Google Cloud Run is a fully managed compute platform that automatically scales your stateless containers. Here’s how to deploy your API Gateway:
1. Set Up Google Cloud SDK
Install and configure the Google Cloud SDK on your machine.
2. Build and Push Your Docker Image
Create a Dockerfile for your Go application:
FROM golang:1.20 as builder
WORKDIR /app
COPY . .
RUN go build -o main .
FROM gcr.io/distroless/base-debian11
WORKDIR /
COPY --from=builder /app/main .
CMD ["./main"]
Then, build and push your Docker image to Google Container Registry (GCR):
gcloud auth configure-docker
docker build -t gcr.io/YOUR_PROJECT_ID/my-api-gateway .
docker push gcr.io/YOUR_PROJECT_ID/my-api-gateway
3. Deploy to Cloud Run
Finally, deploy your service to Cloud Run:
gcloud run deploy my-api-gateway \
--image gcr.io/YOUR_PROJECT_ID/my-api-gateway \
--platform managed \
--region YOUR_REGION \
--allow-unauthenticated
Best Practices for Cloud Run
Use Environment Variables: Securely manage secrets and configuration settings using environment variables in Cloud Run.
Enable Logging and Monitoring: Use Google Cloud's integrated logging and monitoring services to gain insights into your API Gateway’s performance.
Implement Caching: For performance, consider adding caching to reduce load times for frequently accessed resources.
Conclusion
In this guide, we built a secure API Gateway using Go and the Gin framework, integrated it with Cloudflare Zero Trust for authentication, and deployed it on Google Cloud Run. This setup offers a scalable, secure solution for managing access to your microservices.
Feel free to explore additional features, such as rate limiting, enhanced security configurations, or integrating with other Google Cloud services. By following these practices, you can build a robust, production-ready API Gateway that meets the demands of modern applications.
Subscribe to my newsletter
Read articles from Timothy Olaleke directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Timothy Olaleke
Timothy Olaleke
Tim is a software developer who builds awesome stuff, he has a wide experience in building customer-based solutions for digital needs using mind-blowing technologies. He is also a DevOps Enthusiast with a passion for automation and an open-source hobbyist, in his free time, he writes a lot of Google Cloud related tutorials and makes open contributions on GitHub. Tim is an active member of various developers communities, where he focuses on making impacts and sharing his experiences whilst learning.