Powershell Set-ADUser userCertificate parameter type error - powershell

I have a script, which essentially does the following:
$user = Get-ADUser $someUserName -Server $someCertServer -Properties *
$user.userCertificate |% { Set-ADUser $someUserName -Certificates #{Add=$_} }
It copies the cert data from a cert-server to the default server. $user.userCertificate is of type Microsoft.ActiveDirectory.Management.ADPropertyValueCollection and $user.userCertificate[0] is of type System.Byte[]. According to the docs, I can pass a Byte[] and be good to go. By using the foreach operator in the above script, I get the Byte[].
However, Powershell fails with the error message
the parameter certificates requires all values in the collection to be of the same type
(and underlines the #{Add=$_}; the message might not be 100% accurate, since I had to translate it to English). Because of the foreach operator, there is only one type: a Byte[]. What does that error message mean and how can I shove the certificate into the ADUser object?
I also tried to convert the Byte[] to a certificate object, however it ended up with the same error message:
$cert = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2
$cert.Import($user.userCertificate[0])
Set-ADUser $someUserName -Certificates #{Add=$cert}

The very first issue I see is that you are calling on the wrong property for your example to work.
$user.userCertificate | ForEach-Object { Set-ADUser $someUserName -Certificates #{Add=$_}}
While there is a property called userCertificate on that object that contains an collection of [byte[]]. For that code to work the way you want it to you should be using Certificates. Certificates is an collection of Security.Cryptography.X509Certificates.X509Certificate
So making that change I was able to add another users certificate to my own account.
$certUser = Get-Aduser "someGuy" -Properties certificates
$certUser.Certificates | %{ Set-ADUser "ME" -Certificates #{Add=$_}}
Note: It is a better practice to only request the properties you need from AD. Using -properties * is a waste of effort and needless resources
While this exact scenario is not covered there is a nice write-up on the MSDN Blogs about dealing with certs.
Cert as a byte array
Now that we know userCertificate is a collection of byte arrays maybe we can look into how to use that.
I was having issues using the byte array with the certificate parameter for Set-Aduser even though it is supposed to support it. I got the error
Set-ADUser : Cannot validate argument on parameter 'Certificates'. Values in the argument collection should be of Type: 'System.Security.Cryptography.X509Certificates.X509Certificate'
I did get this to work but I had to cast the byte array as a cert object first which was redundant considering this appear to be what the Certificates property already is.
$certUser.Usercertificate | ForEach-Object{
Set-ADUser "ME" -certificate #{Add=[System.Security.Cryptography.X509Certificates.X509Certificate]$_}
}

Related

Setting ImmutableID for O365 users

I'm having difficulties creating a command that generates a new GUID into the user's immutableID field.
The command Set-MsolUser -UserPrincipalName "UPN" -ImmutableID New-GUID seems to just use "New-GUID" as the immutable ID.
Ultimately I'd like to set it to all users so I was thinking something like this:
Get-Msoluser -All | ForEach-Object {set-msoluser -UserPrincipalName $_.UserPrincipalName -ImmutableID New-GUID}
I'm pretty sure I'm missing something that makes the New-GUID run.
Reason I'm doing this is cause O365 doesn't natively have an immutableID so I figured a random GUID would work for federation.
Any help is appreciated.

Add Sip to proxyaddress attribute in AD using powershell

I have username, and email address.
Couldn’t find a simple command to add sip address in AD attributes.
SIP:emiladdress
Please help
Thanks
You need to get the AD user you want to update then append the ProxyAddresses property (attribute) then set the AD user. I neat and easy way to do this is to use the Active Directory cmdlets instancing feature.
$ADUser = Get-ADUser <UserName> -Properties ProxyAddresses
$ADUser.ProxyAddresses = $ADUser.ProxyAddresses += "sip:user#domain.com"
Set-ADUser -Instance $ADUser

Access 'PasswordNeverExpires' property in Azure AD via C#

I have the below code C# which works great for querying Azure AD but I need to also read in the property 'PasswordNeverExpires' as shown in the below screenshot. I cannot see the property on the full MS list here - https://learn.microsoft.com/en-us/graph/api/resources/user?view=graph-rest-1.0 - only a 'passwordPolicies' property which returns "DisablePasswordExpiration" for all our users which doesn't tally up with the results shown in AD manager. I can see plenty of powershell scripts, for example here - https://serverfault.com/questions/730189/powershell-find-all-users-with-password-never-expires - which mention a 'passwordNeverExpires' property but this only appears blank when I run my C# script.
string Url = $"{config.ApiUrl}v1.0/users?$select=userPrincipalName,lastPasswordChangeDateTime,PasswordNeverExpires,passwordNeverExpires";
do {
string JSON = await apiCaller.CallWebApiAndProcessResultASync(Url, result.AccessToken, Display);
Url = AADR.OdataNextLink;
} while (AADR.OdataNextLink != null);
The powershell scripts you found in this post is for AD rather than AAD. So it doesn't work for AAD. There is not a property named PasswordNeverExpires in AAD Module.
PowerShell Script:
You can use the following PowerShell cmdlet to see if a single user's password is set to never expire (reference here):
Get-AzureADUser -ObjectId <user id or UPN> | Select-Object UserprincipalName,#{
N="PasswordNeverExpires";E={$_.PasswordPolicies -contains "DisablePasswordExpiration"}
}
The cmdlet aliases PasswordPolicies -contains "DisablePasswordExpiration" to a new property PasswordNeverExpires.
To see the Password never expires setting for all users, run the following cmdlet:
Get-AzureADUser -All $true | Select-Object UserprincipalName,#{
N="PasswordNeverExpires";E={$_.PasswordPolicies -contains "DisablePasswordExpiration"}
}
Microsoft Graph:
Since there is no PasswordNeverExpires property in MS Graph user resource type, you should just query the passwordPolicies property using MS Graph.
GET https://graph.microsoft.com/v1.0/users?$select=userPrincipalName,lastPasswordChangeDateTime,passwordPolicies
Then you will get "passwordPolicies": "DisablePasswordExpiration" in the response. Use your own code logic to handle it (define a PasswordNeverExpires and set it to true).

Create AD Object - Not Exchange

I am currently trying to create an Active Directory contact object in a specific OU in our Active Directory. I am not looking at using Exchange PowerShell. I would like to do this via normal PowerShell directly in to AD.
I have looked online and found that I can create a contact using the below command, this creates it in a specific OU.
New-ADObject -Name SaraDavisSGTContact3 -Type contact -Path "OU=SGTestOU,OU=Contacts,DC=example,DC=Example,DC=local"
How would I also get it to add other attributes such as mail (email address), first name, surname, etc.? I tried -Mail example.com, etc., but this didn't work.
Please bear in mind I will eventually try and get this to read from a CSV to do in bulk, so the simplier the code the better.
Use the -OtherAttributes Parameter to add additional attributes.
See New-ADObject MSDN Documentation
New-ADObject -name SaraDavisSGTContact3 -Type Contact -path "OU=SGTestOU,OU=Contacts,DC=example,DC=Example,DC=local" -OtherAttributes #{
'mail'="sara#gmail.com";
'proxyAddresses'="sara#gmail.com";
'givenName'="Sara";
'sn'="Davis";
'displayname'="Sara Davis"
}

Powershell: Setting PsCredentials to $Null for username and $Null for password

How can I create a $Null username and $Null password PScredentials object?
According to this article, the null PSCredential causes Powershell to use Windows Authentication, which seems a much easier way to run scripts in a domain setting. Unfortunatelly I cant seem to figure out where/how he's setting it to Null:
http://blogs.msdn.com/b/dvespa/archive/2010/02/22/how-to-use-windows-authentication-with-the-pscredential-class.aspx
Other resources:
This answer specified $Null for password, but wont allow $Null username.
Create PSCredential without a password
Thank you.
Why do you need a $null PSCredential object ?
According to the documentation
-Credential <PSCredential>
Specifies a user account that has permission to perform this action. The default is the current user.
It means tha if you just don't use this parameter you will use Windows Authentication.
Edited :
So in Powershell if you want a null credential you just have to specify it :
test :
Get-WmiObject Win32_Process -Credential
Get-WmiObject Win32_Process -Credential $null
and
Get-WmiObject Win32_Process -Credential (Get-Credential)
The constant [PSCredential]::Empty (aka [System.Management.Automation.PSCredential]::Empty) gives you a valid object of type PSCredential but with both username and password set to null.
However, that is not the current user's credentials; rather it means "no credentials". There may be logic in the function you're calling for this to be a moot point (i.e. where the function's the logic says to use the current security context when $credentials -eq [PSCredential]::Empty), but in some contexts this same value may be used for other purposes (e.g. to say you want to use anonymous authentication).
You cannot get the current user's credentials without prompting for them or explicitly assigning them in some other way; otherwise this would present a security risk
#create a credential object for demo purposes.
#Imagine that instead of this line we were saying `$credential = Get-CurrentUserCredential`
#(you have to imagine this, since no such function exists).
$credential = [PSCredential]::new('myUsername', ('superSecretPassword' | ConvertTo-SecureString -AsPlainText -Force))
#we can now see this user's password;
#someone malicious could have this script run under the current user's
#profile & have this information reported back to them.
$credential.GetNetworkCredential().Password
If you want to run something as the current user, you already are (i.e. hence them being the current user); so you don't need to get their credentials.
That said, there are cases where it would be nice to have their credentials; e.g. if accessing a resource which doesn't use the current user context / needs explicit credentials. In such cases you have to either prompt for credentials (Get-Credential $env:username), or read them from some resource (see https://stackoverflow.com/a/6240319/361842).
There's a really thorough explanation of credentials here: http://duffney.io/AddCredentialsToPowerShellFunctions; definitely worth a read.