{"id":975,"date":"2021-01-03T20:43:57","date_gmt":"2021-01-03T19:43:57","guid":{"rendered":"http:\/\/www.vatland.no\/?p=975"},"modified":"2021-01-07T12:25:57","modified_gmt":"2021-01-07T11:25:57","slug":"log-tenants-from-office-365-to-local-db","status":"publish","type":"post","link":"https:\/\/www.vatland.no\/index.php\/log-tenants-from-office-365-to-local-db\/","title":{"rendered":"Log tenants from office 365 to local Db"},"content":{"rendered":"<p>Hi,<br \/>\nI like to keep control of how many licenses our cutomers use versus how many\u00a0 have been purchased.<br \/>\nHere is 1st part\u00a0 my PS script to copy the info from csp to the DB. I will start creating a database and table to keep a list of all the tenants in the csp. You will also need an service principal in the tenant.<br \/>\nTo create a SPN in CSP check this :<a href=\"https:\/\/www.vatland.no\/index.php\/csp-access-to-tenants-using-powershell-part-1\/\">CSP access to tenants using powershell. Part 1<\/a><br \/>\nI am also using the storedcredential -&gt; <a title=\"Get Secretserver secret\" href=\"https:\/\/www.vatland.no\/index.php\/get-secretserver-secret\/\">Get Secretserver secret<\/a><\/p>\n<div class=\"codecolorer-container powershell default\" style=\"overflow:auto;white-space:nowrap;width:435px;height:300px;\"><div class=\"powershell codecolorer\"><span class=\"kw3\">function<\/span> Update<span class=\"sy0\">-<\/span>TenantListinDB <span class=\"br0\">&#123;<\/span><br \/>\n<br \/>\n<span class=\"co1\"># Set all customers in database where active is &amp;lt; 10 to inactive<\/span><br \/>\nimport<span class=\"sy0\">-<\/span>module partnercenter<br \/>\n<span class=\"re0\">$tid<\/span> <span class=\"sy0\">=<\/span> <span class=\"st0\">&quot;Partnercenter Tenant ID&quot;<\/span><br \/>\n<span class=\"re0\">$appid<\/span> <span class=\"sy0\">=<\/span> <span class=\"st0\">&quot;AppID&quot;<\/span><br \/>\n<span class=\"re0\">$k<\/span> <span class=\"sy0\">=<\/span> <span class=\"br0\">&#40;<\/span>get<span class=\"sy0\">-<\/span>storedcredential <span class=\"sy0\">-<\/span>user <span class=\"re0\">$appid<\/span><span class=\"br0\">&#41;<\/span>.password<br \/>\n<span class=\"re0\">$token<\/span> <span class=\"sy0\">=<\/span> <span class=\"br0\">&#40;<\/span>get<span class=\"sy0\">-<\/span>storedcredential <span class=\"sy0\">-<\/span>user cspuser<span class=\"br0\">&#41;<\/span>.getnetworkcredential<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span>.password<br \/>\n<span class=\"re0\">$app<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw1\">New-Object<\/span> System.Management.Automation.PSCredential <span class=\"kw5\">-ArgumentList<\/span> <span class=\"re0\">$appid<\/span><span class=\"sy0\">,<\/span> <span class=\"re0\">$k<\/span><br \/>\n<span class=\"re0\">$partneraccesstoken<\/span> <span class=\"sy0\">=<\/span> New<span class=\"sy0\">-<\/span>PartnerAccessToken <span class=\"sy0\">-<\/span>RefreshToken <span class=\"re0\">$token<\/span> <span class=\"kw5\">-Credential<\/span> <span class=\"re0\">$app<\/span> <span class=\"sy0\">-<\/span>Tenant <span class=\"re0\">$tid<\/span> <span class=\"sy0\">-<\/span>Scopes <span class=\"st0\">'https:\/\/api.partnercenter.microsoft.com\/user_impersonation'<\/span> <span class=\"sy0\">-<\/span>ServicePrincipal <span class=\"sy0\">-<\/span>ApplicationId <span class=\"re0\">$appid<\/span> <span class=\"co1\"># -Resource &quot;https:\/\/api.partnercenter.microsoft.com&quot;<\/span><br \/>\n<span class=\"re0\">$connected<\/span> <span class=\"sy0\">=<\/span> Connect<span class=\"sy0\">-<\/span>PartnerCenter <span class=\"sy0\">-<\/span>ApplicationId <span class=\"re0\">$appid<\/span> <span class=\"kw5\">-Credential<\/span> <span class=\"re0\">$app<\/span> <span class=\"sy0\">-<\/span>RefreshToken <span class=\"re0\">$token<\/span><br \/>\n<span class=\"kw3\">if<\/span> <span class=\"br0\">&#40;<\/span><span class=\"kw4\">-not<\/span> <span class=\"re0\">$connected<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span> <span class=\"kw3\">throw<\/span> <span class=\"st0\">&quot;Error connecting to partnercenter..&quot;<\/span> <span class=\"br0\">&#125;<\/span><br \/>\nupdate<span class=\"sy0\">-<\/span>storedcredential <span class=\"sy0\">-<\/span>user cspuser <span class=\"sy0\">-<\/span>secret <span class=\"br0\">&#40;<\/span><span class=\"re0\">$partneraccesstoken<\/span>.RefreshToken <span class=\"sy0\">|<\/span> <span class=\"kw1\">ConvertTo-SecureString<\/span> <span class=\"kw5\">-AsPlainText<\/span> <span class=\"kw5\">-Force<\/span><span class=\"br0\">&#41;<\/span><br \/>\n<br \/>\n<span class=\"re0\">$SQLInstance<\/span> <span class=\"sy0\">=<\/span> <span class=\"st0\">&quot;localhost\\SQLExpress&quot;<\/span><br \/>\n<span class=\"re0\">$SQLDatabase<\/span> <span class=\"sy0\">=<\/span> <span class=\"st0\">&quot;Microsoft365&quot;<\/span><br \/>\n<span class=\"re0\">$SQLUsername<\/span> <span class=\"sy0\">=<\/span> <span class=\"st0\">&quot;&quot;<\/span><br \/>\n<span class=\"re0\">$SQLPassword<\/span> <span class=\"sy0\">=<\/span> <span class=\"st0\">&quot;&quot;<\/span><br \/>\n<br \/>\n<span class=\"re0\">$customers<\/span> <span class=\"sy0\">=<\/span> Get<span class=\"sy0\">-<\/span>PartnerCustomer<br \/>\n<br \/>\n<span class=\"re0\">$deactivated<\/span> <span class=\"sy0\">=<\/span> Invoke<span class=\"sy0\">-<\/span>Sqlcmd <span class=\"kw5\">-Query<\/span> <span class=\"st0\">&quot;update tenants set active='0' where active &amp;lt; '10'&quot;<\/span> <span class=\"sy0\">-<\/span>ServerInstance <span class=\"re0\">$SQLInstance<\/span> <span class=\"sy0\">-<\/span>Database <span class=\"re0\">$SQLDatabase<\/span><br \/>\n<span class=\"kw1\">Write-Host<\/span> <span class=\"st0\">&quot;Parsing $(($customers).count) tenants.&quot;<\/span><br \/>\n<span class=\"kw3\">foreach<\/span> <span class=\"br0\">&#40;<\/span><span class=\"re0\">$customer<\/span> <span class=\"kw3\">in<\/span> <span class=\"re0\">$customers<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n<span class=\"co1\"># Check if exists<\/span><br \/>\n<span class=\"re0\">$select<\/span> <span class=\"sy0\">=<\/span> <span class=\"st0\">&quot;select * from tenants where tenantid like '$($customer.customerid)'&quot;<\/span><br \/>\n<span class=\"re0\">$found<\/span> <span class=\"sy0\">=<\/span> invoke<span class=\"sy0\">-<\/span>sqlcmd <span class=\"kw5\">-query<\/span> <span class=\"re0\">$select<\/span> <span class=\"sy0\">-<\/span>ServerInstance <span class=\"re0\">$SQLInstance<\/span> <span class=\"sy0\">-<\/span>Database <span class=\"re0\">$SQLDatabase<\/span><br \/>\n<span class=\"kw3\">if<\/span> <span class=\"br0\">&#40;<\/span><span class=\"re0\">$found<\/span> <span class=\"kw4\">-eq<\/span> <span class=\"re0\">$null<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n<span class=\"kw1\">Write-Host<\/span> <span class=\"st0\">&quot;Inserting tenant:&quot;<\/span> <span class=\"re0\">$customer<\/span>.Name<br \/>\n<span class=\"re0\">$SQLQuery1<\/span> <span class=\"sy0\">=<\/span> <span class=\"st0\">&quot;insert into tenants (tenantid,tenantname,displayname,active) values ('$($customer.CustomerId)','$($customer.Domain)','$($customer.Name)','1')&quot;<\/span><br \/>\ninvoke<span class=\"sy0\">-<\/span>sqlcmd <span class=\"kw5\">-query<\/span> <span class=\"re0\">$SQLQuery1<\/span> <span class=\"sy0\">-<\/span>ServerInstance <span class=\"re0\">$SQLInstance<\/span> <span class=\"sy0\">-<\/span>Database <span class=\"re0\">$SQLDatabase<\/span> <span class=\"co1\"># -Username $SQLUsername -Password $SQLPassword<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"kw3\">else<\/span> <span class=\"br0\">&#123;<\/span><br \/>\nInvoke<span class=\"sy0\">-<\/span>Sqlcmd <span class=\"kw5\">-Query<\/span> <span class=\"st0\">&quot;update tenants set active='1' where tenantID like '$($customer.CustomerId)' and active &amp;lt;'10'&quot;<\/span> <span class=\"sy0\">-<\/span>ServerInstance <span class=\"re0\">$SQLInstance<\/span> <span class=\"sy0\">-<\/span>Database <span class=\"re0\">$SQLDatabase<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p>I use this code to populat my database (using integrated authentication).<br \/>\nSql for tabel (Database named Microsoft365):<\/p>\n<div class=\"codecolorer-container sql default\" style=\"overflow:auto;white-space:nowrap;width:435px;height:300px;\"><div class=\"sql codecolorer\"><span class=\"kw1\">USE<\/span> <span class=\"br0\">&#91;<\/span>Microsoft365<span class=\"br0\">&#93;<\/span><br \/>\n<span class=\"kw1\">GO<\/span><br \/>\n<br \/>\n<span class=\"coMULTI\">\/****** Object: Table [dbo].[tenants] Script Date: 03.01.2021 20:18:23 ******\/<\/span><br \/>\n<span class=\"kw1\">SET<\/span> ANSI_NULLS <span class=\"kw1\">ON<\/span><br \/>\n<span class=\"kw1\">GO<\/span><br \/>\n<br \/>\n<span class=\"kw1\">SET<\/span> QUOTED_IDENTIFIER <span class=\"kw1\">ON<\/span><br \/>\n<span class=\"kw1\">GO<\/span><br \/>\n<br \/>\n<span class=\"kw1\">CREATE<\/span> <span class=\"kw1\">TABLE<\/span> <span class=\"br0\">&#91;<\/span>dbo<span class=\"br0\">&#93;<\/span><span class=\"sy0\">.<\/span><span class=\"br0\">&#91;<\/span>tenants<span class=\"br0\">&#93;<\/span><span class=\"br0\">&#40;<\/span><br \/>\n<span class=\"br0\">&#91;<\/span>tenantID<span class=\"br0\">&#93;<\/span> <span class=\"br0\">&#91;<\/span><span class=\"kw1\">VARCHAR<\/span><span class=\"br0\">&#93;<\/span><span class=\"br0\">&#40;<\/span><span class=\"nu0\">255<\/span><span class=\"br0\">&#41;<\/span> <span class=\"kw1\">NOT<\/span> <span class=\"kw1\">NULL<\/span><span class=\"sy0\">,<\/span><br \/>\n<span class=\"br0\">&#91;<\/span>tenantname<span class=\"br0\">&#93;<\/span> <span class=\"br0\">&#91;<\/span><span class=\"kw1\">VARCHAR<\/span><span class=\"br0\">&#93;<\/span><span class=\"br0\">&#40;<\/span><span class=\"nu0\">255<\/span><span class=\"br0\">&#41;<\/span> <span class=\"kw1\">NOT<\/span> <span class=\"kw1\">NULL<\/span><span class=\"sy0\">,<\/span><br \/>\n<span class=\"br0\">&#91;<\/span>displayname<span class=\"br0\">&#93;<\/span> <span class=\"br0\">&#91;<\/span><span class=\"kw1\">VARCHAR<\/span><span class=\"br0\">&#93;<\/span><span class=\"br0\">&#40;<\/span><span class=\"nu0\">255<\/span><span class=\"br0\">&#41;<\/span> <span class=\"kw1\">NULL<\/span><span class=\"sy0\">,<\/span><br \/>\n<span class=\"br0\">&#91;<\/span>active<span class=\"br0\">&#93;<\/span> <span class=\"br0\">&#91;<\/span><span class=\"kw1\">INT<\/span><span class=\"br0\">&#93;<\/span> <span class=\"kw1\">NOT<\/span> <span class=\"kw1\">NULL<\/span><span class=\"sy0\">,<\/span><br \/>\n<span class=\"kw1\">CONSTRAINT<\/span> <span class=\"br0\">&#91;<\/span>PK_tenants<span class=\"br0\">&#93;<\/span> <span class=\"kw1\">PRIMARY<\/span> <span class=\"kw1\">KEY<\/span> CLUSTERED<br \/>\n<span class=\"br0\">&#40;<\/span><br \/>\n<span class=\"br0\">&#91;<\/span>tenantID<span class=\"br0\">&#93;<\/span> <span class=\"kw1\">ASC<\/span><br \/>\n<span class=\"br0\">&#41;<\/span><span class=\"kw1\">WITH<\/span> <span class=\"br0\">&#40;<\/span>PAD_INDEX <span class=\"sy0\">=<\/span> OFF<span class=\"sy0\">,<\/span> STATISTICS_NORECOMPUTE <span class=\"sy0\">=<\/span> OFF<span class=\"sy0\">,<\/span> IGNORE_DUP_KEY <span class=\"sy0\">=<\/span> OFF<span class=\"sy0\">,<\/span> ALLOW_ROW_LOCKS <span class=\"sy0\">=<\/span> <span class=\"kw1\">ON<\/span><span class=\"sy0\">,<\/span> ALLOW_PAGE_LOCKS <span class=\"sy0\">=<\/span> <span class=\"kw1\">ON<\/span><span class=\"br0\">&#41;<\/span> <span class=\"kw1\">ON<\/span> <span class=\"br0\">&#91;<\/span><span class=\"kw1\">PRIMARY<\/span><span class=\"br0\">&#93;<\/span><br \/>\n<span class=\"br0\">&#41;<\/span> <span class=\"kw1\">ON<\/span> <span class=\"br0\">&#91;<\/span><span class=\"kw1\">PRIMARY<\/span><span class=\"br0\">&#93;<\/span><br \/>\n<span class=\"kw1\">GO<\/span><\/div><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Hi, I like to keep control of how many licenses our cutomers use versus how many\u00a0 have been purchased. Here is 1st part\u00a0 my PS script to copy the info from csp to the DB. I will start creating a database and table to keep a list of all the tenants in the csp. You &hellip; <a href=\"https:\/\/www.vatland.no\/index.php\/log-tenants-from-office-365-to-local-db\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Log tenants from office 365 to local Db<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"Log tenants from office 365 to local Db","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[72,74,2,48],"tags":[],"class_list":["post-975","post","type-post","status-publish","format-standard","hentry","category-azure","category-csp","category-development","category-powershell"],"aioseo_notices":[],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_likes_enabled":false,"jetpack-related-posts":[{"id":1010,"url":"https:\/\/www.vatland.no\/index.php\/add-tenant-licenses-from-csp-to-database\/","url_meta":{"origin":975,"position":0},"title":"Add tenant licenses from csp to database.","author":"Atle","date":"January 17, 2021","format":false,"excerpt":"This is a followup from previus post. In this post I will populate the database with what licenses a tenant has aquired. This will add records of what aquired skus and 'usage'. For me this is how many license are bought versus how many are assigned. This does not account\u2026","rel":"","context":"In &quot;Azure&quot;","block_context":{"text":"Azure","link":"https:\/\/www.vatland.no\/index.php\/category\/azure\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":875,"url":"https:\/\/www.vatland.no\/index.php\/csp-access-to-tenants-using-powershell-part-1\/","url_meta":{"origin":975,"position":1},"title":"CSP access to tenants using powershell. Part 1","author":"Atle","date":"September 18, 2019","format":false,"excerpt":"A short explanation of how to access customer tenant using a CSP tenant SPN credential connectiong to AzureAD and AZ. Have been struggling for a while to manage all our customers tenants using powershell scripts. It can be complicated to organize all the credentials, tenant domain, tenant id's password expiry.\u2026","rel":"","context":"In &quot;Azure&quot;","block_context":{"text":"Azure","link":"https:\/\/www.vatland.no\/index.php\/category\/azure\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":914,"url":"https:\/\/www.vatland.no\/index.php\/csp-access-to-tenants-using-powershell-part-4\/","url_meta":{"origin":975,"position":2},"title":"CSP access to tenants using powershell. Part 4","author":"Atle","date":"September 24, 2019","format":false,"excerpt":"This is a small script that connects to partnercenter list all customers tenants and let you select one. When one is selected it connects to azuread and az for that customer. All my credentials are stored in SecretServer . I use a web service request to get those credentials. I\u2026","rel":"","context":"In &quot;Azure&quot;","block_context":{"text":"Azure","link":"https:\/\/www.vatland.no\/index.php\/category\/azure\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":899,"url":"https:\/\/www.vatland.no\/index.php\/csp-access-to-tenants-using-powershell-part-2\/","url_meta":{"origin":975,"position":3},"title":"CSP access to tenants using powershell. Part 2","author":"Atle","date":"September 20, 2019","format":false,"excerpt":"In part 1 we created the Azure Enterprise App for Partnercenter and used this information to connect using powershell and connect-partnercenter. Now we will use this to connect to one of our customers tenants. First we will use AZ module and connect-azaccount. We will use the AZ module and the\u2026","rel":"","context":"In &quot;Azure&quot;","block_context":{"text":"Azure","link":"https:\/\/www.vatland.no\/index.php\/category\/azure\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":902,"url":"https:\/\/www.vatland.no\/index.php\/csp-access-to-tenants-using-powershell-part-3\/","url_meta":{"origin":975,"position":4},"title":"CSP access to tenants using powershell. Part 3","author":"Atle","date":"September 23, 2019","format":false,"excerpt":"In this part 3 of CSP and powershell I will show how you can connect to azureAD of a customer tenant using your CSP app credentials and refreshtoken. This is almost the same procedure as we use to connect to az. We will start with the same variables as in\u2026","rel":"","context":"In &quot;Azure&quot;","block_context":{"text":"Azure","link":"https:\/\/www.vatland.no\/index.php\/category\/azure\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1020,"url":"https:\/\/www.vatland.no\/index.php\/import-user-licenses-from-csp-using-csp-api-and-graph\/","url_meta":{"origin":975,"position":5},"title":"Import user licenses from CSP using CSP api and graph.","author":"Atle","date":"January 31, 2021","format":false,"excerpt":"Hi,there.This is also quiet simple. I want to get all users and what licenses they have been assigned. All this should do, is retrieve information using a csp token.After some attempts this is my best one. The \"goodlooking\" argument will not work when run from ISE.I'am still using the same\u2026","rel":"","context":"Similar post","block_context":{"text":"Similar post","link":""},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/www.vatland.no\/index.php\/wp-json\/wp\/v2\/posts\/975","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.vatland.no\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.vatland.no\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.vatland.no\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.vatland.no\/index.php\/wp-json\/wp\/v2\/comments?post=975"}],"version-history":[{"count":14,"href":"https:\/\/www.vatland.no\/index.php\/wp-json\/wp\/v2\/posts\/975\/revisions"}],"predecessor-version":[{"id":989,"href":"https:\/\/www.vatland.no\/index.php\/wp-json\/wp\/v2\/posts\/975\/revisions\/989"}],"wp:attachment":[{"href":"https:\/\/www.vatland.no\/index.php\/wp-json\/wp\/v2\/media?parent=975"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.vatland.no\/index.php\/wp-json\/wp\/v2\/categories?post=975"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.vatland.no\/index.php\/wp-json\/wp\/v2\/tags?post=975"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}