最初の CLR ルーチンを SQLServer 2008 に追加しようとしています (まもなく 2014 にアップグレードされます)。目標は、ユーザー オブジェクトを Active Directory に追加し、十数個の属性値を渡して、インターフェイスから ERP へのデータに基づいてユーザーを作成することです (インターフェイスは正常に機能し、データは適切です)。同僚が PrincipalContext をラップするコンパクトな C# クラスを作成し、実際に別の動作中のアプリケーションからコードを取得して、少し簡素化しました (以下を参照)。
CLR を有効にし、DB を TRUSTWORTHLY に設定するなどして、彼のコードと必要なリソースの CREATE ASSEMBLY を UNSAFE オプションを使用して実行することができました。これは、コードが Microsoft の精査された .NET クラスのサブセットの一部ではないためです。 SQLServer 内で実行します。
alter database Util SET TRUSTWORTHY ON
CREATE/ALTER ASSEMBLY SystemDSProtocols
FROM 'C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.DirectoryServices.Protocols.dll'
WITH PERMISSION_SET = UNSAFE
CREATE/ALTER ASSEMBLY SystemDSAccountManagement
FROM 'C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5\System.DirectoryServices.AccountManagement.dll'
WITH PERMISSION_SET = UNSAFE
CREATE/ALTER ASSEMBLY XXXXXXXXX_CLR
FROM 'C:\XXXXXXX\XXXXX\XXXXXXXX.CLR\XXXXXXXX.CLR.dll'
WITH PERMISSION_SET = UNSAFE
(すべての作成と後続の ALTER は正常に実行されます。ここで隠したカスタム クラス ライブラリ XXXXXXX_CLR を変更するたびに、最後の ALTER を変更します... CLR ストアド プロシージャは正常に作成され、ユーザーを保存しようとするまで OK を実行しますPrincipalContext オブジェクトを介して取得しているコードとエラー メッセージは次のとおりです。
このエラーに対する回答を探して 50 の Web ページを読みました。SQLserver がドメイン管理者として実行するユーザーを一時的に作成しました (開発システム - ひどい慣行だと思います)。ドメイン管理者権限を持つログイン SQL ユーザーから呼び出します。明示的な .NET AD 接続ドメイン管理者に渡す、ユーザーとパスワードのオプションを PrincipalContext への呼び出しから外す、SQLServer のユーザーまたは呼び出し元のユーザーの特権がそれを制御するかどうかを確認する、PrincipalContext コンストラクター呼び出しでオプションのさまざまな組み合わせを試す、など.
// Create PrincipalContext
PrincipalContext principalContext = null;
try
{
// as given, used Simplebind only
principalContext = new PrincipalContext(
ContextType.Domain,
LdapName, // Domain name xxxx.yyyy
StudentContainer, // ou=aaaa,ou=bbbb,dc=xxxx,dc=yyyy
ContextOptions.Negotiate
//ContextOptions.SecureSocketLayer
//ContextOptions.SimpleBind,
// | ContextOptions.Signing
| ContextOptions.Sealing,
// | ContextOptions.ServerBind
ContextUser,
ContextPassword
);
}
catch (Exception ex)
{
throw new Exception("Failed to create PrincipalContext. Exception:", ex);
}
using (principalContext)
{
using (var p = new MaricopaUserPrincipal(principalContext))
{
p.SamAccountName = xxxxUserId;
p.Name = xxxxUserName;
....残りの属性について....これは、FIM およびその他の C# ミドルウェア libary 呼び出しを使用して何年にもわたって行ってきました。詳細は無視してください...渡すパラメーターでカバーされた正しい AD 属性が確実にあります。しかし、ここですべてを公開したくはありません。
したがって、ここに常に表示されるエラーメッセージがあります(クラスライブラリCLR内に他の属性検証の問題があったため、C#CLRコードを正常に実行していることはわかっていますが、最終的にPrincipalContextへの呼び出しを行うところまで来て失敗しましたそこの):
Msg 6522, Level 16, State 1, Procedure sp_XXXXXAddXXXXX_CLR, Line 0
A .NET Framework error occurred during execution of user-defined routine or aggregate "sp_XXXXXAddXXXXX_CLR":
System.Exception: Could not save user principal. Exception: ---> System.UnauthorizedAccessException: General access denied error
System.UnauthorizedAccessException:
at System.DirectoryServices.AccountManagement.ADStoreCtx.Insert(Principal p)
at System.DirectoryServices.AccountManagement.Principal.Save()
at XXXXXXX.CLR.xxxxxManager.CreateUser(String xxxxUserId, String xxxxUserName, ...other params follow)
System.Exception: at XXXXXXX.CLR.xxxxxManager.CreateUser(String xxxxUserId, String xxxxUserName, ...other params follow)
Windows ID の「なりすまし」についていくつか読みましたが、関連するすべてのサービスがドメイン管理者特権として実行されているときに、AD で PrincipalContext 呼び出しを実行することさえできない場合、なぜそれが必要なのか理解できません。私はそのアプローチを実際には使用できないことを知っています (セキュリティ非スターター) が、それが機能しない理由と、ここで試してみるべき代替手段を知りたいと思います。実行しているサービス アカウントをドメイン管理者グループ BTW に配置した後、SQLServer をバウンスしました。
この長ったらしい問題の親切なレビューに感謝します。