---
# System prepended metadata

title: HealthBridge AWS Identity Center Migration & Permissions Guide

---

# HealthBridge AWS Identity Center Migration & Permissions Guide

## Executive Summary

This guide outlines the migration from Okta IAM SAML Federation to AWS Identity Center while maintaining the multiple-tile Okta interface required by security. It includes comprehensive permission set definitions for all teams (Developers, DevOps, Data, Security, QA, Connect) with automated Slack-based access management.

## Current State vs Future State

```mermaid
graph TB
    subgraph "Current State: IAM SAML Federation"
        CO[Okta Login] --> CT[Multiple Account Tiles]
        CT --> CIAM[Shared IAM Roles:<br/>ManagementAccount-DevOps-Role<br/>ManagementAccount-Admins-Role<br/>etc.]
        CIAM --> CC[AWS Console]
        CIAM --> CPROB[PROBLEMS:<br/>- Dom adds S3 permission,<br/>Tim & Josh get it too<br/>- Manual IAM updates<br/>- No temp access<br/>- Poor audit trail]
        
        style CPROB fill:#ffebee,stroke:#c62828,color:#000
    end
    
    subgraph "Future State: Identity Center with Deep Links"
        FO[Okta Login] --> FT[Multiple Account Tiles<br/>Same UX]
        FT --> FIC[Identity Center<br/>Deep Links]
        FIC --> FPS[Individual Permission Sets:<br/>Dom: DevOps-PowerUser + S3-Admin<br/>Tim: DevOps-PowerUser + EC2-Admin<br/>Josh: DevOps-PowerUser + RDS-Admin]
        FPS --> FC[AWS Console]
        FPS --> FBEN[BENEFITS:<br/>- Individual permissions<br/>- Slack automation<br/>- Temp elevated access<br/>- Full audit trail]
        
        style FBEN fill:#c8e6c9,stroke:#2e7d32,color:#000
    end
    
    style CT fill:#fff9c4,stroke:#f9a825,color:#000
    style FT fill:#e3f2fd,stroke:#1565c0,color:#000
```

## Permission Philosophy

### Account Classification
```mermaid
graph TD
    subgraph "High Security Accounts"
        PROD[Production<br/>065532173824<br/>Restricted Access]
        MIRROR[Production-Mirror<br/>068217805200<br/>Restricted Access]
    end
    
    subgraph "Standard Security Accounts"
        DEV[Development<br/>658413592781<br/>Permissive Access]
        STAGING[Staging<br/>844077369820<br/>Permissive Access]
        TEST[Test<br/>035966626420<br/>Permissive Access]
    end
    
    subgraph "Administrative Account"
        MGMT[Management<br/>087797848983<br/>Organization Control]
    end
    
    style PROD fill:#ffcdd2,stroke:#c62828,color:#000
    style MIRROR fill:#ffcdd2,stroke:#c62828,color:#000
    style DEV fill:#c8e6c9,stroke:#2e7d32,color:#000
    style STAGING fill:#fff9c4,stroke:#f9a825,color:#000
    style TEST fill:#e1f5fe,stroke:#01579b,color:#000
    style MGMT fill:#f3e5f5,stroke:#6a1b9a,color:#000
```

### Core Principle
- **Production/Mirror**: Read-only by default, no database access for developers, time-limited elevated access
- **Dev/Staging/Test**: Power-user access with guardrails, self-service deployments

## Permission Sets by Team

### Developer Permission Sets
| Permission Set | Production/Mirror | Dev/Staging/Test | Duration | Approval |
|---------------|------------------|------------------|----------|----------|
| **Developer-Prod-ReadOnly** | ✅ View Beanstalk, logs, S3 | - | 12 hours | Auto |
| **Developer-Prod-Deploy** | 🕐 Deploy code only | - | 2 hours | Manager |
| **Developer-NonProd-Standard** | - | ✅ Full Beanstalk, limited RDS | 12 hours | Auto |
| **Developer-NonProd-Admin** | - | 🕐 Full control | 4 hours | Manager |

**Key Protection**: NO database access in production/mirror accounts

### DevOps Permission Sets
| Permission Set | Scope | Duration | Approval |
|---------------|-------|----------|----------|
| **DevOps-PowerUser** | Everything except IAM/Org/Billing | 8 hours | Auto |
| **DevOps-Infrastructure** | + VPC, Direct Connect, Transit Gateway | 4 hours | Manager |
| **DevOps-Security** | + WAF, Security Groups, Shield | 4 hours | Manager |
| **DevOps-BreakGlass** | AdministratorAccess | 30 min | 2-person |

### Data Team Permission Sets
| Permission Set | Production/Mirror | Dev/Staging/Test | Duration | Approval |
|---------------|------------------|------------------|----------|----------|
| **DataScientist-Prod** | 👁️ SageMaker endpoints, S3 read | - | 8 hours | Auto |
| **DataScientist-NonProd** | - | ✅ Full SageMaker, training | 12 hours | Auto |
| **DataEngineer-Prod** | 👁️ Kinesis/Glue read-only | - | 4 hours | Manager |
| **DataEngineer-NonProd** | - | ✅ Full pipeline control | 12 hours | Auto |
| **DataAnalyst-Prod** | 👁️ Query-only access | - | 12 hours | Auto |

### Security Team Permission Sets
| Permission Set | Scope | Duration | Approval |
|---------------|-------|----------|----------|
| **Security-Auditor** | Read everything, all accounts | 12 hours | Auto |
| **Security-Incident** | Isolate resources, block IPs | 4 hours | Security Lead |
| **Security-Admin** | Manage GuardDuty, Security Hub | 8 hours | Manager |

### QA Team Permission Sets
| Permission Set | Scope | Duration | Approval |
|---------------|-------|----------|----------|
| **QA-Tester** | Read/test in Test/Staging | 8 hours | Auto |
| **QA-Engineer** | Deploy test environments | 4 hours | Manager |

### Connect Team Permission Sets
| Permission Set | Production/Mirror | Dev/Staging/Test | Duration | Approval |
|---------------|------------------|------------------|----------|----------|
| **Connect-Developer-Prod** | 👁️ View flows, metrics | - | 8 hours | Auto |
| **Connect-Developer-NonProd** | - | ✅ Full development | 12 hours | Auto |
| **Connect-Admin-Prod** | 🕐 Emergency fixes only | - | 2 hours | Manager |
| **Connect-Admin-NonProd** | - | ✅ Full admin | 8 hours | Manager |

## Okta Tile Configuration with Deep Links

### Actual Tiles Based on Permission Sets

```mermaid
graph LR
    subgraph "Okta Dashboard Tiles"
        subgraph "Production Access"
            T1[🔴 Prod - DevOps Power<br/>DevOps Team]
            T2[🟡 Prod - Developer Read<br/>All Developers]
            T3[🟡 Prod - Data Query<br/>Data Analysts]
            T4[🔴 Prod - Emergency Deploy<br/>On-Demand]
        end
        
        subgraph "Non-Production Access"
            T5[🟢 Dev - Developer<br/>All Developers]
            T6[🟢 Dev - DevOps<br/>DevOps Team]
            T7[🟢 Dev - Data Engineer<br/>Data Team]
            T8[🟢 Test - QA Full<br/>QA Team]
        end
        
        subgraph "Administrative Access"
            T9[🔵 Mgmt - Security Audit<br/>Security Team]
            T10[🔵 Mgmt - DevOps Admin<br/>DevOps Team]
        end
        
        subgraph "Connect Access"
            T11[🟡 Prod - Connect View<br/>Connect Team]
            T12[🟢 Dev - Connect Build<br/>Connect Developers]
        end
    end
    
    style T1 fill:#ffcdd2,stroke:#c62828,color:#000
    style T2 fill:#fff9c4,stroke:#f9a825,color:#000
    style T3 fill:#fff9c4,stroke:#f9a825,color:#000
    style T4 fill:#ffcdd2,stroke:#c62828,color:#000
    style T5 fill:#c8e6c9,stroke:#2e7d32,color:#000
    style T6 fill:#c8e6c9,stroke:#2e7d32,color:#000
    style T7 fill:#c8e6c9,stroke:#2e7d32,color:#000
    style T8 fill:#c8e6c9,stroke:#2e7d32,color:#000
    style T9 fill:#e3f2fd,stroke:#1565c0,color:#000
    style T10 fill:#e3f2fd,stroke:#1565c0,color:#000
    style T11 fill:#fff9c4,stroke:#f9a825,color:#000
    style T12 fill:#c8e6c9,stroke:#2e7d32,color:#000
```

### Deep Link Configuration Examples

```javascript
// Okta Bookmark App Configuration for Real Permission Sets
const tiles = [
  // Production Tiles
  {
    name: "AWS Prod - DevOps Power",
    url: buildDeepLink("065532173824", "ps-devops-poweruser"),
    icon: "aws-red-gear.svg",
    color: "#D32F2F",
    groups: ["AWS-DevOps-Team"],
    description: "DevOps PowerUser access to production"
  },
  {
    name: "AWS Prod - Developer Read",
    url: buildDeepLink("065532173824", "ps-developer-prod-readonly"),
    icon: "aws-yellow-eye.svg",
    color: "#FFA000",
    groups: ["AWS-Developers", "AWS-DevOps-Team"],
    description: "Read-only access to production resources"
  },
  {
    name: "AWS Prod - Data Query",
    url: buildDeepLink("065532173824", "ps-dataanalyst-prod"),
    icon: "aws-yellow-chart.svg",
    color: "#FFA000",
    groups: ["AWS-Data-Team"],
    description: "Query-only access to production data"
  },
  
  // Development Tiles
  {
    name: "AWS Dev - Developer Full",
    url: buildDeepLink("658413592781", "ps-developer-nonprod-standard"),
    icon: "aws-green-code.svg",
    color: "#388E3C",
    groups: ["AWS-Developers"],
    description: "Full development access"
  },
  {
    name: "AWS Dev - Data Engineer",
    url: buildDeepLink("658413592781", "ps-dataengineer-nonprod"),
    icon: "aws-green-pipeline.svg",
    color: "#388E3C",
    groups: ["AWS-Data-Engineers"],
    description: "Data pipeline development"
  },
  
  // Connect Tiles
  {
    name: "AWS Prod - Connect View",
    url: buildDeepLink("065532173824", "ps-connect-developer-prod"),
    icon: "aws-yellow-phone.svg",
    color: "#FFA000",
    groups: ["AWS-Connect-Team"],
    description: "View Connect flows and metrics"
  },
  {
    name: "AWS Dev - Connect Build",
    url: buildDeepLink("658413592781", "ps-connect-developer-nonprod"),
    icon: "aws-green-phone.svg",
    color: "#388E3C",
    groups: ["AWS-Connect-Developers"],
    description: "Build and test contact flows"
  },
  
  // Management Account
  {
    name: "AWS Mgmt - Security Audit",
    url: buildDeepLink("087797848983", "ps-security-auditor"),
    icon: "aws-blue-shield.svg",
    color: "#1976D2",
    groups: ["AWS-Security-Team"],
    description: "Security audit access"
  }
];

function buildDeepLink(accountId, permissionSetId) {
  const baseUrl = "https://d-9267a80d73.awsapps.com/start";
  const instanceId = "790720f893d1c6d2";
  
  return `${baseUrl}#/saml/custom/${instanceId}/accounts/${accountId}/permission-sets/${permissionSetId}`;
}
```

## Slack Automation Implementation

### Access Request Flow

```mermaid
graph TD
    subgraph "Slack Request Flow"
        U[User: /aws-access request] --> FORM[Select:<br/>- Account<br/>- Permission Set<br/>- Duration<br/>- Reason]
        FORM --> RISK{Risk Assessment}
        
        RISK -->|Low Risk| AUTO[Auto-Approve:<br/>- Developer-Prod-ReadOnly<br/>- Security-Auditor<br/>- Connect-Developer-Prod]
        
        RISK -->|Medium Risk| MGR[Manager Approval:<br/>- Developer-Prod-Deploy<br/>- DataEngineer-Prod<br/>- Connect-Admin-Prod]
        
        RISK -->|High Risk| SEC[Security Approval:<br/>- DevOps-BreakGlass<br/>- Security-Incident]
        
        AUTO --> GRANT[Grant Access]
        MGR -->|Approved| GRANT
        SEC -->|Approved| GRANT
        
        GRANT --> EXPIRE[Auto-Expire<br/>After Duration]
    end
    
    style U fill:#e3f2fd,stroke:#1565c0,color:#000
    style AUTO fill:#c8e6c9,stroke:#2e7d32,color:#000
    style MGR fill:#fff9c4,stroke:#f9a825,color:#000
    style SEC fill:#ffcdd2,stroke:#c62828,color:#000
```

### Slack Bot Permission Logic

```python
# Lambda Function: Real Permission Set Handler
import boto3
import json
from datetime import datetime, timedelta

# Permission set configuration based on our design
PERMISSION_SETS = {
    'Developer-Prod-ReadOnly': {
        'risk': 'LOW',
        'max_duration': 12,
        'auto_approve': True,
        'accounts': ['065532173824', '068217805200']  # Prod & Mirror
    },
    'Developer-Prod-Deploy': {
        'risk': 'MEDIUM',
        'max_duration': 2,
        'requires': 'manager',
        'accounts': ['065532173824', '068217805200']
    },
    'Developer-NonProd-Standard': {
        'risk': 'LOW',
        'max_duration': 12,
        'auto_approve': True,
        'accounts': ['658413592781', '844077369820', '035966626420']  # Dev, Staging, Test
    },
    'DevOps-PowerUser': {
        'risk': 'MEDIUM',
        'max_duration': 8,
        'auto_approve': True,
        'accounts': 'ALL'
    },
    'DevOps-BreakGlass': {
        'risk': 'CRITICAL',
        'max_duration': 0.5,  # 30 minutes
        'requires': ['manager', 'security'],
        'mfa_required': True,
        'accounts': 'ALL'
    },
    'DataAnalyst-Prod': {
        'risk': 'LOW',
        'max_duration': 12,
        'auto_approve': True,
        'accounts': ['065532173824', '068217805200']
    },
    'DataEngineer-Prod': {
        'risk': 'MEDIUM',
        'max_duration': 4,
        'requires': 'data-lead',
        'accounts': ['065532173824', '068217805200']
    },
    'Security-Auditor': {
        'risk': 'LOW',
        'max_duration': 12,
        'auto_approve': True,
        'accounts': 'ALL'
    },
    'Security-Incident': {
        'risk': 'HIGH',
        'max_duration': 4,
        'requires': 'security-lead',
        'auto_extend': True,
        'accounts': 'ALL'
    },
    'Connect-Developer-Prod': {
        'risk': 'LOW',
        'max_duration': 8,
        'auto_approve': True,
        'accounts': ['065532173824', '068217805200']
    },
    'Connect-Admin-Prod': {
        'risk': 'MEDIUM',
        'max_duration': 2,
        'requires': 'manager',
        'blackout_hours': '8-12,13-17',  # Business hours EST
        'accounts': ['065532173824', '068217805200']
    }
}

def handle_access_request(event, context):
    """Process Slack access request based on real permission sets"""
    
    payload = json.loads(event['body'])
    user_email = payload['user']['email']
    permission_set = payload['submission']['permission_set']
    account_id = payload['submission']['account']
    reason = payload['submission']['reason']
    duration = float(payload['submission']['duration'])
    
    # Validate permission set exists
    if permission_set not in PERMISSION_SETS:
        return error_response(f"Unknown permission set: {permission_set}")
    
    ps_config = PERMISSION_SETS[permission_set]
    
    # Validate account access
    if ps_config['accounts'] != 'ALL':
        if account_id not in ps_config['accounts']:
            return error_response(f"{permission_set} not available for this account")
    
    # Validate duration
    if duration > ps_config['max_duration']:
        return error_response(f"Max duration is {ps_config['max_duration']} hours")
    
    # Check blackout windows for Connect-Admin-Prod
    if 'blackout_hours' in ps_config:
        if is_blackout_period(ps_config['blackout_hours']):
            return request_exception_approval(user_email, permission_set, "Blackout period")
    
    # Process based on risk level
    if ps_config.get('auto_approve'):
        grant_access(user_email, account_id, permission_set, duration)
        notify_slack(f"✅ Auto-approved: {user_email} granted {permission_set} "
                    f"to {get_account_name(account_id)} for {duration} hours")
    else:
        create_approval_request(user_email, account_id, permission_set, 
                              duration, reason, ps_config.get('requires'))
        notify_slack(f"⏳ Approval pending for {user_email}: {permission_set}")
    
    return success_response()
```

### Slack Commands

```yaml
/aws-access list:
  description: "Show your current AWS access"
  response: |
    Your current AWS access:
    • Production (065532173824): Developer-Prod-ReadOnly - Expires in 4h
    • Development (658413592781): Developer-NonProd-Standard - Expires in 8h

/aws-access request:
  description: "Request AWS access"
  form_fields:
    - Account: [Production, Development, Staging, Test, Management]
    - Permission Set: [Dynamically filtered based on your team]
    - Duration: [1h, 2h, 4h, 8h, 12h]
    - Reason: [Free text, required for audit]

/aws-access extend [account]:
  description: "Extend existing access"
  rules:
    - Can only extend if <2 hours remaining
    - Cannot exceed original max duration
    - Requires re-approval for elevated permissions

/aws-access emergency:
  description: "Emergency break-glass access"
  requirements:
    - Triggers PagerDuty
    - Requires incident ticket
    - Creates audit event
    - Maximum 30 minutes
```

## Migration Execution Plan

### Phase 1: Foundation Setup

```bash
#!/bin/bash
# Create core permission sets first

# Developer permission sets
aws sso-admin create-permission-set \
  --instance-arn $INSTANCE_ARN \
  --name "Developer-Prod-ReadOnly" \
  --description "Read-only access to production resources" \
  --session-duration "PT12H"

aws sso-admin create-permission-set \
  --instance-arn $INSTANCE_ARN \
  --name "Developer-NonProd-Standard" \
  --description "Standard developer access to non-production" \
  --session-duration "PT12H"

# DevOps permission sets  
aws sso-admin create-permission-set \
  --instance-arn $INSTANCE_ARN \
  --name "DevOps-PowerUser" \
  --description "DevOps power user access" \
  --session-duration "PT8H"

# Attach policies
aws sso-admin put-inline-policy-to-permission-set \
  --instance-arn $INSTANCE_ARN \
  --permission-set-arn $PS_ARN \
  --inline-policy file://policies/developer-prod-readonly.json
```

### Phase 2: User Migration Matrix

| Current IAM Role | Users | New Permission Set Assignments |
|-----------------|-------|--------------------------------|
| ManagementAccount-DevOps-Role | Dom, Tim, Josh | DevOps-PowerUser (base) + Individual adds |
| → Dom specifically | | + S3-Admin permission set |
| → Tim specifically | | + EC2-Admin permission set |
| → Josh specifically | | + RDS-Admin permission set |
| ManagementAccount-Developers-Role | 5 users | Developer-Prod-ReadOnly + Developer-NonProd-Standard |
| ManagementAccount-Security-Role | 3 users | Security-Auditor (base) |
| ManagementAccount-Admins-Role | 2 users | Removed, use DevOps-BreakGlass on-demand |

### Phase 3: Parallel Running

```mermaid
graph LR
    subgraph Phase1["Week 1-2: Both Systems Active"]
        OLD["Old IAM Tiles<br/>Marked as OLD"]
        NEW["New Identity Center Tiles<br/>Marked as NEW"]
        BOTH[Both Available]
    end
    
    subgraph Phase2["Week 3-4: Validation"]
        TEST[Pilot Users Test]
        MONITOR[Monitor Usage]
        ADJUST[Adjust Permissions]
    end
    
    subgraph Phase3["Week 5+: Cutover"]
        DISABLE[Disable Old Tiles]
        REMOVE[Remove IAM Roles]
        COMPLETE[Migration Complete]
    end
    
    OLD --> TEST
    NEW --> TEST
    TEST --> MONITOR
    MONITOR --> ADJUST
    ADJUST --> DISABLE
    DISABLE --> REMOVE
    REMOVE --> COMPLETE
    
    style OLD fill:#ffccbc,stroke:#d84315,color:#000
    style NEW fill:#c8e6c9,stroke:#2e7d32,color:#000
```

## Success Metrics

```yaml
Technical Metrics:
  - Authentication success rate: >99.9%
  - Time to grant access via Slack: <2 minutes (auto), <10 minutes (approval)
  - Permission sets in use: Track actual vs assigned

Security Metrics:
  - Standing privilege reduction: Target 80% reduction
  - Time-bound access percentage: >60% of all access
  - Audit compliance: 100% tracked in CloudTrail + DynamoDB

User Experience:
  - Tile clicks to console: Still 1 click (maintained)
  - Access request satisfaction: >90%
  - Support tickets: -50% reduction expected

Operational:
  - Manual IAM changes: -95% reduction
  - Individual vs shared permissions: 100% individual
  - Permission reviews: Automated weekly
```

## Rollback Plan

```bash
#!/bin/bash
# Emergency rollback procedure

echo "=== EMERGENCY ROLLBACK INITIATED ==="

# 1. Re-enable old IAM federation tiles in Okta
echo "Step 1: Reactivate old AWS IAM tiles in Okta"
echo "  Navigate to Okta Admin > Applications > Inactive"
echo "  Reactivate all 'OLD-AWS-*' applications"

# 2. Notify all users
curl -X POST $SLACK_WEBHOOK \
  -d '{"text":"🚨 Reverting to old AWS access. Use original tiles (not NEW- prefix)."}'

# 3. Verify IAM roles still exist
for role in ManagementAccount-DevOps-Role ManagementAccount-Admins-Role; do
  aws iam get-role --role-name $role
done

# 4. Keep Identity Center active but unused
echo "Identity Center remains configured for retry"

echo "=== ROLLBACK COMPLETE ==="
```

## Appendix: Permission Set Details

### Complete Permission Set Inventory

| Permission Set | Risk | Max Duration | Auto-Approve | Approval Required | Accounts |
|---------------|------|--------------|---------------|-------------------|----------|
| Developer-Prod-ReadOnly | Low | 12h | ✅ | - | Prod/Mirror |
| Developer-Prod-Deploy | Medium | 2h | ❌ | Manager | Prod/Mirror |
| Developer-NonProd-Standard | Low | 12h | ✅ | - | Dev/Stage/Test |
| Developer-NonProd-Admin | Medium | 4h | ❌ | Manager | Dev/Stage/Test |
| DevOps-PowerUser | Medium | 8h | ✅ | - | All |
| DevOps-Infrastructure | Medium | 4h | ❌ | Manager | All |
| DevOps-Security | Medium | 4h | ❌ | Manager | All |
| DevOps-BreakGlass | Critical | 30m | ❌ | Manager + Security | All |
| DataScientist-Prod | Low | 8h | ✅ | - | Prod/Mirror |
| DataScientist-NonProd | Low | 12h | ✅ | - | Dev/Stage/Test |
| DataEngineer-Prod | Medium | 4h | ❌ | Data Lead | Prod/Mirror |
| DataEngineer-NonProd | Low | 12h | ✅ | - | Dev/Stage/Test |
| DataAnalyst-Prod | Low | 12h | ✅ | - | Prod/Mirror |
| Security-Auditor | Low | 12h | ✅ | - | All |
| Security-Incident | High | 4h | ❌ | Security Lead | All |
| Security-Admin | Medium | 8h | ❌ | Manager | Management |
| QA-Tester | Low | 8h | ✅ | - | Stage/Test |
| QA-Engineer | Medium | 4h | ❌ | QA Lead | Stage/Test |
| Connect-Developer-Prod | Low | 8h | ✅ | - | Prod/Mirror |
| Connect-Developer-NonProd | Low | 12h | ✅ | - | Dev/Stage/Test |
| Connect-Admin-Prod | Medium | 2h | ❌ | Manager | Prod/Mirror |
| Connect-Admin-NonProd | Medium | 8h | ❌ | Manager | Dev/Stage/Test |

### Production Access Quick Reference

| Team | Read Access | Write Access | Database | Approval |
|------|------------|--------------|----------|----------|
| **Developers** | ✅ Beanstalk, CloudWatch | 🕐 Deploy only (2hr) | ❌ None | Manager |
| **DevOps** | ✅ Everything | ✅ Everything except IAM | ✅ Full | None/2-person |
| **Data** | ✅ S3, endpoints | ❌ None | 🕐 Read-only | Auto/Manager |
| **Security** | ✅ Everything | 🕐 Incident (4hr) | ✅ Read | Auto/Security |
| **QA** | 👁️ Monitoring | ❌ None | ❌ None | N/A |
| **Connect** | ✅ View flows | 🕐 Emergency (2hr) | ❌ None | Manager |

This migration guide now incorporates your complete permission strategy while maintaining focus on the migration process and automation.