Skip to main content

Quick Start Guide

Get Multi-Cloud Manager up and running in minutes with Docker. This guide will walk you through setup, authentication, and creating your first cloud resource.

Prerequisites

Before you begin, ensure you have:
  • Docker and Docker Compose installed
  • Cloud provider accounts (Azure, GCP, and/or AWS)
  • OAuth2 credentials configured for your cloud providers

Docker Setup

1

Clone the repository

Clone the Multi-Cloud Manager repository to your local machine:
git clone <repository-url>
cd multi-cloud-manager
2

Configure environment variables

Create a .env file in the root directory with your cloud provider credentials:
.env
# Azure Configuration
AZURE_TENANT_ID=your-tenant-id
AZURE_CLIENT_ID=your-client-id
AZURE_CLIENT_SECRET=your-client-secret

# GCP Configuration
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
GOOGLE_REDIRECT_URI=http://localhost:5000/google/callback

# AWS Configuration
AWS_ACCESS_KEY_ID=your-aws-access-key
AWS_SECRET_ACCESS_KEY=your-aws-secret-key
AWS_ACCOUNT_ID=your-aws-account-id

# Application Configuration
APP_BASE_URL=http://localhost:5000
Keep your .env file secure and never commit it to version control. Add it to .gitignore.
3

Start the application

Launch both backend and frontend services using Docker Compose:
docker-compose up -d
This command starts:
  • Backend: Flask API server on http://localhost:5000
  • Frontend: React application on http://localhost:3000
The services are connected via a Docker bridge network for seamless communication.
4

Verify the installation

Check that both containers are running:
docker ps
You should see:
  • flask-backend (port 5000)
  • react-frontend (port 3000)

Authentication Flow

Multi-Cloud Manager supports OAuth2 authentication for Azure and GCP, plus IAM role assumption for AWS.

Azure OAuth2

Uses MSAL (Microsoft Authentication Library) for secure Azure authentication.

GCP OAuth2

Implements Google OAuth2 with cloud platform scope for full resource access.

AWS IAM Role

Uses STS AssumeRole with external ID for secure cross-account access.

Azure Authentication

1

Navigate to the home page

Open your browser and go to http://localhost:3000
2

Click 'Login with Azure'

You’ll be redirected to Microsoft’s login page. The authentication flow:
project/backend/auth/azure_auth.py
@azure_auth.route("/api/login/azure")
def login():
    url = build_msal_app().get_authorization_request_url(
        scopes=SCOPE, 
        redirect_uri=f"{APP_BASE_URL}{REDIRECT_PATH}",
    )
    return redirect(url)
3

Grant permissions

Authorize the application to access Azure Resource Manager APIs with scope:
SCOPE = ["https://management.azure.com/.default"]
4

Session created

Upon successful authentication, the app stores your credentials in a server-side session:
project/backend/auth/azure_auth.py
session["user"] = result["id_token_claims"]
session["access_token"] = result.get("access_token")

azure_account = {
    "provider": "azure",
    "tenantId": tenant_id,
    "displayName": display_name,
    "subscriptions": subs
}
session["accounts"] = filtered_accounts

GCP Authentication

1

Click 'Login with Google'

The OAuth2 authorization URL includes comprehensive scopes:
project/backend/auth/gcp_auth.py
url = (
    "https://accounts.google.com/o/oauth2/v2/auth"
    f"?client_id={GOOGLE_CLIENT_ID}"
    f"&redirect_uri={GOOGLE_REDIRECT_URI}"
    "&response_type=code"
    "&scope=openid%20email%20profile%20https://www.googleapis.com/auth/cloud-platform"
    "&access_type=offline"
    "&prompt=consent%20select_account"
)
2

Exchange code for tokens

After authorization, the callback exchanges the code for access and refresh tokens:
project/backend/auth/gcp_auth.py
token_res = http_requests.post(TOKEN_URI, data={
    "code": code,
    "client_id": GOOGLE_CLIENT_ID,
    "client_secret": GOOGLE_CLIENT_SECRET,
    "redirect_uri": GOOGLE_REDIRECT_URI,
    "grant_type": "authorization_code"
})
3

Verify and store tokens

The ID token is verified and credentials are stored in the session:
project/backend/auth/gcp_auth.py
idinfo = id_token.verify_oauth2_token(
    id_token_str, google_requests.Request(), GOOGLE_CLIENT_ID
)

new_gcp_account = {
    "provider": "gcp",
    "email": idinfo.get("email"),
    "displayName": idinfo.get("name"),
    "access_token": access_token,
    "refresh_token": refresh_token
}

AWS Authentication (IAM Role)

AWS uses a different approach - IAM role assumption with external ID for security.
1

Get server configuration

First, retrieve the server’s AWS account ID and external ID:
curl http://localhost:5000/api/account/aws/config
Response:
{
  "awsAccountId": "123456789012",
  "externalId": "multi-cloud-manager-app-v1-secret"
}
2

Create IAM role in your AWS account

Create a role with trust policy allowing the server to assume it:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::SERVER_ACCOUNT_ID:root"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "sts:ExternalId": "multi-cloud-manager-app-v1-secret"
        }
      }
    }
  ]
}
3

Add your role ARN

Submit your role ARN to the application:
curl -X POST http://localhost:5000/api/account/aws/add \
  -H "Content-Type: application/json" \
  -d '{"roleArn": "arn:aws:iam::YOUR_ACCOUNT_ID:role/MultiCloudManagerRole"}'
The server verifies access by assuming the role:
project/backend/auth/aws_auth.py
sts_client = boto3.client(
    'sts',
    aws_access_key_id=AWS_SERVER_ACCESS_KEY_ID,
    aws_secret_access_key=AWS_SERVER_SECRET_KEY,
    region_name='us-east-1'
)

assumed_role_object = sts_client.assume_role(
    RoleArn=role_arn_from_user,
    RoleSessionName="MultiCloudManagerVerification",
    ExternalId=APP_EXTERNAL_ID
)
The external ID acts as a secret shared between your application and AWS, preventing the “confused deputy” problem.

Create Your First Resource

Let’s create a resource group in Azure as your first multi-cloud resource.
1

Navigate to Dashboard

After authentication, you’ll be redirected to http://localhost:3000/dashboard
2

Select subscription

Choose an Azure subscription from the dropdown menu
3

Create a resource group

Click “Create Resource Group” and fill in the details:
curl -X POST http://localhost:5000/api/create_rg \
  -H "Content-Type: application/json" \
  -d '{
    "subscription_id": "your-subscription-id",
    "resource_group_name": "my-first-rg",
    "location": "eastus"
  }'
4

Verify creation

List all resource groups to confirm:
curl http://localhost:5000/api/resource_groups?subscription_id=your-subscription-id

Next Steps

Architecture Overview

Understand how Multi-Cloud Manager is built

Create Virtual Machines

Learn how to provision VMs across Azure and GCP

Manage Storage

Work with blob storage, buckets, and containers

Set Up Monitoring

Configure metrics, logs, and alerts for your resources

Troubleshooting

Check your .env file for missing or invalid credentials. View logs with:
docker logs flask-backend
Ensure your redirect URIs match exactly in both your cloud provider’s app registration and your .env file:
  • Azure: http://localhost:5000/getAToken
  • GCP: http://localhost:5000/google/callback
The Flask session uses a secret key for signing. Check that app.secret_key is set in project/backend/app.py:7
Verify CORS is configured to allow requests from the frontend:
CORS(app, supports_credentials=True, origins=["http://localhost:3000"])

Build docs developers (and LLMs) love