Skip Ribbon Commands
Skip to main content

Ondrej Sevecek's Blog

:

Engineering and troubleshooting by Directory Master!
Ondrej Sevecek's Blog > Posts > Nahrazení Base64 zakódovaných DN cest uvnitř LDIF souboru
říjen 25
Nahrazení Base64 zakódovaných DN cest uvnitř LDIF souboru

Někdy mě až štve, jak se některé věci tváří, jak samy od sebe fungují a přitom nakonec zjistíte, že stejně nedělají to co potřebujete. Včera jsem řešil případ LDIFDE. To je nástroj na import a export obsahu Active Directory.

On sám umí pomocí parametru -C importovat i exportovat za pomoci tzv. macro expansion. To je to, že nahradí DN (distinguishedName) cestu v objektech z nějaké vaší konkrétní na jinou obecnou (například se používá DC=x, místo vašeho například DC=gopas,DC=virtual). Dá se tak vyrobit obecný LDIF (LDF) soubor, který se dá krásně naimportovat do libovolného jiného prostředí, opět za pomoci opačné náhrady.

A teď pozor, důležitý. Jestli nemáte cement, tak si tam dejte nějakej jinej prášek.

To důležité je fakt, že to normálně funguje i pro jednotlivé atributy, jako je třeba členství ve skupinách. Tyto věci se moc často nepřenáší mezi jednotlivými doménami, takže jsem na problém narazil až teď. U jiných exportů jako je struktura OU, nebo rozšiřování schema apod. takové problémy nejsou.

Co je za problém? Pokud máte v DN cestě regionální znaky, LDIFDE je exportuje ve formě Base64 zakódovaného řetězce. To by tak nevadilo. Má taky údajně fungovat atribut -U, který by způsobil, že LDIFDE exportuje Unicode formát souboru a nebude to překódovávat do Base64. Ten ovšem nefunguje. Tedy alespoň ne mě na Windows 2008 R2, kde jsem to celé řešil. Takže ano, budeme mít uvnitř exportu Base64 nečitelné DN cesty pro některé uživatele.

Jenže ten debil to potom nepřeadresuje tím -C parametrem. Nezbláznili byste se z toho? Takže půlka LDIF souboru je v pořádku opravená na DC=X, zatímco ty Base64 vnitřky zůstanou špatně. Pokus o použití -U selhává. Takže jediné řešení je přeadresovávat si to vlastním PowerShell skriptem. Juchů, další tři hodiny zbytečně utraceného času na něco, co má roky fungovat.

Skript jsem udělal dost účelově, takže to opravuje jen dn a member atributy, ale to už se dá jednoduše upravit. Navíc to prostě natvrdo nahrazuje jen jakoukoliv DC= část, kterou najde ve zdrojovém souboru za tu cílovou, kterou si zadáte do parametru - tzn. vůbec nezadáváte zdrojový DN suffix, který chcete nahradit, zadáte jen výsledný.

function global:Replace-DomainDNinLDIF ([string] $srcLDF, [string] $outLDF, [string] $toDN)
# LDIFDE does not process macro expansions (the -C parameter) inside Base64 encoded distinguished names
# while the -U (Unicode input/output) parameter also does not work correctly for member attributes.
{
  [System.Collections.ArrayList] $list = Get-Content $srcLDF -EA SilentlyContinue -EV er
  [System.Collections.ArrayList] $outList = @()

  $i = 0
  while ($i -lt $list.Count) {

    [string] $oneLine = $list[$i]
    $i ++

    if (($oneLine -like 'member:: *') -or ($oneLine -like 'dn:: *') -or ($oneLine -like 'member: *') -or ($oneLine -like 'dn: *')) {

      $attrType = $oneLine.SubString(0, $oneLine.IndexOf(':'))

      # LDIF/LDF format continues lines if they start with either a single space or a single tab character
      while (($i -lt $list.Count) -and (($list[$i] -like " *") -or ($list[$i] -like "`t*"))) {

        $oneLine += $list[$i].SubString(1)
        $i ++
      }

      if ($oneLine -like '*:: *') {

        $decodedPrincipal = [System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($oneLine.SubString($oneLine.IndexOf(':: ') + 3)))
        $decodedBase64 = $true
      
      } else {

        $decodedPrincipal = $oneLine.SubString($oneLine.IndexOf(': ') + 2)
        $decodedBase64 = $false
      }
    
      if ($decodedPrincipal -like "*,DC=*") {

        $newPrincipal = $decodedPrincipal.SubString(0, $decodedPrincipal.IndexOf('DC=', [StringComparison]::CurrentCultureIgnoreCase)) + $toDN

      } else {

        $newPrincipal = $decodedPrincipal
      }

      if ($decodedBase64) {

        $newPrincipal = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($newPrincipal))
        $shouldAdd = '{0}:: {1}' -f $attrType, $newPrincipal

      } else {

        $shouldAdd = '{0}: {1}' -f $attrType, $newPrincipal
      }

      [void] $outList.Add($shouldAdd)

    } else {

      [void] $outList.Add($oneLine)
    }
  }

  Set-Content -Path $outLDF -Value $outList -Force -Encoding ASCII -EA SilentlyContinue -EV er
}

Comments

korekce

V 31 radku  mas chybu  ma tam byt  -+     :-)
Slavo on 28.10.2013 16:30

Add Comment

Title


Pole Title nemusíte vyplňovat, doplní se to samo na stejnou hodnotu jako je nadpis článku.

Author *


Pole Author nesmí být stejné jako pole Title! Mám to tu jako ochranu proti spamu. Roboti to nevyplní dobře :-)

Body *


Type number two as digit *


Semhle vyplňte číslici dvě. Předchozí antispemové pole nefunguje úplně dokonale, zdá se, že jsou i spamery, které pochopily, že je občas potřeba vyplnit autora :-)

Email


Emailová adresa, pokud na ni chcete ode mě dostat odpověď. Nikdo jiný než já vaši emailovou adresu neuvidí.

Attachments