PolicyManager.cs 12 KB

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