> ## Documentation Index
> Fetch the complete documentation index at: https://docs.deploystack.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Cloud Credentials Management

> Comprehensive guide to implementing and managing cloud provider credentials in DeployStack backend with encryption, validation, and role-based access control.

DeployStack provides a secure cloud credentials management system that allows teams to store and manage cloud provider credentials for deployments. This system features encryption, role-based access control, and provider validation.

## Architecture Overview

The cloud credentials system consists of several key components:

* **Provider Configuration**: Defines supported cloud providers and their required fields
* **Encryption Service**: Handles secure storage of credential values
* **Validation System**: Validates credential data against provider schemas
* **Role-Based Access**: Different response formats based on user permissions
* **API Layer**: RESTful endpoints for credential management

## Database Schema

### Team Cloud Credentials Table

```sql theme={null}
CREATE TABLE team_cloud_credentials (
  id TEXT PRIMARY KEY,
  team_id TEXT NOT NULL REFERENCES teams(id) ON DELETE CASCADE,
  provider_id TEXT NOT NULL,
  name TEXT NOT NULL,
  comment TEXT,
  credentials TEXT NOT NULL, -- Encrypted JSON
  created_by TEXT NOT NULL REFERENCES authUser(id),
  created_at INTEGER NOT NULL,
  updated_at INTEGER NOT NULL,
  UNIQUE(team_id, provider_id, name)
);
```

### Key Features

* **Team Isolation**: Credentials are scoped to specific teams
* **Provider Support**: Multiple cloud providers per team
* **Encrypted Storage**: All credential values are encrypted
* **Audit Trail**: Tracks creation and modification metadata
* **Unique Constraints**: Prevents duplicate credential names per provider/team

## Provider Configuration

Cloud providers are configured in `services/backend/config/cloud-providers.ts`:

```typescript theme={null}
export interface CloudProvider {
  id: string;
  name: string;
  description: string;
  fields: CloudProviderField[];
  enabled: boolean;
}

export interface CloudProviderField {
  key: string;
  label: string;
  type: 'text' | 'password' | 'textarea';
  required: boolean;
  secret: boolean;
  placeholder?: string;
  description?: string;
  validation?: {
    pattern?: string;
    minLength?: number;
    maxLength?: number;
  };
}
```

### Example Provider Configuration

```typescript theme={null}
{
  id: 'aws',
  name: 'Amazon Web Services',
  description: 'AWS cloud platform credentials',
  fields: [
    {
      key: 'access_key_id',
      label: 'Access Key ID',
      type: 'text',
      required: true,
      secret: false,
      placeholder: 'AKIAIOSFODNN7EXAMPLE'
    },
    {
      key: 'secret_access_key',
      label: 'Secret Access Key',
      type: 'password',
      required: true,
      secret: true,
      validation: {
        minLength: 40
      }
    }
  ],
  enabled: true
}
```

## Encryption System

### Storage Format

Credentials are stored as encrypted JSON with metadata:

```typescript theme={null}
interface StoredCredentials {
  [fieldKey: string]: {
    value: string;        // Encrypted value
    secret: boolean;      // Field type from provider config
    updatedAt: string;    // ISO timestamp
  };
}
```

### Encryption Process

1. **Field Validation**: Validate against provider schema
2. **Individual Encryption**: Each field value encrypted separately
3. **Metadata Storage**: Include field type and timestamp
4. **JSON Serialization**: Store as encrypted JSON string

### Security Features

* **AES-256-GCM**: Industry-standard encryption algorithm
* **Separate Keys**: Encryption keys managed separately from data
* **Field-Level**: Each credential field encrypted individually
* **No Plaintext**: Credential values never stored in plaintext

## Role-Based Access Control

The cloud credentials system uses **team-contextual permissions** rather than global permissions. For detailed role information and permission matrices, see [Role-Based Access Control](/development/backend/roles).

### Access Levels

| User Type        | Access Level    | Field Information      | Credential Values              |
| ---------------- | --------------- | ---------------------- | ------------------------------ |
| **Global Admin** | Metadata only   | ✅ Field types & status | ❌ No values shown              |
| **Team Admin**   | Full CRUD       | ✅ Field types & status | 🔒 Placeholders for non-secret |
| **Team User**    | Read-only basic | ❌ No field details     | ❌ No values shown              |
| **Non-member**   | No access       | ❌ Blocked              | ❌ Blocked                      |

### Key Security Features

* **Team Isolation**: Users can only access credentials from teams they belong to
* **No Secret Exposure**: Secret values are never returned in API responses
* **Role-Based Responses**: API responses vary based on user's role within the team
* **Global Admin Limitations**: Even global admins cannot see credential values

## API Implementation

### Service Layer

The `CloudCredentialsService` provides the core business logic:

```typescript theme={null}
export class CloudCredentialsService {
  // Role-specific methods
  async getTeamCredentials(teamId: string): Promise<CloudCredentialResponse[]>
  async getTeamCredentialsGlobalAdmin(teamId: string): Promise<CloudCredentialResponse[]>
  async getTeamCredentialsBasic(teamId: string): Promise<CloudCredentialBasicResponse[]>
  
  // CRUD operations
  async createCredentials(teamId: string, userId: string, input: CreateCloudCredentialRequest): Promise<CloudCredentialResponse>
  async updateCredentials(credentialId: string, teamId: string, input: UpdateCloudCredentialRequest): Promise<CloudCredentialResponse | null>
  async deleteCredentials(credentialId: string, teamId: string): Promise<boolean>
  
  // Internal methods
  async getDecryptedCredentials(credentialId: string, teamId: string): Promise<Record<string, string> | null>
}
```

### Route Implementation

Routes automatically detect user role and call appropriate service methods:

```typescript theme={null}
// Check user permissions and role
const roleService = new RoleService();
const hasAdminPermissions = await roleService.userHasPermission(userId, 'cloud_credentials.edit');
const userRole = await roleService.getUserRole(userId);
const isGlobalAdmin = userRole?.id === 'global_admin';

let credentials;
if (hasAdminPermissions && !isGlobalAdmin) {
  // Team admin - full details with placeholders
  credentials = await cloudCredentialsService.getTeamCredentials(teamId);
} else if (isGlobalAdmin) {
  // Global admin - metadata only, no values
  credentials = await cloudCredentialsService.getTeamCredentialsGlobalAdmin(teamId);
} else {
  // Team member - basic details only
  credentials = await cloudCredentialsService.getTeamCredentialsBasic(teamId);
}
```

## API Endpoints

### List Cloud Providers

```http theme={null}
GET /api/teams/:teamId/cloud-providers
Authorization: Required (cloud_credentials.view permission)
```

Returns available cloud providers with their field schemas.

### List Team Credentials

```http theme={null}
GET /api/teams/:teamId/cloud-credentials
Authorization: Required (cloud_credentials.view permission)
```

Returns credentials list with response format based on user role.

### Create Credentials

```http theme={null}
POST /api/teams/:teamId/cloud-credentials
Authorization: Required (cloud_credentials.create permission)
Content-Type: application/json

{
  "providerId": "aws",
  "name": "Production AWS",
  "comment": "Production environment credentials",
  "credentials": {
    "access_key_id": "AKIAIOSFODNN7EXAMPLE",
    "secret_access_key": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
  }
}
```

### Update Credentials

```http theme={null}
PUT /api/teams/:teamId/cloud-credentials/:credentialId
Authorization: Required (cloud_credentials.edit permission)
```

Supports partial updates of name, comment, and credential values.

### Delete Credentials

```http theme={null}
DELETE /api/teams/:teamId/cloud-credentials/:credentialId
Authorization: Required (cloud_credentials.delete permission)
```

Permanently removes credentials from the team.

## Validation System

### Create vs Update Validation

The system provides two validation functions to handle different scenarios:

#### Full Validation (Create)

```typescript theme={null}
export function validateCredentialData(
  providerId: string, 
  credentials: Record<string, string>
): ValidationResult {
  const provider = getCloudProvider(providerId);
  if (!provider) {
    return { valid: false, errors: ['Invalid provider ID'] };
  }

  const errors: string[] = [];
  
  // Check ALL required fields
  for (const field of provider.fields) {
    if (field.required && !credentials[field.key]) {
      errors.push(`${field.label} is required`);
    }
  }
  
  // Validate all provided fields
  for (const [key, value] of Object.entries(credentials)) {
    const field = provider.fields.find(f => f.key === key);
    if (field?.validation) {
      // Apply validation rules
    }
  }
  
  return { valid: errors.length === 0, errors };
}
```

#### Partial Validation (Update)

```typescript theme={null}
export function validateCredentialDataForUpdate(
  providerId: string, 
  credentials: Record<string, string>
): ValidationResult {
  const provider = getCloudProvider(providerId);
  if (!provider) {
    return { valid: false, errors: ['Invalid provider ID'] };
  }

  const errors: string[] = [];
  
  // Only validate fields that are actually provided
  for (const field of provider.fields) {
    const value = credentials[field.key];
    
    // Skip validation if field is not provided
    if (value === null || value === undefined) {
      continue;
    }
    
    // Validate provided fields
    if (field.required && value.trim() === '') {
      errors.push(`${field.label} cannot be empty`);
    }
    
    // Apply format validation if present
    if (field.validation) {
      // Apply validation rules
    }
  }
  
  return { valid: errors.length === 0, errors };
}
```

### Update Process

When updating credentials, the system:

1. **Validates only provided fields** using `validateCredentialDataForUpdate`
2. **Retrieves existing credentials** from encrypted storage
3. **Merges updates** with existing values
4. **Re-encrypts the complete credential set**

This allows partial updates without requiring users to re-submit secret values.

### Validation Rules

* **Required Fields**: Enforced based on provider configuration
* **Field Types**: Text, password, textarea validation
* **Format Validation**: Pattern matching, length constraints
* **Provider Schema**: Validates against defined field structure
* **Partial Updates**: Only validates fields being updated

## Error Handling

### Common Error Scenarios

```typescript theme={null}
// Provider not found
throw new Error('Invalid provider ID');

// Validation failure
throw new Error(`Validation failed: ${validation.errors.join(', ')}`);

// Duplicate name
throw new Error('A credential set with this name already exists for this provider');

// Not found
return null; // Handled as 404 in routes
```

### Error Response Format

```json theme={null}
{
  "success": false,
  "error": "Validation failed",
  "details": ["Access Key ID is required", "Secret Access Key must be at least 40 characters"]
}
```

## Security Considerations

### Data Protection

* **Encryption at Rest**: All credential values encrypted before storage
* **No Plaintext Logs**: Credential values never logged in plaintext
* **Secure Transmission**: HTTPS required for all API calls
* **Access Control**: Role-based response filtering

### Best Practices

* **Principle of Least Privilege**: Users see only necessary information
* **Audit Logging**: Track all credential operations
* **Regular Rotation**: Encourage credential rotation
* **Secure Defaults**: Safe fallbacks for all operations

## Adding New Providers

### 1. Define Provider Configuration

Add new provider to `cloud-providers.ts`:

```typescript theme={null}
{
  id: 'new-provider',
  name: 'New Cloud Provider',
  description: 'Description of the provider',
  fields: [
    {
      key: 'api_key',
      label: 'API Key',
      type: 'password',
      required: true,
      secret: true
    }
  ],
  enabled: true
}
```

### 2. Update Provider Registry

Add to the providers array and export:

```typescript theme={null}
export const CLOUD_PROVIDERS: CloudProvider[] = [
  AWS_PROVIDER,
  RENDER_PROVIDER,
  NEW_PROVIDER, // Add here
];
```

### 3. Test Integration

* Validate field schemas work correctly
* Test encryption/decryption of new field types
* Verify API responses include new provider
* Test credential creation and validation

## Troubleshooting

### Common Issues

#### Encryption Errors

* Verify encryption service is properly configured
* Check that encryption keys are available
* Ensure proper error handling for encryption failures

#### Validation Failures

* Check provider configuration matches expected format
* Verify required fields are properly marked
* Test validation rules with sample data

#### Permission Errors

* Confirm user has required permissions
* Check role assignments are correct
* Verify middleware is properly applied to routes

### Debug Commands

```typescript theme={null}
// Test provider configuration
const provider = getCloudProvider('aws');
console.log('Provider config:', provider);

// Test validation
const validation = validateCredentialData('aws', testCredentials);
console.log('Validation result:', validation);

// Check user permissions
const hasPermission = await roleService.userHasPermission(userId, 'cloud_credentials.view');
console.log('Has permission:', hasPermission);
```

## Performance Considerations

### Optimization Strategies

* **Lazy Loading**: Load provider configurations on demand
* **Caching**: Cache provider configurations in memory
* **Batch Operations**: Support bulk credential operations
* **Pagination**: Implement pagination for large credential lists

### Monitoring

* **API Response Times**: Monitor credential API performance
* **Encryption Overhead**: Track encryption/decryption performance
* **Database Queries**: Optimize credential lookup queries
* **Memory Usage**: Monitor provider configuration memory usage

## Future Enhancements

### Planned Features

* **Credential Sharing**: Share credentials between teams
* **Expiration Dates**: Set expiration dates for credentials
* **Usage Tracking**: Track which deployments use which credentials
* **Backup/Restore**: Export/import encrypted credential backups
* **Integration Testing**: Test credentials against actual providers

### Extension Points

* **Custom Providers**: Plugin system for custom cloud providers
* **Validation Plugins**: Custom validation rules for specific providers
* **Encryption Backends**: Support for different encryption systems
* **Audit Plugins**: Custom audit logging implementations
