Linux のコード例
重要
2020 年 3 月より前にリリースされた Microsoft Rights Management Service SDK のバージョンは非推奨です。2020 年 3 月のリリースを使用するには、以前のバージョンを使用するアプリケーションを更新する必要があります。 詳細については、 非推奨の通知を参照してください。
Microsoft Rights Management Service SDK の今後の機能強化は計画されていません。 分類、ラベル付け、保護サービスには、Microsoft Information Protection SDK の導入を強くお勧めします。
このトピックでは、Linux バージョンの RMS SDK の重要なシナリオとコード要素について説明します。
以下のコード スニペットは、サンプル アプリケーション、 rms_sample 、 rmsauth_sampleのものです。 詳しくは、GitHub リポジトリの「サンプル」をご覧ください。
シナリオ: 保護されたファイルから保護ポリシー情報にアクセスする
RMS で保護された fileSource を開いて読み取ります: rms_sample/mainwindow.cpp
説明: ユーザーからファイル名を取得したら、証明書を読み取り (MainWindow::addCertificates を参照)、クライアント ID とリダイレクト URL で承認コールバックを設定し、ConvertFromPFile を呼び出してから (次のコード例を参照)、保護ポリシー名、説明、およびコンテンツの有効期日を読み取ります。
C++:
void MainWindow::ConvertFromPFILE(const string& fileIn,
const string& clientId,
const string& redirectUrl,
const string& clientEmail)
{
// add trusted certificates using HttpHelpers of RMS and Auth SDKs
addCertificates();
// create shared in/out streams
auto inFile = make_shared<ifstream>(
fileIn, ios_base::in | ios_base::binary);
if (!inFile->is_open()) {
AddLog("ERROR: Failed to open ", fileIn.c_str());
return;
}
string fileOut;
// generate output filename
auto pos = fileIn.find_last_of('.');
if (pos != string::npos) {
fileOut = fileIn.substr(0, pos);
}
// create streams
auto outFile = make_shared<fstream>(
fileOut, ios_base::in | ios_base::out | ios_base::trunc | ios_base::binary);
if (!outFile->is_open()) {
AddLog("ERROR: Failed to open ", fileOut.c_str());
return;
}
try
{
// create authentication context
AuthCallback auth(clientId, redirectUrl);
// process conversion
auto pfs = PFileConverter::ConvertFromPFile(
clientEmail,
inFile,
outFile,
auth,
this->consent);
AddLog("Successfully converted to ", fileOut.c_str());
}
catch (const rmsauth::Exception& e)
{
AddLog("ERROR: ", e.error().c_str());
}
catch (const rmscore::exceptions::RMSException& e) {
AddLog("ERROR: ", e.what());
}
inFile->close();
outFile->close();
}
保護されたファイル streamSource を作成する: rms_sample/pfileconverter.cpp
説明: このメソッドは、SDK メソッド ProtectedFileStream::Acquire を介して渡されたバッキング ストリームから保護されたファイル ストリームを作成し、呼び出し元に返します。
C++:
shared_ptr<GetProtectedFileStreamResult>PFileConverter::ConvertFromPFile(
const string & userId,
shared_ptr<istream> inStream,
shared_ptr<iostream> outStream,
IAuthenticationCallback& auth,
IConsentCallback & consent)
{
auto inIStream = rmscrypto::api::CreateStreamFromStdStream(inStream);
auto fsResult = ProtectedFileStream::Acquire(
inIStream,
userId,
auth,
consent,
POL_None,
static_cast<ResponseCacheFlags>(RESPONSE_CACHE_INMEMORY
| RESPONSE_CACHE_ONDISK));
if ((fsResult.get() != nullptr) && (fsResult->m_status == Success) &&
(fsResult->m_stream != nullptr)) {
auto pfs = fsResult->m_stream;
// preparing
readPosition = 0;
writePosition = 0;
totalSize = pfs->Size();
// start threads
for (size_t i = 0; i < THREADS_NUM; ++i) {
threadPool.push_back(thread(WorkerThread,
static_pointer_cast<iostream>(outStream), pfs,
false));
}
for (thread& t: threadPool) {
if (t.joinable()) {
t.join();
}
}
}
return fsResult;
}
シナリオ: テンプレートを使用して新しい保護ファイルを作成する
ユーザーが選択した templateSource でファイルを保護します。rms_sample/mainwindow.cpp
説明: ユーザーからファイル名を取得したら、証明書を読み取り (MainWindow::addCertificates を参照)、クライアント ID とリダイレクト URL で承認コールバックを設定し、選択したファイルを ConvertToPFileTemplates を呼び出して保護します (次のコード例を参照)。
C++:
void MainWindow::ConvertToPFILEUsingTemplates(const string& fileIn,
const string& clientId,
const string& redirectUrl,
const string& clientEmail)
{
// generate output filename
string fileOut = fileIn + ".pfile";
// add trusted certificates using HttpHelpers of RMS and Auth SDKs
addCertificates();
// create shared in/out streams
auto inFile = make_shared<ifstream>(
fileIn, ios_base::in | ios_base::binary);
auto outFile = make_shared<fstream>(
fileOut, ios_base::in | ios_base::out | ios_base::trunc | ios_base::binary);
if (!inFile->is_open()) {
AddLog("ERROR: Failed to open ", fileIn.c_str());
return;
}
if (!outFile->is_open()) {
AddLog("ERROR: Failed to open ", fileOut.c_str());
return;
}
// find file extension
string fileExt;
auto pos = fileIn.find_last_of('.');
if (pos != string::npos) {
fileExt = fileIn.substr(pos);
}
try {
// create authentication callback
AuthCallback auth(clientId, redirectUrl);
// process conversion
PFileConverter::ConvertToPFileTemplates(
clientEmail, inFile, fileExt, outFile, auth,
this->consent, this->templates);
AddLog("Successfully converted to ", fileOut.c_str());
}
catch (const rmsauth::Exception& e) {
AddLog("ERROR: ", e.error().c_str());
outFile->close();
remove(fileOut.c_str());
}
catch (const rmscore::exceptions::RMSException& e) {
AddLog("ERROR: ", e.what());
outFile->close();
remove(fileOut.c_str());
}
inFile->close();
outFile->close();
}
templateSource: rms_sample/pfileconverter.cppから作成されたポリシーを使用してファイルを保護します
説明: ユーザーに関連付けられたテンプレートの一覧がフェッチされ、選択したテンプレートがポリシーの作成に使用されます。このポリシーを使用してファイルを保護します。
C++:
void PFileConverter::ConvertToPFileTemplates(const string & userId,
shared_ptr<istream> inStream,
const string & fileExt,
std::shared_ptr<iostream>outStream,
IAuthenticationCallback& auth,
IConsentCallback& /*consent*/,
ITemplatesCallback & templ)
{
auto templates = TemplateDescriptor::GetTemplateList(userId, auth);
rmscore::modernapi::AppDataHashMap signedData;
size_t pos = templ.SelectTemplate(templates);
if (pos < templates.size()) {
auto policy = UserPolicy::CreateFromTemplateDescriptor(
templates[pos],
userId,
auth,
USER_AllowAuditedExtraction,
signedData);
ConvertToPFileUsingPolicy(policy, inStream, fileExt, outStream);
}
}
policySource: rms_sample/pfileconverter.cpp という指定されたファイルを保護します
説明: 特定のポリシーを使用して保護されたファイル ストリームを作成し、そのファイルを保護します。
C++:
void PFileConverter::ConvertToPFileUsingPolicy(shared_ptr<UserPolicy> policy,
shared_ptr<istream> inStream,
const string & fileExt,
std::shared_ptr<iostream>outStream)
{
if (policy.get() != nullptr) {
auto outIStream = rmscrypto::api::CreateStreamFromStdStream(outStream);
auto pStream = ProtectedFileStream::Create(policy, outIStream, fileExt);
// preparing
readPosition = 0;
writePosition = pStream->Size();
inStream->seekg(0, ios::end);
totalSize = inStream->tellg();
// start threads
for (size_t i = 0; i < THREADS_NUM; ++i) {
threadPool.push_back(thread(WorkerThread,
static_pointer_cast<iostream>(inStream),
pStream,
true));
}
for (thread& t: threadPool) {
if (t.joinable()) {
t.join();
}
}
pStream->Flush();
}
シナリオ: カスタム保護を使用してファイルを保護する
カスタム protectionSource: rms_sample/mainwindow.cpp を使用してファイルを保護します
説明: ユーザーからファイル名を取得したら、証明書を読み取り (MainWindow::addCertificates を参照)、ユーザーから権限情報を収集し、クライアント ID とリダイレクト URL で承認コールバックを設定し、選択したファイルを ConvertToPFilePredefinedRights を呼び出して保護します (次のコード例を参照)。
C++:
void MainWindow::ConvertToPFILEUsingRights(const string & fileIn,
const vector<UserRights>& userRights,
const string & clientId,
const string & redirectUrl,
const string & clientEmail)
{
// generate output filename
string fileOut = fileIn + ".pfile";
// add trusted certificates using HttpHelpers of RMS and Auth SDKs
addCertificates();
// create shared in/out streams
auto inFile = make_shared<ifstream>(
fileIn, ios_base::in | ios_base::binary);
auto outFile = make_shared<fstream>(
fileOut, ios_base::in | ios_base::out | ios_base::trunc | ios_base::binary);
if (!inFile->is_open()) {
AddLog("ERROR: Failed to open ", fileIn.c_str());
return;
}
if (!outFile->is_open()) {
AddLog("ERROR: Failed to open ", fileOut.c_str());
return;
}
// find file extension
string fileExt;
auto pos = fileIn.find_last_of('.');
if (pos != string::npos) {
fileExt = fileIn.substr(pos);
}
// is anything to add
if (userRights.size() == 0) {
AddLog("ERROR: ", "Please fill email and check rights");
return;
}
try {
// create authentication callback
AuthCallback auth(clientId, redirectUrl);
// process conversion
PFileConverter::ConvertToPFilePredefinedRights(
clientEmail,
inFile,
fileExt,
outFile,
auth,
this->consent,
userRights);
AddLog("Successfully converted to ", fileOut.c_str());
}
catch (const rmsauth::Exception& e) {
AddLog("ERROR: ", e.error().c_str());
outFile->close();
remove(fileOut.c_str());
}
catch (const rmscore::exceptions::RMSException& e) {
AddLog("ERROR: ", e.what());
outFile->close();
remove(fileOut.c_str());
}
inFile->close();
outFile->close();
}
ユーザーが選択したrightsSource: rms_sample/pfileconverter.cpp を付与する保護ポリシーを作成します
説明: ポリシー記述子を作成し、ユーザーの権限情報を使ってこれを入力し、このポリシー記述子を使用してユーザー ポリシーを作成します。 このポリシーを使用して ConvertToPFileUsingPolicy への呼び出しにより選択したファイルを保護します (このトピックの前のセクションの説明を参照)。
C++:
void PFileConverter::ConvertToPFilePredefinedRights(
const string & userId,
shared_ptr<istream> inStream,
const string & fileExt,
shared_ptr<iostream> outStream,
IAuthenticationCallback & auth,
IConsentCallback& /*consent*/,
const vector<UserRights>& userRights)
{
auto endValidation = chrono::system_clock::now() + chrono::hours(48);
PolicyDescriptor desc(userRights);
desc.Referrer(make_shared<string>("https://client.test.app"));
desc.ContentValidUntil(endValidation);
desc.AllowOfflineAccess(false);
desc.Name("Test Name");
desc.Description("Test Description");
auto policy = UserPolicy::Create(desc, userId, auth,
USER_AllowAuditedExtraction);
ConvertToPFileUsingPolicy(policy, inStream, fileExt, outStream);
WorkerThread - サポート メソッド
WorkerThread() メソッドは、上のシナリオ例の 2 つ (保護されたファイル ストリームの作成およびポリシーを指定してファイルを保護) によって、次の方法で呼び出されます。
C++:
threadPool.push_back(thread(WorkerThread,
static_pointer_cast<iostream>(outStream), pfs,
false));
サポート メソッド、WorkerThread()
C++:
static mutex threadLocker;
static int64_t totalSize = 0;
static int64_t readPosition = 0;
static int64_t writePosition = 0;
static vector<thread> threadPool;
static void WorkerThread(shared_ptr<iostream> stdStream,
shared_ptr<ProtectedFileStream>pStream,
bool modeWrite) {
vector<uint8_t> buffer(4096);
int64_t bufferSize = static_cast<int64_t>(buffer.size());
while (totalSize - readPosition > 0) {
// lock
threadLocker.lock();
// check remain
if (totalSize - readPosition <= 0) {
threadLocker.unlock();
return;
}
// get read/write offset
int64_t offsetRead = readPosition;
int64_t offsetWrite = writePosition;
int64_t toProcess = min(bufferSize, totalSize - readPosition);
readPosition += toProcess;
writePosition += toProcess;
// no need to lock more
threadLocker.unlock();
if (modeWrite) {
// stdStream is not thread safe!!!
try {
threadLocker.lock();
stdStream->seekg(offsetRead);
stdStream->read(reinterpret_cast<char *>(&buffer[0]), toProcess);
threadLocker.unlock();
auto written =
pStream->WriteAsync(
buffer.data(), toProcess, offsetWrite, std::launch::deferred).get();
if (written != toProcess) {
throw rmscore::exceptions::RMSStreamException("Error while writing data");
}
}
catch (exception& e) {
qDebug() << "Exception: " << e.what();
}
} else {
auto read =
pStream->ReadAsync(&buffer[0],
toProcess,
offsetRead,
std::launch::deferred).get();
if (read == 0) {
break;
}
try {
// stdStream is not thread safe!!!
threadLocker.lock();
// seek to write
stdStream->seekp(offsetWrite);
stdStream->write(reinterpret_cast<const char *>(buffer.data()), read);
threadLocker.unlock();
}
catch (exception& e) {
qDebug() << "Exception: " << e.what();
}
}
}
}
シナリオ: RMS 認証
次の例は、2 つの異なる認証方法 (UI を使用、または使用せずに Azure 認証 oAuth2 トークンを取得) を示しています。 UISource を使用した oAuth2 認証トークンの取得: rmsauth_sample/mainwindow.cpp
手順 1: rmsauth::FileCache オブジェクトの共有ポイントを作成します。 説明: キャッシュのパスを設定するか、既定値を使用できます。
C++:
auto FileCachePtr = std::make_shared< rmsauth::FileCache>();
手順 2: rmsauth::AuthenticationContext オブジェクトを作成します。説明: Azure 証明機関 URI と FileCache オブジェクトを指定します。
C++:
AuthenticationContext authContext(
std::string("https://sts.aadrm.com/_sts/oauth/authorize"),
AuthorityValidationType::False,
FileCachePtr);
手順 3: authContext オブジェクトの acquireToken メソッドを呼び出し、次のパラメーターを指定します: 説明:
- 要求されるリソース - アクセスする必要のある保護されたリソース
- クライアントの一意な ID - 通常は GUID
- リダイレクト URI - 認証トークンがフェッチされた後に回送される URI
- 認証プロンプトの動作 - PromptBehavior::Auto を設定した場合、必要に応じて、ライブラリによりキャッシュの使用トークンの更新が試行されます
- ユーザー ID - プロンプト ウィンドウに表示されるユーザー名
C++:
auto result = authContext.acquireToken(
std::string("api.aadrm.com"),
std::string("4a63455a-cfa1-4ac6-bd2e-0d046cf1c3f7"),
std::string("https://client.test.app"),
PromptBehavior::Auto,
std::string("john.smith@msopentechtest01.onmicrosoft.com"));
手順 4: 結果からアクセス トークンを取得します。説明: result-> accessToken() メソッドを呼び出します。
メモ認証ライブラリのいずれかの方法で rmsauth::Exception が発生する可能性があります
UISource を使用しない oAuth2 認証トークンの取得: rmsauth_sample/mainwindow.cpp
手順 1: rmsauth::FileCache オブジェクトの共有ポイントを作成します。説明: キャッシュのパスを設定するか、既定値を使用できます。
C++:
auto FileCachePtr = std::make_shared< rmsauth::FileCache>();
手順 2: UserCredential オブジェクトを作成します。説明: ユーザー ログインとパスワードを指定します。
C++:
auto userCred = std::make_shared<UserCredential>("john.smith@msopentechtest01.onmicrosoft.com",
"SomePass");
手順 3: rmsauth::AuthenticationContext オブジェクトを作成します。説明: Azure 証明機関 URI と FileCache オブジェクトを指定します。
C++:
AuthenticationContext authContext(
std::string("https://sts.aadrm.com/_sts/oauth/authorize"),
AuthorityValidationType::False,
FileCachePtr);
手順 4: authContext の acquireToken メソッドを呼び出し、パラメーターを指定します。
- 要求されるリソース - アクセスする必要のある保護されたリソース
- クライアントの一意な ID - 通常は GUID
- ユーザーの資格情報 - 作成されたオブジェクトを渡します
C++:
auto result = authContext.acquireToken(
std::string("api.aadrm.com"),
std::string("4a63455a-cfa1-4ac6-bd2e-0d046cf1c3f7"),
userCred);
手順 5: 結果からアクセス トークンを取得します。説明: result-> accessToken() メソッドを呼び出します。
メモ認証ライブラリのいずれかの方法で rmsauth::Exception が発生する可能性があります