BSOne.SFC/Tocsg.Module/BSOne-AIP-Decrypt/Action.cs

623 lines
26 KiB
C#

/*
*
* Copyright (c) Microsoft Corporation.
* All rights reserved.
*
* This code is licensed under the MIT License.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files(the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.InformationProtection.File;
using Microsoft.InformationProtection.Exceptions;
using Microsoft.InformationProtection;
using System.Configuration;
using static BSOneMip.Define;
using Microsoft.InformationProtection.Protection;
using Microsoft.InformationProtection.Policy.Actions;
namespace BSOneMip
{
/// <summary>
/// Action class implements the various MIP functionality.
/// For this sample, only profile, engine, and handler creation are defined.
/// The IFileHandler may be used to label a file and read a labeled file.
/// </summary>
public class Action : IDisposable
{
// Fetch tenant name to build identity for service principal
private static readonly string tenant = TENANT_ID; // ConfigurationManager.AppSettings["ida:Tenant"];
private AuthDelegateImplementation authDelegate;
private ApplicationInfo appInfo;
private IFileProfile profile;
private IFileEngine engine;
//private IProtectionProfile profile_protec;
//private IProtectionEngine engine_protec;
private MipContext mipContext;
private string sDelegatedUserEmail_;
private string sEmpNo_;
// Used to pass in options for labeling the file.
public struct FileOptions
{
public string FileName;
public string OutputName;
public string LabelId;
public DataState DataState;
public AssignmentMethod AssignmentMethod;
public ActionSource ActionSource;
public bool IsAuditDiscoveryEnabled;
public bool GenerateChangeAuditEvent;
}
/// <summary>
/// Constructor for Action class. Pass in AppInfo to simplify passing settings to AuthDelegate.
/// </summary>
/// <param name="appInfo"></param>
public Action(ApplicationInfo appInfo, string sDelegatedUserEmail = "")
{
this.appInfo = appInfo;
this.sDelegatedUserEmail_ = sDelegatedUserEmail;
this.sEmpNo_ = sDelegatedUserEmail_;
int i = this.sEmpNo_.IndexOf('@');
if (i > 0)
this.sEmpNo_ = this.sEmpNo_.Substring(0, i);
if ((sEmpNo_ != "") && (sEmpNo_.ToLower() == "bsowner"))
sDelegatedUserEmail_ = "";
//sDelegatedUserEmail_ = "aiptest@unitus.co.kr";
//sDelegatedUserEmail_ = "kjkim@tocsgm365.onmicrosoft.com";
authDelegate = new AuthDelegateImplementation(this.appInfo);
// Initialize SDK DLLs. If DLLs are missing or wrong type, this will throw an exception
MIP.Initialize(MipComponent.File);
// Create MipConfiguration Object
MipConfiguration mipConfiguration = new MipConfiguration(appInfo, "mip_data", LogLevel.Trace, false);
// Create MipContext using MipConfiguration
mipContext = MIP.CreateMipContext(mipConfiguration);
// We must construct a service principal identity mail address as it can't be fetched from the token.
// Here, we set it to be ClientId@Tenant.com, but the SDK will accept any properly formatted email address.
Identity id = new Identity(String.Format("{0}@{1}", appInfo.ApplicationId, tenant))
//Identity id = new Identity("kjkim@kku97.onmicrosoft.com")
//Identity id = new Identity("2323308@hec.co.kr")
{
// Use this if you want the app to protect on behalf of a user. That user owns the protected content.
//Email = "2323308@hec.co.kr"
};
// Create profile.
profile = CreateFileProfile(appInfo, ref authDelegate);
// Create engine providing Identity from authDelegate to assist with service discovery.
engine = CreateFileEngine(id);
//profile_protec = CreateProtectionProfile(appInfo, ref authDelegate);
//engine_protec = CreateProtectionEngine(id);
}
/// <summary>
/// Null refs to engine and profile and release all MIP resources.
/// </summary>
public void Dispose()
{
profile.UnloadEngineAsync(engine.Settings.EngineId).Wait();
//profile_protec.Dispose();
//engine_protec.Dispose();
engine.Dispose();
profile.Dispose();
mipContext.ShutDown();
mipContext.Dispose();
}
//public List<TemplateDescriptor> ListTemplates()
//{
// return engine_protec.GetTemplates();
//}
private IProtectionProfile CreateProtectionProfile(ApplicationInfo appInfo, ref AuthDelegateImplementation authDelegate)
{
// Initialize ProtectionProfileSettings
var profileSettings = new ProtectionProfileSettings(mipContext,
CacheStorageType.OnDisk,
new ConsentDelegateImplementation());
// Use MIP.LoadProtectionProfileAsync() providing settings to create IProtectionProfile
// IProtectionProfile is the root of all SDK operations for a given application
var profile = MIP.LoadProtectionProfile(profileSettings);
return profile;
}
//private IProtectionEngine CreateProtectionEngine(Identity identity)
//{
// if (profile_protec == null)
// {
// profile_protec = CreateProtectionProfile(appInfo, ref authDelegate);
// }
// // Create protection engine settings object. Passing in empty string for the first parameter, engine ID, will cause the SDK to generate a GUID.
// // Passing in a email address or other unique value helps to ensure that the cached engine is loaded each time for the same user.
// // Locale settings are supported and should be provided based on the machine locale, particular for client applications.
// var engineSettings = new ProtectionEngineSettings(identity.Email, authDelegate, "", "")
// {
// Identity = identity
// };
// var engine = profile_protec.AddEngine(engineSettings);
// return engine;
//}
/// <summary>
/// Creates an IFileProfile and returns.
/// IFileProfile is the root of all MIP SDK File API operations. Typically only one should be created per app.
/// </summary>
/// <param name="appInfo"></param>
/// <param name="authDelegate"></param>
/// <returns></returns>
private IFileProfile CreateFileProfile(ApplicationInfo appInfo, ref AuthDelegateImplementation authDelegate)
{
// Initialize file profile settings to create/use local state.
var profileSettings = new FileProfileSettings(mipContext, CacheStorageType.OnDiskEncrypted, new ConsentDelegateImplementation());
// Use MIP.LoadFileProfileAsync() providing settings to create IFileProfile.
// IFileProfile is the root of all SDK operations for a given application.
var profile = Task.Run(async () => await MIP.LoadFileProfileAsync(profileSettings)).Result;
return profile;
}
/// <summary>
/// Creates a file engine, associating the engine with the specified identity.
/// File engines are generally created per-user in an application.
/// IFileEngine implements all operations for fetching labels and sensitivity types.
/// IFileHandlers are added to engines to perform labeling operations.
/// </summary>
/// <param name="identity"></param>
/// <returns></returns>
private IFileEngine CreateFileEngine(Identity identity)
{
// If the profile hasn't been created, do that first.
if (profile == null)
{
profile = CreateFileProfile(appInfo, ref authDelegate);
}
// Create file settings object. Passing in empty string for the first parameter, engine ID, will cause the SDK to generate a GUID.
// Locale settings are supported and should be provided based on the machine locale, particular for client applications.
var engineSettings = new FileEngineSettings("", authDelegate, "", "en-US")
{
// Provide the identity for service discovery.
Identity = identity,
DelegatedUserEmail = sDelegatedUserEmail_ // 위임할 계정 정보... 해냈다... 23_1031 kku
};
// Add the IFileEngine to the profile and return.
var engine = Task.Run(async () => await profile.AddEngineAsync(engineSettings)).Result;
return engine;
}
/// <summary>
/// Method creates a file handler and returns to the caller.
/// IFileHandler implements all labeling and protection operations in the File API.
/// </summary>
/// <param name="options">Struct provided to set various options for the handler.</param>
/// <returns></returns>
private IFileHandler CreateFileHandler(FileOptions options)
{
// Create the handler using options from FileOptions. Assumes that the engine was previously created and stored in private engine object.
// There's probably a better way to pass/store the engine, but this is a sample ;)
var handler = Task.Run(async () => await engine.CreateFileHandlerAsync(options.FileName, options.FileName, options.IsAuditDiscoveryEnabled)).Result;
return handler;
}
private IFileHandler CreateFileHandler(string filename)
{
// Create the handler using options from FileOptions. Assumes that the engine was previously created and stored in private engine object.
// There's probably a better way to pass/store the engine, but this is a sample ;)
var handler = Task.Run(async () => await engine.CreateFileHandlerAsync(filename, filename, false)).Result;
return handler;
}
/// <summary>
/// List all labels from the engine and return in IEnumerable<Label>
/// </summary>
/// <returns></returns>
public IEnumerable<Label> ListLabels()
{
// Get labels from the engine and return.
// For a user principal, these will be user specific.
// For a service principal, these may be service specific or global.
return engine.SensitivityLabels;
}
/// <summary>
/// Set the label on the given file.
/// Options for the labeling operation are provided in the FileOptions parameter.
/// </summary>
/// <param name="options">Details about file input, output, label to apply, etc.</param>
/// <returns></returns>
public bool SetLabel(FileOptions options)
{
// The change isn't committed to the file referenced by the handler until CommitAsync() is called.
// Pass the desired output file name in to the CommitAsync() function.
bool result = false;
try
{
RemoveLabel(options);
// LabelingOptions allows us to set the metadata associated with the labeling operations.
// Review the API Spec at https://aka.ms/mipsdkdocs for details
LabelingOptions labelingOptions = new LabelingOptions()
{
AssignmentMethod = options.AssignmentMethod,
IsDowngradeJustified = true,
JustificationMessage = "BSOne"
};
var handler = CreateFileHandler(options);
/////////////////////////////
//List<string> users = new List<string>()
//{
// //USER_ANYONE
// //"aiptest@unitus.co.kr"
//};
//List<string> roles = new List<string>()
//{
// //Microsoft.InformationProtection.Protection.Roles.Viewer, // 사용자 보호해제 금지, 문서 편집, 인쇄, 내보내기, 복사 금지
// //Microsoft.InformationProtection.Protection.Roles.Reviewer // 사용자 보호해제 금지, 문서 편집, 저장 가능, 그외 인쇄, 내보내기, 복사 금지
// //Microsoft.InformationProtection.Protection.Roles.Author // 공동 작성자 - 보기, 편집, 복사, 인쇄
// //Microsoft.InformationProtection.Protection.Roles.CoOwner // 공동 소유자
// "OWNER"
//};
//List<UserRoles> userroles = new List<UserRoles>()
//{
// new UserRoles(users, roles)
//};
//ProtectionDescriptor protectionDescriptor = new ProtectionDescriptor(userroles);
//handler.SetProtection(protectionDescriptor, new ProtectionSettings());
//////////////////////////////
// Use the SetLabel method on the handler, providing label ID and LabelingOptions
// The handler already references a file, so those details aren't needed.
handler.SetLabel(engine.GetLabelById(options.LabelId), labelingOptions, new ProtectionSettings());
//if (bRemoveProctect)
// handler.RemoveProtection();
//handler.DeleteLabel() // 라벨을 설정할 때 (labelingOptions 매개변수를 통해) 작업이 정당화되어야 하는 경우 JustificationRequiredError가 발생합니다.
// Check to see that modifications occurred on the handler. If not, skip commit.
if (handler.IsModified())
{
result = Task.Run(async () => await handler.CommitAsync(options.OutputName)).Result;
}
// If the commit was successful and GenerateChangeAuditEvents is true, call NotifyCommitSuccessful()
if (result && options.GenerateChangeAuditEvent)
{
// Submits and audit event about the labeling action to Azure Information Protection Analytics
handler.NotifyCommitSuccessful(options.FileName);
}
}
catch (Exception ex)
{
Console.WriteLine("Fail .. SetLabel() .. " + ex.Message);
if (ex.InnerException != null)
Console.WriteLine("Fail .. SetLabel() .. 내부 예외 : " + ex.InnerException.Message);
}
return result;
}
public bool RemoveLabel(FileOptions options)
{
// The change isn't committed to the file referenced by the handler until CommitAsync() is called.
// Pass the desired output file name in to the CommitAsync() function.
bool result = false;
try
{
// LabelingOptions allows us to set the metadata associated with the labeling operations.
// Review the API Spec at https://aka.ms/mipsdkdocs for details
LabelingOptions labelingOptions = new LabelingOptions()
{
AssignmentMethod = options.AssignmentMethod,
IsDowngradeJustified = true,
JustificationMessage = "Auto"
};
var handler = CreateFileHandler(options);
handler.DeleteLabel(labelingOptions);
// Check to see that modifications occurred on the handler. If not, skip commit.
if (handler.IsModified())
{
result = Task.Run(async () => await handler.CommitAsync(options.OutputName)).Result;
}
// If the commit was successful and GenerateChangeAuditEvents is true, call NotifyCommitSuccessful()
if (result && options.GenerateChangeAuditEvent)
{
// Submits and audit event about the labeling action to Azure Information Protection Analytics
handler.NotifyCommitSuccessful(options.FileName);
}
}
catch (Exception ex)
{
Console.WriteLine("Fail .. RemoveLabel() .. " + ex.Message);
if (ex.InnerException != null)
Console.WriteLine("Fail .. RemoveLabel() .. 내부 예외 : " + ex.InnerException.Message);
}
return result;
}
public bool SaveLabelList(string sPath)
{
bool result = true;
string sLabelList = "";
try
{
IEnumerable<Label> labels = ListLabels();
foreach (var label in labels)
{
sLabelList += label.Name + "::" + label.Id + "\n";
if (label.Children.Count > 0)
{
foreach (Label child in label.Children)
{
sLabelList += child.Name + "::" + child.Id + "\n";
}
}
}
System.IO.File.WriteAllText(sPath, sLabelList, Encoding.UTF8);
}
catch (Exception ex)
{
Console.WriteLine("Fail .. SetLabel() .. " + ex.Message);
result = false;
if (ex.InnerException != null)
Console.WriteLine("Fail .. SetLabel() .. 내부 예외 : " + ex.InnerException.Message);
}
return result;
}
public bool RemoveProtection(FileOptions options)
{
bool result = false;
try
{
var handler = CreateFileHandler(options);
if (handler.Protection == null)
return result;
handler.RemoveProtection();
//LabelingOptions labelingOptions = new LabelingOptions()
//{
// AssignmentMethod = AssignmentMethod.Privileged
//};
//handler.DeleteLabel(labelingOptions);
if (handler.IsModified())
{
result = Task.Run(async () => await handler.CommitAsync(options.OutputName)).Result;
}
// If the commit was successful and GenerateChangeAuditEvents is true, call NotifyCommitSuccessful()
if (result && options.GenerateChangeAuditEvent)
{
// Submits and audit event about the labeling action to Azure Information Protection Analytics
handler.NotifyCommitSuccessful(options.FileName);
}
}
catch (Exception ex)
{
Console.WriteLine("Fail .. RemoveProtection() .. " + ex.Message);
if (ex.InnerException != null)
Console.WriteLine("Fail .. RemoveProtection() .. 내부 예외 : " + ex.InnerException.Message);
}
return result;
}
//public IProtectionHandler CreatePublishingHandler(string templateId)
//{
// ProtectionDescriptor protectionDescriptor = new ProtectionDescriptor(templateId);
// PublishingSettings publishingSettings = new PublishingSettings(protectionDescriptor);
// var protectionHandler = engine_protec.CreateProtectionHandlerForPublishing(publishingSettings);
// return protectionHandler;
//}
public bool IsProtection(string sPath)
{
bool result = false;
try
{
var handler = CreateFileHandler(sPath);
if (handler.Protection == null)
return result;
result = true;
}
catch (Exception ex)
{
Console.WriteLine("Fail .. SetProtection() .. " + ex.Message);
if (ex.InnerException != null)
Console.WriteLine("Fail .. SetProtection() .. 내부 예외 : " + ex.InnerException.Message);
}
return result;
}
public bool SetProtection(FileOptions options)
{
bool result = false;
try
{
var handler = CreateFileHandler(options);
if (handler.Protection != null)
return result;
//ProtectionDescriptor protectionDescriptor = new ProtectionDescriptor("de6d83a0-f18c-4c66-b51c-9fcf8fd32e52");
//handler.SetProtection(protectionDescriptor, new ProtectionSettings());
//handler.SetProtection(CreatePublishingHandler("00000000-0000-0000-0000-000000000000"));
//var protecTemp = CreateFileHandler("C:\\Users\\kku\\Desktop\\MIP-TEST\\새 Microsoft Excel 워크시트 - 복사본_mipProctec.xlsx").Protection;
//Console.WriteLine("UserRights={0}", protecTemp.ProtectionDescriptor.UserRights);
//Console.WriteLine("UserRoles={0}", protecTemp.ProtectionDescriptor.UserRoles);
//Console.WriteLine("TempId={0}", protecTemp.ProtectionDescriptor.TemplateId);
//handler.SetProtection(protecTemp);
List<string> users = new List<string>()
{
USER_ANYONE
//"aiptest@unitus.co.kr"
//sDelegatedUserEmail_
};
List<string> roles = new List<string>()
{
//Microsoft.InformationProtection.Protection.Roles.Viewer, // 사용자 보호해제 금지, 문서 편집, 인쇄, 내보내기, 복사 금지
//Microsoft.InformationProtection.Protection.Roles.Reviewer // 사용자 보호해제 금지, 문서 편집, 저장 가능, 그외 인쇄, 내보내기, 복사 금지
Microsoft.InformationProtection.Protection.Roles.Author // 공동 작성자 - 보기, 편집, 복사, 인쇄
//Microsoft.InformationProtection.Protection.Roles.CoOwner // 공동 소유자
//"OWNER"
};
List<UserRoles> userroles = new List<UserRoles>()
{
new UserRoles(users, roles)
};
ProtectionDescriptor protectionDescriptor = new ProtectionDescriptor(userroles);
handler.SetProtection(protectionDescriptor, new ProtectionSettings());
// Check to see that modifications occurred on the handler. If not, skip commit.
if (handler.IsModified())
{
result = Task.Run(async () => await handler.CommitAsync(options.OutputName)).Result;
}
// If the commit was successful and GenerateChangeAuditEvents is true, call NotifyCommitSuccessful()
if (result && options.GenerateChangeAuditEvent)
{
// Submits and audit event about the labeling action to Azure Information Protection Analytics
handler.NotifyCommitSuccessful(options.FileName);
}
}
//catch (BadInputException ex1)
//{
//Console.WriteLine("Fail .. SetProtection() .. " + ex1.Message);
//}
catch (Exception ex)
{
Console.WriteLine("Fail .. SetProtection() .. " + ex.Message);
if (ex.InnerException != null)
Console.WriteLine("Fail .. SetProtection() .. 내부 예외 : " + ex.InnerException.Message);
}
return result;
}
/// <summary>
/// Read the label from a file provided via FileOptions.
/// </summary>
/// <param name="options"></param>
/// <returns></returns>
public ContentLabel GetLabel(FileOptions options)
{
try
{
var handler = CreateFileHandler(options);
return handler.Label;
}
catch (Exception ex)
{
Console.WriteLine("Fail .. GetLabel() .. " + ex.Message);
if (ex.InnerException != null)
Console.WriteLine("Fail .. GetLabel() .. 내부 예외 : " + ex.InnerException.Message);
return null;
}
}
public string GetOwner(string sPath)
{
string sOwner = "";
try
{
var handler = CreateFileHandler(sPath);
if ((handler != null) && (handler.Protection != null))
sOwner = handler.Protection.Owner;
}
catch (Exception ex)
{
Console.WriteLine("Fail .. GetOwner() .. " + ex.Message);
if (ex.InnerException != null)
Console.WriteLine("Fail .. GetOwner() .. 내부 예외 : " + ex.InnerException.Message);
}
return sOwner;
}
public string GetDelegatedUserEmail()
{
return sDelegatedUserEmail_;
}
public string GetEmpNo()
{
return sEmpNo_;
}
}
}