#Requires -Version 5.1 <# .SYNOPSIS Initial database setup for ROA Oracle. .DESCRIPTION Performs initial database configuration including: - Validates Oracle installation - Auto-detects CDB vs non-CDB configuration - Configures DEFAULT_PROFILE (disables password expiry) - Configures sqlnet.ora for Instant Client 10/11 compatibility - Creates tablespace ROA - Creates user CONTAFIN_ORACLE with required privileges .PARAMETER OracleHome Oracle home directory. If not specified, auto-detects from registry or environment. .PARAMETER ServiceName Database service name. Auto-detects: ROA for non-CDB, XEPDB1 for Oracle XE CDB. .PARAMETER SystemPassword SYSTEM user password. Default: romfastsoft .PARAMETER ContafinPassword CONTAFIN_ORACLE user password. Default: ROMFASTSOFT .PARAMETER DatafileDir Directory for tablespace datafiles. Auto-detects if not specified. .PARAMETER TablespaceSize Initial size of ROA tablespace in MB. Default: 1000 .PARAMETER SkipSqlnetConfig Skip sqlnet.ora configuration. .EXAMPLE .\01-setup-database.ps1 .EXAMPLE .\01-setup-database.ps1 -ServiceName "XEPDB1" -SystemPassword "mypassword" .EXAMPLE .\01-setup-database.ps1 -OracleHome "C:\app\oracle\product\21c\dbhomeXE" -DatafileDir "D:\oradata" .NOTES File Name : 01-setup-database.ps1 Prerequisite : Oracle Database installed, PowerShell 5.1+ Copyright 2024 : ROMFAST #> [CmdletBinding()] param( [Parameter(Mandatory = $false)] [string]$OracleHome, [Parameter(Mandatory = $false)] [string]$ServiceName, [Parameter(Mandatory = $false)] [string]$DbHost, [Parameter(Mandatory = $false)] [int]$Port = 1521, [Parameter(Mandatory = $false)] [string]$SystemPassword = "romfastsoft", [Parameter(Mandatory = $false)] [string]$ContafinPassword = "ROMFASTSOFT", [Parameter(Mandatory = $false)] [string]$DatafileDir, [Parameter(Mandatory = $false)] [int]$TablespaceSize = 1000, [Parameter(Mandatory = $false)] [switch]$SkipSqlnetConfig ) $ErrorActionPreference = 'Stop' # Load config.ps1 if exists (provides defaults) $configPath = Join-Path (Split-Path $PSScriptRoot -Parent) "config.ps1" if (Test-Path $configPath) { . $configPath # Use config values if parameters not provided if (-not $OracleHome -and $ORACLE_HOME) { $OracleHome = $ORACLE_HOME } if (-not $ServiceName -and $SERVICE_NAME) { $ServiceName = $SERVICE_NAME } if (-not $DbHost -and $DB_HOST) { $DbHost = $DB_HOST } if (-not $Port -and $DB_PORT) { $Port = $DB_PORT } if ($SystemPassword -eq "romfastsoft" -and $SYSTEM_PASSWORD) { $SystemPassword = $SYSTEM_PASSWORD } if ($ContafinPassword -eq "ROMFASTSOFT" -and $CONTAFIN_PASSWORD) { $ContafinPassword = $CONTAFIN_PASSWORD } if (-not $DatafileDir -and $DATAFILE_DIR) { $DatafileDir = $DATAFILE_DIR } } # Source library functions . "$PSScriptRoot\lib\logging-functions.ps1" . "$PSScriptRoot\lib\oracle-functions.ps1" # Initialize logging $logPath = Join-Path $PSScriptRoot "..\logs\01-setup-database_$(Get-Date -Format 'yyyyMMdd_HHmmss').log" Initialize-LogFile -LogPath $logPath -ScriptName "01-setup-database.ps1" try { Write-LogSection "ROA Database Initial Setup" # Step 1: Validate Oracle installation Write-Log "Detecting Oracle installation..." $oraHome = Get-OracleHome -OracleHome $OracleHome Write-LogSuccess "Oracle Home: $oraHome" # Step 2: Auto-detect service name if not specified if (-not $ServiceName) { Write-Log "Auto-detecting service name..." # First try to connect to XE to check CDB status try { $version = Get-OracleVersion -OracleHome $oraHome -ServiceName "XE" -DbHost $DbHost -Port $Port -Password $SystemPassword if ($version.IsCDB) { $ServiceName = "XEPDB1" Write-Log "Detected CDB installation, using PDB: XEPDB1" } else { $ServiceName = "XE" Write-Log "Detected non-CDB installation, using service: XE" } } catch { # Try ROA as fallback try { $null = Test-OracleConnection -OracleHome $oraHome -ServiceName "ROA" -DbHost $DbHost -Port $Port -Password $SystemPassword $ServiceName = "ROA" Write-Log "Using existing service: ROA" } catch { $ServiceName = "XEPDB1" Write-Log "Defaulting to XEPDB1" } } } Write-LogSuccess "Service Name: $ServiceName" if ($DbHost) { Write-Log "Database Host: ${DbHost}:${Port}" } # Step 3: Test connection Write-Log "Testing database connection..." if (-not (Test-OracleConnection -OracleHome $oraHome -ServiceName $ServiceName -DbHost $DbHost -Port $Port -Password $SystemPassword)) { throw "Cannot connect to database. Please verify ServiceName, Host and SystemPassword." } Write-LogSuccess "Database connection successful" # Get version info $versionInfo = Get-OracleVersion -OracleHome $oraHome -ServiceName $ServiceName -DbHost $DbHost -Port $Port -Password $SystemPassword Write-Log "Oracle Version: $($versionInfo.Version)" Write-Log "Oracle Edition: $($versionInfo.Edition)" Write-Log "CDB Mode: $($versionInfo.IsCDB)" # Check container info $containerInfo = Test-PDB -OracleHome $oraHome -ServiceName $ServiceName -DbHost $DbHost -Port $Port -Password $SystemPassword Write-Log "Container: $($containerInfo.ContainerName)" if ($containerInfo.IsPDB) { Write-Log "Connected to PDB (Pluggable Database)" } elseif ($containerInfo.IsNonCDB) { Write-Log "Connected to non-CDB database" } # Step 4: Configure DEFAULT_PROFILE (no password expiry) Write-LogSection "Configuring DEFAULT_PROFILE" $profileSql = @" SET ECHO OFF FEEDBACK ON VERIFY OFF PROMPT Configuring DEFAULT_PROFILE - disabling password expiration... ALTER PROFILE DEFAULT LIMIT PASSWORD_LIFE_TIME UNLIMITED PASSWORD_GRACE_TIME UNLIMITED PASSWORD_REUSE_TIME UNLIMITED PASSWORD_REUSE_MAX UNLIMITED FAILED_LOGIN_ATTEMPTS UNLIMITED PASSWORD_LOCK_TIME UNLIMITED; COMMIT; SELECT 'PROFILE_CONFIGURED' FROM dual; EXIT; "@ $result = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName -DbHost $DbHost -Port $Port ` -Username "SYS" -Password $SystemPassword -SqlCommand $profileSql -AsSysdba if ($result -match "PROFILE_CONFIGURED") { Write-LogSuccess "DEFAULT_PROFILE configured successfully" } else { Write-LogWarning "Could not verify profile configuration" Write-LogDebug $result } # Step 5: Configure sqlnet.ora for old client compatibility if (-not $SkipSqlnetConfig) { Write-LogSection "Configuring sqlnet.ora" # Oracle 21c uses read-only Oracle Home - config goes to 'homes' directory # Check for Oracle 21c homes directory structure first $oraBase = Split-Path (Split-Path (Split-Path $oraHome -Parent) -Parent) -Parent $homesDir = Join-Path $oraBase "product\21c\homes" # Find the actual Oracle Base Home (where user configs go) $networkAdmin = $null if (Test-Path $homesDir) { # Oracle 21c with read-only Oracle Home $oraBaseHome = Get-ChildItem -Path $homesDir -Directory | Where-Object { $_.Name -match "OraDB" } | Select-Object -First 1 if ($oraBaseHome) { $networkAdmin = Join-Path $oraBaseHome.FullName "network\admin" Write-Log "Detected Oracle 21c read-only Home structure" Write-Log "Using Oracle Base Home: $($oraBaseHome.FullName)" } } # Fallback to traditional location if (-not $networkAdmin -or -not (Test-Path (Split-Path $networkAdmin -Parent))) { $networkAdmin = Join-Path $oraHome "network\admin" Write-Log "Using traditional Oracle Home network/admin location" } $sqlnetOra = Join-Path $networkAdmin "sqlnet.ora" if (-not (Test-Path -Path $networkAdmin)) { New-Item -ItemType Directory -Path $networkAdmin -Force | Out-Null } # Backup existing sqlnet.ora if (Test-Path -Path $sqlnetOra) { $backupPath = "$sqlnetOra.bak_$(Get-Date -Format 'yyyyMMdd_HHmmss')" Copy-Item -Path $sqlnetOra -Destination $backupPath -Force Write-Log "Backed up existing sqlnet.ora to $backupPath" } # Create sqlnet.ora with compatibility settings $sqlnetContent = @" # sqlnet.ora - ROA Oracle Configuration # Generated by 01-setup-database.ps1 on $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') # Allow connections from old Oracle Instant Client 10g/11g (ODBC drivers) # These clients don't support newer authentication methods SQLNET.ALLOWED_LOGON_VERSION_SERVER=8 SQLNET.ALLOWED_LOGON_VERSION_CLIENT=8 # Disable encryption requirement for old clients SQLNET.ENCRYPTION_SERVER = ACCEPTED SQLNET.CRYPTO_CHECKSUM_SERVER = ACCEPTED # Connection timeout settings SQLNET.INBOUND_CONNECT_TIMEOUT = 60 SQLNET.RECV_TIMEOUT = 30 SQLNET.SEND_TIMEOUT = 30 # TNS Names directory NAMES.DIRECTORY_PATH = (TNSNAMES, EZCONNECT) "@ Set-Content -Path $sqlnetOra -Value $sqlnetContent -Encoding ASCII Write-LogSuccess "sqlnet.ora configured at $sqlnetOra" Write-Log "Old client compatibility enabled (SQLNET.ALLOWED_LOGON_VERSION=8)" # Restart listener to apply changes Write-Log "Restarting listener to apply sqlnet.ora changes..." $lsnrctl = Join-Path $oraHome "bin\lsnrctl.exe" if (Test-Path $lsnrctl) { try { & $lsnrctl stop 2>&1 | Out-Null Start-Sleep -Seconds 3 $lsnrOutput = & $lsnrctl start 2>&1 Write-LogSuccess "Listener restarted successfully" # Wait for services to register Write-Log "Waiting for database services to register with listener..." Start-Sleep -Seconds 10 } catch { Write-LogWarning "Could not restart listener: $_" Write-Log "Please restart listener manually: lsnrctl stop && lsnrctl start" } } } else { Write-Log "Skipping sqlnet.ora configuration as requested" } # Step 6: Get datafile path if (-not $DatafileDir) { Write-Log "Auto-detecting datafile path..." $DatafileDir = Get-DatafilePath -OracleHome $oraHome -ServiceName $ServiceName -Password $SystemPassword } Write-LogSuccess "Datafile directory: $DatafileDir" # Step 7: Create tablespace ROA Write-LogSection "Creating Tablespace ROA" # Check if tablespace already exists $checkTsSql = @" SET PAGESIZE 0 FEEDBACK OFF VERIFY OFF HEADING OFF ECHO OFF SELECT 'TS_EXISTS' FROM dba_tablespaces WHERE tablespace_name = 'ROA'; EXIT; "@ $tsResult = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName -DbHost $DbHost -Port $Port ` -Username "SYSTEM" -Password $SystemPassword -SqlCommand $checkTsSql -Silent if ($tsResult -match "TS_EXISTS") { Write-LogWarning "Tablespace ROA already exists, skipping creation" } else { $datafilePath = Join-Path $DatafileDir "TS_ROA.DBF" $createTsSql = @" SET ECHO OFF FEEDBACK ON VERIFY OFF PROMPT Creating tablespace ROA... CREATE SMALLFILE TABLESPACE "ROA" DATAFILE '$datafilePath' SIZE ${TablespaceSize}M AUTOEXTEND ON NEXT 10M MAXSIZE UNLIMITED LOGGING EXTENT MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT AUTO; COMMIT; SELECT 'TS_CREATED' FROM dual; EXIT; "@ $result = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName -DbHost $DbHost -Port $Port ` -Username "SYSTEM" -Password $SystemPassword -SqlCommand $createTsSql if ($result -match "TS_CREATED") { Write-LogSuccess "Tablespace ROA created successfully" Write-Log "Datafile: $datafilePath" } else { Write-LogError "Failed to create tablespace ROA" Write-LogDebug $result throw "Tablespace creation failed" } } # Step 8: Create user CONTAFIN_ORACLE Write-LogSection "Creating User CONTAFIN_ORACLE" # Check if user already exists if (Test-OracleUser -OracleHome $oraHome -ServiceName $ServiceName ` -Password $SystemPassword -SchemaName "CONTAFIN_ORACLE") { Write-LogWarning "User CONTAFIN_ORACLE already exists" # Update password $updatePwdSql = @" SET ECHO OFF FEEDBACK ON VERIFY OFF ALTER USER CONTAFIN_ORACLE IDENTIFIED BY "$ContafinPassword"; COMMIT; SELECT 'PWD_UPDATED' FROM dual; EXIT; "@ $result = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName -DbHost $DbHost -Port $Port ` -Username "SYSTEM" -Password $SystemPassword -SqlCommand $updatePwdSql -Silent if ($result -match "PWD_UPDATED") { Write-Log "Password updated for CONTAFIN_ORACLE" } } else { $createUserSql = @" SET ECHO OFF FEEDBACK ON VERIFY OFF PROMPT Creating user CONTAFIN_ORACLE... CREATE USER CONTAFIN_ORACLE IDENTIFIED BY "$ContafinPassword" DEFAULT TABLESPACE ROA TEMPORARY TABLESPACE TEMP PROFILE DEFAULT; PROMPT Granting role privileges... GRANT CONNECT TO CONTAFIN_ORACLE; GRANT RESOURCE TO CONTAFIN_ORACLE; PROMPT Granting system privileges... GRANT CREATE ANY CONTEXT TO CONTAFIN_ORACLE; GRANT CREATE SESSION TO CONTAFIN_ORACLE; GRANT CREATE VIEW TO CONTAFIN_ORACLE; GRANT DELETE ANY TABLE TO CONTAFIN_ORACLE; GRANT DROP ANY CONTEXT TO CONTAFIN_ORACLE; GRANT EXECUTE ANY PROCEDURE TO CONTAFIN_ORACLE; GRANT INSERT ANY TABLE TO CONTAFIN_ORACLE; GRANT SELECT ANY DICTIONARY TO CONTAFIN_ORACLE; GRANT SELECT ANY SEQUENCE TO CONTAFIN_ORACLE; GRANT SELECT ANY TABLE TO CONTAFIN_ORACLE; GRANT UNLIMITED TABLESPACE TO CONTAFIN_ORACLE; GRANT UPDATE ANY TABLE TO CONTAFIN_ORACLE; GRANT CREATE PUBLIC SYNONYM TO CONTAFIN_ORACLE; GRANT DROP PUBLIC SYNONYM TO CONTAFIN_ORACLE; COMMIT; SELECT 'USER_CREATED' FROM dual; EXIT; "@ $result = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName -DbHost $DbHost -Port $Port ` -Username "SYSTEM" -Password $SystemPassword -SqlCommand $createUserSql if ($result -match "USER_CREATED") { Write-LogSuccess "User CONTAFIN_ORACLE created successfully" } else { Write-LogError "Failed to create user CONTAFIN_ORACLE" Write-LogDebug $result throw "User creation failed" } } # Verify user privileges $verifyUserSql = @" SET PAGESIZE 100 FEEDBACK OFF VERIFY OFF HEADING ON ECHO OFF LINESIZE 200 SELECT privilege FROM dba_sys_privs WHERE grantee = 'CONTAFIN_ORACLE' ORDER BY privilege; EXIT; "@ $privileges = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName -DbHost $DbHost -Port $Port ` -Username "SYSTEM" -Password $SystemPassword -SqlCommand $verifyUserSql -Silent Write-Log "CONTAFIN_ORACLE privileges verified" # Step 9: Create DMPDIR directory for Data Pump Write-LogSection "Creating Data Pump Directory" $dmpDir = "C:\DMPDIR" New-OracleDirectory -OracleHome $oraHome -ServiceName $ServiceName ` -Password $SystemPassword -DirectoryName "DMPDIR" -DirectoryPath $dmpDir Write-LogSuccess "Data Pump directory DMPDIR created: $dmpDir" # Step 10: Reset passwords with 10G verifier (required for old client auth) # After sqlnet.ora is configured, passwords must be reset to generate 10G hash if (-not $SkipSqlnetConfig) { Write-LogSection "Resetting Passwords for Old Client Compatibility" Write-Log "Resetting passwords to generate 10G password verifiers..." $resetPwdSql = @" SET ECHO OFF FEEDBACK ON VERIFY OFF -- Reset CONTAFIN_ORACLE password to generate 10G verifier ALTER USER CONTAFIN_ORACLE IDENTIFIED BY "$ContafinPassword"; -- Verify password versions SELECT USERNAME, PASSWORD_VERSIONS FROM DBA_USERS WHERE USERNAME = 'CONTAFIN_ORACLE'; SELECT 'PWD_RESET_DONE' FROM DUAL; EXIT; "@ $result = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName -DbHost $DbHost -Port $Port ` -Username "SYSTEM" -Password $SystemPassword -SqlCommand $resetPwdSql if ($result -match "PWD_RESET_DONE") { Write-LogSuccess "Password reset completed - 10G verifier now available" if ($result -match "10G") { Write-Log "Verified: Password has 10G verifier for old client compatibility" } } else { Write-LogWarning "Could not verify password reset" } } # Summary Write-LogSection "Setup Complete" Write-LogSuccess "Database initial setup completed successfully!" Write-Host "" Write-Log "Summary:" Write-Log " Oracle Home: $oraHome" Write-Log " Service Name: $ServiceName" Write-Log " Oracle Version: $($versionInfo.Version)" Write-Log " Container: $($containerInfo.ContainerName)" Write-Log " Tablespace ROA: $DatafileDir\TS_ROA.DBF" Write-Log " User: CONTAFIN_ORACLE" Write-Log " Data Pump Dir: DMPDIR -> $dmpDir" if (-not $SkipSqlnetConfig) { Write-Log " Old Client Auth: Enabled (sqlnet.ora + 10G verifier)" } Write-Host "" Write-Log "Next steps:" Write-Log " 1. Run 02-create-sys-objects.ps1 to install SYS objects" Write-Log " 2. Run 03-import-contafin.ps1 to import CONTAFIN_ORACLE schema" Close-LogFile -Success $true exit 0 } catch { Write-LogError "Setup failed: $_" Write-LogError $_.ScriptStackTrace Close-LogFile -Success $false exit 1 }