Fivetran Hardening Guide
Data integration platform hardening for Fivetran including SSO configuration, role-based access, and connector security
Overview
Fivetran is a leading data integration platform that automates data pipelines for thousands of organizations worldwide. As a tool that moves data between systems including databases, SaaS applications, and data warehouses, Fivetran security configurations directly impact data confidentiality and integrity across your data ecosystem.
Intended Audience
- Security engineers managing data platforms
- IT administrators configuring Fivetran
- Data engineers securing data pipelines
- GRC professionals assessing data integration security
How to Use This Guide
- L1 (Crawl): Essential controls for all organizations
- L2 (Walk): Enhanced controls for security-sensitive environments
- L3 (Run): Strictest controls for regulated industries
Scope
This guide covers Fivetran Dashboard security including SAML SSO, role-based access control, connector security, and session management.
Table of Contents
- Authentication & SSO
- Access Controls
- Connector Security
- Monitoring & Compliance
- Compliance Quick Reference
1. Authentication & SSO
1.1 Configure SAML Single Sign-On
Profile Level: L1 (Crawl)
| Framework | Control |
|---|---|
| CIS Controls | 6.3, 12.5 |
| NIST 800-53 | IA-2, IA-8 |
Description
Configure SAML SSO to centralize authentication for Fivetran users.
Rationale
Why This Matters:
- Centralizes identity management
- Enables enforcement of organizational MFA policies
- Supports just-in-time provisioning
- Simplifies user lifecycle management
Attack Prevented: Credential theft, phishing, password reuse, unmanaged account sprawl
Prerequisites
- Fivetran account with Account Administrator role
- SAML 2.0 compatible identity provider
- IdP SuperAdmin or AppAdmin access
ClickOps Implementation
Step 1: Access SSO Configuration
- Navigate to: Account Settings → General
- Locate the Authentication Settings section
- Review current authentication configuration
Step 2: Configure Identity Provider
- Create SAML application in your IdP:
- Okta
- Microsoft Entra ID
- Google Workspace
- PingOne
- CyberArk Identity
- Configure attribute mappings, observing Fivetran’s two mandatory SAML requirements:
- The SAML NameID must be the user’s email address — Fivetran matches users by email, and any other NameID format breaks sign-in
- The IdP must sign SAML assertions using RSA-SHA256; other signature algorithms are not accepted
Step 3: Configure Fivetran SSO
- Navigate to: Account Settings → Single Sign-On
- Enable SAML authentication
- Enter IdP metadata:
- IdP SSO URL
- IdP Entity ID
- X.509 Certificate
- Save configuration
Step 4: Test and Enforce
- Test SSO authentication
- Verify user can sign in via IdP
- Enable SSO enforcement (see 1.2)
Time to Complete: ~1 hour
Code Implementation
Code Pack: Terraform
# Configure SAML SSO for centralized authentication
resource "fivetran_external_logging" "saml_sso_config_audit" {
# Note: The Fivetran Terraform provider does not expose a dedicated SAML SSO
# resource. SAML configuration is managed via the Fivetran REST API or
# Dashboard. This file provides the API-based implementation as a
# null_resource provisioner for automation.
count = 0 # Placeholder -- see null_resource below
}
# Automate SAML SSO configuration via the Fivetran REST API
resource "null_resource" "configure_saml_sso" {
count = var.saml_idp_sso_url != "" ? 1 : 0
triggers = {
idp_sso_url = var.saml_idp_sso_url
idp_entity_id = var.saml_idp_entity_id
}
provisioner "local-exec" {
command = <<-EOT
curl -s -X PATCH \
"https://api.fivetran.com/v1/account/config" \
-H "Authorization: Basic $(echo -n '${var.fivetran_api_key}:${var.fivetran_api_secret}' | base64)" \
-H "Content-Type: application/json" \
-d '{
"saml_enabled": true,
"saml_sso_url": "${var.saml_idp_sso_url}",
"saml_entity_id": "${var.saml_idp_entity_id}",
"saml_certificate": "${var.saml_x509_certificate}"
}'
EOT
}
}
1.2 Restrict Authentication to SSO
Profile Level: L2 (Walk)
| Framework | Control |
|---|---|
| CIS Controls | 6.3 |
| NIST 800-53 | IA-2 |
Description
Require all users to authenticate via SSO only.
Rationale
Why This Matters:
- Forcing SAML-only authentication closes the local password login path that bypasses IdP-enforced MFA and conditional access
- Password logins are vulnerable to credential stuffing, phishing, and reuse of breached credentials
- Centralizing every login through the IdP means deprovisioning a user in the IdP instantly revokes Fivetran access
- Fivetran holds the credentials and data flows for your entire pipeline, so any non-SSO login is a high-value bypass
Attack Prevented: Credential stuffing, phishing, MFA bypass, password reuse, orphaned-account access
ClickOps Implementation
Step 1: Configure Authentication Restriction
- Navigate to: Account Settings → General
- Find the Authentication Settings section
- Review the configured login type. Fivetran offers three:
- No restrictions — email/password, Google OAuth, and SAML all permitted
- Google OAuth — Google sign-in permitted
- SAML — SAML sign-in only
Step 2: Set Required Authentication
- Set the required authentication type to SAML
- This closes both the local password login path and the Google OAuth login path — Google OAuth is a second non-SAML entry point that bypasses your IdP’s conditional access, and leaving the account on No restrictions leaves it open
- All users must then sign in through the IdP
Step 3: Verify Enforcement
- Test login with password (should fail)
- Test login with Google OAuth (should fail)
- Verify SSO login works
- Document emergency access procedures
Code Implementation
Code Pack: Terraform
# Enforce SAML-only authentication (L2+)
# Disables password-based login -- all users must authenticate via IdP
resource "null_resource" "enforce_saml_only" {
count = var.profile_level >= 2 && var.sso_enforce_saml_only && var.saml_idp_sso_url != "" ? 1 : 0
triggers = {
profile_level = var.profile_level
enforce_saml = var.sso_enforce_saml_only
}
provisioner "local-exec" {
command = <<-EOT
curl -s -X PATCH \
"https://api.fivetran.com/v1/account/config" \
-H "Authorization: Basic $(echo -n '${var.fivetran_api_key}:${var.fivetran_api_secret}' | base64)" \
-H "Content-Type: application/json" \
-d '{
"required_authentication_type": "SAML"
}'
EOT
}
}
# Validation: verify password login is disabled after enforcement
resource "null_resource" "verify_saml_enforcement" {
count = var.profile_level >= 2 && var.sso_enforce_saml_only && var.saml_idp_sso_url != "" ? 1 : 0
depends_on = [null_resource.enforce_saml_only]
provisioner "local-exec" {
command = <<-EOT
echo "Verifying SAML enforcement..."
RESPONSE=$(curl -s \
"https://api.fivetran.com/v1/account/config" \
-H "Authorization: Basic $(echo -n '${var.fivetran_api_key}:${var.fivetran_api_secret}' | base64)")
echo "$RESPONSE" | grep -q '"required_authentication_type":"SAML"' && \
echo "PASS: SAML-only authentication enforced" || \
echo "WARN: SAML enforcement could not be verified"
EOT
}
}
1.3 Configure Just-In-Time Provisioning
Profile Level: L2 (Walk)
| Framework | Control |
|---|---|
| CIS Controls | 5.3 |
| NIST 800-53 | AC-2 |
Description
Enable automatic user provisioning on first login.
Rationale
Why This Matters:
- JIT provisioning creates accounts only when an IdP-authenticated user signs in for the first time, eliminating pre-created dormant accounts
- New users are created with no permissions by default, enforcing least privilege until roles are explicitly assigned
- Tying account creation to the IdP keeps the user lifecycle authoritative in one place rather than scattered across manual Fivetran account creation
- Manual account creation is error-prone and tends to leave stale, over-privileged accounts behind
Attack Prevented: Orphaned-account access, privilege creep, manual provisioning errors, dormant account abuse
ClickOps Implementation
Step 1: Enable JIT Provisioning
- Navigate to: Account Settings → Single Sign-On
- Enable Enable SAML authentication
- Enable Enable user provisioning
Step 2: Configure SAML Attributes
- Configure IdP to send:
- Email address (this must also be the SAML NameID — see 1.1)
- First name
- Last name
- New users created automatically on SAML sign-on
Step 3: Configure Default Permissions
- Note: JIT users created with no permissions by default
- Assign the user’s team membership and role in Fivetran after the account is created — Fivetran does not derive roles from IdP group membership, including when SCIM is enabled (see 2.3)
- Treat role assignment as a required post-provisioning step in your onboarding runbook, not something the IdP will do for you
Code Implementation
Code Pack: Terraform
# Enable JIT user provisioning via SAML (L2+)
# New users are automatically created on first SAML login with no permissions
resource "null_resource" "configure_jit_provisioning" {
count = var.profile_level >= 2 && var.jit_provisioning_enabled && var.saml_idp_sso_url != "" ? 1 : 0
triggers = {
profile_level = var.profile_level
jit_enabled = var.jit_provisioning_enabled
}
provisioner "local-exec" {
command = <<-EOT
curl -s -X PATCH \
"https://api.fivetran.com/v1/account/config" \
-H "Authorization: Basic $(echo -n '${var.fivetran_api_key}:${var.fivetran_api_secret}' | base64)" \
-H "Content-Type: application/json" \
-d '{
"saml_enabled": true,
"saml_user_provisioning": true
}'
EOT
}
}
1.4 Configure Session Timeout
Profile Level: L1 (Crawl)
| Framework | Control |
|---|---|
| CIS Controls | 6.2 |
| NIST 800-53 | AC-12 |
Description
Configure session timeout for dashboard access.
Rationale
Why This Matters:
- Bounded session lifetimes limit the window in which a stolen or hijacked session token can be reused
- Shorter timeouts protect against unattended-workstation access to the dashboard and its connector configurations
- Aligning timeout length to data sensitivity forces re-authentication in high-risk environments
- A default 24-hour session is a long exposure window for an admin console that controls data movement
Attack Prevented: Session hijacking, token replay, unattended-session abuse, idle-session takeover
Prerequisites
- Enterprise or Business Critical plan (for custom timeout)
ClickOps Implementation
Step 1: Access Session Settings
- Navigate to: Account Settings → General
- Find session timeout settings
Step 2: Configure Timeout Duration
- Select session timeout:
- 15 minutes
- 30 minutes
- 1 hour
- 4 hours
- 1 day
- 2 weeks
- Default is 1 day (24 hours)
Step 3: Apply Restrictions
- Shorter timeouts for sensitive data
- Sessions end when browser closes
- Document timeout policy
Code Implementation
Code Pack: Terraform
# Configure session timeout for dashboard access
# Shorter timeouts reduce risk of session hijacking
#
# Recommended values by profile level:
# L1 (Baseline): 60 minutes (1 hour)
# L2 (Hardened): 30 minutes
# L3 (Maximum Security): 15 minutes
resource "null_resource" "configure_session_timeout" {
triggers = {
profile_level = var.profile_level
timeout_minutes = var.session_timeout_minutes
}
provisioner "local-exec" {
command = <<-EOT
curl -s -X PATCH \
"https://api.fivetran.com/v1/account/config" \
-H "Authorization: Basic $(echo -n '${var.fivetran_api_key}:${var.fivetran_api_secret}' | base64)" \
-H "Content-Type: application/json" \
-d '{
"session_timeout": ${var.session_timeout_minutes}
}'
EOT
}
}
2. Access Controls
2.1 Configure Role-Based Access Control
Profile Level: L1 (Crawl)
| Framework | Control |
|---|---|
| CIS Controls | 5.4 |
| NIST 800-53 | AC-6 |
Description
Implement role-based permissions for Fivetran access.
Rationale
Why This Matters:
- Assigning the least-privileged role to each user limits the blast radius if any single account is compromised
- Restricting Account Administrator to a small number of users reduces the count of high-value targets
- Read-only Analyst roles let users see status without the ability to alter connectors, credentials, or destinations
- Over-broad administrative access lets a single compromised account reconfigure pipelines or exfiltrate source and destination data
Attack Prevented: Privilege escalation, lateral movement, insider misuse, blast-radius expansion
ClickOps Implementation
Step 1: Review Account Roles
- Navigate to: Account Settings → Users
- Review the account-level roles available in your tenant. As of this guide’s last verification these were Account Administrator (full account control), Account Analyst (view-only), Account Billing (billing management), and Team Manager (team administration). Fivetran’s public roles reference page is not currently resolvable, so confirm the exact role names and their scopes in your own account’s Users page rather than relying on this list.
Step 2: Assign Appropriate Roles
- Limit the full-control account administrator role to 2-3 users
- Use the view-only analyst role for read-only needs
- Use custom roles where a built-in role is broader than the job requires — custom roles require an Enterprise or Business Critical plan; on Standard you are limited to the built-in roles, so compensate by keeping team scoping tight (see 2.2)
Step 3: Configure Destination/Connector Roles
- Assign connector-level permissions
- Assign destination-level permissions
- Apply minimum necessary access
Code Implementation
Code Pack: Terraform
# Assign Account Administrator role to designated admin users only
# Limit to 2-3 users per the hardening guide recommendation
resource "fivetran_user" "admin_users" {
for_each = toset(var.admin_user_ids)
# Note: fivetran_user manages user role assignment
# The user must already exist in the Fivetran account
# This resource ensures correct role assignment
}
# Assign read-only Analyst role for view-only access
resource "fivetran_user" "analyst_users" {
for_each = toset(var.analyst_user_ids)
# Note: fivetran_user manages user role assignment
# Analyst role provides read-only access to connectors and destinations
}
# Validation: audit the number of Account Administrators
resource "null_resource" "audit_admin_count" {
triggers = {
admin_count = length(var.admin_user_ids)
}
provisioner "local-exec" {
command = <<-EOT
ADMIN_COUNT=${length(var.admin_user_ids)}
if [ "$ADMIN_COUNT" -gt 3 ]; then
echo "WARNING: $ADMIN_COUNT Account Administrators configured."
echo "Recommendation: Limit to 2-3 administrators."
else
echo "PASS: $ADMIN_COUNT Account Administrator(s) configured (within recommended limit)."
fi
# Enumerate current account users and their roles via API
echo "Fetching current user roles..."
curl -s \
"https://api.fivetran.com/v1/users" \
-H "Authorization: Basic $(echo -n '${var.fivetran_api_key}:${var.fivetran_api_secret}' | base64)" \
| python3 -c "
import sys, json
data = json.load(sys.stdin)
users = data.get('data', {}).get('items', [])
admins = [u for u in users if u.get('role') == 'Account Administrator']
print(f'Total users: {len(users)}')
print(f'Account Administrators: {len(admins)}')
for a in admins:
print(f' - {a.get(\"email\", \"unknown\")}')
" 2>/dev/null || echo "Note: Python3 required for user audit report"
EOT
}
}
2.2 Configure Team Structure
Profile Level: L2 (Walk)
| Framework | Control |
|---|---|
| CIS Controls | 5.4 |
| NIST 800-53 | AC-6(1) |
Description
Organize users into teams for granular access control.
Rationale
Why This Matters:
- Teams scope connector and destination access to the users who actually need it, enforcing need-to-know
- Inherited team permissions make access consistent and auditable rather than ad hoc per user
- Limiting Team Manager assignments controls who can grant access to pipelines and data
- Without segmentation, every user can potentially reach every connector and destination across the account
Attack Prevented: Over-broad data access, lateral movement, unauthorized pipeline changes, insider misuse
ClickOps Implementation
Step 1: Create Teams
- Navigate to: Account Settings → Teams
- Click Create Team
- Name team by function or project
Step 2: Assign Team Managers
- Only Team Managers and Account Admins can manage teams
- Assign Team Manager role
- Limit managers to necessary personnel
Step 3: Configure Team Permissions
- Assign connectors to teams
- Assign destinations to teams
- Users inherit team permissions
Code Implementation
Code Pack: Terraform
# Create teams for granular access control (L2+)
# Teams enable logical grouping of users with shared connector/destination access
resource "fivetran_team" "teams" {
for_each = var.profile_level >= 2 ? var.teams : {}
name = each.value.name
description = each.value.description
role = "Team Member"
}
# Assign users to teams (L2+)
resource "fivetran_team_user_membership" "memberships" {
for_each = var.profile_level >= 2 ? var.team_user_memberships : {}
team_id = fivetran_team.teams[each.key].id
dynamic "user" {
for_each = toset(each.value)
content {
user_id = user.value
role = "Team Member"
}
}
}
2.3 Configure SCIM Provisioning
Profile Level: L2 (Walk)
| Framework | Control |
|---|---|
| CIS Controls | 5.3 |
| NIST 800-53 | AC-2 |
Description
Configure SCIM for automated user and group provisioning.
Rationale
Why This Matters:
- SCIM automates account creation, updates, and deprovisioning from the IdP so access mirrors employment status in near real time
- Automatic deprovisioning removes departed users immediately, eliminating orphaned accounts with standing data access
- Once SCIM is enabled, users can only be created, updated, and removed from the IdP — that single authoritative path removes the drift that comes from parallel manual account management
- Manual offboarding is slow and easily missed, leaving credentials that can be abused after a user leaves
Attack Prevented: Orphaned-account access, offboarding gaps, privilege drift, manual provisioning errors
ClickOps Implementation
Step 1: Enable SCIM
- Navigate to: Account Settings → SCIM
- Generate SCIM API token
- Copy SCIM base URL
Step 2: Configure IdP SCIM
- Add SCIM integration in IdP
- Enter Fivetran SCIM endpoint
- Enter API token
Step 3: Configure User Sync and Assign Roles in Fivetran
- Fivetran SCIM does not support mapping IdP groups to Fivetran teams or roles. SCIM synchronizes user accounts only — team membership and role assignment remain Fivetran-side operations performed by an account administrator or team manager
- Once SCIM is enabled, users must be managed exclusively in the IdP — creating, editing, or deleting users directly in Fivetran is no longer the supported path, and changes made there will be out of step with the IdP
- Build role assignment into your onboarding runbook as an explicit Fivetran-side step, and include Fivetran role review in periodic access reviews since the IdP cannot enforce it
- Test user creation, update, and deactivation end to end before relying on SCIM for offboarding
Code Implementation
Code Pack: Terraform
# Enable SCIM provisioning for automated user and group lifecycle (L2+)
# SCIM endpoint: https://api.fivetran.com/v1/scim
# Configure your IdP to push users/groups to this endpoint
resource "null_resource" "configure_scim" {
count = var.profile_level >= 2 ? 1 : 0
triggers = {
profile_level = var.profile_level
}
# Generate a SCIM API token and output the SCIM base URL
provisioner "local-exec" {
command = <<-EOT
echo "============================================="
echo "SCIM Provisioning Setup (L2+)"
echo "============================================="
echo ""
echo "Fivetran SCIM Base URL:"
echo " https://api.fivetran.com/v1/scim"
echo ""
echo "To generate a SCIM token via API:"
echo ""
RESPONSE=$(curl -s -X POST \
"https://api.fivetran.com/v1/account/scim-token" \
-H "Authorization: Basic $(echo -n '${var.fivetran_api_key}:${var.fivetran_api_secret}' | base64)" \
-H "Content-Type: application/json")
TOKEN=$(echo "$RESPONSE" | python3 -c "
import sys, json
data = json.load(sys.stdin)
token = data.get('data', {}).get('token', '')
if token:
print(f'SCIM Token generated successfully.')
print(f'Token (first 8 chars): {token[:8]}...')
print(f'Store this token securely -- it cannot be retrieved again.')
else:
print('WARN: Could not generate SCIM token. Check API permissions.')
print(f'Response: {json.dumps(data)}')
" 2>/dev/null || echo "Note: Python3 required for token parsing")
echo ""
echo "IdP Configuration Steps:"
echo " 1. Add SCIM integration in your IdP"
echo " 2. Set SCIM endpoint: https://api.fivetran.com/v1/scim"
echo " 3. Enter the generated SCIM API token"
echo " 4. Map IdP groups to Fivetran teams"
echo " 5. Test user synchronization"
EOT
}
}
3. Connector Security
3.1 Secure Connector Credentials
Profile Level: L1 (Crawl)
| Framework | Control |
|---|---|
| CIS Controls | 3.11 |
| NIST 800-53 | SC-12 |
Description
Secure credentials used for data source connections.
Rationale
Why This Matters:
- Fivetran stores credentials for data sources
- Compromised credentials expose source systems
- Apply least privilege to connector accounts
Attack Prevented: Source-system compromise via stolen connector credentials, privilege abuse, lateral movement into source databases
ClickOps Implementation
Step 1: Create Dedicated Service Accounts
- Create service accounts for each connector
- Grant minimum required permissions:
- Read access for data extraction
- SELECT only for database connectors
- Never use admin credentials
Step 2: Use SSH Tunnels
- For database connectors, enable SSH tunnels
- More secure than direct connections
- Encrypt data in transit
Step 3: Rotate Credentials
- Establish rotation schedule (90 days)
- Update credentials in Fivetran
- Verify connector after rotation
Code Implementation
Code Pack: Terraform
# Create connectors with least-privilege service account credentials
# Each connector should use a dedicated service account with minimum permissions
resource "fivetran_connector" "managed_connectors" {
for_each = var.connectors
group_id = each.value.group_id
service = each.value.service
sync_frequency = each.value.sync_frequency
paused = each.value.paused
trust_certs = each.value.trust_certs
trust_fpints = each.value.trust_fpints
run_setup_tests = each.value.run_setup_tests
dynamic "config" {
for_each = length(each.value.config) > 0 ? [each.value.config] : []
content {
# Connector-specific configuration is passed via the config map
# Ensure credentials use dedicated service accounts with:
# - Read-only access for data extraction
# - SELECT-only for database connectors
# - Never admin/superuser credentials
}
}
}
# Validation: audit connector configurations for security posture
resource "null_resource" "audit_connector_credentials" {
triggers = {
connector_count = length(var.connectors)
}
provisioner "local-exec" {
command = <<-EOT
echo "============================================="
echo "Connector Credential Security Audit"
echo "============================================="
echo ""
# List all connectors and their services
curl -s \
"https://api.fivetran.com/v1/groups/${var.fivetran_account_id}/connectors" \
-H "Authorization: Basic $(echo -n '${var.fivetran_api_key}:${var.fivetran_api_secret}' | base64)" \
| python3 -c "
import sys, json
data = json.load(sys.stdin)
connectors = data.get('data', {}).get('items', [])
print(f'Total connectors: {len(connectors)}')
print('')
for c in connectors:
status = c.get('status', {}).get('setup_state', 'unknown')
print(f' [{status}] {c.get(\"service\", \"unknown\")} -- {c.get(\"schema\", \"no-schema\")}')
print('')
print('Reminder: Verify each connector uses a dedicated service account')
print('with minimum required permissions (read-only / SELECT only).')
" 2>/dev/null || echo "Note: Python3 required for connector audit report"
EOT
}
}
3.2 Configure Network Security
Profile Level: L2 (Walk)
| Framework | Control |
|---|---|
| CIS Controls | 13.5 |
| NIST 800-53 | AC-17 |
Description
Secure network access for Fivetran connections.
Rationale
Why This Matters:
- IP allowlisting restricts source-system access to known Fivetran addresses, shrinking the attack surface to a defined set of origins
- PrivateLink and private networking keep data off the public internet, removing exposure to interception and internet-facing scanning
- Requiring SSL/TLS with certificate validation protects pipeline data in transit and defends against man-in-the-middle attacks
- Source databases exposed to the public internet are routinely scanned and brute-forced by attackers
Attack Prevented: Man-in-the-middle interception, network eavesdropping, unauthorized source access, internet-exposed database attacks
ClickOps Implementation
Step 1: Configure Allowlisting
- Retrieve the Fivetran IP addresses for your account’s cloud region from Fivetran’s published IP list
- Prefer domain/hostname allowlisting over IP allowlisting where your firewall supports it. Fivetran states its IP addresses may change in the future without notice, so a hostname-based rule survives address changes that would otherwise break syncs or tempt an operator into loosening the rule
- Allowlist only Fivetran’s addresses or hostnames on source systems and block other external access
- If you must allowlist by IP, subscribe to Fivetran’s IP change communications and re-check the published list on a schedule
Step 2: Enable Private Networking
- Use Fivetran PrivateLink if available
- Connect via private networks
- Avoid public internet
Step 3: Configure Database Security
- Enable SSL/TLS for database connections
- Require encrypted connections
- Verify certificate validation
3.3 Configure Destination Security
Profile Level: L1 (Crawl)
| Framework | Control |
|---|---|
| CIS Controls | 3.11 |
| NIST 800-53 | SC-8 |
Description
Secure data warehouse and destination configurations.
Rationale
Why This Matters:
- Dedicated least-privilege service accounts for the destination limit what a compromised Fivetran connection can write or alter
- Encryption in transit and at rest protects the consolidated warehouse data, which is often more sensitive than any single source
- Restricting who can change destination settings prevents redirection of data or weakening of warehouse controls
- The destination aggregates data from many sources, making it a concentrated, high-value target
Attack Prevented: Data exfiltration, unauthorized warehouse writes, data redirection, eavesdropping on data in transit and at rest
ClickOps Implementation
Step 1: Secure Destination Credentials
- Use service accounts for destinations
- Grant minimum write permissions
- Avoid using admin credentials
Step 2: Enable Encryption
- Ensure destination supports encryption
- Enable TLS for connections
- Verify data encrypted at rest
Step 3: Configure Access Controls
- Limit who can modify destination settings
- Restrict data access in destination
- Apply column-level security if needed
Code Implementation
Code Pack: Terraform
# Secure data warehouse/destination configuration
# Use service accounts with minimum write permissions
resource "fivetran_destination" "primary" {
count = var.destination_group_id != "" && var.destination_service != "" ? 1 : 0
group_id = var.destination_group_id
service = var.destination_service
region = "GCP_US_EAST4"
time_zone_offset = "0"
run_setup_tests = true
trust_certs = true
trust_fingerprints = true
config {
# Destination-specific configuration is passed via variables
# Ensure the service account has:
# - Minimum write permissions to target schemas/datasets
# - No admin/owner-level access to the data warehouse
# - TLS encryption enabled for the connection
}
}
# Validate destination security configuration
resource "null_resource" "audit_destination_security" {
count = var.destination_group_id != "" ? 1 : 0
triggers = {
destination_group_id = var.destination_group_id
}
provisioner "local-exec" {
command = <<-EOT
echo "============================================="
echo "Destination Security Audit"
echo "============================================="
echo ""
# Fetch destination configuration
curl -s \
"https://api.fivetran.com/v1/destinations/${var.destination_group_id}" \
-H "Authorization: Basic $(echo -n '${var.fivetran_api_key}:${var.fivetran_api_secret}' | base64)" \
| python3 -c "
import sys, json
data = json.load(sys.stdin)
dest = data.get('data', {})
print(f'Destination: {dest.get(\"service\", \"unknown\")}')
print(f'Region: {dest.get(\"region\", \"unknown\")}')
print(f'Setup status: {dest.get(\"setup_status\", \"unknown\")}')
config = dest.get('config', {})
# Check for TLS/SSL indicators
has_ssl = any('ssl' in k.lower() or 'tls' in k.lower() for k in config.keys())
print(f'SSL/TLS configured: {\"Yes\" if has_ssl else \"Check manually\"}')
print('')
print('Destination Security Checklist:')
print(' [1] Service account with minimum write permissions')
print(' [2] No admin credentials used')
print(' [3] TLS encryption enabled')
print(' [4] Data encrypted at rest in destination')
print(' [5] Column-level security applied where needed')
" 2>/dev/null || echo "Note: Python3 required for destination audit report"
EOT
}
}
3.4 Use an External Secret Manager for Connector Credentials
Profile Level: L3 (Run)
| Framework | Control |
|---|---|
| CIS Controls | 3.11, 5.2 |
| NIST 800-53 | SC-12, SC-28, IA-5 |
Description
Store connector and destination credentials in your own secret manager instead of in Fivetran, so Fivetran retrieves secrets at runtime from a vault you control, rotate, and audit.
Rationale
Why This Matters:
- Keeping the authoritative copy of every connector credential in your own vault means rotation, revocation, and access auditing happen on infrastructure you own rather than inside a SaaS console
- Centralizing secrets removes the pattern where credentials are pasted into a vendor UI and then live there indefinitely with no rotation record
- A vault-backed secret can be revoked in one place the moment a connector, employee, or integration is compromised, without touching every Fivetran connector individually
Attack Prevented: Standing credential exposure in a third-party console, rotation gaps, delayed revocation after compromise
Prerequisites
- Business Critical plan
- Account Administrator role
- A supported external secret manager: Azure Key Vault, AWS Secrets Manager, Google Secret Manager, or HashiCorp Vault
- This feature is in private preview. It is not self-serve — request access through your Fivetran account team, and confirm current availability and supported connectors before designing around it.
ClickOps Implementation
Step 1: Confirm Availability
- Confirm your account is on the Business Critical plan and that you hold the Account Administrator role
- Request private-preview access to External Secrets Managers through your Fivetran account team
Step 2: Prepare the Vault
- Create the secrets your connectors need in Azure Key Vault, AWS Secrets Manager, Google Secret Manager, or HashiCorp Vault
- Grant Fivetran only the read access it needs to those specific secrets — never a broad vault-wide read grant
- Record the rotation schedule and owner for each secret in your vault
Step 3: Connect Fivetran to the Vault
- Navigate to: Account Settings → General → External Secrets Managers
- Add your secret manager and supply the connection details for the chosen provider
- Reference the vault-held secrets from the connectors that should use them
Step 4: Retire In-Console Credentials
- Once a connector is sourcing from the vault, remove or rotate the credential value that was previously stored in Fivetran
- Verify the connector still syncs after the change
Validation & Testing
- Rotate a secret in the vault and confirm the connector picks up the new value without a Fivetran-side edit
- Revoke Fivetran’s read access to a test secret and confirm the connector fails closed rather than falling back to a cached credential
- Confirm your vault’s audit log shows Fivetran’s reads
3.5 Govern Hybrid Deployment Agents
Profile Level: L2 (Walk)
| Framework | Control |
|---|---|
| CIS Controls | 1.1, 5.2, 12.6 |
| NIST 800-53 | CM-8, IA-5, SC-7 |
Description
Inventory, credential-rotate, and retire the Hybrid Deployment agents that run pipelines inside your own environment, so no stale agent retains a valid token into your network.
Rationale
Why This Matters:
- Hybrid Deployment runs the data processing inside your environment on an agent you host (via Docker, Podman, or Kubernetes), so the agent — and its authentication token — is a persistent inbound trust relationship you own and must manage
- Only metadata and logs leave your environment for Fivetran’s control plane, which means the agent itself is where your actual data is handled and is therefore the asset worth hardening
- A forgotten agent left registered after a project ends keeps a valid token and a running workload in your infrastructure with nobody watching it
Attack Prevented: Abuse of stale or orphaned agent tokens, unmanaged compute in the data path, undetected agent compromise
Prerequisites
- Hybrid Deployment enabled for the account
- Account Administrator role
- A container runtime you operate: Docker, Podman, or Kubernetes
ClickOps Implementation
Step 1: Inventory Agents
- Navigate to: Account Settings → Hybrid Deployment Agents
- Record every registered agent, the environment it runs in, its owner, and the connectors bound to it
- Reconcile that list against the container workloads actually running in your environment — an agent present in one list and not the other is a finding
Step 2: Rotate Agent Tokens
- Regenerate the authentication token for each agent on a defined schedule and immediately after any suspected compromise or operator departure
- Update the token in the agent’s runtime configuration and confirm the agent reconnects
- Treat the token as a secret with the same handling as any other production credential
Step 3: Delete Stale Agents
- Delete any agent that is no longer running, no longer owned, or no longer bound to an active connector
- Confirm the corresponding container workload is torn down in your environment, not merely deregistered
Step 4: Harden the Agent Host
- Run the agent on a dedicated, patched host or namespace with least-privilege network egress
- Apply your standard container hardening and monitoring to the agent workload
Validation & Testing
- Confirm the registered-agent list in the dashboard matches your running workloads exactly
- After a token regeneration, confirm the old token no longer authenticates
- Confirm a deleted agent’s workload stops processing and its connectors report the expected failure
4. Monitoring & Compliance
4.1 Configure Activity Logging
Profile Level: L1 (Crawl)
| Framework | Control |
|---|---|
| CIS Controls | 8.2 |
| NIST 800-53 | AU-2 |
Description
Monitor user and connector activity.
Rationale
Why This Matters:
- Activity logs provide the audit trail needed to detect unauthorized logins, permission changes, and connector tampering
- Exporting logs to a SIEM enables correlation, alerting, and retention beyond the dashboard’s native view
- Monitoring credential and SSO configuration changes catches attacker attempts to weaken authentication controls
- Without logging, account compromise and configuration drift go undetected and forensic investigation is impossible
Attack Prevented: Undetected account compromise, configuration tampering, insider misuse, post-incident blind spots
ClickOps Implementation
Step 1: Access Activity Logs
- Navigate to: Account Settings → Activity Log
- Review logged events:
- User logins
- Configuration changes
- Connector modifications
- Sync activities
Step 2: Export Logs to an External Service
- Configure an external logging service on the destination. Fivetran supports AWS CloudWatch, Azure Monitor, Datadog, Dynatrace, Google Cloud Logging, Grafana Loki, New Relic Log, and Splunk
- Note the one-per-destination constraint: a destination can be connected to only one external logging service at a time, so pick the system that is actually your investigation surface rather than the one that is easiest to wire up
- Plan gate: external logging and the Audit Trail require an Enterprise or Business Critical plan
- If you are on a plan without external logging, use the Fivetran Platform Connector instead — it is available on all plans at no additional cost and lands log and metadata tables in your destination, which you can then query or forward to your SIEM
- Set retention and alerting on the receiving system, not just on Fivetran’s dashboard view
Step 3: Monitor Key Events
- User provisioning/deprovisioning
- SSO configuration changes
- Connector credential updates
- Permission modifications
Code Implementation
Code Pack: Terraform
# Configure webhook for streaming activity logs to SIEM/monitoring
# Fivetran emits events for user logins, config changes, connector mods, syncs
resource "fivetran_webhook" "activity_log_webhook" {
count = var.webhook_url != "" ? 1 : 0
type = "account"
url = var.webhook_url
secret = var.webhook_secret
active = true
events = [
"sync_start",
"sync_end",
"status",
"connection_successful",
"connection_failure",
"dbt_run_start",
"dbt_run_succeeded",
"dbt_run_failed"
]
}
# Audit: enumerate recent activity log events via API
resource "null_resource" "audit_activity_logs" {
triggers = {
timestamp = timestamp()
}
provisioner "local-exec" {
command = <<-EOT
echo "============================================="
echo "Activity Log Audit"
echo "============================================="
echo ""
# Fetch recent activity log entries
curl -s \
"https://api.fivetran.com/v1/account/activity-log?limit=10" \
-H "Authorization: Basic $(echo -n '${var.fivetran_api_key}:${var.fivetran_api_secret}' | base64)" \
| python3 -c "
import sys, json
data = json.load(sys.stdin)
events = data.get('data', {}).get('items', [])
print(f'Recent activity log entries (last 10):')
print('')
for e in events:
print(f' [{e.get(\"created_at\", \"\")}] {e.get(\"event\", \"unknown\")} -- {e.get(\"actor\", \"system\")}')
if not events:
print(' No activity log entries found (or API permissions insufficient)')
print('')
print('Key events to monitor:')
print(' - User logins and provisioning/deprovisioning')
print(' - SSO configuration changes')
print(' - Connector credential updates')
print(' - Permission modifications')
print(' - Sync failures and errors')
" 2>/dev/null || echo "Note: Python3 required for activity log report"
EOT
}
}
4.2 Configure Sync Monitoring
Profile Level: L1 (Crawl)
| Framework | Control |
|---|---|
| CIS Controls | 8.2 |
| NIST 800-53 | CA-7 |
Description
Monitor data sync status and errors.
Rationale
Why This Matters:
- Sync failure alerts surface broken or tampered pipelines quickly, protecting data freshness and integrity
- Webhook integration with monitoring systems enables automated detection and response to abnormal sync behavior
- Prompt investigation of errors distinguishes routine failures from credential revocation or malicious interference
- Silent sync failures can mask data manipulation, exfiltration, or a compromised source connection
Attack Prevented: Undetected pipeline tampering, data integrity loss, silent connector compromise, delayed incident response
ClickOps Implementation
Step 1: Configure Notifications
- Navigate to: Notification Settings
- Enable sync failure alerts
- Configure email recipients
Step 2: Monitor Sync Health
- Review sync dashboard
- Identify failed syncs
- Investigate errors promptly
Step 3: Configure Webhooks
- Set up webhooks for events
- Integrate with monitoring systems
- Automate incident response
Code Implementation
Code Pack: Terraform
# Configure notification settings for sync failure alerts
# Integrates with email, Slack, PagerDuty, and custom webhooks
resource "fivetran_webhook" "sync_failure_webhook" {
count = var.webhook_url != "" ? 1 : 0
type = "account"
url = var.webhook_url
secret = var.webhook_secret
active = true
events = [
"sync_end",
"connection_failure",
"status"
]
}
# Audit: check current sync health across all connectors
resource "null_resource" "audit_sync_health" {
triggers = {
timestamp = timestamp()
}
provisioner "local-exec" {
command = <<-EOT
echo "Checking sync health across all connectors..."
curl -s \
"https://api.fivetran.com/v1/groups/${var.fivetran_account_id}/connectors" \
-H "Authorization: Basic $(echo -n '${var.fivetran_api_key}:${var.fivetran_api_secret}' | base64)" \
| python3 -c "
import sys, json
data = json.load(sys.stdin)
connectors = data.get('data', {}).get('items', [])
failed = [c for c in connectors if c.get('status', {}).get('sync_state') == 'failure']
paused = [c for c in connectors if c.get('paused')]
healthy = len(connectors) - len(failed) - len(paused)
print(f'Connector Health Summary:')
print(f' Total: {len(connectors)}')
print(f' Healthy: {healthy}')
print(f' Failed: {len(failed)}')
print(f' Paused: {len(paused)}')
if failed:
print('')
print('Failed connectors requiring attention:')
for c in failed:
print(f' - {c.get(\"service\", \"unknown\")}: {c.get(\"schema\", \"\")}')
" 2>/dev/null || echo "Note: Python3 required for sync health report"
EOT
}
}
4.3 Data Governance
Profile Level: L2 (Walk)
| Framework | Control |
|---|---|
| CIS Controls | 3.1 |
| NIST 800-53 | AC-3 |
Description
Implement data governance controls for sensitive data.
Rationale
Why This Matters:
- Column blocking prevents sensitive fields such as PII from ever being replicated into the destination, reducing the data footprint
- Column hashing protects sensitive values while preserving referential integrity for analytics
- Documented data flows and lineage support compliance audits and rapid scoping during an incident
- Replicating unnecessary sensitive data expands breach impact and regulatory exposure across every destination
Attack Prevented: PII over-exposure, sensitive-data sprawl, compliance violations, expanded breach blast radius
ClickOps Implementation
Step 1: Configure Column Blocking
- Navigate to connector settings
- Block sensitive columns from sync so they are never written to the destination
- Primary-key columns cannot be blocked or hashed — Fivetran needs them to identify and update rows. If a primary key is itself sensitive (an email address, a national ID), the fix is upstream schema design or a different sync strategy, not column blocking
- Column blocking and hashing apply to all connectors except Magic Folder
- Blocking a column does not reduce your MAR (monthly active rows). Treat column blocking as a privacy and data-minimization control, not a cost control — budgeting on the assumption that blocked columns are free will be wrong
Step 2: Configure Hashing
- Enable column hashing for sensitive columns you still need to join or count on
- Hashing is one-way — the original value cannot be recovered from the destination, so hash only what you will never need to read back
- Fivetran salts hashes per destination, so a hashed value is joinable across tables within one destination but not across two different destinations. Design cross-destination joins accordingly rather than discovering the mismatch in production
Step 3: Document Data Flows
- Inventory all connectors
- Document data destinations
- Maintain data lineage
Code Implementation
Code Pack: Terraform
# Data governance: column blocking and hashing for sensitive data (L2+)
# Prevents PII replication and maintains referential integrity
# Block sensitive columns from sync (L2+)
# Column blocking prevents specific columns from being replicated to the destination
resource "fivetran_connector_schema_config" "column_blocking" {
for_each = var.profile_level >= 2 ? var.blocked_columns : {}
connector_id = each.key
schema_change_handling = "BLOCK_ALL"
# Note: Column-level blocking is configured per-schema within the connector.
# The fivetran_connector_schema_config resource manages schema-level settings.
# For column-level blocking, use the schema configuration to disable
# specific columns containing PII or sensitive data.
#
# Blocked columns for this connector:
# %{ for col in each.value ~}
# - ${col}
# %{ endfor ~}
}
# Hash sensitive columns during sync (L2+)
# Hashing replaces column values with one-way hashes for referential integrity
resource "null_resource" "configure_column_hashing" {
for_each = var.profile_level >= 2 ? var.hashed_columns : {}
triggers = {
connector_id = each.key
columns = join(",", each.value)
}
provisioner "local-exec" {
command = <<-EOT
echo "============================================="
echo "Column Hashing Configuration (L2+)"
echo "============================================="
echo ""
echo "Connector: ${each.key}"
echo "Columns to hash:"
%{ for col in each.value ~}
echo " - ${col}"
%{ endfor ~}
echo ""
echo "Column hashing is configured via Fivetran Dashboard:"
echo " 1. Navigate to connector settings"
echo " 2. Go to Schema tab"
echo " 3. Select the column to hash"
echo " 4. Enable 'Hash this column'"
echo ""
echo "Hashing preserves referential integrity while protecting PII."
echo "Hashed values are consistent -- the same input always produces"
echo "the same hash -- enabling joins across tables."
EOT
}
}
# Audit: document data flows for governance
resource "null_resource" "audit_data_flows" {
count = var.profile_level >= 2 ? 1 : 0
triggers = {
profile_level = var.profile_level
timestamp = timestamp()
}
provisioner "local-exec" {
command = <<-EOT
echo "============================================="
echo "Data Governance Audit (L2+)"
echo "============================================="
echo ""
# Inventory all connectors and destinations
curl -s \
"https://api.fivetran.com/v1/groups" \
-H "Authorization: Basic $(echo -n '${var.fivetran_api_key}:${var.fivetran_api_secret}' | base64)" \
| python3 -c "
import sys, json
data = json.load(sys.stdin)
groups = data.get('data', {}).get('items', [])
print(f'Data Flow Inventory:')
print(f' Groups (destinations): {len(groups)}')
for g in groups:
print(f' - {g.get(\"name\", \"unnamed\")} (ID: {g.get(\"id\", \"\")})')
print('')
print('Data Governance Checklist:')
print(' [1] Inventory all connectors and their data sources')
print(' [2] Document data destinations and schemas')
print(' [3] Block sensitive/PII columns from sync')
print(' [4] Hash columns requiring referential integrity')
print(' [5] Maintain data lineage documentation')
print(' [6] Review data flows quarterly')
" 2>/dev/null || echo "Note: Python3 required for data flow audit report"
EOT
}
}
5. Compliance Quick Reference
SOC 2 Trust Services Criteria Mapping
| Control ID | Fivetran Control | Guide Section |
|---|---|---|
| CC6.1 | SSO/SAML | 1.1 |
| CC6.2 | RBAC | 2.1 |
| CC6.6 | Session timeout | 1.4 |
| CC6.7 | Encryption | 3.3 |
| CC7.2 | Activity logging | 4.1 |
NIST 800-53 Rev 5 Mapping
| Control | Fivetran Control | Guide Section |
|---|---|---|
| IA-2 | SSO | 1.1 |
| AC-2 | SCIM provisioning | 2.3 |
| AC-6 | Least privilege | 2.1 |
| SC-12 | Credential security | 3.1 |
| IA-5 | External secret management | 3.4 |
| CM-8 | Hybrid Deployment agent inventory | 3.5 |
| AU-2 | Audit logging | 4.1 |
Appendix A: Plan Compatibility
| Feature | Standard | Enterprise | Business Critical |
|---|---|---|---|
| SAML SSO | ✅ | ✅ | ✅ |
| Custom Session Timeout | ❌ | ✅ | ✅ |
| SCIM Provisioning | ❌ | ✅ | ✅ |
| Custom Roles | ❌ | ✅ | ✅ |
| External Logging & Audit Trail | ❌ | ✅ | ✅ |
| Fivetran Platform Connector | ✅ | ✅ | ✅ |
| External Secrets Managers (private preview) | ❌ | ❌ | ✅ |
| Private Networking | ❌ | Add-on | Add-on |
| Advanced Security | ❌ | ❌ | ✅ |
Appendix B: References
Official Fivetran Documentation:
- Fivetran Security Documentation
- Getting Started
- Single Sign-On
- Account Settings
- SCIM Provisioning
- External Secrets Managers
- Hybrid Deployment Agents
- Column Blocking and Hashing
- Logs and External Logging Services
- Fivetran IP Addresses
- SSO with Okta
- SSO with Microsoft Entra ID
API & Developer Documentation:
Security Incidents:
- No major public security incidents identified affecting the Fivetran platform.
Changelog
| Date | Version | Maturity | Changes | Author |
|---|---|---|---|---|
| 2026-08-08 | 0.2.0 | draft | Currency pass against Fivetran docs: corrected 2.3 (SCIM does NOT map IdP groups to teams/roles; IdP becomes the only user-management path), 1.1/1.3 (Single Sign-On page name, mandatory email NameID and RSA-SHA256 assertion signing), 1.2 (named Google OAuth as a third login path to close), 4.1 (real external logging destination list, one service per destination, Enterprise/Business Critical gate, all-plans Platform Connector alternative), 4.3 (primary keys cannot be blocked or hashed, one-way per-destination-salted hashing, blocking does not reduce MAR, Magic Folder exception), 3.2 (prefer hostname over IP allowlisting; IPs may change without notice), 2.1 (custom roles are Enterprise/Business Critical; role names softened pending a resolvable roles doc); added 3.4 External Secrets Managers (private preview) and 3.5 Hybrid Deployment agent governance; added missing Attack Prevented lines to 1.1 and 3.1; pruned Trust Center, /security marketing, compliance-badge, and whitepaper links from Appendix B and added the IP, logs, SCIM, secrets-manager, hybrid-agent, and column-blocking docs. Tier 2 survey found no CIS Benchmark, DISA STIG, or CISA SCuBA baseline for Fivetran; Tier 3/4 not surveyed this pass. | Claude Code (Opus 4.8) |
| 2025-02-05 | 0.1.0 | draft | Initial guide with SSO, access controls, and connector security | Claude Code (Opus 4.5) |
Contributing
Found an issue or want to improve this guide?
- Report outdated information: Open an issue with tag
content-outdated - Propose new controls: Open an issue with tag
new-control - Submit improvements: See Contributing Guide