Why is my powershell Base64 String truncated to 36 characters? - powershell

I'm using PowerShell inside VSTS Build for querying the VSTS API. I'm using PAT for authentication.
However, I see it failing when I generate the Auth string. Here is my code inside
$VstsAccessEmail = $Env:VstsAccessEmail
$VstsAccessToken = $Env:VstsAccessToken
$pair = "${VstsAccessEmail}:${VstsAccessToken}"
$base64 = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($pair))
Write-Host $base64
If I see the outcome here, I see the first 36 characters of the actual auth string. I generated the string using Powershell on my machine and I get the entire 108 characters. I have hard-coded this for time being to test this like the following steps that follow the above code.
$base641 = "a2FuZ2thbi5nb3N3YW1pQHVuaXN5cy5jb206cHh4b25oaHBlNmtjb3g3aTRhdHZxMzdoNms2ZnpuNHhyaWhyZ2ozdGZ3ejRlNmxxxxXXXX=="
if($base64.length -ne 108){
$base64 = $base641
}
Write-Host "base64 is: $base64 "
This works correctly. Initially, I thought it might be an issue with Writing to host. However, If I do invoke the RestMethod without updating with the hard-coded one, I get 401 Unauthorized.
Please help.
UPDATE:
I found the issue. I set the VstsAccessToken as a secret in the build variables. So the value is not coming through. making it unsecured works fine.
Can someone help how this can be done keeping the token as a secret?
SOLVED
Using $Env:variable does not allow to use the value when the variable is secret. However, passing it as a parameter to the PowerShell let the code read it, though the output to log is masked.

This section is definitely wrong. I see one thing that's definitely wrong, another that's possibly wrong.
$VstsAccessEmail = $Env:VstsAccessEmail
$VstsAccessToken = $Env:VstsAccessToken
$pair = "${VstsAccessEmail}:${VstsAccessToken}"
$base64 = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($pair))
$pair = "${VstsAccessEmail}:${VstsAccessToken}" should be $pair = ":${VstsAccessToken}". No email address is neccessary, just a colon and then the auth token.
UTF8.GetBytes may be wrong. I always use ASCII.GetBytes.

Using $Env:variable does not allow to use the value when the variable is secret. However, passing it as a parameter to the PowerShell let the code read it, though the output to log is masked.

Related

Joining strings and # character missing

I'm assuming its obvious, but I'm completely missing it. I've got a PowerShell script I'm working on to automate user creation. One of my functions generates the email address. Right now, its not doing anything fancy, just joining the username and domain. I'll be adding more later to increment the value if in use. But I can't get the basic version to work.
function generateMailbox {
param(
[parameter(Mandatory=$true)]
$userName,
[parameter(Mandatory=$true)]
$domain
)
$uniqueMailbox = $null
#set initial value for $uniqueMailbox as the initial mailbox name
$uniqueMailbox = "$userName#$domain"
return $uniqueMailbox
}
So, pretty straightforward. BUT... the "#" is missing from the emails it generates. I put in a break point on the return and verified $uniquemailbox is missing that "#". So if $userName = "uname" and $domain = "domain.com", then $uniqueMailbox will be set to "unamedomain.com"
While in the debug mode, I can manually enter $uniqueMailbox = "$userName#$domain" and then the value returns correctly. For the life of me I can't see my mistake.
I did double check the $uniqueMailbox variable isn't used anywhere outside this function.

Get Process Handle in PowerShell

I am trying to get a process handle without success, I have read a lot about that but don't know why I cannot achieve it.
This is what I am doing:
$handle = $Kernel32::OpenProcess(PROCESS_ALL_ACCESS, FALSE, 4548)
I am doing it with admin rights, it seems like it doesn't like the PROCESS_ALL_ACCESS parameter. Any idea?
PowerShell doesn't recognize the symbolic constants you're trying to use there. Use the numeric values instead. For PROCESS_ALL_ACCESS that should be 1056763 or 0x00101ffb (and you also need $false instead of FALSE). However, you probably shouldn't be using PROCESS_ALL_ACCESS in the first place.
Try with PROCESS_QUERY_LIMITED_INFORMATION (numeric value 4096 or 0x1000):
$handle = $Kernel32::OpenProcess(0x1000, $false, 4548)

How to correctly add a variable's value to parameters in Postman?

I'm learning Chrome Postman now and my issue now is:
I need to generate a new value of a parameter for each request.
So each request (I make a POST) must have a unique value of this parameter.
So far I thought to manage it with environment variables and I have done it like this:
I add a new environment variable with a unique value
I use this variable in the "value" field on a parameter
And it doesn't work - I get error 401 Authorization Required.
Seems that the error is not connected to the parameter at all but as soon as I change the parameter and manually input a unique data it works well!
So this will work for me:
Please suggest what I'm doing wrong here and advice how to do it right. Thanks!
Spent some more hours investigating I found my problem!
The problem is the value I put into a variable - it included ":" sign and this sign simply changed my URL.

Teamcity not printing built-in parameters using Powershell

I'm trying to print TeamCity parameters using Powershell. The Teamcity parameter is formed at run-time, by assigning it values elsewhere. The problem is that Teamcity only prints the string thus formed and not the value that is stored within the parameter. Please see a sample code where I need to print the build id, here the words "teamcity" and "build.id" are formed during run time. However, upon running Teamcity prints the string %teamcity.build.id%, and not the actual build id.
NOTE:
The type of TeamCity build in parameters that I need to print are agent parameters and not system parameters or environment parameters
$per = "%"
$t = "teamcity"
$b = ".build.id"
$indirect = $per+$t+$b+$per
Write-Output $indirect
PowerShell can't interpret the TeamCity variable at runtime.
The variable is injected into the script prior to it being run, thus the only way to do this would be to reference the variable as a whole.
e.g.
$buildId = "%teamcity.build.id%"
Write-Output $buildId

How do I reset my LDAP password from Perl?

My company, like everyone else's, requires password resets from time to time. This is all good and well for security's sake, but I'd like to explore the challenge of resetting it through a script (notably because we can't use our previous 25 passwords; Perl is much quicker about cycling through a list two-dozen deep than my fingers are).
I'm trying to use Perl and Win32::OLE's LDAP connectors to reset my password. I've followed a couple of examples online, and have, briefly:
use strict;
use Win32::OLE;
my $dn = 'cn=name,dc=corp,dc=com';
my $ldap = Win32::OLE->GetObject('LDAP:');
my $ldap_user = $ldap->OpenDSObject('LDAP://' . $dn,'username','password',1);
$ldap_user->SetPassword('mySw337NewPassword');
And all I get for my troubles is:
Win32::OLE(0.1707) error 0x80070005: "Access is denied"
in METHOD/PROPERTYGET "SetPassword" at pw.change.pl line 8
Is this something that can be worked around? I've located the Net::LDAP::Extension::SetPassword module, but no dice there.
Thanks!
Update for Leon (Max, you're next):
You're correct, I should have specified better. I tried Win32::OLE, failed, then separately tried Net::LDAP::Extension::SetPassword and failed even harder.
As for my server: I'm not certain, I'm not the LDAP guy :) By running ->root_dse->get_value('supportedExtension') I can see that the setPassword OID is not set, so maybe it's just not meant to be.
Final props to barneyton!
Final solution:
use strict;
use Win32::OLE;
my $orig_password = 'password123Test';
my $target_password = 'password321Test';
my $dn = 'cn=myname,dc=corp,dc=com';
my $ldap = Win32::OLE->GetObject('LDAP:');
my $ldap_user = $ldap->OpenDSObject('LDAP://'.$dn,'myname',$orig_password,1);
my $tmp_password = '';
for ( my $i = 0; $i < 30; ++$i )
{
$tmp_password = 'password' . $i . 'ABC';
print 'Changing to ' . $tmp_password . "\n";
$ldap_user->ChangePassword($orig_password,$tmp_password);
$orig_password = $tmp_password;
sleep 1;
}
$ldap_user->ChangePassword($tmp_password,$target_password);
When you said you were trying to "reset" your password, I think you really meant change password rather than set password. There is a difference between the two. "SetPassword" requires god/admin privilege since you are setting a user's password to a new value regardless of whether the old password is known, while "ChangePassword" requires the user to actually know the old password. I'm assuming your account does not have admin privilege, else you would not have gotten 0x80070005: "Access is denied"
So instead of:
$ldap_user->SetPassword('mySw337NewPassword');
try this:
$ldap_user->ChangePassword('password', 'mySw337NewPassword');
By the way, I've never done this stuff in perl, so I'm just guessing. Hope this helps you out.
Net::LDAP::Extension::SetPassword doesn't have anything to do with any OLE LDAP object. Either you use Net::LDAP, or you use Win32::OLE->GetObject('LDAP:').
You didn't mention what server you're using. Setting passwords requires an extension to LDAP, so that is relevant.
Another thing to keep in mind is Active Directory does not let you set passwords unless you bind to port 636 using LDAPS.
You could try to write the value to userPassword which would be a password reset, and you might not have rights to do that.
Otherwise you could try in one operation (LDIF would show it as separated by a single dash on a line) remove the value of the old password and then add the value of the new password. That would be a password change event.