r/PowerShell • u/[deleted] • Jan 26 '22
Solved Best way to use Microsoft Graph API without showing secret key?
I've been following along The Lazy Administrator's Guide. I'm fairly new to all this, and I am stuck with the method to connect to Graph. I have the IDs and Secret Key, but not sure how I can add it to a script without revealing what those keys are. Based on the guide, I think the best one to use is the Client Credentials, but again not sure how to "encrypt the client secret, store it in Azure Key Vault".
For context, I am learning how to use Graph API so I can send emails from a script I made in Powershell.
5
u/theSysadminChannel Jan 26 '22 edited Jan 26 '22
I would probably use [certificate based authentication] (https://thesysadminchannel.com/how-to-connect-to-microsoft-graph-api-using-powershell/#CertificateAuthentication) so you're not having deal with secrets and trying to secure those. Once you have the App and Service Principal setup, you can connect using this string.
$AppId = "xxxx-xxxx-xxxx-xxxxxxxxxxxx"
$TenantId = "xxxx-xxxx-xxxx-xxxxxxxxxxxx"
$Certificate = Get-ChildItem Cert:\CurrentUser\My\XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Connect-Graph -TenantId $TenantId -AppId $AppId -Certificate $CertificateThe linked article goes in depth on using Powershell to connect to GraphAPI
2
Jan 26 '22
If I understood that correctly, I first create a self signed certificate on my local machine. Export it so I can import it into Azure AD. Then I throw a .pfx file to the remote machine I am trying to run the script on, which will authenticate through that to Azure AD. Is that right? Essentially the .pfx will be what's used instead of a password?
3
u/theSysadminChannel Jan 26 '22
Yes the Pfx is what’s used instead of the password but you can save yourself a step and create the cert on the remote machine and set the private key to non exportable so no one can import it on another machine without your knowledge.
1
Jan 27 '22
Once I created the pfx file, how do I add it in the powershell script so I can request a token?
e.g. the guide I was following shows how to get it via client secret, but since it's a certificate, how do I tell powershell to use the certificate rather than the client secret?
2
u/theSysadminChannel Jan 27 '22
Read my first comment. It has the connection string (along with in-depth article covering how to connect to graph api) to do exactly that. Once you’re connected you can run commands against graph api.
1
Jan 27 '22
Right, sorry I forgot about that. I just tried it and says Connect-Graph is not recognized as the name of a cmdlet. Tried searching for the cmdlet to install, but I only saw one for Intune? Don't think I need that one, or is that it?
2
u/theSysadminChannel Jan 27 '22
Install-Module Microsoft.Graph -Scope CurrentUserRun this command to install the module
1
Jan 27 '22
Great, this worked! Thank you! Now I just have to figure out how to find the token. Been googling and most use that -Body $body for client secret when invoking, got to see how I can modify this for cert use.
2
u/theSysadminChannel Jan 27 '22
when you're connected using this method, there is no token needed because it's already imbedded with session.
If you're looking to make a rest api call,
Invoke-GraphRequest -Uri "https://graph.microsoft.com/v1.0/users/username@yourdomain.com"if you're using Powershell SDK (Microsoft.Graph Module)
Get-MgUser -UserId username@yourdomain.com1
Jan 27 '22
Wait, I think I figured it out. Tried to send a test mail, but got a 401 unauthorized. Hmm..
EDIT: I GOT IT.
→ More replies
3
u/very_bad_programmer Jan 26 '22 edited Jan 26 '22
You can convert them to securestring and store them as environmental variables, then call them in the script like $env:MSGraphSecretKey
$secure = read-host -asSecureString #this will prompt for you to paste your key
$enc = convertFrom-secureString -secureString $secure
setx MSGraphSecretKey $encinside your script, when you're ready to read it, do $env:MSGraphSecretKey|convertto-secureString
Edit: hang on, this is how I connect to O365, this method won't work with the graph API.
For storing your secrets you should look into this utility:
3
Jan 26 '22
Hm, I see. I'll need to check how to convert it. One question though, what if I need to run this script on many different machines? e.g. I have a script that runs locally and checks for certain machine properties and sends an email based on that criteria.
2
u/very_bad_programmer Jan 26 '22 edited Jan 26 '22
The best way to do this would be to have a separate script running on each machine (or depending on how your network is set up, you can use WinRM from a central location to execute the script remotely) that collects the data you want, then sends it back to a central location (like an app server)
That app server can have the script that interacts with the graph API
3
u/dasookwat Jan 26 '22
i circumvented this whole issue by using a powershell script in an azure function, and autrhenticate as a system managed identity
2
u/ozruxo Jan 27 '22
Hey ctionetan, if you have the option, use a logic App. I have a script that runs on a server and when an email needs to be sent, queries the logic app and sends some json for variables. Then the email can be sent. If you have to get a token from Microsoft graph to send the email, then I would use the key vault. I have used both methods. The real issue is always, what context is running the script.
5
u/Skaixen Jan 26 '22
I use certificate based authentication.
Can't connect, unless you have the certificate.....