feat(Makefile): introduce admin console deployment to Cloud Run with IAP
feat(Makefile): add IAP configuration management for both launchpad and admin feat(Makefile): refactor IAP user management commands for reusability feat(Makefile): add Dockerfile for admin-web to containerize the application feat(Makefile): remove App Engine deployment targets for admin-web This commit introduces significant changes to the deployment process for the admin console, migrating it from App Engine to Cloud Run and integrating Identity-Aware Proxy (IAP) for enhanced security. The key changes include: - **Admin Console Deployment to Cloud Run:** The admin console is now deployed to Cloud Run using a Dockerfile that builds and containerizes the application. This provides a more scalable and flexible deployment environment. - **IAP Integration:** IAP is now enabled for the admin console, restricting access to authorized users only. This enhances the security of the application and protects sensitive data. - **IAP Configuration Management:** New commands have been added to the Makefile to manage IAP configuration for both the launchpad and admin console. These commands allow for easy addition and removal of IAP users. - **Refactored IAP User Management Commands:** The IAP user management commands have been refactored to be more reusable and generic. This allows for easier management of IAP users for both the launchpad and admin console. - **Removal of App Engine Deployment Targets:** The App Engine deployment targets for the admin console have been removed, as the application is now deployed to Cloud Run. These changes provide a more secure, scalable, and maintainable deployment process for the admin console.
This commit is contained in:
122
Makefile
122
Makefile
@@ -4,7 +4,7 @@
|
|||||||
# It is designed to be the main entry point for developers.
|
# It is designed to be the main entry point for developers.
|
||||||
|
|
||||||
# Use .PHONY to declare targets that are not files, to avoid conflicts.
|
# Use .PHONY to declare targets that are not files, to avoid conflicts.
|
||||||
.PHONY: help install dev build integrate-export prepare-export deploy-launchpad deploy-launchpad-full deploy-app admin-install admin-dev admin-build admin-deploy-dev admin-deploy-staging configure-iap-launchpad list-iap-users remove-iap-user setup-labels export-issues create-issues-from-file install-git-hooks
|
.PHONY: help install dev build integrate-export prepare-export deploy-launchpad deploy-launchpad-full deploy-app admin-install admin-dev admin-build deploy-admin deploy-admin-full configure-iap-launchpad configure-iap-admin list-iap-users remove-iap-user setup-labels export-issues create-issues-from-file install-git-hooks
|
||||||
|
|
||||||
# The default command to run if no target is specified (e.g., just 'make').
|
# The default command to run if no target is specified (e.g., just 'make').
|
||||||
.DEFAULT_GOAL := help
|
.DEFAULT_GOAL := help
|
||||||
@@ -19,8 +19,13 @@ CR_LAUNCHPAD_SERVICE_NAME := internal-launchpad
|
|||||||
CR_LAUNCHPAD_REGION := us-central1
|
CR_LAUNCHPAD_REGION := us-central1
|
||||||
CR_LAUNCHPAD_IMAGE_URI := us-docker.pkg.dev/$(GCP_DEV_PROJECT_ID)/gcr-io/$(CR_LAUNCHPAD_SERVICE_NAME)
|
CR_LAUNCHPAD_IMAGE_URI := us-docker.pkg.dev/$(GCP_DEV_PROJECT_ID)/gcr-io/$(CR_LAUNCHPAD_SERVICE_NAME)
|
||||||
|
|
||||||
|
CR_ADMIN_SERVICE_NAME := admin-console
|
||||||
|
CR_ADMIN_REGION := us-central1
|
||||||
|
CR_ADMIN_IMAGE_URI := us-docker.pkg.dev/$(GCP_PROJECT_ID)/gcr-io/$(CR_ADMIN_SERVICE_NAME)
|
||||||
|
|
||||||
# --- Environment Detection ---
|
# --- Environment Detection ---
|
||||||
ENV ?= dev
|
ENV ?= dev
|
||||||
|
SERVICE ?= launchpad # Default service for IAP commands: 'launchpad' or 'admin'
|
||||||
|
|
||||||
# --- Conditional Variables by Environment ---
|
# --- Conditional Variables by Environment ---
|
||||||
ifeq ($(ENV),staging)
|
ifeq ($(ENV),staging)
|
||||||
@@ -33,6 +38,18 @@ else
|
|||||||
HOSTING_TARGET := app-dev
|
HOSTING_TARGET := app-dev
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# --- Conditional Variables by Service for IAP commands ---
|
||||||
|
ifeq ($(SERVICE),admin)
|
||||||
|
IAP_SERVICE_NAME := $(CR_ADMIN_SERVICE_NAME)
|
||||||
|
IAP_SERVICE_REGION := $(CR_ADMIN_REGION)
|
||||||
|
IAP_PROJECT_ID := $(GCP_PROJECT_ID) # Admin console is env-specific
|
||||||
|
else
|
||||||
|
IAP_SERVICE_NAME := $(CR_LAUNCHPAD_SERVICE_NAME)
|
||||||
|
IAP_SERVICE_REGION := $(CR_LAUNCHPAD_REGION)
|
||||||
|
IAP_PROJECT_ID := $(GCP_DEV_PROJECT_ID) # Launchpad is dev-only
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
# Shows this help message.
|
# Shows this help message.
|
||||||
help:
|
help:
|
||||||
@echo "--------------------------------------------------"
|
@echo "--------------------------------------------------"
|
||||||
@@ -45,16 +62,13 @@ help:
|
|||||||
@echo " make build - Builds the web frontend for production."
|
@echo " make build - Builds the web frontend for production."
|
||||||
@echo ""
|
@echo ""
|
||||||
@echo " --- DEPLOYMENT ---"
|
@echo " --- DEPLOYMENT ---"
|
||||||
@echo " make deploy-launchpad - Deploys the internal launchpad to Cloud Run."
|
@echo " make deploy-launchpad-full - Deploys internal launchpad to Cloud Run (dev only) with IAP."
|
||||||
@echo " make deploy-launchpad-full - Deploys launchpad to Cloud Run & configures IAP."
|
@echo " make deploy-admin-full [ENV=staging] - Deploys Admin Console to Cloud Run with IAP (default: dev)."
|
||||||
@echo " make deploy-app [ENV=staging] - Builds and deploys the main web app (default: dev)."
|
@echo " make deploy-app [ENV=staging] - Builds and deploys the main web app via Firebase Hosting (default: dev)."
|
||||||
@echo " make admin-deploy-dev - Builds and deploys the admin web app to the DEV environment (App Engine)."
|
|
||||||
@echo " make admin-deploy-staging - Builds and deploys the admin web app to the STAGING environment (App Engine)."
|
|
||||||
@echo ""
|
@echo ""
|
||||||
@echo " --- CLOUD IAP (for Cloud Run Launchpad) ---"
|
@echo " --- CLOUD IAP MANAGEMENT ---"
|
||||||
@echo " make configure-iap-launchpad - Adds users from iap-users.txt as IAP-secured Web App Users and grants IAP Service Account Cloud Run Invoker role."
|
@echo " make list-iap-users [SERVICE=admin] - Lists IAP users for a service (default: launchpad)."
|
||||||
@echo " make list-iap-users - Lists all users with IAP-secured Web App User role."
|
@echo " make remove-iap-user USER=... [SERVICE=admin] - Removes an IAP user from a service."
|
||||||
@echo " make remove-iap-user USER=user:email@example.com - Removes the IAP-secured Web App User role from a user."
|
|
||||||
@echo ""
|
@echo ""
|
||||||
@echo " --- PROJECT MANAGEMENT & TOOLS ---"
|
@echo " --- PROJECT MANAGEMENT & TOOLS ---"
|
||||||
@echo " make setup-labels - Creates/updates GitHub labels from labels.yml."
|
@echo " make setup-labels - Creates/updates GitHub labels from labels.yml."
|
||||||
@@ -125,19 +139,33 @@ admin-build:
|
|||||||
@echo "--> Building admin console for production..."
|
@echo "--> Building admin console for production..."
|
||||||
@cd admin-web && VITE_APP_ENV=$(ENV) npm run build
|
@cd admin-web && VITE_APP_ENV=$(ENV) npm run build
|
||||||
|
|
||||||
admin-deploy-dev: admin-build
|
deploy-admin: admin-build
|
||||||
@echo "--> Deploying Admin Web App to DEV environment (App Engine)..."
|
@echo "--> Building and deploying Admin Console to Cloud Run [$(ENV)]..."
|
||||||
@cd admin-web && gcloud app deploy app.dev.yaml --project=$(GCP_DEV_PROJECT_ID)
|
@echo " - Step 1: Building container image..."
|
||||||
|
@cd admin-web && gcloud builds submit \
|
||||||
|
--tag $(CR_ADMIN_IMAGE_URI) \
|
||||||
|
--project=$(GCP_PROJECT_ID)
|
||||||
|
@echo " - Step 2: Deploying to Cloud Run..."
|
||||||
|
@gcloud run deploy $(CR_ADMIN_SERVICE_NAME) \
|
||||||
|
--image $(CR_ADMIN_IMAGE_URI) \
|
||||||
|
--platform managed \
|
||||||
|
--region $(CR_ADMIN_REGION) \
|
||||||
|
--no-allow-unauthenticated \
|
||||||
|
--project=$(GCP_PROJECT_ID)
|
||||||
|
@echo " - Step 3: Enabling IAP on the service..."
|
||||||
|
@gcloud beta run services update $(CR_ADMIN_SERVICE_NAME) \
|
||||||
|
--region=$(CR_ADMIN_REGION) \
|
||||||
|
--project=$(GCP_PROJECT_ID) \
|
||||||
|
--iap
|
||||||
|
@echo "--> ✅ Admin Console deployment to Cloud Run successful."
|
||||||
|
|
||||||
|
deploy-admin-full: deploy-admin configure-iap-admin
|
||||||
|
@echo "✅ Admin Console deployed and IAP configured successfully!"
|
||||||
|
|
||||||
admin-deploy-staging: admin-build
|
|
||||||
@echo "--> Deploying Admin Web App to STAGING environment (App Engine)..."
|
|
||||||
@cd admin-web && gcloud app deploy app.staging.yaml --project=$(GCP_STAGING_PROJECT_ID)
|
|
||||||
|
|
||||||
# --- Cloud IAP Configuration ---
|
# --- Cloud IAP Configuration ---
|
||||||
# NOTE: These commands use the 'gcloud beta iap web' command set, which is the correct
|
|
||||||
# method for managing user access to an IAP-protected Cloud Run service.
|
|
||||||
configure-iap-launchpad:
|
configure-iap-launchpad:
|
||||||
@echo "--> Configuring IAP users for Cloud Run service [$(CR_LAUNCHPAD_SERVICE_NAME)]..."
|
@echo "--> Configuring IAP for Cloud Run service [$(CR_LAUNCHPAD_SERVICE_NAME)]..."
|
||||||
@echo " - Granting Cloud Run Invoker role to IAP Service Account..."
|
@echo " - Granting Cloud Run Invoker role to IAP Service Account..."
|
||||||
@gcloud run services add-iam-policy-binding $(CR_LAUNCHPAD_SERVICE_NAME) \
|
@gcloud run services add-iam-policy-binding $(CR_LAUNCHPAD_SERVICE_NAME) \
|
||||||
--region=$(CR_LAUNCHPAD_REGION) \
|
--region=$(CR_LAUNCHPAD_REGION) \
|
||||||
@@ -158,46 +186,56 @@ configure-iap-launchpad:
|
|||||||
--role='roles/iap.httpsResourceAccessor' \
|
--role='roles/iap.httpsResourceAccessor' \
|
||||||
--quiet; \
|
--quiet; \
|
||||||
done
|
done
|
||||||
@echo "✅ IAP user configuration complete."
|
@echo "✅ IAP configuration for Launchpad complete."
|
||||||
|
|
||||||
|
configure-iap-admin:
|
||||||
|
@echo "--> Configuring IAP for Cloud Run service [$(CR_ADMIN_SERVICE_NAME)] in [$(ENV)]..."
|
||||||
|
@echo " - Granting Cloud Run Invoker role to IAP Service Account..."
|
||||||
|
@gcloud run services add-iam-policy-binding $(CR_ADMIN_SERVICE_NAME) \
|
||||||
|
--region=$(CR_ADMIN_REGION) \
|
||||||
|
--project=$(GCP_PROJECT_ID) \
|
||||||
|
--member="serviceAccount:$(IAP_SERVICE_ACCOUNT)" \
|
||||||
|
--role='roles/run.invoker' \
|
||||||
|
--quiet
|
||||||
|
@echo " - Adding users from iap-users.txt..."
|
||||||
|
@cd admin-web && \
|
||||||
|
grep -v '^#' iap-users.txt | grep -v '^$$' | while read -r member; do \
|
||||||
|
echo " Adding $$member as IAP-secured Web App User..."; \
|
||||||
|
gcloud beta iap web add-iam-policy-binding \
|
||||||
|
--project=$(GCP_PROJECT_ID) \
|
||||||
|
--resource-type=cloud-run \
|
||||||
|
--service=$(CR_ADMIN_SERVICE_NAME) \
|
||||||
|
--region=$(CR_ADMIN_REGION) \
|
||||||
|
--member="$$member" \
|
||||||
|
--role='roles/iap.httpsResourceAccessor' \
|
||||||
|
--quiet; \
|
||||||
|
done
|
||||||
|
@echo "✅ IAP configuration for Admin Console complete."
|
||||||
|
|
||||||
list-iap-users:
|
list-iap-users:
|
||||||
@echo "--> Current IAP users for Cloud Run service [$(CR_LAUNCHPAD_SERVICE_NAME)]:"
|
@echo "--> Current IAP users for Cloud Run service [$(IAP_SERVICE_NAME)]:"
|
||||||
@gcloud beta iap web get-iam-policy \
|
@gcloud beta iap web get-iam-policy \
|
||||||
--project=$(GCP_DEV_PROJECT_ID) \
|
--project=$(IAP_PROJECT_ID) \
|
||||||
--resource-type=cloud-run \
|
--resource-type=cloud-run \
|
||||||
--service=$(CR_LAUNCHPAD_SERVICE_NAME) \
|
--service=$(IAP_SERVICE_NAME) \
|
||||||
--region=$(CR_LAUNCHPAD_REGION)
|
--region=$(IAP_SERVICE_REGION)
|
||||||
|
|
||||||
remove-iap-user:
|
remove-iap-user:
|
||||||
@if [ -z "$(USER)" ]; then \
|
@if [ -z "$(USER)" ]; then \
|
||||||
echo "❌ Error: Please specify USER=user:email@example.com"; \
|
echo "❌ Error: Please specify USER=user:email@example.com"; \
|
||||||
exit 1; \
|
exit 1; \
|
||||||
fi
|
fi
|
||||||
@echo "--> Removing IAP access for $(USER) from Cloud Run service [$(CR_LAUNCHPAD_SERVICE_NAME)]..."
|
@echo "--> Removing IAP access for $(USER) from Cloud Run service [$(IAP_SERVICE_NAME)]..."
|
||||||
@gcloud beta iap web remove-iam-policy-binding \
|
@gcloud beta iap web remove-iam-policy-binding \
|
||||||
--project=$(GCP_DEV_PROJECT_ID) \
|
--project=$(IAP_PROJECT_ID) \
|
||||||
--resource-type=cloud-run \
|
--resource-type=cloud-run \
|
||||||
--service=$(CR_LAUNCHPAD_SERVICE_NAME) \
|
--service=$(IAP_SERVICE_NAME) \
|
||||||
--region=$(CR_LAUNCHPAD_REGION) \
|
--region=$(IAP_SERVICE_REGION) \
|
||||||
--member="$(USER)" \
|
--member="$(USER)" \
|
||||||
--role='roles/iap.httpsResourceAccessor' \
|
--role='roles/iap.httpsResourceAccessor' \
|
||||||
--quiet
|
--quiet
|
||||||
@echo "✅ User removed from IAP."
|
@echo "✅ User removed from IAP."
|
||||||
|
|
||||||
disable-iap-launchpad:
|
|
||||||
@echo "--> Disabling IAP and making Cloud Run service [$(CR_LAUNCHPAD_SERVICE_NAME)] public..."
|
|
||||||
@gcloud beta run services update $(CR_LAUNCHPAD_SERVICE_NAME) \
|
|
||||||
--region=$(CR_LAUNCHPAD_REGION) \
|
|
||||||
--project=$(GCP_DEV_PROJECT_ID) \
|
|
||||||
--no-iap --quiet
|
|
||||||
@gcloud run services add-iam-policy-binding $(CR_LAUNCHPAD_SERVICE_NAME) \
|
|
||||||
--region=$(CR_LAUNCHPAD_REGION) \
|
|
||||||
--project=$(GCP_DEV_PROJECT_ID) \
|
|
||||||
--member="allUsers" \
|
|
||||||
--role='roles/run.invoker' \
|
|
||||||
--quiet
|
|
||||||
@echo "✅ IAP disabled. The service is now public."
|
|
||||||
|
|
||||||
# --- Project Management ---
|
# --- Project Management ---
|
||||||
setup-labels:
|
setup-labels:
|
||||||
@echo "--> Setting up GitHub labels..."
|
@echo "--> Setting up GitHub labels..."
|
||||||
|
|||||||
38
admin-web/Dockerfile
Normal file
38
admin-web/Dockerfile
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# STAGE 1: Build the React application
|
||||||
|
FROM node:20-alpine AS build
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy package files and install dependencies
|
||||||
|
COPY package.json package-lock.json ./
|
||||||
|
RUN npm install
|
||||||
|
|
||||||
|
# Copy the rest of the application source code
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Build the application for production
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# STAGE 2: Serve the static files with Nginx
|
||||||
|
FROM nginx:alpine
|
||||||
|
|
||||||
|
# Copy the built files from the build stage
|
||||||
|
COPY --from=build /app/dist /usr/share/nginx/html
|
||||||
|
|
||||||
|
# Copy our custom Nginx configuration
|
||||||
|
# This config is for a Single Page Application (SPA) and listens on port 8080 for Cloud Run
|
||||||
|
RUN echo 'server {
|
||||||
|
listen 8080;
|
||||||
|
server_name _;
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
}' > /etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
|
# Expose the port Nginx is listening on
|
||||||
|
EXPOSE 8080
|
||||||
|
|
||||||
|
# Command to run Nginx in the foreground
|
||||||
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
runtime: nodejs20
|
|
||||||
service: admin-web-dev
|
|
||||||
|
|
||||||
handlers:
|
|
||||||
# Servir les fichiers statiques (js, css, images, etc.)
|
|
||||||
- url: /(.*\.(js|css|svg|png|jpg|ico|txt))$
|
|
||||||
static_files: dist/\1
|
|
||||||
upload: dist/.*\.(js|css|svg|png|jpg|ico|txt)$
|
|
||||||
|
|
||||||
# Servir l'index.html pour toutes les autres routes (pour le routing côté client de React)
|
|
||||||
- url: /.*
|
|
||||||
static_files: dist/index.html
|
|
||||||
upload: dist/index.html
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
runtime: nodejs20
|
|
||||||
service: admin-web-staging
|
|
||||||
|
|
||||||
handlers:
|
|
||||||
# Servir les fichiers statiques (js, css, images, etc.)
|
|
||||||
- url: /(.*\.(js|css|svg|png|jpg|ico|txt))$
|
|
||||||
static_files: dist/\1
|
|
||||||
upload: dist/.*\.(js|css|svg|png|jpg|ico|txt)$
|
|
||||||
|
|
||||||
# Servir l'index.html pour toutes les autres routes (pour le routing côté client de React)
|
|
||||||
- url: /.*
|
|
||||||
static_files: dist/index.html
|
|
||||||
upload: dist/index.html
|
|
||||||
8
admin-web/iap-users.txt
Normal file
8
admin-web/iap-users.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# List of authorized users for the Admin Console
|
||||||
|
# Format: one email per line, lines starting with # are comments
|
||||||
|
#
|
||||||
|
# IMPORTANT: These users must belong to the 'krowwithus.com' organization.
|
||||||
|
# This is a known limitation of enabling IAP directly on Cloud Run.
|
||||||
|
# See: https://docs.cloud.google.com/run/docs/securing/identity-aware-proxy-cloud-run#known_limitations
|
||||||
|
|
||||||
|
user:admin@krowwithus.com
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
# Liste des utilisateurs autorisés pour le Internal Launchpad
|
# List of authorized users for the Internal Launchpad
|
||||||
# Format: un email par ligne, les lignes commençant par # sont des commentaires
|
# Format: one email per line, lines starting with # are comments
|
||||||
|
#
|
||||||
|
# IMPORTANT: These users must belong to the 'krowwithus.com' organization.
|
||||||
|
# This is a known limitation of enabling IAP directly on Cloud Run.
|
||||||
|
# See: https://docs.cloud.google.com/run/docs/securing/identity-aware-proxy-cloud-run#known_limitations
|
||||||
|
|
||||||
user:boris@oloodi.com
|
|
||||||
# user:temporaire@oloodi.com # Décommenté pour donner accès temporaire
|
|
||||||
user:admin@krowwithus.com
|
user:admin@krowwithus.com
|
||||||
|
# user:boris@oloodi.com # External users are not supported with this IAP method
|
||||||
|
|||||||
Reference in New Issue
Block a user