Home
%3CLINGO-SUB%20id%3D%22lingo-sub-875849%22%20slang%3D%22en-US%22%3EHow%20to%20Build%20a%20Custom%20AIP%20Tracking%20Portal%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-875849%22%20slang%3D%22en-US%22%3E%3CP%3EAs%20adoption%20of%20Azure%20Information%20Protection%20continues%20to%20accelerate%2C%20the%20need%20for%20visibility%20into%20who%20has%20accessed%20your%20protected%20documents%20remains%20consistent.%20Although%20we%20provided%20a%20tracking%20portal%20that%20required%20the%20classic%20AIP%20client%2C%20the%20response%20showed%20that%20it%20rarely%20met%20your%20needs.%20Much%20of%20the%20feedback%20focused%20on%20the%20lack%20of%20control%20over%20the%20data%20displayed%20to%20users%20and%20administrators.%20Some%20of%20you%20expressed%20concern%20about%20the%20oversharing%20of%20data%20with%20end%20users%20(i.e.%20the%20location%20of%20the%20person%20who%20opened%20or%20tried%20to%20open%20the%20document)%2C%20while%20others%20requested%20the%20ability%20to%20filter%20labeling%20activity%20by%20region.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EAnother%20limitation%20of%20the%20tracking%20portal%20was%20that%20it%20required%20users%20to%20manually%20register%20each%20document%20they%20wished%20to%20track.%20Given%20the%20effort%20involved%20to%20track%20a%20file%2C%20the%20feature%20was%20seldom%20used%20which%20lead%20us%20to%20remove%20it%20from%20the%20Unified%20Labeling%20(UL)%20client.%20But%20not%20to%20worry.%20Beyond%20the%20solution%20outlined%20in%20this%20blog%2C%20there%20are%20plenty%20of%20%3CA%20href%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2FAzure-Information-Protection%2FHow-you-can-use-the-AIP-unified-labeling-client-TODAY%2Fba-p%2F860132%22%20target%3D%22_blank%22%20rel%3D%22noopener%22%3Eother%20reasons%3C%2FA%3E%20why%20you%20should%20migrate%20to%20the%20UL%20client%20today.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CSTRONG%3ENow%2C%20some%20good%20news%3A%3C%2FSTRONG%3E%20Given%20the%20recent%20integration%20between%20AIP%20audit%20logs%20and%20Azure%20RMS%20logs%2C%20you%20now%20have%20an%20opportunity%20to%20build%20your%20own%20custom%20AIP%20tracking%20solution%20for%20both%20users%20and%20administrators.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EIn%20this%203-part%20blog%20series%2C%20you%20will%20learn%20how%20to%3A%3C%2FP%3E%0A%3COL%3E%0A%3CLI%3ECreate%20a%20custom%20AIP%20Tracking%20portal%20for%20end%20users%3C%2FLI%3E%0A%3CLI%3ECreate%20a%20custom%20AIP%20Tracking%20portal%20for%20Security%20and%2For%20Compliance%20administrators%3C%2FLI%3E%0A%3CLI%3ENotify%20end%20users%20and%2For%20Security%20professionals%20when%20access%20to%20a%20protected%20document%20is%20denied%3C%2FLI%3E%0A%3C%2FOL%3E%0A%3CP%3ELet%E2%80%99s%20begin%20with%20the%20AIP%20Tracking%20portal%20for%20end%20users.%20This%20blog%20will%20focus%20on%20the%20steps%20to%20build%20your%20own%20portal%20and%20present%20the%20desired%20data%20to%20the%20right%20users.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3ELet%E2%80%99s%20look%20at%20the%20concept%20solution.%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20style%3D%22width%3A%20550px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Fgxcuf89792.i.lithium.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F133546iB1E2CCEB22593707%2Fimage-dimensions%2F550x176%3Fv%3D1.0%22%20width%3D%22550%22%20height%3D%22176%22%20alt%3D%22image1.jpg%22%20title%3D%22image1.jpg%22%20%2F%3E%3CSPAN%20class%3D%22lia-inline-image-caption%22%20onclick%3D%22event.preventDefault()%3B%22%3ESolution%20components%3C%2FSPAN%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EThe%20concept%20solution%20is%20quite%20simple.%20For%20this%20example%2C%20we%20used%20an%20ASP.NET%20front%20end%20with%20Azure%20AD%20integration%20and%20two%20Azure%20Functions%20to%20query%20our%20Log%20Analytics%20(LA)%20Workspace.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CSTRONG%3ESome%20notable%20points%3A%3C%2FSTRONG%3E%3C%2FP%3E%0A%3CUL%3E%0A%3CLI%3EYou%20may%20use%20a%20single%20Azure%20Function.%20But%20to%20not%20upset%20any%20micro-services%20architecture%20deities%2C%20we%20decided%20to%20keep%20them%20separate.%3C%2FLI%3E%0A%3CLI%3ETo%20quickly%20test%20the%20solution%20in%20your%20environment%2C%20you%20can%20do%20so%20without%20Azure%20Key%20Vault.%20If%20you%20don%E2%80%99t%20have%20AIP%20data%2C%20any%20other%20accessible%20LA%20Workspace%20will%20do.%3C%2FLI%3E%0A%3CLI%3EBecause%20the%20Service%20Principal%20has%20the%20required%20permission%20to%20read%20the%20audit%20data%2C%20%3CSTRONG%3Ethere%E2%80%99s%20no%20need%20to%20provide%20end%20users%20access%20to%20the%20LA%20Workspace%3C%2FSTRONG%3E.%3C%2FLI%3E%0A%3CLI%3ELastly%2C%20Azure%20Function%20is%20not%20required%20to%20connect%20to%20the%20back-end%20REST%20API%2C%20but%20we%20found%20it%20allowed%20more%20ease%20and%20flexibility.%20Feel%20free%20to%20pick%20your%20favorite%20method.%3C%2FLI%3E%0A%3C%2FUL%3E%0A%3CP%3ELet%E2%80%99s%20unpack%20the%20solution%20a%20bit%20and%20explore%20all%20its%20components%20starting%20from%20the%20back-end%20data%20layer.%3C%2FP%3E%0A%3COL%3E%0A%3CLI%3E%3CSTRONG%3EData%3C%2FSTRONG%3E%20%3CSTRONG%3ELayer%3C%2FSTRONG%3E%20%E2%80%93%20As%20above%20diagram%20illustrates%3B%20AIP%20labeling%20data%20is%20stored%20in%20a%20LA%20Workspace.%20You%20can%20learn%20more%20about%20it%20here.%3C%2FLI%3E%0A%3CLI%3E%3CSTRONG%3ELogic%2Fmiddle%20Layer%3C%2FSTRONG%3E%20%E2%80%93%20This%20part%20of%20the%20solution%20is%20comprised%20of%204%20separate%20components%20(Azure%20Functions%20and%20Key%20Vault%20are%20optional%20for%20testing%20but%20recommended%20in%20production)%3A%3COL%3E%0A%3CLI%3EAn%20Azure%20AD%20application%20(Service%20Principal)%20that%20has%20Log%20Analytics%20Data%20Reader%20permission%20on%20the%20AIP%20Log%20Analytics%20Workspace.%3C%2FLI%3E%0A%3CLI%3ETwo%20Azure%20Functions%3COL%3E%0A%3CLI%3EAn%20Azure%20Function%20that%20makes%20use%20of%20the%20Service%20Principal%20(SP)%20to%20connect%20to%20Log%20Analytics%20via%20REST%20API%20and%20return%20the%20list%20of%20protected%20documents%20for%20the%20current%20user.%3C%2FLI%3E%0A%3CLI%3EA%20second%20Azure%20Function%20that%20makes%20use%20of%20the%20Service%20Principal%20to%20connect%20to%20Log%20Analytics%20via%20REST%20API%20and%20returns%20the%20list%20of%20activities%20for%20a%20selected%20document.%3C%2FLI%3E%0A%3C%2FOL%3E%0A%3C%2FLI%3E%0A%3CLI%3EAzure%20Key%20Vault%20to%20protect%20all%20necessary%20secrets%20(Workspace%20ID%2C%20Client%20ID%2C%20and%20App%20Secret).%3C%2FLI%3E%0A%3C%2FOL%3E%0A%3C%2FLI%3E%0A%3CLI%3E%3CSTRONG%3EUI%20Layer%3C%2FSTRONG%3E%20%E2%80%93%20For%20this%20solution%2C%20we%20used%20an%20ASP.NET%20Web%20application%20with%20Azure%20Active%20Directory%20integration%20for%20authentication.%3C%2FLI%3E%0A%3C%2FOL%3E%0A%3CP%3ELet%E2%80%99s%20look%20at%20the%20configuration%20settings%20for%20the%20solution%20components%20within%20Azure.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EFirst%2C%20here%20is%20a%20look%20at%20the%20settings%20for%20the%20Service%20Principal%20in%20Azure%20AD.%20Notice%20we%20had%20to%20provide%20%3CSTRONG%3EData.Reader%3C%2FSTRONG%3E%20access%20to%20our%20Log%20Analytics%20Workspace.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EFollow%20%3CA%20href%3D%22https%3A%2F%2Fdev.loganalytics.io%2Foms%2Fdocumentation%2F1-Tutorials%2F1-Direct-API%22%20target%3D%22_blank%22%20rel%3D%22noopener%20nofollow%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%22%3Ethese%20instructions%3C%2FA%3E%20on%20how%20to%20create%20a%20Service%20Principal%20in%20Azure.%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20style%3D%22width%3A%20576px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Fgxcuf89792.i.lithium.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F133547iA56505F4B37E9615%2Fimage-dimensions%2F576x249%3Fv%3D1.0%22%20width%3D%22576%22%20height%3D%22249%22%20alt%3D%22image2.png%22%20title%3D%22image2.png%22%20%2F%3E%3CSPAN%20class%3D%22lia-inline-image-caption%22%20onclick%3D%22event.preventDefault()%3B%22%3EAPI%20permission%20page%3C%2FSPAN%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EHere%20is%20a%20view%20of%20the%20two%20Azure%20Functions%20we%20created.%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20style%3D%22width%3A%20478px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Fgxcuf89792.i.lithium.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F133549iDBAA5575B2412623%2Fimage-dimensions%2F478x271%3Fv%3D1.0%22%20width%3D%22478%22%20height%3D%22271%22%20alt%3D%22image3.png%22%20title%3D%22image3.png%22%20%2F%3E%3CSPAN%20class%3D%22lia-inline-image-caption%22%20onclick%3D%22event.preventDefault()%3B%22%3EList%20of%20Functions%20in%20Azure%3C%2FSPAN%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EThen%20we%20stored%20the%20Workspace%20ID%2C%20SP%20Client%20ID%2C%20and%20SP%20Client%20Secret%20in%20Azure%20Key%20Vault%20as%20shown%20below.%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20style%3D%22width%3A%20464px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Fgxcuf89792.i.lithium.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F133550i2EBB4F84B56E2AE7%2Fimage-dimensions%2F464x212%3Fv%3D1.0%22%20width%3D%22464%22%20height%3D%22212%22%20alt%3D%22image4.png%22%20title%3D%22image4.png%22%20%2F%3E%3CSPAN%20class%3D%22lia-inline-image-caption%22%20onclick%3D%22event.preventDefault()%3B%22%3EAzure%20Key%20Vault%20Secrets%3C%2FSPAN%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EWe%20then%20configured%20both%20Azure%20Functions%20to%20get%20the%20required%20secrets%20from%20Azure%20Key%20Vault.%20Please%20check%20out%20Jeff%E2%80%99s%20excellent%20%3CA%20href%3D%22https%3A%2F%2Fmedium.com%2Fstatuscode%2Fgetting-key-vault-secrets-in-azure-functions-37620fd20a0b%22%20target%3D%22_blank%22%20rel%3D%22noopener%20nofollow%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%22%3Eblog%20post%3C%2FA%3E%20on%20how%20to%20set%20this%20up.%20Please%20don%E2%80%99t%20skip%20the%20part%20about%20using%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fapp-service%2Foverview-managed-identity%23creating-an-app-with-an-identity%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%22%3Emanaged%20identities%3C%2FA%3E%20for%20Azure%20Functions.%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20style%3D%22width%3A%20614px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Fgxcuf89792.i.lithium.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F133551iEEC03357B2CE4E83%2Fimage-dimensions%2F614x135%3Fv%3D1.0%22%20width%3D%22614%22%20height%3D%22135%22%20alt%3D%22image5.jpg%22%20title%3D%22image5.jpg%22%20%2F%3E%3CSPAN%20class%3D%22lia-inline-image-caption%22%20onclick%3D%22event.preventDefault()%3B%22%3EAzure%20Function%20settings%3C%2FSPAN%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3ENow%20let%E2%80%99s%20look%20at%20some%20code%2C%20shall%20we%3F%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EWith%20the%20above%20components%20configured%2C%20it%E2%80%99s%20now%20time%20to%20put%20them%20in%20use%20and%20see%20if%20everything%20works%20as%20expected.%3C%2FP%3E%0A%3CP%3EThe%20first%20step%20is%20to%20write%20the%20code%20for%20the%20Azure%20Function%20that%20will%20retrieve%20the%20list%20of%20protected%20documents%20for%20a%20given%20user%20email%2FID.%20I%20used%20Visual%20Studio%202019%20to%20create%20both%20Functions%2C%20but%20you%20can%20leverage%20VS%20Code%20and%20other%20tools.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CSTRONG%3EIMPORTANT%3C%2FSTRONG%3E%3A%20This%20is%20a%20concept%20application%20and%20therefore%20has%20no%20error%20checking%20or%20any%20of%20the%20other%20enterprise%20grade%20optimizations%20you%20would%20need%20on%20a%20production%20solution.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EWe%20start%20by%20retrieving%20the%20required%20secrets%20from%20the%20Function%E2%80%99s%20variable%20setup%20above.%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20style%3D%22width%3A%20588px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Fgxcuf89792.i.lithium.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F133552iA89E9474FCE140D8%2Fimage-dimensions%2F588x103%3Fv%3D1.0%22%20width%3D%22588%22%20height%3D%22103%22%20alt%3D%22image6.png%22%20title%3D%22image6.png%22%20%2F%3E%3CSPAN%20class%3D%22lia-inline-image-caption%22%20onclick%3D%22event.preventDefault()%3B%22%3EC-Sharp%20Code%20to%20get%20Secrets%20from%20AKV%3C%2FSPAN%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3EYou%20then%20need%20to%20setup%20the%20code%20required%20to%20authenticate%20to%20the%20Log%20Analytics%20Workspace.%20This%20code%20was%20borrowed%20from%20the%20%3CA%20href%3D%22https%3A%2F%2Fapi.loganalytics.io%22%20target%3D%22_blank%22%20rel%3D%22noopener%20nofollow%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%22%3ELog%20Analytics%20API%20site%3C%2FA%3E.%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20style%3D%22width%3A%20999px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Fgxcuf89792.i.lithium.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F133554i6B0AC6391D05CED1%2Fimage-size%2Flarge%3Fv%3D1.0%26amp%3Bpx%3D999%22%20alt%3D%22image7.png%22%20title%3D%22image7.png%22%20%2F%3E%3CSPAN%20class%3D%22lia-inline-image-caption%22%20onclick%3D%22event.preventDefault()%3B%22%3EAzure%20Function%20code%3C%2FSPAN%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3EFinally%2C%20you%20configure%20and%20update%20your%20Kusto%20query%20with%20the%20email%20address%20of%20the%20current%20user%20and%20call%20the%20Log%20Analytics%20endpoint.%20Please%20look%20at%20the%20Log%20Analytics%20API%20link%20above%20to%20see%20the%20JSON%20response%20sample.%20In%20this%20case%20we%20are%20just%20returning%20the%20first%20table.%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20style%3D%22width%3A%20790px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Fgxcuf89792.i.lithium.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F133557i8B37802B20D38480%2Fimage-dimensions%2F790x407%3Fv%3D1.0%22%20width%3D%22790%22%20height%3D%22407%22%20alt%3D%22image8.png%22%20title%3D%22image8.png%22%20%2F%3E%3CSPAN%20class%3D%22lia-inline-image-caption%22%20onclick%3D%22event.preventDefault()%3B%22%3EKusto%20query%20in%20Azure%20Function%3C%2FSPAN%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3ENow%20you%20can%20run%20the%20Function%20in%20Visual%20Studio%20to%20make%20sure%20you%20code%20is%20talking%20to%20the%20back-end%20as%20expected.%20If%20you%20pass%20a%20user%20email%20from%20your%20tenant%20on%20the%20%E2%80%9Cname%E2%80%9D%20parameter%2C%20you%20should%20see%20some%20JSON%20data%20returned%20on%20the%20browser.%20Happy%20times.%20Your%20solution%20is%20setup%20and%20ready%20to%20be%20hosted%20(in%20the%20cloud%20of%20course).%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20style%3D%22width%3A%20684px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Fgxcuf89792.i.lithium.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F133560i9E9623E635228E87%2Fimage-dimensions%2F684x139%3Fv%3D1.0%22%20width%3D%22684%22%20height%3D%22139%22%20alt%3D%22image9.png%22%20title%3D%22image9.png%22%20%2F%3E%3CSPAN%20class%3D%22lia-inline-image-caption%22%20onclick%3D%22event.preventDefault()%3B%22%3EKusto%20query%20results%3C%2FSPAN%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EOnce%20you%20confirm%20that%20your%20code%20returns%20the%20desired%20data%2C%20you%20are%20ready%20to%20publish%20to%20Azure.%20Follow%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fazure-functions%2Ffunctions-create-your-first-function-visual-studio%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%22%3Ethese%20instructions%3C%2FA%3E%20to%20learn%20about%20publishing%20Azure%20Functions%20from%20Visual%20Studio%20into%20an%20Azure%20Web%20Service.%3C%2FP%3E%0A%3CP%3EYou%20can%20now%20repeat%20these%20steps%20to%20create%20your%20second%20Azure%20Function%20making%20sure%20you%20pass%20the%20selected%20document%20instead%20of%20the%20user%20email.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EFinally%2C%20let%E2%80%99s%20look%20at%20the%20user%20facing%20front%20end%20application.%20For%20this%20example%2C%20we%20created%20a%20simple%20ASP.NET%20web%20application%20right%20from%20a%20Visual%20Studio%20template.%20You%20can%20use%20a%20low-code%2Fno-code%20solution%20like%20PowerApps%20of%20course%20but%20we%E2%80%99ll%20leave%20that%20one%20up%20to%20you.%3C%2FP%3E%0A%3CP%3EAs%20shown%20below%2C%20the%20very%20talented%20design%20staff%20at%20Contoso%20put%20together%20this%20elegant%20UI%20to%20display%20a%20list%20of%20recently%20protected%20documents%20by%20the%20authenticated%20user.%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20style%3D%22width%3A%20626px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Fgxcuf89792.i.lithium.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F133561i15E8134F73FAE774%2Fimage-dimensions%2F626x195%3Fv%3D1.0%22%20width%3D%22626%22%20height%3D%22195%22%20alt%3D%22image10.png%22%20title%3D%22image10.png%22%20%2F%3E%3CSPAN%20class%3D%22lia-inline-image-caption%22%20onclick%3D%22event.preventDefault()%3B%22%3ECustom%20AIP%20Tracking%20Portal%20UI%3C%2FSPAN%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EUpon%20clicking%20on%20the%20%E2%80%9CTrack%20File%E2%80%9D%20button%20next%20to%20each%20document%2C%20a%20list%20of%20activity%20for%20the%20file%20is%20display%20right%20below.%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20style%3D%22width%3A%20724px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Fgxcuf89792.i.lithium.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F133562i1E87D2C591524B6B%2Fimage-dimensions%2F724x129%3Fv%3D1.0%22%20width%3D%22724%22%20height%3D%22129%22%20alt%3D%22image11.png%22%20title%3D%22image11.png%22%20%2F%3E%3CSPAN%20class%3D%22lia-inline-image-caption%22%20onclick%3D%22event.preventDefault()%3B%22%3EAIP%20Document%20activity%3C%2FSPAN%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EAt%20this%20point%20the%20file%20owner%20can%20see%20the%20list%20of%20users%20who%20have%20successfully%20opened%20(%3CSTRONG%3EAccess%3C%2FSTRONG%3E)%20and%20those%20who%20were%20denied%20access%20(%3CSTRONG%3EAccessDenied%3C%2FSTRONG%3E)%20to%20the%20document.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EThat%E2%80%99s%20all%20there%E2%80%99s%20to%20it.%20You%20can%20find%20the%20source%20code%20used%20in%20this%20sample%20in%20this%20%3CA%20href%3D%22https%3A%2F%2Fgithub.com%2FAzure-Samples%2FAIP-Custom-Tracking-Portal-Samples%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%22%3EGitHub%20repo%3C%2FA%3E.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EWe%20hope%20this%20walk%20through%20has%20sparked%20some%20ideas%20for%20your%20own%20solution%20to%20get%20label%20activity%20into%20the%20hands%20of%20your%20users.%20If%20you%20do%20or%20plan%20to%20use%20something%20like%20this%20in%20your%20own%20environment%2C%20we%20would%20love%20to%20hear%20about%20it.%20Please%20visit%20the%20%3CA%20href%3D%22https%3A%2F%2Fwww.yammer.com%2Faskipteam%22%20target%3D%22_blank%22%20rel%3D%22noopener%20nofollow%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%22%3EAIP%20Yammer%20group%3C%2FA%3E%20and%20share%20your%20thoughts%2Fsolution%20with%20the%20hashtag%20%3CSTRONG%3E%23AIPLogsSolution%3C%2FSTRONG%3E.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EThanks%20for%20your%20reading%20and%20stay%20tuned%20for%20the%20second%20installment%20of%20this%20series.%20Happy%20coding.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-TEASER%20id%3D%22lingo-teaser-875849%22%20slang%3D%22en-US%22%3E%3CP%3E%3CSPAN%3EThis%20blog%20contains%20sample%20code%20and%20the%20steps%20required%20to%20help%20you%20build%20a%20custom%20AIP%20Tracking%20portal.%20The%20portal%20outlined%20in%20this%20solution%20allows%20end%20users%20to%20see%20who%20has%20accessed%20or%20tried%20to%20access%20protected%20files%20they've%20shared%20internally%20or%20externally.%3C%2FSPAN%3E%3C%2FP%3E%3C%2FLINGO-TEASER%3E%3CLINGO-SUB%20id%3D%22lingo-sub-875916%22%20slang%3D%22en-US%22%3ERe%3A%20How%20to%20Build%20a%20Custom%20AIP%20Tracking%20Portal%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-875916%22%20slang%3D%22en-US%22%3E%3CP%3ENice%20work%2C%26nbsp%3B%3CA%20href%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fuser%2Fviewprofilepage%2Fuser-id%2F102197%22%20target%3D%22_blank%22%3E%40Rafael%20Dominguez%3C%2FA%3E!%3C%2FP%3E%3C%2FLINGO-BODY%3E

As adoption of Azure Information Protection continues to accelerate, the need for visibility into who has accessed your protected documents remains consistent. Although we provided a tracking portal that required the classic AIP client, the response showed that it rarely met your needs. Much of the feedback focused on the lack of control over the data displayed to users and administrators. Some of you expressed concern about the oversharing of data with end users (i.e. the location of the person who opened or tried to open the document), while others requested the ability to filter labeling activity by region.

 

Another limitation of the tracking portal was that it required users to manually register each document they wished to track. Given the effort involved to track a file, the feature was seldom used which lead us to remove it from the Unified Labeling (UL) client. But not to worry. Beyond the solution outlined in this blog, there are plenty of other reasons why you should migrate to the UL client today.

 

Now, some good news: Given the recent integration between AIP audit logs and Azure RMS logs, you now have an opportunity to build your own custom AIP tracking solution for both users and administrators.

 

In this 3-part blog series, you will learn how to:

  1. Create a custom AIP Tracking portal for end users
  2. Create a custom AIP Tracking portal for Security and/or Compliance administrators
  3. Notify end users and/or Security professionals when access to a protected document is denied

Let’s begin with the AIP Tracking portal for end users. This blog will focus on the steps to build your own portal and present the desired data to the right users.

 

Let’s look at the concept solution.

image1.jpgSolution components

 

The concept solution is quite simple. For this example, we used an ASP.NET front end with Azure AD integration and two Azure Functions to query our Log Analytics (LA) Workspace.

 

Some notable points:

  • You may use a single Azure Function. But to not upset any micro-services architecture deities, we decided to keep them separate.
  • To quickly test the solution in your environment, you can do so without Azure Key Vault. If you don’t have AIP data, any other accessible LA Workspace will do.
  • Because the Service Principal has the required permission to read the audit data, there’s no need to provide end users access to the LA Workspace.
  • Lastly, Azure Function is not required to connect to the back-end REST API, but we found it allowed more ease and flexibility. Feel free to pick your favorite method.

Let’s unpack the solution a bit and explore all its components starting from the back-end data layer.

  1. Data Layer – As above diagram illustrates; AIP labeling data is stored in a LA Workspace. You can learn more about it here.
  2. Logic/middle Layer – This part of the solution is comprised of 4 separate components (Azure Functions and Key Vault are optional for testing but recommended in production):
    1. An Azure AD application (Service Principal) that has Log Analytics Data Reader permission on the AIP Log Analytics Workspace.
    2. Two Azure Functions
      1. An Azure Function that makes use of the Service Principal (SP) to connect to Log Analytics via REST API and return the list of protected documents for the current user.
      2. A second Azure Function that makes use of the Service Principal to connect to Log Analytics via REST API and returns the list of activities for a selected document.
    3. Azure Key Vault to protect all necessary secrets (Workspace ID, Client ID, and App Secret).
  3. UI Layer – For this solution, we used an ASP.NET Web application with Azure Active Directory integration for authentication.

Let’s look at the configuration settings for the solution components within Azure.

 

First, here is a look at the settings for the Service Principal in Azure AD. Notice we had to provide Data.Reader access to our Log Analytics Workspace.

 

Follow these instructions on how to create a Service Principal in Azure.

image2.pngAPI permission page

 

Here is a view of the two Azure Functions we created.

image3.pngList of Functions in Azure

 

Then we stored the Workspace ID, SP Client ID, and SP Client Secret in Azure Key Vault as shown below.

image4.pngAzure Key Vault Secrets

 

We then configured both Azure Functions to get the required secrets from Azure Key Vault. Please check out Jeff’s excellent blog post on how to set this up. Please don’t skip the part about using managed identities for Azure Functions.

image5.jpgAzure Function settings

 

Now let’s look at some code, shall we?

 

With the above components configured, it’s now time to put them in use and see if everything works as expected.

The first step is to write the code for the Azure Function that will retrieve the list of protected documents for a given user email/ID. I used Visual Studio 2019 to create both Functions, but you can leverage VS Code and other tools.

 

IMPORTANT: This is a concept application and therefore has no error checking or any of the other enterprise grade optimizations you would need on a production solution.

 

We start by retrieving the required secrets from the Function’s variable setup above.

image6.pngC-Sharp Code to get Secrets from AKV

You then need to setup the code required to authenticate to the Log Analytics Workspace. This code was borrowed from the Log Analytics API site.

image7.pngAzure Function code

Finally, you configure and update your Kusto query with the email address of the current user and call the Log Analytics endpoint. Please look at the Log Analytics API link above to see the JSON response sample. In this case we are just returning the first table.

image8.pngKusto query in Azure Function

 

Now you can run the Function in Visual Studio to make sure you code is talking to the back-end as expected. If you pass a user email from your tenant on the “name” parameter, you should see some JSON data returned on the browser. Happy times. Your solution is setup and ready to be hosted (in the cloud of course).

image9.pngKusto query results

 

Once you confirm that your code returns the desired data, you are ready to publish to Azure. Follow these instructions to learn about publishing Azure Functions from Visual Studio into an Azure Web Service.

You can now repeat these steps to create your second Azure Function making sure you pass the selected document instead of the user email.

 

Finally, let’s look at the user facing front end application. For this example, we created a simple ASP.NET web application right from a Visual Studio template. You can use a low-code/no-code solution like PowerApps of course but we’ll leave that one up to you.

As shown below, the very talented design staff at Contoso put together this elegant UI to display a list of recently protected documents by the authenticated user.

image10.pngCustom AIP Tracking Portal UI

 

Upon clicking on the “Track File” button next to each document, a list of activity for the file is display right below.

image11.pngAIP Document activity

 

At this point the file owner can see the list of users who have successfully opened (Access) and those who were denied access (AccessDenied) to the document.

 

That’s all there’s to it. You can find the source code used in this sample in this GitHub repo.

 

We hope this walk through has sparked some ideas for your own solution to get label activity into the hands of your users. If you do or plan to use something like this in your own environment, we would love to hear about it. Please visit the AIP Yammer group and share your thoughts/solution with the hashtag #AIPLogsSolution.

 

Thanks for your reading and stay tuned for the second installment of this series. Happy coding.

 

 

1 Comment
Microsoft

Nice work, @Rafael Dominguez!