Custom Data Refresh in Microsoft Power BI - powershell

I have a data source connected to to a dashboard that needs to refreshed without actually opening the power bi account. Currently I am able to figure out the powershell script that help me do it from my powershell promt.
The request is something like this
Invoke-WebRequest -Uri "https://api.powerbi.com/v1.0/myorg/datasets/DATASET_ID/refreshes" -Method "POST" -Headers #{"Sec-Fetch-Mode"="cors"; "Authorization"="Bearer XXXXXXXXXXTOKENXXXXXXXX"} -ContentType "application/json;charset=UTF-8"
Now the Token gets expired after sometime and I again need to open the power bi website to get the new token.
Is there a way for generate token locally without actually open the website? i tried using Login-PowerBI in Powershell to get token but is there any other way also.

you need to get a new token each time or get the refresh token from the API. I have tested getting token everytime and I never have a problem. Check my code here to complete your powershell:
https://github.com/ibarrau/PowerBi-code/blob/master/PowerShell/RefreshPowerBi.ps1
Remember you can always install an On Premise Data Gateway to solve this for you.
https://learn.microsoft.com/en-us/power-bi/service-gateway-onprem

As far as I understood, you want to refresh a dataset with PowerShell, but without prompting for credentials. In this case, you can store them in the script itself and do something like this:
Import-Module MicrosoftPowerBIMgmt
Import-Module MicrosoftPowerBIMgmt.Profile
$password = "xxxxx" | ConvertTo-SecureString -asPlainText -Force
$username = "xxxxx#yyyyy.com"
$credential = New-Object System.Management.Automation.PSCredential($username, $password)
Connect-PowerBIServiceAccount -Credential $credential
Invoke-PowerBIRestMethod -Url 'groups/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/datasets/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/refreshes' -Method Post
Disconnect-PowerBIServiceAccount

Related

How to retrieve office 365 mailbox IDs using Invoke-RestMethod step by step

I'm developing a simple PowerShell script to retrieve office365 user mailbox folder IDs, my code fails at authentication stage displaying error 401 unauthorized. Is there a step that is missing so as to connect to office 365 mailbox using the Invoke-RestMethod cmdlet?
Below is the code
$cred = Get-Credential
Invoke-RestMethod -Uri "https://outlook.office.com/api/v1.0/me/MailFolders/" -Credential $cred | foreach-object{$_.value |select DisplayName,ID}
Error upon running the code.

Access web service behind Citrix NetScaler

I'm having an internal .NET web service which I try to access from the public network.
If using a browser, a user may enter login and passwd in a form on the Citrix NetScaler custom page and after the form is submitted, the browsing continues and the web service endpoint is working with no issues.
I don't know anything about Citrix NetScaler, but by checking the network calls in the browser's dev tools, I was able to get to the web service by using PowerShell and the a Microsoft.PowerShell.Commands.WebRequestSession object:
$session = New-Object Microsoft.PowerShell.Commands.WebRequestSession
$cookie = New-Object System.Net.Cookie
$cookie.Name = "NSC_TASS"
$cookie.Value = "https://REST_SERVICE_DOMAIN/api/"
$cookie.Domain = "CITRIX_NETSCALER_DOMAIN.com"
$session.Cookies.Add($cookie);
$response = Invoke-WebRequest -Uri "https://CITRIX_NETSCALER_DOMAIN/cgi/login" `
-Method "POST" `
-Headers #{"Content-Type"="application/x-www-form-urlencoded"} `
-Body "login=URL_ENCODED_EMAIL&passwd=URLENCODED_PASSWORD" `
-WebSession $session
Is there a way to login by not using PowerShell's Microsoft.PowerShell.Commands.WebRequestSession object? Do I use the right endpoint?
EDIT: I'm looking for a solution which doesn't involve PowerShell, but it only relies on HTTP headers and cookies
I think you may be able to do -SessionVariable with Invoke-WebRequest, and then append the cookies a similar way.
Invoke-WebRequest https://CITRIX_NETSCALER_DOMAIN/cgi/login -SessionVariable session
...
$session.Cookies.Add($cookie);

Powershell - Save encrypted user and pass in a script?

I have using a script in Powershell, which make a web request with user and password from an API. Since is a shared computer, for security reason, i want to encrypt the user and password.
this is the basic web request i have using (that i obtain from other question in stack overflow ):
$user = 'user'
$pass = 'pass'
$pair = "$($user):$($pass)"
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($pair))
$basicAuthValue = "Basic $encodedCreds"
$Headers = #{
Authorization = $basicAuthValue
}
Invoke-WebRequest -Uri 'https://whatever' -Headers $Headers
My issue is that i do not found a way to encrypt the user and password variables, try to use the ConvertTo-SecureString and convertTFrom-SecureString, but it does not work. i wanna know if there is a way to save the encrypted credentials in a file or other way. without need to saved as an environment variable and avoid getting credentials, since i wanna automatizes the script as a task.
Please comment any doubt.
Thanks for looking, happy coding.
Regards
If anyone in the future have the same issue as me, you can use the next tool in powershell, Export-Clixml and Import-Clixml:
$cred = Get-Credential | Export-CliXml -Path ..\cred.ps1.credentials
and then use import to access the credentials
$Credential = Import-CliXml -Path "..\cred.ps1.credentials"
now you have to added to the invoke-webrequest
Invoke-WebRequest -Uri 'https://whatever' -credentials $credential
Happy coding!

Invoke-RestMethod PowerShell Google DDNS

I seem to be having a lot of issues with this seemingly basic script to update my IP with Google's DDNS service.
#Fetch current IP address
$ipuri = "https://api.ipify.org"
$ip = Invoke-RestMethod -Uri $ipuri
#Send fetched IP address to Google Domains through their API
$uri = "https://username:password.google.com/nic/update?hostname=home.domain.com&myip="$ip""
Invoke-RestMethod -Method 'Get' -Uri $uri
The first issue is with the $ip variable. It produces no output if I keep the $ip on it but works fine without it (I need it as a variable as I use it later on).
The second issue is with the https://username:password#domains.google.com/nic/update?hostname=home.domain.com&myip="$ip".
It works fine if I dump the exact string into postman (substituting an actual IP address instead of $ip)
but fails to send anything even if I run it with a manually inserted IP (such as https://username:password#domains.google.com/nic/update?hostname=home.domain.com&myip=1.2.3.4) in PowerShell.
P.S. In my actual code I substitute in the correct username and password (as provided by Google) and correct subdomain, domain, top-level domain as it applies to me.
Any thoughts on this?
EDIT:
The updated (and working) code is looks like this:
#Fetches current IPv4 address
$ipuri = "https://api.ipify.org"
$ip = Invoke-RestMethod -Uri $ipuri
#Stores Google-provided username and password
$password = ConvertTo-SecureString "password" -AsPlainText -Force
$credential = New-Object Management.Automation.PSCredential ('username', $password)
#Send fetched IP address to Google Domains through their API
$uri = "https://domains.google.com/nic/update?hostname=home.domain.com&myip=$($ip)"
Invoke-RestMethod -Method 'POST' -Uri $uri -Credential $credential
First off, that's a neat service, api.ipify.org, I'll have to use that in the future.
Secondly, I think the only issue here is your definition of the $url.
The syntax you had before actually throws an error if you try to run the line on its own, error shown here.
"https://username:password.google.com/nic/update?hostname=home.domain.com&myip="$ip""
At line:1 char:81
+ ... e:password.google.com/nic/update?hostname=home.domain.com&myip="$ip""
+ ~~~~~
Unexpected token '$ip""' in expression or statement.
In PowerShell you should use string expansion syntax like this, instead of nesting quotes.
$uri = "https://username:password.google.com/nic/update?hostname=home.domain.com&myip=$($ip)"
Update
Found the API Docs here https://support.google.com/domains/answer/6147083?hl=en. They say to provide your username and password using Basic Auth, which makes a base64 encoded string of your credential. We can do that in PowerShell pretty easily!
You can provide your credentials my using the Get-Credential cmdlet to save them then pass them into Invoke-RestMethod and adding -Credential and -Authentication as parameters. Here is what a completed solution would look like.
$ipuri = "https://api.ipify.org"
$ip = Invoke-RestMethod -Uri $ipuri
#Send fetched IP address to Google Domains through their API
$myCredential = Get-Credential #you'll be prompted to provide your google username and pwd.
$uri = "https://domains.google.com/nic/update?hostname=home.domain.com&myip=$($ip)"
Invoke-RestMethod -Method 'POST' -Uri $uri -Credential $myCredential -Authentication Basic

VSTS Build and PowerShell and AzureAD Authentication

I have a VSTS project connected via a Service Principal to an Azure subscription through an Azure Resource Manager endpoint. This works fine for my builds that configure ARM resources via templated, parameter driven deployments.
I have an additional requirement to set up Azure AD groups as part of the build. I have a script that works fine from my local machine. When I deployed it via the build and it executed on the hosted build controller, the script could initially not find the AzureAD module. I got around this by including the script in git Repo and accessing it through:
$adModulePath = $PSScriptRoot + "\PsModules\AzureAD\2.0.0.131\AzureAD.psd1"
Import-Module $adModulePath
However, I now have another problem when it comes to running New-AzureADGroup. The script requires Connect-AzureAD to be run before the command is issued. This works fine by hardcoding a credential but I don't want to do this, I want it to run under the context of the SPN created, which is running the scripts on the hosted build controller.
So, the question is, can I get the current context of the Azure PowerShell execution SPN and pass that to Connect-AzureAD to avoid storing credential in plain text? Am I missing a trick? Are there any alternatives?
My current code is as below, the commented connection works fine from the command like with hard coded values. The call with no parameters presents the login UI which terminates the build since it is obviously not interactive.
## Login to Azure
#$SecurePassword = ConvertTo-SecureString $AdminPassword -AsPlainText -Force
#$AdminCredential = New-Object System.Management.Automation.PSCredential ($AdminUserEmailAddress, $SecurePassword)
#Connect-AzureAD -Credential $AdminCredential
Connect-AzureAD
Write-Output "------------------ Start: Group Creation ------------------"
$TestForAdminGroup = Get-AzureADGroup -SearchString $AdminGroup
$TestForContributorGroup = Get-AzureADGroup -SearchString $ContributorGroup
$TestForReaderGroup = Get-AzureADGroup -SearchString $ReaderGroup
Thanks
This is possible. Got it working today for my own VSTS extension that I released a while ago. My extension is using a Azure Resource Manager endpoint as input.
Running it now on a Microsoft Hosted Visual Studio 2017 agent pool using the below code. See for more information my post on how to use AzureAD PowerShell cmdlets on VSTS agent.
Write-Verbose "Import AzureAD module because is not on default VSTS agent"
$azureAdModulePath = $PSScriptRoot + "\AzureAD\2.0.1.16\AzureAD.psd1"
Import-Module $azureAdModulePath
# Workaround to use AzureAD in this task. Get an access token and call Connect-AzureAD
$serviceNameInput = Get-VstsInput -Name ConnectedServiceNameSelector -Require
$serviceName = Get-VstsInput -Name $serviceNameInput -Require
$endPointRM = Get-VstsEndpoint -Name $serviceName -Require
$clientId = $endPointRM.Auth.Parameters.ServicePrincipalId
$clientSecret = $endPointRM.Auth.Parameters.ServicePrincipalKey
$tenantId = $endPointRM.Auth.Parameters.TenantId
$adTokenUrl = "https://login.microsoftonline.com/$tenantId/oauth2/token"
$resource = "https://graph.windows.net/"
$body = #{
grant_type = "client_credentials"
client_id = $clientId
client_secret = $clientSecret
resource = $resource
}
$response = Invoke-RestMethod -Method 'Post' -Uri $adTokenUrl -ContentType "application/x-www-form-urlencoded" -Body $body
$token = $response.access_token
Write-Verbose "Login to AzureAD with same application as endpoint"
Connect-AzureAD -AadAccessToken $token -AccountId $clientId -TenantId $tenantId
To conclude, the Powershell module can’t share the same context and you need to store the credential in secret variable in VSTS.
To take this further, it is possible to use the Service Principal by following example 3 here:
https://learn.microsoft.com/en-us/powershell/module/azuread/connect-azuread?view=azureadps-2.0
Once you have created a self-signed cert and attached it, you can connect to the Azure AD by passing in the thumbprint of the cert along with a couple of other parameters:
Connect-AzureAD -TenantId $tenantId -ApplicationId $sp.AppId -CertificateThumbprint $thumb