Skip to content

Implement Oracle TCPS Listener and automated Wallet configuration#419

Merged
sahsagar-google merged 22 commits intogoogle:masterfrom
sahsagar-google:tls-setup
Apr 9, 2026
Merged

Implement Oracle TCPS Listener and automated Wallet configuration#419
sahsagar-google merged 22 commits intogoogle:masterfrom
sahsagar-google:tls-setup

Conversation

@sahsagar-google
Copy link
Copy Markdown
Collaborator

@sahsagar-google sahsagar-google commented Mar 22, 2026

Automated TLS Encryption for Oracle Database (Multi-Node & 26ai Compliant)

Summary

This PR implements end-to-end automation for securing Oracle Database deployments using Transport Layer Security (TLS). It introduces enterprise-grade Terraform resources for Certificate Authority (CA) integration and secure Secret Manager storage, engineered to natively support multi-node Data Guard clusters.

Additionally, it introduces a new Ansible role (tls-setup) that dynamically provisions node-specific Oracle Wallets and Listeners. By utilizing a non-destructive block-append strategy, the automation is fully compliant with both legacy 19c deployments and modern Oracle 23ai/26ai WALLET_ROOT and Transparent Data Encryption (TDE) architectures.

Key Changes

1. Infrastructure Security & Multi-Node Support (Terraform)

  • terraform/main.tf & terraform/variables.tf:
    • Cluster-Aware PKI Generation: Utilizes for_each loops to dynamically mint distinct Private Keys, CSRs, Certificates (google_privateca_certificate), and DNS A-Records for every node in a deployment (e.g., Primary and Standby).
    • Zero-Trust Secret Management: Cryptographic material (Key, Cert Chain, and generated Wallet Password) is packed into a single JSON payload and stored securely in google_secret_manager_secret per node.
    • IAM Hardening: VMs are strictly granted secretAccessor rights only to their specific node-level secret, ensuring least-privilege access post-deployment.

2. Configuration Management (Ansible)

  • roles/tls-setup/ (New Role):
    • Dynamic Node-Level Secret Retrieval: Ansible natively targets {{ inventory_hostname }}-tls-secret via gcloud to ensure each Data Guard node fetches its correct, unique cryptographic payload.
    • Non-Destructive Configuration (blockinfile): Safely appends TCPS parameters to listener.ora and sqlnet.ora without wiping out critical DBCA-generated defaults (such as standard TCP ports and native TDE encryption paths).
    • Oracle 26ai & TDE Compliance: Standardized the wallet directory to {{ oracle_base }}/admin/{{ oracle_db_name }}/wallet_root/tls. Introduced conditional Jinja2 logic directly inside the blockinfile block to explicitly map WALLET_LOCATION for 19c databases, while relying natively on the system-level WALLET_ROOT for 23ai/26ai to prevent TDE conflicts.
    • Idempotent Wallet Automation: Automates orapki and openssl to create auto-login wallets (cwallet.sso), splitting the commands into distinct tasks with explicit creates parameters to ensure perfect idempotency.
    • Explicit Verification: Added debug tasks to run and print lsnrctl status LISTENER_TCPS directly to the Ansible standard output, providing immediate, verifiable proof of the TCPS endpoint in the pipeline logs.
    • Automated Client Provisioning: Automatically packages the Root CA truststore into a readily accessible client_bundle.zip directly in the Oracle user's home directory (/home/oracle/) to simplify secure downstream client connectivity.
  • roles/db-start/templates/:
    * Updated start_all.sh.j2 and stop_all.sh.j2 to ensure the new dedicated LISTENER_TCPS starts and stops cleanly alongside the default database services during reboot or dbora.service cycles.
  • Core Dependencies & Secret Validation (main.yml & validate_passwords.yml):
    • Fixed a dependency execution bug to ensure the Google Cloud CLI is explicitly installed on database hosts when TLS is enabled.
    • Hardened the secret fetching tasks to gracefully fallback to reporting Ansible .msg variables instead of .stderr when executables fail or are missing, ensuring clean and accurate pipeline error outputs.

3. Orchestration & Config

  • install-oracle.sh: Streamlined argument parsing based on reviewer feedback. Removed the redundant --enable-tls flag, now intelligently inferring TLS enablement directly from the presence of the secret.
  • config-db.yml: Integrated the conditional execution of the tls-setup role into the core database configuration playbook.
  • presubmit_tests/26ai-dg.tfvars: Updated test configuration to validate the new TLS pathways on multi-node Data Guard deployments.

Testing & Verification

The changes were verified via full end-to-end deployments using the automated CI/CD test harnesses for Data Guard topologies. The pipeline now explicitly captures and outputs the listener status for immediate visual validation, alongside the implicit proof of a successful deployment.

1. Non-Destructive Integration Proof

Wallet Files Generated and Secured:
The find module successfully located the wallet files and applied the strict 0600 permissions so Oracle could read them without throwing ownership errors.

TASK [tls-setup : tls-setup | Explicitly Secure All Wallet Files] **************
ok: [192.168.10.68] => (item={'path': '/u01/app/oracle/admin/orcl/wallet_root/tls/cwallet.sso', 'mode': '0600'...
ok: [192.168.10.68] => (item={'path': '/u01/app/oracle/admin/orcl/wallet_root/tls/ewallet.p12', 'mode': '0600'...

Explicit Listener Verification: The pipeline logs now explicitly output the results of lsnrctl status LISTENER_TCPS, visually confirming the secure protocol is active and correctly bound to port 2484 while leaving the default TCP listener untouched:

 Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCPS)(HOST=github-presubmit-26ai-dg-...)(PORT=2484)))
  STATUS of the LISTENER
  ------------------------
  Alias                     LISTENER_TCPS
  Start Date                22-MAR-2026 21:00:44
  Listening Endpoints Summary...
    (DESCRIPTION=(ADDRESS=(PROTOCOL=tcps)(HOST=github-presubmit-26ai-dg-...)(PORT=2484)))
  The command completed successfully

Database Startup Success:
The pipeline successfully completed the db-start sequence (via dbora.service). Because the native dbstart script strictly relies on the default TCP port (1521) to verify listener health, this proves our blockinfile strategy successfully preserved the default DBCA listener.

TDE Encryption Preserved:
The database successfully mounted and opened without ORA decryption errors. This proves that our conditional logic successfully suppressed the global WALLET_LOCATION override on 26ai, allowing the database engine to natively read its TDE keys.

2. Multi-Node Replication Proof

Data Guard Synchronization:
The pipeline successfully executed the dg-config role, which natively runs a DGMGRL> SHOW CONFIGURATION verification step. The resulting SUCCESS state confirms that the Primary and Standby nodes successfully exchanged passwords, started their respective listeners without crashing, and established robust Data Guard communication over the newly configured environment.

Result:
The pipeline returned an ansible_completed_success state with zero fatal errors.

User Guide

go/user-guide-otk-tls-encryption

@sahsagar-google
Copy link
Copy Markdown
Collaborator Author

Took care of Marc's feedback on the earlier PR (closed unintentionally)
documented here https://docs.google.com/document/d/1rOE8P-E7n1v97HEfNm2lnzkC4QrxQ9hwFwxfb9joAQM/edit?resourcekey=0-8gkNr1nhc1XKOt7c5RMwwg&tab=t.0

@sahsagar-google sahsagar-google self-assigned this Mar 24, 2026
Copy link
Copy Markdown
Member

@mfielding mfielding left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding a few comments based on observing the code, but I do want to actually test a real deployment too.

But I should ask this question first: I noticed that the actual certificate authority and cloud DNS setup weren't in the terraform config. Is this because we need them to be shared across deployments? If so, can you create a sample Terraform config for the one-time setup we need?

And as a bonus, it will help me test this out myself too.

Another comment not associated with a file changed here:

We open a port on the host firewall for the listener in

- name: Open listener port in firewall

I imaging that with a TCPS listener, we'd want to open the TCPS listener port only.

Comment thread roles/tls-setup/tasks/main.yml Outdated
Comment thread terraform/variables.tf Outdated
Comment thread terraform/main.tf Outdated
Comment thread terraform/variables.tf
Comment thread install-oracle.sh Outdated
Comment thread roles/db-start/templates/start_all.sh.j2 Outdated
Comment thread presubmit_tests/26ai-dg.tfvars
@mfielding
Copy link
Copy Markdown
Member

@sahsagar-google just to keep the history of changes and comments here, could you please merge-commit https://github.com/sahsagar-google/oracle-toolkit/tree/fix-tls-review-comments here? I don't mind the extra commit in the history. (Or, alternately, grant me privileges on your repo and I can do it on your behalf)

AI-suggested commands:

# 1. Update the original branch locally
git fetch origin
git checkout tls-setup
git merge origin/fix-review-comments

# 2. Update the original PR on GitHub
git push origin tls-setup

@google-oss-prow google-oss-prow Bot added size/XL and removed size/L labels Apr 2, 2026
Copy link
Copy Markdown
Member

@mfielding mfielding left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good! I'll do some testing on my end, but here are a few quick comments to start.

Comment thread install-oracle.sh Outdated
Comment thread roles/db-start/templates/start_all.sh.j2 Outdated
Comment thread roles/lsnr-create/tasks/main.yml Outdated
Comment thread terraform/main.tf Outdated
Comment thread terraform/main.tf Outdated
Comment thread terraform/variables.tf Outdated
Comment thread terraform/variables.tf Outdated
Copy link
Copy Markdown
Member

@mfielding mfielding left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for all your work here. As part of testing to get a config working myself, here are a few things that came up.

Comment thread install-oracle.sh Outdated
Comment thread terraform/variables.tf Outdated
Comment thread terraform/variables.tf Outdated
Comment thread terraform/main.tf Outdated
Comment thread terraform/main.tf Outdated
Comment thread terraform/tls-prerequisites/main.tf
Comment thread terraform/tls-prerequisites/main.tf
Comment thread terraform/tls-prerequisites/main.tf
Comment thread roles/tls-setup/tasks/main.yml
Copy link
Copy Markdown
Member

@mfielding mfielding left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One more request after going through

Comment thread terraform/tls-prerequisites/main.tf
Comment thread roles/tls-setup/tasks/main.yml
Copy link
Copy Markdown
Member

@mfielding mfielding left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I finally got a successful connection in my 26ai test, but it took a few more fixes to work, notably for dynamic listener registration, and sqlnet.ora/listener.ora syncing.

I've added comments below.

Comment thread roles/tls-setup/tasks/main.yml
Comment thread roles/tls-setup/tasks/main.yml
Comment thread roles/tls-setup/tasks/main.yml
Comment thread roles/db-create/templates/dbca.rsp.sh.j2 Outdated
Comment thread roles/db-create/templates/dbca.rsp.sh.j2 Outdated
Comment thread roles/db-create/templates/dbca.rsp.sh.j2
Comment thread install-oracle.sh Outdated
Comment thread roles/tls-setup/tasks/main.yml Outdated
Comment thread roles/tls-setup/tasks/main.yml
Comment thread roles/tls-setup/tasks/main.yml Outdated
@sahsagar-google
Copy link
Copy Markdown
Collaborator Author

Adding a few comments based on observing the code, but I do want to actually test a real deployment too.

But I should ask this question first: I noticed that the actual certificate authority and cloud DNS setup weren't in the terraform config. Is this because we need them to be shared across deployments? If so, can you create a sample Terraform config for the one-time setup we need?

And as a bonus, it will help me test this out myself too.

Another comment not associated with a file changed here:

We open a port on the host firewall for the listener in

- name: Open listener port in firewall

I imaging that with a TCPS listener, we'd want to open the TCPS listener port only.

for the CA/DNS setup, I left them out of the main config since they're shared infrastructure, but I just added a one-time setup example (with a sample .tfvars) in terraform/data-guard-tls/ so you can easily test it out (I'm testing it as I speak too).

Also, great call on the firewall. I updated the listener role to only open the TCPS port when TLS is enabled instead of opening both.

Comment thread roles/tls-setup/tasks/main.yml
Comment thread terraform/terraform.tfvars.tls.example
Comment thread terraform/terraform.tfvars.tls.example
Copy link
Copy Markdown
Member

@mfielding mfielding left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good! Just some minor comments.

Comment thread docs/tls-encryption-user-guide.md Outdated
Comment thread docs/tls-encryption-user-guide.md
Comment thread docs/tls-encryption-user-guide.md Outdated
Comment thread docs/tls-encryption-user-guide.md
Comment thread docs/tls-encryption-user-guide.md Outdated
Comment thread docs/tls-encryption-user-guide.md Outdated
Comment thread install-oracle.sh Outdated
Comment thread roles/ora-host/tasks/validate_passwords.yml Outdated
Comment thread docs/tls-encryption-user-guide.md Outdated
Comment thread docs/tls-encryption-user-guide.md Outdated
Copy link
Copy Markdown
Member

@mfielding mfielding left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good My tests succeed too.

@google-oss-prow
Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: mfielding, sahsagar-google

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@sahsagar-google sahsagar-google merged commit 269f47d into google:master Apr 9, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants