# SOAP to CI Access Audit

LLMS index: [llms.txt](/llms.txt)

---

<div class="alert alert-primary border shadow-sm mb-4" role="note">
  <div class="d-flex flex-column flex-lg-row align-items-lg-center justify-content-between gap-3">
    <div>
      <strong>New to psLens?</strong> This page documents one specific report. To see how it runs in the product, what
      the output looks like, and how teams use it in practice, start with a live walkthrough.
    </div>
    <div class="d-flex flex-wrap gap-2">
      <a class="btn btn-sm btn-primary" href="/contact/">Book a Demo</a>
      <a class="btn btn-sm btn-outline-primary" href="/docs/reports/">Browse Reports</a>
    </div>
  </div>
</div><div id="pslens-context-panel" class="card border-info mb-4 d-none">
  <div class="card-header bg-light text-info py-2 fw-bold d-flex align-items-center border-bottom border-info-subtle">
    <i class="bi bi-info-circle-fill me-2"></i>
    <span>Tailored Operational Context</span>
  </div>
  <div class="card-body p-0">
    <ul class="list-group list-group-flush">
      <li id="row-db" class="list-group-item d-flex align-items-center justify-content-between py-2 d-none">
        <strong>Target Database:</strong>
        <span id="ctx-db" class="badge bg-secondary font-monospace">&mdash;</span>
      </li>
      <li id="row-type" class="list-group-item d-flex align-items-center justify-content-between py-2 d-none">
        <strong>Context Type:</strong>
        <span id="ctx-type" class="badge bg-light text-dark border font-monospace text-uppercase">&mdash;</span>
      </li>
      <li id="row-severity" class="list-group-item d-flex align-items-center justify-content-between py-2 d-none">
        <strong>Alert Severity:</strong>
        <span id="ctx-severity" class="badge">&mdash;</span>
      </li>
      <li id="row-time" class="list-group-item d-flex align-items-center justify-content-between py-2 d-none">
        <strong>Triggered Time:</strong>
        <span id="ctx-time" class="text-muted small">&mdash;</span>
      </li>
      <li id="row-details" class="list-group-item py-2 d-none">
        <strong id="label-details" class="d-block mb-1">Firing Context:</strong>
        <code id="ctx-details" class="d-block p-2 bg-light border rounded small"
          style="white-space: pre-wrap; word-break: break-all;">&mdash;</code>
      </li>
    </ul>
  </div>
</div>

<script>
  (function () {
    const params = new URLSearchParams(window.location.search);
    const metadata = params.get('metadata');
    if (!metadata) return;

    try {
      
      const base64 = metadata.replace(/-/g, '+').replace(/_/g, '/');
      const jsonStr = decodeURIComponent(escape(window.atob(base64)));
      const data = JSON.parse(jsonStr);

      if (data) {
        let hasData = false;

        if (data.db) {
          document.getElementById('ctx-db').textContent = data.db;
          document.getElementById('row-db').classList.remove('d-none');
          hasData = true;
        }

        if (data.type) {
          document.getElementById('ctx-type').textContent = data.type;
          document.getElementById('row-type').classList.remove('d-none');
          hasData = true;
        }

        if (data.severity) {
          const severityBadge = document.getElementById('ctx-severity');
          const severity = data.severity.toLowerCase();
          severityBadge.textContent = severity.toUpperCase();
          if (severity === 'critical') {
            severityBadge.className = 'badge bg-danger';
          } else if (severity === 'warning') {
            severityBadge.className = 'badge bg-warning text-dark';
          } else {
            severityBadge.className = 'badge bg-info';
          }
          document.getElementById('row-severity').classList.remove('d-none');
          hasData = true;
        }

        if (data.t) {
          const date = new Date(data.t * 1000);
          document.getElementById('ctx-time').textContent = date.toLocaleString();
          document.getElementById('row-time').classList.remove('d-none');
          hasData = true;
        }

        if (data.details) {
          document.getElementById('ctx-details').textContent = data.details;

          
          const labelDetails = document.getElementById('label-details');
          if (data.type === 'object') {
            labelDetails.textContent = 'Object Metadata Details:';
          } else if (data.type === 'report') {
            labelDetails.textContent = 'Report Description:';
          } else {
            labelDetails.textContent = 'Firing Context:';
          }

          document.getElementById('row-details').classList.remove('d-none');
          hasData = true;
        }

        if (hasData) {
          document.getElementById('pslens-context-panel').classList.remove('d-none');
        }
      }
    } catch (e) {
      console.error('Failed to parse operational context metadata:', e);
    }
  })();
</script>

## SOAP to Component Interface Access Audit Report

**Report ID:** `security-soap-to-ci-access`
**Category:** Security

## Purpose

"SOAP to CI" is a powerful tool that allows using excel or any web client to interact with PeopleSoft Component Interfaces via SOAP web services. However, this capability also introduces significant security risks if not properly controlled, as it can allow users to programmatically read or write data in the application database. The number of users with access to this WebLib should be tightly controlled and regularly audited.

The **SOAP to Component Interface Access Audit** report identifies all PeopleSoft users (OPRIDs) who have access to the SOAP-to-CI WebLib (`WEBLIB_SOAPTOCI`). This WebLib allows programmatic data loading into PeopleSoft using standard Component Interface Web Services (acting as the endpoint for Excel-to-CI and custom integrations like `psDataLoader`).

For each identified user, the report details:

1. The security paths (Roles and Permission Lists) granting WebLib access.
2. The specific Component Interfaces they are authorized to access and execute, and which Roles and Permission Lists grant that CI access.

This report is critical for security audits to ensure that only authorized integration accounts or administrators possess programmatic write access to the application database.

## Tables Queried

### PSAUTHITEM — WebLib Authorizations

Used to find permission lists that grant access to `WEBLIB_SOAPTOCI`.

|  Field   |     Description      |             Filter             |
| -------- | -------------------- | ------------------------------ |
| CLASSID  | Permission list name |                                |
| MENUNAME | WebLib name          | `MENUNAME = 'WEBLIB_SOAPTOCI'` |

### PSROLECLASS — Role to Permission List Mapping

Used to trace permission lists back to roles.

|  Field   |            Description             |
| -------- | ---------------------------------- |
| CLASSID  | Permission list                    |
| ROLENAME | Role assigning the permission list |

### PSROLEUSER — User to Role Mapping

Used to identify users assigned to the roles that grant Weblib access, and to map all roles assigned to those users.

|  Field   |   Description   |
| -------- | --------------- |
| ROLEUSER | User ID (OPRID) |
| ROLENAME | Assigned role   |

### PSOPRDEFN — Operator Definitions

Used to identify users who get direct access via their Primary Permission List (`OPRCLASS`), and to retrieve user account lock status and descriptions.

|    Field    |                    Description                    |
| ----------- | ------------------------------------------------- |
| OPRID       | User ID                                           |
| OPRDEFNDESC | User name / description                           |
| OPRCLASS    | Primary permission list                           |
| ACCTLOCK    | Lock status (`0` = Active/Unlocked, `1` = Locked) |

### PSAUTHBUSCOMP — Component Interface Authorizations

Used to trace all Component Interface authorizations for the permission lists assigned to the identified users.

|  Field   |        Description         |
| -------- | -------------------------- |
| CLASSID  | Permission list            |
| BCNAME   | Component Interface name   |
| BCMETHOD | Component Interface method |

## Data Flow

```text
1. Query PSAUTHITEM to find all permission lists (CLASSID) authorizing WEBLIB_SOAPTOCI
        |
        v
2. Query PSROLECLASS to trace those permission lists back to Roles
        |
        v
3. Query PSROLEUSER and PSOPRDEFN to identify all users (OPRID) with:
   - Assignment to those Roles
   - Direct Primary Permission List (OPRCLASS) granting access
        |
        v
4. Fetch user details (description, lock status) for all identified users
        |
        v
5. Fetch all Roles and Permission Lists assigned to those users
        |
        v
6. Fetch all Component Interface (CI) authorizations (PSAUTHBUSCOMP) for those permission lists
        |
        v
7. For each user, map their SOAP-to-CI access paths and all authorized Component Interfaces
        |
        v
8. Sort users (active first, then by ID) and generate the Markdown report
```

## Parameters

This report has no configurable parameters.

## Report Output

The generated report contains:

- **Header** with database name and generation timestamp.
- **Summary statistics** (total users, active vs. locked, unique roles, unique permission lists).
- **WebLib Access Path Summary Table** listing each Role-Permission List pair granting SOAP-to-CI access and the number of active users with that assignment.
- **User Access Details Section** detailing each user:
  - User ID (linked to detail page) and Description.
  - Account lock status (Active/Unlocked vs. Locked 🔒).
  - Explicit Weblib Authorization Paths (Roles and Permission Lists granting Weblib access).
  - A table of **Accessible Component Interfaces** detailing which Role and Permission List grants access to each specific Component Interface.
- **Remediation Recommendations** to secure your environments.

## Interpreting Results

- **Unlocked users with SOAP-to-CI access must be verified.** Programmatic SOAP-to-CI access should be reserved for integration service accounts or system administrators. Standard business users should not have access to this WebLib.
- **Active users with no Component Interface access** have WebLib access but cannot interact with any business objects. While they present less immediate risk, their WebLib access should still be revoked to adhere to the principle of least privilege.
- **Locked users** are flagged with `Locked 🔒`. While they cannot authenticate, their security definitions should still be cleaned up if their access is no longer required.
- **Primary Permission List grants** (indicated by `Primary Permission List` instead of a Role) should be avoided. Best practice is to assign Weblib access through Roles.

## Recommendations

1. **Restrict WEBLIB_SOAPTOCI**: Remove this WebLib access from any roles assigned to standard business users. Ensure it is only assigned to dedicated integration/service accounts.
2. **Implement Least Privilege for CIs**: Verify that service accounts only have access to the specific Component Interfaces (CIs) required for their integration. Remove broad or administrative permission lists that grant access to unnecessary CIs.
3. **Lock Stale Accounts**: Ensure that any old, inactive, or deprecated integration accounts are explicitly locked in `PSOPRDEFN`.
