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
Clone the repository
Clone the Multi-Cloud Manager repository to your local machine: git clone < repository-ur l >
cd multi-cloud-manager
Configure environment variables
Create a .env file in the root directory with your cloud provider credentials: # 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.
Start the application
Launch both backend and frontend services using Docker Compose: 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.
Verify the installation
Check that both containers are running: 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
Navigate to the home page
Open your browser and go to http://localhost:3000
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)
Grant permissions
Authorize the application to access Azure Resource Manager APIs with scope: SCOPE = [ "https://management.azure.com/.default" ]
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
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 %20e mail%20profile%20https://www.googleapis.com/auth/cloud-platform"
"&access_type=offline"
"&prompt=consent %20s elect_account"
)
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"
})
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.
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"
}
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"
}
}
}
]
}
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.
Navigate to Dashboard
After authentication, you’ll be redirected to http://localhost:3000/dashboard
Select subscription
Choose an Azure subscription from the dropdown menu
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"
}'
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
Backend container fails to start
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
Session lost after refresh
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" ])