diff --git a/.github/workflows/validate-scripts.yml b/.github/workflows/validate-scripts.yml index 91e55f6..86f5582 100644 --- a/.github/workflows/validate-scripts.yml +++ b/.github/workflows/validate-scripts.yml @@ -2,13 +2,15 @@ name: Validate Sample Scripts on: push: - branches: [master] + branches: [main] paths: - - 'SampleScripts/**/*.json' + - 'samples/**/*.json' + - 'templates/**/*.json' pull_request: - branches: [master] + branches: [main] paths: - - 'SampleScripts/**/*.json' + - 'samples/**/*.json' + - 'templates/**/*.json' jobs: validate-json: @@ -22,19 +24,21 @@ jobs: failed=0 found=0 - while IFS= read -r -d '' f; do - found=1 + for dir in samples templates; do + while IFS= read -r -d '' f; do + found=1 - if ! jq empty "$f" >/dev/null 2>&1; then - echo "::error file=$f::Invalid JSON syntax" - echo "FAILED: $f" - jq empty "$f" - failed=1 - fi - done < <(find SampleScripts -type f -name '*.json' -print0) + if ! jq empty "$f" >/dev/null 2>&1; then + echo "::error file=$f::Invalid JSON syntax" + echo "FAILED: $f" + jq empty "$f" + failed=1 + fi + done < <(find "$dir" -type f -name '*.json' -print0) + done if [ "$found" -eq 0 ]; then - echo "No JSON files found under SampleScripts/." + echo "No JSON files found under samples/ or templates/." exit 0 fi diff --git a/.vscode/settings.json b/.vscode/settings.json index 66e0921..c21d3f6 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,7 +1,7 @@ { "json.schemas": [ { - "fileMatch": ["SampleScripts/**/*.json"], + "fileMatch": ["samples/**/*.json", "templates/**/*.json"], "url": "./schema/custom-platform-script.schema.json" } ] diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f3211f7..ddc793d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -18,10 +18,10 @@ git checkout -b my-change ## Contributing Sample Scripts -- Add new scripts under `SampleScripts/` in the correct protocol folder: - - `SampleScripts/SSH/` - - `SampleScripts/HTTP/` - - `SampleScripts/Telnet/` +- Add new scripts under `samples/` in the correct protocol folder: + - `samples/ssh/` + - `samples/http/` + - `samples/telnet/` - Follow the JSON structure in [docs/reference/script-structure.md](docs/reference/script-structure.md). - Include the standard operations your target supports whenever possible. At minimum, include `CheckSystem` (the operation behind **Test Connection**) and `CheckPassword`, unless accounts change their own passwords on that platform (in which case `CheckSystem` may not apply). - Use meaningful parameter names and sensible defaults. diff --git a/README.md b/README.md index a7e8fe3..8e6dae4 100644 --- a/README.md +++ b/README.md @@ -1,56 +1,66 @@ # Safeguard Custom Platform Scripts -Build and adapt custom platform scripts for Safeguard when built-in platforms do not fit your target system. +Build custom platform scripts for [Safeguard for Privileged Passwords (SPP)](https://www.oneidentity.com/products/safeguard-for-privileged-passwords/) when built-in platforms don't cover your target system. -## What is this? +Custom platform scripts are JSON definitions that teach SPP how to connect to any target — Linux hosts, network appliances, REST APIs, web portals, cloud services — and manage credentials (passwords, SSH keys, API keys) through SSH, HTTP, or Telnet. -Safeguard custom platform scripts are JSON-based definitions that tell Safeguard for Privileged Passwords (SPP) how to connect to a target, navigate its interface, and perform credential operations such as password changes, key updates, and account validation. +## Where Do I Start? -This repository is for asset administrators and automation teams who need to manage passwords or SSH keys on operating systems, appliances, network devices, web applications, or vendor-specific workflows not covered by built-in platforms. It includes practical guidance and examples for both SSH- and HTTP-based integrations, plus historical Telnet-related content. +| I want to... | Go here | +| --- | --- | +| **Get something working in 5 minutes** | [Quick Start](docs/quick-start/) | +| **Understand how custom platforms work** | [Concepts](docs/concepts/) | +| **Learn step by step with a tutorial** | [Tutorials](docs/tutorials/) | +| **Look up a specific command or parameter** | [Reference](docs/reference/) | +| **Deploy a tested sample script** | [Samples](samples/) | +| **Start a new script from a template** | [Templates](templates/) | +| **Solve a specific problem** | [Guides](docs/guides/) | -## Quick Start +## Repository Layout -If you want the docs and samples locally while you work, clone the repository first: +``` +docs/ + quick-start/ 5-minute guides to get a working platform fast + concepts/ Architecture, execution model, feature flags + tutorials/ Step-by-step walkthroughs for building scripts + guides/ Task-focused how-to content (SSH patterns, HTTP patterns, etc.) + reference/ Commands, operations, parameters, variables +samples/ Production-tested scripts with companion documentation + ssh/ Linux, Unix, appliance samples + http/ REST API, OAuth2, form-based samples + telnet/ Cisco IOS, IBM RACF TN3270 samples +templates/ Pattern templates and minimal starters (not tested against live targets) +schema/ JSON Schema for IDE autocomplete +tools/ TestTool.ps1 for local validation +``` + +## Quick Start ```powershell +# Clone the repo git clone https://github.com/OneIdentity/SafeguardCustomPlatform.git cd SafeguardCustomPlatform -``` - -1. **Write.** Start with the closest template in `SampleScripts/Templates/`, then customize commands, prompts, parameters, and validation flow for your target. -2. **Upload.** Use `Import-SafeguardCustomPlatformScript` from `safeguard-ps` to upload the script to SPP. -3. **Test.** Validate against a safe test asset with `Test-SafeguardAssetAccountPassword -ExtendedLogging` before rolling into production. - -## Documentation -Start with [`docs/`](docs/) to find the right level of detail for your task: +# Pick a template and customize it +code templates/TemplateSshMinimal.json -- [`docs/getting-started/`](docs/getting-started/) - Tutorials and first-script walkthroughs for new custom platform authors. -- [`docs/reference/`](docs/reference/) - Script structure, supported operations, parameters, and command behavior. -- [`docs/guides/`](docs/guides/) - SSH patterns, HTTP patterns, regex guidance, and advanced implementation topics. -- [`docs/guides/regex-patterns.md`](docs/guides/regex-patterns.md) - Practical .NET regex patterns for prompts, parsing, and error detection. -- [`docs/guides/feature-flags.md`](docs/guides/feature-flags.md) - Understand which operations and capabilities your platform advertises. -- [`docs/guides/troubleshooting.md`](docs/guides/troubleshooting.md) - Common errors, diagnostic tips, and fixes. +# Upload to SPP +Import-SafeguardCustomPlatformScript -FilePath .\MyPlatform.json -## Sample Scripts - -Browse [`SampleScripts/`](SampleScripts/) for working examples you can study or adapt. Samples are organized by protocol so you can quickly focus on the right category: +# Test +Test-SafeguardAssetAccountPassword -AssetToUse "MyHost" -AccountToUse "admin" -ExtendedLogging +``` -- SSH -- HTTP -- Telnet +For detailed quick-start paths, see [docs/quick-start/](docs/quick-start/). ## Tools -Use [`tools/TestTool.ps1`](tools/TestTool.ps1) to test custom platform scripts locally before uploading them to SPP. - -## Telnet / Pattern Files - -Telnet pattern files have moved to [SafeguardAutomation](https://github.com/OneIdentity/SafeguardAutomation/tree/master/Terminal%20Pattern%20Files). +- [`tools/TestTool.ps1`](tools/TestTool.ps1) — Validate script JSON locally before uploading to SPP +- [`schema/custom-platform-script.schema.json`](schema/custom-platform-script.schema.json) — JSON Schema for IDE autocomplete (VS Code configured automatically) ## Contributing -Contributions are welcome, including new sample scripts, fixes, and documentation improvements. See [CONTRIBUTING.md](CONTRIBUTING.md) for contribution guidelines, and feel free to share community-tested samples that others can adapt. +Contributions are welcome — new sample scripts, documentation improvements, and bug fixes. See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines. ## Support @@ -59,20 +69,3 @@ One Identity open source projects are supported through [GitHub issues](https:// ## License See [LICENSE](LICENSE). - -## Compatibility Matrix - -> Approximate only — check your SPP release notes for exact availability in your build. - -| SPP Version | Custom Platform Feature Added | -| --- | --- | -| 6.0 | Custom platforms introduced (SSH, Telnet) | -| 6.7 | HTTP/REST custom platforms added | -| 7.0 | `DiscoverAccounts` | -| 7.0 | `DiscoverServices` | -| 7.0 | `DiscoverSshHostKey` | -| 7.4 | `ExecuteCommand` (SSH batch mode) | -| 7.4 | `ExecuteDependentCommand` (dependent system workflows) | -| 7.5 | `ElevateAccount` / `DemoteAccount` | -| 7.5 | `EnableAccount` / `DisableAccount` | -| 7.6 | `CheckFile` / `ChangeFile` | diff --git a/SampleScripts/HTTP/README.md b/SampleScripts/HTTP/README.md deleted file mode 100644 index 1c7cf91..0000000 --- a/SampleScripts/HTTP/README.md +++ /dev/null @@ -1,171 +0,0 @@ -[← Sample Scripts](../README.md) - -# Guide to SafeguardCustomPlatform - HTTP Scripts - -## Table of Contents -[OneLogin_GRC_JIT_addon](#onelogin_grc_jit_addon) -[Okta_WithDiscoveryAndGroupMembershipRestore](#okta_withdiscoveryandgroupmembershiprestore) - -## OneLogin_GRC_JIT_addon - -This Solution Accelerator addon was created to implement JIT role elevation for OneLogin until it is available out-of-box in Safeguard. - -### How does it work -The OneLogin_GRC_JIT_addon implements Restore/Suspend and Elevate/Demote functions. The ChangePassword function is also defined as it's a must-have for Custom Platform scripts, however it does nothing (only logs that it does nothing). - -Changing the password is: - * Either not necessary as the Account will only store a TOTP code, configured automatically by OneLogin. - * Or if the base privileged Account is created & managed by the out-of-box Starling Connect connector for OneLogin, that will be managing the password. - -The addon will be the Platform Types for additionally created Assets in Safeguard, each separate Asset representing a Role in OneLogin: - - - -Each privileged OneLogin User having permission to elevate into that Role needs to have an Account object created within the Asset representing the Role. - - - -(Note: the Assets could also represent groups of Roles.) - -In SPP the Account shows up on the Access Request portal only if it has the password set. Hence each of these Accounts need to have a dummy password configured. - -The Users need to have Entitlements / Access Request Policies to the base privileged OneLogin Account as well as for the individual Accounts representing the Roles. This requires creating an Entitlement per User as at the time of writing this reamde (in SPP v8.2) the Accounts of neither the OneLogin platform Asset, nor the custom platform Assets can be added as Linked Accounts. - - - -When the User is requesting access to the privileged OneLogin Account, at the same time the desired Roles should also be selected. The privileged OneLogin Account will have the Roles assigned, once the subsequent access requests representing the Roles become available (after Pending Restore state). - - - -#### Demo video - -Watch demo video - - -### About enabling/disabling the OneLogin user via a Safeguard Access Request -JIT enable/disable or elevate/demote tasks are implemented on the OneLogin_GRC_JIT_addon Asset/Accounts. - -There are two typical setups: - -1. When the Account objects are managed by OneLogin, all of them stored under a OneLogin_GRC_JIT_addon Asset: - * In this scenario enable the *Suspend account when checked in* function under Password Profile > Change Password policy for the main privileged account. Do not configure JIT groups for this Accounts. - * Configure the JIT group elevation for the Accounts on the Assets representing the Roles. Do not enable the *Suspend account when checked in* function for these Accounts. - * Once the main -adm account is checked out, it gets activated. The Roles get assigned depending on which corresponding Asset is requested along with the main Account. Whilst the main Account is checked out, the User can request further Roles, or check any of them in, demoting that Role in OneLogin. - -2. When the main Account is managed by the out-of-box Starling Connect connector for OneLogin, and only the Assets representing a Role are configured with the OneLogin_GRC_JIT_addon platform type: - * In this case both the *Suspend account when checked in* function and the JIT groups should be configured on each of the Asset/Accounts representing a OneLogin Role. - * Despite the main Account is checked out, it is still inactive in OneLogin. It will only be activated once an Asset/Account representing a Role gets checked out too, as the OneLogin_GRC_JIT_addon is the connector implementing JIT activation and elevation. - * In case the Account is assigned to multiple Roles via requesting multiple Asset/Accounts representing a OneLogin Role, the User should not check in any of the Roles before finishing all activities because checking one of these requests in will not only demote the requested Role, but also deactivate the Account inside OneLogin. - -### Configuration -It can be configured with two different approaches: -* **Accounts are created by OneLogin through its Generic REST Connector.** - * In this case the default Starling Connect connector for OneLogin is not used. Asset and Account objects are created by OneLogin, as well as the Entitlements and the Access Request Policies. - * Every Role which you want to make available for the privileged OneLogin account is mapped to an Asset/Account object in Safeguard, automatically by OneLogin. Corresponding Entitlements and Access Request policies are also created by OneLogin. - * OneLogin is automatically registering the TOTP for the privileged OneLogin account, as well as vaulting it in SPP (the TOTP seed is never exposed, users are technically forced to use the vaulted credential). -* **The base Account is created via the Discovery feature of the Starling Connect connector for OneLogin or in any other way, like via AD (in case the accounts are synchronized into OneLogin from AD).** - * In this case the Asset/Account objects representing the Role/User pairs must be created manually, or via 3rd party automation, so as the Entitlements and Access Request Policies. - * The TOTP seed for the base privileged OneLogin Account must be vaulted manually, or via 3rd party automation. - -#### Configuration: Accounts are created by OneLogin through its Generic REST Connector - - 1. Create the API Credential in OneLogin with Manage All permissions. This will be used as the service account for the Assets in Safeguard. - 2. Upload the custom platform script to SPP. - -  - - -  - - - - 3. Configure the OneLogin REST Connector for Safeguard and let it do the heavy-lifting Safeguard: Assets, Accounts, Entitlements, Access Request Policies, etc. Search the **One Identity Safeguard (OneLogin Account Onboarding)** and **One Identity Safeguard (OneLogin-Virtual AssetAccounts for JIT elevation)** connectors in the OneLogin Application Catalog. - - - - -With this, the User is now able to raise Access Requests in Safeguard which enables the Account in OneLogin and assigns the requested Roles. - -#### Configuration: The base Account is created via the Discovery feature of the Starling Connect connector for OneLogin, or from Active Directory - -1. Onboard the OneLogin Accounts to SPP in the preferred way, for example using the out-of-box Starling Connect connector for OneLogin. This is going to be the main Account object holding the actual secrets of the privileged OneLogin Account. Feel free to manage these Accounts as needed. The Accounts may also originate from AD so that we can configure RDP Apps. In case the status and password of the OneLogin account is in sync with AD, then you can also manage the corresponding AD accounts in SPP. - -  - - -2. Create the API Credential in OneLogin with Manage All permissions. This will be used as the service account for the Assets in Safeguard. - -3. Upload the custom platform script to SPP. - -  - - -  - -4. Create an Asset for each OneLogin Role, or combination of Roles, that the User has permission to elevate into. The platform type is the OneLogin_GRC_JIT_addon. - - As the Roles look like in OneLogin: - -  - - - As the corresponding Assets look like in Safeguard: - -  - - -5. Create an Account on each of the these Assets with the same name as the original OneLogin Account. For example as shown on one of the Assets representing a OneLogin Role: - -  - - - Make sure that a dummy password is set on each of these Accounts otherwise these won't show up when raising an Access Request (note: the OneLogin_GRC_JIT_addon does not change the password of the Account, even if the Task is successfully completed). - - The Password Profile of these Accounts should do nothing with the password. No Check / No Change. - -6. Configure the corresponding Role name in the JIT configuration of these Accounts. For example as shown on one of the Assets representing a OneLogin Role: - -  - -7. If the base OneLogin Account is managed through the originating AD Account, then create an Entitlement for password or pession (RDP App) access with the Users' Linked Accounts. - -  - -  - -  - -Don't forget creating the virtual asset to connect to: - -  - -Otherwise the Access Request Policy will be created in the per-user Entitlement together with the access to the virtual JIT Assets. - -8. Create an Entitlement per each User. This is required as at the time of writing this readme (in SPP v8.2) the Accounts of a Custom Platfom Asset can't be configured as Linked Accounts. - -  - -9. Create a Dynamic Account Group for all the Role-specific Accounts of the User. - -  - -  - - -10. Create a password Access Request Policy into the Entitlement. In the Scope of this Access Request Policy, add the Dynamic Account Group of the User. - -  - -  - - -With this, the User is now able to raise Access Requests in Safeguard which enables the Account in OneLogin and assigns the requested Roles. - - - - - -## Okta_WithDiscoveryAndGroupMembershipRestore -This script had been implemented before the JIT Elevation functionality was available in Safeguard. Hence the configuration is cumbersome and does not work as JIT is confgured. - -The script should be reworked a bit to reflect the out-of-box JIT configuration approach. diff --git a/SampleScripts/README.md b/SampleScripts/README.md deleted file mode 100644 index dfa2232..0000000 --- a/SampleScripts/README.md +++ /dev/null @@ -1,124 +0,0 @@ -To better understand these sample scripts, read the [documentation](../docs/README.md). - -These sample custom platform scripts show how to extend Safeguard for Privileged Passwords (SPP) with custom platforms that manage assets through the platform scripting engine over [SSH](SSH/), [Telnet (TN3270)](Telnet/), and [HTTP](HTTP/). Some target systems can be managed through more than one protocol, so start with the sample that is closest to your target workflow. - -For getting started, see the [overview](../docs/getting-started/overview.md) and -[development workflow](../docs/getting-started/development-workflow.md) guides. For -product-level details on custom platforms and asset onboarding, refer to the SPP -Administration Guide available from the [One Identity documentation site](https://docs.oneidentity.com/). - -## How to Use This Catalog - -- [`SSH/`](SSH/), [`HTTP/`](HTTP/), and [`Telnet/`](Telnet/) contain real tested samples. -- [`Templates/`](Templates/) contains illustrative examples that are **not** tested against live targets and are not intended to be deployed as-is. -- Files prefixed with `Pattern-` show recommended approaches for a specific integration pattern. -- Files prefixed with `Template` are minimal starters you can copy and fill in. -- Complexity ratings describe the expected customization effort: - - ⭐ **Beginner** — minimal starter or straightforward workflow - - ⭐⭐ **Intermediate** — multiple operations or moderate parsing/orchestration - - ⭐⭐⭐ **Advanced** — discovery, SSH key lifecycle, JIT elevation, dependent systems, file management, or other multi-step flows - -## SSH Samples (`SSH/`) - -Real tested SSH samples for Unix-like systems and appliances. - -| Sample | Complexity | Use case | -| --- | --- | --- | -| [`GenericLinux.json`](SSH/GenericLinux.json) | ⭐⭐ | Baseline Linux local account management over interactive SSH, including SSH host key discovery. | -| [`GenericLinuxWithAD.json`](SSH/GenericLinuxWithAD.json) | ⭐⭐ | Linux SSH account management where the functional account logs in with a domain-qualified identity. | -| [`GenericLinuxWithDiscovery.json`](SSH/GenericLinuxWithDiscovery.json) | ⭐⭐⭐ | Extends the baseline Linux SSH flow with local account discovery. | -| [`GenericLinuxWithSSHKeySupport.json`](SSH/GenericLinuxWithSSHKeySupport.json) | ⭐⭐⭐ | Adds authorized_keys discovery, validation, and rotation to Linux SSH account management. | -| [`LinuxApplicationTextConfig.json`](SSH/LinuxApplicationTextConfig.json) | ⭐⭐⭐ | Rotates an application password stored in a Linux text configuration file over SSH. | -| [`LinuxSshBatchModeExample.json`](SSH/LinuxSshBatchModeExample.json) | ⭐⭐ | Uses remote SSH commands in batch mode instead of an interactive shell for Linux password operations. | -| [`RestrictedAuthorizedKeyExample.json`](SSH/RestrictedAuthorizedKeyExample.json) | ⭐⭐⭐ | Authenticates the service account with a restricted authorized key and passwordless sudo for Linux password operations. | -| [`vCenterServerAppliance.json`](SSH/vCenterServerAppliance.json) | ⭐⭐⭐ | Manages VMware vCenter Server Appliance local root and SSO accounts, including account discovery and synchronized password handling. | - -> `LinuxApplicationTextConfig.json` is primarily a change-password example for file-based application credentials. - -## HTTP Samples (`HTTP/`) - -Real tested HTTP samples ranging from REST APIs to browser-form workflows. - -| Sample | Complexity | Use case | -| --- | --- | --- | -| [`CustomFacebook.json`](HTTP/CustomFacebook.json) | ⭐⭐⭐ | Browser-form HTTP example for Facebook-style credential validation and password change workflows. | -| [`CustomTwitter.json`](HTTP/CustomTwitter.json) | ⭐⭐⭐ | Browser-form HTTP example for Twitter-style login, challenge handling, lock detection, and password changes. | -| [`Forgerock_OpenAM.json`](HTTP/Forgerock_OpenAM.json) | ⭐⭐ | ForgeRock AM 7.5 REST sample for system validation and password rotation. | -| [`Okta_WithDiscoveryAndGroupMembershipRestore.json`](HTTP/Okta_WithDiscoveryAndGroupMembershipRestore.json) | ⭐⭐⭐ | Okta REST sample with account discovery plus group membership restore during enable and disable operations. | -| [`OneLogin_GRC_JIT_addon.json`](HTTP/OneLogin_GRC_JIT_addon.json) | ⭐⭐⭐ | OneLogin add-on for account activation and JIT role elevation in a PIAM/PIdP flow. | -| [`WordPressHttp.json`](HTTP/WordPressHttp.json) | ⭐⭐ | WordPress REST API sample using Basic Auth for system checks, credential validation, and password change. | - -## Telnet Samples (`Telnet/`) - -Real tested Telnet and TN3270 samples for network devices and mainframes. - -| Sample | Complexity | Use case | -| --- | --- | --- | -| [`GenericCiscoIosTelnet.json`](Telnet/GenericCiscoIosTelnet.json) | ⭐⭐⭐ | Cisco IOS Telnet sample for enable-mode validation and local or enable password rotation. | -| [`GenericRacfTn3270.json`](Telnet/GenericRacfTn3270.json) | ⭐⭐⭐ | IBM RACF TN3270 sample for mainframe logon validation and password changes. | - -## Templates (`Templates/`) - -The [`Templates/`](Templates/) folder contains illustrative scripts that help you design your own custom platform. These files are **not** tested against live targets. - -### Pattern templates (`Pattern-*.json`) - -Pattern templates show recommended approaches for specific scenarios. - -| Sample | Complexity | Use case | -| --- | --- | --- | -| [`Pattern-GenericHttpAccountDiscovery.json`](Templates/Pattern-GenericHttpAccountDiscovery.json) | ⭐⭐ | Illustrates paginated REST API account discovery with `WriteDiscoveredAccount`. | -| [`Pattern-GenericHttpJitElevation.json`](Templates/Pattern-GenericHttpJitElevation.json) | ⭐⭐⭐ | Illustrates idempotent JIT elevation over HTTP by adding and removing group membership. | -| [`Pattern-GenericLinuxDependentSystem.json`](Templates/Pattern-GenericLinuxDependentSystem.json) | ⭐⭐⭐ | Illustrates `UpdateDependentSystem` over SSH with a caller-provided dependency command. | -| [`Pattern-GenericLinuxFileManagement.json`](Templates/Pattern-GenericLinuxFileManagement.json) | ⭐⭐⭐ | Illustrates `CheckFile` and `ChangeFile` over SSH, including decode, deploy, and verify steps. | -| [`Pattern-GenericLinuxFull.json`](Templates/Pattern-GenericLinuxFull.json) | ⭐⭐⭐ | Illustrates a comprehensive Linux SSH platform spanning password, SSH key, discovery, and enable/disable operations. | -| [`Pattern-GenericLinuxServiceDiscovery.json`](Templates/Pattern-GenericLinuxServiceDiscovery.json) | ⭐⭐ | Illustrates Linux service discovery over SSH with `WriteDiscoveredService`. | -| [`Pattern-GenericRestApiBasicAuth.json`](Templates/Pattern-GenericRestApiBasicAuth.json) | ⭐⭐ | Illustrates REST API management using HTTP Basic auth for check, change, and discovery workflows. | -| [`Pattern-GenericRestApiBearerToken.json`](Templates/Pattern-GenericRestApiBearerToken.json) | ⭐⭐ | Illustrates REST API management using OAuth2 client credentials and bearer tokens. | -| [`Pattern-GenericRestApiKeyRotation.json`](Templates/Pattern-GenericRestApiKeyRotation.json) | ⭐⭐⭐ | Illustrates API key validation and rotation through a REST API lifecycle. | -| [`Pattern-WindowsSshBasic.json`](Templates/Pattern-WindowsSshBasic.json) | ⭐⭐ | Illustrates Windows password management over SSH with PowerShell and `net user`. | - -### Minimal starters (`Template*.json`) - -Minimal starters give you the smallest possible scaffold for a new platform. - -| Sample | Complexity | Use case | -| --- | --- | --- | -| [`TemplateHttpMinimal.json`](Templates/TemplateHttpMinimal.json) | ⭐ | Minimal HTTP starter that calls a health endpoint with a bearer token. | -| [`TemplateSshMinimal.json`](Templates/TemplateSshMinimal.json) | ⭐ | Minimal SSH starter that validates connectivity with a single echo command. | - -For a folder-focused listing, see [Templates/README.md](Templates/README.md). - -## Which Sample Should I Start With? - -| I need to… | Start here | -| --- | --- | -| Manage a Linux system over SSH | [`GenericLinux.json`](SSH/GenericLinux.json) — the baseline for interactive SSH workflows | -| Add account discovery to Linux | [`GenericLinuxWithDiscovery.json`](SSH/GenericLinuxWithDiscovery.json) — extends the baseline with `DiscoverAccounts` | -| Manage SSH keys on Linux | [`GenericLinuxWithSSHKeySupport.json`](SSH/GenericLinuxWithSSHKeySupport.json) — authorized_keys lifecycle | -| Use SSH in batch mode (no interactive shell) | [`LinuxSshBatchModeExample.json`](SSH/LinuxSshBatchModeExample.json) | -| Manage a REST API with Basic Auth | [`WordPressHttp.json`](HTTP/WordPressHttp.json) — simple REST check/change pattern | -| Manage a REST API with tokens | [`Forgerock_OpenAM.json`](HTTP/Forgerock_OpenAM.json) — token-based REST workflow | -| Discover accounts via REST API | [`Okta_WithDiscoveryAndGroupMembershipRestore.json`](HTTP/Okta_WithDiscoveryAndGroupMembershipRestore.json) | -| Implement JIT privilege elevation | [`OneLogin_GRC_JIT_addon.json`](HTTP/OneLogin_GRC_JIT_addon.json) | -| Handle browser-form login flows | [`CustomFacebook.json`](HTTP/CustomFacebook.json) or [`CustomTwitter.json`](HTTP/CustomTwitter.json) | -| Manage a network device over Telnet | [`GenericCiscoIosTelnet.json`](Telnet/GenericCiscoIosTelnet.json) | -| Manage a mainframe (TN3270) | [`GenericRacfTn3270.json`](Telnet/GenericRacfTn3270.json) | -| Start from scratch (SSH) | [`TemplateSshMinimal.json`](Templates/TemplateSshMinimal.json) — smallest possible scaffold | -| Start from scratch (HTTP) | [`TemplateHttpMinimal.json`](Templates/TemplateHttpMinimal.json) — smallest possible scaffold | - -## Samples by Feature (Advanced) - -Features that only a few samples demonstrate — useful when you need a specific capability: - -| Feature | Samples | -| --- | --- | -| Account discovery (`DiscoverAccounts`) | [`GenericLinuxWithDiscovery.json`](SSH/GenericLinuxWithDiscovery.json), [`vCenterServerAppliance.json`](SSH/vCenterServerAppliance.json), [`Okta_WithDiscoveryAndGroupMembershipRestore.json`](HTTP/Okta_WithDiscoveryAndGroupMembershipRestore.json) | -| SSH key rotation (`CheckSshKey` / `ChangeSshKey`) | [`GenericLinuxWithSSHKeySupport.json`](SSH/GenericLinuxWithSSHKeySupport.json) | -| SSH key discovery (`DiscoverAuthorizedKeys`) | [`GenericLinuxWithSSHKeySupport.json`](SSH/GenericLinuxWithSSHKeySupport.json) | -| Enable / Disable account | [`Okta_WithDiscoveryAndGroupMembershipRestore.json`](HTTP/Okta_WithDiscoveryAndGroupMembershipRestore.json), [`OneLogin_GRC_JIT_addon.json`](HTTP/OneLogin_GRC_JIT_addon.json) | -| JIT elevation (`ElevateAccount` / `DemoteAccount`) | [`OneLogin_GRC_JIT_addon.json`](HTTP/OneLogin_GRC_JIT_addon.json) | -| Dependent systems (`UpdateDependentSystem`) | Pattern: [`Pattern-GenericLinuxDependentSystem.json`](Templates/Pattern-GenericLinuxDependentSystem.json) | -| File management (`CheckFile` / `ChangeFile`) | Pattern: [`Pattern-GenericLinuxFileManagement.json`](Templates/Pattern-GenericLinuxFileManagement.json) | -| Service discovery (`DiscoverServices`) | Pattern: [`Pattern-GenericLinuxServiceDiscovery.json`](Templates/Pattern-GenericLinuxServiceDiscovery.json) | -| API key rotation (`CheckApiKey` / `ChangeApiKey`) | Pattern: [`Pattern-GenericRestApiKeyRotation.json`](Templates/Pattern-GenericRestApiKeyRotation.json) | diff --git a/SampleScripts/SSH/README.md b/SampleScripts/SSH/README.md deleted file mode 100644 index 18538e4..0000000 --- a/SampleScripts/SSH/README.md +++ /dev/null @@ -1,5 +0,0 @@ -[← Sample Scripts](../README.md) - -The Generic Linux script in this directory goes along with a -document -that describes how to write an SSH custom platform script that Safeguard understands. diff --git a/SampleScripts/Templates/README.md b/SampleScripts/Templates/README.md deleted file mode 100644 index 966bbf2..0000000 --- a/SampleScripts/Templates/README.md +++ /dev/null @@ -1,41 +0,0 @@ -[← Sample Scripts](../README.md) - -# Pattern Templates - -These scripts are **pattern templates** — they illustrate recommended approaches -for common integration scenarios. They are _not_ tested against live targets and -should not be deployed without modification. - -Use them as a reference when building your own platform scripts, or copy a -minimal starter and expand from there. - -## Minimal Starters - -| File | Description | -|------|-------------| -| `TemplateSshMinimal.json` | Bare-bones SSH script with CheckSystem only. Copy and expand. | -| `TemplateHttpMinimal.json` | Bare-bones HTTP script with CheckSystem only. Copy and expand. | - -## Pattern Scripts - -| File | Demonstrates | -|------|-------------| -| `Pattern-GenericRestApiBasicAuth.json` | REST API integration using Basic authentication. | -| `Pattern-GenericRestApiBearerToken.json` | REST API integration using OAuth2 Bearer tokens. | -| `Pattern-GenericRestApiKeyRotation.json` | API key rotation workflow with rollback safety. | -| `Pattern-GenericHttpAccountDiscovery.json` | HTTP-based account discovery using paginated API responses. | -| `Pattern-GenericHttpJitElevation.json` | Just-In-Time privilege elevation via HTTP API. | -| `Pattern-GenericLinuxFull.json` | Full Linux SSH workflow: check, change, discover. | -| `Pattern-GenericLinuxDependentSystem.json` | Dependent system updates after a password change. | -| `Pattern-GenericLinuxFileManagement.json` | File-based credential management over SSH. | -| `Pattern-GenericLinuxServiceDiscovery.json` | Service and asset discovery on Linux hosts. | -| `Pattern-WindowsSshBasic.json` | Windows management via OpenSSH (non-WinRM). | - -## Functional Samples - -For production-ready scripts tested against real targets, see the parent -directories: - -- [SSH/](../SSH/) — Linux, AIX, macOS, and Windows-over-SSH samples -- [HTTP/](../HTTP/) — Facebook, OneLogin, Duo, and other HTTP-based platforms -- [Telnet/](../Telnet/) — TN3270 mainframe samples diff --git a/docs/README.md b/docs/README.md index 4f3e72a..52d43f9 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,65 +1,80 @@ -# Safeguard Custom Platform Documentation +[← Home](../README.md) -This documentation hub helps you learn, build, and maintain Safeguard Custom Platform scripts. Start here for onboarding material, detailed references, and task-focused guides. +# Documentation -## Suggested Reading Order +Everything you need to learn, build, and maintain Safeguard custom platform scripts. -1. [Overview](getting-started/overview.md) — Learn the architecture, execution model, and when a custom platform is the right fit. -2. [First Tutorial](getting-started/your-first-ssh-script.md) — Build your first SSH-based script step by step. -3. [Script Structure](reference/script-structure.md) — Understand the JSON layout, operations, and `Do` blocks used by every script. -4. [Operations Reference](reference/operations.md) — Review the supported operations available when implementing a platform. +## Reading Paths -## Getting Started +Choose based on what you need right now: -| Document | Description | -| --- | --- | -| [getting-started/overview.md](getting-started/overview.md) | Architecture, script execution flow, and guidance on whether you need a custom platform. | -| [getting-started/your-first-ssh-script.md](getting-started/your-first-ssh-script.md) | Step-by-step tutorial for creating your first SSH custom platform script. | -| [getting-started/your-first-http-script.md](getting-started/your-first-http-script.md) | Step-by-step tutorial for creating your first HTTP custom platform script (REST API). | -| [getting-started/your-first-form-script.md](getting-started/your-first-form-script.md) | Step-by-step tutorial for managing passwords on web portals with HTML form submission. | -| [getting-started/development-workflow.md](getting-started/development-workflow.md) | End-to-end workflow from upload through testing and iteration. | -| [getting-started/testing-and-debugging.md](getting-started/testing-and-debugging.md) | Test tools, logs, and `extendedLogging` techniques for troubleshooting. | +### 🚀 I want something working fast +→ [Quick Start](quick-start/) — 5-minute paths to a working platform. -## Reference +### 🧠 I want to understand how this works +→ [Concepts](concepts/) — Architecture, execution model, feature flags, lifecycle. -| Document | Description | -| --- | --- | -| [reference/script-structure.md](reference/script-structure.md) | JSON structure, top-level keys, operations, and `Do` blocks. | -| [reference/operations.md](reference/operations.md) | Reference for all supported operations. | -| [reference/reserved-parameters.md](reference/reserved-parameters.md) | Complete reference for reserved platform parameters. | -| [reference/custom-parameters.md](reference/custom-parameters.md) | How to define and use your own custom parameters. | -| [reference/variables.md](reference/variables.md) | Variable system reference for reading, setting, and reusing values. | -| [reference/commands/](reference/commands/) | Command reference organized by category. | -| [reference/imports.md](reference/imports.md) | Reusable SSH function libraries and import patterns. | -| [reference/status-messages.md](reference/status-messages.md) | Predefined status messages available to scripts. | - -## Guides - -| Document | Description | -| --- | --- | -| [guides/ssh-platforms.md](guides/ssh-platforms.md) | SSH design patterns and session integration guidance. | -| [guides/http-platforms.md](guides/http-platforms.md) | REST, OAuth2, and Bearer token implementation patterns. | -| [guides/account-discovery.md](guides/account-discovery.md) | Guidance for discovering accounts through custom platforms. | -| [guides/ssh-key-management.md](guides/ssh-key-management.md) | Patterns for checking, changing, and discovering SSH keys. | -| [guides/api-key-management.md](guides/api-key-management.md) | Approaches for API key rotation workflows. | -| [guides/file-management.md](guides/file-management.md) | Working with file-based credentials and related operations. | -| [guides/jit-elevation.md](guides/jit-elevation.md) | Implementing JIT elevation and demotion scenarios. | -| [guides/dependent-systems.md](guides/dependent-systems.md) | Updating dependent systems as part of platform workflows. | -| [guides/error-handling.md](guides/error-handling.md) | Try/Catch patterns for reliable error handling. | -| [guides/regex-patterns.md](guides/regex-patterns.md) | Practical .NET regex patterns for prompts, parsing, and error detection. | -| [guides/feature-flags.md](guides/feature-flags.md) | How script content enables and shapes platform capabilities. | -| [guides/troubleshooting.md](guides/troubleshooting.md) | Common errors, diagnostics, and recommended fixes. | - -## General - -| Document | Description | -| --- | --- | -| [compatibility.md](compatibility.md) | Compatibility matrix for documented SPP custom platform capabilities and versions. | +### 📖 I want to learn step by step +→ [Tutorials](tutorials/) — Build your first SSH, HTTP, or form-based script from scratch. + +### 🔧 I need to solve a specific problem +→ [Guides](guides/) — Task-focused how-to content: SSH patterns, HTTP patterns, discovery, error handling, testing. + +### 📋 I need to look up a detail +→ [Reference](reference/) — Commands, operations, parameters, variables, imports. + +--- + +## Full Table of Contents + +### Quick Start +- [SSH Password Change in 5 Minutes](quick-start/ssh-password-change.md) +- [HTTP API Check in 5 Minutes](quick-start/http-api-check.md) + +### Concepts +- [Architecture](concepts/architecture.md) — What custom platforms are and when you need one +- [Script Execution Model](concepts/script-execution-model.md) — How SPP loads and runs scripts +- [Feature Flags](concepts/feature-flags.md) — Automatic capability derivation from script content +- [Platform Lifecycle](concepts/platform-lifecycle.md) — From authoring to production and updates + +### Tutorials +- [Your First SSH Script](tutorials/your-first-ssh-script.md) +- [Your First HTTP Script](tutorials/your-first-http-script.md) +- [Your First Form Script](tutorials/your-first-form-script.md) +- [Building a Complete Platform](tutorials/building-a-complete-platform.md) + +### Guides +- [Development Workflow](guides/development-workflow.md) +- [Testing and Debugging](guides/testing-and-debugging.md) +- [SSH Platforms](guides/ssh-platforms.md) +- [HTTP Platforms](guides/http-platforms.md) +- [Account Discovery](guides/account-discovery.md) +- [SSH Key Management](guides/ssh-key-management.md) +- [API Key Management](guides/api-key-management.md) +- [File Management](guides/file-management.md) +- [JIT Elevation](guides/jit-elevation.md) +- [Dependent Systems](guides/dependent-systems.md) +- [Error Handling](guides/error-handling.md) +- [Regex Patterns](guides/regex-patterns.md) +- [Troubleshooting](guides/troubleshooting.md) + +### Reference +- [Script Structure](reference/script-structure.md) +- [Operations](reference/operations.md) (19 operations) +- [Reserved Parameters](reference/reserved-parameters.md) (72 parameters) +- [Custom Parameters](reference/custom-parameters.md) +- [Variables](reference/variables.md) +- [Commands](reference/commands/) (60+ commands) +- [Imports](reference/imports.md) +- [Status Messages](reference/status-messages.md) +- [Compatibility Matrix](reference/compatibility.md) ## Additional Resources | Resource | Description | | --- | --- | -| [SampleScripts](../SampleScripts/) | Working examples you can use as references when building scripts. | -| [TestTool.ps1](../tools/TestTool.ps1) | Local test tool for validating and iterating on platform scripts. | -| [One Identity Support](https://support.oneidentity.com/) | General Safeguard product documentation, downloads, and support resources. | +| [Samples](../samples/) | Production-tested scripts with companion documentation | +| [Templates](../templates/) | Pattern templates and minimal starters | +| [TestTool.ps1](../tools/TestTool.ps1) | Local script validation tool | +| [JSON Schema](../schema/custom-platform-script.schema.json) | IDE autocomplete schema | +| [One Identity Support](https://support.oneidentity.com/) | Official product support | diff --git a/docs/concepts/README.md b/docs/concepts/README.md new file mode 100644 index 0000000..bb3fa86 --- /dev/null +++ b/docs/concepts/README.md @@ -0,0 +1,12 @@ +[← Documentation](../README.md) + +# Concepts + +Understand how Safeguard custom platforms work before you start building. + +Read in this order: + +1. [Architecture](architecture.md) — What custom platforms are, the execution model, and when you need one. +2. [Feature Flags](feature-flags.md) — How SPP automatically derives platform capabilities from your script content. +3. [Script Execution Model](script-execution-model.md) — How SPP loads, validates, expands, and runs your script at task time. +4. [Platform Lifecycle](platform-lifecycle.md) — The full lifecycle: authoring → upload → testing → production → updates. diff --git a/docs/getting-started/overview.md b/docs/concepts/architecture.md similarity index 99% rename from docs/getting-started/overview.md rename to docs/concepts/architecture.md index 7e62d4a..e298237 100644 --- a/docs/getting-started/overview.md +++ b/docs/concepts/architecture.md @@ -1,4 +1,4 @@ -[← Documentation](../README.md) +[← Concepts](README.md) # Architecture Overview diff --git a/docs/guides/feature-flags.md b/docs/concepts/feature-flags.md similarity index 99% rename from docs/guides/feature-flags.md rename to docs/concepts/feature-flags.md index 738f16d..6e4c79a 100644 --- a/docs/guides/feature-flags.md +++ b/docs/concepts/feature-flags.md @@ -1,4 +1,4 @@ -[← Documentation](../README.md) +[← Concepts](README.md) # Platform Feature Flags diff --git a/docs/concepts/platform-lifecycle.md b/docs/concepts/platform-lifecycle.md new file mode 100644 index 0000000..1ac811c --- /dev/null +++ b/docs/concepts/platform-lifecycle.md @@ -0,0 +1,132 @@ +[← Concepts](README.md) + +# Platform Lifecycle + +This document covers the full lifecycle of a custom platform — from initial development through production deployment and ongoing maintenance. + +## Phases + +``` +Author → Upload → Test → Deploy → Monitor → Update +``` + +## 1. Author + +Write your script as a JSON file on your workstation. Use an IDE with the JSON schema for autocomplete: + +- Schema: [`schema/custom-platform-script.schema.json`](../../schema/custom-platform-script.schema.json) +- VS Code setup: the `.vscode/` directory in this repo configures schema association automatically. + +Start from a [template](../../templates/) or an existing [sample](../../samples/) that matches your target system. + +**Best practices during authoring:** +- Start small — get `CheckSystem` working first, then add operations incrementally. +- Use the [development workflow](../guides/development-workflow.md) guide for the upload-test-iterate cycle. +- Test each operation independently before combining them. + +## 2. Upload + +Upload your script to SPP using either method: + +**PowerShell (recommended for development):** +```powershell +Import-SafeguardCustomPlatformScript -FilePath .\MyPlatform.json +``` + +**Web UI:** +1. Navigate to **Asset Management > Connect and Platforms > Custom Platforms** +2. Click **Add** +3. Browse to your JSON file and upload + +SPP validates the script immediately. If validation fails, you get an error message describing the issue. Fix the script and re-upload. + +## 3. Test + +Testing happens in two stages: + +### Local Validation +Use the [TestTool](../../tools/TestTool.ps1) to validate JSON structure before uploading: +```powershell +.\tools\TestTool.ps1 -ScriptFile .\MyPlatform.json +``` + +### Live Testing +After upload, test against a real (non-production) target: + +1. Create a test asset using your custom platform +2. Configure valid credentials +3. Run individual operations: + +```powershell +# Test connectivity +Test-SafeguardAssetConnection -AssetToUse "TestHost" -ExtendedLogging + +# Test password check +Test-SafeguardAssetAccountPassword -AssetToUse "TestHost" -AccountToUse "testuser" -ExtendedLogging + +# Test password change (use a disposable test account!) +Invoke-SafeguardAssetAccountPasswordChange -AssetToUse "TestHost" -AccountToUse "testuser" +``` + +The `-ExtendedLogging` flag captures the full execution trace in the task log, which is essential for debugging. + +See [Testing and Debugging](../guides/testing-and-debugging.md) for detailed guidance. + +## 4. Deploy + +Once testing passes: + +1. Create production assets using the custom platform +2. Assign real service accounts and managed accounts +3. Configure check and change schedules +4. Set up profiles and access policies as needed + +**Deployment checklist:** +- [ ] All operations tested successfully with ExtendedLogging +- [ ] Error paths tested (wrong password, unreachable host, locked account) +- [ ] Service account has appropriate privileges on the target +- [ ] Network connectivity confirmed from the SPP appliance to the target +- [ ] Schedules configured appropriately (not too aggressive) + +## 5. Monitor + +After deployment, monitor platform health through: + +- **Task logs** — Check for failed tasks in the SPP Activity Center +- **Password check results** — Confirm scheduled checks pass consistently +- **Account discovery** — If enabled, verify discovered accounts appear correctly + +## 6. Update + +To update a platform script: + +1. Download the current version: use the **Download** button in Custom Platforms or the API +2. Make your changes locally +3. Test the changes against a test asset +4. Upload the updated script — SPP replaces the old version + +**Important:** Updating a script does NOT change parameter defaults on existing assets. If you add a new custom parameter with a default value, existing assets won't pick up that default automatically — you need to update them individually or recreate them. + +## Version Management + +SPP does not version custom platform scripts internally. Best practices: + +- Keep your scripts in version control (like this repository) +- Use meaningful commit messages for changes +- Tag releases if you distribute scripts to multiple SPP instances +- Document breaking changes (parameter renames, operation removals) clearly + +## Deprecation + +To deprecate a custom platform: + +1. Ensure no assets are actively using it (or migrate them to a replacement) +2. Delete the custom platform from **Asset Management > Custom Platforms** + +**Warning:** Deleting a custom platform that is assigned to assets will reassign those assets to the "Other" platform type, which halts all credential management operations. + +## Related + +- [Architecture](architecture.md) — how custom platforms fit into SPP +- [Development Workflow](../guides/development-workflow.md) — the upload-test-iterate cycle +- [Testing and Debugging](../guides/testing-and-debugging.md) — detailed testing guidance diff --git a/docs/concepts/script-execution-model.md b/docs/concepts/script-execution-model.md new file mode 100644 index 0000000..79cc4c6 --- /dev/null +++ b/docs/concepts/script-execution-model.md @@ -0,0 +1,91 @@ +[← Concepts](README.md) + +# Script Execution Model + +This document explains what happens when SPP runs a custom platform script — from the moment you upload a JSON file to the moment a task executes against a target system. + +## Upload and Validation + +When you upload a script (via the web UI or `Import-SafeguardCustomPlatformScript`), SPP performs these steps in order: + +1. **JSON parse** — The file must be valid JSON. Syntax errors are rejected immediately. +2. **Structure validation** — SPP checks for required top-level keys (`Id`, `BackEnd`) and verifies that operations contain `Parameters` and `Do` arrays. +3. **Parameter type checking** — Each parameter is validated against known types (string, boolean, integer, password/secret). Reserved parameter names are matched against their expected types. +4. **Import expansion** — If the script declares `Imports`, SPP locates the referenced function libraries and merges their function definitions into the script. The expanded script is what gets stored. +5. **Feature flag derivation** — SPP scans the operations present in the script and sets capability flags automatically. See [Feature Flags](feature-flags.md). +6. **Storage** — The validated, expanded script is stored in the SPP database and the platform is ready for use. + +## Task Execution + +When SPP needs to perform an operation (e.g., a scheduled password check), this is the execution flow: + +### 1. Operation Selection + +SPP determines which operation to call based on the task type: +- A password check task invokes `CheckPassword` +- A password change task invokes `ChangePassword` +- An account discovery task invokes `DiscoverAccounts` +- And so on for all 19 operations + +### 2. Parameter Population + +SPP auto-populates reserved parameters from the asset and account configuration: +- `Address` ← asset network address +- `Port` ← asset connection port +- `FuncUserName` / `FuncPassword` ← service account credentials +- `AccountUserName` / `AccountPassword` ← managed account credentials +- `NewPassword` ← the SPP-generated replacement password (for change operations) + +Custom parameters retain their configured default values unless overridden at the asset level. + +### 3. Script Engine Execution + +The scripting engine processes the operation's `Do` array sequentially: + +1. Each command in the `Do` array is executed in order. +2. Variable interpolation (`%VariableName%`) is resolved at execution time. +3. Commands may set variables, make connections, send data, or branch execution. +4. Flow control commands (`Condition`, `Switch`, `For`, `ForEach`) alter the execution path. +5. Functions can be called and may return values. +6. Error handling (`Try`/`Catch`) provides recovery paths. + +### 4. Result Determination + +The operation result is determined by: +- **Success** — The `Do` block completes without an unhandled error. +- **Failure** — A `Throw` command executes without a surrounding `Try`/`Catch`, or a connection fails, or an unrecoverable error occurs. + +For discovery operations, success means the script called `WriteDiscoveredAccount` (or `WriteDiscoveredService`, etc.) one or more times before completing. + +## Connection Lifecycle + +For SSH operations, the connection lifecycle is: +1. `Connect` opens the SSH session (interactive or batch mode) +2. Commands interact with the remote system +3. `Disconnect` closes the session +4. If the script ends without `Disconnect`, the engine cleans up automatically + +For HTTP operations, there is no persistent connection — each `Request` is independent (though cookies and session state persist across requests within a single operation execution). + +## Import Libraries + +When a script declares `Imports`, the referenced function libraries are expanded into the script at upload time. At runtime, these imported functions are available for the script to call just like locally-defined functions. + +Import libraries provide reusable patterns for common tasks (e.g., SSH login sequences, privilege escalation, output parsing). See [Imports Reference](../reference/imports.md) for the full catalog. + +## Error Propagation + +Errors propagate up the call stack: +1. A command fails or `Throw` is called +2. If inside a `Try` block, execution jumps to the `Catch` block +3. If not caught, the error propagates to the calling function +4. If uncaught at the top level, the operation fails + +The task log captures all errors and, with `ExtendedLogging` enabled, captures the full execution trace. + +## Related + +- [Architecture](architecture.md) — high-level overview +- [Feature Flags](feature-flags.md) — how capabilities are derived +- [Operations Reference](../reference/operations.md) — all 19 operations +- [Testing and Debugging](../guides/testing-and-debugging.md) — how to diagnose execution issues diff --git a/docs/guides/.gitkeep b/docs/guides/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/docs/guides/README.md b/docs/guides/README.md new file mode 100644 index 0000000..7004598 --- /dev/null +++ b/docs/guides/README.md @@ -0,0 +1,38 @@ +[← Documentation](../README.md) + +# Guides + +Task-focused how-to documentation for building and maintaining custom platforms. Each guide covers a specific topic in depth. + +## Development + +| Guide | Description | +| --- | --- | +| [Development Workflow](development-workflow.md) | End-to-end workflow from authoring through upload, testing, and iteration. | +| [Testing and Debugging](testing-and-debugging.md) | Test tools, task logs, `ExtendedLogging`, and diagnostic techniques. | +| [Error Handling](error-handling.md) | Try/Catch patterns for reliable error recovery in scripts. | +| [Regex Patterns](regex-patterns.md) | Practical .NET regex patterns for prompts, parsing, and error detection. | +| [Troubleshooting](troubleshooting.md) | Common errors, diagnostics, and recommended fixes. | + +## SSH Platforms + +| Guide | Description | +| --- | --- | +| [SSH Platforms](ssh-platforms.md) | SSH design patterns: interactive vs. batch, login flows, prompt detection. | +| [SSH Key Management](ssh-key-management.md) | Checking, changing, and discovering SSH authorized keys. | + +## HTTP Platforms + +| Guide | Description | +| --- | --- | +| [HTTP Platforms](http-platforms.md) | REST, OAuth2, Bearer tokens, forms, and cookie-based workflows. | +| [API Key Management](api-key-management.md) | API key validation and rotation patterns. | + +## Advanced Features + +| Guide | Description | +| --- | --- | +| [Account Discovery](account-discovery.md) | Implementing `DiscoverAccounts` and `DiscoverServices` operations. | +| [File Management](file-management.md) | Working with file-based credentials (`CheckFile`/`ChangeFile`). | +| [JIT Elevation](jit-elevation.md) | Implementing just-in-time privilege elevation and demotion. | +| [Dependent Systems](dependent-systems.md) | Updating dependent systems as part of credential rotation workflows. | diff --git a/docs/guides/account-discovery.md b/docs/guides/account-discovery.md index a81010a..59c81cd 100644 --- a/docs/guides/account-discovery.md +++ b/docs/guides/account-discovery.md @@ -1,4 +1,4 @@ -[← Documentation](../README.md) +[← Guides](README.md) # Account Discovery Guide @@ -523,7 +523,7 @@ If that restriction changes in the future, the related pattern would be similar - [Operations Reference](../reference/operations.md) - [Output Commands](../reference/commands/output.md) - [Command Index](../reference/commands/index.md) -- [Your First SSH Script](../getting-started/your-first-ssh-script.md) -- [Your First HTTP Script](../getting-started/your-first-http-script.md) +- [Your First SSH Script](../tutorials/your-first-ssh-script.md) +- [Your First HTTP Script](../tutorials/your-first-http-script.md) - [SSH Platforms Guide](ssh-platforms.md) - [HTTP Platforms Guide](http-platforms.md) diff --git a/docs/guides/api-key-management.md b/docs/guides/api-key-management.md index ca0eee2..568c2b9 100644 --- a/docs/guides/api-key-management.md +++ b/docs/guides/api-key-management.md @@ -1,4 +1,4 @@ -[← Documentation](../README.md) +[← Guides](README.md) # API Key Management @@ -413,5 +413,5 @@ Design your script so these cases produce a clear error message and never report - [Operations Reference](../reference/operations.md) - [Reserved Parameters](../reference/reserved-parameters.md) - [HTTP/REST API Platforms](http-platforms.md) -- [Your First HTTP Script](../getting-started/your-first-http-script.md) +- [Your First HTTP Script](../tutorials/your-first-http-script.md) - [Output Commands](../reference/commands/output.md) diff --git a/docs/guides/dependent-systems.md b/docs/guides/dependent-systems.md index 17a4316..00088ea 100644 --- a/docs/guides/dependent-systems.md +++ b/docs/guides/dependent-systems.md @@ -1,4 +1,4 @@ -[← Documentation](../README.md) +[← Guides](README.md) # Dependent Systems Guide diff --git a/docs/getting-started/development-workflow.md b/docs/guides/development-workflow.md similarity index 98% rename from docs/getting-started/development-workflow.md rename to docs/guides/development-workflow.md index 4e80b93..7950a50 100644 --- a/docs/getting-started/development-workflow.md +++ b/docs/guides/development-workflow.md @@ -1,4 +1,4 @@ -[← Documentation](../README.md) +[← Guides](README.md) # Development Workflow @@ -38,7 +38,7 @@ In practice, you will repeat this cycle many times while you refine connectivity Start with a known-good base whenever possible. -- Begin from a template in `SampleScripts/Templates/` or adapt an existing sample script that is close to your target system. +- Begin from a template in `templates/` or adapt an existing sample script that is close to your target system. - Use a JSON-aware editor so syntax errors are caught before upload. - Refer to [Script Structure](../reference/script-structure.md) for the required format, top-level keys, operations, and `Do` blocks. - Validate early with `Test-SafeguardCustomPlatformScript` before you even create a custom platform on the appliance. diff --git a/docs/guides/error-handling.md b/docs/guides/error-handling.md index 9c2c2de..7f46aaf 100644 --- a/docs/guides/error-handling.md +++ b/docs/guides/error-handling.md @@ -1,4 +1,4 @@ -[← Documentation](../README.md) +[← Guides](README.md) # Error Handling Guide @@ -80,7 +80,7 @@ A few important points: - `Try` also supports `Finally`, which always runs after `Do` or `Catch`. This is useful for cleanup. - `Finally` cannot `Return` or `Break`. If `Finally` throws, that cleanup error replaces the earlier result. -For syntax details, see [Error Handling Commands](../reference/commands/error-handling.md). For real examples, compare [`GenericLinux.json`](../../SampleScripts/SSH/GenericLinux.json), [`CustomFacebook.json`](../../SampleScripts/HTTP/CustomFacebook.json), and [`OneLogin_GRC_JIT_addon.json`](../../SampleScripts/HTTP/OneLogin_GRC_JIT_addon.json). +For syntax details, see [Error Handling Commands](../reference/commands/error-handling.md). For real examples, compare [`GenericLinux.json`](../../samples/ssh/generic-linux/GenericLinux.json), [`CustomFacebook.json`](../../samples/http/facebook/CustomFacebook.json), and [`OneLogin_GRC_JIT_addon.json`](../../samples/http/onelogin-jit/OneLogin_GRC_JIT_addon.json). ## Choosing between `Return true`, `Return false`, and `Throw` @@ -582,7 +582,7 @@ For broader HTTP patterns, see [HTTP/REST API Platforms](http-platforms.md). ## Using `ExitStatusBufferName` and `Condition` -For SSH batch-mode scripts, [`ExitStatusBufferName`](../reference/commands/execute-command.md) is the standard way to capture a command's numeric exit code. Pair it with [`Condition`](../reference/commands/flow-control.md) so the script can decide whether the result means success, failure, or error. [`LinuxSshBatchModeExample.json`](../../SampleScripts/SSH/LinuxSshBatchModeExample.json) is a good end-to-end sample of this pattern. +For SSH batch-mode scripts, [`ExitStatusBufferName`](../reference/commands/execute-command.md) is the standard way to capture a command's numeric exit code. Pair it with [`Condition`](../reference/commands/flow-control.md) so the script can decide whether the result means success, failure, or error. [`LinuxSshBatchModeExample.json`](../../samples/ssh/linux-ssh-batch-mode/LinuxSshBatchModeExample.json) is a good end-to-end sample of this pattern. ```json [ diff --git a/docs/guides/file-management.md b/docs/guides/file-management.md index 3d6d035..eb7b4aa 100644 --- a/docs/guides/file-management.md +++ b/docs/guides/file-management.md @@ -1,4 +1,4 @@ -[← Documentation](../README.md) +[← Guides](README.md) # File Management Guide @@ -484,7 +484,7 @@ File-based credentials are often long-lived, high-value secrets. Handle them lik - [Reserved Parameters Reference](../reference/reserved-parameters.md#file-management) - [SSH Platforms Guide](ssh-platforms.md) - [HTTP Platforms Guide](http-platforms.md) -- [Your First SSH Script](../getting-started/your-first-ssh-script.md) +- [Your First SSH Script](../tutorials/your-first-ssh-script.md) - [Variables Reference](../reference/variables.md) - [ExecuteCommand](../reference/commands/execute-command.md) - [Request](../reference/commands/request.md) diff --git a/docs/guides/http-platforms.md b/docs/guides/http-platforms.md index e72e709..d4f7d1f 100644 --- a/docs/guides/http-platforms.md +++ b/docs/guides/http-platforms.md @@ -1,4 +1,4 @@ -[← Documentation](../README.md) +[← Guides](README.md) # HTTP/REST API Platforms @@ -112,7 +112,7 @@ For APIs that accept a username and password on every request, use [`HttpAuth`]( ] ``` -This is the pattern used by `SampleScripts/HTTP/WordPressHttp.json`. +This is the pattern used by `samples/http/wordpress/WordPressHttp.json`. > [!IMPORTANT] > [`HttpAuth`](../reference/commands/http-auth.md) currently supports `Basic` and `Digest`. For `Bearer` tokens and most API-key schemes, add the header yourself with [`Headers`](../reference/commands/http-setup.md). @@ -184,7 +184,7 @@ A common pattern is: ] ``` -This is the same overall shape used in `SampleScripts/HTTP/OneLogin_GRC_JIT_addon.json`, which stores a token and then sends `Authorization: "Bearer %AccessToken%"` on later `Request` commands. +This is the same overall shape used in `samples/http/onelogin-jit/OneLogin_GRC_JIT_addon.json`, which stores a token and then sends `Authorization: "Bearer %AccessToken%"` on later `Request` commands. ### API keys in headers @@ -215,7 +215,7 @@ If the API expects an API key instead of a bearer token, add it with [`Headers`] ] ``` -That is the same style used in `SampleScripts/HTTP/Okta_WithDiscoveryAndGroupMembershipRestore.json`. +That is the same style used in `samples/http/okta-discovery/Okta_WithDiscoveryAndGroupMembershipRestore.json`. The header name can be anything the API requires: @@ -235,7 +235,7 @@ Some systems do not expose a clean REST login endpoint. Instead, they expect the 5. `POST` the form. 6. Reuse the resulting cookies on later requests. -This is the pattern used by `SampleScripts/HTTP/CustomTwitter.json` and `SampleScripts/HTTP/CustomFacebook.json`. +This is the pattern used by `samples/http/twitter/CustomTwitter.json` and `samples/http/facebook/CustomFacebook.json`. ## Common end-to-end flow @@ -552,7 +552,7 @@ Practical guidance: If the page depends on JavaScript to build the real request, inspect the browser traffic and target the underlying HTTP endpoint directly. Safeguard cannot run the page's JavaScript for you. -For a full walkthrough, see [Your First Form Script](../getting-started/your-first-form-script.md). +For a full walkthrough, see [Your First Form Script](../tutorials/your-first-form-script.md). ## Cookie management @@ -715,7 +715,7 @@ Build a URL with `limit` and an offset or page number, then loop until the curre ### Link-header or cursor pagination -Some APIs return a `Link` header or a `next` cursor instead of page numbers. `SampleScripts/HTTP/Okta_WithDiscoveryAndGroupMembershipRestore.json` shows this style: it reads the `Link` header and loops until there is no next link. +Some APIs return a `Link` header or a `next` cursor instead of page numbers. `samples/http/okta-discovery/Okta_WithDiscoveryAndGroupMembershipRestore.json` shows this style: it reads the `Link` header and loops until there is no next link. Use this pattern when: @@ -892,7 +892,7 @@ Use this guide together with the command reference pages: - [`JSON`](../reference/commands/json.md) - [`Flow Control`](../reference/commands/flow-control.md) - [`Error Handling`](../reference/commands/error-handling.md) -- [Your First HTTP Script](../getting-started/your-first-http-script.md) -- [Your First Form Script](../getting-started/your-first-form-script.md) +- [Your First HTTP Script](../tutorials/your-first-http-script.md) +- [Your First Form Script](../tutorials/your-first-form-script.md) When you are building a new HTTP platform, start simple: verify connectivity with one authenticated `GET`, confirm the response parsing works, and only then add multi-step login, pagination, retries, and cleanup logic. diff --git a/docs/guides/jit-elevation.md b/docs/guides/jit-elevation.md index 29ab5d4..d543ec3 100644 --- a/docs/guides/jit-elevation.md +++ b/docs/guides/jit-elevation.md @@ -1,4 +1,4 @@ -[← Documentation](../README.md) +[← Guides](README.md) # JIT Elevation and Account Lifecycle Operations @@ -545,8 +545,8 @@ The user never needs to know whether the target-side change was done with SSH co The repository already includes a JIT-focused OneLogin sample: -- [`../../SampleScripts/HTTP/OneLogin_GRC_JIT_addon.json`](../../SampleScripts/HTTP/OneLogin_GRC_JIT_addon.json) -- [`../../SampleScripts/HTTP/README.md`](../../SampleScripts/HTTP/README.md) +- [`../../samples/http/onelogin-jit/OneLogin_GRC_JIT_addon.json`](../../samples/http/onelogin-jit/OneLogin_GRC_JIT_addon.json) +- [`../../samples/http/README.md`](../../samples/http/README.md) That sample is useful because it implements both pairs: diff --git a/docs/guides/regex-patterns.md b/docs/guides/regex-patterns.md index fb1218e..237a289 100644 --- a/docs/guides/regex-patterns.md +++ b/docs/guides/regex-patterns.md @@ -1,4 +1,4 @@ -[← Documentation](../README.md) +[← Guides](README.md) # Regex Patterns Guide @@ -307,7 +307,7 @@ Use these patterns as starting points. Adjust them to the exact output your targ - **Be careful with greedy `.*`.** Use `.*?` when you are matching between start and end markers. - **Strip ANSI when needed.** Colored prompts can make a correct prompt regex look broken. - **Keep parsing in small steps.** Capture into `match`, inspect `match.Success`, then read named groups. -- **Use the local test workflow before upload.** See [Testing and Debugging](../getting-started/testing-and-debugging.md) and the repository's `tools\TestTool.ps1`. +- **Use the local test workflow before upload.** See [Testing and Debugging](../guides/testing-and-debugging.md) and the repository's `tools\TestTool.ps1`. ## Related references @@ -317,4 +317,4 @@ Use these patterns as starting points. Adjust them to the exact output your targ - [Variables Reference](../reference/variables.md) - [SSH Platforms Guide](ssh-platforms.md) - [Error Handling Guide](error-handling.md) -- [Testing and Debugging](../getting-started/testing-and-debugging.md) +- [Testing and Debugging](../guides/testing-and-debugging.md) diff --git a/docs/guides/ssh-key-management.md b/docs/guides/ssh-key-management.md index 66d44ad..153fb78 100644 --- a/docs/guides/ssh-key-management.md +++ b/docs/guides/ssh-key-management.md @@ -1,4 +1,4 @@ -[← Documentation](../README.md) +[← Guides](README.md) # SSH Key Management Guide @@ -103,7 +103,7 @@ Do not assume only one path exists. A practical Unix pattern is to check multipl - `%h/.ssh/authorized_keys` - `%h/.ssh/authorized_keys2` -[`GenericLinuxWithSSHKeySupport.json`](../../SampleScripts/SSH/GenericLinuxWithSSHKeySupport.json) follows exactly that pattern and resolves the final paths before check, change, or discovery. +[`GenericLinuxWithSSHKeySupport.json`](../../samples/ssh/generic-linux-ssh-keys/GenericLinuxWithSSHKeySupport.json) follows exactly that pattern and resolves the final paths before check, change, or discovery. ### 2. Check for a key with exact matching @@ -154,7 +154,7 @@ A simplified append step looks like this: } ``` -The sample [`GenericLinuxWithSSHKeySupport.json`](../../SampleScripts/SSH/GenericLinuxWithSSHKeySupport.json) uses the same overall approach, including backup and rollback. +The sample [`GenericLinuxWithSSHKeySupport.json`](../../samples/ssh/generic-linux-ssh-keys/GenericLinuxWithSSHKeySupport.json) uses the same overall approach, including backup and rollback. ### 4. Remove the old key by rewriting the file @@ -288,7 +288,7 @@ Restricted keys are keys with option prefixes such as: - `no-port-forwarding` - `restrict` -The repository's [`RestrictedAuthorizedKeyExample.json`](../../SampleScripts/SSH/RestrictedAuthorizedKeyExample.json) shows the broader pattern of using a restricted key for service-account authentication. For target-account key management, the important lesson is the same: do not assume a key line starts with `ssh-rsa` or `ssh-ed25519`. +The repository's [`RestrictedAuthorizedKeyExample.json`](../../samples/ssh/restricted-authorized-key/RestrictedAuthorizedKeyExample.json) shows the broader pattern of using a restricted key for service-account authentication. For target-account key management, the important lesson is the same: do not assume a key line starts with `ssh-rsa` or `ssh-ed25519`. A good parser anchors on the key type but allows an optional prefix before it: @@ -390,6 +390,6 @@ During `DiscoverAuthorizedKeys`, it is fine to skip blank or malformed lines. Bu - [Reserved Parameters](../reference/reserved-parameters.md) - [SSH Platforms Guide](ssh-platforms.md) - [Imports](../reference/imports.md) -- [Your First SSH Script](../getting-started/your-first-ssh-script.md) +- [Your First SSH Script](../tutorials/your-first-ssh-script.md) - [Account Discovery](account-discovery.md) - [Output Commands](../reference/commands/output.md) diff --git a/docs/guides/ssh-platforms.md b/docs/guides/ssh-platforms.md index 61b4e7a..9b60087 100644 --- a/docs/guides/ssh-platforms.md +++ b/docs/guides/ssh-platforms.md @@ -1,4 +1,4 @@ -[← Documentation](../README.md) +[← Guides](README.md) # SSH Platforms Guide @@ -31,13 +31,13 @@ As a rule: - Use **interactive SSH** when you must react to prompts one step at a time. - Use **batch mode** when the remote system can do the whole job with normal command execution. -- Prefer **sample-first development**. Start from a close match in [`SampleScripts/SSH`](../../SampleScripts/SSH/) instead of building from scratch. +- Prefer **sample-first development**. Start from a close match in [`samples/SSH`](../../samples/ssh/) instead of building from scratch. ## Connection and login patterns ### Interactive expect-style pattern -This is the classic Linux pattern used in [`GenericLinux.json`](../../SampleScripts/SSH/GenericLinux.json): connect, flush the banner, set up the shell, send a command, receive output, and react to prompts. +This is the classic Linux pattern used in [`GenericLinux.json`](../../samples/ssh/generic-linux/GenericLinux.json): connect, flush the banner, set up the shell, send a command, receive output, and react to prompts. ```json { @@ -109,7 +109,7 @@ Use this pattern when: - the target behaves like a normal SSH command runner - you do not need a PTY - you want cleaner stdout, stderr, and exit-code handling -- you are working from samples such as [`LinuxSshBatchModeExample.json`](../../SampleScripts/SSH/LinuxSshBatchModeExample.json) or [`RestrictedAuthorizedKeyExample.json`](../../SampleScripts/SSH/RestrictedAuthorizedKeyExample.json) +- you are working from samples such as [`LinuxSshBatchModeExample.json`](../../samples/ssh/linux-ssh-batch-mode/LinuxSshBatchModeExample.json) or [`RestrictedAuthorizedKeyExample.json`](../../samples/ssh/restricted-authorized-key/RestrictedAuthorizedKeyExample.json) ## Using `Connect`, `Disconnect`, `Send`, `Receive`, and `ExecuteCommand` @@ -474,22 +474,22 @@ The Linux samples set environment variables so prompts are more predictable and - For interactive shells, detect a `sudo` or `su` password prompt with `Receive`. - For batch mode, use `ExecuteCommand` and inspect `stderr` and `rc`. - If `sudo` requires a password, decide whether to support that path explicitly or require password-less sudo for the service account. -- If your script uses a restricted authorized key, follow the batch-mode patterns from [`RestrictedAuthorizedKeyExample.json`](../../SampleScripts/SSH/RestrictedAuthorizedKeyExample.json). +- If your script uses a restricted authorized key, follow the batch-mode patterns from [`RestrictedAuthorizedKeyExample.json`](../../samples/ssh/restricted-authorized-key/RestrictedAuthorizedKeyExample.json). ## Sample scripts to study Start with the closest example in this repository: -- [`GenericLinux.json`](../../SampleScripts/SSH/GenericLinux.json) - interactive Linux password workflows -- [`GenericLinuxWithSSHKeySupport.json`](../../SampleScripts/SSH/GenericLinuxWithSSHKeySupport.json) - interactive Linux plus SSH key management -- [`GenericLinuxWithDiscovery.json`](../../SampleScripts/SSH/GenericLinuxWithDiscovery.json) - interactive Linux plus discovery helpers -- [`LinuxSshBatchModeExample.json`](../../SampleScripts/SSH/LinuxSshBatchModeExample.json) - non-interactive `ExecuteCommand` pattern -- [`RestrictedAuthorizedKeyExample.json`](../../SampleScripts/SSH/RestrictedAuthorizedKeyExample.json) - restricted-key SSH authentication with batch-mode command execution -- [`vCenterServerAppliance.json`](../../SampleScripts/SSH/vCenterServerAppliance.json) - appliance-specific interactive flow with timing considerations +- [`GenericLinux.json`](../../samples/ssh/generic-linux/GenericLinux.json) - interactive Linux password workflows +- [`GenericLinuxWithSSHKeySupport.json`](../../samples/ssh/generic-linux-ssh-keys/GenericLinuxWithSSHKeySupport.json) - interactive Linux plus SSH key management +- [`GenericLinuxWithDiscovery.json`](../../samples/ssh/generic-linux-with-discovery/GenericLinuxWithDiscovery.json) - interactive Linux plus discovery helpers +- [`LinuxSshBatchModeExample.json`](../../samples/ssh/linux-ssh-batch-mode/LinuxSshBatchModeExample.json) - non-interactive `ExecuteCommand` pattern +- [`RestrictedAuthorizedKeyExample.json`](../../samples/ssh/restricted-authorized-key/RestrictedAuthorizedKeyExample.json) - restricted-key SSH authentication with batch-mode command execution +- [`vCenterServerAppliance.json`](../../samples/ssh/vcenter-appliance/vCenterServerAppliance.json) - appliance-specific interactive flow with timing considerations ## Related references -- [Your First SSH Script](../getting-started/your-first-ssh-script.md) +- [Your First SSH Script](../tutorials/your-first-ssh-script.md) - [Connect and Disconnect](../reference/commands/connect.md) - [Send and Receive](../reference/commands/send-receive.md) - [ExecuteCommand](../reference/commands/execute-command.md) diff --git a/docs/getting-started/testing-and-debugging.md b/docs/guides/testing-and-debugging.md similarity index 95% rename from docs/getting-started/testing-and-debugging.md rename to docs/guides/testing-and-debugging.md index 8dbb9fe..20c7a42 100644 --- a/docs/getting-started/testing-and-debugging.md +++ b/docs/guides/testing-and-debugging.md @@ -1,4 +1,4 @@ -[← Documentation](../README.md) +[← Guides](README.md) # Testing and Debugging @@ -162,7 +162,7 @@ You can also check the custom parameters the platform exposes: Get-SafeguardCustomPlatformScriptParameter "My Custom Platform" ``` -If a capability is missing, compare the uploaded script against the rules in [Platform Feature Flags](../guides/feature-flags.md). Many "why does SPP not show this option?" problems are really operation-name or reserved-parameter-name problems. +If a capability is missing, compare the uploaded script against the rules in [Platform Feature Flags](../concepts/feature-flags.md). Many "why does SPP not show this option?" problems are really operation-name or reserved-parameter-name problems. ## Tips @@ -176,6 +176,6 @@ If a capability is missing, compare the uploaded script against the rules in [Pl ## Next Steps - [Operations Reference](../reference/operations.md) for the full operation list. -- [Platform Feature Flags](../guides/feature-flags.md) for verifying derived capabilities after upload. +- [Platform Feature Flags](../concepts/feature-flags.md) for verifying derived capabilities after upload. - [Troubleshooting](../guides/troubleshooting.md) for deeper error-resolution guidance. - [Commands Reference](../reference/commands/index.md) for the commands available inside `Do` blocks. diff --git a/docs/guides/troubleshooting.md b/docs/guides/troubleshooting.md index 149af62..0795247 100644 --- a/docs/guides/troubleshooting.md +++ b/docs/guides/troubleshooting.md @@ -1,10 +1,10 @@ -[← Documentation](../README.md) +[← Guides](README.md) # Troubleshooting When a custom platform operation fails, start here. -For the exact PowerShell cmdlets, REST calls, and UI steps for running operations with extended logging, see [Testing and Debugging](../getting-started/testing-and-debugging.md). +For the exact PowerShell cmdlets, REST calls, and UI steps for running operations with extended logging, see [Testing and Debugging](../guides/testing-and-debugging.md). ## Quick Triage @@ -18,7 +18,7 @@ Use this table first. It covers the failure modes people usually search for. | Parameter type mismatch | A reserved parameter is declared with the wrong `Type`, such as `Port` as `String` instead of `Integer` | Check [Reserved Parameters](../reference/reserved-parameters.md) and correct both the parameter name and type. | | Operation timeout | The target system is unreachable or responding too slowly | Check network connectivity, increase the `Timeout` parameter, and verify `Address` and `Port`. | | Task failure with no useful error | Default logging is too sparse to show where the script failed | Re-run the same operation with `?extendedLogging=true` or PowerShell `-ExtendedLogging` so the task log includes command-by-command detail. | -| Feature flags not appearing after upload | The script is missing the required operation and parameter combination for that flag | See [Feature Flags](../guides/feature-flags.md) for the exact operation and reserved parameter each flag requires. | +| Feature flags not appearing after upload | The script is missing the required operation and parameter combination for that flag | See [Feature Flags](../concepts/feature-flags.md) for the exact operation and reserved parameter each flag requires. | | `Function not found` at runtime | A call references a function that is not defined in the script or any imported library | Check the function name spelling and verify the required import library is listed. | | Connection refused or timeout on `Connect` | Wrong port, firewall policy, or target service is not running | Verify the `Port` parameter, confirm network reachability, and make sure the target service is listening. | | Password change succeeds but `CheckPassword` fails | The new password was not actually applied on the target | Review the `ChangePassword` logic and verify the password-change command returned a successful exit status. | @@ -28,7 +28,7 @@ Use this table first. It covers the failure modes people usually search for. ## Debugging Workflow 1. **Enable extended logging.** - Use the same operation that is failing, but run it with extended logging enabled. See [Testing and Debugging](../getting-started/testing-and-debugging.md) for the full workflow. + Use the same operation that is failing, but run it with extended logging enabled. See [Testing and Debugging](../guides/testing-and-debugging.md) for the full workflow. ```powershell Test-SafeguardAsset "Test Target" -ExtendedLogging @@ -131,15 +131,15 @@ If these fail, fix connectivity first. The script cannot recover from a blocked If a script behaves as if values are missing, verify that you used the exact reserved parameter names and types documented in [Reserved Parameters](../reference/reserved-parameters.md). Then confirm the expected values actually exist on the asset, account, or profile. -Good examples to verify are `Address`, `Port`, `Timeout`, `AccountUserName`, `FuncUserName`, and `UseSsl`. If a built-in field or workflow is missing, compare the script against [Feature Flags](../guides/feature-flags.md) and [Operations Reference](../reference/operations.md). +Good examples to verify are `Address`, `Port`, `Timeout`, `AccountUserName`, `FuncUserName`, and `UseSsl`. If a built-in field or workflow is missing, compare the script against [Feature Flags](../concepts/feature-flags.md) and [Operations Reference](../reference/operations.md). ## Getting Help - Browse the [SafeguardCustomPlatform repository](https://github.com/OneIdentity/SafeguardCustomPlatform) for sample scripts and existing documentation. - Ask questions in the [One Identity Community forums](https://www.oneidentity.com/community/). - Keep these references open while debugging: - - [Testing and Debugging](../getting-started/testing-and-debugging.md) + - [Testing and Debugging](../guides/testing-and-debugging.md) - [Reserved Parameters](../reference/reserved-parameters.md) - - [Feature Flags](../guides/feature-flags.md) + - [Feature Flags](../concepts/feature-flags.md) - [Operations Reference](../reference/operations.md) - [Commands Reference](../reference/commands/index.md) diff --git a/docs/quick-start/README.md b/docs/quick-start/README.md new file mode 100644 index 0000000..d80fe7d --- /dev/null +++ b/docs/quick-start/README.md @@ -0,0 +1,13 @@ +[← Documentation](../README.md) + +# Quick Start + +Pick the path that matches your target system and get a working custom platform in under 5 minutes. + +| I need to manage... | Guide | +| --- | --- | +| A Linux/Unix system over SSH | [SSH Password Change](ssh-password-change.md) | +| A REST API over HTTP | [HTTP API Check](http-api-check.md) | +| A web application with a login form | [HTTP Form-Fill](http-form-fill.md) | + +These guides skip the theory and focus on getting a result. For deeper understanding, see [Concepts](../concepts/) or [Tutorials](../tutorials/). diff --git a/docs/quick-start/http-api-check.md b/docs/quick-start/http-api-check.md new file mode 100644 index 0000000..1e6bbad --- /dev/null +++ b/docs/quick-start/http-api-check.md @@ -0,0 +1,70 @@ +[← Quick Start](README.md) + +# Quick Start: HTTP API Check + +Get a working custom platform that validates connectivity to a REST API over HTTP in under 5 minutes. + +## What You'll Get + +A minimal platform script that sends an HTTP request to an API endpoint to verify that the system is reachable and credentials are valid. + +## Steps + +### 1. Copy the Minimal Template + +Download or copy [`TemplateHttpMinimal.json`](../../templates/TemplateHttpMinimal.json) and rename it (e.g., `MyApiCheck.json`). + +### 2. Customize the Endpoint + +Open the file and update the `CheckSystem` operation to hit your API's health or authentication endpoint. For example, if your API uses Basic Auth: + +```json +"CheckSystem": { + "Parameters": [ + { "Address": "" }, + { "FuncUserName": "" }, + { "FuncPassword": "" } + ], + "Do": [ + { "BaseAddress": "https://%Address%" }, + { "NewHttpRequest": { "Name": "req" } }, + { "HttpAuth": { "Type": "Basic", "UserName": "%FuncUserName%", "Password": "%FuncPassword%", "Request": "req" } }, + { "Request": { "Method": "GET", "Url": "/api/v1/health", "Request": "req" } }, + { + "Condition": { + "If": "Response.StatusCode != 200", + "Then": { "Do": [{ "Throw": { "Message": "System check failed: HTTP %Response.StatusCode%" } }] } + } + } + ] +} +``` + +Replace `/api/v1/health` with your target's actual endpoint. + +### 3. Upload to SPP + +```powershell +Import-SafeguardCustomPlatformScript -FilePath .\MyApiCheck.json +``` + +### 4. Create an Asset + +1. In the SPP web UI, go to **Asset Management > Assets > Add** +2. Set the platform to your new custom platform +3. Set the network address to the API hostname +4. Assign a service account with API credentials (username/password or token) + +### 5. Test + +```powershell +Test-SafeguardAssetConnection -AssetToUse "MyApiServer" -ExtendedLogging +``` + +If it reports success, SPP can reach your API. + +## Next Steps + +- Add `CheckPassword` and `ChangePassword` — see [Your First HTTP Script](../tutorials/your-first-http-script.md) +- Learn about HTTP authentication patterns — see [HTTP Platforms Guide](../guides/http-platforms.md) +- Study a production-ready sample — see [WordPress HTTP](../../samples/http/wordpress/) diff --git a/docs/quick-start/http-form-fill.md b/docs/quick-start/http-form-fill.md new file mode 100644 index 0000000..a243ebc --- /dev/null +++ b/docs/quick-start/http-form-fill.md @@ -0,0 +1,136 @@ +[← Quick Start](README.md) + +# Quick Start: HTTP Form-Fill Password Check + +Get a working custom platform that validates credentials against a web login form in under 5 minutes. + +## What You'll Get + +A minimal platform script that navigates to a login page, fills in the username and password fields, submits the form, and checks whether the login succeeded — the same pattern used by the Facebook and Twitter samples. + +## When to Use Form-Fill vs. REST API + +| Approach | Use when... | +| --- | --- | +| **REST API** ([HTTP API Quick Start](http-api-check.md)) | The target exposes a programmatic API with JSON responses | +| **Form-Fill** (this guide) | The target only has a web login page with HTML forms | + +## Steps + +### 1. Start with the Minimal HTTP Template + +Download or copy [`TemplateHttpMinimal.json`](../../templates/TemplateHttpMinimal.json) and rename it (e.g., `MyWebAppFormFill.json`). + +### 2. Replace CheckSystem with a Form-Fill Login + +Replace the `CheckSystem` operation with one that fetches the login page, extracts the form, fills in credentials, and submits: + +```json +"CheckSystem": { + "Do": [ + { "BaseAddress": { "Address": "https://%Address%" } }, + { "Cookies": { "Enabled": true } }, + { "NewHttpRequest": { "ObjectName": "LoginPageReq" } }, + { "Request": { + "Verb": "Get", + "Url": "/login", + "RequestObjectName": "LoginPageReq", + "ResponseObjectName": "LoginPageResp" + } }, + { "ExtractFormData": { + "ResponseObjectName": "LoginPageResp", + "FormObjectName": "LoginForm" + } }, + { + "Condition": { + "If": "LoginForm == null", + "Then": { "Do": [ + { "Throw": { "Message": "Login form not found on page" } } + ] } + } + }, + { "SetFormValue": { + "FormObjectName": "LoginForm", + "InputName": "username", + "Value": "%FuncUserName%" + } }, + { "SetFormValue": { + "FormObjectName": "LoginForm", + "InputName": "password", + "Value": "%FuncPassword%", + "ContainsSecret": true + } }, + { "NewHttpRequest": { "ObjectName": "LoginPostReq" } }, + { "Request": { + "Verb": "Post", + "Url": "%LoginForm.Action%", + "Body": "%LoginForm%", + "ContentType": "application/x-www-form-urlencoded", + "RequestObjectName": "LoginPostReq", + "ResponseObjectName": "LoginPostResp" + } }, + { + "Condition": { + "If": "Response.StatusCode == 200 || Response.StatusCode == 302", + "Then": { "Do": [{ "Return": { "Value": true } }] } + } + }, + { "Throw": { "Message": "Login failed: HTTP %Response.StatusCode%" } } + ] +} +``` + +### 3. Adapt for Your Login Page + +You'll likely need to adjust: + +| What to change | How to find it | +| --- | --- | +| Login URL (`/login`) | Open the page in a browser and note the URL | +| Form field names (`username`, `password`) | Inspect the `` elements in the HTML source | +| Success condition | Some sites redirect (302), others return 200 with a session cookie | + +> **Tip:** If the page has multiple `