Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 67 additions & 24 deletions content/resources/core/oracledb_session.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ platform = "os"
parent = "resources/core"
+++

Use the `oracledb_session` Chef InSpec audit resource to test SQL commands run against a Oracle database.
Use the `oracledb_session` Chef InSpec audit resource to test SQL commands run against an Oracle database.

## Availability

Expand All @@ -24,27 +24,42 @@ This resource first became available in v1.0.0 of InSpec.

## Syntax

A `oracledb_session` resource block declares the username and PASSWORD to use for the session with an optional service to connect to, and then the command to be run:
An `oracledb_session` resource block declares the session username and password, an optional service to connect to, and the command to run. For example:

```ruby
describe oracledb_session(user: 'username', PASSWORD: 'PASSWORD', service: 'ORCL.localdomain').query('QUERY').row(0).column('result') do
its('value') { should eq('') }
describe oracledb_session(user: '<USERNAME>', PASSWORD: '<PASSWORD>', service: '<ORACLE_SERVICE>').query('<QUERY>').row(<NUMBER>).column('<COLUMN_NAME>') do
its('<VALUE>') { should eq('<EXPECTED_VALUE>') }
end
```

where:

- `oracledb_session` declares a username and PASSWORD with permission to run the query (required), and an optional parameters for host (default: `localhost`), system identifier (SID) (default: `nil`), which uses the default SID, and path to the sqlplus binary (default: `sqlplus`).
- it's possible to run queries as sysdba/sysoper by using `as_db_role option`, see examples
- SQLcl can be used in place of sqlplus. Use the `sqlcl_bin` option to set the sqlcl binary path instead of `sqlplus_bin`.
- `query('QUERY')` contains the query to be run
- `its('value') { should eq('') }` compares the results of the query against the expected result in the test
- `oracledb_session` resource declares a username and password with permission to run the query (required), and an optional Oracle service name or SID.
- `query` declares the Oracle session query you are testing.
- `column` and `row` filter the query results.
- `its('<VALUE>') { should eq('<EXPECTED_VALUE>') }` compares the results of the query against the expected result in the test.

## oracledb_session(...).query method Properties
## Properties

- rows the query result as array of hashes
- row(number) selected row from query result, where number is just a row number in the query result
- column(name) array with values from selected column
You can use the following properties to query an Oracle database:

- `user`: The user to query the database.
- `password`: The user's password.
- `service`: The Oracle service name or SID.
- `host`: The hostname or IP address of the Oracle database server. Default: `localhost`.
- `port`: The port number for the Oracle database listener. Default: `1521`.
- `tns_alias`: The Transparent Network Substrate (TNS) alias from `tnsnames.ora`. This is recommended for TCPS/SSL connections.
- `env`: A hash of environment variables, for example, `TNS_ADMIN`, `LD_LIBRARY_PATH`, and `ORACLE_HOME`.
- `as_db_role`: The database role. For example, `sysasm`, `sysdba`, or `sysoper`. See the examples for more information.
- `as_os_user`: The OS user to switch to before running queries. This is available on Unix or Linux only.
- `sqlplus_bin`: The path to the `sqlplus` binary. Default: `sqlplus`.
- `sqlcl_bin`: The path to the `sqlcl` binary if you're using SQLcl instead of `sqlplus`.

Use the following query method properties to access and filter query results:

- `rows`: The query result as an array of hashes.
- `row(number)`: The selected row from the query result, where `number` is a row number in the query result.
- `column(name)`: An array with values from the selected column.

## Examples

Expand All @@ -60,7 +75,7 @@ describe sql.query('SELECT NAME AS VALUE FROM v$database;').row(0).column('value
end
```

### Test for matching databases with custom host, SID and sqlplus binary location
### Test for matching databases with custom host, SID, and sqlplus binary location

```ruby
sql = oracledb_session(user: 'USERNAME', pass: 'PASSWORD', host: 'ORACLE_HOST', sid: 'ORACLE_SID', sqlplus_bin: '/u01/app/oracle/product/12.1.0/dbhome_1/bin/sqlplus')
Expand All @@ -70,19 +85,19 @@ describe sql.query('SELECT NAME FROM v$database;').row(0).column('name') do
end
```

### Test for table contains a specified value in any row for the given column name
### Test that a table contains a specified value in any row for the given column name

```ruby
sql = oracledb_session(user: 'USERNAME', pass: 'PASSWORD', service: 'ORACLE_SID')

describe sql.query('SELECT * FROM my_table;').column('COLUMN') do
it { should include 'my_value' }
describe sql.query('SELECT * FROM table_name;').column('column') do
it { should include 'value' }
end
```

### Test tablespace exists as sysdba
### Test that a tablespace exists as sysdba

The check will change user (with su) to specified user and run 'sqlplus / as sysdba' (sysoper, sysasm)
This test changes the user (with `su`) to the specified user and runs `sqlplus / as sysdba` (or `sysoper`, `sysasm`).

```ruby
sql = oracledb_session(as_os_user: 'oracle', as_db_role: 'sysdba', service: 'ORACLE_SID')
Expand All @@ -92,9 +107,9 @@ describe sql.query('SELECT tablespace_name AS name FROM dba_tablespaces;').colum
end
```

The option `as_os_user` is available only on unix-like systems and not supported on Windows. Also this option requires that you are running inspec as `root` or with `--sudo`
The `as_os_user` option is available only on Unix-like systems and isn't supported on Windows. This option also requires that you're running InSpec as `root` or with `--sudo`.

### Test number of rows in the query result
### Test the number of rows in the query result

```ruby
sql = oracledb_session(user: 'USERNAME', pass: 'PASSWORD')
Expand All @@ -104,18 +119,46 @@ describe sql.query('SELECT * FROM my_table;').rows do
end
```

### Use data out of (remote) DB query to build other tests
### Use data from a remote database query to build other tests

```ruby
sql = oracledb_session(user: 'USERNAME', pass: 'PASSWORD', host: 'my.remote.db', service: 'ORACLE_SID')
sql = oracledb_session(
user: 'USERNAME',
password: 'PASSWORD',
host: 'oracle.example.com',
service: 'ORACLE_SID'
)

sql.query('SELECT * FROM files;').rows.each do |file_row|
describe file(file_row['path']) do
its('owner') { should eq file_row['owner']}
its('owner') { should eq file_row['owner'] }
end
end
```

### Test using a Transparent Network Substrate (TNS) alias for TCPS/SSL connections

```ruby
sql = oracledb_session(
user: 'system',
password: 'Oracle123',
tns_alias: 'XEPDB1_TCPS',
env: {
'TNS_ADMIN' => '/opt/oracle/network/admin',
'LD_LIBRARY_PATH' => '/opt/oracle/instantclient',
'ORACLE_HOME' => '/opt/oracle'
}
)

describe sql.query('SELECT * FROM dual;').row(0).column('column_name') do
its('value') { should eq 'X' }
end
```

Use the `tns_alias` option for TCPS/SSL connections as it allows proper TNS name resolution from `tnsnames.ora`.
When you use `tns_alias`, you can use the `env` hash to set required environment variables like `TNS_ADMIN` (the path to `tnsnames.ora` and wallet files).
This enables secure connections with SSL/TLS certificate validation.

## Matchers

{{< readfile file="content/reusable/md/inspec_matchers_link.md" >}}
4 changes: 3 additions & 1 deletion cspell.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ ignoreRegExpList:
- /'d\b/
- /^\s*```[\s\S]*?^\s*```/gm
- "{{(.+)(?=}})"
words: []
words:
- TCPS
- tnsnames
languageSettings:
- languageId: markdown
ignoreRegExpList:
Expand Down
Loading