I ***absolutely*** do not recommend
setting legacyExchangeDN this way.
It is absolutely critical that the LEDN be unique in the
ORG and there is no attempt verify that uniqueness. Best to just let the
RUS set it as you don't need to. If you absolutely want to do it, I would
recommend querying any DCs being used by any RUS instances to verify the LEDN
value is unique. As a person stuck trying to find why certain things are working
in squirrely ways in Exchange, duped LEDN's is a very popular reason.
The only objects I can think of that you must create the
LEDN for if creating through a script are Query Based DLs. Interestingly enough,
MS has no mechanism for creating mail enabled Query Based DLs, I bugged this
with MS last year. On top of that, doing the method I mentioned below won't work
with them as well because the RUS won't populate many of the values so you have
to populate most of the info yourself, but again, LEDN is critical to get right.
I would also recommend against setting the mail addresses
as well and let the recipient policies handle it.
joe
From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Alain Lissoir
Sent: Wednesday, May 18, 2005 11:34 AM
To: [email protected]
Subject: RE: [ActiveDir] Least Privilege User Account Provisioning for AD AND Exchange
Yes, you can script it with a pure ADSI code initializing
required attributes.
It is true that MS doesn't support this method as only the
CDOEXM way is supported.
You can find details at http://www.lissware.net , White
Papers section, Part 2 - The powerful combination of WSH and ADSI under Windows
2000 (Script Kit).
See Sample 20 Enabling E-Mail on object for Exchange 2000
with ADSI.
Code can create the mailbox-enabled definition and/or
mail-enable a trustee (group or user).
You can also refer to http://www.exchangeadmin.com/Articles/Index.cfm?ArticleID=38190 for
more info about mailbox security as it is often the next question after
provisionning the mailbox in AD (only if you have Windows IT Pro
subscription).
Note that creating the mailbox definition in AD with ADSI
does not create the mailbox. It gets created in the store when the first message
is received or when the user connects the first time.
That's for the code logic. Now regarding the rights the
initialize these attributes, they rely on the default Exchange and AD security
(which can always be tweaked but it is not trivial).
Code excerpt:
.:
.:
.:
14:Option Explicit
15:
16:Const NO_CREATE_MB = 0
17:Const CREATE_MB = 1
18:
19:' ------------------------------------------------------------------------------------------
20:Private Sub EnableEmailAddress (objObject, _
21: strExchangeComputer, _
22: strOrganization, _
23: strExchangeAdminGroup, _
24: strExchangeStorageGroup, _
25: strExchangeMailboxStore, _
26: boolMB)
..:
45: Set ObjRoot = GetObject("LDAP://RootDSE")
46: strRootDomainNC = objRoot.Get("RootDomainNamingContext")
47: strConfigNC = ObjRoot.Get("configurationNamingContext")
..:
51: ' ----------------------------------------------------------------------------------
52: Set objRootDomainNC = GetObject("LDAP://" & strRootDomainNC)
53:
54: ' Retrieve a constructed property, so 1st we do a GetInfoEx
55: objRootDomainNC.GetInfoEx Array("canonicalName"), 0
56: strRootDNSDomainName = objRootDomainNC.Get("canonicalName")
57: ' Remove the / at the end
58: strRootDNSDomainName = Mid (strRootDNSDomainName, 1, Len(strRootDNSDomainName) - 1)
..:
63: ' Build the path with the Microsoft Exchange organization path
64: strOrganizationDN = "CN=" & strOrganization & _
65: ",CN=Microsoft Exchange,CN=Services," & strConfigNC
66:
67: ' ----------------------------------------------------------------------------------
68: Select Case objObject.Class
69: Case "user"
70: strRecipient = EliminateSpaces (LCase (objObject.FirstName) & _
71: "." & LCase (objObject.LastName))
72: ' Set the Alias name
73: objObject.put "mailNickName", strRecipient
74:
75: ' Build the SMTP Address
76: strSMTPAddress = strRecipient & "@" & strRootDNSDomainName
77: ' Build the X400 Address
78: strX400Address = "c=" & strCountry & _
79: ";a= " & _
80: ";p=" & Left (strOrganization, 16) & _
81: ";o=Exchange" & _
82: ";s=" & Lcase (objObject.LastName) & _
83: ";g=" & Lcase (objObject.FirstName) & _
84: ";"
85:
86: ' Set in which GAL to show the user
87: strDefaultGAL = "CN=Default Global Address List," & _
88: "CN=All Global Address Lists,CN=Address Lists Container," & _
89: strOrganizationDN
90: objObject.PutEx ADS_PROPERTY_UPDATE, "showInAddressBook", _
91: Array(strDefaultGAL)
92:
93: ' Set the legacy Exchange distinguished name of the created user
94: strLegacyExchangeDN = "/o=" & strOrganization & _
95: "/ou=" & strExchangeAdminGroup & _
96: "/cn=Recipients/cn=" & strRecipient
97:
98: Case "group"
99: strRecipient = EliminateSpaces (objObject.Get ("sAMAccountName"))
100:
101: ' Set the Alias name
102: objObject.put "mailNickName", strRecipient
103:
104: ' Build the SMTP Address
105: strSMTPAddress = strRecipient & "@" & strRootDNSDomainName
106: ' Build the X400 Address
107: strX400Address = "c=" & strCountry & _
108: ";a= " & _
109: ";p=" & Left (strOrganization, 16) & _
110: ";o=Exchange" & _
111: ";s=" & strRecipient & _
112: ";"
113:
114: ' Set in which GAL to show the group
115: strDefaultGAL = "CN=Default Global Address List," & _
116: "CN=All Global Address Lists,CN=Address Lists Container," & _
117: strOrganizationDN
118: strGroupGAL = "CN=All Groups,CN=All Address Lists," & _
119: "CN=Address Lists Container," & _
120: strOrganizationDN
121: objObject.PutEx ADS_PROPERTY_UPDATE, "showInAddressBook", _
122: Array(strGroupGAL, strDefaultGAL)
123:
124: ' Set the legacy Exchange distinguished name of the created group
125: strLegacyExchangeDN = "/o=" & strOrganization & _
126: "/ou=" & strExchangeAdminGroup & _
127: "/cn=Recipients/cn=" & strRecipient
...:
131: End Select
132:
133: objObject.PutEx ADS_PROPERTY_UPDATE, "proxyAddresses", _
134: Array("X400:" & strX400Address, "SMTP:" & strSMTPAddress)
135:
136: ' Other LDAP value with X400 address
137: objObject.put "textEncodedORAddress", strX400Address
138:
139: ' Other LDAP value with SMTP Address
140: objObject.put "mail", strSMTPAddress
141:
142: objObject.put "msExchHideFromAddressLists", False
143:
144: objObject.put "legacyExchangeDN", strLegacyExchangeDN
145:
146: objObject.SetInfo
147:
148: ' ----------------------------------------------------------------------------------
149: If (objObject.Class = "user" And boolMB) Then
150: objObject.put "mDBUseDefaults", True
151:
152: strHomeMTA = "CN=Microsoft MTA,CN=" & strExchangeComputer & _
153: ",CN=Servers,CN=" & strExchangeAdminGroup & _
154: ",CN=Administrative Groups," & strOrganizationDN
155: objObject.put "HomeMTA", strHomeMTA
156:
157: strHomeMDB = "CN=" & strExchangeMailboxStore & ",CN=" & _
158: strExchangeStorageGroup & _
159: ",CN=InformationStore,CN=" & strExchangeComputer & _
160: ",CN=Servers,CN=" & strExchangeAdminGroup & _
161: ",CN=Administrative Groups," & strOrganizationDN
162: objObject.put "HomeMDB", strHomeMDB
163:
164: ' Set the Exchange Home server of the created user
165: strExchangeComputerDN = "/o=" & strOrganization & _
166: "/ou=" & strExchangeAdminGroup & _
167: "/cn=Configuration/cn=Servers/cn=" & _
168: strExchangeComputer
169: objObject.put "msExchHomeServerName", strExchangeComputerDN
170: objObject.SetInfo
171:
172: Wscript.Echo " Successfully created Microsoft " & _
173: "Exchange 2000 Mailbox for user '" & _
174: objObject.Get ("cn") & "'."
175:
176: ' -------------------------------------------------------------------------------
177: ' Create the Exchange 2000 Security Descriptor
178: SetSD objObject, _
179: Array ("Self", _
180: ADS_ACETYPE_ACCESS_ALLOWED, _
181: RIGHT_MB_READ_PERMISSIONS Or _
182: RIGHT_MB_FULL_MB_ACCESS Or _
183: RIGHT_MB_SEND_AS, _
184: CONTAINER_INHERIT_ACE), _
185: MB_OBJECT
186: Else
187: ' If mail-enabled object, initialize targetAddress with the SMTP Address
188: objObject.put "targetAddress", "SMTP:" & strSMTPAddress
189:
190: ' Make this for the X400 address if necessary (instead of SMTP:)
191: ' objObject.put "targetAddress", "X400:" & strX400Address
192: objObject.SetInfo
193:
194: Wscript.Echo " Successfully enabled Microsoft Exchange 2000 E-Mail for '" & _
195: objObject.Get ("cn") & "'."
196:
197: End If
198:
199:End Sub
...:
...:
...:
14:Option Explicit
15:
16:Const NO_CREATE_MB = 0
17:Const CREATE_MB = 1
18:
19:' ------------------------------------------------------------------------------------------
20:Private Sub EnableEmailAddress (objObject, _
21: strExchangeComputer, _
22: strOrganization, _
23: strExchangeAdminGroup, _
24: strExchangeStorageGroup, _
25: strExchangeMailboxStore, _
26: boolMB)
..:
45: Set ObjRoot = GetObject("LDAP://RootDSE")
46: strRootDomainNC = objRoot.Get("RootDomainNamingContext")
47: strConfigNC = ObjRoot.Get("configurationNamingContext")
..:
51: ' ----------------------------------------------------------------------------------
52: Set objRootDomainNC = GetObject("LDAP://" & strRootDomainNC)
53:
54: ' Retrieve a constructed property, so 1st we do a GetInfoEx
55: objRootDomainNC.GetInfoEx Array("canonicalName"), 0
56: strRootDNSDomainName = objRootDomainNC.Get("canonicalName")
57: ' Remove the / at the end
58: strRootDNSDomainName = Mid (strRootDNSDomainName, 1, Len(strRootDNSDomainName) - 1)
..:
63: ' Build the path with the Microsoft Exchange organization path
64: strOrganizationDN = "CN=" & strOrganization & _
65: ",CN=Microsoft Exchange,CN=Services," & strConfigNC
66:
67: ' ----------------------------------------------------------------------------------
68: Select Case objObject.Class
69: Case "user"
70: strRecipient = EliminateSpaces (LCase (objObject.FirstName) & _
71: "." & LCase (objObject.LastName))
72: ' Set the Alias name
73: objObject.put "mailNickName", strRecipient
74:
75: ' Build the SMTP Address
76: strSMTPAddress = strRecipient & "@" & strRootDNSDomainName
77: ' Build the X400 Address
78: strX400Address = "c=" & strCountry & _
79: ";a= " & _
80: ";p=" & Left (strOrganization, 16) & _
81: ";o=Exchange" & _
82: ";s=" & Lcase (objObject.LastName) & _
83: ";g=" & Lcase (objObject.FirstName) & _
84: ";"
85:
86: ' Set in which GAL to show the user
87: strDefaultGAL = "CN=Default Global Address List," & _
88: "CN=All Global Address Lists,CN=Address Lists Container," & _
89: strOrganizationDN
90: objObject.PutEx ADS_PROPERTY_UPDATE, "showInAddressBook", _
91: Array(strDefaultGAL)
92:
93: ' Set the legacy Exchange distinguished name of the created user
94: strLegacyExchangeDN = "/o=" & strOrganization & _
95: "/ou=" & strExchangeAdminGroup & _
96: "/cn=Recipients/cn=" & strRecipient
97:
98: Case "group"
99: strRecipient = EliminateSpaces (objObject.Get ("sAMAccountName"))
100:
101: ' Set the Alias name
102: objObject.put "mailNickName", strRecipient
103:
104: ' Build the SMTP Address
105: strSMTPAddress = strRecipient & "@" & strRootDNSDomainName
106: ' Build the X400 Address
107: strX400Address = "c=" & strCountry & _
108: ";a= " & _
109: ";p=" & Left (strOrganization, 16) & _
110: ";o=Exchange" & _
111: ";s=" & strRecipient & _
112: ";"
113:
114: ' Set in which GAL to show the group
115: strDefaultGAL = "CN=Default Global Address List," & _
116: "CN=All Global Address Lists,CN=Address Lists Container," & _
117: strOrganizationDN
118: strGroupGAL = "CN=All Groups,CN=All Address Lists," & _
119: "CN=Address Lists Container," & _
120: strOrganizationDN
121: objObject.PutEx ADS_PROPERTY_UPDATE, "showInAddressBook", _
122: Array(strGroupGAL, strDefaultGAL)
123:
124: ' Set the legacy Exchange distinguished name of the created group
125: strLegacyExchangeDN = "/o=" & strOrganization & _
126: "/ou=" & strExchangeAdminGroup & _
127: "/cn=Recipients/cn=" & strRecipient
...:
131: End Select
132:
133: objObject.PutEx ADS_PROPERTY_UPDATE, "proxyAddresses", _
134: Array("X400:" & strX400Address, "SMTP:" & strSMTPAddress)
135:
136: ' Other LDAP value with X400 address
137: objObject.put "textEncodedORAddress", strX400Address
138:
139: ' Other LDAP value with SMTP Address
140: objObject.put "mail", strSMTPAddress
141:
142: objObject.put "msExchHideFromAddressLists", False
143:
144: objObject.put "legacyExchangeDN", strLegacyExchangeDN
145:
146: objObject.SetInfo
147:
148: ' ----------------------------------------------------------------------------------
149: If (objObject.Class = "user" And boolMB) Then
150: objObject.put "mDBUseDefaults", True
151:
152: strHomeMTA = "CN=Microsoft MTA,CN=" & strExchangeComputer & _
153: ",CN=Servers,CN=" & strExchangeAdminGroup & _
154: ",CN=Administrative Groups," & strOrganizationDN
155: objObject.put "HomeMTA", strHomeMTA
156:
157: strHomeMDB = "CN=" & strExchangeMailboxStore & ",CN=" & _
158: strExchangeStorageGroup & _
159: ",CN=InformationStore,CN=" & strExchangeComputer & _
160: ",CN=Servers,CN=" & strExchangeAdminGroup & _
161: ",CN=Administrative Groups," & strOrganizationDN
162: objObject.put "HomeMDB", strHomeMDB
163:
164: ' Set the Exchange Home server of the created user
165: strExchangeComputerDN = "/o=" & strOrganization & _
166: "/ou=" & strExchangeAdminGroup & _
167: "/cn=Configuration/cn=Servers/cn=" & _
168: strExchangeComputer
169: objObject.put "msExchHomeServerName", strExchangeComputerDN
170: objObject.SetInfo
171:
172: Wscript.Echo " Successfully created Microsoft " & _
173: "Exchange 2000 Mailbox for user '" & _
174: objObject.Get ("cn") & "'."
175:
176: ' -------------------------------------------------------------------------------
177: ' Create the Exchange 2000 Security Descriptor
178: SetSD objObject, _
179: Array ("Self", _
180: ADS_ACETYPE_ACCESS_ALLOWED, _
181: RIGHT_MB_READ_PERMISSIONS Or _
182: RIGHT_MB_FULL_MB_ACCESS Or _
183: RIGHT_MB_SEND_AS, _
184: CONTAINER_INHERIT_ACE), _
185: MB_OBJECT
186: Else
187: ' If mail-enabled object, initialize targetAddress with the SMTP Address
188: objObject.put "targetAddress", "SMTP:" & strSMTPAddress
189:
190: ' Make this for the X400 address if necessary (instead of SMTP:)
191: ' objObject.put "targetAddress", "X400:" & strX400Address
192: objObject.SetInfo
193:
194: Wscript.Echo " Successfully enabled Microsoft Exchange 2000 E-Mail for '" & _
195: objObject.Get ("cn") & "'."
196:
197: End If
198:
199:End Sub
...:
...:
...:
From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of joe
Sent: Wednesday, May 18, 2005 8:16 AM
To: [email protected]
Subject: RE: [ActiveDir] Least Privilege User Account Provisioning for AD AND Exchange
Grrr.
I certainly should be able to. Well... I actually can, I
just have to then separately delegate it back to Exchange again since they are
currently in "Public Information" and that is what Exchange delegates.
joe
From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Coleman, Hunter
Sent: Wednesday, May 18, 2005 11:10 AM
To: [email protected]
Subject: RE: [ActiveDir] Least Privilege User Account Provisioning for AD AND Exchange
You probably also put mailNickname and homeMDB in a custom
property set :-)
From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of joe
Sent: Wednesday, May 18, 2005 8:55 AM
To: [email protected]
Subject: RE: [ActiveDir] Least Privilege User Account Provisioning for AD AND Exchange
Depending on what documentation you read, MS does not
support mailbox enabling of users outside of the GUI or CDOEXM interfaces. Both
of which require Exchange View Access.
That being said... Let me tell you how to do it without
Exchange View Access at least on Exchange 2003.
I have found that you truly only need to set a couple of
attributes on a user to get the RUS to kick in and mailbox enable a user. You
have to set mailNickname and one of the following three attributes (homeMTA,
homeMDB, msExchHomeServerName).
The RUS will take it from there.
From the sound of it, you will want to set mailNickname and
homeMDB so you can specify the exact store, note you need to know the URL of the
store, that is what the Exchange View Access is used to figure out.
So short and sweet, delegate
WP mailNickname
WP homeMDB
WP homeMDB
and have at it.
If you fill out those two attributes, the RUS should "kick
in" and mailbox enable the object.
joe
From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Frost, David: #CIO-BPI
Sent: Wednesday, May 18, 2005 10:09 AM
To: [email protected]
Subject: [ActiveDir] Least Privilege User Account Provisioning for AD AND Exchange
I have a scenario I
need to explore where the ability to create and modify the AD user account and
associated Exchange (2003)mailbox creation is delegated out to 1st and 2nd
line service desk personnel. It is not desirable t have 1 and 2 LS staff
using native tools such as ADUC or Exchange System
Manager. I have been able to successfully lock down the AD
account creation permissions and script the process in such a way to reduce the
possibility of data entry errors and provide consistent data.
The sticky issue
comes with the requirement to have the exchange mailbox assigned. It
appears from most of the reading I have done, the users who create the mailbox
enabled user account must be a member of Exchange View-only
Administrators. This is even less desirable than allowing them to use ADUC
or ESM. Then there is the issue of assigning the new user to the correct
Exchange server/storage group/mailbox store to ensure proper
loading.
So My
questions;
Is there a way to
script the creation of a mailbox enabled user account in such a way as to not
use ADUC and/or ESM AND not be a member of Exchange View-only admins? How
to handle the Server/Storage Group/Mailbox Store selection?
Is there a COTS tool
for (simple) account provisioning that a) is "cheap and cheerful", b)
does not require either a full blown meta-directory or connection to an HR
system be implemented (see point a) ; that will allow for service desk
operators to create and manage user accounts?
David
Frost
Directory Engineering - Messaging Directories and
PKI
Industry Canada
(613) 957-8442
email [EMAIL PROTECTED]
