Skip to content

Operational runbook

ADUserServices deploys to IIS through the SAIF web-IIS deployment template in two build variants that are materially identical in this repository — same Release configuration, same artifact name, same anonymous-authentication setting, and the same Web.Release.config transform. Concrete site, virtual-directory, and application-pool details are owned by the external deploy template and are not present in this repository. The service holds no process-wide state, so there is nothing to reset on an application-pool recycle, and it emits no logs of any kind.

Deployment

Attribute Value
Host IIS
Site / virtual directory Not determined from source
Application pool Not determined from source (identity sourced from variable group Architecture.ServiceAccounts.IIS; see Authentication and authorization)
Platform target Not declared — BuildPlatformInternal/BuildPlatformExternal are empty values in pipelines\build-vars.yml
Build configurations Release (both Internal and External variants)
Deployment mechanism pipelines\release.yml, extending /Stages/v2/deploy-stages-web-iis-webservices.yml@templates
Artifacts app-internal — both ArtifactNameInternal and ArtifactNameExternal are set to this same name (TD-27, HIGH)

Environments and variants

Environment Variant Address Environment track Notes
Non-production Internal / External (materially identical) <host>/<virtual-directory>/clsADUserServices.asmx — host and virtual directory not determined from source entdev6, entdev7, enttest6, enttest7, np14, np18, np19, np20, np30, np31, npuat, preprod (12 tracks) Each track carries one allowedips address in environmentsettings\settings.yml
Production Internal / External (materially identical) <host>/<virtual-directory>/clsADUserServices.asmx — host and virtual directory not determined from source prod Carries four allowedips addresses

The two build variants (Internal/External) are not distinct deployment environments in this repository — they differ only in artifact-naming intent (both currently resolve to app-internal, see TD-27) and neither transforms a different configuration value.

Health verification

Check Request Expected result
Service metadata reachable GET <address>?wsdl WSDL document returned
Service responds SOAP request invoking HelloWorld Constant string "Hello World" returned; no side effects, no shared state, no directory access

HelloWorld is the lightest available read — it takes no parameters, performs no directory lookup, and cannot fail. No dedicated health endpoint exists in this service; none is invented here.

Fault conditions

Condition What the caller receives Operator action
Operation succeeds Response message (ADServiceResponse, Boolean, ArrayList, or String depending on operation) None
Invalid input message SoapException from framework deserialization, or an operation-specific sentinel (e.g. UserDoesNotExist) Return the fault detail to the caller; no server-side action
Authorization failure (8 gated operations) ADServiceResponse{Response=Failure, Message="Access Denied"} — never a fault Verify the caller's source address against the configured allowedips track value
Allow-list setting missing or environment service unreachable SoapException — unhandled exception propagated out of CheckAccess Verify the aduserservices.allowedips setting is provisioned for the deployment track and the environment service is reachable (TD-12)
Unknown SOAP action SoapException — method not recognized Verify the operation name and the http://tempuri.org/ namespace the caller is using
No service at the address Connection/routing failure at the IIS level — the request never reaches the service, so no SOAP fault is produced Verify the .asmx file deployed and the virtual directory
Unhandled exception in an ungated read operation with no Try/Catch (e.g. DoesUserHaveResource, CheckAccess) SoapException carrying the .NET exception Escalate; no logged exception detail exists to reference (see Logs below)
Directory failure inside GetContext/GetUserPrincipal/GetGroupPrincipal Operation-specific sentinel (UserDoesNotExist, GroupDoesNotExist, False, empty list) — never the underlying failure detail Escalate to Active Directory operations; the service itself provides no diagnostic detail (BR-34)

Logs

Surface Location Content Retention
None found Not applicable Not applicable Not applicable

No log4net initialization or call, no Trace.WriteLine, no EventLog write, and no StreamWriter exists anywhere in source, despite the log4net 2.0.5 package reference being present in packages.config. This is a negative finding recorded explicitly: there is no logging destination to configure, monitor, or rotate for this service, and no mutating operation (account creation, deletion, password reset, group change) leaves any application-level record of who performed it.

Environment configuration

Setting Key Purpose
Allowed IPs aduserservices.allowedips Comma-separated network-origin allow-list evaluated by CheckAccess to gate the eight mutating/password operations

See Configuration for the complete settings catalog, including the embedded domain/container constants that cannot be changed without a rebuild.

Error scenarios

Scenario Symptom Impact Recovery
aduserservices.allowedips setting missing for a track SoapException on every gated operation for that track All 8 mutating operations fail; the 11 read operations are unaffected Provision the setting in environmentsettings\settings.yml for the affected track
Environment service unreachable SoapException propagated out of CheckAccess All 8 mutating operations fail; reads continue serving directory data Verify SAIF environment-service availability
Active Directory unavailable Sentinel (UserDoesNotExist/GroupDoesNotExist/False/empty list) for most operations, or a SoapException from the handful of operations with no Try/Catch (DoesUserHaveResource, CheckAccess) Directory-dependent operations degrade; the failure detail is not surfaced to the caller Verify the configured directory domains (external.saif.com, corp.saif.com) and connectivity
Log directory unavailable Not applicable — no logging surface exists Not applicable Not applicable
Application pool recycled under load No impact — no process-wide cache, counter, or shared state exists in this service (see Architecture) None None required
Stale cached data served Not applicable — no cache exists Not applicable Not applicable
Hard-coded default password in effect for accounts created with an empty inPassword Newly-created accounts share a single known credential Any holder of that credential can authenticate as any account created without an explicit password Always supply an explicit inPassword; remediate per Tech debt (SEC-05, CRITICAL)

Monitoring and alerting

Alert Trigger Recipient Severity
None configured Not applicable Not applicable Not applicable

No telemetry, fault-rate alert, or availability probe is configured anywhere in this repository. This is stated plainly rather than describing a hypothetical alert.

Note: Statements marked with * were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts. Statements marked with ** could not be confirmed; treat as unknown until verified.

Sources

  • pipelines\release.yml
  • pipelines\build-vars.yml
  • environmentsettings\settings.yml
  • src\ADUserServices\clsADUserServices.asmx.vb
  • .saifdocgen\state\runs\20260922-101326-aduserservices\analysis\aduserservices-analysis.md