Skip to content

Commit e022008

Browse files
committed
docs(oracle19c): durable Oracle-specific documentation
Concise docs covering only the Oracle-specific deltas from generic RDS broker behavior: README (offering + deltas), licensing (SE2+License-Included rationale + SE2-vs-EE deltas / ISSO risk-deviation), hardening-baseline (hardened values + SC-8/SC-13 + platform-SG dependency; links the STIG overlay repo), limitations, connection-examples (TCPS), design-notes (durable why), operator credential- rotation (Oracle master is DBA-class).
1 parent 1b19daf commit e022008

7 files changed

Lines changed: 359 additions & 0 deletions

File tree

docs/oracle19c/README.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Oracle Database 19c on Amazon RDS
2+
3+
Oracle Database **19c Standard Edition 2 (SE2)**, **License Included**, offered as
4+
an Amazon RDS plan on the existing `aws-rds` service. It is provisioned, bound, and
5+
rotated exactly like the other RDS plans (PostgreSQL / MySQL) — the generic
6+
`cf create-service` / `cf bind-service` / `VCAP_SERVICES` flow is documented in the
7+
top-level [README.md](../../README.md) and applies unchanged. This directory
8+
documents **only** the Oracle-specific deltas.
9+
10+
## Plan
11+
12+
`oracle-se2-license-included-dev` — a **dev/test tier** plan (the `-dev` suffix
13+
mirrors the sandbox-only `micro-psql` / `small-mysql` tier). **Not
14+
production-ready.**
15+
16+
- `db.t3.medium`, 20 GB `gp3`, `encrypted: true` (KMS at rest)
17+
- private only (no public accessibility)
18+
- backup retention **14 days**
19+
- `oracle-se2` 19c, `licenseModel: license-included`
20+
21+
## Oracle-specific deltas you must know
22+
23+
- **TLS on port 2484 (TCPS), not 1521.** RDS Oracle serves TLS on a dedicated TCPS
24+
listener. The binding advertises `port=2484`, `protocol=tcps`. Plaintext `1521`
25+
is the RDS default port. See [connection-examples.md](connection-examples.md).
26+
- **Fixed SID `ORCL`.** RDS Oracle constrains DBName/SID to ≤8 uppercase chars; the
27+
broker uses a stable `ORCL`. The unique per-instance identifier is the
28+
`DBInstanceIdentifier`, not the SID.
29+
- **Master credential per binding.** Same model as the other RDS engines — the
30+
binding returns the instance master credential; the customer creates
31+
least-privilege in-database users. This matters **more** on Oracle because the
32+
RDS master is **DBA-class**. See [limitations.md](limitations.md) and
33+
[../../ops/oracle19c/credential-rotation.md](../../ops/oracle19c/credential-rotation.md).
34+
- **`ENABLE_ORACLE` staged-rollout flag.** Oracle provisioning is off unless the
35+
broker environment sets `ENABLE_ORACLE`. This gates when the new offering appears
36+
— it is **not** a security control.
37+
- **License Included (no BYOL).** AWS holds the Oracle license and bundles it into
38+
the instance price — no license key, no attestation. See [licensing.md](licensing.md).
39+
40+
## Pages
41+
42+
- [licensing.md](licensing.md) — SE2 + License Included; SE2-vs-EE deltas
43+
- [hardening-baseline.md](hardening-baseline.md) — hardened parameter/option/log baseline
44+
- [connection-examples.md](connection-examples.md) — TCPS connect strings + client examples
45+
- [limitations.md](limitations.md) — Oracle-specific limitations
46+
- [design-notes.md](design-notes.md) — the durable "why" behind the design
47+
- [../../ops/oracle19c/credential-rotation.md](../../ops/oracle19c/credential-rotation.md) — rotation
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Oracle 19c — connecting a bound app
2+
3+
After `cf bind-service`, the credentials appear in `VCAP_SERVICES` under the
4+
`aws-rds` service. Reading credentials (`cf env`), opening space egress
5+
(`cf bind-security-group trusted_local_networks_egress`), and tunnelling from a
6+
laptop (`cf ssh -L`) are identical to the Postgres/MySQL flow — see the top-level
7+
[README.md](../../README.md). This page covers only the Oracle-specific connection
8+
detail.
9+
10+
## Binding payload (Oracle-specific keys)
11+
12+
```json
13+
{
14+
"uri": "oracle://APP_USER:REDACTED@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCPS)(HOST=my-oracle.abc.us-gov-west-1.rds.amazonaws.com)(PORT=2484))(CONNECT_DATA=(SID=ORCL)))",
15+
"jdbcUrl": "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCPS)(HOST=my-oracle.abc.us-gov-west-1.rds.amazonaws.com)(PORT=2484))(CONNECT_DATA=(SID=ORCL)))",
16+
"port": "2484",
17+
"protocol": "tcps",
18+
"service_name": "ORCL",
19+
"sid": "ORCL",
20+
"ssl_required": "true",
21+
"ssl_server_dn_match": "true",
22+
"ca_cert_bundle_url": "https://truststore.pki.us-gov-west-1.rds.amazonaws.com/global/global-bundle.pem"
23+
}
24+
```
25+
26+
The binding uses a full Oracle connect `DESCRIPTION` on the **TCPS listener (port
27+
2484)** — not EZConnect, which cannot express `PROTOCOL=TCPS`. `ssl_required=true`
28+
and `ssl_server_dn_match=true` tell the client to encrypt **and** verify the server
29+
identity against `ca_cert_bundle_url` (the GovCloud RDS CA bundle). No hardcoded
30+
server-cert DN is published — the RDS cert subject is Amazon-owned and rotates, so
31+
the driver derives it from the trusted cert. The instance uses the RDS default RSA CA
32+
(`rds-ca-rsa2048-g1`), compatible with the ECDHE_RSA cipher.
33+
34+
## JDBC (Java)
35+
36+
```bash
37+
# import the GovCloud RDS CA bundle (ca_cert_bundle_url from the binding):
38+
wget https://truststore.pki.us-gov-west-1.rds.amazonaws.com/global/global-bundle.pem
39+
keytool -importcert -alias rds-ca -file global-bundle.pem \
40+
-keystore truststore.jks -storepass "$TRUSTSTORE_PW" -noprompt
41+
```
42+
43+
```java
44+
String url = System.getenv("ORACLE_JDBC_URL"); // the TCPS jdbcUrl from the binding
45+
Properties p = new Properties();
46+
p.put("user", username);
47+
p.put("password", password);
48+
p.put("oracle.net.ssl_server_dn_match", "true"); // ssl_server_dn_match=true
49+
p.put("javax.net.ssl.trustStore", "truststore.jks");
50+
p.put("javax.net.ssl.trustStorePassword", System.getenv("TRUSTSTORE_PW"));
51+
Connection c = DriverManager.getConnection(url, p);
52+
```
53+
54+
## SQL*Plus
55+
56+
```bash
57+
# full TCPS connect descriptor (EZConnect cannot express PROTOCOL=TCPS):
58+
sqlplus 'APP_USER@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCPS)(HOST=<host>)(PORT=2484))(CONNECT_DATA=(SID=ORCL)))'
59+
```
60+
61+
Configure a wallet / truststore holding the imported GovCloud RDS CA bundle so the
62+
client trusts the server certificate.
63+
64+
## Python (python-oracledb, thin mode)
65+
66+
```python
67+
import oracledb
68+
69+
dsn = (
70+
"(DESCRIPTION=(ADDRESS=(PROTOCOL=TCPS)(HOST=<host>)(PORT=2484))"
71+
"(CONNECT_DATA=(SID=ORCL))"
72+
"(SECURITY=(SSL_SERVER_DN_MATCH=TRUE)))"
73+
)
74+
# config_dir points at a directory holding the imported GovCloud RDS CA bundle
75+
# (ca_cert_bundle_url) as the trust store the thin driver reads.
76+
conn = oracledb.connect(user=username, password=password, dsn=dsn,
77+
config_dir="/path/to/wallet")
78+
```
79+
80+
The listener negotiates **TLS 1.2** (RDS Oracle has no 1.3) with the FIPS-validated
81+
AEAD cipher `TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384`; `FIPS.SSLFIPS_140=TRUE` means
82+
the client **must** offer a FIPS cipher or the handshake fails. See
83+
[hardening-baseline.md](hardening-baseline.md).
84+
85+
> **Use a least-privilege user, not the master.** The bound credential is the
86+
> instance master, which on Oracle is **DBA-class**. Connect as the master once to
87+
> create a least-privilege application user, then run your app as that user.
88+
> Creating in-database users is the customer's responsibility — see
89+
> [limitations.md](limitations.md).

docs/oracle19c/design-notes.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Oracle 19c — design notes
2+
3+
The durable rationale behind the Oracle offering. The code and tests are the source
4+
of truth; this captures the non-obvious "why".
5+
6+
## SE2 + License Included
7+
8+
License Included is **SE2-only** on RDS; Enterprise Edition is **BYOL-only** — they
9+
are mutually exclusive. License Included is chosen to remove the unlicensed-Oracle
10+
liability: AWS holds the license and it is inseparable from the running instance, so
11+
cloud.gov cannot facilitate an unlicensed Oracle DB on GSA-operated infrastructure
12+
(BYOL would only reallocate that liability via attestation, not remove it). The
13+
consequence is SE2, which lacks the EE-only features (notably Oracle-native TDE and
14+
FGA). Those SE2 STIG deltas are accepted as an ISSO risk/deviation, with RDS-KMS
15+
at-rest encryption and standard/unified auditing as the compensating controls. If a
16+
control is ever found to *require* TDE or FGA, the edition decision must be re-opened
17+
(EE + BYOL). See [licensing.md](licensing.md).
18+
19+
## STIG validation lives in the overlay, not the broker
20+
21+
The broker is a Go service that provisions and configures RDS. STIG validation
22+
(InSpec/Cinc controls, SQL assessment, RDS-applicability mapping, evidence) lives in
23+
the separate `cg-oracle-database-19c-stig-overlay` repo. **The broker never runs
24+
InSpec/Cinc.** This keeps a clean separation of duties — the thing being audited does
25+
not audit itself — avoids a Ruby/InSpec runtime in a Go broker, and lets controls
26+
evolve independently. **Broker configures; overlay validates.** See
27+
[hardening-baseline.md](hardening-baseline.md).
28+
29+
## Hardened baseline as embedded YAML behind a per-engine abstraction
30+
31+
Engine behavior is dispatched through an `RDSBaseline` engine-strategy interface
32+
(`mysqlBaseline`, `postgresBaseline`, `oracle19cBaseline`), and the hardened values
33+
live as structured YAML under `services/rds/baselines/oracle19c/` rather than
34+
hard-coded Go conditionals. This makes the hardening values directly reviewable by a
35+
security reviewer, keeps Oracle logic out of scattered `if DbType == "..."`
36+
conditionals, and keeps the declarative baseline portable if RDS brokerage ever
37+
moves to CSB (which is also declarative). Broker *runtime* behavior (async
38+
lifecycle, credential encryption, state) is not portable and is deliberately out of
39+
the baseline files.
40+
41+
## Why `ENABLE_ORACLE` exists
42+
43+
`ENABLE_ORACLE` gates a staged rollout of a new offering not yet validated on a live
44+
foundation — it governs when the offering appears, not per-request approval. It is
45+
**not** a security or boundary control: Oracle uses the same credential model as the
46+
Postgres/MySQL plans (master credential per binding; customer creates least-privilege
47+
users).
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Oracle 19c — hardening baseline
2+
3+
Every brokered Oracle instance is provisioned with a broker-managed hardened
4+
parameter group, default audit log exports, and an SSL option group. The
5+
authoritative values live in the reviewable, embedded baseline files under
6+
[`services/rds/baselines/oracle19c/`](../../services/rds/baselines/oracle19c/); this
7+
page documents the durable deltas and the controls they map to.
8+
9+
## Parameter group (`baselines/oracle19c/parameters.yml`)
10+
11+
| Parameter | Value | Apply | STIG intent |
12+
|-----------|-------|-------|-------------|
13+
| `audit_trail` | `DB,EXTENDED` | pending-reboot | enable DB auditing |
14+
| `audit_sys_operations` | `TRUE` | pending-reboot | audit privileged SYS ops |
15+
| `sec_case_sensitive_logon` | `TRUE` | immediate | case-sensitive passwords |
16+
| `remote_login_passwordfile` | `NONE` | pending-reboot | disable remote OS password-file auth |
17+
| `resource_limit` | `TRUE` | immediate | enforce profile resource limits |
18+
| `sql92_security` | `TRUE` | pending-reboot | SQL92 DML-predicate least privilege |
19+
20+
`pending-reboot` parameters take effect after a reboot; the broker surfaces
21+
pending-reboot state via the existing async/modify path. All six are base Oracle
22+
init parameters available in SE2 (none are EE-only), so the baseline fully applies.
23+
24+
## Log exports (`baselines/oracle19c/log_exports.yml`)
25+
26+
Default CloudWatch exports: `alert`, `audit`, `listener`. `trace` and `oemagent` are
27+
opt-in (high-volume / requires OEM).
28+
29+
## Option group — SSL / TCPS (SC-8 / SC-8(1) / SC-13)
30+
31+
The create path provisions an RDS Oracle **SSL option group** and attaches it,
32+
serving TLS on a dedicated **TCPS listener (port 2484)**:
33+
34+
| Setting | Value | Intent |
35+
|---------|-------|--------|
36+
| listener port | `2484` (TCPS) | separate TLS listener (RDS Oracle serves TLS off-port) |
37+
| `SQLNET.SSL_VERSION` | `1.2` | TLS 1.2 — RDS Oracle ceiling (no 1.3); acceptable for FedRAMP Moderate |
38+
| `SQLNET.CIPHER_SUITE` | `TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384` | FIPS AEAD suite; RSA-CA-compatible |
39+
| `FIPS.SSLFIPS_140` | `TRUE` | FIPS 140 crypto mode |
40+
41+
This delivers encryption-in-transit (SC-8 / SC-8(1)) with FIPS-validated crypto
42+
(SC-13); DISA Oracle 19c STIG **V-270579** (SC-8(2)) + **V-270571** (SC-13). The
43+
instance uses the RDS default RSA CA (`rds-ca-rsa2048-g1`), compatible with the
44+
ECDHE_RSA cipher (an ECDSA-only suite would need the ECC CA and is rejected
45+
fail-closed before the AWS call). `FIPS.SSLFIPS_140=TRUE` means clients **must**
46+
negotiate a FIPS cipher or the handshake fails. No attack-surface options (XML DB
47+
HTTP listener, `extproc`, Java VM, APEX) are enabled.
48+
49+
> **TLS-only depends on the platform security group (durable operational fact).**
50+
> The broker provisions + attaches the SSL option and expresses the 2484 intent, but
51+
> **cannot** open `2484` ingress or deny plaintext `1521` — that is a platform
52+
> security-group change owned by cg-provision, outside the broker's IAM. TLS-only
53+
> enforcement requires cg-provision to allow `2484` and deny `1521`.
54+
55+
## STIG validation lives in the overlay
56+
57+
SQL-level hardening (profiles, default-account lockout, unified audit policies,
58+
PUBLIC-grant review) and full STIG validation are **not** in the broker. They live
59+
in the separate
60+
[`cg-oracle-database-19c-stig-overlay`](https://github.com/cloud-gov/cg-oracle-database-19c-stig-overlay)
61+
repo, whose `control-layers.yml` classifies each control by layer
62+
(`broker_infra`, `aws_rds_parameter_group`, `aws_rds_option_group`, `sql_hardening`,
63+
`aws_inherited`, `not_applicable_rds`, …) — which is what stops the ~33 OS/listener
64+
controls from failing misleadingly on managed RDS. The broker configures; the
65+
overlay validates. See [design-notes.md](design-notes.md).

docs/oracle19c/licensing.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Oracle 19c — licensing (SE2 + License Included)
2+
3+
The `oracle-se2-license-included-dev` plan uses Amazon RDS **License Included**: AWS
4+
holds the Oracle Database license and bundles it into the instance price. Customers
5+
do **not** buy or bring an Oracle license — no license key, no BYOL entitlement, no
6+
attestation, no license parameter. There is **no unlicensed state**: cloud.gov never
7+
facilitates an unlicensed Oracle database, because the license is held by AWS and is
8+
inseparable from the running instance.
9+
10+
## Why License Included (and therefore SE2)
11+
12+
- **License Included is Standard Edition 2 (SE2) only** on RDS; Enterprise Edition
13+
is **BYOL-only**. The two are mutually exclusive — you cannot have License
14+
Included + EE. Choosing License Included to remove the unlicensed-Oracle liability
15+
means the offering is **SE2**.
16+
- **Cost.** The bundled license makes an Oracle plan cost more than an
17+
open-source-engine plan. Cost is handled the same way as the Postgres/MySQL RDS
18+
plans — the instance carries `free: false` and the underlying AWS charge is
19+
passed through to agencies as **cloud.gov resource credits** (this broker's
20+
catalog does not itself carry a per-plan price figure).
21+
22+
## SE2 STIG deviations (ISSO risk/deviation)
23+
24+
SE2 does not include the Enterprise-Edition-only security features. The material
25+
gaps, and how they are handled on this offering:
26+
27+
| EE-only feature (absent in SE2) | Handling on this offering |
28+
|---|---|
29+
| **Oracle-native TDE** (tablespace / column encryption) | **RDS storage-level encryption at rest (AES-256 / KMS)** (`encrypted: true`) — edition-independent, the same at-rest control the Postgres/MySQL plans use. |
30+
| **Fine-Grained Auditing (FGA)** | **Standard / unified (mixed-mode) auditing** via `audit_trail` + CloudWatch `audit` export. (Even on EE, RDS does not export FGA events to CloudWatch.) |
31+
| Oracle Database Vault | **Not applicable** — unsupported on RDS even for EE. |
32+
| VPD, Label Security, Data Redaction, Partitioning, Data Guard | Not available on SE2; not part of this offering's control posture. |
33+
34+
Whether a specific STIG control is satisfied by **RDS-KMS at-rest encryption** in
35+
place of Oracle-native TDE, and by **standard/unified auditing** in place of FGA, is
36+
a control-interpretation decision recorded as an **ISSO risk/deviation acceptance**.
37+
If a control is found to *require* Oracle-native TDE or FGA, the edition decision
38+
(EE + BYOL, licensing handled by attestation) must be re-opened — see
39+
[design-notes.md](design-notes.md).
40+
41+
## References
42+
43+
- [design-notes.md](design-notes.md) — SE2 + License Included rationale
44+
- [README.md](README.md) — the `oracle-se2-license-included-dev` plan
45+
- AWS: *Licensing Amazon RDS for Oracle* (License Included is SE2-only)
46+
- AWS: *Amazon RDS for Oracle pricing* (License Included bundles the Oracle license)

docs/oracle19c/limitations.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Oracle 19c — known limitations & caveats
2+
3+
Oracle-specific limitations only. Generic RDS behavior is documented in the
4+
top-level [README.md](../../README.md).
5+
6+
## Credential model (intended boundary — not a limitation)
7+
8+
The binding returns the instance **master credential**, the same model as the
9+
Postgres/MySQL RDS plans. Creating least-privilege application users *inside* the
10+
database is the customer's responsibility — the intended shared-responsibility
11+
boundary. On Oracle this matters more: the RDS master user is **DBA-class** (it
12+
carries the DBA-style role RDS grants), more privileged than a Postgres/MySQL
13+
master. Bind apps to a **least-privilege user you create**, not to the master. This
14+
is customer guidance, not a broker-enforced gate.
15+
16+
## Limitations
17+
18+
1. **No in-place engine-version update.** `oracle19cBaseline.SupportsEngineVersionUpdate()`
19+
returns false; version is pinned by the plan.
20+
2. **Fixed SID `ORCL`.** RDS Oracle constrains DBName/SID to ≤8 uppercase chars. The
21+
unique per-instance identifier is the `DBInstanceIdentifier`, not the SID.
22+
3. **SE2 lacks the EE-only features.** No Oracle-native TDE, Fine-Grained Auditing
23+
(FGA), VPD, Label Security, Data Redaction, Partitioning, or Data Guard. At-rest
24+
encryption is provided by RDS-KMS storage encryption and auditing by
25+
standard/unified auditing; the residual TDE/FGA control interpretation is an
26+
accepted ISSO risk/deviation — see [licensing.md](licensing.md). An accepted
27+
deviation of the chosen edition, not an unfinished feature.
28+
4. **TLS-only needs the platform security group.** The broker provisions + attaches
29+
the SSL option group (TCPS 2484, TLS 1.2, `TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384`,
30+
`FIPS.SSLFIPS_140=TRUE`) and the binding advertises TCPS/2484, but it cannot open
31+
`2484` ingress or deny plaintext `1521` — that is a cg-provision security-group
32+
change. See [hardening-baseline.md](hardening-baseline.md).
33+
5. **TLS 1.2 ceiling.** RDS Oracle SSL supports TLS 1.2 only (no 1.3). Acceptable for
34+
FedRAMP Moderate.
35+
6. **~33 OS/listener STIG controls are AWS-inherited / not applicable** on managed
36+
RDS. They are classified in the overlay's `control-layers.yml`, not remediated in
37+
the broker; any that cannot be met become POA&M candidates.
38+
7. **`ENABLE_ORACLE` staged-rollout switch.** Oracle provisioning is off until the
39+
broker environment opts in. A rollout control for a new offering — **not** a
40+
security/boundary control (the credential model matches Postgres/MySQL).
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Oracle 19c — credential rotation
2+
3+
Oracle uses the **same customer-initiated rotation flow as the other RDS engines**
4+
(Postgres/MySQL): `cf update-service -c '{"rotate_credentials": true}'`, then
5+
unbind/bind and restage. The full step-by-step (including the downtime caveat and
6+
the need to recreate service keys) is documented for the platform at
7+
[docs.cloud.gov — Rotate your credentials](https://docs.cloud.gov/platform/services/relational-database/#rotate-your-credentials);
8+
the Oracle steps are identical. There is no automatic/scheduled rotation.
9+
10+
```bash
11+
cf update-service my-oracle -c '{"rotate_credentials": true}'
12+
cf unbind-service my-app my-oracle
13+
cf bind-service my-app my-oracle # VCAP_SERVICES is populated at bind time
14+
cf restage my-app --strategy rolling
15+
```
16+
17+
## Oracle-specific note: the master is DBA-class
18+
19+
The rotated credential is the **instance master**, which on Oracle is a **DBA-class**
20+
account — more privileged than a Postgres/MySQL master. Do **not** point production
21+
apps directly at the master. Connect as the master once to create a least-privilege
22+
application user, and bind/run your app as that user; rotating the master does not
23+
change an app user the customer created. Creating least-privilege in-database users
24+
is the customer's responsibility (the intended shared-responsibility boundary). See
25+
[../../docs/oracle19c/limitations.md](../../docs/oracle19c/limitations.md).

0 commit comments

Comments
 (0)