π’ Note: This lab environment is designed for testing and demonstration purposes. For production deployments, consult the official Okta documentation.
A Docker-based laboratory environment for testing Okta's On-Premises Provisioning (OPP) Agent with CSV directory integration. This setup enables you to quickly deploy and test user provisioning workflows by importing user identities from CSV files into Okta using scheduled imports.
- Overview
- Prerequisites
- Quick Start
- Configuration
- CSV File Management
- Testing CSV Imports
- Makefile Commands
- Troubleshooting
- Security Considerations
- Advanced Topics
- Resources
The Okta On-Premises Provisioning (OPP) Agent acts as a secure bridge between Okta's cloud identity platform and your on-premises systems. It enables:
- Secure Communication: Outbound-only HTTPS connections from your network to Okta
- Flexible Integration: Supports various on-premises integration methods including CSV imports
- Automated Operations: Scheduled and automated user LifeCycle Management (LCM)
The CSV Directory Integration enables organizations to import user identities from CSV files into Okta:
- Scheduled Imports: Recurring ingestion of CSV files containing user identity data
- Attribute-Level Sourcing: Rich user attribute profiles with flexible mapping
- Matching Rules: Intelligent user matching to update existing profiles or create new ones
- Feature Parity: Same capabilities as other Okta profile sources (such as Workday, Active Directory)
This Docker Compose environment includes:
- Okta Provisioning Agent (okta-opp-csv): Maintains secure connection to Okta and processes CSV files
- CSV Directory: Local directory (
./csv/) for CSV file storage and processing - VisiData (visidata): Terminal-based CSV editor for viewing and editing CSV files interactively
---
config:
layout: dagre
---
flowchart TB
subgraph subGraph0["**Okta Cloud**"]
A["Okta Org"]
end
subgraph subGraph1["**Docker Environment**"]
B["OPP Agent"]
C["CSV Files Directory"]
D["CSV Editor"]
end
B -- Outbound HTTPS --> A
B -- Reads CSV Files --> C
D -- Edit CSV Files --> C
style B fill:#FFE0B2
style C fill:#FFCDD2
style D fill:#FFF9C4
style subGraph0 stroke:#757575,fill:#C8E6C9
style subGraph1 fill:#BBDEFB,stroke:#2962FF
Before starting, ensure you have:
- Docker Desktop or Docker Engine with Docker Compose v2+
- Okta Organization with administrative access
- Required Files downloaded (see below)
Place the following files in ./docker/okta-opp/packages/:
| File | Required | Description | Download |
|---|---|---|---|
OktaProvisioningAgent-*.rpm |
β Yes | OPP Agent installer | Download from Okta |
*.pem or *.crt (certificates) |
Custom VPN certificates | Copy your VPN provider root CA |
β οΈ Important: Certificate files are only needed if you're connecting through a VPN with custom CA certificates (e.g., Palo Alto GlobalProtect, Prisma Access). If you don't have custom VPN certificates, you can ignore the warnings during startup.For Oktanauts only: copy from
~/.local/prisma_certificates.pemto the packages directory.
# Copy OPP Agent files to docker/okta-opp/packages/:
# - OktaProvisioningAgent-*.rpm
# - *.pem or *.crt (optional, for custom VPN)# Build Docker images
make build
# Start services
make start-logsThe make start command will:
- Run prerequisite checks
- Start the OPP Agent container
Wait for this message in the logs:
β³ Waiting for configuration files. Please configure the Agent...
Then, close the logs (Ctrl+C) or open another terminal, and configure the agent:
make configureThe project includes pre-populated CSV files with 15 Star Wars characters in the ./csv/ directory:
users.csv: Basic user attributes (login, email, firstName, lastName)users_extended.csv: Extended attributes including displayName, title, department, manager, employeeNumber, organization, and streetAddress
You can use these sample files as-is for testing, or replace them with your own user data.
Sample users included: Luke Skywalker, Leia Organa, Han Solo, Obi-Wan Kenobi, Yoda, Chewbacca, PadmΓ© Amidala, Lando Calrissian, Qui-Gon Jinn, Mace Windu, Darth Vader, Darth Sidious, Wilhuff Tarkin, C-3PO, and R2-D2.
See CSV File Format section for detailed specifications.
- In Okta Admin Console, go to Directory β Directory Integrations
- Click Add Directory
- Select CSV Directory
- Configure the integration:
- Integration Name: Give it a descriptive name
- CSV Location: Configure the file path on the agent (e.g.,
/csv/users.csvor/csv/users_extended.csv) - Import Schedule: Set up automatic import frequency
- Attribute Mappings: Map CSV columns to Okta user attributes
- Matching Rules: Configure how to match existing users
- Run the initial import
- Verify users are imported correctly
Official Documentation: https://help.okta.com/en-us/content/topics/directory/csv-integration-get-started.htm
The agent configuration is stored in ./data/okta-opp/conf/OktaProvisioningAgent.conf:
orgUrl = https://your-org.okta.com
agentId = your-agent-id
agentKey = your-agent-key
keystoreKey = your-keystore-key
keyPassword = your-key-password
env = prod # or 'preview'
subdomain = your-subdomainπ’ Note: These values are generated during agent registration in the Okta Admin Console. You don't need to change them.
CSV files should be placed in the ./csv/ directory and follow these guidelines:
File Requirements:
- Format: Standard CSV (Comma-Separated Values)
- Encoding: UTF-8
- Header Row: First row must contain column names (attribute names)
- Required Fields: At minimum, include
emailorloginfor user identification - File Location: Files are accessible at
/csv/inside the container
Supported Attributes: Common Okta user attributes you can include:
email- Primary email address (required)login- Username for Okta login (required)firstName- User's first name (required)lastName- User's last name (required)mobilePhone- Mobile phone numbersecondEmail- Secondary email addressdisplayName- Display nametitle- Job titledepartment- Departmentmanager- Manager's email or login (for org chart)employeeNumber- Employee IDorganization- Organization namestreetAddress- Street addresscity- Citystate- State/ProvincezipCode- Postal codecountryCode- Country code- ... any other custom attribut that you can then map in the Okta configuration
Example 1: Basic CSV (./csv/users.csv):
login,email,firstName,lastName
luke.skywalker@galaxy.local,luke.skywalker@galaxy.local,Luke,Skywalker
leia.organa@galaxy.local,leia.organa@galaxy.local,Leia,Organa
han.solo@galaxy.local,han.solo@galaxy.local,Han,Solo
obiwan.kenobi@galaxy.local,obiwan.kenobi@galaxy.local,Obi-Wan,Kenobi
yoda@galaxy.local,yoda@galaxy.local,Minch,YodaExample 2: Extended CSV (./csv/users_extended.csv):
login,email,firstName,lastName,displayName,title,department,manager,employeeNumber,organization,streetAddress
luke.skywalker@galaxy.local,luke.skywalker@galaxy.local,Luke,Skywalker,Luke Skywalker,Jedi Knight,JEDI-COUNCIL,obiwan.kenobi@galaxy.local,10021,Jedi,"Lars Moisture Farm, Anchorhead, Tatooine"
leia.organa@galaxy.local,leia.organa@galaxy.local,Leia,Organa,Princess Leia,Princess of Alderaan,REBEL-COMMAND,,10022,Resistance,"Royal Palace, Aldera, Alderaan"
han.solo@galaxy.local,han.solo@galaxy.local,Han,Solo,Han Solo,Smuggler Captain,FREELANCE,leia.organa@galaxy.local,10023,Resistance,"Docking Bay 94, Mos Eisley, Tatooine"π Note: The project includes both files pre-populated with 15 Star Wars characters for testing.
Best Practices:
- Use consistent formatting for phone numbers
- Include all users in a single CSV file or use multiple files with different names
- Update the CSV file whenever user data changes
- Keep historical versions for audit purposes
- Validate CSV format before placing in the directory
File Permissions: Ensure the CSV files are readable by the container (chmod 644 or similar)
The project includes two pre-populated CSV files in the ./csv/ directory with 15 Star Wars characters:
Example 1: Basic Users (./csv/users.csv):
Contains 15 users with basic required attributes only:
- Columns: login, email, firstName, lastName
- Users: Luke Skywalker, Leia Organa, Han Solo, Obi-Wan Kenobi, Yoda, Chewbacca, PadmΓ© Amidala, Lando Calrissian, Qui-Gon Jinn, Mace Windu, Darth Vader, Darth Sidious, Wilhuff Tarkin, C-3PO, R2-D2
login,email,firstName,lastName
luke.skywalker@galaxy.local,luke.skywalker@galaxy.local,Luke,Skywalker
leia.organa@galaxy.local,leia.organa@galaxy.local,Leia,Organa
han.solo@galaxy.local,han.solo@galaxy.local,Han,Solo
...Example 2: Users with Extended Attributes (./csv/users_extended.csv):
Contains the same 15 users with extended profile attributes:
- Columns: login, email, firstName, lastName, displayName, title, department, manager, employeeNumber, organization, streetAddress
- Includes: Job titles, departments, manager relationships, employee numbers, organizations (Jedi, Resistance, Empire, Droid), and addresses
login,email,firstName,lastName,displayName,title,department,manager,employeeNumber,organization,streetAddress
luke.skywalker@galaxy.local,luke.skywalker@galaxy.local,Luke,Skywalker,Luke Skywalker,Jedi Knight,JEDI-COUNCIL,obiwan.kenobi@galaxy.local,10021,Jedi,"Lars Moisture Farm, Anchorhead, Tatooine"
leia.organa@galaxy.local,leia.organa@galaxy.local,Leia,Organa,Princess Leia,Princess of Alderaan,REBEL-COMMAND,,10022,Resistance,"Royal Palace, Aldera, Alderaan"
...π Note: These sample files are ready to use for testing CSV imports. You can modify them or create your own CSV files with your actual user data.
# List CSV files
docker compose exec okta-opp-csv ls -la /csv/
# View CSV file contents
docker compose exec okta-opp-csv cat /csv/users.csv
# Count users in CSV
docker compose exec okta-opp-csv wc -l /csv/users.csv-
Method 1: Edit with VisiData (interactive terminal CSV editor)
docker compose exec visidata visidataVisiData keyboard shortcuts:
- Arrow keys: Navigate cells
e: Edit cella: Add new rowd: Delete rowq: QuitCtrl+S: Save changes
-
Method 2: Edit CSV files on your host system
nano ./csv/users.csv -
Method 3: Copy new CSV files
cp ~/Downloads/new_users.csv ./csv/users.csv
π Files are immediately available in the container via volume mount
Before importing, validate your CSV files:
Check CSV Format:
# Verify CSV file is readable
cat ./csv/users.csv
# Check for correct line endings (should be Unix LF, not Windows CRLF)
file ./csv/users.csv
# Count rows
wc -l ./csv/users.csvCommon Issues:
- Encoding: Ensure UTF-8 encoding (not ISO-8859-1 or Windows-1252)
- Line Endings: Use Unix line endings (
LF), not Windows (CRLF) - Quotes: Use double quotes for fields containing commas
- Headers: First row must contain column names
- Empty Fields: Use empty strings, not
NULLornull
| Command | Description |
|---|---|
make help |
Display all available commands |
make check-prereqs |
Run prerequisite checks without starting services |
make build |
Build Docker images (with prereq checks) |
make rebuild |
Force rebuild from scratch (no cache) |
make start |
Start services in detached mode (with prereq checks) |
make start-live |
Start services in foreground mode |
make start-logs |
Start services and follow logs |
make stop |
Stop and remove all containers |
make restart |
Restart all services |
make restart-logs |
Restart and follow logs |
make logs |
Follow container logs (last 500 lines) |
make kill |
Kill containers and remove orphans |
make configure |
Launch interactive agent configuration script |
make editor |
Open VisiData CSV editor (interactive) |
# Initial setup
make build
make start
make configure
# Start
make start
# Stop
make stop
# Restart
make restart
# Rebuild images (i.e. update of the RPM)
make stop
make rebuild
make start
# Clean everything and start from scratch
make stop
rm -rf ./data/okta-opp
make rebuild
make start
make configureThe project includes pre-populated CSV files ready for testing. You can start with either file:
-
Choose a CSV file:
- Basic import: Use
/csv/users.csv(15 users with basic attributes) - Extended import: Use
/csv/users_extended.csv(same users with extended attributes including titles, departments, managers, etc.)
- Basic import: Use
-
Configure CSV import in Okta Admin Console:
- Go to Directory β Directory Integrations
- Click Add Directory β CSV Directory
- Configure the CSV file path:
/csv/users.csvor/csv/users_extended.csv - Set up attribute mappings:
- For basic: login β login, email β email, firstName β firstName, lastName β lastName
- For extended: Add mappings for displayName, title, department, manager, employeeNumber, organization, streetAddress
- Configure matching rules (match by email or login)
-
Run manual import:
- Trigger a manual import from Okta Admin Console
- Monitor import progress
- You should see 15 users being imported
-
Verify import results:
- Go to Directory β People
- Search for imported users (e.g., "Luke Skywalker", "Leia Organa")
- Verify attributes were mapped correctly
-
Modify CSV file
-
Trigger import:
- Wait for scheduled import or trigger manually from Okta Admin Console
- Okta will update existing users based on matching rules (by email or login)
Check OPP Agent logs:
# View live logs
docker compose logs -f okta-opp-csv
# View agent log file
tail -f ./data/okta-opp/logs/agent.log
# Search for CSV-related messages
grep -i csv ./data/okta-opp/logs/agent.logMissing RPM files:
ERROR: Okta Provisioning Agent RPM not found!
Solution: Download the RPM file from Okta and place in ./docker/okta-opp/packages/
Symptoms: Agent shows "Waiting for configuration files..."
Solution: Ensure these files exist in ./data/okta-opp/:
conf/OktaProvisioningAgent.confwith all required keyssecurity/OktaProvisioningKeystore.p12
Check logs:
# View OPP Agent logs
docker compose logs -f okta-opp-csv
# View agent log file directly
tail -f ./data/okta-opp/logs/agent.logSymptoms: Import fails with "file not found" error
Solution:
- Verify file exists in ./csv/ directory:
ls -la ./csv/- Check file is accessible from container:
docker compose exec okta-opp-csv ls -la /csv/
docker compose exec okta-opp-csv cat /csv/yourfile.csv- Verify file path in Okta configuration:
- File path should be
/csv/filename.csv(not./csv/or relative path)
- File path should be
Common issues:
- Invalid CSV format: Check for proper UTF-8 encoding, correct delimiters, header row
- Missing required fields: Ensure
emailorloginfield exists - Duplicate users: Check matching rules in Okta configuration
- Invalid attribute values: Verify data format (phone numbers, dates, etc.)
Debug CSV file:
# Check file encoding
file ./csv/users.csv
# View file contents
cat ./csv/users.csv
# Check for Windows line endings
dos2unix ./csv/users.csv # Convert if neededWARNING: No certificate file (.pem or .crt) found
This is normal: The warning indicates the container will work without custom VPN certificates. Only add certificates if you're connecting through a VPN with custom CAs (e.g., Prisma Access, GlobalProtect).
If you need certificates: Place *.pem or *.crt files in ./docker/okta-opp/packages/
β οΈ Warning: This lab environment is for testing and demonstration purposes only. Do not use in production.
β οΈ Warning: Docker is not officially supported by Okta to run the OPP Agent in production. Always consult official Okta documentation and support for production deployments.
- Supported Operating Systems: Use supported OS for OPP Agent (RHEL, CentOS, Windows Server, etc.)
- File Security: Protect CSV files with appropriate file permissions
- Network Security:
- Isolate the OPP agent in a secure network segment
- Use firewall rules to control access
- Monitoring: Enable logging and alerting for agent status and import errors
- Regular Updates: Keep OPP Agent patched and updated
- Backup Strategy: Implement regular backups of CSV source data
- High Availability: Consider redundancy for critical import workflows
- Data Privacy: Ensure CSV files containing PII are encrypted at rest
- Access Control: Restrict access to CSV directories to authorized processes only
For production use, you may want to automate CSV file generation from your HR system or database:
Example: Generate CSV from Database:
#!/bin/bash
# Script to export users from database to CSV
mysql -h yourdb -u user -p password yourdb -e \
"SELECT email, firstName, lastName, login, mobilePhone
FROM users WHERE active=1" \
--batch --skip-column-names \
| sed 's/\t/,/g' \
> /path/to/csv/users.csvExample: Generate CSV from API:
#!/usr/bin/env python3
import requests
import csv
# Fetch users from HR API
response = requests.get('https://hr-api.example.com/users')
users = response.json()
# Write to CSV
with open('/path/to/csv/users.csv', 'w', newline='') as f:
writer = csv.DictWriter(f, fieldnames=['email', 'firstName', 'lastName', 'login'])
writer.writeheader()
writer.writerows(users)Configure cron jobs or scheduled tasks to update CSV files automatically:
# Example cron job (runs daily at 2 AM)
0 2 * * * /usr/local/bin/generate_csv.shYou can configure multiple CSV directory integrations for different user populations, e.g.:
./csv/employees.csv- Full-time employees./csv/contractors.csv- Contractors./csv/partners.csv- Partner users
Each integration can have different import schedules and attribute mappings.
This project includes VisiData, a powerful terminal-based spreadsheet editor for CSV files:
Launch VisiData:
# Open VisiData with a specific CSV file
docker compose exec visidata visidata
# Or access the VisiData container shell first
docker compose exec visidata sh
# Then run: visidata /data/users.csvVisiData Quick Reference:
- Navigation: Arrow keys to move between cells
- Edit cell: Press
eto edit the current cell - Add row: Press
ato add a new row after the current row - Delete row: Press
dto delete the current row - Search: Press
/to search for text - Sort column: Press
[or]to sort ascending/descending - Save changes: Press
Ctrl+Sto save the file - Quit: Press
qto quit (orCtrl+Qto force quit without saving)
Benefits of VisiData:
- Interactive editing with spreadsheet-like interface
- Syntax highlighting and column-aware navigation
- Built-in data validation and CSV format preservation
- No need to install anything on your host system
- Works directly with mounted CSV files
Official Documentation: VisiData Documentation
- Install the Okta Provisioning Agent
- CSV Directory Integration - Get Started
- CSV Directory Integration Prerequisites
- Okta On-Premises Provisioning Overview
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
Fabio Grasso
- Blog: iam.fabiograsso.net
- GitHub: @fabiograsso
Disclaimer: This is a demonstration laboratory environment. It is not officially supported by Okta for production use. Always consult official Okta documentation and support for production deployments.