modules/Definitions/Aws.Entro.psm1

Set-StrictMode -Version Latest

function Get-EntroAwsTemplatePath {
    param(
        [ValidateSet('Default', 'Europe')]
        [string]$Region = 'Default'
    )
    Import-Module (Join-Path (Split-Path $PSScriptRoot -Parent) 'IW.EntroCatalog.psm1') -Force -WarningAction SilentlyContinue
    $base = Join-Path (Get-EntroConnectSkillRoot) 'integrations/amazon-web-services'
    if ($Region -eq 'Europe') {
        return Join-Path $base 'Entro Security AWS Template - Europe region.json'
    }
    Join-Path $base 'Entro Security AWS Template.json'
}

function Get-EntroAwsCloudFormationStackName {
    param([Parameter(Mandatory)][string]$ExternalId)
    $safe = ($ExternalId -replace '[^A-Za-z0-9-]', '-').Trim('-')
    if (-not $safe) { $safe = 'account' }
    $name = "Entro-$safe"
    if ($name.Length -gt 128) { $name = $name.Substring(0, 128).TrimEnd('-') }
    return $name
}

function Get-EntroAwsCloudFormationProbeResult {
    param([string]$StackStatus)
    $status = if ($StackStatus) { $StackStatus.Trim() } else { '' }
    if (-not $status -or $status -eq 'None') { return 'Create' }
    if ($status -in @('CREATE_COMPLETE', 'UPDATE_COMPLETE')) { return 'Skip' }
    if ($status -like '*IN_PROGRESS') { return 'Skip' }
    return 'Update'
}

function Get-EntroAwsWizardWorkDirectory {
    param([hashtable]$Context)
    $base = if ($Context['OutputDirectory']) { $Context['OutputDirectory'] } else { Get-Location }
    Join-Path $base 'entro-aws'
}

function Get-EntroAwsRoleArn {
    param([hashtable]$Context)
    if ($Context['EntroRoleArn']) { return [string]$Context['EntroRoleArn'] }
    $rn = if ($Context['EntroRoleName']) { $Context['EntroRoleName'] } else { 'EntroReadOnly' }
    $arn = aws iam get-role --role-name $rn --query Role.Arn --output text 2>$null
    if ($LASTEXITCODE -ne 0 -or [string]::IsNullOrWhiteSpace([string]$arn)) { return $null }
    $Context['EntroRoleArn'] = ([string]$arn).Trim()
    return $Context['EntroRoleArn']
}

function Get-EntroAwsHandoffStep {
    param([hashtable]$Context)
    $method = if ($Context['Method']) { $Context['Method'] } else { 'AssumeRole' }
    $rn = if ($Context['EntroRoleName']) { $Context['EntroRoleName'] } else { 'EntroReadOnly' }
    $manual = switch ($method) {
        'CloudFormation' { 'The wizard deployed the Entro CloudFormation stack, and the stack notifies Entro. In Entro, confirm the AWS account appears under Accounts.' }
        'Terraform' { 'Apply Terraform-Entro.tf from the Entro AWS integration folder, then add the account in Entro (Add account, AWS) with the Role ARN it outputs.' }
        default { "In Entro, Add account, AWS, Assume Role: paste the Role ARN of $rn (printed at the end of this run) and an Environment name." }
    }
    @{
        Id     = 'entro-handoff'
        Title  = 'Register in Entro UI'
        Kind   = 'Manual'
        Manual = $manual
    }
}

function Register-AwsEntroDefinitions {
    Register-IntegrationWizardDefinition @{
        Id           = 'aws-entro'
        Platform     = 'AWS'
        Product      = 'Entro'
        CoreSwitch   = 'Entro'
        CliName      = 'aws'
        Title        = 'Entro AWS integration'
        FolderName   = 'Entro AWS'
        AccessLevels = @()
        AdminRoles   = @('IAM policy and role management')
        OutputsHelp  = 'Paste Environment label and AWS Role ARN into the Entro admin console (Add account → AWS).'
        Inputs       = @(
            @{ Name = 'EntroExternalId'; Source = 'Supply'; Prompt = 'Entro External ID from the wizard'; Purpose = 'IAM trust ExternalId for Entro'; Required = $true }
            @{ Name = 'Method'; Source = 'Supply'; Prompt = 'Integration method'; Purpose = 'How Entro connects'; Required = $true; ValidateSet = @('AssumeRole', 'CloudFormation', 'Terraform'); Default = 'AssumeRole' }
            @{ Name = 'EntroTemplateRegion'; Source = 'Supply'; Prompt = 'Entro template region'; Purpose = 'Default vs Europe SNS region'; Required = $false; ValidateSet = @('Default', 'Europe'); Default = 'Default' }
            @{ Name = 'EntroRoleName'; Source = 'Supply'; Prompt = 'Entro IAM role name'; Purpose = 'Entro read role'; Required = $false; Default = 'EntroReadOnly' }
            @{ Name = 'OutputDirectory'; Source = 'Supply'; Prompt = 'Output directory'; Purpose = 'Wizard output directory'; Required = $false }
        )
        Steps        = {
            param($ctx)
            @(
                @{
                    Id    = 'entro-trust'
                    Title = 'Create Entro trust role and read policy'
                    Kind  = 'Ensure'
                    Probe = {
                        param($c)
                        $method = if ($c['Method']) { $c['Method'] } else { 'AssumeRole' }
                        if ($method -eq 'Terraform') { return 'Skip' }
                        if ($method -eq 'CloudFormation') {
                            if ([string]::IsNullOrWhiteSpace([string]$c['EntroExternalId'])) { return 'Create' }
                            $stack = Get-EntroAwsCloudFormationStackName -ExternalId ([string]$c['EntroExternalId'])
                            $region = if ($c['Region']) { $c['Region'] } else { 'us-east-1' }
                            $status = aws cloudformation describe-stacks --stack-name $stack --region $region --query 'Stacks[0].StackStatus' --output text 2>$null
                            if ($LASTEXITCODE -ne 0) { return 'Create' }
                            return Get-EntroAwsCloudFormationProbeResult -StackStatus ([string]$status)
                        }
                        $rn = if ($c['EntroRoleName']) { $c['EntroRoleName'] } else { 'EntroReadOnly' }
                        $exists = aws iam get-role --role-name $rn 2>$null
                        if ($LASTEXITCODE -eq 0) { return 'Skip' }
                        'Create'
                    }
                    Run   = {
                        param($c)
                        $method = if ($c['Method']) { $c['Method'] } else { 'AssumeRole' }
                        if ($method -eq 'Terraform') {
                            Write-Info 'Terraform method: use Entro Terraform-Entro.tf in the Entro AWS integration folder.'
                            return
                        }
                        $modRoot = Join-Path (Split-Path (Split-Path $PSScriptRoot -Parent) -Parent) 'modules'
                        Import-Module (Join-Path $modRoot 'ISC.EntroAws.psm1') -Force
                        $tplRegion = if ($c['EntroTemplateRegion']) { $c['EntroTemplateRegion'] } else { 'Default' }
                        $tpl = Get-EntroAwsTemplatePath -Region $tplRegion
                        $work = Get-EntroAwsWizardWorkDirectory -Context $c
                        $rn = if ($c['EntroRoleName']) { $c['EntroRoleName'] } else { 'EntroReadOnly' }
                        if ($method -eq 'CloudFormation') {
                            $stack = Get-EntroAwsCloudFormationStackName -ExternalId ([string]$c['EntroExternalId'])
                            $region = if ($c['Region']) { $c['Region'] } else { 'us-east-1' }
                            Invoke-EntroAwsCloudFormationDeploy -TemplatePath $tpl -StackName $stack `
                                -ExternalId $c['EntroExternalId'] -Region $region | Out-Null
                        }
                        else {
                            $c['EntroRoleArn'] = Invoke-EntroAwsAssumeRoleSetup -EntroExternalId $c['EntroExternalId'] -RoleName $rn `
                                -TemplatePath $tpl -WorkDirectory $work
                        }
                    }
                    BuildScript = {
                        param($c)
                        $method = if ($c['Method']) { $c['Method'] } else { 'AssumeRole' }
                        if ($method -eq 'Terraform') {
                            return '# Use Entro Terraform-Entro.tf from the Entro AWS integration catalog.'
                        }
                        $tplRegion = if ($c['EntroTemplateRegion']) { $c['EntroTemplateRegion'] } else { 'Default' }
                        $rn = if ($c['EntroRoleName']) { $c['EntroRoleName'] } else { 'EntroReadOnly' }
                        $work = (Get-EntroAwsWizardWorkDirectory -Context $c) -replace "'", "''"
                        @"
Import-Module (Join-Path `$PSScriptRoot 'modules/ISC.EntroAws.psm1') -Force
Import-Module (Join-Path `$PSScriptRoot 'modules/Definitions/Aws.Entro.psm1') -Force
`$tpl = Get-EntroAwsTemplatePath -Region '$tplRegion'
`$work = '$work'
Invoke-EntroAwsAssumeRoleSetup -EntroExternalId '$($c['EntroExternalId'])' -RoleName '$rn' -TemplatePath `$tpl -WorkDirectory `$work
"@

                    }
                }
                (Get-EntroAwsHandoffStep -Context $ctx)
            )
        }
        OnRunComplete = {
            param($ctx)
            $method = if ($ctx['Method']) { $ctx['Method'] } else { 'AssumeRole' }
            Write-Host ''
            Write-Host 'Entro handoff' -ForegroundColor Cyan
            Write-Host ' Environment: (your label)'
            Write-Host " External ID: $($ctx['EntroExternalId'])"
            if ($method -eq 'CloudFormation') {
                $tplRegion = if ($ctx['EntroTemplateRegion']) { $ctx['EntroTemplateRegion'] } else { 'Default' }
                Write-Host " Template: $(Get-EntroAwsTemplatePath -Region $tplRegion)"
            }
            elseif ($method -eq 'AssumeRole') {
                $arn = Get-EntroAwsRoleArn -Context $ctx
                Write-Host " Role ARN: $(if ($arn) { $arn } else { '(not found; run aws iam get-role)' })"
            }
            Write-Host ''
        }
    }
}

Export-ModuleMember -Function Register-AwsEntroDefinitions, Get-EntroAwsTemplatePath, Get-EntroAwsCloudFormationStackName, Get-EntroAwsCloudFormationProbeResult