> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/Arvo-AI/aurora/llms.txt
> Use this file to discover all available pages before exploring further.

# Cloud Integrations

> Multi-cloud support for GCP, AWS, Azure, Scaleway, Tailscale, and OVH with unified command execution

Aurora supports multiple cloud providers, allowing you to manage infrastructure across GCP, AWS, Azure, Scaleway, Tailscale, and OVH from a single interface.

## Supported Cloud Providers

<CardGroup cols={3}>
  <Card title="Google Cloud (GCP)" icon="google">
    OAuth 2.0 authentication with full gcloud SDK support
  </Card>

  <Card title="Amazon Web Services (AWS)" icon="aws">
    IAM Role with External ID for secure access
  </Card>

  <Card title="Microsoft Azure" icon="microsoft">
    Service Principal authentication with Azure CLI
  </Card>

  <Card title="Scaleway" icon="cloud">
    API key authentication for Scaleway resources
  </Card>

  <Card title="Tailscale" icon="network-wired">
    API key for private network management
  </Card>

  <Card title="OVH" icon="server">
    OAuth 2.0 multi-region support (EU, CA, US)
  </Card>
</CardGroup>

<Note>
  OVH support is feature-flagged. Enable with `FEATURE_FLAG_OVH_ENABLED=true` in your environment.
</Note>

## Architecture

### Connector System

Each cloud provider has a dedicated connector in `server/connectors/`:

```
server/connectors/
├── gcp_connector/
│   ├── README.md          # OAuth setup guide
│   ├── connector.py       # GCP authentication logic
│   └── service_account.json  # Service account credentials
├── aws_connector/
│   ├── README.md          # IAM Role setup guide
│   └── connector.py       # AWS authentication logic
├── azure_connector/
│   ├── README.md          # Service Principal guide
│   └── connector.py       # Azure authentication logic
├── ovh_connector/
│   ├── README.md          # OVH OAuth guide
│   └── connector.py       # OVH multi-region auth
└── README.md              # Connector overview
```

### Authentication Flow

<Steps>
  <Step title="User initiates OAuth">
    User clicks "Connect" button in UI for a provider (e.g., GCP)
  </Step>

  <Step title="Backend redirects to provider">
    Flask route `/api/auth/gcp` redirects to provider's OAuth consent page
  </Step>

  <Step title="User grants permissions">
    User approves requested scopes (e.g., `https://www.googleapis.com/auth/cloud-platform`)
  </Step>

  <Step title="Provider redirects back">
    Callback route `/api/auth/gcp/callback` receives authorization code
  </Step>

  <Step title="Backend exchanges for tokens">
    Connector exchanges code for access token and refresh token
  </Step>

  <Step title="Tokens stored in Vault">
    Credentials saved to HashiCorp Vault at `kv/data/aurora/users/{user_id}/gcp`
  </Step>
</Steps>

### Credential Storage

All user credentials are stored in HashiCorp Vault (not in the database):

```python theme={null}
# Reference stored in database
user_tokens.token = "vault:kv/data/aurora/users/user_abc123/gcp"

# Retrieved at runtime
from utils.vault.vault_client import vault_get
credentials = vault_get(user_tokens.token)
# Returns: {"access_token": "...", "refresh_token": "...", "project_id": "..."}
```

<Info>
  See [Vault Secrets](/configuration/vault-secrets) for configuration details.
</Info>

## Cloud Tool Execution

The `cloud_tool` is Aurora's unified interface for executing commands across all cloud providers:

```python theme={null}
# server/chat/backend/agent/tools/cloud_tools.py
@tool("cloud_tool")
def cloud_tool(
    provider: str,
    command: str,
    selected_project_id: Optional[str] = None,
    confirmation_id: Optional[str] = None
) -> str:
    """
    Execute cloud provider CLI commands.
    
    Args:
        provider: Cloud provider - gcp, aws, azure, scaleway, tailscale, ovh
        command: Command to execute (e.g., 'gcloud compute instances list')
        selected_project_id: Project/account ID to scope command
        confirmation_id: ID for user confirmation on write operations
    
    Returns:
        JSON with command output, status, and metadata
    """
    # Validation
    if provider not in SUPPORTED_PROVIDERS:
        return {"error": f"Unsupported provider: {provider}"}
    
    # Read-only check in Ask mode
    if mode == "ask" and not is_read_only_command(command):
        return {"error": "Write operations not allowed in Ask mode"}
    
    # Require confirmation for destructive operations
    if is_destructive_command(command) and not confirmation_id:
        return {"requires_confirmation": True, "confirmation_id": generate_id()}
    
    # Execute command
    result = execute_cloud_command(provider, command, user_id, selected_project_id)
    return result
```

### Command Execution Examples

<CodeGroup>
  ```bash GCP - List Compute Instances theme={null}
  gcloud compute instances list --project=my-project
  ```

  ```bash AWS - List EC2 Instances theme={null}
  aws ec2 describe-instances --region us-west-2
  ```

  ```bash Azure - List Virtual Machines theme={null}
  az vm list --resource-group my-rg
  ```

  ```bash Scaleway - List Instances theme={null}
  scw instance server list zone=fr-par-1
  ```

  ```bash Tailscale - List Devices theme={null}
  tailscale status
  ```
</CodeGroup>

### Read-Only Command Detection

Aurora categorizes commands as read-only or write:

```python theme={null}
def is_read_only_command(command: str) -> bool:
    """Check if command is read-only (safe in Ask mode)."""
    read_only_patterns = [
        r'^gcloud .* (list|describe|get|show)',
        r'^aws .* (describe|list|get)',
        r'^az .* (list|show|get)',
        r'^kubectl (get|describe)',
    ]
    
    for pattern in read_only_patterns:
        if re.match(pattern, command.strip()):
            return True
    return False

def is_destructive_command(command: str) -> bool:
    """Check if command requires user confirmation."""
    destructive_patterns = [
        r'delete', r'remove', r'destroy', r'terminate',
        r'drop', r'truncate', r'--force'
    ]
    
    return any(re.search(pattern, command.lower()) for pattern in destructive_patterns)
```

## User Workflows

### Connecting a Cloud Provider

1. Navigate to **Connectors** page (`/connectors`)
2. Click **"Connect"** next to your cloud provider
3. Complete OAuth flow or enter API credentials
4. Select default project/account (optional)
5. Credentials are stored in Vault and ready to use

<Frame>
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/arvo-ai-aurora/images/placeholder-connectors.png" alt="Connectors page showing GCP, AWS, and Azure connection status" />

  *Connectors page with connection status for each provider*
</Frame>

### Executing Commands via Chat

**In Agent Mode**:

```
You: "List all GCP compute instances in my production project"

Aurora: I'll check your GCP instances.

[Executing: gcloud compute instances list --project=prod-123]

NAME          ZONE        MACHINE_TYPE   STATUS
api-server-1  us-west1-a  n1-standard-4  RUNNING
api-server-2  us-west1-b  n1-standard-4  RUNNING
db-primary    us-west1-a  n1-highmem-8   RUNNING

You have 3 instances running in production.
```

**In Ask Mode**:

```
You: "Delete the test-instance in GCP"

Aurora: I cannot execute delete operations in Ask mode. 
Switch to Agent mode to perform this action.
```

### Multi-Cloud Queries

Aurora can execute commands across multiple clouds in a single conversation:

```
You: "Compare my GCP and AWS instance counts"

Aurora: Let me check both providers.

[Executing: gcloud compute instances list --format=json]
[Executing: aws ec2 describe-instances --output json]

GCP: 12 instances across 3 projects
AWS: 8 instances across 2 regions

Total: 20 instances across both clouds.
```

### Provider Preference

Set provider preference to scope commands:

```typescript theme={null}
// Frontend sends provider preference with each message
webSocket.send(JSON.stringify({
  query: "List all instances",
  provider_preference: ["gcp", "aws"],  // Only use these providers
  selected_project_id: "my-gcp-project"  // Scope to specific project
}));
```

The AI will only use tools for the specified providers.

## Provider-Specific Features

<Tabs>
  <Tab title="GCP">
    ### OAuth Scopes

    * `https://www.googleapis.com/auth/cloud-platform` (full access)
    * `https://www.googleapis.com/auth/compute.readonly` (read-only compute)

    ### Project Selection

    Users can select a default project or specify per-command:

    ```bash theme={null}
    gcloud compute instances list --project=my-project
    ```

    ### Service Account

    Server uses a service account for background operations (e.g., Terraform):

    ```json theme={null}
    // server/connectors/gcp_connector/service_account.json
    {
      "type": "service_account",
      "project_id": "aurora-prod",
      "private_key_id": "...",
      "private_key": "...",
      "client_email": "aurora-sa@aurora-prod.iam.gserviceaccount.com"
    }
    ```
  </Tab>

  <Tab title="AWS">
    ### IAM Role with External ID

    Aurora uses an IAM Role with an External ID for secure cross-account access:

    ```json theme={null}
    {
      "Version": "2012-10-17",
      "Statement": [{
        "Effect": "Allow",
        "Principal": {
          "AWS": "arn:aws:iam::AURORA_ACCOUNT_ID:root"
        },
        "Action": "sts:AssumeRole",
        "Condition": {
          "StringEquals": {
            "sts:ExternalId": "unique-external-id-per-user"
          }
        }
      }]
    }
    ```

    ### Region Selection

    Default region can be set in credentials:

    ```python theme={null}
    aws_credentials = {
      "role_arn": "arn:aws:iam::123456789012:role/AuroraAccess",
      "external_id": "unique-id",
      "default_region": "us-west-2"
    }
    ```
  </Tab>

  <Tab title="Azure">
    ### Service Principal

    Aurora uses a Service Principal for authentication:

    ```bash theme={null}
    # Create service principal
    az ad sp create-for-rbac \
      --name aurora-sp \
      --role Contributor \
      --scopes /subscriptions/{subscription-id}
    ```

    ### Stored Credentials

    ```python theme={null}
    azure_credentials = {
      "tenant_id": "...",
      "client_id": "...",
      "client_secret": "...",
      "subscription_id": "..."
    }
    ```
  </Tab>

  <Tab title="OVH">
    ### Multi-Region Support

    OVH has separate OAuth endpoints per region:

    * **EU**: `https://eu.api.ovh.com/`
    * **CA**: `https://ca.api.ovh.com/`
    * **US**: `https://api.us.ovhcloud.com/`

    Users select region during OAuth flow.

    ### Feature Flag

    Enable OVH in `.env`:

    ```bash theme={null}
    FEATURE_FLAG_OVH_ENABLED=true
    ```
  </Tab>
</Tabs>

## Security

### Credential Isolation

* All credentials stored in Vault (not database)
* Per-user credential isolation
* Row-Level Security (RLS) on `user_tokens` table
* Refresh tokens rotated on each use

### Command Validation

```python theme={null}
# Prevent command injection
def sanitize_command(command: str) -> str:
    """Remove dangerous characters from command."""
    if any(c in command for c in [';', '&&', '||', '|', '>', '<', '`', '$']):
        raise ValueError("Command contains forbidden characters")
    return command.strip()
```

### Confirmation Flow

Destructive operations require user confirmation:

<Steps>
  <Step title="AI detects destructive command">
    Command matches pattern: `delete`, `terminate`, `destroy`, etc.
  </Step>

  <Step title="Backend requests confirmation">
    Returns `{"requires_confirmation": true, "confirmation_id": "conf_abc123"}`
  </Step>

  <Step title="UI shows confirmation dialog">
    User reviews command and clicks "Confirm" or "Cancel"
  </Step>

  <Step title="User confirms">
    Frontend sends `confirmation_response` via WebSocket with `confirmation_id`
  </Step>

  <Step title="Backend executes command">
    Command runs with the confirmation ID passed back to `cloud_tool`
  </Step>
</Steps>

## API Reference

### Connect Provider

```http theme={null}
GET /api/auth/{provider}
```

Initiates OAuth flow for provider. Redirects to provider's consent page.

### OAuth Callback

```http theme={null}
GET /api/auth/{provider}/callback?code={auth_code}
```

Receives OAuth callback with authorization code. Exchanges for tokens and stores in Vault.

### Get Connected Providers

```http theme={null}
GET /api/user/connected-providers
```

Returns list of providers the user has connected.

```json theme={null}
{
  "providers": ["gcp", "aws", "azure"],
  "default_provider": "gcp"
}
```

### Disconnect Provider

```http theme={null}
DELETE /api/auth/{provider}/disconnect
```

Removes credentials from Vault and database.

## Related Features

<CardGroup cols={2}>
  <Card title="AI Chat Interface" icon="message" href="/features/ai-chat-interface">
    Execute cloud commands via natural language chat
  </Card>

  <Card title="Incident Investigation" icon="bug" href="/features/incident-investigation">
    Automatic diagnostics across all connected cloud providers
  </Card>
</CardGroup>
