Quantcast
Channel: LATAM Support Blog
Viewing all 98 articles
Browse latest View live

Bulk delete SharePoint Online List Items

$
0
0

By: Fabiano Mira
We know that using large lists with SharePoint Online can cause some problems due the 5000 item List View Threshold, and it is completely understandable why this limit exists, it´s to minimize database contention SQL Server, the back-end database for SharePoint, often uses row-level locking as a strategy to ensure accurate updates without adversely impacting other users who are accessing other rows.
There are several ways to manage large lists that can be find in this article:

Manage large lists and libraries in SharePoint
https://support.office.com/en-us/article/Manage-large-lists-and-libraries-in-SharePoint-B8588DAE-9387-48C2-9248-C24122F07C59

Just in case you get throttled and the list become instable or you can´t access it anymore to create your views you can clean the items to open the list again.
Usually this applies to historical lists where the data can be erased.
Here it is an CSOM PowerShell Script that you can easily use to delete all list items on a bulk operation.

#Change here with your local path with SP DLLs downloaded from SP Framerwork
Import-Module 'C:\temp\SharePoint Online Client Browser v2.2\Microsoft.SharePoint.Client.dll'
Import-Module 'C:\temp\SharePoint Online Client Browser v2.2\Microsoft.SharePoint.Client.Runtime.dll'
Add-Type -Path 'C:\temp\SharePoint Online Client Browser v2.2\Microsoft.SharePoint.Client.dll'


$site = ''
$admin = ''

$password = Read-Host 'Enter Password' -AsSecureString

$context = New-Object Microsoft.SharePoint.Client.ClientContext($site)
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($admin , $password)
$context.Credentials = $credentials


$list = $context.Web.Lists.GetByTitle('')
$context.Load($list)
$context.ExecuteQuery()
$count = $list.ItemCount

$newline = [environment]::newline
Write-Host -NoNewline "Deleting listitems" -foregroundcolor black -backgroundcolor yellow
$continue = $true
while($continue)
{
    Write-Host -NoNewline "." -foregroundcolor black -backgroundcolor yellow
    $query = [Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery(100, "ID")
    $listItems = $list.GetItems( $query )
    $context.Load($listItems)
    $context.ExecuteQuery()
    if ($listItems.Count -gt 0)
    {
        for ($i = $listItems.Count-1; $i -ge 0; $i--)
        {
            $listItems[$i].DeleteObject()
        }
        $clientContext.ExecuteQuery()
    }
    else
    {
        Write-Host "." -foregroundcolor black -backgroundcolor yellow
        $continue = $false;
    }
}
Write-Host "All listitems deleted from Pages." -foregroundcolor black -backgroundcolor green


O365, Outlook e o Modern Authentication

$
0
0

By: Caio Ribeiro César e César Augusto Hara

Com o aumento da utilização do Outlook 2016, mais organizações estão utilizando a funcionalidade de Modern Authentication. O que é o Modern Authentication?

Para entender o Modern Authentication, vamos primeiro explicar quais são os outros métodos de autenticação, também conhecidos como “legacy”, disponíveis para o O365.

1 - Autenticação Ativa (WSTRUST)

Modelo de autenticação utilizado por versões mais antigas de Outlook (2010 + 2013 sem as atualizações necessárias) ou até protocolos como ActiveSync, POP3, IMAP, SMTP.

Exchange Online é o responsável pela comunicação com o Identity Provider (ADFS). O Outlook em si não faz parte do processo de autenticação, apenas dos resultados do processo. Já discutimos anteriormente neste post, porém vamos revisar de uma maneira mais simples:

• Usuário final faz o request para a utilização de um recurso no Exchange Online (Ol2010);
• Exchange Online faz o pedido de credencial;
• O usuário adiciona a informação para a autenticação (usuário e senha). Estas informações são armazenadas pelo Exchange Online;
• Exchange Online faz o contato com o OrgID (O365). Se a conta é comum/cloud, o usuário é autenticado – caso contrário seguimos com o passo de autenticação ativa e a comunicação é redirecionada para o Identity Provider (ADFS);
• Exchange Online faz contato com o IDP;
• O SAML token é enviado do IDP para o Exchange Online;
• Exchange Online envia o SAML token para o OrgId;
• OrgId retorna o O365 token;
• Exchange Online consome o token e concede acesso para o usuário final.

2 - Autenticação Passiva (WSFED)

Modelo mais simples de autenticação, utilizado no OWA e no Portal. Cada passo de autenticação é exposto para o cliente (browser).

• Usuário efetua o acesso para o OWA sem estar logado (importante lembrar que usuários utilizando um cookie persistente com o keep me signed não terão que readicionar as informações de login);
• OWA efetua o redirecionamento para o OrgID (login.microsoftonline.com);
• O usuário adiciona o User Principal Name. Como estamos falando de um ambiente federado, assim que o usuário selecionar a opção de senha, o browser irá redirecionar para a página de acesso “\adfs\ls” da organização;
• Usuário insere as credenciais;
• O Identity Provider retorna o SAML token para o browser e efetua o redirecionamento para o OrgId;
• Browser efetua um POST do Token para o OrgId, que retorna um cookie de autenticação;
• Com o cookie, o browser acessa o OWA.

Por ser um modelo mais simples, o troubleshoot geralmente é feito apenas com traces de Fiddler.

Explicamos para os engenheiros de suporte que o processo em si pode ser explicado com apenas uma imagem:

Brincadeiras a parte, vamos ao último método de autenticação!

3 - Modern Authentication

O modelo “moderno” de autenticação já é utilizado por muitos de nossos clientes de O365. Também conhecido como “OAuth” ou “ADAL”, utiliza as bibliotecas de autenticação do ADAL (Azure Active Directory Authentication Libraries). Quem lida com o processo de autenticação não é o Exchange Online, e sim o Cliente (Outlook).

Para validar se a sua organização possui o Modern Authentication habilitado, basta executar o procedimento via PowerShell.

Get-OrganizationConfig | fl *oau*

Caso o resultado seja “False”, execute o comando:

Set-OrganizationConfig - OAuth2ClientProfileEnabled $True

Vale ressaltar que as conexões não serão forçadas para Modern Authentication. Se a sua organização ainda possui clientes que utilizam a autenticação Ativa, as comunicações não serão afetadas (iremos apenas aceitar Modern Auth para as versões abaixo).

As versões que suportam este modelo são:

• Outlook 2016 + Outlook 2016 for Mac (15.20);
• Outlook Mobile para IOS/Android;
PowerShell;
• Outlook 2013, desde que:

a) A versão esteja atualizada. O requerimento mínimo é 15.0.4701, porém sempre recomendamos a última release do produto.

b) O Outlook tenha esta configuração manualmente ativada (hardcoded) no registro:

HKCU\SOFTWARE\Microsoft\Office\15.0\Common\Identity\EnableADAL
REG_DWORD 1

HKCU\SOFTWARE\Microsoft\Office\15.0\Common\Identity\Version
REG_DWORD 1

• Usuário acessa o Outlook, que faz o query autodiscover + conexão para o ExO;
• Exchange Online envia um “401”: token necessário para conexão Outlook;
• Outlook envia um “GET” realm pra o O365, que responde com a informação do STS (Identity Provider);
• Outlook entra em contato com o IDP (sts.domain.com);
• Outlook recebe o prompt de autenticação do IDP;
• A credencial é inserida e enviada ao IDP;
• SAML token enviado do IDP para o Outlook;
• POST do token efetuado do Outlook para o O365;
• Refresh token enviado do O365 para o Outlook;
• Acesso garantido Outlook <> Exchange Online.

Dicas de troubleshooting para Modern Authentication

1) Fiddler

O Fiddler trace ajuda a entender as etapas de autenticação. Geralmente, filtramos para o que ocorre durante ou após o “401”:

x-ms-diagnostics: 4000000;reason="Flighting is not enabled for domain contoso.com.";error_category="oauth_not_available"
trusted_issuers="", error="invalid_token"

2) Credential Manager

Como a autenticação é “trabalhada” pelo Outlook, as credenciais podem ser removidas manualmente via “Control Panel\User Accounts\Credential Manager\Windows Credentials”:

* Os tokens estão localizados em:

HKEY_CURRENT_USER\Software\Microsoft\Office\16.0\Common\Identity\Identities

O365 – Exporting specific mailbox folders to pst files

$
0
0

By: Ricardo Viana

Some customers engage support by asking how to export specific folders to pst files.

Ediscovery can help you to achieve exporting the entire mailbox, and will not query Exchange Online Archive.

Support Engineer Ricardo Viana from O365 LATAM has built this script in order to export a single mailbox folder from Office365.

The script will map folder id's of selected mailbox and create a content search of all items in it. You can then download your results on Security and Compliance Center > Content Search.

Download the script here!

THIS CODE AND ANY ASSOCIATED INFORMATION ARE PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK OF USE, INABILITY TO USE, OR RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.



$Loop = $true
While ($Loop)
{
    write-host
    write-host +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    write-host   "Exchange Online Foler Export - Script menu"
    write-host +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    write-host
	write-host -ForegroundColor green '----------------------------------------------------------------------------------------------'
    write-host -ForegroundColor white  -BackgroundColor DarkGreen   'SECTION A:  Create a PST of one or more folders           '
    write-host -ForegroundColor green '----------------------------------------------------------------------------------------------'
    write-host                                              ' 1)  Create a PST from a mailbox '
	write-host                                              ' 2)  Create a PST from an archive '
    write-host
    write-host -ForegroundColor green  '----------------------------------------------------------------------------------------------'
    write-host -ForegroundColor white  -BackgroundColor DarkRed 'End of PowerShell - Script menu '
    write-host -ForegroundColor green  '----------------------------------------------------------------------------------------------'
    write-host -ForegroundColor Yellow            "3)  Exit the PowerShell script menu"
    write-host

    $opt = Read-Host "Select an option [1-3]"
    write-host $opt
    switch ($opt)


{



1
{
$email = Read-Host "Enter an email address"

if (!$credentials)
{
    $credentials = Get-Credential
}

if ($email.IndexOf("@") -ige 0)
{

    $emailAddress = $email


    if (!$ExoSession)
    {
        $ExoSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell-liveid/ -Credential $credentials -Authentication Basic -AllowRedirection
        Import-PSSession $ExoSession -AllowClobber -DisableNameChecking
    }

    $folderQueries = @()
    $folderStatistics = Get-MailboxFolderStatistics $emailAddress
    foreach ($folderStatistic in $folderStatistics)
    {
        $folderId = $folderStatistic.FolderId;
        $folderPath = $folderStatistic.FolderPath;
        $foldersize = $folderStatistic.Foldersize;
        $folderitems = $folderStatistic.ItemsInFolder;

        $encoding= [System.Text.Encoding]::GetEncoding("us-ascii")
        $nibbler= $encoding.GetBytes("0123456789ABCDEF");
        $folderIdBytes = [Convert]::FromBase64String($folderId);
        $indexIdBytes = New-Object byte[] 48;
        $indexIdIdx=0;
        $folderIdBytes | select -skip 23 -First 24 | %{$indexIdBytes[$indexIdIdx++]=$nibbler[$_ -shr 4];$indexIdBytes[$indexIdIdx++]=$nibbler[$_ -band 0xF]}
        $folderQuery = "folderid:$($encoding.GetString($indexIdBytes))";

        $folderStat = New-Object PSObject
        Add-Member -InputObject $folderStat -MemberType NoteProperty -Name FolderPath -Value $folderPath
        Add-Member -InputObject $folderStat -MemberType NoteProperty -Name FolderQuery -Value $folderQuery
        Add-Member -InputObject $folderStat -MemberType NoteProperty -Name Foldersize -Value $Foldersize
        Add-Member -InputObject $folderStat -MemberType NoteProperty -Name ItemsInFolder -Value $folderitems

        $folderQueries += $folderStat
    }
    Write-Host "-----Select Folders-----"
    $folderid2= $folderQueries | Out-GridView -OutputMode Multiple -Title 'Select folder/s:'
}

    Write-host "Folder selected:",$folderid2.folderpath
    $searchName = "Search"
    $searchActionName = "Search_Preview"


    if (!$SccSession)
    {
        $SccSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.compliance.protection.outlook.com/powershell-liveid -Credential $credentials -Authentication Basic -AllowRedirection
        Import-PSSession $SccSession -AllowClobber -DisableNameChecking
    }


    Remove-ComplianceSearch $searchName -Confirm:$false -ErrorAction 'SilentlyContinue'


    $complianceSearch = New-ComplianceSearch -Name $searchName -ContentMatchQuery $folderid2.folderquery -ExchangeLocation "$email"
    Start-ComplianceSearch $searchName
    do{
        Write-host "Waiting for search to complete..."
        Start-Sleep -s 5
        $complianceSearch = Get-ComplianceSearch $searchName
    }while ($complianceSearch.Status -ne 'Completed')


    if ($complianceSearch.Items -gt 0)
    {
        # Create a Complinace Search Action and wait for it to complete. The folders will be listed in the .Results parameter
        $complianceSearchAction = New-ComplianceSearchaction -SearchName $searchName -Preview
        do
        {
            Write-host "Waiting for search action to complete..."
            Start-Sleep -s 5
            $complianceSearchAction = Get-ComplianceSearchAction $searchActionName
        }while ($complianceSearchAction.Status -ne 'Completed')


        $results = Get-ComplianceSearch -Identity $complianceSearchAction.EstimateSearchRunId |select successresults
        $results= $results -replace "@{SuccessResults={", "" -replace "}}",""
        $results -match "size:","(\d+)"
        $match= $matches[1]
        $matchmb= $match/1Mb
        $matchGb= $match/1Gb
        Write-Host "------------------------"
        Write-Host "Results"
        Write-Host "------------------------"
        Write-Host "$results"
        Write-Host "------------------------"
        Write-Host "Found Size"
        Write-Host "$matchmb","Mb"
        Write-Host "$matchGb","Gb"
        Write-Host "________________________"
        Write-Host -foregroundcolor green "Success"
        Write-Host "________________________"
        Write-Host "go to https://protection.office.com/#/contentsearch and export your PST"
        write-host
        write-host
        Read-Host "Press Enter to get back to the menu..."
        write-host
        write-host
        }
        }
2
{
$email = Read-Host "Enter an email address"

if (!$credentials)
{
    $credentials = Get-Credential
}

if ($email.IndexOf("@") -ige 0)
{

    $emailAddress = $email


    if (!$ExoSession)
    {
        $ExoSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell-liveid/ -Credential $credentials -Authentication Basic -AllowRedirection
        Import-PSSession $ExoSession -AllowClobber -DisableNameChecking
    }

    $folderQueries = @()
    $folderStatistics = Get-MailboxFolderStatistics $emailAddress -Archive
    foreach ($folderStatistic in $folderStatistics)
    {
        $folderId = $folderStatistic.FolderId;
        $folderPath = $folderStatistic.FolderPath;

        $encoding= [System.Text.Encoding]::GetEncoding("us-ascii")
        $nibbler= $encoding.GetBytes("0123456789ABCDEF");
        $folderIdBytes = [Convert]::FromBase64String($folderId);
        $indexIdBytes = New-Object byte[] 48;
        $indexIdIdx=0;
        $folderIdBytes | select -skip 23 -First 24 | %{$indexIdBytes[$indexIdIdx++]=$nibbler[$_ -shr 4];$indexIdBytes[$indexIdIdx++]=$nibbler[$_ -band 0xF]}
        $folderQuery = "folderid:$($encoding.GetString($indexIdBytes))";

        $folderStat = New-Object PSObject
        Add-Member -InputObject $folderStat -MemberType NoteProperty -Name FolderPath -Value $folderPath
        Add-Member -InputObject $folderStat -MemberType NoteProperty -Name FolderQuery -Value $folderQuery

        $folderQueries += $folderStat
    }
    Write-Host "-----Select Folders-----"
    $folderid2= $folderQueries | Out-GridView -OutputMode Multiple -Title 'Select folder/s:'
}

    Write-host "Folder selected:",$folderid2.folderpath
    $searchName = "Search"
    $searchActionName = "Search_Preview"


    if (!$SccSession)
    {
        $SccSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.compliance.protection.outlook.com/powershell-liveid -Credential $credentials -Authentication Basic -AllowRedirection
        Import-PSSession $SccSession -AllowClobber -DisableNameChecking
    }


    Remove-ComplianceSearch $searchName -Confirm:$false -ErrorAction 'SilentlyContinue'


    $complianceSearch = New-ComplianceSearch -Name $searchName -ContentMatchQuery $folderid2.folderquery -ExchangeLocation "$email"
    Start-ComplianceSearch $searchName
    do{
        Write-host "Waiting for search to complete..."
        Start-Sleep -s 5
        $complianceSearch = Get-ComplianceSearch $searchName
    }while ($complianceSearch.Status -ne 'Completed')


    if ($complianceSearch.Items -gt 0)
    {
        # Create a Complinace Search Action and wait for it to complete. The folders will be listed in the .Results parameter
        $complianceSearchAction = New-ComplianceSearchaction -SearchName $searchName -Preview
        do
        {
            Write-host "Waiting for search action to complete..."
            Start-Sleep -s 5
            $complianceSearchAction = Get-ComplianceSearchAction $searchActionName
        }while ($complianceSearchAction.Status -ne 'Completed')


        $results = Get-ComplianceSearch -Identity $complianceSearchAction.EstimateSearchRunId |select successresults
        $results= $results -replace "@{SuccessResults={", "" -replace "}}",""
        $results -match "size:","(\d+)"
        $match= $matches[1]
        $matchmb= $match/1Mb
        $matchGb= $match/1Gb
        Write-Host "------------------------"
        Write-Host "Results"
        Write-Host "------------------------"
        Write-Host "$results"
        Write-Host "------------------------"
        Write-Host "Found Size"
        Write-Host "$matchmb","Mb"
        Write-Host "$matchGb","Gb"
        Write-Host "________________________"
        Write-Host -foregroundcolor green "Success"
        Write-Host "________________________"
        Write-Host "go to https://protection.office.com/#/contentsearch and export your PST"
        write-host
        write-host
        Read-Host "Press Enter to get back to the menu..."
        write-host
        write-host


        }
        }

3
{
$Loop = $true
Exit
}
}
}

O365 – Exportando pastas específicas para um arquivo pst

$
0
0

Alguns clientes entram em contato com o suporte perguntando como exportar pastas específicas para arquivos ".pst".

O engenheiro de Suporte O365 Ricardo Viana criou o script abaixo para que você possa efetuar esta tarefa. Nesta nova versão. também efetuamos a exportação de dados do Exchange Online Archive.

O script irá mapear os folder id's das mailboxes em questão e então efetuar o content search para os items de cada pastas. Você poderá então baixar os resultados no Security & Compliance Center (SCC> Content Search).

O script está localizado aqui!

THIS CODE AND ANY ASSOCIATED INFORMATION ARE PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK OF USE, INABILITY TO USE, OR RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.

 


$Loop = $true
While ($Loop)
{
    write-host
    write-host +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    write-host   "Exchange Online Foler Export - Script menu"
    write-host +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    write-host
	write-host -ForegroundColor green '----------------------------------------------------------------------------------------------'
    write-host -ForegroundColor white  -BackgroundColor DarkGreen   'SECTION A:  Create a PST of one or more folders           '
    write-host -ForegroundColor green '----------------------------------------------------------------------------------------------'
    write-host                                              ' 1)  Create a PST from a mailbox '
	write-host                                              ' 2)  Create a PST from an archive '
    write-host
    write-host -ForegroundColor green  '----------------------------------------------------------------------------------------------'
    write-host -ForegroundColor white  -BackgroundColor DarkRed 'End of PowerShell - Script menu '
    write-host -ForegroundColor green  '----------------------------------------------------------------------------------------------'
    write-host -ForegroundColor Yellow            "3)  Exit the PowerShell script menu"
    write-host

    $opt = Read-Host "Select an option [1-3]"
    write-host $opt
    switch ($opt)


{



1
{
$email = Read-Host "Enter an email address"

if (!$credentials)
{
    $credentials = Get-Credential
}

if ($email.IndexOf("@") -ige 0)
{

    $emailAddress = $email


    if (!$ExoSession)
    {
        $ExoSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell-liveid/ -Credential $credentials -Authentication Basic -AllowRedirection
        Import-PSSession $ExoSession -AllowClobber -DisableNameChecking
    }

    $folderQueries = @()
    $folderStatistics = Get-MailboxFolderStatistics $emailAddress
    foreach ($folderStatistic in $folderStatistics)
    {
        $folderId = $folderStatistic.FolderId;
        $folderPath = $folderStatistic.FolderPath;
        $foldersize = $folderStatistic.Foldersize;
        $folderitems = $folderStatistic.ItemsInFolder;

        $encoding= [System.Text.Encoding]::GetEncoding("us-ascii")
        $nibbler= $encoding.GetBytes("0123456789ABCDEF");
        $folderIdBytes = [Convert]::FromBase64String($folderId);
        $indexIdBytes = New-Object byte[] 48;
        $indexIdIdx=0;
        $folderIdBytes | select -skip 23 -First 24 | %{$indexIdBytes[$indexIdIdx++]=$nibbler[$_ -shr 4];$indexIdBytes[$indexIdIdx++]=$nibbler[$_ -band 0xF]}
        $folderQuery = "folderid:$($encoding.GetString($indexIdBytes))";

        $folderStat = New-Object PSObject
        Add-Member -InputObject $folderStat -MemberType NoteProperty -Name FolderPath -Value $folderPath
        Add-Member -InputObject $folderStat -MemberType NoteProperty -Name FolderQuery -Value $folderQuery
        Add-Member -InputObject $folderStat -MemberType NoteProperty -Name Foldersize -Value $Foldersize
        Add-Member -InputObject $folderStat -MemberType NoteProperty -Name ItemsInFolder -Value $folderitems

        $folderQueries += $folderStat
    }
    Write-Host "-----Select Folders-----"
    $folderid2= $folderQueries | Out-GridView -OutputMode Multiple -Title 'Select folder/s:'
}

    Write-host "Folder selected:",$folderid2.folderpath
    $searchName = "Search"
    $searchActionName = "Search_Preview"


    if (!$SccSession)
    {
        $SccSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.compliance.protection.outlook.com/powershell-liveid -Credential $credentials -Authentication Basic -AllowRedirection
        Import-PSSession $SccSession -AllowClobber -DisableNameChecking
    }


    Remove-ComplianceSearch $searchName -Confirm:$false -ErrorAction 'SilentlyContinue'


    $complianceSearch = New-ComplianceSearch -Name $searchName -ContentMatchQuery $folderid2.folderquery -ExchangeLocation "$email"
    Start-ComplianceSearch $searchName
    do{
        Write-host "Waiting for search to complete..."
        Start-Sleep -s 5
        $complianceSearch = Get-ComplianceSearch $searchName
    }while ($complianceSearch.Status -ne 'Completed')


    if ($complianceSearch.Items -gt 0)
    {
        # Create a Complinace Search Action and wait for it to complete. The folders will be listed in the .Results parameter
        $complianceSearchAction = New-ComplianceSearchaction -SearchName $searchName -Preview
        do
        {
            Write-host "Waiting for search action to complete..."
            Start-Sleep -s 5
            $complianceSearchAction = Get-ComplianceSearchAction $searchActionName
        }while ($complianceSearchAction.Status -ne 'Completed')


        $results = Get-ComplianceSearch -Identity $complianceSearchAction.EstimateSearchRunId |select successresults
        $results= $results -replace "@{SuccessResults={", "" -replace "}}",""
        $results -match "size:","(\d+)"
        $match= $matches[1]
        $matchmb= $match/1Mb
        $matchGb= $match/1Gb
        Write-Host "------------------------"
        Write-Host "Results"
        Write-Host "------------------------"
        Write-Host "$results"
        Write-Host "------------------------"
        Write-Host "Found Size"
        Write-Host "$matchmb","Mb"
        Write-Host "$matchGb","Gb"
        Write-Host "________________________"
        Write-Host -foregroundcolor green "Success"
        Write-Host "________________________"
        Write-Host "go to https://protection.office.com/#/contentsearch and export your PST"
        write-host
        write-host
        Read-Host "Press Enter to get back to the menu..."
        write-host
        write-host
        }
        }
2
{
$email = Read-Host "Enter an email address"

if (!$credentials)
{
    $credentials = Get-Credential
}

if ($email.IndexOf("@") -ige 0)
{

    $emailAddress = $email


    if (!$ExoSession)
    {
        $ExoSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell-liveid/ -Credential $credentials -Authentication Basic -AllowRedirection
        Import-PSSession $ExoSession -AllowClobber -DisableNameChecking
    }

    $folderQueries = @()
    $folderStatistics = Get-MailboxFolderStatistics $emailAddress -Archive
    foreach ($folderStatistic in $folderStatistics)
    {
        $folderId = $folderStatistic.FolderId;
        $folderPath = $folderStatistic.FolderPath;

        $encoding= [System.Text.Encoding]::GetEncoding("us-ascii")
        $nibbler= $encoding.GetBytes("0123456789ABCDEF");
        $folderIdBytes = [Convert]::FromBase64String($folderId);
        $indexIdBytes = New-Object byte[] 48;
        $indexIdIdx=0;
        $folderIdBytes | select -skip 23 -First 24 | %{$indexIdBytes[$indexIdIdx++]=$nibbler[$_ -shr 4];$indexIdBytes[$indexIdIdx++]=$nibbler[$_ -band 0xF]}
        $folderQuery = "folderid:$($encoding.GetString($indexIdBytes))";

        $folderStat = New-Object PSObject
        Add-Member -InputObject $folderStat -MemberType NoteProperty -Name FolderPath -Value $folderPath
        Add-Member -InputObject $folderStat -MemberType NoteProperty -Name FolderQuery -Value $folderQuery

        $folderQueries += $folderStat
    }
    Write-Host "-----Select Folders-----"
    $folderid2= $folderQueries | Out-GridView -OutputMode Multiple -Title 'Select folder/s:'
}

    Write-host "Folder selected:",$folderid2.folderpath
    $searchName = "Search"
    $searchActionName = "Search_Preview"


    if (!$SccSession)
    {
        $SccSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.compliance.protection.outlook.com/powershell-liveid -Credential $credentials -Authentication Basic -AllowRedirection
        Import-PSSession $SccSession -AllowClobber -DisableNameChecking
    }


    Remove-ComplianceSearch $searchName -Confirm:$false -ErrorAction 'SilentlyContinue'


    $complianceSearch = New-ComplianceSearch -Name $searchName -ContentMatchQuery $folderid2.folderquery -ExchangeLocation "$email"
    Start-ComplianceSearch $searchName
    do{
        Write-host "Waiting for search to complete..."
        Start-Sleep -s 5
        $complianceSearch = Get-ComplianceSearch $searchName
    }while ($complianceSearch.Status -ne 'Completed')


    if ($complianceSearch.Items -gt 0)
    {
        # Create a Complinace Search Action and wait for it to complete. The folders will be listed in the .Results parameter
        $complianceSearchAction = New-ComplianceSearchaction -SearchName $searchName -Preview
        do
        {
            Write-host "Waiting for search action to complete..."
            Start-Sleep -s 5
            $complianceSearchAction = Get-ComplianceSearchAction $searchActionName
        }while ($complianceSearchAction.Status -ne 'Completed')


        $results = Get-ComplianceSearch -Identity $complianceSearchAction.EstimateSearchRunId |select successresults
        $results= $results -replace "@{SuccessResults={", "" -replace "}}",""
        $results -match "size:","(\d+)"
        $match= $matches[1]
        $matchmb= $match/1Mb
        $matchGb= $match/1Gb
        Write-Host "------------------------"
        Write-Host "Results"
        Write-Host "------------------------"
        Write-Host "$results"
        Write-Host "------------------------"
        Write-Host "Found Size"
        Write-Host "$matchmb","Mb"
        Write-Host "$matchGb","Gb"
        Write-Host "________________________"
        Write-Host -foregroundcolor green "Success"
        Write-Host "________________________"
        Write-Host "go to https://protection.office.com/#/contentsearch and export your PST"
        write-host
        write-host
        Read-Host "Press Enter to get back to the menu..."
        write-host
        write-host


        }
        }

3
{
$Loop = $true
Exit
}
}
}

Eliminación masiva de elementos de una lista en SharePoint Online

$
0
0


Es sabido que el uso de listas largas puede provocar algunos problemas debido al límite de 5000 elementos de una vista, y el hecho de que este límite exista es totalmente comprensible: El objetivo es minimizar el bloqueo de la base de datos en el servidor de SQL, la base de datos propia de SharePoint. Éste utiliza un bloqueo a nivel registro como estrategia para asegurar actualizaciones en él sin impactar negativamente a otros usuarios que estén accediéndolo.

Existen otras maneras de manejar listas largas, las cuales pueden verse en este artículo:

Administrar listas y bibliotecas grandes en SharePoint

En el caso de enfrentarse con una situación en donde una lista o biblioteca hayan excedido este límite y no se tenga la necesidad de mantener toda la información en ella (tal es el caso de listas de tareas, workflows, históricos, etc), y la visualizacion por el navegador no sea posible y no tengamos forma de poder crear vistas, podemos usar una alternativa CSOM para eliminar los items y poder crear o editar las vistas y así evitar nuevamente este problema. Es importante hacer notar que esto aplica principalmente para listas o bibliotecas de históricos donde la información pueda ser borrada sin riesgo para la empresa.

A continuación se muestra el código de PowerShell CSOM y así poder eliminar de forma masiva los elementos de las bibliotecas o listas.

#Adapta la ruta para apuntar a las librerías de SharePoint (dll) que pueden descargarse desde SP Framerwork
Import-Module 'C:\temp\SharePoint Online Client Browser v2.2\Microsoft.SharePoint.Client.dll'
Import-Module 'C:\temp\SharePoint Online Client Browser v2.2\Microsoft.SharePoint.Client.Runtime.dll'
Add-Type -Path 'C:\temp\SharePoint Online Client Browser v2.2\Microsoft.SharePoint.Client.dll'


$site = ''
$admin = ''

$password = Read-Host 'Enter Password' -AsSecureString

$context = New-Object Microsoft.SharePoint.Client.ClientContext($site)
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($admin , $password)
$context.Credentials = $credentials


$list = $context.Web.Lists.GetByTitle('')
$context.Load($list)
$context.ExecuteQuery()
$count = $list.ItemCount

$newline = [environment]::newline
Write-Host -NoNewline "Eliminando elementos de la lista " -foregroundcolor black -backgroundcolor yellow
$continue = $true
while($continue)
{
    Write-Host -NoNewline "." -foregroundcolor black -backgroundcolor yellow
    $query = [Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery(100, "ID")
    $listItems = $list.GetItems( $query )
    $context.Load($listItems)
    $context.ExecuteQuery()
    if ($listItems.Count -gt 0)
    {
        for ($i = $listItems.Count-1; $i -ge 0; $i--)
        {
            $listItems[$i].DeleteObject()
        }
        $clientContext.ExecuteQuery()
    }
    else
    {
        Write-Host "." -foregroundcolor black -backgroundcolor yellow
        $continue = $false;
    }
}
Write-Host "Se han eliminado todos los listitems." -foregroundcolor black -backgroundcolor green

Recuperar información en un sitio personal de OneDrive For Business de un usuario eliminado

$
0
0



Un escenario común de Office 365 y OneDrive For Business que podemos encontrar, es que el administrador necesita recuperar la información de un sitio personal de OneDrive For Business de un usuario que ya no hace parte de la organización o que fue removido / eliminado de Office 365.


En este caso, podemos asignar como administrador del sitio una cuenta activa de Office 365.


Puntos a tener en cuenta:


  • El sitio debe estar activo. Cuando se elimina el usuario del Tenant, el sitio se mantiene activo por defecto 30 días después.

  • Se recomienda asignar como administrador del sitio alguna cuenta de administración de Office 365.

  • El procedimiento se realiza a través de la Consola de Administración de SharePoint Online. Se puede descargar AQUI



Procedimiento:


Nos conectamos al Sitio de Administración de SharePoint Online:


Connect-SPOService –Url “Sitio de administración de SPO”

Capture1

La colección de sitios de administración es la que tiene el sufijo “-admin”


Allí se abrirá una ventana para poner nuestras credenciales de administrador:

Capture2


Ejecutamos el siguiente comando:

Set-SPOUser -Site "UrlDelSitioPersonal" -LoginName "CuentaAdmin" -IsSiteCollectionAdmin $true

Siendo "UrlDelSitioPersonal" la URL del sitio al que deseamos acceder y "CuentaAdmin", la cuenta a la que le delegaremos acceso como administrador.

Capture3


Luego, desde nuestro navegador, accedemos al sitio personal, con las credenciales que delegamos acceso y allí podremos ver los archivos del sitio y poder descargarlos. Recordar que solamente disponemos de hasta 30 días después de la eliminación del usuario para acceder al sitio, por lo que se debe descargar la información antes de los 30 días.




O365 – Procurar por qualquer objeto no tenant associado a um dominio especifico

$
0
0

Com este script, você consegue pesquisar qualquer objeto associado a um domínio especifico através de uma interface amigável.

Aqui fica uma amostra da interface:

 

NOTA: Por padrão, o script tentará se conectar ao Azure enquanto instala/importa os módulos necessários.
Este processo pode ser ignorado comentando (#) a seção "Conexões".

#------------------------------------------------------------------------------

# THIS CODE AND ANY ASSOCIATED INFORMATION ARE PROVIDED “AS IS” WITHOUT
# WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
# LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS
# FOR A PARTICULAR PURPOSE. THE ENTIRE RISK OF USE, INABILITY TO USE, OR
# RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.

#------------------------------------------------------------------------------
#
# PowerShell Source Code
#
# NAME: Domain Association Search.PS1
#
# VERSION: 1.0
#
#------------------------------------------------------------------------------

#----------------------------------------------
#region Import Assemblies
#----------------------------------------------
[void][Reflection.Assembly]::Load('System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')
[void][Reflection.Assembly]::Load('System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')
[void][Reflection.Assembly]::Load('System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a')
[void][Reflection.Assembly]::Load('System.DirectoryServices, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a')
#endregion Import Assemblies

#Define a Param block to use custom parameters in the project
#Param ($CustomParameter)

function Main {

Param ([String]$Commandline)

if((Show-MainForm_psf) -eq 'OK')
{

}

$script:ExitCode = 0 #Set the exit code for the Packager
}

function Show-MainForm_psf
{

#----------------------------------------------
#region Import the Assemblies
#----------------------------------------------
[void][reflection.assembly]::Load('System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')
[void][reflection.assembly]::Load('System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')
[void][reflection.assembly]::Load('System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a')
#endregion Import Assemblies

#----------------------------------------------
#region Generated Form Objects
#----------------------------------------------
[System.Windows.Forms.Application]::EnableVisualStyles()
$form1 = New-Object 'System.Windows.Forms.Form'
$textbox1 = New-Object 'System.Windows.Forms.TextBox'
$listbox3 = New-Object 'System.Windows.Forms.ListBox'
$listbox2 = New-Object 'System.Windows.Forms.ListBox'
$listbox1 = New-Object 'System.Windows.Forms.ListBox'
$labelAZUREApps = New-Object 'System.Windows.Forms.Label'
$labelEXOMailboxesMailUser = New-Object 'System.Windows.Forms.Label'
$labelMSODSUsersGroupsCont = New-Object 'System.Windows.Forms.Label'
$labelDomainAssociationSea = New-Object 'System.Windows.Forms.Label'
$labelDomainName = New-Object 'System.Windows.Forms.Label'
$buttonSearch = New-Object 'System.Windows.Forms.Button'
$InitialFormWindowState = New-Object 'System.Windows.Forms.FormWindowState'
#endregion Generated Form Objects

$form1_Load = {
#Connections
$Module = Get-Module

$ModTMP="| "
foreach ($Mod in $Module){$ModTMP += $Mod.Name +" | "}

if($ModTMP.IndexOf("| MSOnline |") -gt -1) {
Import-Module Msonline
Write-Host "------------- Import MSOnline -------------" -fore cyan
}
else {
Install-Module msonline -Force
Import-Module Msonline
Write-Host "------------- Install MSOnline -------------" -fore cyan
}

if($ModTMP.IndexOf("| AzureAD |") -gt -1) {
Import-Module azuread
Write-Host "------------- Import AzureAD -------------" -fore cyan

}
else {
Install-Module azuread -Force
Import-Module azuread
Write-Host "------------- Install AzureAD -------------" -fore cyan
}

$livecred = Get-Credential
Connect-MsolService -Credential $livecred
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powerShell-liveID?serializationLevel=Full -Credential $LiveCred -Authentication Basic –AllowRedirection
Import-PSSession $Session -AllowClobber
Connect-AzureAD -Credential $livecred
}

$labelDomainAssociationSea_Click={

}

$labelDomainName_Click={

}

$textbox1_TextChanged={

}

$buttonSearch_Click = {
#Clear the Boxes
$listbox1.Items.Clear()
$listbox2.Items.Clear()
$listbox3.Items.Clear()

$form1.Cursor = 'WaitCursor'

#Run MSODS
$listbox1.Items.Add("Finding active Users...")
$msods = Get-Msoluser -all | Where-Object { $_.UserPrincipalName -match $textbox1.text }
$msods2 = Get-MsolUser -all | Where-Object { $_.ProxyAddresses -match $textbox1.text }
$msods3 = Get-MsolUser -all | Where-Object { $_.WindowsLiveId -match $textbox1.text }
if ($msods -ne $null) { $listbox1.Items.AddRange($msods.Displayname) }
if ($msods2 -ne $null) { $listbox1.Items.AddRange($msods2.Displayname) }
if ($msods3 -ne $null) { $listbox1.Items.AddRange($msods3.Displayname) }

$listbox1.Items.Add("Finding deleted Users...")
$msods6 = Get-Msoluser -returndeletedusers -all | Where-Object { $_.UserPrincipalName -match $textbox1.text }
$msods8 = Get-MsolUser -returndeletedusers -all | Where-Object { $_.ProxyAddresses -match $textbox1.text }
$msods9 = Get-MsolUser -returndeletedusers -all | Where-Object { $_.WindowsLiveId -match $textbox1.text }
if ($msods6 -ne $null) { $listbox1.Items.AddRange($msods6.Displayname) }
if ($msods8 -ne $null) { $listbox1.Items.AddRange($msods8.Displayname) }
if ($msods9 -ne $null) { $listbox1.Items.AddRange($msods9.Displayname) }

$listbox1.Items.Add("Finding Groups...")
$msods11 = Get-MsolGroup -all | Where-Object { $_.EmailAddresses -match $textbox1.text }
if ($msods11 -ne $null) { $listbox1.Items.AddRange($msods11.Displayname) }

$listbox1.Items.Add("Finding Contacts...")
$msods4 = Get-MsolContact -all | Where-Object { $_.UserPrincipalName -match $textbox1.text }
if ($msods4 -ne $null) { $listbox1.Items.AddRange($msods4.Displayname) }

#Run EXO
$listbox2.Items.Add("Finding MAilboxes...")
$exo15 = Get-Mailbox -ResultSize unlimited | Where-Object { $_.EmailAddresses -match $textbox1.text }
$exo17 = Get-Mailbox -Softdeleted -ResultSize unlimited | Where-Object { $_.EmailAddresses -match $textbox1.text }
$exo19 = Get-Mailbox -InactiveMailboxOnly -ResultSize unlimited | Where-Object { $_.EmailAddresses -match $textbox1.text }
$exo25 = Get-Sitemailbox -ResultSize unlimited | Where-Object { $_.EmailAddresses -match $textbox1.text }
if ($exo15 -ne $null) { $listbox2.Items.AddRange($exo15.Displayname) }
if ($exo17 -ne $null) { $listbox2.Items.AddRange($exo17.Displayname) }
if ($exo19 -ne $null) { $listbox2.Items.AddRange($exo19.Displayname) }
if ($exo25 -ne $null) { $listbox2.Items.AddRange($exo25.Displayname) }

$listbox2.Items.Add("Finding Mail Users...")
$exo11 = Get-MailUser -ResultSize unlimited | Where-Object { $_.EmailAddresses -match $textbox1.text }
if ($exo11 -ne $null) { $listbox2.Items.AddRange($exo11.Displayname) }

$listbox2.Items.Add("Finding Groups...")
$exo1 = Get-DistributionGroup -ResultSize unlimited | Where-Object { $_.EmailAddresses -match $textbox1.text }
$exo3 = Get-DynamicDistributionGroup -ResultSize unlimited | Where-Object { $_.EmailAddresses -match $textbox1.text }
$exo5 = Get-UnifiedGroup -ResultSize unlimited | Where-Object { $_.EmailAddresses -match $textbox1.text }
if ($exo1 -ne $null) { $listbox2.Items.AddRange($exo1.Displayname) }
if ($exo3 -ne $null) { $listbox2.Items.AddRange($exo3.Displayname) }
if ($exo5 -ne $null) { $listbox2.Items.AddRange($exo5.Displayname) }

$listbox2.Items.Add("Finding Groups...")
$exo9 = Get-MailContact -ResultSize unlimited | Where-Object { $_.EmailAddresses -match $textbox1.text }
if ($exo9 -ne $null) { $listbox2.Items.AddRange($exo9.Displayname) }

$listbox2.Items.Add("Finding Public Folders...")
$exo21 = Get-Mailbox -PublicFolder -ResultSize unlimited | Where-Object { $_.EmailAddresses -match $textbox1.text }
$exo23 = Get-MailPublicFolder -ResultSize unlimited | Where-Object { $_.EmailAddresses -match $textbox1.text }
if ($exo21 -ne $null) { $listbox2.Items.AddRange($exo21.Displayname) }
if ($exo23 -ne $null) { $listbox2.Items.AddRange($exo23.Displayname) }

#Run Azure
$listbox3.Items.Add("Finding Applications...")
$azure = Get-AzureADApplication | Where-Object { $_.IdentifierUris -match $textbox1.text }
if ($azure -ne $null) { $listbox3.Items.AddRange($azure.Displayname) }

$form1.Cursor = 'Default'

}

#region Control Helper Functions
function Update-ListBox
{

param
(
[Parameter(Mandatory = $true)]
[ValidateNotNull()]
[System.Windows.Forms.ListBox]
$ListBox,
[Parameter(Mandatory = $true)]
[ValidateNotNull()]
$Items,
[Parameter(Mandatory = $false)]
[string]
$DisplayMember,
[switch]
$Append
)

if (-not $Append)
{
$listBox.Items.Clear()
}

if ($Items -is [System.Windows.Forms.ListBox+ObjectCollection] -or $Items -is [System.Collections.ICollection])
{
$listBox.Items.AddRange($Items)
}
elseif ($Items -is [System.Collections.IEnumerable])
{
$listBox.BeginUpdate()
foreach ($obj in $Items)
{
$listBox.Items.Add($obj)
}
$listBox.EndUpdate()
}
else
{
$listBox.Items.Add($Items)
}

$listBox.DisplayMember = $DisplayMember
}
#endregion

$form1_FormClosing=[System.Windows.Forms.FormClosingEventHandler]{
#Event Argument: $_ = [System.Windows.Forms.FormClosingEventArgs

}

#----------------------------------------------
#region Generated Events
#----------------------------------------------

$Form_StateCorrection_Load=
{
#Correct the initial state of the form to prevent the .Net maximized form issue
$form1.WindowState = $InitialFormWindowState
}

$Form_StoreValues_Closing=
{
#Store the control values
$script:MainForm_textbox1 = $textbox1.Text
$script:MainForm_listbox3 = $listbox3.SelectedItems
$script:MainForm_listbox2 = $listbox2.SelectedItems
$script:MainForm_listbox1 = $listbox1.SelectedItems
}

$Form_Cleanup_FormClosed=
{
#Remove all event handlers from the controls
try
{
$textbox1.remove_TextChanged($textbox1_TextChanged)
$labelDomainAssociationSea.remove_Click($labelDomainAssociationSea_Click)
$labelDomainName.remove_Click($labelDomainName_Click)
$buttonSearch.remove_Click($buttonSearch_Click)
$form1.remove_FormClosing($form1_FormClosing)
$form1.remove_Load($form1_Load)
$form1.remove_Load($Form_StateCorrection_Load)
$form1.remove_Closing($Form_StoreValues_Closing)
$form1.remove_FormClosed($Form_Cleanup_FormClosed)
}
catch { Out-Null <# Prevent PSScriptAnalyzer warning #> }
}
#endregion Generated Events

#----------------------------------------------
#region Generated Form Code
#----------------------------------------------
$form1.SuspendLayout()
#
# form1
#
$form1.Controls.Add($textbox1)
$form1.Controls.Add($listbox3)
$form1.Controls.Add($listbox2)
$form1.Controls.Add($listbox1)
$form1.Controls.Add($labelAZUREApps)
$form1.Controls.Add($labelEXOMailboxesMailUser)
$form1.Controls.Add($labelMSODSUsersGroupsCont)
$form1.Controls.Add($labelDomainAssociationSea)
$form1.Controls.Add($labelDomainName)
$form1.Controls.Add($buttonSearch)
$form1.AutoScaleDimensions = '11, 20'
$form1.AutoScaleMode = 'Font'
$form1.ClientSize = '1075, 549'
$form1.Font = 'Microsoft Sans Serif, 10.2pt, style=Bold'
$form1.Margin = '6, 5, 6, 5'
$form1.Name = 'form1'
$form1.Text = 'Form'
$form1.add_FormClosing($form1_FormClosing)
$form1.add_Load($form1_Load)
#
# textbox1
#
$textbox1.Font = 'Microsoft Sans Serif, 10.2pt'
$textbox1.Location = '349, 81'
$textbox1.Margin = '6, 5, 6, 5'
$textbox1.Name = 'textbox1'
$textbox1.Size = '358, 27'
$textbox1.TabIndex = 13
$textbox1.add_TextChanged($textbox1_TextChanged)
#
# listbox3
#
$listbox3.Font = 'Microsoft Sans Serif, 10.2pt'
$listbox3.FormattingEnabled = $True
$listbox3.ItemHeight = 20
$listbox3.Location = '720, 254'
$listbox3.Margin = '6, 5, 6, 5'
$listbox3.Name = 'listbox3'
$listbox3.Size = '312, 264'
$listbox3.TabIndex = 12
#
# listbox2
#
$listbox2.Font = 'Microsoft Sans Serif, 10.2pt'
$listbox2.FormattingEnabled = $True
$listbox2.ItemHeight = 20
$listbox2.Location = '381, 254'
$listbox2.Margin = '6, 5, 6, 5'
$listbox2.Name = 'listbox2'
$listbox2.Size = '300, 264'
$listbox2.TabIndex = 11
#
# listbox1
#
$listbox1.Font = 'Microsoft Sans Serif, 10.2pt'
$listbox1.FormattingEnabled = $True
$listbox1.ItemHeight = 20
$listbox1.Location = '33, 254'
$listbox1.Margin = '6, 5, 6, 5'
$listbox1.Name = 'listbox1'
$listbox1.Size = '303, 264'
$listbox1.TabIndex = 10
#
# labelAZUREApps
#
$labelAZUREApps.AutoSize = $True
$labelAZUREApps.Font = 'Microsoft Sans Serif, 7.8pt, style=Bold'
$labelAZUREApps.Location = '730, 206'
$labelAZUREApps.Margin = '6, 0, 6, 0'
$labelAZUREApps.Name = 'labelAZUREApps'
$labelAZUREApps.Size = '58, 32'
$labelAZUREApps.TabIndex = 9
$labelAZUREApps.Text = 'AZURE
(Apps)'
#
# labelEXOMailboxesMailUser
#
$labelEXOMailboxesMailUser.AutoSize = $True
$labelEXOMailboxesMailUser.Font = 'Microsoft Sans Serif, 7.8pt, style=Bold'
$labelEXOMailboxesMailUser.Location = '382, 190'
$labelEXOMailboxesMailUser.Margin = '6, 0, 6, 0'
$labelEXOMailboxesMailUser.Name = 'labelEXOMailboxesMailUser'
$labelEXOMailboxesMailUser.Size = '227, 48'
$labelEXOMailboxesMailUser.TabIndex = 8
$labelEXOMailboxesMailUser.Text = 'EXO
(Mailboxes, MailUsers, Groups,
Public Folders)'
#
# labelMSODSUsersGroupsCont
#
$labelMSODSUsersGroupsCont.AutoSize = $True
$labelMSODSUsersGroupsCont.Font = 'Microsoft Sans Serif, 7.8pt, style=Bold'
$labelMSODSUsersGroupsCont.Location = '33, 206'
$labelMSODSUsersGroupsCont.Margin = '6, 0, 6, 0'
$labelMSODSUsersGroupsCont.Name = 'labelMSODSUsersGroupsCont'
$labelMSODSUsersGroupsCont.Size = '184, 32'
$labelMSODSUsersGroupsCont.TabIndex = 7
$labelMSODSUsersGroupsCont.Text = 'MSODS
(Users, Groups, Contacts)'
#
# labelDomainAssociationSea
#
$labelDomainAssociationSea.AutoSize = $True
$labelDomainAssociationSea.Font = 'Microsoft Sans Serif, 12pt, style=Bold'
$labelDomainAssociationSea.Location = '382, 9'
$labelDomainAssociationSea.Margin = '6, 0, 6, 0'
$labelDomainAssociationSea.Name = 'labelDomainAssociationSea'
$labelDomainAssociationSea.Size = '278, 25'
$labelDomainAssociationSea.TabIndex = 3
$labelDomainAssociationSea.Text = 'Domain Association Search'
$labelDomainAssociationSea.add_Click($labelDomainAssociationSea_Click)
#
# labelDomainName
#
$labelDomainName.AutoSize = $True
$labelDomainName.Location = '209, 84'
$labelDomainName.Margin = '6, 0, 6, 0'
$labelDomainName.Name = 'labelDomainName'
$labelDomainName.Size = '127, 20'
$labelDomainName.TabIndex = 2
$labelDomainName.Text = 'Domain Name'
$labelDomainName.add_Click($labelDomainName_Click)
#
# buttonSearch
#
$buttonSearch.Font = 'Microsoft Sans Serif, 7.8pt, style=Bold'
$buttonSearch.Location = '730, 78'
$buttonSearch.Margin = '6, 5, 6, 5'
$buttonSearch.Name = 'buttonSearch'
$buttonSearch.Size = '126, 35'
$buttonSearch.TabIndex = 1
$buttonSearch.Text = 'Search'
$buttonSearch.UseVisualStyleBackColor = $True
$buttonSearch.add_Click($buttonSearch_Click)
$form1.ResumeLayout()
#endregion Generated Form Code

#----------------------------------------------

#Save the initial state of the form
$InitialFormWindowState = $form1.WindowState
#Init the OnLoad event to correct the initial state of the form
$form1.add_Load($Form_StateCorrection_Load)
#Clean up the control events
$form1.add_FormClosed($Form_Cleanup_FormClosed)
#Store the control values when form is closing
$form1.add_Closing($Form_StoreValues_Closing)
#Show the Form
return $form1.ShowDialog()

}

#Start the application
Main ($CommandLine)

Migración de Algoritmo hash SHA1 a SHA2 de una Entidad Certificadora. Lo que necesita saber!

$
0
0

 

Hola! soy Eric Avila del grupo de Directory Services de LATAM.  Desde hace un tiempo he visto en nuestros clientes varias dudas sobre el proceso de migración de SHA1 a SHA2 en entidades certificadoras.
El proceso comenzó a despertar la necesidad de los clientes, a partir del anuncio de Microsoft sobre la falta de seguridad que presentaba el algoritmo SHA1 y el cual sería obsoleto para Enero, 2016.

https://support.microsoft.com/en-us/help/3123479/microsoft-security-advisory-deprecation-of-sha-1-hashing-algorithm-for

A partir de este anuncio, muchos de nuestros clientes han abierto casos para entender tanto el proceso de migración, como el impacto en su actual infraestructura de PKI. El objetivo de este blog es aclarar las dudas más frecuentes y mostrar el proceso que deben seguir para lograr la migración de su infraestructura de PKI ya sea de uno, dos o tres niveles.

 

Empecemos respondiendo una serie de preguntas que comúnmente nos han hecho llegar al grupo de escalación:

¿En una infraestructura PKI de dos o tres niveles, es necesario migrar la Root CA?

La respuesta inicial es no, pero dependerá del requerimiento o la necesidad de migra al algoritmo a SHA2. Normalmente lo que requieren es que los certificados emitidos a los usuarios, computadora o servicios tengan el algoritmo hash en SHA2, por lo que bajo este escenario la única entidad que es necesario migrar es la denominada “Issuing”, es decir la entidad que emite los certificados.

La Root Certificate no es necesaria migrarla bajo este escenario, ya que no es la responsable de emitir los certificados a los usuarios, computadoras (finales) y servicios.  Pongamos el escenario: Usted ha decido migrar solo la entidad Issuing, lo cual conlleva solo el cambio de una llave de registro (proceso que más adelante se explicara), después de realizar el cambio un error común es revisar el certificado raíz de la entidad issuing y se percatan que dicho certificado aún
cuenta con una Hash algoritmo SHA1 (imagen 1), lo cual es totalmente normal y esperado, ya que dicho certificado fue emitido en su momento por la Root CA, la cual aún se encuentra configurada para emitir certificados SHA1.  La mejor
forma de validad si la issuing fue migrada a SHA2, es emitiendo desde la Issuing un certificado de usuario, computadora o servicio y al validar el algoritmo hash este debe ser SHA2.

 

¿Qué sucederá con los certificados emitidos antes de la migración, seguirán siendo validados?

Totalmente continuaran siendo validados, es importante aclarar que la entidad certificadora solo se le ha instruido a
través del cambio del algoritmo hash, que todos certificado emitido a partir del momento de la migración sean SHA2, pero el certificado raíz y su correspondiente llave privada seguirá siento la misma y con ello la validación
de los certificados emitidos ya sean SHA1 o SHA2, será realizada sin mayor problema.

 

¿Cuándo debo migrar la Root CA a SHA2?

La Root CA deberá ser migrada en el momento que por alguna razón especifica requiera que las entidades certificadoras
Intermedias (para el caso de 3 Niveles) o Issuing (Para el caso de 2 niveles), contengan como Root Certificate un certificado con Algoritmo SHA2. Lo cual, vuelo a reiterar no significa que teniendo un Certificado Raíz SHA2, la CA
emita certificados SHA2, eso lo hará hasta realizar el cambio en la llave de registro del proceso que explicara más adelante. “Proceso de Migración de una entidad certificadora de un algoritmo Hash SHA1 a SHA2.”

 

¿Cómo saber si la CA será migrada de forma exitosa a un algoritmo Hash SHA2?

Gran cantidad de los casos advisory que hemos recibido sobre el proceso de migración, han vuelto a ser abiertos dado
que el proceso no fue exitoso. Esto al emitir un certificado de prueba se percatan que el certificado aún tiene un algoritmo SHA1(Figura 1). La causa de esto es debido al “Proveedor de Criptografía”, lo cuales son capaces de manejar
diferentes algoritmos Hash de diferentes tamaños.  Si el certificado raíz hace uso de “Cryptographic Service Provider (CSP)”, el proceso de migración a SHA2 no será exitoso, por lo tanto es necesario migrar “Key Storage Provider (KSP)”.
Aquí dejo unas referencias quien deseé profundizar en el tema sobre CSP o KSP:

“Understanding Cryptographic Providers”

https://msdn.microsoft.com/en-us/library/windows/desktop/bb931380(v=vs.85).aspx

“Cryptographic Service Provider (CSP)”

https://msdn.microsoft.com/en-us/library/windows/desktop/bb931357(v=vs.85).aspx

“Key Storage Provider (KSP)”

https://msdn.microsoft.com/en-us/library/windows/desktop/bb931355(v=vs.85).aspx

 

Para identificar el proveedor del certificado raíz de la entidad que deseo migrar es necesario ejecutar el siguiente comando:

– Certutil –store my <Your CA common name>

Como ejemplo usando un nombre de CA “Dispositivos”

    Certutil –store my “Dispositivos”

Número
de serie: 610e224900020000000e

Emisor:
CN=ROOTCA, SERIALNUMBER=123456789, O=contoso, C=com

 NotBefore: 28/01/2016 12:36 p.m.

 NotAfter:
28/01/2021 12:46 p.m.

Sujeto:
CN=Dispositivos, DC=contoso, DC=com

Versión
de CA: V1.0

Nombre
de plantilla de certificado (Tipo de certificado): SubCA

Certificado
no raíz

Plantilla:
SubCA

Hash
de cert(sha1): 07 01 32 d7 ac 34 7e c8 40 30 73 b2 63 5c 3d df ae 3f 11 29


Contenedor de claves = Dispositivos


Nombre de contenedor exclusivo:
b7e4a69d7b97e8da1c9436f2dfd73950_937f6140-3894-44f2-b93f-d49fbae60e51

  Proveedor = Microsoft Strong Cryptographic Provider                     

 Se ha pasado la prueba de firma

CertUtil:
-store comando completado correctamente.

 

Debemos de poner atención en el renglón:

  Proveedor = Microsoft Strong Cryptographic Provider       <<<<<<  AquÍ se refleja el uso de un proveedor CSP, y se tiene que convertir a KSP, para lograr una migración exitosa a SHA2.

 

Aquí hare referencia a un Blog ya existente

https://blogs.technet.microsoft.com/askds/2015/10/26/sha1-key-migration-to-sha256-for-a-two-tier-pki-hierarchy/

https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/58/02/metablogapi/clip_image005_2B2A4248.jpg

Si mi certificado tiene como “Provider” cualquiera de los resaltados en amarillo, es necesario migrar a “Key Storage
Provider (KSP)” (Imagen 2)

 

 ¿Cuál es proceso de Migración del “Proveedor de Criptografía”?

El proceso se explica detalladamente en el KB de Technet:

https://technet.microsoft.com/en-us/library/dn771627(v=ws.11).aspx

Cada uno de los pasos deberá seguirse con precaución

En términos generales los pasos a seguir son:

  1.  Usaremos como ejemplo el nombre de la entidad certificadora “Dispositivos”.

Obtener el “Provider” del certificado raíz de la entidad certificadora, “Dispositivos” que se desea migrar, esto con el comando:

Certutil –store my
" Dispositivos m
y "Personal"

================
Certificado 0 ================

Número
de serie: 612e0acd00020000000e

Emisor:
CN=ROOT Contoso, SERIALNUMBER=123456789, O=Contoso, C=com

 NotBefore:
11/01/2012 01:05 p.m.

 NotAfter: 11/01/2017 01:15 p.m.

Sujeto:
CN= Dispositivos, DC=contoso, DC=com

Versión
de CA: V0.0

Nombre
de plantilla de certificado (Tipo de certificado): SubCA

Certificado
no raíz

Plantilla:
SubCA

Hash
de cert(sha1): 8b c0 d7 24 67 7b 64 c5 4f ee fe f7 64 d7 10 45 75 bf 31 db

  Contenedor
de claves = Dispositivos


Nombre de contenedor exclusivo:
b7e4a69d7b97e8da1c9436f2dfd73950_937f6140-3894-44f2-b93f-d49fbae60e51


Proveedor = Microsoft Strong Cryptographic Provider

Se
ha pasado la prueba de firma

 

================
Certificado 2 ================

Número
de serie: 610e224900020000000e

Emisor:
CN=ROOTCA, SERIALNUMBER=123456789, O=contoso, C=com

 NotBefore: 28/01/2016 12:36 p.m.

 NotAfter:
28/01/2021 12:46 p.m.

Sujeto:
CN=Dispositivos, DC=contoso, DC=com

Versión
de CA: V1.0

Nombre
de plantilla de certificado (Tipo de certificado): SubCA

Certificado
no raíz

Plantilla:
SubCA

Hash
de cert(sha1): 07 01 32 d7 ac 34 7e c8 40 30 73 b2 63 5c 3d df ae 3f 11 29


Contenedor de claves = Dispositivos


Nombre de contenedor exclusivo:
b7e4a69d7b97e8da1c9436f2dfd73950_937f6140-3894-44f2-b93f-d49fbae60e51

  Proveedor = Microsoft Strong Cryptographic Provider <<<<<<<<<<<<<<<<< Aqui se refleja el uso de CSP, y se tiene que migrar a KSP

Se ha pasado la prueba de firma

CertUtil:
-store comando completado correctamente.

  

2. Una vez confirmado el uso de CSP y para continuar con el proceso de migración, es imperativo realizar un backup de la entidad certificadora.  Para ello se pueden apoyar el siguiente KB:https://technet.microsoft.com/en-us/library/ee126140(v=ws.10).aspx#BKMK_BackUpReg

 

3.     3. Detener el servicio de la Entidad Certificadora

4.      4. Abrir una consola de PowerShell y borrar el certificado raíz a través de los siguientes comandos:

Cd
cert:\localmachine\my 

Del –deletekey
<"Certificate ID"> 

Esta operación se
deberá repetir para todos los certificados en el contenedor de MY.

5.       5. A través de línea de comandos, migrar el certificado raíz “Dispositivos” a KSP, haciendo uso del certificado *.p12 que fue resultado del
backup del paso No 2 y proporcionado la contraseña que fue asignada:

certutil -csp "Microsoft Software Key Storage Provider" -importpfx "c:\temp\Dispositivos.p12"

Escriba la contraseña PFX: El certificado "Dispositivos" se ha agregado al almacén.

 

El certificado "Dispositivos" se ha agregado al almacén.

CertUtil: -importPFX comando completado correctamente.

 

6.      6. El siguiente paso, es exportar el resultado del archivo migrado pfx al almacen de certificados My “Personal”

certutil -exportpfx my "Dispositivos" Dispositivos.pfx my "Personal"

 

7.      7. Restaurar el archivo *.pfx

     certutil -restorekey  Dispositivos.pfx

 8.       Crear un archivo llamado Csp.reg.  Asegurarse de sustituir por el nombre de la CA.

 Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration\<Your
CA Com
mon Name>\CSP]

"ProviderType"=dword:00000000

"Provider"="Microsoft
Software Key Storage Provider"

"CNGPublicKeyAlgorithm"="RSA"

"CNGHashAlgorithm"="SHA1"

 

9.       9. Crear un archivo llamado: EncryptionCsp.reg Asegurase sustituir por el nombre de la CA.

Windows Registry Editor Version 5.00

 

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration\<Your
CA Common Name>\EncryptionCSP] 

"ProviderType"=dword:00000000

"Provider"="Microsoft
Software Key Storage Provider" 

"CNGPublicKeyAlgorithm"="RSA"

"CNGEncryptionAlgorithm"="3DES"

"MachineKeyset"=dword:00000001

"SymmetricKeySize"=dword:000000a8

 

    10.  Antes de ejecutar los 2 archivos Csp.reg  y EncryptionCsp.reg, asegúrese de que su CA se encuentra usando SHA1 con el siguiente comando:

 

Certutil –v –getreg ca\csp\HashAlgorithm

Poner  atención en la salida:

 

HashAlgorithm REG_DWORD = 8004 (32772)

CALG_SHA1

Algorithm Class: 0x8000(4) ALG_CLASS_HASH

Algorithm Type: 0x0(0) ALG_TYPE_ANY

Algorithm Sub-id: 0x4(4) ALG_SID_SHA1

 

              De igual forma asegurarse de que se hace uso de 3DES con el siguiente comando:

              certutil -v -getreg ca\encryptioncsp\EncryptionAlgorithm

              Poner atención a la salida:

EncryptionAlgorithm REG_DWORD = 6603
(26115)

CALG_3DES

Algorithm Class:
0x6000(3) ALG_CLASS_DATA_ENCRYPT

Algorithm Type:
0x600(3) ALG_TYPE_BLOCK

Algorithm Sub-id:
0x3(3) ALG_SID_3DES

 

11. Una vez migrado el Provider de CSP a KSP el siguiete paso es migrar la entidad certificadora a SHA2.

 

Migración entidad certificadora de SHA1 a SHA2.

El proceso de migración de una entidad certificadora de SHA1 a SHA2 consiste en modificar una llave de registro, ya sea de forma manual o a través de línea de comandos.

El comando para realizar la migración es:

certutil -setreg ca\csp\CNGHashAlgorithm SHA256

Una vez realizado el cambio, se necesita iniciar el servicio de la entidad certificadora:

Net start certsvc.

Estos son los pasos que comprendería hacer migración de una entidad certificadora de un algoritmo hash SHA1 a SHA2.

 

¿Qué pasa si mi Certificate Authority es Windows Server 2008 R2?

Windows Server 2008 o Windows Server 2008 R2 no soporta los comandos para la conversión a KSP dentro de la utilería certutil. Si nuestra CA que deseamos migrar a SHA2 es Windows Server 2008 R2 o anterior, el proceso tendrá una variante y el cual consiste en exportar el certificado raíz de la entidad certificadora a PFX y mover el archivo a un servidor Windows Server 2012 R2 y realizar el proceso descrito en la sección: ¿Cuál es proceso de Migración del “Proveedor de Criptografía”?”.

Una vez realizada la migración y el certificado se tenga listo, es necesario exportar el certificado migrado a un formato PFX y mandarlo nuevamente al servidor Windows Server 2008 R2 e importarlo dentro del contenedor Personal de Computer.

 

Conclusión:

Migrar el Algoritmo Hash de una entidad certificadora a SHA2 no tiene un impacto en la operación y validación de los certificados emitidos previamente.  Por otra parte, el proceso de migración solo comprende el cambio de un valor en la llave de registro. Sin embargo, la entidad certificadora debe cumplir los requerimientos de proveedor de criptografía siendo KSP el único soportado para lograr migrar a SHA2. En caso de no cumplir con el proveedor de criptografía a KSP, los pasos a seguir para la conversión son sencillos, pero deben de realizarse con cuidado para evitar confusión en el procedimiento. Esperando que este blog les sirva como una guía que los ayude a resolver las dudas respecto al tema de migración a SHA2 y proporcionarles las referencias para realizar la migración exitosamente.

 

 

 

 

 


O365 Identity – SourceAnchor e ImmutableID: o que são e para que servem estes atributos?

$
0
0

By: Cesar Hara and Caio Cesar

 

O intuito deste artigo é auxiliar no entendimento geral do conceito por trás dos atributos “SourceAnchor” e “ImmutableID” em contas de usuários, utilizados em ambientes sincronizados via AD Connect.


Definição

SourceAnchor: um atributo imutável durante o tempo de vida de um objeto. Este atributo identifica um objeto sendo o mesmo no Active Directory On-Premises (Source of Authority) e no Azure AD. O sourceAnchor também é conhecido como ImmutableID.

Qual a diferença dos dois atributos? Nenhuma, além da nomenclatura. Os valores são idênticos – “sourceAnchor” geralmente é relacionado quando mencionamos o atributo na base de dados do AADConnect (metaverse), quando “ImmutableID” no Azure AD.

A palavra imutável significa não alterável, sendo assim o atributo deve ser escolhido com muito critério uma vez que o mesmo não pode ser alterado quando definido no Azure AD.


Pontos importantes

  1. “Sourceanchor” e “ImmutableId” se referem ao mesmo atributo;
  2. Este atributo é responsável por vincular um objeto do Active Directory local com o objeto que foi sincronizado/criado na nuvem (Azure AD);
  3. Uma vez definido no Azure AD, o mesmo não pode ser alterado (se torna “Read Only” em contas sincronizadas).


ObjectGUID como sourceAnchor

Por padrão, até a versão de AD Connect 1.1.486.0, o atributo ObjectGUID era escolhido como o sourceAnchor no momento da instalação.

Isto significa que o Azure ADConnect criaria o valor de sourceAnchor (e respectivamente ImmutableId) fazendo uma conversão para base64 do atributo ObjectGUID dos objetos.

O ObjectGUID também é um atributo imutável, por esse motivo foi um bom candidato por muito tempo para ser o valor de ImmutableId das contas do Azure AD.

Podemos comprovar os valores exportando os dados das contas dos objetos. Neste exemplo, iremos utilizar uma conta de testes user01@o365identity.com”:

ObjectGUID: 771a06cd-a5dc-4d9a-a5e2-6b6c6690326b

ImmutableID: zQYad9ylmk2l4mtsZpAyaw==

Conforme informado anteriormente, o valor de Sourceanchor/ImmutableID é uma conversão do valor de ObjectGuid.

Podemos utilizar os cmdlets nativos do módulo do Active Directory para descobrir o ImmutableID que deve ser definido no Azure AD*:

$guid = (get-Aduser sAmAccountname).ObjectGuid
$immutableID = [System.Convert]::ToBase64String($guid.tobytearray())
$immutableID

 

Após a sincronização da conta, confirmamos o valor no Azure AD:

 

Como podemos observar, a conta está corretamente vinculada, ou seja, o valor de ObjectGUID do objeto local convertido para base64 é exatamente o mesmo valor do objeto da nuvem.


Impacto na escolha do sourceAnchor

Vamos supor um cenário onde o atributo “displayName” foi escolhido como sourceAnchor no setup do AD Connect. Após a sincronização inicial, o ImmutableID na nuvem ficaria com o valor “User01”**.

Após um período de tempo, há a necessidade de alterar o displayName para “User”. Se este valor for alterado, na próxima tarefa de sincronização o AD Connect tentará alterar o ImmutableID de “User01” para “User”.

A consequência será um erro de duplicidade de atributos, pelo fato de que para o AD Connect e Azure AD, agora estamos lidando com duas contas diferentes - com diferentes valores de ImmutableID (a primeira “User01” e a segunda “User”).

Ou seja, uma vez definido o ImmutableID no AAD o mesmo se torna “Read-Only” sem a possibilidade de alteração. Isto significa o valor de sourceAnchor, deve ser sempre imutável.


Conclusão

O ImmutableID é muito importante e deve ser compreendido para evitar problemas futuros.

Se não houver um bom planejamento do ambiente sincronizado, problemas complexos surgirão.

 

* Algumas pessoas optam pela utilização do ps1 “GUID2ImmutableID”. O resultado final é o mesmo.

** Se o sourceAnchor selecionado não for do tipo de cadeia de caracteres, o Azure AD Connect usará Base64Encode no valor do atributo para assegurar que nenhum caractere especial será exibido.If you use another federation server than ADFS, make sure your server can also Base64Encode the attribute.



                       

Certificate authentication prompt does not show up after being configured in ADFS.

$
0
0

Hello everyone, we decided to write this article since the number of customers using certificate authentication is increasing, together with the number of cases.

This is one of the most common and problematic scenarios we are facing nowadays - and the reason why we are covering it today.

Scenario:

Hey Microsoft Support, we have configured all settings as the articles below state and this is not working, the user is never prompted for a certificate and the page just keeps loading:
https://blogs.msdn.microsoft.com/samueld/2016/07/19/adfs-certauth-aad-o365/

https://docs.microsoft.com/en-us/windows-server/identity/ad-fs/operations/configure-user-certificate-authentication

 

Troubleshooting:

The quick fix (for this scenario also applies for android devices not authenticating), open the Local Computer certificates MMC, on the “Trusted Root” container check if there is any non-root CA certificate misplaced there.

If there is any, just remove them and restart the server (yes restart the server to update this information).

Important: You must do this on all ADFS and WAP servers.

Another way to find a misplaced certificate is by running the following PowerShell cmdlet:

Get-Childitem cert:\LocalMachine\root -Recurse | Where-Object {$_.Issuer -ne $_.Subject} | Format-List * | Out-File "c:\computer_filtered.txt"

If there is any data on the output file, then you need to take action.

Moving forward with the analysis of the problem, what happens is:

When we are establishing an SSL communication for certificate authentication, the server will send the “Certificate Trust List” to the client so they can start the communication, this list is pretty much the information about all certificates placed in the “Trusted Root” container on the server.

Presenting this list to the client, the client can find a matching root certificate with one that it owns, to perform the cert based authentication.

If a non-root certificate is misplaced on the “Trusted Root” container, the server will not send the complete list, and the client will be unable to choose a personal certificate it has, that is trusted by the ADFS/WAP server.

We can see this behavior by taking a network trace on the client machine, we will use Wireshark here to make it simple:

  1. After capturing the trace, we need to configure Wireshark to show us the frames properly.First, locate a frame where the port 49443 (in ADFS 2012 R2 we use this port for cert authentication) was captured:

    With this setting applied we are telling Wireshark to consider the traffic on port 49443 as an SSL (default 443) traffic.
  2. On any frame, right-click and select “Decode As” and the following window will show, change column “Value” to 49443 and “Current” to SSL and click “Accept”:
  3. The last thing we will have to do is to apply the filter to show only SSL Handshake and the IP of the ADFS server:ssl.handshake && ip.addr == 198.1.1.1

 

Consequently, we will have a much cleaner capture to analyze now, we can seek (in this case) the last “Server Hello” frame, in the “Certificate Request” section, we are only sending one certificate, instead of the whole list:

 

If we look at the same section, for a scenario that works, we are be able to see the whole list as we do have on the server:

 

Conclusion:

To wrap it up, the rule is to have all certificates in their respective containers, Root, Intermediate, Personal and so on... If we misplace them, we will find ourselves in the scenario above.

If this is not the problem, it could be an issue with certificate’s AIA and CDP verification - but we will discuss this further in another article! 🙂

O365 – Importando regras de transporte (ETR) para o Exchange Online

$
0
0

By: Caio Ribeiro César e Ramon Rocha

Em 2011, comentamos sobre o procedimento para High Availability de Edge Transport Servers. Este procedimento consistia basicamente de um export de configurações para XML e posteriormente o import para os outros servidores.

O tempo passou, porém ainda utilizamos XML para diversas tarefas administrativas. Hoje, iremos comentar sobre a exportação e importação de ETR (Exchange Transport Rules).

Exportar a coleção de regras é um processo de duas etapas. Inicialmente, exportamos as de regras para uma variável e, em seguida, gravamos os dados em um arquivo XML.

No exemplo abaixo, exportamos as regras de um Exchange Online:

PS C:\Users\caioc> $file = Export-TransportRuleCollection
PS C:\Users\caioc> Set-Content -Path "C:\Users\caioc\Downloads\RulesExO.xml" -Value $file.Filedata -Encoding Byte

A regra é exportada em um arquivo XML:

ExO

No exemplo abaixo, exportamos as regras de um ambiente Exchange Server 2010 (legacy):

<rule name="Discard messages to - noreply@c4iocesar.com" comments="Noreply Disregard Emails"><version requiredMinVersion="14.0.0.0"><fork><recipient address="noreply@c4iocesar.com"/></fork><condition><and><true/></and></condition><action name="DeleteMessage"/></version></rule>

Como podemos visualizar, o padrão do formato do arquivo diferencia entre versões antigas e as mais atuais (2013+).

O processo para importar a regra segue o mesmo padrão - carregamos os dados para uma variável e depois usamos essa variável para transmitir os dados para o cmdlet:

PS C:\Users\caioc> [Byte[]]$Data = Get-Content -Path "C:\Users\caioc\Downloads\RulesExO.xml" -Encoding Byte -ReadCount 0
PS C:\Users\caioc> Import-TransportRuleCollection -FileData $Data
Confirm
Importing a rule collection will overwrite all existing rules in that collection.  Do you want to continue?
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [?] Help (default is "Y"): A
WARNING: The message rejection text and custom status code that you created are ignored because you have configured the policy to notify the sender with a Policy Tip. - Error details: RejectMessageReasonText and RejectMessageEnhancedStatusCode parameters will be ignored because  NotifySender action is set to NotifyOnly.
WARNING: The rule contains NotifySender action with an option that may reject the message. In case the message gets rejected, other actions won't be applied.

Conforme podemos observar acima, as regras foram importadas de um arquivo xml. É muito importante ressaltar que o import substitui todas as regras de transporte definidas na sua organização. Ou seja, ele irá sobrescrever as configurações de acordo com o arquivo XML.

Recentemente, a equipe de suporte teve um chamado em que ao importar as regras de um ambiente Exchange Server 2010 para o Exchange Online, o erro abaixo ocorria:

PS C:\Users\caioc> [Byte[]]$Data = Get-Content -Path "C:\Users\caioc\Downloads\Rules.xml" -Encoding Byte -ReadCount 0
PS C:\Users\caioc> Import-TransportRuleCollection -FileData $Data
Confirm
Importing a rule collection will overwrite all existing rules in that collection.  Do you want to continue?
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [?] Help (default is "Y"): A
'Import-TransportRuleCollection' cannot be used with a engine-based XML file in Datacenter environment.
    + CategoryInfo          : InvalidData: (File Data:String) [Import-TransportRuleCollection], ParseException
    + FullyQualifiedErrorId : [Server=FR1PR80MB1730,RequestId=8a6017a4-4ce7-44d2-bc92-a235d03861b3,TimeStamp=12/21/2017 4:50:05 PM] [
   FailureCategory=Cmdlet-ParseException] 5BFD5E30,Microsoft.Exchange.MessagingPolicies.Rules.Tasks.ImportTransportRuleCollection
    + PSComputerName        : ps.outlook.com

A mensagem de erro “Cannot be used with a engine-based XML file in Datacenter environment” ocorre pois o formato do conjunto de regras de transporte exportado foi alterado no Exchange Server 2013.

O novo formato não pode ser exportado da versão 2010 para o Exchange Online, ou mesmo importado das atuais para o Exchange Server 2010.

O workaround para este cenário é a importação destas regras para versões 2013 ou 2016 e então um novo export & import para o Exchange Online.

O365 – NDR de Spam Abuse al enviar con el dominio “onmicrosoft.com”

$
0
0

En nuestro día a día en el equipo de Soporte manejamos variados escenarios, cuando múltiples clientes y/o socios de negocios se encuentran con el mismo inconveniente o comportamiento es momento de explicar cómo fue diseñado el producto, cuál es su comportamiento esperado y como los administradores del mismo deben actuar.

En reiteradas ocasiones hemos visto casos relacionados con problemas de entrega a destinatarios externos al utilizar el dominio "@*.onmicrosoft.com". Cuando un usuario envía un correo con una dirección SMTP "usuario@tenant.onmicrosoft.com", estos mensajes son rechazados con el siguiente mensaje.

  1. a) “Remote Server returned ‘550 5.7.501 Access denied, spam abuse detected”;
  2. b) The organization admin will list those emails in the High Risk Delivery Pool (HRDP), classified as outbound spam;
  3. c) Recipient mail server will reject the message, informing that it is classified as SPAM (usually with a high Spam Confidence Level;SCL).

Surge entonces la pregunta de ¿ por qué el mensaje se clasifica como SPAM ?.

El subdominio fue clasificado como SPAM por los mismos motivos que cualquier otro dominio seria (mails masivos, falsos positivos o usuarios que utilizan in dominio con propósitos de SPAM).

Cualquier remitente incluyendo el original [domain].onmicrosoft.com está sujeto a un proceso de analisis realizado por Exchange Online Protection (EOP) llamado "Outbound SPAM", pero no a controles adicionales.

Correo con destino a organizaciones externas deben ser enviados desde dominios validados como ser <@contoso.com> en lugar de <@contoso.onmicrosoft.com>. Si el correo utilizado es @contoso.com significa que el administrador ha provisto evidencia que le permiten demostrar que es el dueño de ese dominio (normalmente a través de la creación de un registro en DNS) y los buzones que se crean con esa dirección SMTP cumplen con la misma condición.

A pesar de que es técnicamente posible utilizar esta dirección (dominio.onmicrosoft.com) para enviar correos, no significa que sea una buena práctica o este recomendado hacerlo. Para corregir el problema, no use la dirección <@contoso.onmicrosoft.com>, utilice la de su dominio validado <@contoso.com>

Si usted recibe el mensaje de NDR a pesar de estar utilizando la dirección validada <@contoso.com>, entonces por favor abra un incidente con Soporte y con gusto lo asistiremos.

 

 

Exchange Online – migração IMAP falhando com “FolderHierarchyContainsMultipleRootsTransientException”

$
0
0

By: Caio Ribeiro César

Uma das opções para migrar mailboxes para o Exchange Online é a migração IMAP. Estes cenários ocorrem quando o servidor de origem é executado em plataformas de terceiros como gmail, dovecot, entre outros produtos. O IMAP pode até ser habilitado em um servidor On-Premises (Exchange), porém, como existem outros métodos de migração para este source, não é um cenário comum.

Para que uma migração IMAP funcione, o servidor source deve ser acessado pelo Exchange Online via portas 143 ou 993 (ssl).

Considerações migrações IMAP:

  • A migração IMAP não é completa. Itens de calendário, contatos, regras e tarefas não são migrados;
  • O protocolo IMAP não efetua o provisionamento de usuários. Isto deve ser feito pelo administrador com um arquivo csv;
  • Em alguns cenários, o servidor de origem não suporta o adicionar permissões em mailboxes (algo parecido com o Full Mailbox Permission). Isto significa que o arquivo .csv pode precisar armazenar as senhas de cada mailbox;
  • Alguns servidores IMAP utilizam modelos diferentes de autenticação. Isto significa que o arquivo csv pode utilizar modelos de template diferentes do padrão.

Migração IMAP em etapas:

  1. Provisionamento de usuários;
  2. Criação do CSV com as credenciais de cada mailbox ou utilizando permissão de administrador em cada conta;
  3. Criação do Endpoint de migração (recomendação utilização da porta 993 com SSL) ;
  4. Sincronismo Inicial;
  5. Sincronismo Incremental a cada 24 horas;
  6. Validamos se as mailboxes e dados foram migrados para o destino (Exchange Online, Get-MailboxFolderStatistics);
  7. Alteração do MX para o Exchange Online;
  8. Confirmamos que o mailflow está funcionando (emails sendo entregues para as mailboxes no Exchange Online), selecionamos a opção de completar a migração no batch;
  9. O “delta” de dados é feito pelo último Sincronismo Incremental e a migração termina.

Considerações de Troubleshooting em IMAP:

Networking – telnet nas portas 143/993 (dentro, fora da rede);

Utilizar o próprio Outlook para conectar na mailbox que está sendo migrada (opção de IMAP);

Problemas com o arquivo csv – validar EmailAddress, UserName, Password e os modelos em cada servidor (com ou sem impersonate do administrador);

PowerShell - Get-Migrationbatch, Get-MigrationUser , Get-MigrationStatus (| fl);

Caso não tenha o Outlook, o teste de conexão e listagem de pastas pode ser efetuado via telnet na 143:

		Telnet IMAP.empresa.com.br 143 
		? LOGIN DOMAIN/UserAlias PASSWORD 
		? LIST "" "*" 
		? Select Sent 
		? LIST "" "*"

*Exemplo de listagem da pasta “Sent”.

Vamos então ao cenário.

Cliente migrando de uma plataforma IMAP (servidor dovecot) para o Exchange Online. No momento da criação do batch, temos o erro abaixo:

“The username or password for this account is incorrect, or IMAP access is disabled. --> The username or password for this account is incorrect, or IMAP access is disabled. --> Imap server reported an error during LoginCommand indicating that authentication failed: 'Authentication failed.'.”

Iniciamos o troubleshooting na questão de autenticação e acesso ao servidor de fora da rede (telnet e o comando abaixo):

 

Test-MigrationServerAvailability -IMAP -RemoteServer  -Port <143 or 993> -Security <None, Ssl, or Tls>


Após esta etapa, acessamos no Outlook uma das mailboxes que estava sendo migrada (com sucesso). Confirmamos e o template de csv estava corretamente configurado para o servidor de origem (dovecot).

Passamos para a segunda etapa de troubleshooting, coletando o Relatório simples da migração. No log, conseguimos listar o erro “FolderHierarchyContainsMultipleRootsTransientException”:

19/02/2018 11:05:51 [FR1PR80MB1554] '' created request.
19/02/2018 11:06:16 [FR1PR80MB1809] The Microsoft Exchange Mailbox Replication service 'FR1PR80MB1809.lamprd80.prod.outlook.com' (15.20.506.23 ServerCaps:7FFFFF, ProxyCaps:01FDC7FD6FFFBF5FFFFFCB07FFFF, MailboxCaps:, legacyCaps:7FFFFF) is examining the request.
19/02/2018 11:06:16 [FR1PR80MB1809] Connected to target mailbox 'c4iocesar.omicrosoft.com\asdasd-a-4e90-a384-3ba03b50f6ea (Primary)', database 'LAMPR80DG114-db001', Mailbox server 'FR1PR80MB1809.lamprd80.prod.outlook.com' Version 15.20 (Build 506.0).
19/02/2018 11:06:16 [FR1PR80MB1809] Sync state for request c4d602d9-58ca-4d75-7765-9db823000cc1 is null.
19/02/2018 11:06:18 [FR1PR80MB1809] Connected to source mailbox 'caioc@c4iocesar.com (IMAP)', database '', Mailbox server 'mail.c4iocesar.com:993 (None)' Version 0.0 (Build 0.0), proxy server 'FR1PR80MB1809.lamprd80.prod.outlook.com' 15.20.506.23 ServerCaps:7FFFFF, ProxyCaps:01FDC7FD6FFFBF5FFFFFCB07FFFF, MailboxCaps:, legacyCaps:01FDC7FD6FFFBF5FFFFFCB07FFFF.
19/02/2018 11:06:18 [FR1PR80MB1809] Request processing started.
19/02/2018 11:06:20 [FR1PR80MB1809] Transient error FolderHierarchyContainsMultipleRootsTransientException has occurred. The system will retry (1/600).
19/02/2018 11:11:26 [FR1PR80MB1809] The Microsoft Exchange Mailbox Replication service 'FR1PR80MB1809.lamprd80.prod.outlook.com' (15.20.506.23 ServerCaps:7FFFFF, ProxyCaps:01FDC7FD6FFFBF5FFFFFCB07FFFF, MailboxCaps:, legacyCaps:7FFFFF) is examining the request.
19/02/2018 11:11:26 [FR1PR80MB1809] Connected to target mailbox 'c4iocesar.omicrosoft.com\asdasd-50f2-4e90-a384-3ba03b50f6ea (Primary)', database 'LAMPR80DG114-db001', Mailbox server 'FR1PR80MB1809.lamprd80.prod.outlook.com' Version 15.20 (Build 506.0).
19/02/2018 11:11:26 [FR1PR80MB1809] Sync state for request c4d602d9-58ca-4d75-7765-9db823000cc1 is null.
19/02/2018 11:11:28 [FR1PR80MB1809] Connected to source mailbox 'caioc@c4iocesar.com (IMAP)', database '', Mailbox server 'mail.c4iocesar.com:993 (None)' Version 0.0 (Build 0.0), proxy server 'FR1PR80MB1809.lamprd80.prod.outlook.com' 15.20.506.23 ServerCaps:7FFFFF, ProxyCaps:01FDC7FD6FFFBF5FFFFFCB07FFFF, MailboxCaps:, legacyCaps:01FDC7FD6FFFBF5FFFFFCB07FFFF.
19/02/2018 11:11:28 [FR1PR80MB1809] Request processing started.

Temos uma suposição de que o servidor IMAP de origem possui uma estrutura muito extensa de pastas “Root”. Esta exceção não trouxe maiores informações de quais possíveis pastas “Roots” adicionais o Exchange Online não estava conseguindo criar na hierarquia desta caixa de correio - seguimos então para a terceira etapa de coleta de dados:

Get-MigrationUserStatistics -Identity caioc@c4iocesar.com -IncludeReport | Export-Clixml log.xml

Tendo o arquivo .xml em mãos, prosseguimos com a filtragem de conteúdo para a análise e exportamos apenas os erros para um arquivo de log:

PS C:\Users\caioc> $stats = Import-CliXml  C:\Users\caioc\Downloads\log.xml
PS C:\Users\caioc> $stats.report.Failures > logReportFalha.txt

Tendo então o erro abaixo:

Timestamp         : 2/19/2018 11:06:20 AM
FailureType       : FolderHierarchyContainsMultipleRootsTransientException
FailureHash       : 60ea
FailureCode       : -2146233088
MapiLowLevelError : 0
FailureSide       : 
FailureSideInt    : 0
ExceptionTypes    : {Exchange, Transient, MRS, MRSTransient}
ExceptionTypesInt : {1, 2, 10, 11}
WorkItem          : AnalyzeFolderHierarchy
Message           : Mailbox folder hierarchy contains multiple roots: [Folder2: EntryID: [len=54, data=56                3D313B503D494D41503B46503D42333045423941303344303544413533313537324139364131383232423735343134373043374244], ParentID: [len=54,data=563D313B503D494D41503B46503D34344331393641431423545363630354243313036414645304339303936303436433044424635], Type: Generic, WKFType:None], [Painitec: EntryID: [len=54, data=563D313B503D494D41503B46503D3344353535433130453], ParentID: [len=54, data=563D313B503D494D41503B46503D34344331393641433241423545363630354243313036414645304339303936303436433044424635], Type: Generic, WKFType: None].

Confirmamos com um segundo filtro no arquivo .xml:

PS C:\Users\caioc> $stats.report.failures[-1]

Timestamp         : 2/19/2018 4:13:40 PM
FailureType       : TooManyTransientFailureRetriesPermanentException
FailureHash       : 60ea
FailureCode       : -2146233088
MapiLowLevelError : 0
FailureSide       :
FailureSideInt    : 0
ExceptionTypes    : {Exchange, MRS, MRSPermanent}
ExceptionTypesInt : {1, 10, 12}
WorkItem          : AnalyzeFolderHierarchy
Message           : The job encountered too many transient failures (61) and is quitting. The most common
failure is FolderHierarchyContainsMultipleRootsTransientException with the hit count 60.
--> Mailbox folder hierarchy contains multiple roots: [Folder2: EntryID: [len=54, dat
a=3043374244], ParentID: [len=54, data=563D313B503D494D41503B46503D343443313936414
33241423545363630354243313036414645304339303936303436433044424635], Type: Generic,
WKFType: None], [Painitec: EntryID: [len=54, data=563D313B503D494D41503B46503D334435353543
31304533453446333144354638313330333633393339384344333041434433363535], ParentID:[len=54,
data=563D313B503D494D41503B46503D3434433139364143324142354536363035424331303641464339303936303436433044424635], Type: Generic, WKFType: None].
MessageData       :
DataContext       :
DataContextData   :
StackTrace        :
InnerException    : FolderHierarchyContainsMultipleRootsTransientException: Mailbox folder hierarchy contains multiple roots: [Folder2: EntryID: [len=54, 
Generic, WKFType: None].
UnknownElements   :
UnknownAttributes :
XmlSchemaType     :

Após esta última análise, provavelmente é algo que precisa ser corrigido no lado do servidor IMAP de origem, pois ter diversas “root folders” (pastas raízes) não é algo permitido no Exchange. Conseguimos entender do arquivo de log que a pasta específica “Folder2” estava sendo considerada pelo Exchange Online como uma pasta de sistema.

Removemos a pasta nas configurações de conta IMAP e a migração foi efetuada com sucesso.

Gostaria de agradecer o apoio do nosso amigo Pedro Henrique Lemos de Miranda, da empresa Verdanatech Soluções em T.I para a ajuda no troubleshooting deste cenario!

Actualizando membresia para AddressList

$
0
0

Si deseamos crear listas de direcciones "AddressList" que contengan usuarios especificos podemos hacerlo utilizando el cmdlet New-AddressList y aplicando el filtro para que la misma contenga los usuarios deseados como se muestra a continuacion:

En este ejemplo vamos a crear una lista de usuarios cuyo departamento sea IT:

1-) Validamos a traves de una consulta que los usuarios listados son los que deseamos aparezcan en la lista de direcciones.

2- Luego vamos a crear la lista de direcciones con dichos usuarios.

3- Actualizamos los usuarios utilizando el siguiente comando.
Update-Recipient janedoe

4- Validamos que ahora el Usuario se muestra como perteneciente a esa lista de direcciones "ITDepartment"

5- Si deseamos hacer el proceso de forma masiva podemos realizarlo a traves de la importacion de los usuarios utilizando in CSV.

a-) Exportamos la lista de usuarios utilizando el comando:

Get-Recipient -Filter {(Department -eq 'IT')} |Select Guid |Export-Csv c:\temp\list.csv -NoTypeInformation

b-) importamos el CSV a PowerShell.

$users = import-csv c:\temp\list.csv

c-) Actualizamos los usuarios de la siguiente manera:

5- Finalmente confirmamos que vemos al Usuario en la lista a traves de OWA

 

Agradecimiento especial a Agustin Gallegos quien amablemente facilitó la parte de scripting.

Using the mS-DS-ConsistencyGuid attribute to fix sync issues to Office 365/AAD.

$
0
0

By Cesar Hara, Victor Santana and Caio Cesar

Greetings everyone!

Today we are going to cover a very interesting way to troubleshoot user synchronization issues to Office 365 (Azure Active Directory). The method consists of using the attribute: “mS-DS-ConsistencyGuid”.

We recommend going through this article for a better understanding of what is being discussed in this post.

As many of you know, historically, AD Connect used to choose “ObjectGUID” as the sourceAnchor attribute to sync objects to the cloud. Starting on version 1.1.524.0, we can use mS-DS-ConsistencyGuid instead.

What is the big deal with it? Unlike ObjectGuid, this attribute is writable. This means we can manipulate synced objects easier.

Recently, customers started to raise tickets related to this matter. We were able to fix these incidents without causing service disruption to the end users, scenarios may vary from: “I have a synced multi-forest environment and the user was migrated between them”, “A user was deleted from Active Directory by mistake while AD Connect was not working and we reinstalled it” and “I lost the only DC in my forest, so I had to rebuild my AD forest completely”.
(PLEASE, ALWAYS PROMOTE AT LEAST TWO DOMAIN CONTROLLERS!!)

Pre-requisites: You will need to have access to AAD PowerShell connected to your tenant (with global admin permissions), AD Connect Server and access to the Domain Controller.

Scenario 1:

“A user was deleted from AD by mistake while AD Connect was not working. We created a new account since we cannot recover the old one and then we reinstalled AD Connect, but the changes performed on local Active Directory object are not syncing to the cloud account.”
NOTE: There are other possible scenarios, this is only one of the scenarios we have seen.

Understanding the problem:

• As AD Connect was down, the removal of the user was not “picked” by AD Connect.
• As a result, this deletion did not occur in AAD. This means the account is orphan in AAD.
• The new account has a new on-prem ImmutableID (originated from ObjectGUID). This attribute cannot be changed in the cloud for synced accounts.
To reproduce this behavior, we have uninstalled AD Connect, deleted the user account from Active Directory and re-installed AD Connect.

To confirm that the problem is with the different ImmutableID, you can follow these steps:
• Get the ImmutableID of the affected account in the cloud:

Get-MsolUser -UserPrincipalName john@cesarhara.com | select ImmutableID
ImmutableID: kKfL2wwI+0W+rN0kfeaboA==

• Perform a metaverse search for the new user created in AD (or convert the ObjectGUID taken from AD into a base64 format with the GUID2ImmutableID tool) to confirm the new ImmutableID:

• If you have attribute resiliency, AD Connect will not show any errors. You can go to the Portal or PowerShell to identify the error:

In summary, any changes we make to this on-prem object will not be reflected to the cloud.

Steps to resolve:

1- Confirm that the attribute being used in AD Connect as the “SourceAnchor” is the “mS-DS-ConsistencyGuid”, just run the AD Connect Wizard and choose “View Current Configuration”:

2- Make sure that the “UPN” and “ProxyAddresses” attributes are the same in O365 and AD accounts - you can download the users report in the Admin Portal or use PowerShell to extract this information. These attributes are essential, if you are aware of any other one missing, proceed to add it to the account in your local AD accordingly.

3- Grab the ImmutableID value of the cloud/original account. Here is the cmdlet again:

Get-MsolUser -UserPrincipalName john@cesarhara.com | select ImmutableID
ImmutableID: kKfL2wwI+0W+rN0kfeaboA==

4- We have to convert the value of the “ImmutableID” to a HEX format so we can add it into the on-prem account:

[system.convert]::FromBase64String("kKfL2wwI+0W+rN0kfeaboA==") | %{$a += [System.String]::Format("{0:X}", $_) + " "};$result = $null;$result = $a.trimend();$result

The output is:
90 A7 CB DB C 8 FB 45 BE AC DD 24 7D E6 9B A0

5- Now let’s get back to our AD Connect server and stop the scheduled task (it’s a good practice to do so, avoiding a sync task to run while we are troubleshooting this):

Set-ADSyncScheduler -SyncCycleEnabled $false

6- Move the account to a non-synced OU and run a delta sync (this is required to the match occurs later).

Start-ADSyncSyncCycle -PolicyType Delta

7- In the new account created in ADDS, edit its attributes. Do this by locating the mS-DS-ConsistencyGuid and adding the HEX value from step 2 (if there is a value, AD Connect added the current ObjectGUID value as the default behavior, proceed to add the new one):

8- Move the account back to a synced OU and run a delta sync again, if everything ran as expected the sync would occur successfully.

9- Add or change an attribute in AD to make sure the sync worked as expected. Finally, check in the Portal and the error will be gone:

 

Conclusion:

With this new feature, it is possible to resolve problems that used to be hard to deal with it when using “ObjectGUID”. Regardless the scenario, we must always use the original ImmutableID (already set in the cloud), convert it to an HEX value and add into the “mS-DS-ConsistencyGuid” so the match occurs.
If you are going to migrate accounts between forests make sure to populate in the target forest object “mS-DS-ConsistencyGuid”, the value of the source object “ObjectGUID”.


NTLM vs KERBEROS

$
0
0

NTLM vs KERBEROS

(WWW)

 

 

Podemos interpretar este post como os três W's, um para cada capítulo.

Vamos passar pelos conceitos basicos do NTLM e do Kerberos. Quais são as principais diferenças entre eles, como funciona o fluxo e como podemos identificar qual protocolo está sendo usado.

Então, sem mais demora. Aqui vai a história ...

 

 

Capítulo 1

The What:

 

O que é o NTLM?
O NTLM é um protocolo de autenticação. Era o protocolo padrão usado nas versões antigas do Windows, mas ainda é usado hoje. Se por algum motivo o Kerberos falhar, o NTLM será usado.
O NTLM possui um mecanismo de desafio / resposta.
Aqui está como funciona o fluxo NTLM:

1 - Um usuário acessa um computador cliente e fornece um nome de domínio, um nome de usuário e uma senha.
O cliente calcula um hash criptográfico da senha e descarta a senha real. O cliente envia o nome do usuário para o servidor (em texto sem formatação).

2 - O servidor gera um número aleatório de 16 bytes, chamado desafio, e o envia de volta ao cliente.

3 - O cliente criptografa esse desafio com o hash da senha do usuário e retorna o resultado para o servidor. Isso é chamado de resposta.

4 - O servidor envia os três itens a seguir para o controlador de domínio:
- Nome do usuário
- Desafio enviado ao cliente
- Resposta recebida do cliente

5 - O controlador de domínio usa o nome de usuário para recuperar o hash da senha do usuário. Ele compara o desafio criptografado com a resposta do cliente (na etapa 4). Se eles forem idênticos, a autenticação será bem-sucedida e o controlador de domínio notificará o servidor.

6 - O servidor envia a resposta apropriada de volta ao cliente.

 

O que é o Kerberos?
O Kerberos é um protocolo de autenticação. É o protocolo de autenticação padrão nas versões do Windows acima do W2k, substituindo o protocolo de autenticação NTLM.
Aqui está como o fluxo do Kerberos funciona:

1 - Um usuário loga na máquina cliente. O cliente faz um pedido de texto simples (TGT). A mensagem contém: (ID do usuário; ID do serviço solicitado (TGT); O endereço de rede do cliente (IP); tempo de vida da validação)

2 - O servidor de autenticação verificará se o usuário existe no banco de dados do KDC. Se o usuário for encontrado, ele gerará aleatoriamente uma chave (chave de sessão) para uso entre o usuário e o Servidor de Concessão de Ticket (TGS). O servidor de autenticação enviará duas mensagens de volta para o cliente: - Um é criptografado com a chave secreta do TGS. - Um é criptografado com a chave secreta do cliente.

NOTA: A chave de sessão TGS é a chave compartilhada entre o cliente e o TGS. A chave secreta do cliente é o hash das credenciais do usuário (nome de usuário + senha).

3 - O cliente descriptografa a chave e pode fazer logon, fazendo o cache localmente. Ele também armazena o TGT criptografado em seu cache. Ao acessar um recurso de rede, o cliente envia uma solicitação ao TGS com o nome do recurso que ele deseja acessar, o ID do usuário / registro de data e hora e o TGT em cache.

4 - O TGS descriptografa as informações do usuário e fornece um tíquete de serviço e uma chave de sessão de serviço para acessar o serviço e enviá-lo de volta ao Cliente depois de criptografado.

5 - O cliente envia o pedido para o servidor (criptografado com o tíquete de serviço e a chave de sessão)

6 - O servidor descriptografa o pedido e, se for genuíno, fornece acesso ao serviço.

 

 

Capítulo 2

The When:

 

Como podemos identificar quando estamos usando o NTLM ou o Kerberos?
Podemos confirmar a autenticação sendo usada pela simples coleta de um Fiddler. No Fiddler, podemos ver os pedidos sendo feitos nos Inspetores / Cabeçalhos:

Kerberos:

NTLM:

 

Se a solicitação iniciar com o Kerberos e falhar, o NTLM será usado. Podemos ver a resposta nos cabeçalhos também:

 

Quais são as dependências do Kerberos?
Tanto o cliente quanto o servidor precisam estar executando o W2k ou versões posteriores e estar no mesmo domínio ou confiável.
Um SPN precisa existir no AD para a conta de domínio em uso para executar o serviço no qual o cliente está sendo autenticado.

 

 

Capítulo 3

The Why:

Os hashes NTLMv1 podem ser quebrados em segundos com a computação de hoje, pois eles têm sempre o mesmo tamanho e não são salted.
O NTLMv2 é um pouco melhor, desde o tamanho variável e o hash salted, mas não muito melhor. Mesmo que o hash seja salted antes de ser enviado, ele é salvo unsalted na memória de uma máquina.
E claro, quando falamos sobre o NTLM, falamos sobre um mecanismo de desafio / resposta, que expõe sua senha ao cracking off-line ao responder ao desafio.

O Kerberos fornece várias vantagens sobre o NTLM:
- Mais seguro: Nenhuma senha armazenada localmente ou enviada pela rede.
- Melhor desempenho: desempenho aprimorado em relação à autenticação NTLM.
- Suporte à delegação: os servidores podem representar clientes e usar o contexto de segurança do cliente para acessar um recurso.
- Gerenciamento de confiança mais simples: evita a necessidade de ter relações de confiança p2p em ambientes de vários domínios.
- Suporta MFA (Multi Factor Authentication)

 

O fim

O365 Exchange Online e o novo Message Trace

$
0
0

By: Caio Ribeiro César

 Como muitos já perceberam, existe uma nova opção abaixo de “Threat management” no Security & Compliance Center:

Trata-se do novo Message Trace, disponibilizado para os administradores desde o dia 25 de Abril (full availability para todos os tenants pode demorar de 4 até 6 semanas).

A decisão foi tomada a partir de diversos pedidos do time de suporte, juntamente com o field.

Message trace antigo e suas limitações

Utilizado desde a época de migração de BPOS para O365, sem muitos updates, o Message Trace antigo possui algumas limitações.

  1. O search comum é efetuado apenas para o range de até 7 dias;
  2. O search detalhado de +7 dias demora para ser entregue;
  3. Filtro de emails e queries customizáveis são apenas disponibilizados via PowerShell.

Message trace antigo e sua interface disponibilizada no Exchange Admin Center (EAC).

Message trace novo e suas novas features

Com a ferramenta disponibilizada no SCC, podemos:

  • Procurar e-mails baseando-se no time zone;
  • Filtrar e-mails via Subject filtering;
  • Filtrar apenas e-mails marcados como Junk

  • Real time trace, facilitando o troubleshooting para procurar mensagens real time;
  • Common queries (templates) criados pelo time de Produto;
  • Disponibilização da criação de custom queries para os administradores;
  • Repositório de relatórios para download;
  • Search detalhado mais rápido e efetivo;
  • Output de resultados na interface gráfica estendido de 1.000 para 10.000;
  • On-screen search aumentado de 7 para 10 dias;
  • Extended search customizado de últimas 6 horas até 90 dias.

Gostaram da atualização? Deixe seu comentário!

Obrigado ao Arindam Thokder, SEE Beta Engineer de Exchange que nos apresentou esta feature antes de estar released para o público!

Kudos to Arindam Thokder, SEE Beta Engineer from the Exchange team, that presented this feature to us before it was publically available, making us aware and ready to build this post!

Obs. O Message trace antigo também continuará funcionando após a release do novo Message Trace.

O final do suporte para a release de Exchange 2010 está chegando! Atualize-se!

Exchange 2010 end of Support is coming! Patch it up!!

O365 – Migração Híbrida para Exchange Online falhando com MigrationPermanentException – Recoverable Items quota exceeds 100GB

$
0
0

By: Caio Ribeiro César

Hoje iremos discutir um cenário comum no suporte em um método short and simple (kiss).

Alguns clientes que possuem um ambiente híbrido, ligam informando receber o erro abaixo em mailbox moves:

Hybrid migration of mailboxes with more than 100GB of storage from an Exchange 2010 to Office 365.

Error: MigrationPermanentException: The size of Recoverable Items 129.7 GB (139,275,977,263 bytes) exceeds the Recoverable Items quota of the target mailbox database 100 GB (107,374,182,400 bytes). -> The size of Recoverable Items 129.7 GB (139,275,977,263 bytes) exceeds the Recoverable Items quota of the target mailbox database 100 GB (107,374,182,400 bytes).

Mesmo a causa sendo bem simples, iremos discutir aqui o que ocorre neste cenário. Primeiro, iremos coletar um Get-Mailbox da conta On-Premises:

ServerName : caiocex01
Database : DB01
ProhibitSendQuota : unlimited
ProhibitSendReceiveQuota : unlimited
RecoverableItemsQuota : unlimited
RecoverableItemsWarningQuota : unlimited

Ter o “RecoverableItemsQuota” configurado como unlimited é um problema por diversos motivos, iremos listar alguns:

  1. Mailbox Audit logging. O mailbox audit utiliza quota de RecoverableItems para armazenamento de logs. Caso esteja configurado como unlimited, os logs podem alcançar um tamanho muito grande (por exemplo, com a opção de mailbox audit owner hablilitado).

 

  1. Gerência de dados. O administrador deve ter controle dos dados, caso contrário temos uma “bola de neve”. Em questão de Scalability, não é recomendado ter ambientes sem quota.

 

  1. Segurança: não é um cenário comum, porém pode acontecer (lembre-se das leis imutáveis de segurança*). Um atacante pode conseguir acesso para uma única conta do seu ambiente e transformar este ataque simples em um Denial of Service (DoS). O atacante não precisa ser um gênio para tal feito – basta consumir os dados de RecoverableItems até a database da mailbox chegar em um limite máximo de disco.

Para o administrador que quer testar seus limites, recomendamos o Jetstress.

Vamos então para as ações necessárias para que este “problema” de mailbox move seja resolvido.

  1. O Recoverable Items quota está configurado como unlimited no ambiente On-Premises. Este é o real motivo do mailbox move falhar. No Exchange Online temos esta configuração para 100GB e a mailbox On-Premises está utilizando ~130GB.
  2. Para um entendimento de “quotas”, explicamos para o administrador como elas funcionam.
  3. A ação necessária para o ambiente local seria a criação de uma quota/customização de como o retention está configurado para o ambiente, ou a remoção de dados (purge) para que o mailbox move possa ser efetuado. Recomendamos aguardar a atuação do MFA (Managed Folder Assistant) e não executar o comando de Start-ManagedFolderAssistant manualmente após estas alterações.
  4. A partir do momento que o mailbox move pode ser concluído, podemos atuar em outras soluções tais como a utilização de Archive com Auxiliary (+100GB a cada 30 dias) para o cenário.
  5. Podemos (suporte) estudar um aumento de RecoverableItemsQuota para alguns ambientes, porém este aumento só é efetuado após um Business Justification para o estudo da real necessidade. Lembrando também que este possível aumento só é efetuado post-migration, já que na migração, o objeto no ambiente cloud não é uma “mailbox” (não possui store) e sim um Mail Enabled User.

*Nobody believes anything bad can happen to them, until it does.

Recurso de bloqueio inteligente de extranet – Extranet Smart Lockout (ESL)

$
0
0

Recurso de bloqueio inteligente de extranet - Extranet Smart Lockout (ESL)

 

Em 22 de março de 2018, uma nova atualização foi lançada para o servidor Windows 2016 (KB4088889). Esta atualização nos trouxe o novo recurso de bloqueio inteligente da extranet do ADFS, ou ESL.

O recurso de bloqueio de extranet interromperá os ataques de força bruta bloqueando a conta no ADFS e impedindo que as contas sejam bloqueadas no Active Directory.
Como o nome sugere, esse recurso só será aplicado se a solicitação de autenticação for proveniente da extranet e para autenticações de nome de usuário/senha.

O novo recurso de ESL consiste na implementação de um novo parâmetro chamado <ExtranetLockoutMode >
Este parâmetro contém 3 valores diferentes:
ADPasswordCounter - este é o valor padrão. O "bloqueio de extranet suave". Não difere com base na localização.
ADFSSmartLockoutLogOnly - Esse é o modo somente de logs de bloqueio inteligente da extranet. Não rejeitará os pedidos. Em vez disso, auditará os eventos para análises.
ADFSSmartLockoutEnforce - Este é o bloqueio inteligente da extranet eficaz. Ele bloqueará as tentativas de senha incorreta quando o limite for atingido.

 

Antes de começar, precisamos conceder permissões de leitura/gravação ao nosso Administrador sobre o banco de dados de artefatos do ADFS, executando:

Update-AdfsArtifactDatabasePermission

(Autenticar com um administrador do ADFS)
Quando as permissões estiverem definidas, podemos iniciar a configuração de bloqueio inteligente da extranet.

 

Para ativar o bloqueio de extranet, precisamos executar o cmdlet:

Set-AdfsProperties -EnableExtranetLockout $true -ExtranetLockoutThreshold <valor> -ExtranetObservationWindow <valor>

 

Vamos examinar os parâmetros individualmente:
EnableExtranetLockout - Este parâmetro representa a chave liga/desliga. É sempre um valor codificado, $true ou $false
ExtranetLockoutThreshold - Esse parâmetro representa o número de tentativas de senha com falha antes que a conta seja bloqueada.
Nota: O limite de bloqueio deve ser sempre menor que o do Active Directory, de modo que as contas sejam bloqueadas no ADFS apenas enquanto os usuários ainda puderem acessar seu Active Directory pela intranet ou usando uma VPN.
ExtranetObservationWindow - Este parâmetro representa a janela de tempo de observação entre os blocos. Quando o limite de bloqueio é atingido, o intervalo de tempo da janela de observação é iniciado. Quando o período de tempo da janela de observação expirar e a tentativa de autenticação for bem-sucedida, a conta será desbloqueada automaticamente e a contagem será redefinida para 0. Se uma tentativa de autenticação incorreta for feita, a janela de observação será reiniciada.

 

Gerenciando o ESL:

Depois de definir o ExtranetLockoutMode como <ADFSSmartLockoutEnforce>, a diversão começa 😊

PS: Certifique-se de reiniciar o serviço do ADFS em todos os nods do ADFS no farm:

Restart-Service adfssrv

 

Por padrão, todos os registros de contas ficarão assim:

Depois que o usuário autentica com sucesso (com base em senha), o endereço IP é automaticamente adicionado à lista de itens conhecidos.

Se o limite de bloqueio for atingido, a conta será bloqueada automaticamente e a janela de observação será iniciada:

 

Mesmo que a conta esteja bloqueada, ela só é bloqueada em locais desconhecidos. O usuário ainda poderá acessar sua conta a partir de um local familiar.
Esta é uma melhoria maciça no recurso de bloqueio de extranet.

 

Em um cenário de força bruta, em que a conta está sendo constantemente bloqueada de locais desconhecidos, o que acontece quando o proprietário da conta tenta acessar sua conta também de um local desconhecido?
Ele não poderá acessar sua conta. No entanto, ele pode entrar em contato com o administrador para ter seu endereço IP atual adicionado nos locais conhecidos:

Set-AdfsAccountActivity -Identity <UPN> -AdditionalFamiliarIps "IP"

 

NOTA: A qualquer momento, a atividade da conta de bloqueio inteligente da extranet pode ser definida como padrão:

Set-AdfsAccountActivity -Identity <UPN> -Clear

 

O log de tentativa de acesso à conta será exibido no respectivo nod do ADFS em "Windows Logs/Segurança do Windows"

 

Aqui está um exemplo do log:

The Federation Service failed to issue a valid token. See XML for failure details.
Activity ID: 6d265a76-f305-4ede-a7c1-316c35514791
Additional Data
XML: <?xml version="1.0" encoding="utf-16"?>
<AuditBase xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="AppTokenAudit">
<AuditType>AppToken</AuditType>
<AuditResult>Failure</AuditResult>
<FailureType>GenericError</FailureType>
<ErrorCode>N/A</ErrorCode>
<ContextComponents>
<Component xsi:type="ResourceAuditComponent">
<RelyingParty>http://adfs.contoso.com/adfs/services/trust</RelyingParty>
<ClaimsProvider>N/A</ClaimsProvider>
<UserId>user@contoso.com</UserId>
</Component>
<Component xsi:type="AuthNAuditComponent">
<PrimaryAuth>N/A</PrimaryAuth>
<DeviceAuth>false</DeviceAuth>
<DeviceId>N/A</DeviceId>
<MfaPerformed>false</MfaPerformed>
<MfaMethod>N/A</MfaMethod>
<TokenBindingProvidedId>false</TokenBindingProvidedId>
<TokenBindingReferredId>false</TokenBindingReferredId>
<SsoBindingValidationLevel>NotSet</SsoBindingValidationLevel>
</Component>
<Component xsi:type="ProtocolAuditComponent">
<OAuthClientId>N/A</OAuthClientId>
<OAuthGrant>N/A</OAuthGrant>
</Component>
<Component xsi:type="RequestAuditComponent">
<Server>http://adfs.contoso.com/adfs/services/trust</Server>
<AuthProtocol>WSFederation</AuthProtocol>
<NetworkLocation>Extranet</NetworkLocation>
<IpAddress>1.2.3.4</IpAddress>
<ForwardedIpAddress>1.2.3.4</ForwardedIpAddress>
<ProxyIpAddress>N/A</ProxyIpAddress>
<NetworkIpAddress>N/A</NetworkIpAddress>
<ProxyServer>WAP</ProxyServer>
<UserAgentString>Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36</UserAgentString>
<Endpoint>/adfs/ls/</Endpoint>
</Component>
</ContextComponents>
</AuditBase>

 

 

Espero que isto ajude.

 

O365 – Exchange 2007 Staged Mailbox move falhando com “SourceRecipientDoesNotExistException”

$
0
0

By: Caio Ribeiro César e Cesar Augusto Hara

Após um longo período de tempo, recebemos um chamado referente à uma migração “Staged” para o Exchange Online.

Como o nome sugere, uma migração “Staged” é feita em estágios, etapas. Pode parecer um cenário simples com poucos pontos de falha, porém temos que entender um pouco como esta migração funciona antes de iniciar qualquer tipo de troubleshooting.

Considerações deste tipo de migração:

  1. Os objetos são provisionados via AD<>AAD. Ou seja, mandatório que exista um AADConnect no ambiente;
  2. Algumas funcionalidades cross premises não são suportadas (tais como FreeBusy, Cross Prem Archive , Hybrid Mailbox Permission entre outros) ;
  3. Não existe um mailbox offboard feito nativamente via Exchange (assim como temos no ambiente híbrido);
  4. Não é uma solução “longo termo”. O decomission dos servidores on-premises pode ser feito após a migração.

Resumindo a migração “Staged” em etapas:

(mais detalhes aqui)

  1. Provisionamento de objetos
  2. Mailbox Permission para o administrador (Full Access)
  3. Arquivo CSV
  4. Criação do endpoint para conexão (Outlook Anywhere do ambiente On-Premises deve estar configurado e disponibilizado externamente – este é o ponto de falha mais comum em migrações staged).
  5. Migração
  6. Alteração do DNS (MX)
  7. Completar a migração
  8. Clean Up (remoção de batches, decommission).

Vamos então ao cenário.

Cliente informa que a maioria das caixas de correio foram migradas com êxito via Staged Migration, porém algumas não estão sendo migradas.

Para ter o foco na coleta de dados e troubleshooting, isolamos o problema para uma específica. Inicialmente, coletamos o erro que estava aparecendo na interface gráfica do Exchange Online:

SourceRecipientDoesNotExistException: Não foi possível encontrar o endereço de email de origem caioc@contoso.com.br no domínio local. Relatório: caioc@contoso.com.br Baixe o relatório para esse usuário

Criamos um plano de ação de coleta de dados:

1. Para confirmar que o SMTP é valido no ambiente On-Premises, executados a coleta do comando

Get-Mailbox -Id caioc@contoso.com.br | fl

Resultado: SMTP válido e existente, mailbox ativa no Exchange 2007.

2. Coletamos os relatórios enviados para o email do administrador que estava efetuando o move mailbox.

MailboxesCreated.csv

MailboxCreationErrors.csv

EmailMigrationErrors.csv

Resultado:  o relatório mostra o Status “SyncedWithErrors”, com o mesmo erro da interface gráfica.

3. Coletamos relatórios verbose para o batch e para o usuário em questão.

Get-MigrationBatch -identity  |fl *status*
Get-MigrationBatch  -IncludeReport -Diagnostic | Export-clixml batchname_report.xml
Get-MigrationUser -Identity caioc@contoso.com.br| fl 
Get-MigrationUserStatistics -Identity caioc@contoso.com.br -IncludeReport | Export-Clixml report.xml

Resultado: todos os logs informaram a mesma mensagem de erro:

SerializationData         : {0, 1, 0, 0...}
RunspaceId                : 48fbab7-5386-473b-9e30-22c7cb09cc02
Identity                  : caioc@contoso.com.br
Guid                      : e8764567812df-08bd-433a-9987652-cd6e7eb2e1a0
Identifier                : caioc@contoso.com.br
BatchId                   : migracao
MailboxIdentifier         : caioc@contoso.com.br
MailboxEmailAddress       : 
RecipientType             : Mailbox
SkippedItemCount          : 0
SyncedItemCount           : 0
MailboxGuid               : 00000000-0000-0000-0000-000000000000
MailboxLegacyDN           : 
RequestGuid               : 00000000-0000-0000-0000-000000000000
LastSuccessfulSyncTime    : 
Status                    : Failed
State                     : Failed
Flags                     : None
WorkflowStep              : Provisioning
WorkflowStage             : Discovery
TriggeredAction           : None
ErrorSummary              : Não foi possível encontrar o endereço de email de origem caioc@contoso.com.br no domínio local.
StatusSummary             : Failed
LastSubscriptionCheckTime : 
SupportedActions          : Start, Set, Remove
IsValid                   : True
ObjectState               : Unchanged

SerializationData : {0, 1, 0, 0...}
CreationTime : 5/8/2018 4:20:31 PM
ServerName : SC1P215MB0907
Type : Error
TypeInt : 4
Flags : Failure, Fatal, Target
FlagsInt : 2066
Message : User 'caioc@contoso.com.br' failed migration: The source email address caioc@contoso.com.br couldn't be found in the on-premises domain.
MessageData                : {0, 1, 0, 0...}
Failure : SourceRecipientDoesNotExistException: Nao foi possível encontrar o endereço de email de origem caioc@contoso.com.br no domínio local.					 
LocalizedString :  User 'caioc@contoso.com.br' failed migration: The source email address caioc@contoso.com.br couldn't be found in the on-premises domain.

Efetuamos um query local no AD e conseguimos encontrar a mailbox utilizando o valor de SMTP como Identifier. A partir deste ponto, voltamos ao entendimento da teoria do mailbox move em um ambiente staged.

Como fomos informados que outras contas foram movidas sem problemas, tentamos não focar o troubleshooting no Outlook Anywhere em si (networking, endpoint, test migration connectivity).

Discutimos o cenário em questão e lembramos que nesta migração, o Exchange Online irá se comunicar via NSPI com o ambiente OnPremises para localizar a mailbox (diferente de um ambiente híbrido que utilizaria o serviço de EWS via MRSProxy):

O objeto estava sincronizado sem problema algum para o Exchange Online via AADConnect, então focamos na análise de dados utilizando um método de comparação e a matriz de soluções de suporte.

Utilizando este método, conseguimos isolar o problema para uma possível falha ou configuração do objeto em si. Comparamos o get-mailbox de uma conta que foi migrada com sucesso vs. a que está falhando e encontramos uma diferença na configuração abaixo (opção “Compare” do Office Word):

HiddenFromAddressListsEnabled : True

Se o objeto está “Hidden”, logo o Exchange Online não conseguirá efetuar o move via Outlook Anywhere :).

Após esta alteração, efetuamos um novo batch de migração para o usuário, desta vez com sucesso.

Viewing all 98 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>