Exporting Oracle OCI Compute Instances to CSV

When running an Oracle OCI scan in DMC, you must provide a list of compute instances that DMC will connect to.
Unlike VMware (vCenter integration), DMC cannot directly enumerate OCI compute instances.
Instead, you must generate a CSV of IPs/FQDNs + OS type for bulk import.

This guide provides PowerShell helper scripts using Oracle's official OCI.PSModules to export OCI compute instances into a DMC-ready CSV file.

Why this is needed

  • DMC has no native Oracle OCI integration today.
  • You must supply compute instance endpoints explicitly.
  • The CSV export makes it easy to bulk load these into DMC.

Requirements

Before running the export script, ensure you have the following:

Oracle OCI Access - OCI account with appropriate compute instance enumeration permissions - Compartment access to the resources you want to inventory - API key configured with proper permissions - Network connectivity to OCI services

PowerShell Environment - PowerShell 5.1 or later (PowerShell 7+ recommended) - Execution policy allowing script execution (RemoteSigned, Unrestricted, or Bypass) - Internet access for module installation from PowerShell Gallery - Write access to the output directory for CSV export

Required PowerShell Modules - OCI.PSModules (automatically installs all required OCI modules) - OCI.PSModules.Common (for configuration management) - OCI.PSModules.Compute (for compute instance enumeration) - OCI.PSModules.Network (for network interface information)

Required Permissions

The following OCI permissions are required to successfully enumerate compute instances:

Compute Instance Permissions - COMPUTE_INSTANCE_READ - Ability to list and view compute instances - COMPUTE_INSTANCE_ATTACHMENT_READ - Access to instance network attachments - VNIC_READ - Ability to read network interface information

Compartment Access - COMPARTMENT_READ - Read access to the target compartment - COMPARTMENT_INSPECT - Ability to inspect compartment contents

Network Permissions - VCN_READ - Read access to Virtual Cloud Network information - SUBNET_READ - Access to subnet details for network interface resolution

API Key Permissions - API_KEY_READ - Ability to use API keys for authentication - USER_READ - Read access to user information for authentication

Note: These permissions are typically granted through OCI policies. Contact your OCI administrator if you encounter permission errors.

Note: The script automatically handles module installation. If you're in a restricted environment, you can manually install the modules using the commands provided in this guide.

CSV format required by DMC

Host,Os
fqdn-or-ip,windows|linux|unknown
  • Host: FQDN or IP address of the compute instance
  • Os: windows, linux, or unknown

DMC will validate the OS type during the Validate Servers step.

The script provided in this guide is supplied as-is, without any warranties or guarantees. You should validate and test the script in your own environment before running it in production or on critical systems.

Export OCI Compute Instances

This script connects to Oracle Cloud Infrastructure and exports compute instance IP addresses or FQDNs into the format required by DMC.

<#
.SYNOPSIS
  Export Oracle OCI compute instances to a DMC-ready CSV (Host,Os) with module preflight checks.

  REQUIREMENTS:
  - PowerShell 5.1+ (PowerShell 7+ recommended)
  - OCI account with compute instance enumeration permissions
  - Compartment access to target resources
  - API key configured with proper permissions
  - Internet access for automatic module installation
  - Write access to output directory for CSV export

.DESCRIPTION
  - Ensures required OCI PowerShell modules are present.
  - Connects to OCI using configured credentials.
  - Enumerates compute instances from specified compartments.
  - Exports Host (FQDN or IP) and Os (windows|linux|unknown) as DMC expects.
  - Focuses on private IP addresses for internal network scanning.

.PARAMETER CompartmentId
  OCI Compartment OCID to enumerate compute instances from.

.PARAMETER OutputPath
  Path to save CSV file. Defaults to .\oci_compute_instances.csv

.PARAMETER DefaultOS
  Optional override for OS column. Accepts 'Windows' or 'Linux'. Defaults to 'unknown'.

.PARAMETER UsePublicIPs
  Switch: use public IPs instead of private IPs (default is private IPs).

.EXAMPLE
  .\Export-OCIComputeInstances.ps1 -CompartmentId "ocid1.compartment.oc1..example" -DefaultOS Linux
#>

[CmdletBinding()]
param(
  [Parameter(Mandatory)] [string] $CompartmentId,
  [Parameter()]          [string] $OutputPath = ".\oci_compute_instances.csv",
  [Parameter()] [ValidateSet('Windows','Linux')] [string] $DefaultOS,
  [Parameter()] [switch] $UsePublicIPs
)

# -----------------------------
# Preflight: Environment checks
# -----------------------------
# Enforce TLS 1.2 for gallery downloads (older hosts)
try { [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 } catch {}

function Write-Info { param([string]$m) Write-Host "[INFO]  $m" -ForegroundColor Cyan }
function Write-Warn { param([string]$m) Write-Host "[WARN]  $m" -ForegroundColor Yellow }
function Write-Err  { param([string]$m) Write-Host "[ERROR] $m" -ForegroundColor Red }

# Minimal PS version (5.1+ or PowerShell 7+ recommended)
$psVerOk = ($PSVersionTable.PSVersion.Major -ge 5)
if (-not $psVerOk) {
  Write-Err "PowerShell 5.1 or later required. Current: $($PSVersionTable.PSVersion)"
  exit 1
}

# Ensure NuGet provider (for Install-Module), ignore errors on locked-down hosts
try {
  if (-not (Get-PackageProvider -ListAvailable | Where-Object { $_.Name -eq 'NuGet' })) {
    Write-Info "Installing NuGet package provider..."
    Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force -Scope CurrentUser | Out-Null
  }
} catch { Write-Warn "Could not ensure NuGet provider (offline/locked-down?). If module install fails, install OCI.PSModules manually." }

# Helper to ensure a module is available; installs to CurrentUser if missing.
function Ensure-Module {
  param(
    [Parameter(Mandatory)] [string] $Name,
    [string] $MinVersion = "0.0.0"
  )
  $loaded = Get-Module -ListAvailable -Name $Name | Sort-Object Version -Descending | Select-Object -First 1
  if ($loaded -and ($loaded.Version -ge [version]$MinVersion)) {
    Write-Info "Module '$Name' found (v$($loaded.Version))."
    return $true
  }

  Write-Info "Module '$Name' not found. Attempting install from PSGallery (CurrentUser)..."
  try {
    # Avoid prompts on first-time PSGallery use
    if (-not (Get-PSRepository -Name 'PSGallery' -ErrorAction SilentlyContinue)) {
      Register-PSRepository -Default -ErrorAction SilentlyContinue
    }
    Set-PSRepository -Name 'PSGallery' -InstallationPolicy Trusted -ErrorAction SilentlyContinue
    Install-Module -Name $Name -Scope CurrentUser -Force -AllowClobber -ErrorAction Stop
    Write-Info "Module '$Name' installed."
    return $true
  } catch {
    Write-Warn "Failed to install '$Name' from PSGallery: $($_.Exception.Message)"
    return $false
  }
}

# -----------------------------
# Required modules
# -----------------------------
Write-Info "Ensuring required OCI PowerShell modules are available..."

$okOCI = Ensure-Module -Name "OCI.PSModules"
if (-not $okOCI) {
  Write-Err @"
OCI.PSModules is required but could not be installed automatically.
Options:
  1) Install from PowerShell Gallery (if internet is allowed):
       Install-Module OCI.PSModules -Scope CurrentUser
  2) Install individual modules:
       Install-Module OCI.PSModules.Common -Scope CurrentUser
       Install-Module OCI.PSModules.Compute -Scope CurrentUser
       Install-Module OCI.PSModules.Network -Scope CurrentUser
"@
  exit 1
}

# Import required modules
try {
  Import-Module OCI.PSModules.Common -ErrorAction Stop
  Import-Module OCI.PSModules.Compute -ErrorAction Stop
  Import-Module OCI.PSModules.Network -ErrorAction Stop
  Write-Info "OCI modules imported successfully."
} catch {
  Write-Err "Failed to import OCI modules: $($_.Exception.Message)"
  exit 1
}

# -----------------------------
# Check OCI Configuration
# -----------------------------
Write-Info "Checking OCI client configuration..."

try {
  $config = Get-OCIClientConfig -ErrorAction Stop
  if (-not $config) {
    Write-Err @"
OCI client configuration not found. Please configure your OCI environment first:

1. Run: Set-OCIClientConfig
2. Enter your Tenancy OCID, User OCID, Region, and API key details
3. Or manually create ~/.oci/config file

For more information, see: https://docs.oracle.com/en-us/iaas/tools/powershell-sdk/using/getting-started.html
"@
    exit 1
  }
  Write-Info "OCI configuration found and validated."
} catch {
  Write-Err "Failed to validate OCI configuration: $($_.Exception.Message)"
  Write-Err "Please run Set-OCIClientConfig to configure your OCI environment."
  exit 1
}

# -----------------------------
# Normalize Default OS
# -----------------------------
$defaultOsCsv = if ($PSBoundParameters.ContainsKey('DefaultOS')) {
  if ($DefaultOS -eq 'Windows') { 'windows' } else { 'linux' }
} else { 'unknown' }

Write-Info "Default Os value for CSV rows: '$defaultOsCsv'"
Write-Info "IP preference: $($UsePublicIPs ? 'Public IPs' : 'Private IPs')"

# -----------------------------
# Collect Compute Instances -> DMC CSV rows
# -----------------------------
Write-Info "Enumerating compute instances from compartment: $CompartmentId"

try {
  $instances = Get-OCIComputeInstance -CompartmentId $CompartmentId -ErrorAction Stop
  Write-Info "Found $($instances.Count) compute instances."
} catch {
  Write-Err "Failed to enumerate compute instances: $($_.Exception.Message)"
  exit 1
}

if ($instances.Count -eq 0) {
  Write-Warn "No compute instances found in the specified compartment."
}

$rows = @()
foreach ($instance in $instances) {
  Write-Info "Processing instance: $($instance.DisplayName) (State: $($instance.LifecycleState))"

  # Skip instances that are not running
  if ($instance.LifecycleState -ne "RUNNING") {
    Write-Warn "Skipping instance '$($instance.DisplayName)' - not running (State: $($instance.LifecycleState))"
    continue
  }

  try {
    # Get network interfaces for this instance
    $vnics = Get-OCINetworkVnic -CompartmentId $CompartmentId -InstanceId $instance.Id -ErrorAction Stop

    foreach ($vnic in $vnics) {
      $ipAddress = $null

      if ($UsePublicIPs -and $vnic.PublicIp) {
        $ipAddress = $vnic.PublicIp
        Write-Info "  Using public IP: $ipAddress"
      } elseif ($vnic.PrivateIp) {
        $ipAddress = $vnic.PrivateIp
        Write-Info "  Using private IP: $ipAddress"
      }

      if ($ipAddress) {
        # Try to resolve FQDN; fall back to IP
        $fqdn = $null
        try { 
          $fqdn = [System.Net.Dns]::GetHostEntry($ipAddress).HostName 
          if ($fqdn -and $fqdn -ne $ipAddress) {
            Write-Info "  Resolved FQDN: $fqdn"
          }
        } catch {}

        $rows += [pscustomobject]@{
          Host = if ($fqdn -and $fqdn -ne $ipAddress) { $fqdn } else { $ipAddress }
          Os   = $defaultOsCsv
        }
      }
    }
  } catch {
    Write-Warn "Failed to get network interfaces for instance '$($instance.DisplayName)': $($_.Exception.Message)"
  }
}

if ($rows.Count -eq 0) {
  Write-Warn "No IP addresses discovered from compute instances. Check compartment permissions and network configuration."
}

# -----------------------------
# Write CSV
# -----------------------------
try {
  $rows | Select-Object Host, Os | Export-Csv -Path $OutputPath -NoTypeInformation -Encoding UTF8
  Write-Info "Export complete: $OutputPath"
  Write-Info "Columns: Host,Os"
  Write-Info "Total rows exported: $($rows.Count)"
} catch {
  Write-Err "Failed to write CSV to '$OutputPath': $($_.Exception.Message)"
  exit 1
}

# -----------------------------
# Summary
# -----------------------------
Write-Host ""
Write-Info "Export Summary:"
Write-Info "  Compartment ID: $CompartmentId"
Write-Info "  Instances processed: $($instances.Count)"
Write-Info "  IP addresses exported: $($rows.Count)"
Write-Info "  Default OS assumption: $defaultOsCsv"
Write-Info "  IP preference: $($UsePublicIPs ? 'Public IPs' : 'Private IPs')"
Write-Host ""

Examples

Basic Usage

Export from a specific compartment with default settings:

.\Export-OCIComputeInstances.ps1 -CompartmentId "ocid1.compartment.oc1..example"

Default OS Assumption

Force Windows for all instances:

.\Export-OCIComputeInstances.ps1 -CompartmentId "ocid1.compartment.oc1..example" -DefaultOS Windows

Force Linux for all instances:

.\Export-OCIComputeInstances.ps1 -CompartmentId "ocid1.compartment.oc1..example" -DefaultOS Linux

Custom Output Path

.\Export-OCIComputeInstances.ps1 -CompartmentId "ocid1.compartment.oc1..example" -OutputPath "C:\exports\oci_servers.csv"

Use Public IPs Instead of Private

.\Export-OCIComputeInstances.ps1 -CompartmentId "ocid1.compartment.oc1..example" -UsePublicIPs

Prerequisites Setup

1. Install OCI PowerShell Modules

Install all modules:

Install-Module -Name OCI.PSModules -Scope CurrentUser

Or install individual modules:

Install-Module -Name OCI.PSModules.Common -Scope CurrentUser
Install-Module -Name OCI.PSModules.Compute -Scope CurrentUser
Install-Module -Name OCI.PSModules.Network -Scope CurrentUser

2. Configure OCI Environment

Interactive configuration:

Import-Module OCI.PSModules.Common
Set-OCIClientConfig

This will prompt you for: - Tenancy OCID - User OCID
- Region - API Key file path and fingerprint

Manual configuration: Create ~/.oci/config file with your credentials:

[DEFAULT]
user=ocid1.user.oc1..example
fingerprint=xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx
key_file=~/.oci/oci_api_key.pem
tenancy=ocid1.tenancy.oc1..example
region=us-ashburn-1

3. Find Your Compartment ID

Log in to OCI Console

Log in to the OCI Console.

Open Compartments

Navigate to Identity > Compartments.

Select Compartment

Select your target compartment.

Copy the OCID

Copy the OCID from the compartment details.

Using the CSV in DMC

Open Server Selection

In Physical Scan, go to Server Selection.

Import CSV

Click Import CSV and choose the exported file.

Validate Connectivity

Validate servers to confirm connectivity (WinRM or SSH).

Run Scan

Proceed with Guest Credentials → Settings → Scan → Results.

Because OCI doesn't reliably expose guest OS information through the API, most entries will export with Os = unknown.
Use DMC's Validate Servers step to confirm operating system type automatically.

Troubleshooting

Module Installation Issues

If automatic module installation fails:

# Check PowerShell Gallery access
Get-PSRepository -Name 'PSGallery'

# Install manually with verbose output
Install-Module -Name OCI.PSModules -Scope CurrentUser -Verbose

Authentication Issues

If you get authentication errors:

# Check current configuration
Get-OCIClientConfig

# Reconfigure if needed
Set-OCIClientConfig

Permission Issues

Ensure your OCI user has: - Compute Instance Read permissions - Network VNIC Read permissions
- Access to the target compartment

Network Connectivity

  • Verify your machine can reach OCI services
  • Check firewall rules for outbound HTTPS (443) connections
  • Ensure DNS resolution works for OCI endpoints
© 2025 Altra Technologies