PolicyManager.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.ObjectModel;
  4. using System.Threading.Tasks;
  5. using Microsoft.InformationProtection;
  6. using Microsoft.InformationProtection.Policy;
  7. using Microsoft.InformationProtection.Policy.Actions;
  8. using Serilog;
  9. using Serilog.Core;
  10. namespace AipGateway.AIP
  11. {
  12. public class PolicyManager : AbstractManager
  13. {
  14. private IPolicyProfile _profile = null;
  15. private IPolicyEngine _engine = null;
  16. public PolicyManager(Logger logger, string clientId) : base(logger, clientId)
  17. {
  18. }
  19. ~PolicyManager() => this.Dispose(false);
  20. public override void Dispose()
  21. {
  22. this.Dispose(true);
  23. GC.SuppressFinalize((object)this);
  24. }
  25. protected virtual void Dispose(bool disposing)
  26. {
  27. lock (this)
  28. {
  29. if (_profile != null && _engine != null)
  30. {
  31. //_profile.UnloadEngineAsync(_engine.Settings.Id).Wait();
  32. _profile.Dispose();
  33. _engine.Dispose();
  34. }
  35. _engine = null;
  36. _profile = null;
  37. }
  38. }
  39. public override bool CreateProfile(ref MipContext mipContext)
  40. {
  41. try
  42. {
  43. var profileSettings = new PolicyProfileSettings(mipContext,
  44. //CacheStorageType.OnDiskEncrypted
  45. CacheStorageType.InMemory
  46. );
  47. // IFileProfile은 특정 애플리케이션에 대한 모든 SDK 작업의 루트입니다.
  48. _profile = Task.Run(async () => await MIP.LoadPolicyProfileAsync(profileSettings)).Result;
  49. }
  50. catch (Exception e)
  51. {
  52. SetError(1, "PolicyManager::CreateProfile Failed.", e.Message);
  53. return false;
  54. }
  55. return _profile != null;
  56. }
  57. public override bool CreateEngine(ref Identity identity, ref AuthDelegateImplementation authDelegate)
  58. {
  59. try
  60. {
  61. authDelegate.ResetError();
  62. var engineSettings = new PolicyEngineSettings(identity.Email, authDelegate, string.Empty, "en-US")
  63. {
  64. // Provide the identity for service discovery.
  65. Identity = identity
  66. };
  67. _engine = Task.Run(async () => await _profile.AddEngineAsync(engineSettings)).Result;
  68. }
  69. catch (Exception e)
  70. {
  71. if (authDelegate.LastErrNo != 0)
  72. {
  73. SetError(authDelegate.LastErrNo, "PolicyManager::CreateEngine Failed.", authDelegate.LastErrMsg);
  74. }
  75. else
  76. {
  77. SetError(2, "PolicyManager::CreateEngine Failed.", e.Message);
  78. }
  79. return false;
  80. }
  81. return _engine != null;
  82. }
  83. public IEnumerable<Label> ListSensitivityLabels()
  84. {
  85. // 사용자 주체의 경우 이는 사용자별로 다릅니다.
  86. // 서비스 주체의 경우 이는 서비스별로 또는 전역적일 수 있습니다.
  87. return _engine.ListSensitivityLabels();
  88. }
  89. private IPolicyHandler CreatePolicyHandler(ExecutionStateOptions options)
  90. {
  91. try
  92. {
  93. var handler = _engine.CreatePolicyHandler(options.generateAuditEvent);
  94. return handler;
  95. }
  96. catch (Exception ex)
  97. {
  98. SetError(91, "PolicyManager::CreatePolicyHandler Failed.", ex.Message);
  99. }
  100. return null;
  101. }
  102. public ReadOnlyCollection<Microsoft.InformationProtection.Policy.Actions.Action> ComputeActions(ExecutionStateOptions options)
  103. {
  104. var handler = CreatePolicyHandler(options);
  105. if (handler == null)
  106. {
  107. return null;
  108. }
  109. try
  110. {
  111. ExecutionStateImplementation state = new ExecutionStateImplementation(options);
  112. var actions = handler.ComputeActions(state);
  113. if (actions.Count == 0 && options.generateAuditEvent)
  114. {
  115. handler.NotifyCommittedActions(state);
  116. }
  117. return actions;
  118. }
  119. catch (Exception ex)
  120. {
  121. SetError(92, "PolicyManager::ComputeActions Failed.", ex.Message);
  122. }
  123. return null;
  124. }
  125. public bool ComputeActionLoop(ExecutionStateOptions options)
  126. {
  127. ExecutionStateImplementation state = new ExecutionStateImplementation(options);
  128. var handler = CreatePolicyHandler(options);
  129. var actions = handler.ComputeActions(state);
  130. while (actions.Count > 0)
  131. {
  132. //Console.WriteLine("Action Count: {0}", actions.Count);
  133. foreach (var action in actions)
  134. {
  135. switch (action.ActionType)
  136. {
  137. case ActionType.Metadata:
  138. var derivedMetadataAction = (MetadataAction)action;
  139. if (derivedMetadataAction.MetadataToRemove.Count > 0)
  140. {
  141. //Console.WriteLine("*** Action: Remove Metadata.");
  142. //Rather than iterate, in the same we just remove it all.
  143. options.metadata.Clear();
  144. }
  145. if (derivedMetadataAction.MetadataToAdd.Count > 0)
  146. {
  147. //Console.WriteLine("*** Action: Apply Metadata.");
  148. //Iterate through metadata and add to options
  149. foreach (var item in derivedMetadataAction.MetadataToAdd)
  150. {
  151. options.metadata.Add(item.Key, item.Value);
  152. //Console.WriteLine("*** Added: {0} - {1}", item.Key, item.Value);
  153. }
  154. }
  155. break;
  156. case ActionType.ProtectByTemplate:
  157. var derivedProtectbyTemplateAction = (ProtectByTemplateAction)action;
  158. options.templateId = derivedProtectbyTemplateAction.TemplateId;
  159. //Console.WriteLine("*** Action: Protect by Template: {0}", derivedProtectbyTemplateAction.TemplateId);
  160. break;
  161. case ActionType.RemoveProtection:
  162. var derivedRemoveProtectionAction = (RemoveProtectionAction)action;
  163. options.templateId = string.Empty;
  164. //Console.Write("*** Action: Remove Protection.");
  165. break;
  166. case ActionType.Justify:
  167. var derivedJustificationAction = (JustifyAction)action;
  168. //Console.WriteLine("*** Justification Required!");
  169. //Console.Write("Provide Justification: ");
  170. string justificationMessage = Console.ReadLine();
  171. options.isDowngradeJustified = true;
  172. options.downgradeJustification = justificationMessage;
  173. break;
  174. case ActionType.AddContentFooter:
  175. // Any other actions must be explicitly defined after this.
  176. break;
  177. default:
  178. break;
  179. }
  180. }
  181. state = new ExecutionStateImplementation(options);
  182. actions = handler.ComputeActions(state);
  183. //Console.WriteLine("*** Remaining Action Count: {0}", actions.Count);
  184. }
  185. if (options.generateAuditEvent && actions.Count == 0)
  186. {
  187. handler.NotifyCommittedActions(state);
  188. }
  189. return true;
  190. }
  191. public Label GetLabelById(string labelId)
  192. {
  193. Label label;
  194. try
  195. {
  196. label = _engine.GetLabelById(labelId);
  197. }
  198. catch (Exception ex)
  199. {
  200. SetError(99, "FileManager::GetLabel Failed. Request Label Id: " + labelId, ex.Message);
  201. return null;
  202. }
  203. return label;
  204. }
  205. public bool SetComputeAction(string fileName, string actualFileName, string email, string labelId, string comments)
  206. {
  207. ExecutionStateOptions options = new ExecutionStateOptions();
  208. Label label = GetLabelById(labelId);
  209. options.newLabel = label; // 레벨은 선택할 수 있다.
  210. options.actionSource = ActionSource.Manual;
  211. options.assignmentMethod = AssignmentMethod.Standard;
  212. options.contentFormat = Microsoft.InformationProtection.Policy.ContentFormat.File;
  213. options.contentIdentifier = fileName;
  214. options.dataState = DataState.Use;
  215. options.isDowngradeJustified = false;
  216. options.generateAuditEvent = true;
  217. options.metadata = new Dictionary<string, string>();
  218. if (options.newLabel == null)
  219. {
  220. return false;
  221. }
  222. var initialActions = ComputeActions(options);
  223. // 추가 작업이 필요한 경우 ExecutionStateImplementation.cs에서 GetSupportedActions를 수정하세요.
  224. // 그런 다음 관심 있는 작업(예: 머리글, 바닥글 또는 워터마크 적용)에 대한 작업을 반복합니다.
  225. // 파생된 작업에서 콘텐츠 표시 정보를 얻을 수 있습니다.
  226. foreach (var item in initialActions)
  227. {
  228. switch (item.ActionType)
  229. {
  230. case ActionType.Metadata:
  231. options.metadata.Clear();
  232. foreach (var data in ((MetadataAction)item).MetadataToAdd)
  233. {
  234. options.metadata.Add(data.Key, data.Value);
  235. }
  236. break;
  237. case ActionType.ProtectByTemplate:
  238. options.templateId = ((ProtectByTemplateAction)item).TemplateId;
  239. break;
  240. default:
  241. break;
  242. }
  243. }
  244. options.newLabel = GetLabelById(labelId);
  245. var result = ComputeActionLoop(options);
  246. return result;
  247. }
  248. }
  249. }