January, 2012 - フィールドSEあがりの安納です - Site Home - TechNet Blogs

フィールドSEあがりの安納です

Microsoft Evangelist -- Junichi Anno

January, 2012

  • 【PowerShell】WEB ページをアーカイブする

    ちょっと必要に迫られて調べただけなので、中途半端な情報ですみません。役に立つ方がいらっしゃるかもしれないので投稿しておきます。

    WEB サイトの移行や廃棄等で、既存のページのバックアップを取っておきたい場合があります。それも、大量にあるので出来る限り自動化したいという。

    方法はいくつかあるのですが、代表的な方法として2つ考えられます。

    ※ここでは再現性の高い MHT 形式で保存するものとします。

    1. CDO.Message を使用する

    いにしえの方法で、こなれた感じではありますが、正直なところ出力結果に難ありです。

    例えば、Tech Fielders サイトで公開されている、Windows Intune 利用時に知っておくべき Proxy Server 環境設定 | Tech Fielders コラム(三井情報株式会社 後藤 諭史 さん)を保存してみます。

    $url = "http://www.microsoft.com/japan/powerpro/TF/column/sg_01_1.mspx"
    $filename = "c:\tmp\tf\sg_01_1.mht"
    $cdo = New-Object -ComObject "CDO.Message"
    $n = $cdo.CreateMHTMLBody( $url, 0, "", "")
    $objStm = $cdo.GetStream()
    $objStm.SaveToFile( $filename,  2)

    実行結果は以下の通りです。読めなくはないですが、レイアウト的に微妙な感じですよねぇ。

    image

    ちなみに、CreateMHTMLBody メソッドの第二パラメタ「0」は、指定したURLの全てのコンテンツをダウンロードすることを示しています。

    (参考)CdoMHTMLFlags Enum

    また、SaveToFile に指定している 2 は $filename が存在している場合に上書きすることを示しています。1 を指定すると、同じファイルが存在する場合にエラーとなります。

    2. IE の ExecWB を使用する

    この方法は、IE で「ページを名前を付けて保存する」をスクリプトから実行するものです。IE から GUI を操作して保存した場合とまったく同じ結果を得ることができるため、結果の品質は申し分ありません。

    ただ、問題がちょっとだけあります。それは、「名前を付けて保存」を自動化することができないということです。

    以下のスクリプトの最終行に書かれている、ExecWB(4,0,$null,[ref]$null) は IE の「名前を付けて保存」ダイアログを呼び出すためのメソッドです。「4」が「名前を付けて保存」を意味しています。第二パラメタには「0」を指定していますが、「2」を指定するとプロンプトを表示しないで実行ができるはずなのです...が、どうもうまくいかない...ということで、だったらダイアログ操作を自動的にやってしまうことにしました。

    $url = "http://www.microsoft.com/japan/powerpro/TF/column/sg_01_1.mspx"
    $code = '$WShell = New-Object -comobject WScript.Shell; '
    $code = $code + '$WShell.AppActivate(''Web ページの保存'', $true); '
    $code = $code + '$WShell.SendKeys(''%T'') ; '
    $code = $code + '$WShell.SendKeys(''{DOWN}'') ; '
    $code = $code + '$WShell.SendKeys(''{DOWN}'') ; '
    $code = $code + '$WShell.SendKeys(''{ENTER}'') ; '
    $code = $code + '$WShell.SendKeys(''%N'') ; '
    $code = $code + '$WShell.SendKeys(''{HOME}'') ; '
    $code = $code + '$WShell.SendKeys(''C:\TMP\TF\'') ; '
    $code = $code + '$WShell.SendKeys(''%S'')'
    $ie = New-Object -ComObject InternetExplorer.Application
    $ie.Navigate( $url )
    while ($ie.ReadyState -ne 4) { Start-Sleep -Milliseconds 100}
    Start-Process powershell.exe -argument ('-version 2.0 -noprofile -windowstyle hidden -command "{0}"' -f $code)
    $ie.ExecWB(4,0,$null,[ref]$null)

    コードをご覧いただいてもわかるように、ちょっと特殊なことというか...古臭いことをしています。

    Windows Script 時代からスクリプトを使っていた方ならばご存じの、SendKeys メソッドです。

    (参考)Converting the Windows Script Host SendKeys Method

    事前に、$code に WScript.Shell を使用した SendKyes メソッドを埋め込んでおきます。そして、ExecWB を実行する直前で、Start-Process コマンドレットを使ってスクリプトを実行しています。

    こうすることで、ExecWB によって表示されたダイアログを SendKeys メソッドで操作することができます。

    image

    今回は Windows Script を使用しましたが、.NET Framework らしく [System.Windows.Forms.SendKeys] を使うこともできます。ただ、これだとコードが見づらくなってしまうので、個人的にはあまり好きじゃありません。

    ちなみに、「名前を付けて保存」の便利なところは、ファイル名として自動的にWEBページのタイトルを使用してくれるところです。そのため、ファイル名の指定にも SendKey を使用するといった面倒なことをする必要がありません。

    この他 WORD に読み込んで保存するなど方法はいくつかありますが、出力結果を比較すると、やはり ExecWB がベターかなといった感じです。

  • 【IDM】AD FS で既存のクレームルールセットをバックアップするには

    前回以下の投稿をしました。

    【IDM】AD FS で Event ID 323、364 が発生して認可されない場合の対処

    この投稿に関連し、既存のクレームルールセットをバックアップする方法についても紹介しておきます。クレームルールは大切なリソースですから、変更の前には必ずバックアップするようにしましょう。

    AD FS には PowerShell 用コマンドレットが大量に用意されており、それらを使えばバックアップなんて簡単です。

    AD FS 2.0 Cmdlets in Windows PowerShell

    クレームルールセットを取得できるのは、以下の2つです。

    • Get-ADFSClaimsProviderTrust
      :要求プロバイダー信頼に関する情報の取得
    • Get-ADFSRelyingPartyTrust
      :証明書利用者信頼(RP)に関する情報の取得

    いずれのコマンドレットも、出力のフォーマットは同様です。今回は、Get-ADFSClaimsProviderTrust を使用してみます。

    PowerShell コンソールを開き、 以下のコマンドレットで AD FS スナップインを読み込んでください。

    PS C:\>Add-PSSnapin Microsoft.Adfs.Powershell

    要求プロバイダー名が "Active Directory" であれば、以下のようにして要求プロバイダーの情報を取得することができます。

    PS C:\> Get-ADFSClaimsProviderTrust -Name "Active Directory"

    出力結果の中に AcceptanceTransformRules というプロパティが用意されていますが、これがクレームルールセットです。

    image

    そこで、以下のように入力すると、以下のように、クレームルールセットのみを取得することができます。

    PS C:\> $cp = Get-ADFSClaimsProviderTrust -Name "Active Directory"
    PS C:\> $cp.AcceptanceTransformRules

    @RuleTemplate = "PassThroughClaims"
    @RuleName = "Pass through all Name claims"
    c:[Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", Issuer
    =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"]
    => issue(claim = c);

    @RuleTemplate = "PassThroughClaims"
    @RuleName = "Pass through all Primary SID claims"
    c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid"
    , Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"]
    => issue(claim = c);

    @RuleTemplate = "PassThroughClaims"
    @RuleName = "Pass through all Group SID claims"
    c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid",
    Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"]
    => issue(claim = c);

    @RuleTemplate = "PassThroughClaims"
    @RuleName = "Pass through all Primary group SID claims"
    c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/primarygrou
    psid", Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"]
    => issue(claim = c);

    @RuleTemplate = "PassThroughClaims"
    @RuleName = "Pass through all Deny only group SID claims"
    c:[Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/denyonlysid",
    Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"]
    => issue(claim = c);

    @RuleTemplate = "PassThroughClaims"
    @RuleName = "Pass through all Deny only primary SID claims"
    c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlypri
    marysid", Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"]
    => issue(claim = c);

    @RuleTemplate = "PassThroughClaims"
    @RuleName = "Pass through all Deny only primary group SID claims"
    c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlypri
    marygroupsid", Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"]
    => issue(claim = c);

    @RuleTemplate = "PassThroughClaims"
    @RuleName = "Pass through all Authentication method claims"
    c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticat
    ionmethod", Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"]
    => issue(claim = c);

    @RuleTemplate = "PassThroughClaims"
    @RuleName = "Pass through all Authentication time stamp claims"
    c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticat
    ioninstant", Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"]
    => issue(claim = c);

    あとは、単純にテキストファイルに出力結果をリダイレクトすれば OK です。

    PS C:\> $cp = Get-ADFSClaimsProviderTrust -Name "Active Directory"
    PS C:\> $cp.AcceptanceTransformRules > crs.bak

    超簡単ですね。そして、Windows PowerShell って素敵ですね。

  • 生涯エバンジェリストでありつづけることは難しいことです

    マイクロソフトに「テクノロジー エバンジェリスト」として入社する人間は、方向性に差はあるものの、それぞれに IT への強い思い入れを持っています。

    技術を愛していることは言わずもがな、それによって IT 業界を変えられると真剣に信じています。

    しかし大きな夢はプレッシャーでもあります。限界を感じることもあり、夢半ばで離脱される方も少なくありません。

    今年入社5年となる私も、暗闇の中でいつ限界が来るのだろうかと考えることがあります。私だけではないはずです。周囲の全員がそうでしょう。

    祓いきれないプレッシャーを抱える我々の心の支えは、間違いなく偉大なる先輩方です。

    既にご存知の方も多いと思いますが、2012年1月20日、エバンジェリストである 川西 裕幸 さんがお亡くなりになりました。

    私の UX & Client プラットフォーム推進部への移動によって、2011年7月、より近しい存在となった 川西 さんは、偉大なる大先輩の1人でした。

    正論を吐き続けるだけでは、長い年月をエバンジェリストであり続け、かつ社内外からの高い評価を維持し続けることはできません。ニューテクノロジーに詳しいだけでは言葉が軽くなります。

    言葉の重みは歴史の重みでもあります。

    川西さんの言葉や文章には、間違いなく重みがありました。

    テクノロジーの歴史を未来に向けて紡ぐことができる、稀有なエバンジェリストでした。

    私たちエバンジェリストは、まだまだ川西さんから学ぶべきことが多くありました。

    それだけに川西さんの訃報が残念でなりません。

    いまはただ、川西さんのご冥福をお祈りします。

    川西 裕幸のブログ
    http://blogs.msdn.com/b/hiroyuk/

    Facebook
    https://www.facebook.com/profile.php?id=721589565&ref=tn_tnmn#!/profile.php?id=100002542766076

  • 【WP for IT Pros】Windows Phone のセキュリティモデル 1 ~「チャンバー」という考え方(1)

    Windows Phone のセキュリティモデルについて断片ばかりで系統的に語ったことが無かったので、あらためて。

    参考:Download: Windows Phone 7.5 IT Papers - Microsoft Download Center - Download Details

    以下の図は、Windows Phone のセキュリティモデルを模式的に表したものです。

    image

    Windows Phone のセキュリティモデルは「分離の原則」と「最小限の権限」という思想のもとに設計されており、「チャンバー」と呼ばれるコンセプトに沿って実装されています。

    ここで言う「チャンバー」とは、心室や心房などのように仕切られた部屋を意味しています。Windows Phone 上で動作するアプリケーションやドライバーは、必ずいずれかのチャンバーに隔離され、チャンバーごとに定義されたアクセス権限のみを行使することができます。これにより Windows Phone で動作するアプリケーションの独立性と必要最小限のパーミッションによる動作が保障されています。

    チャンバーはセキュリティポリシーの定義によって以下の4つのタイプに分けられています。

    TCB(Trusted Computing Base)チャンバー image

    最も高度な権限を持ったチャンバー。Windows Phone 内のリソースの大部分に無制限にアクセスすることができる。TCB チャンバーはポリシーを変更したり、セキュリティモデルを強制することができる。カーネルとカーネルモードドライバーは TCB チャンバー内で動作する。TCBチャンバー内で動作するアプリケーションを最小限に抑えることが Windows Phone へのアタック面を最小限に減らすことになる重要な要素である。マイクロソフトだけがTCBチャンバーにアプリケーションを追加できる。

    ERC(Elevated Rights Chamber)

    セキュリティポリシーを除く全てのリソースにアクセス可能なチャンバー。ERC は、他の Windows Phone アプリが使用する機能を提供するサービスやユーザーモードドライバを対象にしている。マイクロソフトだけが ERC にソフトウェアを追加することができる。

    SRC(Standard Rights Chamber)

    SRCはプリインストールアプリケーションに与えられる既定のチャンバーである。デバイス全体に影響するサービスを提供するアプリを除き、すべてのプリインストールアプリケーションはSRCで動作する。マイクロソフトの OUTLOOK Mobile 2010 はこのタイプのアプリの例である。

    LPC(Least Privileged Chamber)

    LPC はマイクロソフト以外のアプリ開発者が Marketplace を通して提供できるアプリケーションに与えられる既定のチャンバーである。このチャンバー内に存在するアプリケーションは、分離ストレージへのアクセスを含めた最小限の権限を持っている。チャンバー内で動作するアプリケーションは他のアプリケーションのメモリ領域やストレージなどにアクセスすることはできない。

    以下につづく

     【WP for IT Pros】Windows Phone のセキュリティモデルについて~「チャンバー」という考え方(2)

  • 【WP for IT Pros】Windows Phone のセキュリティモデル 2 ~「チャンバー」という考え方(2)

    前回は「チャンバー」の概念についてお話ししました。

    【WP for IT Pros】Windows Phone のセキュリティモデルについて~「チャンバー」という考え方(1)

    今回は、その補足的な内容となるのですが、「機能ベースの権限モデル」と「サンドボックス」について書きます。

    ■ 機能(Capabilities)ベースの権限モデル

    「機能」とは別の言い方をすれば「リソース」です。Windows Phone にはさまざまな機能が実装されており、「位置情報」「カメラ」「マイク」「ネットワーク」「センサー」などが「機能」に該当します。これらの機能は、Windows Phone の使い方と密接に関連していることは言うまでもありませんが、機能こそが「ユーザープライバシー」「セキュリティ」「コスト」「ビジネスに関する考慮事項念」などに影響を与えることになります。

    既に述べたように、LPC(Least Privileged Chamber)には規定で必要最小限のアクセス権限が与えられています。しかし、だからといって LPC 内のアプリケーションがそれ以上の機能を使用できないわけではありません。例えば LPC 内のアプリケーションが「カメラ」機能を使用する必要がある場合には、アプリケーションのインストール中に「カメラ」へのアクセスがユーザーに打診されます。ユーザーがそれを承認すれば、アプリケーションはカメラ機能を使用することができるようになります。ただし、こうした権限の昇格はアプリケーションの実行中に与えられることは無く、かならずアプリケーションを使い始める前に承認される必要があります。

    このようにして、LPC はダイナミックに「機能」によってによって権限が拡張されます。これを「機能ベースの権限モデル」と呼びます。

    機能ベースの権限モデルには、以下のような利点が挙げられます。

    - アタック面の最小化

    それぞれのアプリケーションは、その動作に必要最小限の「機能」のみを使用する。攻撃の対象はそれらの機能に付随することになるが、逆に言えばその範囲に留まるということでもある。

    - ユーザーの承諾と制御

    それぞれのアプリケーションが利用者に対して、どのような機能を使用するのかを提示する義務を負う。規定では、以下に示す場所とタイミングで使用する機能を提示しなければならない。

      • Windows Phone Marketplace 内のアプリケーション詳細説明ページ
      • アプリケーションの購入画面
      • アプリケーションを最初に使用するとき

    アプリケーションの開発者は、Windows Phone の開発ツールを使用して、機能リストを作成する必要があります。機能リストはアプリケーションパッケージの WMAppManifest.xml ファイルに格納されます。

    image

    ■ サンドボックス

    Windows phone の全てのアプリケーションが、それぞれの分離したチャンバーの中で事前に定義された機能とともに動作することは既に述べたとおりです。

    このとき、必要最小限の権限が全てのアプリケーションに与えられますが、その中には「分離ストレージ」へのアクセス権も含まれています。アプリケーション間には、クラウド等の外部デバイスを除き、いかなる通信チャネルも存在していません。アプリケーションは互いに完全に分離されており、当然のことながら互いのメモリやデータにアクセスすることもきません。これにはキーボードのキャッシュも含まれています。

    image

    加えて、Windows Phone はバックグラウンドで動作することも許されていません。これにより、意図的に隠されたアプリケーションや、いわゆるスパイウェアから利用者のデータを守っています。利用者が別のアプリケーションに切り替えたときには、これまで使用していたアプリケーションは休止状態となり、それまでの動作状態が保存されます。こうしたアプローチにより、アプリケーションがリソースを食いつぶしたり、裏で勝手にインターネットにアクセスするといったことを抑止しているのです。

    本来参照する権限を持たないユーザーに対して社内情報を流出してしまうなど、スマートフォンにありがちな一般的なリスクを軽減するには、堅牢なセキュリティで守られたデバイス上にアプリケーションを展開する必要があります。

    Windows Phone はデバイス自身がこのようなセキュリティで守られている他、Exchange Active Sync(EAS)によりセキュリティポリシーの集中管理が行えるようになります。EAS については別の記事で解説します。

    以下につづく

    【WP for IT Pros】Windows Phone のセキュリティモデルについて~データの保護

  • 【Management】一括で「ブロックを解除」する streams コマンド編

    2012年初の投稿となります。本年もよろしくお願いいたします。

    さて、完全に覚書レベルの話ですみません。結構知らない方が多いかもと思ったので書いておきます。

    インターネットからダウンロードしたファイルを使用するとき、ファイルに書き込まれている ZoneId と呼ばれる代替データストリームをリセットしなければならない場合があります。ZoneId をリセットするには、ファイルのプロパティから「ブロックの解除」を実行します。この操作は比較的おなじみですよね。

    image

    しかし大量のファイルが存在する場合には、この作業はとても面倒です。

    そこで、そんな作業を軽減するためのツールがいくつか用意されています。その1つが、Windows Sysinternals の Streams コマンドです。

    Streams v1.56

    このコマンドを使用すると、以下のように複数のファイルから一括で ZoneId を含めた代替データストリームを削除することができます。

    C:\tmp\Files\>streams -s -d *.*

    Streams v1.56 - Enumerate alternate NTFS data streams
    Copyright (C) 1999-2007 Mark Russinovich
    Sysinternals - www.sysinternals.com

    C:\tmp\Files\ADFS???????\ADFSClient.sln:
       Deleted :Zone.Identifier:$DATA
    C:\tmp\Files\ADFS???????\ADFSClient.suo:
       Deleted :Zone.Identifier:$DATA



    @IT の打越さんの記事に理屈も含めて詳しく書かれていますので、是非とも参考にしてください。打越さん、とても詳しい記事ありがとうございます!...でも、かなりマニアックですよ(笑)

    streamsコマンドでNTFSの代替データ・ストリーム情報を表示/削除する - @IT

  • 【PowerShell】一括で「ブロックを解除」する ~ Windows PowerShell 編 その1

    先の投稿で、一括で「ブロックを解除する」方法についてご紹介しました。

    【Management】一括で「ブロックを解除」する ~ streams コマンド編

    ただ、この方法だとファイルの代替データストリームを全て削除してしまうので、ちょっと感じ悪いというか...なんか他に影響が出ないかすごく心配だったりします。IT Pro 的には。

    ※ ちなみに、ファイルのプロパティから「ブロックを解除」すれば、ZoneID のみを削除することができます。ただし、ファイル単位に操作するので超面倒なのですね。

    代替データストリームは、Dir /r コマンドで確認することができます。例えば、以下の場合には、4つの代替データストリームが存在していることがわかります。

    C:\tmp>dir /r IdentityModel.WP7.dll
    ドライブ C のボリューム ラベルがありません。
    ボリューム シリアル番号は 6E7E-0B00 です

    C:\tmp のディレクトリ

    24/01/12  20:08            44,032 IdentityModel.WP7.dll
                                    7 IdentityModel.WP7.dll:ads1:$DATA
                                    7 IdentityModel.WP7.dll:ads2:$DATA
                                    7 IdentityModel.WP7.dll:ads3:$DATA
                                   26 IdentityModel.WP7.dll:Zone.Identifier:$DATA
                   1 個のファイル              44,032 バイト
                   0 個のディレクトリ  16,348,221,440 バイトの空き領域

    dir /r で参照した場合、実際に保存されているデータは $DATA と表現されてます。中身は、代替データストリームごとに notepad で参照することができます。ファイル名の後ろに「:<代替データストリーム名>」を付加していることに注意してください。

    (参考)NTFS 代替データストリームに関するメモ - B-) の独り言@Ihara さん

    C:\tmp>notepad IdentityModel.WP7.dll:Zone.Identifier

    image

    前置きが長くなってしまいました。ここからが本題です。Windows PowerShell を使用して Zone.Identifier のみを削除するスクリプトを書いてみたいと思います。そんなに難しくありません!

    ....と、実は少々高をくくっていました...いやー .NET Framework って代替データストリームへのアクセスに対応していないですねぇ。知らなかった...。完全になめていました。

    で、いろいろと当たってみると、CodeProject で提供されている以下のライブラリが使いやすそうだと思いました。

    代替データストリームにアクセスするためのライブラリ(Richard Deeming 氏提供)
    Accessing alternative data-streams of files on an NTFS volume - CodeProject®

    上記をダウンロードし、zip ファイルを解凍したら、bin\Trinet.Core.IO.Ntfs.dll を適当なフォルダ(c:\tmpなど)に保存してください。

    なお、この dll ファイルもインターネットからダウンロードしたものなので、手動で「ブロックの解除」を行っておいてください。

    PowerShell のコンソールを開き、以下のようにして解凍した DLL ファイルを読み込みます。

    PS C:\> [System.Reflection.Assembly]::LoadFile("c:\tmp\Trinet.Core.IO.Ntfs.dll")

    ファイルに設定されている代替データストリームの一覧を表示するには、ListAlternateDataStreams メソッドを使用し、以下のように入力します。ここでは、C:\tmp\IdentityModel.WP7.dll ファイルの代替データストリームを参照しています。dir /r で表示したときと同じようなデータが表示されていることがわかりますね。

    PS C:\> [Trinet.Core.IO.Ntfs.FileSystem]::ListAlternateDataStreams("C:\tmp\IdentityModel.WP7.dll")

    FullPath   : C:\tmp\IdentityModel.WP7.dll:ads1:$DATA
    FilePath   : C:\tmp\IdentityModel.WP7.dll
    Name       : ads1
    Exists     : True
    Size       : 7
    StreamType : AlternateDataStream
    Attributes : None

    FullPath   : C:\tmp\IdentityModel.WP7.dll:ads2:$DATA
    FilePath   : C:\tmp\IdentityModel.WP7.dll
    Name       : ads2
    Exists     : True
    Size       : 7
    StreamType : AlternateDataStream
    Attributes : None

    FullPath   : C:\tmp\IdentityModel.WP7.dll:ads3:$DATA
    FilePath   : C:\tmp\IdentityModel.WP7.dll
    Name       : ads3
    Exists     : True
    Size       : 7
    StreamType : AlternateDataStream
    Attributes : None

    FullPath   : C:\tmp\IdentityModel.WP7.dll:Zone.Identifier:$DATA
    FilePath   : C:\tmp\IdentityModel.WP7.dll
    Name       : Zone.Identifier
    Exists     : True
    Size       : 26
    StreamType : AlternateDataStream
    Attributes : None

    もちろん PowerShell ですから、以下のようにして代替データストリーム単位に参照することも可能です。

    PS C:\> $File = "C:\tmp\IdentityModel.WP7.dll"
    PS C:\> $ADS = [Trinet.Core.IO.Ntfs.FileSystem]::ListAlternateDataStreams( $File )
    PS C:\> $ADS[3]

    FullPath   : C:\tmp\IdentityModel.WP7.dll:Zone.Identifier:$DATA
    FilePath   : C:\tmp\IdentityModel.WP7.dll
    Name       : Zone.Identifier
    Exists     : True
    Size       : 26
    StreamType : AlternateDataStream
    Attributes : None

    Zone.Identifier が存在するかどうかを判断するには、AlternateDataStreamExists を使用して以下のように記述します。

    PS C:\> $ADSName = "Zone.Identifier"
    PS C:\> $File = "C:\tmp\IdentityModel.WP7.dll"
    PS C:\> [Trinet.Core.IO.Ntfs.FileSystem]::AlternateDataStreamExists( $File, $ADSName )

    True

    代替データストリームの中から、Zone.Identifier を削除するには DeleteAlternateDataStream を使用します。削除に成功すると、以下のように True が返されます。

    PS C:\> $ADSName = "Zone.Identifier"
    PS C:\> $File = "C:\tmp\IdentityModel.WP7.dll"
    PS C:\> [Trinet.Core.IO.Ntfs.FileSystem]::DeleteAlternateDataStream( $File, $ADSName )

    True

    この方法を使用して、指定したフォルダ配下の全てのファイルの Zone.Identifier を削除するには、以下のようなスクリプトを作成して実行すればOKです。

    [System.Reflection.Assembly]::LoadFile("c:\tmp\Trinet.Core.IO.Ntfs.dll")
    $Path = "c:\tmp\test"
    $ADSName = "Zone.Identifier"
    $Files = Get-ChildItem -Recurse -Name $Path
    Foreach ($F in $Files) { [Trinet.Core.IO.Ntfs.FileSystem]::DeleteAlternateDataStream( $Path+"\"+$F, $ADSName ) }

    もちろん、削除されるのは Zone.Identifier のみなので、その他の代替データストリームはそのまま残ります。

  • 【PowerShell】「ブロックを解除」するためのメソッドを追加してみる

    前回の投稿では、CodeProject で公開されているライブラリを使用して、一括でブロックを解除する方法について紹介しました。

    【PowerShell】一括で「ブロックを解除」する ~ Windows PowerShell 編 その1

    頻繁に使用するかどうかははなはだ疑問なのですが、ついでなので「ブロックを解除」するためのメソッドを追加しちゃいましょう。

    メソッドを追加するとはどういうことか?例えば、以下のような感じです。

    PS C:\> $File = Get-Item .\IdentityModel.WP7.dll
    PS C:\> $File.DeleteAlternateDataStream

    標準では Get-Item で作成した $File には、DeleteAlternateDataStream というメソッドは用意されていません。それを作ってしまおうということです。

    なんか、とてつもないことを言っているように感じるかもしれませんが、PowerShell では、既存の Types.ps1xml ファイルを編集したり、新しい Types.ps1xml ファイルを作成することで、メソッドやプロパティを追加することができます。もちろん、内部の処理はスクリプトで書くことができるので、Visual Studio を使って云々..なんて必要もありません。

    参考サイトはたくさんありますが、いちおうスタンダードなものは以下でしょうかね。

    about_Types.ps1xml

    では早速着手してみましょう。

    1.メソッドを追加するクラスを特定する

    はじめに、どのクラスにメソッドやプロパティを追加するかを決めておく必要があります。

    今回は、$File = Get-Item .\IdentityModel.WP7.dll で取得した $File に対してメソッド等を追加しようとしています。

    では、$File のクラスはどうやってを調べるのかといえば、以下のようにして調べることができます。

    PS C:\> $File.GetType().FullName
    System.IO.FileInfo

    もし、Get-Item で取得したオブジェクトがレジストリキーであれば、クラスは以下のように Microsoft.Win32.RegistryKey となります。

    PS C:\> $REG = Get-Item hklm:\software\microsoft
    PS C:\> $REG.GetType().FullName
    Microsoft.Win32.RegistryKey

    2.メソッドの設計

    まずは、どんなメソッドを実装するかを決めておきます。今回は、以下のメソッドだけを追加しましょう。

    • UnBlock
      代替データストリームから Zone.Identifier を決め打ちで削除する(ブロックを解除する)。引数はありません。

    3. .ps1xml ファイルを作成する

    メソッドおよびプロパティの定義は、.ps1xml ファイルを新しく作成して、その中に定義します。

    今回は、ファイル名を adsinfo.ps1xml としましょう。

    まずはメモ帳で adsinfo.ps1xml を新規に作成し、以下の内容をコピペしてください。

    <?xml version="1.0" encoding="utf-8" ?>
    <Types> 
      <Type>
        <Name>System.IO.FileInfo</Name>
        <Members>
          <ScriptMethod>
            <Name>UnBlock</Name>
            <Script>
              [System.Reflection.Assembly]::LoadFile("c:\tmp\Trinet.Core.IO.Ntfs.dll")
              $File = Get-Item( $this.FullName )
              $ADSName = "Zone.Identifier"
              [Trinet.Core.IO.Ntfs.FileSystem]::DeleteAlternateDataStream( $File, $ADSName )

            </Script>
          </ScriptMethod>
        </Members>
      </Type>
    </Types>

    作成したファイルは適当な場所に保存しておいてもよいのですが、$pshome に保存しておくことをお勧めします。

    あえて解説するまでもないですが、念のために書いておきます。

    <Name>System.IO.FileInfo</Name> はメソッドを実装するクラス(オブジェクトの型)です。指定するクラスを間違えると意味がないので注意しましょう。

    <Name>UnBlock</Name> が実際に実装するメソッドの名前です。

    <Script> ~ </Script> の間に、処理内容を PowerShell で記述します。 見ていただければわかる通り、何も変わった書き方はありません。1点だけ注意していただきたいのは、取得したファイルオブジェクトは $this として表現されている点です。ここでは、ファイルオブジェクトの FullName プロパティを使用して、あらためて $FS オブジェクトを作成しています。

    なお、[System.Reflection.Assembly]::LoadFile("c:\tmp\Trinet.Core.IO.Ntfs.dll") については以下の BLOG エントリを参照してください。このライブラリを用意して読み込まないと、このスクリプトは動きません。ライブラリの保存先はどこでもOKです。今回は c:\tmp に保存しています。

    【PowerShell】一括で「ブロックを解除」する ~ Windows PowerShell 編 その1

    4. 作成した ps1xml ファイルを読み込む

    作成した adsinfo.ps1xml ファイルを読み込むには、update-typedata コマンドを使用します。

    PS C:\> update-typedata $pshome\adsinfo.ps1xml

    今回はファイルを $pshome(C:\Windows\System32\WindowsPowerShell\v1.0)に保存していますが、特に決まりはありません。管理上便利な場所に保存して、紛失しないようにしましょう。

    なお、ファイルの読み込みは、PowerShell コンソールごとに行う必要があります。そのため、一度コンソールを閉じてしまうと定義は消えてしまいます。

    定義を永続化するには、$PROFILE(Microsoft.PowerShell_profile.ps1)に上記コマンドを記述しておきます。

    5. 動作確認

    インターネットからダウンロードしたDLLファイル等を用意して、Get-Item で取得してください。

    さらに、 Get-Member でメソッドに UnBlock が追加されていることを確認しましょう。

    PS C:\tmp> $File = Get-Item .\IdentityModel.WP7.dll
    PS C:\tmp> $File |Get-Member

       TypeName: System.IO.FileInfo

    Name                      MemberType     Definition
    ----                      ----------     ----------
    Mode                      CodeProperty   System.String Mode{get=Mode;}
    AppendText                Method         System.IO.StreamWriter AppendText()
    CopyTo                    Method         System.IO.FileInfo CopyTo(string de...
    Create                    Method         System.IO.FileStream Create()



    Length                    Property       System.Int64 Length {get;}
    Name                      Property       System.String Name {get;}
    UnBlock                   ScriptMethod   System.Object UnBlock();
    BaseName                  ScriptProperty System.Object BaseName {get=if ($th...
    VersionInfo               ScriptProperty System.Object VersionInfo {get=[Sys...

    実際に UnBlock を実行するには、以下のように入力するだけです。

    PS C:\tmp> $File.UnBlock()

    GAC    Version        Location
    ---    -------        --------
    False  v2.0.50727     c:\tmp\Trinet.Core.IO.Ntfs.dll
    True

    Zone.Identifier が削除されると、True と表示されます。

    同じように、代替データストリームの一覧を表示するメソッドや、指定した代替データストリームを削除するメソッドなども追加できます。

    今回は代替データストリームを削除するためのメソッドを実装してみましたが、業務特有の処理をメソッド化しておくと、業務の処理を効率化したり標準化することができて便利ですね。

    他に、スクリプトコマンドレットを作成する...なんていう方法もあるのですが、個人的にはこちらのほうが好みです。

    Windows PowerShell: スクリプトでコマンドレットを記述する

  • 【WP for IT Pros】AD FS 接続テストツール(ADFSClient)を公開しました

    非常にニッチな Windows Phone アプリを公開しました。

    その名も、AD FS 接続テストツール です。

    社内の AD FS から SAML トークンが正しく受け取れるかどうかを検証するためのツールです。

    まだマーケットプレースの検索にはヒットしないようですが、以下からダウンロードすることができます。

    http://www.windowsphone.com/ja-JP/apps/6396423a-d26e-4ef7-a03e-9e695f87d52b

    画面は以下の1画面だけ(笑)。「ログオン」をタップして正常に認証/認可されると、右のような画面が表示されます。これだけです。

    1/5 4/5 

    こんなアプリも公開可能なので、ITPROの方にも是非チャレンジしていただきたいですねl

    このアプリのソースコードは以下で公開しています。是非もっと便利にアレンジして使ってください!

    2011/11/28 セミナー資料 Windows Phone アプリケーションに認証機能を実装する

  • 【IDM】AD FS で Event ID 323、364 が発生して認可されない場合の対処

    みなさん、AD FS 使ってますか~? とかるーいノリで...。

    たったいま、ハマった現象について覚書程度に記しておきます。

    AD FSをインストールすると、規定の要求プロバイダーとして Active Directory が登録されます。

    image

    でもって、この要求プロバイダー"Active Directory"には、既定のクレームルールセットが登録されています。

    image

    この規定のクレームルールを削除してしまうと、認証方式や認証のタイムスタンプ等をRP(Relying Party)側に伝えることができなくなり、RP 側の STS からセキュリティトークン発行を拒否されてしまうことがあります(RP 側 STS の実装によります)。

    拒否されると、イベントログには以下のようなイベントが出力されます。

    image

    フェデレーション サービスは、発信者 '' から証明書利用者 'https://tfazureforitpro.accesscontrol.windows.net/' へのサブジェクト 'Administrator' の代理としてのトークンの発行を承認できませんでした。 発信者 ID については、同じインスタンス ID を持つイベント 501 を参照してください。 OnBehalfOf ID (存在する場合) については、同じインスタンス ID を持つイベント 502 を参照してください。


    インスタンス ID: d3c3c678-6bce-4fb5-90ee-f86810c4c53c

    例外の詳細:
    Microsoft.IdentityServer.Service.IssuancePipeline.OnBehalfOfAuthorizationException: MSIS5009: 証明書利用者信頼
    https://tfazureforitpro.accesscontrol.windows.net/ の発信者 ID および委任 システム 管理者 に対する偽装承認が失敗しました。
    場所 Microsoft.IdentityModel.Threading.AsyncResult.End(IAsyncResult result)
    場所 Microsoft.IdentityModel.Protocols.WSTrust.WSTrustServiceContract.ProcessCoreAsyncResult.End(IAsyncResult ar)
    場所 Microsoft.IdentityModel.Protocols.WSTrust.WSTrustServiceContract.EndProcessCore(IAsyncResult ar, String requestAction, String responseAction, String trustNamespace)
    ユーザー操作
    AD FS 2.0 の Windows PowerShell コメントを使用して、サブジェクトの代理の発信者が証明書利用者に対して承認されていることを確認してください。

    image

    パッシブな要求のフェデレーション中にエラーが発生しました。

    追加データ

    例外の詳細:
    Microsoft.IdentityServer.Web.RequestFailedException: MSIS7012: 要求の処理中にエラーが発生しました。詳細については、管理者に問い合わせてください。 ---> System.ServiceModel.FaultException: MSIS3126: アクセスが拒否されました。
       場所 Microsoft.IdentityServer.Protocols.WSTrust.WSTrustClientManager.Issue(Message request, WCFResponseData responseData)
       場所 Microsoft.IdentityServer.Protocols.WSTrust.WSTrustClient.Issue(RequestSecurityToken rst, WCFResponseData responseData)
       場所 Microsoft.IdentityServer.Web.FederationPassiveAuthentication.SubmitRequest(MSISRequestSecurityToken request)
       --- 内部例外スタック トレースの終わり ---
       場所 Microsoft.IdentityServer.Web.FederationPassiveAuthentication.SubmitRequest(MSISRequestSecurityToken request)
       場所 Microsoft.IdentityServer.Web.FederationPassiveAuthentication.RequestBearerToken(MSISSignInRequestMessage signInRequest, SecurityTokenElement onBehalfOf, SecurityToken primaryAuthToken, String desiredTokenType, Uri& replyTo)
       場所 Microsoft.IdentityServer.Web.FederationPassiveAuthentication.RequestBearerToken(MSISSignInRequestMessage signInRequest, SecurityTokenElement onBehalfOf, SecurityToken primaryAuthToken, String desiredTokenType, MSISSession& session)
       場所 Microsoft.IdentityServer.Web.FederationPassiveAuthentication.BuildSignInResponseCoreWithSerializedToken(String signOnToken, WSFederationMessage incomingMessage)
       場所 Microsoft.IdentityServer.Web.FederationPassiveAuthentication.BuildSignInResponseCoreWithSecurityToken(SecurityToken securityToken, WSFederationMessage incomingMessage)
       場所 Microsoft.IdentityServer.Web.FederationPassiveAuthentication.BuildSignInResponseForProtocolRequest(FederationPassiveContext federationPassiveContext, SecurityToken securityToken)
       場所 Microsoft.IdentityServer.Web.FederationPassiveAuthentication.BuildSignInResponse(SecurityToken securityToken)

    System.ServiceModel.FaultException: MSIS3126: アクセスが拒否されました。
       場所 Microsoft.IdentityServer.Protocols.WSTrust.WSTrustClientManager.Issue(Message request, WCFResponseData responseData)
       場所 Microsoft.IdentityServer.Protocols.WSTrust.WSTrustClient.Issue(RequestSecurityToken rst, WCFResponseData responseData)
       場所 Microsoft.IdentityServer.Web.FederationPassiveAuthentication.SubmitRequest(MSISRequestSecurityToken request)

    自分で設定したクレームルールに何の問題もないのに、このエラーが出た場合には、既定のルールを削除してしまったか変更してしまった可能性があります。

    (参考)AD FS 2.0: Error Event 323, "MSIS5009: The impersonation authorization failed" and Event 364, "MSIS3126: Access denied" - TechNet Articles - Home - TechNet Wiki

    そんなときは、ひとまず既定のルールセットを復旧しましょう。

    当然、何が入っていたか覚えてますよね?

    覚えていない!?なんてことでしょう!

    そんな方のために、既定のルールセットの復旧手順が用意されています(私はこれに助けられました!)。

    AD FS 2.0: How to Restore the Default Acceptance Transform Rules for the Active Directory Claims Provider Trust - TechNet Articles - Home - TechNet Wiki

    ※注意!この処理を行うと 要求プロバイダー"Active Directory" のクレームルールが初期化されます!
    ※必ず事前にクレームルールセットのバックアップを取りましょう
    【IDM】AD FS で既存のクレームルールセットをバックアップするには

    英語を読むのが面倒な方は以下をご覧ください。

    1.以下のテキストを 丸ごとコピーして adcprules-default.txt というファイル名で保存してください。

    AD FS に詳しい方であれば、以下がクレームルール言語で書かれてことがわかるはずです。

    @RuleTemplate = "PassThroughClaims" @RuleName = "Pass through all Windows account name claims" c:[Type ==
    "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname", Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"] => issue(claim = c);

    @RuleTemplate = "PassThroughClaims" @RuleName = "Pass through all Name claims" c:[Type ==
    "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"] => issue(claim = c);

    @RuleTemplate = "PassThroughClaims" @RuleName = "Pass through all Primary SID claims" c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid", Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"] => issue(claim = c);

    @RuleTemplate = "PassThroughClaims" @RuleName = "Pass through all Group SID claims" c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid", Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"] => issue(claim = c);

    @RuleTemplate = "PassThroughClaims" @RuleName = "Pass through all Primary group SID claims" c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/primarygroupsid", Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"] => issue(claim = c);

    @RuleTemplate = "PassThroughClaims" @RuleName = "Pass through all Deny only group SID claims" c:[Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/denyonlysid", Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"] => issue(claim = c);

    @RuleTemplate = "PassThroughClaims" @RuleName = "Pass through all Deny only primary SID claims" c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarysid", Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"] => issue(claim = c);

    @RuleTemplate = "PassThroughClaims" @RuleName = "Pass through all Deny only primary group SID claims" c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarygroupsid", Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"] => issue(claim = c);

    @RuleTemplate = "PassThroughClaims" @RuleName = "Pass through all Authentication method claims" c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod", Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"] => issue(claim = c);

    @RuleTemplate = "PassThroughClaims" @RuleName = "Pass through all Authentication time stamp claims" c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationinstant", Issuer =~ "^(AD AUTHORITY|SELF AUTHORITY|LOCAL AUTHORITY)$"] => issue(claim = c);

    2.PowerShell コンソールを開いてください

    3.以下のコマンドレットを入力して、AD FS のスナップインを読み込んでください。

    Add-PSSnapin Microsoft.Adfs.Powershell

    4.以下のコマンドレットを入力して、保存したクレームルールセットを読み込んでください。

    Set-AdfsClaimsProviderTrust -TargetName "Active Directory" -AcceptanceTransformRulesFile "adcprules-default.txt"

    以上で完了です。

    AD FS 管理コンソールで要求プロバイダー "Active Directory" のクレームルールを見ていただければ、元の状態に戻っていることがわかります。

    繰り返しますが、この処理を行うと要求プロバイダー"Active Directory” に定義したクレームルールセットは消えてしまうので注意してください。

    (参考)【IDM】AD FS で既存のクレームルールセットをバックアップするには