Showing posts with label Active Directory. Show all posts
Showing posts with label Active Directory. Show all posts

Friday, August 18, 2017

SharePoint 2013 Notes: On using the Everyone group for SharePoint User Groups

Which AD group should the SharePoint administrator use for populating a SharePoint Visitors user group? In this Notes posting, I examine three security principals that  are often used for populating SharePoint "Visitors" user groups: Everyone, NT AUTHORITY\AUTHENTICATED USERS and [DOMAIN]\DOMAIN USERS.  At the end of this article, I provide my recommendation on which one is the best to use.  I would like to thank Tim MacLaughlin, a senior systems administrator, for providing helpful comments and insights on Active Directory concepts while drafting these Notes.

Background

The situation is, you are creating the security structure for a new SharePoint-based enterprise content management (ECM) system to be deployed in your customer company A.  You have a set of site collections, and each site collection corresponds to a customer organization within the customer's company A.  Each portal page of the site collection should be visible to everyone authenticated into the company A network, which is comprised of a single domain in a forest having trust relationships with several other forests among partner companies B, C and D that are all members of the same holding company E. You have developed a security architecture that entails each site collection having the standard SharePoint user groups: Owners, Designers, Contributors and Visitors with commensurate permission levels.  You want the Visitors group, which has SharePoint permission level Read, to be populated with a single AD group that will allow all company A users to view the portal of the site collection.  The same AD group should be used for all site collection visitor user groups.

You create the respective Visitors groups for each site collection.  You know there is an Everyone group that you can see appearing as you type it.  You're not sure about what other AD user groups that there might be and which AD group might be the best and/or most appropriate one to use.

Discussion

There are several groups that you can choose from.  Which one to use will likely depend on the direction of your systems administrators and security officer.  Let's look at what each one entails.

The Everyone Group

The Everyone security principal is frequently referred to as a "group" for convenience sake even in TechNet literature but is not actually a user group in the sense of being able to add and remove user accounts from it. It is one of the Windows special identities that:
...[does] not have specific memberships that can be modified.
(see Understanding Group Accounts)
The Everyone security principal is defined and managed by the Windows operating system and represents...
... all current network users, including guests and users from other domains. Whenever a user logs on to the network, the user is added automatically to the Everyone group
(see Understanding Group Accounts)
This security principal previously included...
...all users, even anonymous users and guests..[including] authenticated and unauthenticated users. In essence, every user who accesses the system is a member of the Everyone group...
(see Microsoft Windows 2000 Security Configuration Guide: Appendix D - User and Group Accounts)
However, this was changed for Windows 2003 and greater (see Understanding Group Accounts: Special Identities), where the Anonymous Logon group was no longer a member of the Everyone security principal by default.  You can still add it to Everyone, but this must now be done through security policy setting.

The Everyone security principal also includes a number of builtin accounts that you might not normally want to have authorized to connect to a site collection, such as:
  • Guest
  • SERVICE
  • LOCAL SERVICE
  • NETWORK_SERVICE
  • SYSTEM
which exist independently on each Windows machine in the domain.   For a complete listing see: Windows Built-in Users and Default Groups and Default local groups. It also includes the  NT AUTHORITY\AUTHENTICATED USERS security principal, which encompasses users not only in the home domain, but also other domains in the forest trusted by the target domain and even in domains in other forests having inter-forest trust relationships with the forest of the home domain. Thus, the membership of the Everyone security principal is not centrally manageable at the domain level. Consider it as a superset of local security principals - one containing other local security principals and the NT AUTHORITY\AUTHENTICATED USERS principal.  As its name implies, its membership includes everything (except, by default, anonymous).  Thus, this security principal is not centrally manageable.

One additional note.  The Anonymous and Guest accounts in the context of SharePoint can be a bit confusing.  The reason being that SharePoint rests on top of IIS, and, if IIS is serving to Internet users, IIS must be configured to allow anonymous access. Now, if anonymous access is tied to a dedicated service account, there won't be any immediate problems. However, if you tie IIS anonymous access to the builtin Anonymous account, you've now opened up your system to everyone on the internet.

The AUTHENTICATED USERS Group

The NT AUTHORITY\AUTHENTICATED USERS is also frequently referred to as a "group" but isn't one in actuality.  Instead, like the Everyone "group," it is a:
...special security principal that specifies any session that's been authenticated using some account, such as a local SAM account, domain account, or account from any trusted domain
(see WindowsITPro: Understanding the Authenticated Users Group and 
Microsoft Windows 2000 Security Configuration Guide: Appendix D - User and Group Accounts)
Thus, it too is not a group in the sense of being able to add and remove user accounts from it, but is simply referred to as a "group" for the sake of convenience. The AUTHENTICATED USERS security principal is effectively a subset of the Everyone security principal and includes...
...all users with a valid user account on the computer or in Active Directory services.
(see Microsoft Windows 2000 Security Configuration Guide: Appendix D - User and Group Accounts)
Note that this encompasses not only the builtin local accounts but also any other local account.  Note too that, as discussed previously, AUTHENTICATED USERS includes not just users authenticated into the home domain of the home forest hosting the SharePoint farm but any user authenticated into another domain within that forest trusted by the home domain or domains in external forests.  Thus the pool of users encompassed by authenticated users is dynamic and can fluctuate depending on active directory configuration (see What's the scope of the built-in Authenticated Users group in a multi-forest Active Directory (AD) environment?).  Thus, the membership of the NT AUTHORITY\AUTHENTICATED USERS security principal is not centrally manageable at the domain level.

The DOMAIN USERS  Group

The [DOMAIN]\DOMAIN USERS group is a true user group in the sense that user accounts can be added to and removed from this group.  The DOMAIN USERS group is defined and managed at the Active Directory domain level.  This group...
...includes all user accounts in a domain. When you create a user account in a domain, it is automatically added to this group.
 
By default, any user account that is created in the domain automatically becomes a member of this group. This group can be used to represent all users in the domain. For example, if you want all domain users to have access to a printer, you can assign permissions for the printer to this group (or add the Domain Users group to a local group on the print server that has permissions for the printer).
 
The Domain Users group applies to versions of the Windows Server operating system listed in the Active Directory default security groups by operating system version.
 
This security group has not changed since Windows Server 2008.
(see Windows Server 2012: Active Directory Security Groups)
The DOMAIN USERS group is a true group.  It contains only users (not computers) that have authenticated to the local domain, and it does not include any user accounts from outside the domain. This group is updated automatically whenever a new user account in the local domain is created, modified, disabled or removed.

Since DOMAIN USERS includes all user accounts in the domain, it will also include all application service domain accounts, including those service accounts provisioned for your farm.  All of these application service accounts will potentially have data access to the SharePoint farm, at least at the View or Read level, if you use the DOMAIN USERS group to populate SharePoint site Visitors user groups like I do.  If you then use regular domain groups to populate SharePoint site Contributor and Member user groups (having Contribute and Edit permission levels respectively), the fact that application service accounts may have View or Read access to content may not be a significant security risk.

Another thing to bear in mind is that if a public-facing website is using anonymous access tied to a domain service account, if that domain account is broken, that account could then be used for unauthorized access to a site.

Lastly, rather than using the default DOMAIN USERS group for capturing all users authenticated into the domain, you may also wish to consider creating a custom regular domain group that you add all of your user accounts to. A regular domain group is completely manageable and it has the added benefit of enabling you to include users from other domains and forests having a trust relationship with the home domain.  It can also allow you to restrict access to a subset of domain users within the home domain rather than having to include all of them, such as, for example, excluding all application service domain accounts.  While populating this group may seem onerous when considering an environment of many thousands of users, it actually isn't.  The knowledgeable systems administrator can easily accomplish this using PowerShell and a CSV file of the users to be added; and some references for this are listed below.  Many more can be found through appropriate searches.

Review

Let's review what has been discussed thus far.  The table below lists the characteristics of the three security principals discussed in this article for ease of comparison.
Characteristic EveryoneAUTHENTICATED USERSDomain Users
Includes all users in external forestsCapableCapableNo
Includes all computers in external forestsCapableCapableNo
Includes all users in external domainsCapableCapableNo
Includes all computers in external domainsCapableCapableNo
Includes all computers in domainYesYesNo
Includes all users in domainYesYesYes
Includes all application service accounts in domainYesYesYes
Includes Windows builtin accountsYesYesNo
Includes local user accountsYesYesNo
Includes Guest accountYesYesNo
Includes AnonymousNoNoNo
Centrally manageable at domain levelNoNoYes
Of these three security principals, only the DOMAIN USERS AD group presents a static, well-defined, centrally manageable true user group that only includes authenticated domain users.  It is only this security principal that enables you (through your systems administrator) to have granular control over the membership of the group you use to assign all users a specific SharePoint permission level.  Of the three user "groups" discussed in these notes, only the DOMAIN USERS group would meet the requirement in the scenario presented in these notes of restricting access to the new ECM to users in the Company A domain.  If possible, an even better alternative is to use a regular domain group and populate that group only with user accounts of your actual users.  There are risks associated with all of these approaches, with the Everyone and AUTHENTICATED USERS security principals introducing the most risk, the DOMAIN USERS security principal introducing considerably less risk, and a regular domain group introducing the least risk.

Recommendation

When needing to assign a SharePoint permission level to all users, don't use the Everyone or AUTHENTICATED USERS "groups."  Instead, use the DOMAIN USERS Active Directory group appropriate to the domain in which your SharePoint farm resides.  Use this AD group when needing to, for example, assign the SharePoint Read permission level to all users in your organization.

You will need to assess the relative benefits of using this group against the potential risks of providing data access to your farm by:
  • application service accounts and
  • broken domain accounts tied to IIS Anonymous access
An even better approach, if your systems admin team will allow it, or if they have already implemented it, is to use a regular domain group populated only with accounts of your actual users.

References

Notes

  • Here's an example scenario that implements this recommendation:
    Scenario
     
    You need the portal page to your home organizational SharePoint-based itranet ECM solution to be accessible by all users across the home organization and only to users in the home organization.  The home organization is comprised of a single domain having some trust relationships with some other domains in the larger organization containing the home organization.  All users in the home organization should be able to at least read content at the portal page and download any files.
     
    Solution
     
    First, engage your systems administrators to verify that the Domain Users group is actively being used for the domain in which your farm resides or if there is another domain group they would rather have you use.  Verify with them too that all users having accounts in the domain also have their accounts added to this group. Once you have verified this, create a SharePoint user group Visitors in the site collection. Assign this SharePoint user group the Read permission level.  Populate this user group with a single member, [HOME DOMAIN]\Domain Users.  If you have activated Publishing for the site collection, also ensure that all users have Read permission to the Style and the Site Collection Images libraries, as Publishing pages will pull content from these document libraries.
  • You may wish to consider including in your governance plan direction to your site collection administrators on the appropriate group to use when wanting to provide "everyone" access to some SharePoint site or resource.

Tuesday, May 12, 2015

Active Directory 2012 Tip: how to import users in bulk from a CSV

Here's a sample PowerShell script for importing users in bulk into Active Directory (AD).  It configures these AD fields:
  • SamAccountName
  • UserPrincipalName
  • GivenName
  • Initials
  • Surname
  • DisplayName
  • Name
  • Description
  • Company
  • StreetAddress
  • City
  • State
  • PostalCode
  • OfficePhone
  • Fax
  • EmailAddress
  • AccountPassword
  • ChangePasswordAtLogon
  • PasswordNeverExpires
  • Enabled
  • PassThru
And then here's the script that I use to perform the import:
import-csv c:\temp\100.csv | foreach-object {New-ADUser -SamAccountName $_.SAMAccountName -UserPrincipalName $_.SAMAccountName -GivenName $_.givenName -Initials $_.Initials -Surname $_.Surname -DisplayName $_.DisplayName -Name ($_.givenName + $_.Initials + $_.Surname) -Description $_.Description -Company $_.Company -StreetAddress $_.StreetAddress -City $_.City -State $_.State -PostalCode $_.PostalCode -OfficePhone $_.OfficePhone -Fax $_.Fax -EmailAddress $_.EmailAddress -AccountPassword (ConvertTo-SecureString "P@ssw0rd" -AsPlainText -Force) -ChangePasswordAtLogon $False -PasswordNeverExpires $True -Enabled $True -PassThru -WhatIf}
References
Notes

Thursday, April 2, 2015

TIP: how to use repadmin to find user info in AD LDS

Tip

This posting presents repadmin commands useful against an AD LDS instance used for a small SharePoint 2007 farm.

Get Time Stamps

Get badPasswordTime, lastLogonTimestamp, pwdLastSet and whenCreated for all users

repadmin /showattr * "CN=...,dc=...,dc=..." /subtree /filter:"(&(objectCategory=Person)(objectClass=user))" /attrs:badPasswordTime,lastLogontimestamp,pwdLastSet,whenCreated /homeserver:serverName:389 > C:\lastlogons.txt

References

Notes
  • Windows Server 2008 R2

Thursday, September 26, 2013

Build a SharePoint 2007 Two-Tier Farm on Windows 2003

Introduction

This posting walks through the process of building a small two-tier SharePoint Server 2007 farm on Windows Server 2003 R2 that can be used for testing and development.  Performed on VMware Workstation 7.X.  Components of this environment will include:
  • Windows Server 2003 R2 Enterprise (trial version)
  • SharePoint Server 2007
  • SQL Server Express version 2005
  • .NET Frameworks 2.0 and 3.0
  • Domain controller
  • DNS server
Building the environment involves the following discrete steps:
  1. Build servers
  2. Configure DC and DNS
  3. Join Domain
  4. Install SQL Server Express
  5. Install SharePoint Server 2007
Step 1: Build Servers
  • Build two Windows Server 2003 R2 Enterprise instances using the clone developed in a previous posting.
  • Launch first server:
    • during mini-setup, set name to spdev21.
  • Launch second server:
    • During mini-setup, set name to spdev23.
Step 2: Configure DC and DNS
  • On the first server (spdev21):
    1. On Manage Your Server, click Add or remove a role.  The Configure Your Server wizard is launched.
    2. Configure domain as AdventureWorks.Com.
    3. After completion, verify that new forward lookup, pointing to this DNS, was automatically created.
    4. Reboot (automatic).
    5. Verify Internet connectivity and access.
    6. From Administrative Tools, launch Active Directory Users and Computers.
    7. Add SharePoint service accounts: sp_admin, sp_web and sp_app.
Step 3: Join Domain
  • On the second server (spdev23):
    1. Configure network adaptor IP and DNS.
    2. Verify Internet connectivity and access.
Step 4: Install SQL Server Express
  1. On spdev21:
    1. Install .NET Framework 2.0 SP2.
    2. Install SQL Server Express (2005).
    3. Add account sp_admin:
      • Add roles: dbcreator, securityadmin.
    4. Add own account as sysadmin.
    5. Note the SQL Server instance name: SPDEV21\SQLEXPRESS.
Step 5: Install SharePoint Server 2007
  1. Install .NET Framework 2.0.
  2. Install .NET Framework 2.0 SP2.
  3. Install .NET Framework 3.0.
  4. Open a command window and navigate to: C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727.
  5. Run this command:
    • aspnet_regiis -I
  6. Verify that the SQL Server Browser service is running.  If it isn't, start it.
  7. Perform an installation of SharePoint Server 2007 per a previous posting.
  8. Install WSS SP1 and Office Server 2007 SP1; to version 12.0.0.6219.
  9. Reboot (optional).
  10. Install WSS SP2 and Office Server 2007 SP2; to version 12.0.0.6421.
  11. Reboot (optional).
  12. Install WSS SP3 and Office Server 2007 SP3.

References
Notes
  • Step 2: no roles were added to the clone template, during the clone template build process for Windows Server 2003 R2 Enterprise.  When adding a role to the machine for the first time, the Configure Your Server wizard will conveniently launch into adding the DC, DNS and DHCP roles.  It will also check the network adaptor settings and conveniently configure DNS forwarding automatically, based upon the settings it detects.
  • Step 4: Windows Server 2003 R2 Enterprise has .NET Framework 2.0 already installed.  Verify this by downloading and running dotNETInspector.
  • Step 5: I'm not sure why yet, but formally installing .NET 2.0 framework adds features and capabilities not originally there, even though Windows Server 2003 R2 is supposed to have .NET 2.0 already installed and this is verified by running .NET Inspector.
  • Step 5: installing a more recent copy of the SharePoint Server 2007 requires not only .NET Framework version 2.0 but also .NET framework version 3.0.
  • Step 5: installation of SP1 isn't necessary as it's rolled up into SP2. However, still good as an exercise.

Friday, September 20, 2013

How to present AD metrics in a SharePoint 2010 dashboard

PowerShell Metrics Series: Active Directory Reporting
How to generate and report basic AD account metrics
How to generate complex AD account metrics part 1
How to generate complex AD account metrics part 2
How to store AD metrics in SharePoint 2010
How to present AD metrics in a SharePoint 2010 dashboard
Introduction

In the previous posting in this series, we explored how to harvest basic Active Directory account metrics, using a PowerShell script running on the server hosting the SharePoint Server 2010 instance, and then writing those metrics to a list in the SharePoint Server 2010 instance.  In this posting, we'll explore methods for presenting those metrics in a SharePoint 2010 dashboard.  We'll explore presenting metrics data using the Data View and Chart web parts.  This will involve the following steps:
  1. Step 1: create a new page
  2. Step 2: customize the page
  3. Step 3: add data view web part and configure
  4. Step 4: add a chart web part and configure.
  5. Step 5: test
Step 1: create page
  1. Open a browser and connect to the site
  2. Navigate to the Site Pages folder
  3. Add a new page to this folder, naming it dashboard.
Step 2: customize page
  1. With the page open for editing, select a Text Layout
  2. Save and close the page.
  3. Launch Designer, and then open the page for editing.
  4. In the bottom most web part zone, insert a Content Editor web part.
  5. Link this web part to a text file containing CSS that hides the Recently Modified group in the Quick Launch navigation section of the page.
  6. Save the page and continue to the next step.
Step 3: add Data View web part
  1. Launch SharePoint Designer 2010, and then connect to the site.
  2. Open dashboard.aspx for editing.
  3. Carefully insert the cursor into a cell, making sure it goes into the DIV container within that cell
  4. On the Insert ribbon, click Data View, and then click Empty Data View.  An empty Data View web part is added and the Data Source Details task view appears.
  5. On the Data Source Details task pane, select the fields to be inserted (these will be the ones displaying integer values), and then select Multiple item View:
  6. In Design view, on the Data View web part, select any column header, and then click the Bold button on the Home
  7. Select the Split view tab to see both design and code simultaneously.
  8. In Code view, edit the column headers
  9. Other possible customizations:
    1. Bold all the column headers.
    2. Set the cell containing the date to NoWrap:
  10. Configure the data view:
    1. Web part title: Total Accounts by Type.
    2. Chrome Type: Title Only.
    3. Chrome State: Normal.
  11. Save the page, and then close the page in Designer.  If this page was checked out, check it back in.
  12. Open a browser and navigate to dashboard.aspx to see the results thus far:
Step 4: add Chart web part
  1. In the browser, check out and open the page for editing.
  2. From the Insert tab, click Web Part; from the Categories pane, select Business Data; and then from the Web Parts pane, select Chart Web Part.
  3. Click Add
  4. On the Chart web part, click Data & Appearance, click Connect Chart to Data, and then select Connect to a List.
  5. Click Next.  From the List dropdown, select the data list
  6. Click Next, and then click Next again.
  7. Configure the Default series as so:
    1. Series Name: Total.
    2. Series Type: Line.
    3. Series X-Axis: Primary.
    4. Series Y-Axis: Primary.
    5. Y Field: TotalAllAccounts.
    6. X Field: Title (or Date, if you added it already).
    7. Leave all others default.
    8. This configures one line of the chart - the line for Total Accounts
  8. Click the "+" icon next to the Series dropdown.
  9. Configure the second series as so:
    1. Series Name: Admin.
    2. Series Type: Line.
    3. Series X-Axis: Primary.
    4. Series Y-Axis: Primary.
    5. Y Field: TotalAdminAccounts.
    6. X Field: Title (or Date, if you added it already).
    7. Leave all others default.
    8. This configures the line for Total Admin Accounts.
  10. Repeat this process for each of the other totals: Service, Test, User.
  11. Click Finish
  12. On the Chart web part, click Advanced Properties.
  13. At left, in the Select an Element link group, click Series.
  14. Above, from the Series Menu dropdown, select Total.
  15. In the list of properties, scroll down to MarkerStyle; click it to open the dropdown and then select a value
  16. Pause for a few seconds to allow the Chart Preview image at right to refresh, before proceeding to make the next change.  Otherwise, any changes will be lost.
  17. Above, from the Series Menu dropdown, select Admin, and repeat.
  18. Repeat these steps for each of the other series (Service, Test, User)
  19. At left, in the Select an Element link group, click Titles.
  20. Click the "+" sign next to the Titles Menu dropdown.
  21. Below, in the list of properties, scroll down to Text (near the bottom), enter a title, and then press Enter
  22. Pause to allow the Chart Preview to refresh.
  23. Change other title properties as desired (e.g., font).
  24. At left, in the Select an Element link group, click Chart Areas.
  25. Above, from the Axis Menu dropdown, select X axis.
  26. Below, scroll down the list of properties to Title (near the bottom), enter text, and then press Enter
  27. Pause to allow the Chart Preview to refresh.
  28. Repeat this for y axis.
  29. Click Finish
  30. Open the page in Designer.
  31. On the Format ribbon, click Chrome Type, and then select None.
  32. Select the Split view.
  33. On the Home ribbon, click Advanced Mode.
  34. Press CTRL+V, enter the search keyword ShowToolbar, and then click Find Next
  35. In Code view, change the ShowToolbar Chart web part property to False.
  36. Close the Find and Replace dialog.
  37. Save the page.
  38. Refresh the browser to see the changes
Step 5: Test
  1. To see the results of several days data capture, enter some sample data into the list, and then refresh the browser
Summary

In this posting of the PowerShell Metrics series, we have explored how to present the Active Directory metrics discussed previously in both list and chart formats.

References
Notes
  • After inserting the Data View onto the page, the specific XML generating each of the headers will not be exposed.  In Split view, if the you select the column header while in the Design view, you will see a group of markup selected in Code view but not specific reference to markup associated with the item selected:

    To expose this XML, use the trick of selecting a header in design view and then bolding it.  This cause Designer to rewrite the XML to specifically script the generation of each header.  Once exposed, you can edit the headers individually as needed
  • SharePoint Server 2010 Standard or Enterprise?  It isn't necessary to expend resources to upgrade SharePoint Server 2010 Standard, as the methods presented here work for either. 
  • SharePoint Server 2010 Chart web part: this web part is based upon the standard .NET chart control.  The SharePoint version has limited documentation, and the vast majority of its properties are not documented per se.  These can, however, be discovered for the most part by reviewing documentation for the .NET chart control.

Thursday, September 19, 2013

How to store AD metrics in SharePoint 2010


PowerShell Metrics Series: Active Directory Reporting
How to generate and report basic AD account metrics
How to generate complex AD account metrics part 1
How to generate complex AD account metrics part 2
How to store AD metrics in SharePoint 2010
How to present AD metrics in a SharePoint 2010 dashboard
Introduction

In the previous posting in this series, we explored how to generate more complex AD account metrics using PowerShell. In this posting, we'll explore how to store these metrics in a SharePoint Server 2010 list for convenient access. This will involve the following four steps:
  1. Creating a new list with appropriate fields.
  2. Adding the Active Directory remote management tools to the SharePoint host.
  3. Modifying the PowerShell script developed in previous postings to write results to this list.
  4. Running the script to verify metrics harvest from Active Directory and their storage in the list.
To prepare for this procedure, the Northwind Traders database was added to a new site collection. All nine of the employees were added to Active Directory and made members of a new group, Northwind. Additionally, the SharePoint Server 2010 service accounts, sp_admin, sp_web and sp_app, were also made members of the Northwind group, along with a test account, sp_test, and the administrators account, brens, for a total of 14 accounts in the Northwind AD group.

NOTE: PowerShell is sensitive to field name case!  Field names, when first created in a SharePoint 2010 list, are case-sensitive: $Item["fieldname"] is different than $Item["Fieldname"].

Step 1: create list
  1. Create a new custom list in SharePoint Server 2010. Give the list a short name to simplify referencing it in PowerShell.
  2. Add to this list all of the basic metrics developed previously, including:
    1. Total accounts
    2. Total admin accounts
    3. Total service accounts
    4. Total test accounts
    5. Total end-user accounts
  3. Format these fields as numbers with 0 decimal places
Step 2: add tools
  1. Open Server Manager.
  2. Click Add Features.
  3. Select Remote Server Administration Tools | Role Administration Tools | AD DS and AD DS Tools:
  4. Install the tools.
Step 3: modify script
  1. Open a PowerShell window on the SharePoint Server.
  2. Add the PowerShell snap-in for SharePoint.
  3. Import the PowerShell module for Active Directory
  4. Follows is the modified script, simplified and with most comments removed:
Import-Module ActiveDirectory
Add-PSSnapin Microsoft.SharePoint.PowerShell
$DateTime = Get-Date
# Get the Northwind group accounts only
$NorthWindAccounts = (Get-ADGroup 'Northwind').DistinguishedName
# Extract general metrics
$AllAccounts = Get-ADUser -Filter {(memberof -eq $NorthWindAccounts)} -Properties Name, Givenname, Surname, DistinguishedName, Enabled, LastLogonDate, LastLogonTimeStamp, LockedOut, SAMAccountName, CreateTimeStamp, Created, PasswordLastSet, Description
[array]$AllAdminAccounts = $AllAccounts | Where-Object {$_.Description -Like '*Admin*'}
[array]$AllServiceAccounts = $AllAccounts | Where-Object {$_.Description -Like '*Service*'}
[array]$AllTestingAccounts = $AllAccounts | Where-Object {$_.Description -Like '*Testing*'}
[array]$AllUserAccounts = $AllAccounts | Where-Object {($_.Description -NotLike '*Admin*') -and ($_.Description -NotLike '*Service*') -and ($_.Description -NotLike '*Testing*')}
# Handle null values
if (($AllAccounts.count -eq $NULL) -or ($AllAccounts.count -eq 0)){
    $AllAccountsValue = 0
}
else{
    $AllAccountsValue = $AllAccounts.count
}
if (($AllAdminAccounts.count -eq $NULL) -or ($AllAdminAccounts.count -eq 0)){
    $AllAdminAccountsValue = 0
}
else{
    $AllAdminAccountsValue = $AllAdminAccounts.count
}
if (($AllServiceAccounts.count -eq $NULL) -or ($AllServiceAccounts.count -eq 0)){
    $AllServiceAccountsValue = 0
}
else{
    $AllServiceAccountsValue = $AllServiceAccounts.count
}
if (($AllTestingAccounts.count -eq $NULL) -or ($AllTestingAccounts.count -eq 0)){
    $AllTestingAccountsValue = 0
}
else{
    $AllTestingAccountsValue = $AllTestingAccounts.count
}
if (($AllUserAccounts.count -eq $NULL) -or ($AllUserAccounts.count -eq 0)){
    $AllUserAccountsValue = 0
}
else{
    $AllUserAccountsValue = $AllUserAccounts.count
}
# Get the site object
$SiteURL = "http://spdev12:4000/"
$Site = Get-SPWeb $SiteURL
# Get the list object from this site
$ListName = "dl_ml"
$List = $Site.Lists[$ListName]
# Prepare a new list row
$NewItem = $List.Items.Add()
    $NewItem["Title"] = $DateTime
    $NewItem["TotalAllAccounts"] = $AllAccountsValue
    $NewItem["TotalAdminAccounts"] = $AllAdminAccountsValue
    $NewItem["TotalServiceAccounts"] = $AllServiceAccountsValue
    $NewItem["TotalTestAccounts"] = $AllTestingAccountsValue
    $NewItem["TotalUserAccounts"] = $AllUserAccountsValue
# Add the new list row
$NewItem.Update()
# Dispose the site object
$Site.Dispose()
Step 4: test script
  1. On the SharePoint Server 2010 host, open the PowerShell ISE.
  2. Paste the script above into a new tab.
  3. Modify server names, site URLs, list names and column names as necessary.
  4. Run the script under an account that has at least read privileges to the domain controller.
  5. Open a browser, and then connect to the site to view the list:
Summary

In this posting, we explored how to generate AD metrics from the server hosting SharePoint Server 2010 Enterprise and then store those metrics in a SharePoint Server 2010 list. All references consulted in writing this posting are listed below. In the next posting in this series, we'll explore how to present these metrics in the Data View and Chart web parts.

References
Notes
  • Microsoft.SharePoint.PowerShell: From what I've found thus far, there doesn't appear to be a way to install the this snap-in on other machines to facilitate remote scripting. The only options found were: remote desktop or remote PowerShell session.
  • Import-Module ActiveDirectory: this isn't normally needed for the machine hosting SharePoint Server 2010. However, it is needed in order to interact with domain controllers and extract account metrics from them.
  • If you see this error after running the above PowerShell script,
    check the case of the fieldnames that you are using against what they are in the SharePoint list.

Sunday, September 15, 2013

How to generate complex AD account metrics part 2


PowerShell Metrics Series: Active Directory Reporting
How to generate and report basic AD account metrics
How to generate complex AD account metrics part 1
How to generate complex AD account metrics part 2
How to store AD metrics in SharePoint 2010
How to present AD metrics in a SharePoint 2010 dashboard
Introduction

In the first posting of this series, we explored the basic process for generating AD metrics and saving them to a file.  In the second posting, we explored generating somewhat more complex metrics.  In this posting, we will conclude this exploration by extracting and categorizing AD account last logons again using the simplest approach.

Obtaining user account last logons provides immediate business value to system administrators, management and customers, as they show infrastructure usage.  Capturing and archiving these values supports trending analysis and more accurate budget planning.

The AD account attribute that will be used is LastLogonDate.  This attribute is a conversion of the LastLogonTimeStamp long integer value into a friendly time format that is formatted according to your local time zone and settings.  The LastLogonTimeStamp attribute is replicated (by default) between 9 to 14 days among the domain controllers and thus LastLogonDate as well.

Review

Here's the script generated thus far:
##################################### # Name:        AD Report Generator # Author:      [your name] # Date:        [date] # Description: ##################################### Import-module ActiveDirectory # Create the report container # --------------------------- # Save the data and time.  This date and time # will be used also for generating the report # filename. $DateTime = Get-Date # Use this date/time to generate the report file name $DateTimeFileString = $DateTime.ToString("yyyyMMddHHmmss") # Now generate the path/file string $FilePathString = "\\[YourPath]\ADReport_" + $DateTimeFileString + ".txt" # Create a new text file New-Item $FilePathString -Type File # Write the report date/time # -------------------------- # Add the date/time to the top of the file [string]$StringToWrite = $DateTime Set-Content $FilePathString $StringToWrite # and then add a couple of lines after Add-Content $FilePathString "" Add-Content $FilePathString "" # Add a header to the report # -------------------------- $StringToWrite = "AD Domain Accounts Report" Add-Content $FilePathString $StringToWrite $StringToWrite = "Generated on host " + $env:Computername + " by " + $env:UserName Add-Content $FilePathString $StringToWrite Add-Content $FilePathString "=====================================================" Add-Content $FilePathString "" Add-Content $FilePathString "" Add-Content $FilePathString ""   # Build the report # ---------------- # This next line of code interrogates AD and builds the array # that contains all accounts in AD and the desired properties.   # It effectively generates a list of accounts and their # properties that you can parse and filter as needed.  This only # needs to be performed once, for the entire report, as all of # the rest of the attention will be focused on this array. [array]$AllAccounts = Get-ADUser -Filter * -Properties Name, Givenname, Surname, DistinguishedName, Enabled, LastLogonDate, LastLogonTimeStamp, LockedOut, msExchHomeServerName, SAMAccountName, CreateTimeStamp, Created, PasswordLastSet, Description # This line gets the total number of accounts and report it.   # It effectively counts all of the rows in the array. $StringToWrite = "Total number of AD domain accounts of all types: " + $AllAccounts.Count Add-Content $FilePathString $StringToWrite Add-Content $FilePathString "" # This line gets the total number of accounts having Exchange # mailboxes. The Where-Object performs all of the complex # interaction necessary for filtering the array - you simply # need to provide it with the filter parameters.  Note the use # of "$_", which is a shorthand reference to the object being # filtered.  Note too how Boolean equations are written.   # Boolean operators are denoted by a hyphen "-".  See the # References for additional discussion on this notation. [array]$AllMailboxUsers = $AllAccounts | Where-Object {$_.msExchHomeServerName -NotLike $NULL} $StringToWrite = "Total number of users who have email accounts: " + $AllMailboxUsers.Count Add-Content $FilePathString $StringToWrite Add-Content $FilePathString "" # This line gets the total number of administrative accounts # using the # same approach as previous.  As discussed earlier, # it assumes that admin accounts are distinguished by having # the word "Admin" in their Description field.  Other fields # may also be used - if so, use them instead. [array]$AllAdminAccounts = $AllAccounts | Where-Object {$_.Description -Like '*Admin*'} $StringToWrite = "Total number of Administrative accounts: " + $AllAdminAccounts.Count Add-Content $FilePathString $StringToWrite Add-Content $FilePathString "" # Get total number of service accounts.  Same approach as # previous. Assumes that service accounts are distinguished # by having the word "Service" in their Description field. [array]$AllServiceAccounts = $AllAccounts | Where-Object {$_.Description -Like '*Service*'} $StringToWrite = "Total number of Service accounts: " + $AllServiceAccounts.Count Add-Content $FilePathString $StringToWrite Add-Content $FilePathString "" # Get total number of accounts used for testing.  Same approach # as previous. Assumes that testing accounts are distinguished by # having the word "Testing" in their Description field. [array]$AllTestingAccounts = $AllAccounts | Where-Object {$_.Description -Like '*Testing*'} $StringToWrite = "Total number of Testing accounts: " + $AllTestingAccounts.Count Add-Content $FilePathString $StringToWrite Add-Content $FilePathString "" # Get total number of end user accounts.  Same approach as # previous, but this time the array is filtered for NOT having # certain keywords in their their Description field.   [array]$AllUserAccounts = $AllAccounts | Where-Object {($_.Description -NotLike '*Admin*') -and ($_.Description -NotLike '*Service*') -and ($_.Description -NotLike '*Testing*')} $StringToWrite = "Total number of User accounts: " + $AllUserAccounts.Count Add-Content $FilePathString $StringToWrite Add-Content $FilePathString "" # This line gets the total number of user accounts that # are enabled. [array]$AllEnabledUserAccounts = $AllUserAccounts | Where-Object {$_.Enabled -eq $True} $StringToWrite = "Total number of Enabled User accounts: " + $AllEnabledUserAccounts.Count Add-Content $FilePathString $StringToWrite Add-Content $FilePathString "" # This line gets the total number of user accounts that # are disabled. [array]$AllDisabledUserAccounts = $AllUserAccounts | Where-Object {$_.Enabled -eq $False} $StringToWrite = "Total number of Disabled User accounts: " + $AllDisabledUserAccounts.Count Add-Content $FilePathString $StringToWrite Add-Content $FilePathString "" # This line gets the total number of enabled users # accounts that have been locked out. [array]$AllEnabledLockedUserAccounts = $AllEnabledUserAccounts | Where-Object {$_.LockedOut -eq $True} $StringToWrite = "Total number of Enabled User accounts that are locked out: " + $AllEnabledLockedUserAccounts.Count Add-Content $FilePathString $StringToWrite Add-Content $FilePathString "" # This line gets the total number of enabled users # that have never logged in. [array]$AllEnabledUserAccountsNeverlogon = $AllEnabledUserAccounts | Where-Object {$_.LastLogonDate -eq $NULL} $StringToWrite = "Total number of Enabled User accounts that have never logged on: " + $AllEnabledUserAccountsNeverlogon.Count Add-Content $FilePathString $StringToWrite Add-Content $FilePathString ""

LastLogon Metrics

Here is the script to be added.  Let's look at the first metric: users who have logged in within the past 365 days.
# This line gets the number of enabled user accounts that # have logged in within the past 365 days. This time, we # filter the array using a time value, which is obtained # by subtracting 365 from the variable holding the time # value obtained at the start of this script. $365Days = $DateTime.AddDays(-365) [array]$LastLogon365EnabledUserAccounts = $AllEnabledUserAccounts | Where-Object {$_.LastLogonDate -ge $365Days} $StringToWrite = "Total number of enabled users who have logged in within the past 365 days: " + $LastLogon365EnabledUserAccounts.Count Add-Content $FilePathString $StringToWrite Add-Content $FilePathString "" test It follows the same general approach used previously. Repeat this approach for the other date categories, including: 180, 90, 45, and 30 days. $180Days = $DateTime.AddDays(-180) [array]$LastLogon180DaysEnabledUserAccounts = $AllEnabledUserAccounts | Where-Object {$_.LastLogonDate -ge $180Days} $StringToWrite = "Total number of enabled users who have logged in within the past 180 days: " + $LastLogon180DaysEnabledUserAccounts.Count Add-Content $FilePathString $StringToWrite Add-Content $FilePathString "" $90Days = $DateTime.AddDays(-90) [array]$LastLogon90DaysEnabledUserAccounts = $AllEnabledUserAccounts | Where-Object {$_.LastLogonDate -ge $90Days} $StringToWrite = "Total number of enabled users who have logged in within the past 90 days: " + $LastLogon90DaysEnabledUserAccounts.Count Add-Content $FilePathString $StringToWrite Add-Content $FilePathString "" $45Days = $DateTime.AddDays(-45) [array]$LastLogon45DaysEnabledUserAccounts = $AllEnabledUserAccounts | Where-Object {$_.LastLogonDate -ge $45Days} $StringToWrite = "Total number of enabled users who have logged in within the past 45 days: " + $LastLogon45DaysEnabledUserAccounts.Count Add-Content $FilePathString $StringToWrite Add-Content $FilePathString "" $30Days = $DateTime.AddDays(-30) [array]$LastLogon30DaysEnabledUserAccounts = $AllEnabledUserAccounts | Where-Object {$_.LastLogonDate -ge $30Days} $StringToWrite = "Total number of enabled users who have logged in within the past 30 days: " + $LastLogon30DaysEnabledUserAccounts.Count Add-Content $FilePathString $StringToWrite Add-Content $FilePathString "" $15Days = $DateTime.AddDays(-15) [array]$LastLogon15DaysEnabledUserAccounts = $AllEnabledUserAccounts | Where-Object {$_.LastLogonDate -ge $15Days} $StringToWrite = "Total number of enabled users who have logged in within the past 15 days: " + $LastLogon15DaysEnabledUserAccounts.Count Add-Content $FilePathString $StringToWrite Add-Content $FilePathString ""
Summary

This posting, the third in this series, has presented script for extracting additional Active Directory user account metrics.  It uses the LastLogonDate attribute.  The default replication frequency determines the default window of accuracy of LastLogonDate . The default replication frequency works out to be approximately 9-14 days.  This accuracy is good enough for time windows of 30, 60, 90 days, and so on, but is insufficiently accurate when seeking time windows of 1, 2, or 7 days. In a later posting, we'll explore how to improve this accuracy and thus obtain more immediate usage metrics.

References

Thursday, September 12, 2013

How to generate complex AD account metrics


PowerShell Metrics Series: Active Directory Reporting
How to generate and report basic AD account metrics
How to generate complex AD account metrics part 1
How to generate complex AD account metrics part 2
How to store AD metrics in SharePoint 2010
How to present AD metrics in a SharePoint 2010 dashboard
Introduction

In the previous posting in this series, we explored how to generate and report simple Active Directory metrics, such as total number of accounts by type and total number of accounts with mail boxes. In this posting, we will explore how to generate more complex metrics, including:
  • Total number of enabled user accounts
  • Total number of disabled user accounts
  • Total number of user accounts that have been locked out
  • Total number of enabled user accounts that have never logged on
Review

Here's the script that has been created thus far (below).  I've added additional comments to help you understand what is going on:
##################################### # Name:        AD Report Generator # Author:      [your name] # Date:        [date] # Description: ##################################### Import-module ActiveDirectory # Create the report container # --------------------------- # Save the data and time.  This date and time # will be used also for generating the report # filename. $DateTime = Get-Date # Use this date/time to generate the report file name $DateTimeFileString = $DateTime.ToString("yyyyMMddHHmmss") # Now generate the path/file string $FilePathString = "\\[YourPath]\ADReport_" + $DateTimeFileString + ".txt" # Create a new text file New-Item $FilePathString -Type File # Write the report date/time # -------------------------- # Add the date/time to the top of the file [string]$StringToWrite = $DateTime Set-Content $FilePathString $StringToWrite # and then add a couple of lines after Add-Content $FilePathString "" Add-Content $FilePathString "" # Add a header to the report # -------------------------- $StringToWrite = "AD Domain Accounts Report" Add-Content $FilePathString $StringToWrite $StringToWrite = "Generated on host " + $env:Computername + " by " + $env:UserName Add-Content $FilePathString $StringToWrite Add-Content $FilePathString "=====================================================" Add-Content $FilePathString "" Add-Content $FilePathString "" Add-Content $FilePathString ""   # Build the report # ---------------- # This next line of code interrogates AD and builds the array # that contains all accounts in AD and the desired properties.   # It effectively generates a list of accounts and their # properties that you can parse and filter as needed.  This only # needs to be performed once, for the entire report, as all of # the rest of the attention will be focused on this array. [array]$AllAccounts = Get-ADUser -Filter * -Properties Name, Givenname, Surname, DistinguishedName, Enabled, LastLogonDate, LastLogonTimeStamp, LockedOut, msExchHomeServerName, SAMAccountName, CreateTimeStamp, Created, PasswordLastSet, Description # This line gets the total number of accounts and report it.   # It effectively counts all of the rows in the array. $StringToWrite = "Total number of AD domain accounts of all types: " + $AllAccounts.Count Add-Content $FilePathString $StringToWrite Add-Content $FilePathString "" # This line gets the total number of accounts having Exchange # mailboxes. The Where-Object performs all of the complex # interaction necessary for filtering the array - you simply # need to provide it with the filter parameters.  Note the use # of "$_", which is a shorthand reference to the object being # filtered.  Note too how Boolean equations are written.   # Boolean operators are denoted by a hyphen "-".  See the # References for additional discussion on this notation. [array]$AllMailboxUsers = $AllAccounts | Where-Object {$_.msExchHomeServerName -NotLike $NULL} $StringToWrite = "Total number of users who have email accounts: " + $AllMailboxUsers.Count Add-Content $FilePathString $StringToWrite Add-Content $FilePathString "" # This line gets the total number of administrative accounts # using the # same approach as previous.  As discussed earlier, # it assumes that admin accounts are distinguished by having # the word "Admin" in their Description field.  Other fields # may also be used - if so, use them instead. [array]$AllAdminAccounts = $AllAccounts | Where-Object {$_.Description -Like '*Admin*'} $StringToWrite = "Total number of Administrative accounts: " + $AllAdminAccounts.Count Add-Content $FilePathString $StringToWrite Add-Content $FilePathString "" # Get total number of service accounts.  Same approach as # previous. Assumes that service accounts are distinguished # by having the word "Service" in their Description field. [array]$AllServiceAccounts = $AllAccounts | Where-Object {$_.Description -Like '*Service*'} $StringToWrite = "Total number of Service accounts: " + $AllServiceAccounts.Count Add-Content $FilePathString $StringToWrite Add-Content $FilePathString "" # Get total number of accounts used for testing.  Same approach # as previous. Assumes that testing accounts are distinguished by # having the word "Testing" in their Description field. [array]$AllTestingAccounts = $AllAccounts | Where-Object {$_.Description -Like '*Testing*'} $StringToWrite = "Total number of Testing accounts: " + $AllTestingAccounts.Count Add-Content $FilePathString $StringToWrite Add-Content $FilePathString "" # Get total number of end user accounts.  Same approach as # previous, but this time the array is filtered for NOT having # certain keywords in their their Description field.   [array]$AllUserAccounts = $AllAccounts | Where-Object {($_.Description -NotLike '*Admin*') -and ($_.Description -NotLike '*Service*') -and ($_.Description -NotLike '*Testing*')} $StringToWrite = "Total number of User accounts: " + $AllUserAccounts.Count Add-Content $FilePathString $StringToWrite Add-Content $FilePathString ""

Add Additional Active Directory Metrics

Below is what we will add.  The first metric to extract is the total number of enabled user accounts, and then we'll get the total number of disabled user accounts.  We already have an array that is composed of user accounts only, namely, $AllUserAccounts.  All that needs to be done is to filter this array further based upon the value of the account Enabled property, which is a Boolean.  Here again note that a single line of code is all that is needed to extract the desired metric:
# This line gets the total number of user accounts that # are enabled. [array]$AllEnabledUserAccounts = $AllUserAccounts | Where-Object {$_.Enabled -eq $True} $StringToWrite = "Total number of Enabled User accounts: " + $AllEnabledUserAccounts.Count Add-Content $FilePathString $StringToWrite Add-Content $FilePathString "" # This line gets the total number of user accounts that # are disabled. [array]$AllDisabledUserAccounts = $AllUserAccounts | Where-Object {$_.Enabled -eq $False} $StringToWrite = "Total number of Disabled User accounts: " + $AllDisabledUserAccounts.Count Add-Content $FilePathString $StringToWrite Add-Content $FilePathString ""

The next couple of metrics to explore are the total number of locked out user accounts and the number of user accounts that have never logged in:
# This line gets the total number of enabled users # accounts that have been locked out. [array]$AllEnabledLockedUserAccounts = $AllEnabledUserAccounts | Where-Object {$_.LockedOut -eq $True} $StringToWrite = "Total number of Enabled User accounts that are locked out: " + $AllEnabledLockedUserAccounts.Count Add-Content $FilePathString $StringToWrite Add-Content $FilePathString "" # This line gets the total number of enabled users # that have never logged in. [array]$AllEnabledUserAccountsNeverlogon = $AllEnabledUserAccounts | Where-Object {$_.LastLogonDate -eq $NULL} $StringToWrite = "Total number of Enabled User accounts that have never logged on: " + $AllEnabledUserAccountsNeverlogon.Count Add-Content $FilePathString $StringToWrite Add-Content $FilePathString ""

Summary

In this posting, we have explored how to generate more complex metrics.  These more complex metrics build upon the metrics already extracted previously. In the next posting, we'll complete our exploration of how to generate metrics by learning how to generate the various LastLogonDate categories typically of interest, such as 180, 90, 45, 30 and 14 day logons, to name a few.  Extracting LastLogonDate values brings real value to management and your customers, as it provides the raw data on actual system usage that management can use to more effectively perform trend analyses and justify and plan infrastructure budgets.

References