Auto logging in to salesforce using PS on Chrome - powershell

I have the following script for logging in to salesforce on IE.
I want to login using chrome or firefox.
If I need a completely new script I will use it.
$username = "username#domain.com"
$password = "Mypassword"
$ie = New-Object -com InternetExplorer.Application
$ie.visible=$true
$ie.navigate("https://login.salesforce.com")
while ($ie.Busy -eq $true)
{
Start-Sleep -Milliseconds 1000;
}
$ie.document.getElementById("username").value= "$username
$ie.document.getElementById("password").value = "$password"
$login = $ie.document.getElementsByClassName("button r4 wide primary") | Select-Object -first 1
$login.click()

TL;DR: There's no built-in way to do what you're asking.
Let me preface this by saying that, in general, trying to automate logins in this manner is a really, really bad idea. I cannot stress enough how dangerous this is from a security perspective. I would strongly recommend against attempting to write a Powershell script to automate a login in this manner unless it is done with a fake username and password for learning/test purposes.
That being said, IE has a rich COM interface - Chrome and Firefox, not so much. You will need to install an extension to enable the same functionality.

This is evil, if you want systematic access and automation you should look into proper REST or SOAP API access, with OAuth2 flows. There's even a flow where you don't share password, the trust is established by signing a request with certificate that was earlier uploaded to SF and the user preauthorised...
This should never be part of any serious deliverable. If this gets hacked - your company / client can sue for damages.
If you really need it you can use simple GET like https://login.salesforce.com/?un=username#example.com&pw=hunter2, no need for fancy scripting. In Setup -> Login History you'll see that the method was GET instead of POST (submitting the real form). I don't think it's officially supported, they could change it anytime. It'd pass your password plaintext over the web...
Edit:
Check what your company signed. For example the Master Service Agreement
https://a.sfdcstatic.com/content/dam/www/ocms-backup/assets/pdf/misc/salesforce_MSA.pdf
(…)the Service or Content may not be accessed by more than that number
of Users, (b) a User’s password may not be shared with any other
individual(…)

Related

Login to website with powershell without IE COM method

Looking for solution how to test website login with powershell without IE COM method. There is lot of examples how to do it with IE COM method: -ComObject 'internetExplorer.Application, but unfortunately this is not working for me as site is not working with IE at all.
Google chrome has a nice feature in its developer tools, on the network tab.
Clear the network log, filter so that it shows "All" requests/responses.
Log into the site and then click the red button or hit "ctrl + e" to stop the log from increasing.
Go through each request until you see the login request (These can sometimes be hard to spot.)
Once you have found the request right click on the name of the request, you can then select "Copy -> Copy As PowerShell".
Paste this into ISE etc.
I would personally then remove all of the $Session lines from above the request and change -WebSession $session to -SessionVariable $session and subsequently call -WebSession $session in each web request there after. (Only use -Sessionvariable once as this is the what instantiates the session). The reason I do this is so that the login creates its own session data rather than using any possible data from the browser.
Last of all you will want to clear any unwanted headers out of the webrequest.
Depending on the login mechanism the request may need tweaking to allow it to be done through automation, I have only had a couple of circumstances where this has been the case and multiple requests have been required due to AJAX or other elements on the page.

Powershell Question: How to check if password is implemented clarifications

So I tried messing around the basics by creating a bulk user script. I made 3 dummy accounts with different information.
I also set a securestring password for the accounts, but here's the thing, how do I check if I DID actually implement the passwords? Currently in my Active Directory, the users are created with a black arrow marked on the icon.
From what I understand its either I haven't enable the account or I didn't set a password for it. Is there a way for me to login into these dummy account to test if I have actually added the password?
Sorry, I'm a total beginner to this, still learning hence I have certain doubts. Im using a VM Win Server 2019 for practice.
I check passwords are actual this way:
$de = New-Object -TypeName 'System.DirectoryServices.DirectoryEntry' -ArgumentList #($null, 'UserName', 'Pa$$w0Rd')
if ($de.DistinguishedName -eq $null)
{
# Could not login to DC#
}
But user needs to be enabled and allowed to logon.

Get Google Search results via Powershell

Let's say you only have the artist and title from a music file but you don't know the album name.
When you do a Google search in Chrome for i.e Golden Earring Radar Love Album you get:
You see the album name (Moontan), release date (July 1973) and even the correct album cover. How is this page section called? Google Preview? Google Instant Page? I don't know
My question is
How do I programmatically get these information via PowerShell?
What I have tried
Invoke-Webrequest: Not working, specific content not in response
$Response = Invoke-WebRequest -URI "https://www.google.com/search?hl=en&q=Golden+Earring+Radar+Love+Album"
$Response.content | Set-Content D:\test.txt
XmlHttpRequest: Not working, specific content not in response
$objXmlHttp = New-Object -ComObject MSXML2.ServerXMLHTTP
$objXmlHttp.Open("GET", "https://www.google.com/search?hl=en&q=Golden+Earring+Radar+Love+Album")
$objXmlHttp.Send()
$objXmlHttp.responseText | Set-Content D:\test.txt
Invoke-RestMethod: Not working, retrieves only URLs and their snippets
$Response = Invoke-RestMethod -Uri 'https://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=Golden%20Earring%20Radar%20Love%20Album'
$Response.responseData.results
I looked for a Google Play or Google Music API which can be used within PowerShell
I believe the problem is, that these information are loaded via Javascript which is not executed when using methods like Invoke-WebRequest. I could be wrong here.
I see two solutions: 1) Imitate a web browser within PowerShell and load the whole website into a form. Or 2) Use fiddler to see when and how these extra information are loaded. I would prefer the second solution but both are beyond my knowledge.
Background to avoid comments saying There are other services like XYZ which better fit your needs
I already have working PowerShell scripts to get album name and additional info only by a given artist and track title for numerous services including Amazon, Deezer, Discogs, EchoNest, iTunes, Last.fm, MusicBrainz, Napster, rdio and Spotify. Because they all offer an easy to use API (except Amazon. Their implementation is pretty hard).
I ran some tests against ~3000 music files only given the artist and track title to retrieve the according album name. And when I compared the results with Google I noticed that none of the above services were so accurate as Google was.
open the powershell profile ii $profile
paste the following snippet to the profile
Function search-google {
$query = 'https://www.google.com/search?q='
$args | % { $query = $query + "$_+" }
$url = $query.Substring(0, $query.Length - 1)
start "$url"
}
Set-Alias glg search-google
restart the powershell session
from the console just run the new command glg hello world
no quotes for strings needed
It's quite possible that Google returns different results depending on the user-agent making the request. So in your case you're not passing a user-agent so Google assumes that it's not a browser and is limiting the amount of information that they are returning (maybe to make your parsing a little easier).
So you have a few options, two of them are:
As suggested by #AlexanderObersht, use Fiddler to sniff some of the network traffic and see what additional headers are being provided by default and fiddle around (pun-intended) with them to see if you can make it work.
With Invoke-RestMethod or Invoke-WebRequest you will need to add a -Headers parameter
With XMLHttpRequest you will have to add the headers in the appropriate properties.
If you don't want to deal with the browser details you can just automate IE directly from Powershell. I've got a sample shown below.
-
$ie = New-Object -com InternetExplorer.Application -ErrorAction Stop
$ie.Visible = $true
$ie.Navigate("https://www.bing.com")
while($ie.Busy) { Start-Sleep -Milliseconds 1 }
$ie.Document.DoStuff()

Is it possible to set call forwarding via the Lync SDK (2013 or other)?

I work for an IS department in a large institution. The Lync servers that handle our telephones are handled by another department, and any solution that requires cooperation from them is not viable. This rules out any solutions that require extra privileges, running from the Lync servers, SEFAUtil, etc.
My personal Lync 2013 client has some abominable GUI menu where I can forward my desk phone to another number. I know therefor that it is possible, in theory.
I have powershell code that (with a ton of SDKs installed) will login with my own personal credentials. The blog I grabbed it from allowed the script to send some arbitrary IM message (not very useful to me). It looks like this:
if (-not (Get-Module -Name Microsoft.Lync.Model)) {
try {
Import-Module -Name (Join-Path -Path ${env:ProgramFiles} -ChildPath "Microsoft Office\Office15\LyncSDK\Assemblies\Desktop\Microsoft.Lync.Model.dll")
-ErrorAction Stop
}
catch {
Write-Warning "Microsoft.Lync.Model not available, download and install the Lync 2013 SDK http://www.microsoft.com/en-us/download/details.aspx?id=36824" break
}
}
$client = [Microsoft.Lync.Model.LyncClient]::GetClient()
if ($client.State -ne [Microsoft.Lync.Model.ClientState]::SignedIn) {
$client.EndSignIn(
$client.BeginSignIn("x#x.com", "domain\johno", "youllNeverGuess", $null, $null))
}
if ($Client.State -eq "SignedIn") {
Write-Host "DEBUG: We managed to sign in!" }
}
This seems to work, in that if I supply it the wrong password, it barfs.
From within the SDK, is it possible to set callfowarding to a particular number? Microsoft's horrible documentation demonstrates how to forward an incoming call that the script caught through an event handler, meaning that it'd have to run in a polling loop... and that I couldn't just iterate through a list of accounts to forward. From the GUI client, if you set your phone to forward to a number, it sticks even if you power down the machine, so it's sending something to the server that is semi-permanent. Can Lync SDK accomplish the same?
Though Lync 2010 is deprecated, I would be happy with a solution based upon that. Powershell is preferred, but if you have code in VB or C#, again that would be ok too. I don't need the whole thing served up on a silver platter, just a few clues to work with.
You need to publish your routing information to the Lync server. This contains your simultaneous-ring and forwarding settings, amongst others.
If you're OK with creating a .Net solution, try the following:
When you need to program against the Lync server and cannot get any elevated privileges, try using UCMA and create a UserEndpoint. Since you know your Lync server address and have login details, you can create and authenticate a UserEndpoint without cooperation from the other department.
Example (not mine): Creating UCMA Applications with a UserApplication instance.
Once you get your endpoint set up, you're basically home free. With the ability to publish presence, you can publish routing settings. For Lync, "presence" is a container which contains everything like availability, routing, contact details, custom locations, etc.
On your UserEndpoint, subscribe to LocalOwnerPresence.PresenceNotificationReceived MSDN.
After you sign in with your endpoint, this event will fire and give you your current settings. In the event argument LocalPresentityNotificationEventArgs, grab the AllCategories collection, and look for the PresenceCategoryWithMetaData with the name "routing". Create a new instance of the Routing container with this data.
The routing container is the class Microsoft.Rtc.Internal.Collaboration.Routing in Microsoft.Rtc.Collaboration.dll.
private void OnLocalPresenceNotificationReceived(
object sender,
LocalPresentityNotificationEventArgs e)
{
var container = (from c in e.AllCategories
where string.Equals(c.Name, "routing", StringComparison.OrdinalIgnoreCase)
orderby c.PublishTime descending
select c).FirstOrDefault();
if (container != null)
{
var routing = new Microsoft.Rtc.Internal.Collaboration.Routing(container);
// You can access the routing data here...
}
}
If you do not receive any routing container, you can create a new instance. Take care though that publishing a new instance will override all your current routing settings instead of allowing you to update the current settings.
In the Routing class you can write to the following property:
routing.CallForwardToTargetsEnabled = true;
routing.CallForwardTo.Clear();
routing.CallForwardTo.Add("sip or tel number");
routing.UserOnlyWaitTime = TimeSpan.FromSeconds(...);
And finally, publish the new routing settings:
endpoint.LocalOwnerPresence.PublishPresenceAsync(new PresenceCategory[] {
routing
});
It is also possible to publish presence by getting your current Lync instance with the GetClient() method in the Lync SDK. I'm not sure however if this can be used to publish routing settings. You could try though, I found many undocumented options while playing around with Lync. Look at the following two resources:
How to: Publish enhanced presence information and
Self.BeginPublishContactInformation

PowerShell file upload with PhoneGap not retrieving page

I am trying to upload an archive file (a Zip archive if that matters) to an existing API at an external site and while I can get the webclient to connect and get a token to the site the upload never seems to work, I continually get a 404 error. The problem may be on their side, but I seem to be the only one who has posted about it on their site, yet I wonder if I am using the UploadFile correctly, or if there is a way to capture the response from the command, which I'd like to know if only to improve my PowerShell coding.
What I am running is the following:
# Variables I want to use
$appArchive = "\\networkpath\Releases\CodeReleasePackage.zip"
$localArchive = "c:\temp\CodeReleasePackage.zip"
[string]$appUrl = "https://site.com/api/v1/apps/(id)/"
[string]$tokenUrl = "https://site.com/token"
[string]$uploadUrl = "https://site.com/api/v1/apps/(id)/?auth_token=$mytoken"
# $appCred = Get-Credential
$username = "email#address"
$password = "password"
# Create the web client
"Creating the client.`n"
$pgup = new-object System.Net.WebClient
$pgup.Credentials = New-Object net.NetworkCredential($username,$password)
"Going to the token page"
$pgToken = $pgup.UploadString($tokenUrl,"")
$mytoken = $pgToken -replace '{|}|"|:|token',''
"Now trying to upload the latest file with my token: $mytoken"
$pgup.UploadFile($uploadUrl,$appArchive)
I get the token which is something like {"token","hkjuihgkjhiuhhlkhuhk"} and not really knowing if there is a better way to handle the resulting token I did the replace to get rid of everything but the token string. Adding it to the URL is supposed to work but I just get 404 errors accorinding to Fiddler.
So I'd like to be able to capture the response from the site when I run $pgup.UploadFile() but when I do it seems like nothing is coming back, is there a particular way to capture that? I couldn't find a clear example and when I do something like $response = $pgup.UploadFile() I have nothing in $response. Anything that is useful for diagnosing webclient errors would be great, I'd like to learn more about this since it seems pretty useful
Im not sure if this is what your looking for, however here is a bit of code that I use to upload a zip file to a server.
$File = "yourfile.zip" #File to be uploaded
$ftp = "ftp://yourserver/directory #Location for the zip file to be uploaded
$webclient = New-Object System.Net.WebClient
$uri = New-Object System.Uri($ftp)
$webclient.Credentials = Get-Credential #Will prompt for user info. You can use your above way to gather credentials as well
$webclient.UploadFile($uri,$File)
As you can see its rather short and simple, and almost identical to your code but does not handle tokens.
It looks like I cannot access the site with PowerShell as the driver, for some reason I can never get the upload to work but I can read the pages on the site and actually get responses for my account. It may be their API doesn't like the way PowerShell is running the connection, although I have never been able to confirm anything from PhoneGap since they have not yet responded to my issues on this yet.
Edited: 6/14/12
The whole reason this was failing was due to the Apache implementation on their side not accepting the HTTP 1.1 request the way WebClient sends it. If I can get back to HTTP 1.0 then they say I should be able to complete this. Or I can wait for the OAUTH 2.0 implementation and just go from there.