クイック スタート: Protection SDK 向けのクライアント アプリケーションの初期化 (C++)

このクイックスタートでは、実行時に MIP C++ SDK によって使用される、クライアントの初期化パターンを実装する方法について説明します。

Note

MIP Protection SDK を使用するすべてのクライアント アプリケーションに対して、このクイックスタートで概説されている手順を実施する必要があります。 これらのクイック スタートは、アプリケーションの初期化と、認証の委任および同意の委任の各クラスの実装後に、順次実行する必要があります。

前提条件

まだ実施していない場合は、必ず次の作業を行ってください。

  • Microsoft Information Protection (MIP) SDK のセットアップと構成」の手順を完了します。 この "クライアント アプリケーションの初期化" クイック スタートは、適切な SDK のセットアップと構成に依存します。
  • 必要に応じて:
    • プロファイルとエンジンのオブジェクトに関する記事を確認します。 プロファイルとエンジンのオブジェクトは、MIP File、MIP Policy、MIP Protection の各 SDK を使用するクライアントによって必要とされるユニバーサルな概念です。
    • 認証の概念に関する記事を確認して、認証と同意が SDK とクライアント アプリケーションによってどのように実装されるかについて学習します。
    • オブザーバーの概念に関する記事を確認して、オブザーバーの詳細およびその実装方法について学習します。 MIP SDK では、オブザーバー パターンを使用して、非同期イベント通知を実装します。

Visual Studio のソリューションとプロジェクトを作成する

まず、最初の Visual Studio のソリューションとプロジェクトを作成して構成します。他のクイック スタートは、これに基づいて作成されます。

  1. Visual Studio 2017 を開いて、[ファイル] メニュー、[新規][プロジェクト] の順に選択します。 [新しいプロジェクト] ダイアログで次の操作を行います。

    • 左側のペインの [インストール済み] の下の [その他の言語] で、[Visual C++] を選択します。

    • 中央のペインで、[Windows コンソール アプリケーション] を選択します

    • 下部のペインで、プロジェクトの [名前][場所]、含める [ソリューション名] を適宜更新します。

    • 完了したら、右下の [OK] ボタンをクリックします。

      Visual Studio solution creation

  2. 次の手順に従って、MIP Protection SDK 用の Nuget パッケージをプロジェクトに追加します。

    • ソリューション エクスプローラーで、プロジェクト ノード (最上位/ソリューション ノードのすぐ下) を右クリックして、[NuGet パッケージの管理] を選択します。

    • [エディター グループ] タブ領域で [NuGet パッケージ マネージャー] タブが開いたら、次の操作を行います。

      • 参照を選択します。
      • 検索ボックスに「Microsoft.InformationProtection」と入力します。
      • [Microsoft.InformationProtection.Protection] パッケージを選択します。
      • [インストール] をクリックし、[変更のプレビュー] の確認ダイアログが表示されたら [OK] をクリックします。

      Visual Studio add NuGet package

保護プロファイルとエンジンのオブジェクトを監視するためのオブザーバー クラスを実装する

次に、SDK の mip::ProtectionProfile::Observer クラスを拡張して、保護プロファイル オブザーバー クラスの基本的な実装を作成します。 このオブザーバーはインスタンス化され、保護プロファイル オブジェクトの読み込みと、プロファイルへのエンジン オブジェクトの追加を監視するために、後で使用されます。

  1. 新しいクラスをプロジェクトに追加します。これにより、header/.h と implementation/.cpp の両方のファイルが生成されます。

    • ソリューション エクスプローラーでもう一度プロジェクト ノードを右クリックし、[追加][クラス] の順に選択します。

    • [クラスの追加] ダイアログで、以下の操作を行います。

      • [クラス名] フィールドに「profile_observer」と入力します。 [.h ファイル][.cpp ファイル] の両方のフィールドが、入力した名前に基づいて自動的に設定されることに注意してください。
      • 完了したら、[OK] ボタンをクリックします。

      Visual Studio add class

  2. クラスの .h と .cpp のファイルを作成すると、両方のファイルが [エディター グループ] タブに表示されます。 次に、各ファイルを更新して、新しいオブザーバー クラスを実装します。

    • 生成した profile_observer クラスを選択または削除して、"profile_observer.h" を更新します。 前の手順で生成された、プリプロセッサ ディレクティブ (#pragma、#include) は削除しないでください。 次に、次のソースをコピーし、ファイル内で、既存の任意のプリプロセッサ ディレクティブの後に貼り付けます。

      #include <memory>
      #include "mip/protection/protection_profile.h"
      using std::exception_ptr;
      using std::shared_ptr;
      
      
      class ProtectionProfileObserver final : public mip::ProtectionProfile::Observer {
      public:
           ProtectionProfileObserver() { }
           void OnLoadSuccess(const std::shared_ptr<mip::ProtectionProfile>& profile, const std::shared_ptr<void>& context) override;
           void OnLoadFailure(const std::exception_ptr& Failure, const std::shared_ptr<void>& context) override;
           void OnAddEngineSuccess(const std::shared_ptr<mip::ProtectionEngine>& engine, const std::shared_ptr<void>& context) override;
           void OnAddEngineFailure(const std::exception_ptr& Failure, const std::shared_ptr<void>& context) override;
      };
      
    • 生成した profile_observer クラス実装を選択または削除して、"profile_observer.cpp" を更新します。 前の手順で生成された、プリプロセッサ ディレクティブ (#pragma、#include) は削除しないでください。 次に、次のソースをコピーし、ファイル内で、既存の任意のプリプロセッサ ディレクティブの後に貼り付けます。

      #include <future>
      
      using std::promise;
      using std::shared_ptr;
      using std::static_pointer_cast;
      using mip::ProtectionEngine;
      using mip::ProtectionProfile;
      
      void ProtectionProfileObserver::OnLoadSuccess(const shared_ptr<ProtectionProfile>& profile, const shared_ptr<void>& context) {
           auto promise = static_pointer_cast<std::promise<shared_ptr<ProtectionProfile>>>(context);
           promise->set_value(profile);
      }
      
      void ProtectionProfileObserver::OnLoadFailure(const std::exception_ptr& error, const shared_ptr<void>& context) {
           auto promise = static_pointer_cast<std::promise<shared_ptr<ProtectionProfile>>>(context);
           promise->set_exception(error);
      }
      
      void ProtectionProfileObserver::OnAddEngineSuccess(const shared_ptr<ProtectionEngine>& engine, const shared_ptr<void>& context) {
           auto promise = static_pointer_cast<std::promise<shared_ptr<ProtectionEngine>>>(context);
           promise->set_value(engine);
      }
      
      void ProtectionProfileObserver::OnAddEngineFailure(const std::exception_ptr& error, const shared_ptr<void>& context) {
           auto promise = static_pointer_cast<std::promise<shared_ptr<ProtectionEngine>>>(context);
           promise->set_exception(error);
      }
      
  3. 1 の手順に従って、 保護エンジン オブザーバーの新しいクラス "engine_observer" をプロジェクトに追加します。これにより、header/.h と implementation/.cpp の両方のファイルが生成されます。

  4. クラスの .h と .cpp のファイルを作成すると、両方のファイルが [エディター グループ] タブに表示されます。 次に、各ファイルを更新して、新しいオブザーバー クラスを実装します。

    • 生成した engine_observer クラスを選択または削除して、"engine_observer.h" を更新します。 前の手順で生成された、プリプロセッサ ディレクティブ (#pragma、#include) は削除しないでください。 次に、次のソースをコピーし、ファイル内で、既存の任意のプリプロセッサ ディレクティブの後に貼り付けます。

      #include <memory>
      #include "mip/protection/protection_engine.h"
      using std::vector;
      using std::exception_ptr;
      using std::shared_ptr;
      
      class ProtectionEngineObserver final : public mip::ProtectionEngine::Observer {
        public:
        ProtectionEngineObserver() {}
        void OnGetTemplatesSuccess(const vector<std::shared_ptr<mip::TemplateDescriptor>>& templateDescriptors, const shared_ptr<void>& context) override;
        void OnGetTemplatesFailure(const exception_ptr& Failure, const shared_ptr<void>& context) override;
      
      };
      
    • 生成した engine_observer クラス実装を選択または削除して、"engine_observer.cpp" を更新します。 前の手順で生成された、プリプロセッサ ディレクティブ (#pragma、#include) は削除しないでください。 次に、次のソースをコピーし、ファイル内で、既存の任意のプリプロセッサ ディレクティブの後に貼り付けます。

      #include "mip/protection/protection_profile.h"
      #include "engine_observer.h"
      
      using std::promise;
      void ProtectionEngineObserver::OnGetTemplatesSuccess(const vector<shared_ptr<mip::TemplateDescriptor>>& templateDescriptors,const shared_ptr<void>& context) {
          auto loadPromise = static_cast<promise<vector<shared_ptr<mip::TemplateDescriptor>>>*>(context.get());
          loadPromise->set_value(templateDescriptors);
        };
      
        void ProtectionEngineObserver::OnGetTemplatesFailure(const exception_ptr& Failure, const shared_ptr<void>& context) {
          auto loadPromise = static_cast<promise<shared_ptr<mip::ProtectionProfile>>*>(context.get());
          loadPromise->set_exception(Failure);
        };
      
  5. 続行する前に、必要に応じて、Ctrl + Shift + B ([ソリューションのビルド]) を使用してソリューションのテスト コンパイルとリンクを実行し、正しくビルドされていることを確認します。

MIP SDK では、クラスの拡張機能を使用して認証を実装します。これにより、認証作業をクライアント アプリケーションと共有するメカニズムが提供されます。 クライアントは、適切な OAuth2 アクセス トークンを取得し、実行時に MIP SDK に提供する必要があります。

SDK の mip::AuthDelegate クラスを拡張し、mip::AuthDelegate::AcquireOAuth2Token() 純粋仮想関数をオーバーライドまたは実装することで、認証の委任の実装を作成します。 File SDK アプリケーションの初期化のクイックスタートに関するページに記載されている手順に従います。 この認証の委任はインスタンス化され、保護プロファイルと保護エンジンのオブジェクトによって後で使用されます。

次に、SDK の mip::ConsentDelegate クラスを拡張し、mip::AuthDelegate::GetUserConsent() 純粋仮想関数をオーバーライドまたは実装することで、同意の委任の実装を作成します。 File SDK アプリケーションの初期化のクイックスタートに関するページに記載されている手順に従います。 この同意の委任はインスタンス化され、保護プロファイルと保護エンジンのオブジェクトによって後で使用されます。

保護のプロファイルとエンジンを作成する

前述のとおり、MIP API を使用する SDK クライアントには、プロファイルとエンジンのオブジェクトが必要です。 プロファイルとエンジンのオブジェクトをインスタンス化するコードを追加して、このクイック スタートのコード部分を完了します。

  1. ソリューション エクスプローラーから、main() メソッドの実装が含まれる .cpp ファイルをプロジェクトで開きます。 既定の名前は、それが含まれるプロジェクトと同じであり、プロジェクトの作成時に指定したものです。

  2. 生成された main() の実装を削除します。 プロジェクトの作成時に Visual Studio によって生成されたプリプロセッサ ディレクティブ (#pragma, #include) は削除しないでください。 任意のプリプロセッサ ディレクティブの後に次のコードを追加します。

#include "mip/mip_init.h"
#include "mip/mip_context.h"  
#include "auth_delegate.h"
#include "consent_delegate.h"
#include "profile_observer.h"
#include"engine_observer.h"

using std::promise;
using std::future;
using std::make_shared;
using std::shared_ptr;
using std::string;
using std::cout;
using mip::ApplicationInfo;
using mip::ProtectionProfile;
using mip::ProtectionEngine;

int main(){

  // Construct/initialize objects required by the application's profile object
  // ApplicationInfo object (App ID, name, version)
  ApplicationInfo appInfo{"<application-id>",                    
                          "<application-name>",
                          "<application-version>"};

  std::shared_ptr<mip::MipConfiguration> mipConfiguration = std::make_shared<mip::MipConfiguration>(mAppInfo,
				                                                                                               "mip_data",
                                                                                      			         mip::LogLevel::Trace,
                                                                                                     false);

  std::shared_ptr<mip::MipContext> mMipContext = mip::MipContext::Create(mipConfiguration);

  auto profileObserver = make_shared<ProtectionProfileObserver>(); // Observer object
  auto authDelegateImpl = make_shared<AuthDelegateImpl>("<application-id>"); // Authentication delegate object (App ID)
  auto consentDelegateImpl = make_shared<ConsentDelegateImpl>(); // Consent delegate object

  // Construct/initialize profile object
  ProtectionProfile::Settings profileSettings(
    mMipContext,
    mip::CacheStorageType::OnDisk,      
    consentDelegateImpl,
    profileObserver);

  // Set up promise/future connection for async profile operations; load profile asynchronously
  auto profilePromise = make_shared<promise<shared_ptr<ProtectionProfile>>>();
  auto profileFuture = profilePromise->get_future();
  try
  {
    mip::ProtectionProfile::LoadAsync(profileSettings, profilePromise);
  }
  catch (const std::exception& e)
  {
    cout << "An exception occurred... are the Settings and ApplicationInfo objects populated correctly?\n\n"
          << e.what() << "'\n";
    system("pause");
    return 1;
  }

  auto profile = profileFuture.get();

  // Construct/initialize engine object
  ProtectionEngine::Settings engineSettings(       
     mip::Identity("<engine-account>"),         // Engine identity (account used for authentication)
     authDelegateImpl,                          // Reference to mip::AuthDelegate implementation
     "",                                        // ClientData field
     "en-US");                                  // Locale (default = en-US)

  // Set the engineId so it can be cached and reused. 
  engineSettings.SetEngineId("<engine-account>");

  // Set up promise/future connection for async engine operations; add engine to profile asynchronously
  auto enginePromise = make_shared<promise<shared_ptr<ProtectionEngine>>>();
  auto engineFuture = enginePromise->get_future();
  profile->AddEngineAsync(engineSettings, enginePromise);
  std::shared_ptr<ProtectionEngine> engine;

  try
  {
    engine = engineFuture.get();
  }
  catch (const std::exception& e)
  {
    cout << "An exception occurred... is the access token incorrect/expired?\n\n"
         << e.what() << "'\n";
    system("pause");
    return 1;
  }

  // Application shutdown. Null out profile and engine, call ReleaseAllResources();
  // Application may crash at shutdown if resources aren't properly released.
  engine = nullptr;
  profile = nullptr;
  mipContext.Shutdown();
  mipContext = nullptr;

  return 0;
}
  1. 次の文字列定数を使用して、貼り付けたソース コードのすべてのプレースホルダー値を置き換えます。

    プレースホルダー
    <application-id> "MIP SDK のセットアップと構成" (setup-configure-mip.md) に関する記事の手順 2 で登録したアプリケーションに割り当てられた Microsoft Entra アプリケーション ID (GUID)。 2 つのインスタンスを置き換えます。 "0edbblll-8773-44de-b87c-b8c6276d41eb"
    <application-name> アプリケーションのユーザー定義のフレンドリ名。 有効な ASCII 文字 (';' を除く) が含まれている必要があります。Microsoft Entra 登録で使用したアプリケーション名と一致するものが理想的です。 "AppInitialization"
    <application-version> アプリケーションのユーザー定義のバージョン情報。 有効な ASCII 文字 (';' を除く) が含まれている必要があります。 "1.1.0.0"
    <engine-account> エンジンの ID に使用されるアカウント。 トークン取得時の認証では、この値と一致するユーザー アカウントを使用する必要があります。 "user1@tenant.onmicrosoft.com"
    <engine-state> エンジンに関連付けられるユーザー定義の状態。 "My App State"
  2. ここで、アプリケーションの最終ビルドを行い、すべてのエラーを解決します。 コードは正常にビルドされますが、次のクイック スタートを完了するまでは、正しく実行されません。 アプリケーションを実行すると、次のような出力が表示されます。 アプリケーションにより保護プロファイルと保護エンジンは正常に作成されますが、認証モジュールは起動しないため、次のクイックスタートを完了するまでアクセス トークンは取得できません。

     C:\MIP Sample Apps\ProtectionQS\Debug\ProtectionQS.exe (process 8252) exited with code 0.
     To automatically close the console when debugging stops, enable Tools->Options->Debugging->Automatically close the console when debugging stops.
     Press any key to close this window . . .
    

次のステップ

これで、初期化コードが完成したので、次のクイック スタートに進み、MIP Protection SDK の操作を開始する準備ができました。