Skip to content

AD Provider: Generate initial policy-aware password and support controlled output #155

@blindzero

Description

@blindzero

Problem Statement

For AD joiner workflows, IdLE must be able to create and enable accounts in domains with password policies (length/complexity/history). If no password is supplied, user creation/enabling may fail with domain policy errors.

Additionally, onboarding often requires a human-readable initial password. Returning plaintext unconditionally is dangerous because results/events may be persisted, exported, or logged.

Goal:

  1. Generate policy-compliant initial passwords when none is supplied.
  2. Allow controlled, explicit plaintext output only when requested.
  3. Provide a safe “reveal” method when plaintext output is not requested.

Proposed Solution

1) Policy-aware password generation (with fallback)

When creating an AD user and no password input is provided (see Issue #1), and the account is requested to be enabled:

  1. Try to read domain password policy using Get-ADDefaultDomainPasswordPolicy.
  2. Generate a password that satisfies:
    • minimum length (policy or fallback)
    • complexity (upper/lower/digit/special)
  3. If policy read fails for any reason:
    • use provider configuration fallback rules (e.g., length 24, 4 character classes).
  4. Convert generated plaintext to SecureString and set via New-ADUser -AccountPassword (or set password immediately after creation, depending on existing adapter behavior).

2) Enable handling when password is missing

If no password input is provided and generation is disabled/unavailable:

  • If Enabled is not explicitly $true, ensure the account is created disabled (Enabled = $false or do not pass Enabled).
  • If Enabled = $true is explicitly requested and no password can be set/generated: fail fast with a clear error.

3) Reset on first login (must be overridable)

Introduce/standardize With.ResetOnFirstLogin:

  • Default: $true (when a password is set or generated)
  • Must allow explicit override to $false (e.g., hybrid remote login scenarios)

Map this to AD semantics (e.g., “User must change password at next logon”).

4) Controlled password output and reveal path

4.1 Default output (no plaintext)

By default, do not return plaintext in results/events.

Instead, always include a ProtectedString representation for reveal use:

  • GeneratedAccountPasswordProtected = output of ConvertFrom-SecureString (created in the execution context)

This is a secret and must be redacted from logs/exports.

4.2 Explicit plaintext output (opt-in)

If and only if With.AllowPlainTextPasswordOutput = $true:

  • Include GeneratedAccountPasswordPlainText in the result for that step.

Guardrails:

  • Ensure this value is never written to verbose/debug logs or plan exports.
  • Clearly document that results containing plaintext must not be persisted.

4.3 Reveal path (when plaintext output is not enabled)

Document a supported reveal workflow:

$secure = $GeneratedAccountPasswordProtected | ConvertTo-SecureString
$plain  = [pscredential]::new('x',$secure).GetNetworkCredential().Password

5) Documentation (mandatory)

Update AD Provider documentation and examples:

  • “Initial password generation”
  • “How to request plaintext output (AllowPlainTextPasswordOutput)”
  • “How to reveal the password from ProtectedString”
  • Warnings about DPAPI scope (same Windows user + machine execution context)

Alternatives Considered

  • Always return plaintext.

    • Rejected: too risky; secrets would leak into logs/artifacts.
  • Require a secret store capability first.

    • Deferred: secret store/SecretRef is a better long-term solution but should not block AD joiner usability.

Impact

  • Does this affect existing workflows?

    • Additive. Existing workflows remain unchanged.
    • Workflows without a password become reliable in policy-enforced domains.
  • Any backward compatibility concerns?

    • Low. New optional With.* knobs, and improved defaults.

Additional Context

Acceptance Criteria

  • Policy read attempted via Get-ADDefaultDomainPasswordPolicy; fallback used if unavailable.
  • Password generation produces compliant passwords (min length + complexity).
  • With.ResetOnFirstLogin:
    • default $true when password is set/generated
    • allow $false override
  • Results contain ProtectedString by default; plaintext only when With.AllowPlainTextPasswordOutput = $true.
  • Redaction rules prevent secrets from appearing in logs/events/exports unless explicitly requested plaintext output is used (and even then, still no logging/export).

Configuration (fallback)

Provider config supports fallback generation rules, e.g.:

  • PasswordGenerationFallbackMinLength = 24
  • PasswordGenerationRequireUpper = true
  • PasswordGenerationRequireLower = true
  • PasswordGenerationRequireDigit = true
  • PasswordGenerationRequireSpecial = true
  • PasswordGenerationSpecialCharSet = "!@#$%&*+-_=?"

Metadata

Metadata

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions