I am trying to check for expired certs. The problem is we leave expired ones on our servers sometimes for reference, and I only want to display ones leading up to an expiration. How do I exclude negative integers in this case?
Example output:
Expires In (Days) : -25 NotAfter : 9/1/2018 10:56:27 AM Subject : CN=SERVER01.domain.com Issuer : CN=SOMEAUTHICA01, DC=domain, DC=com
Expires In (Days) : -17 NotAfter : 9/9/2018 3:45:55 PM Subject : CN=SERVER02.domain.com Issuer : CN=SOMEAUTHICA01, DC=domain, DC=com
$threshold = 30 #Number of days to look for expiring certificates
$deadline = (Get-Date).AddDays($threshold) #Set expiration deadline date
$serverList = 'SERVER01.domain.com','SERVER02.domain.com'
$expired = Invoke-Command -ComputerName $serverList { Dir Cert:\LocalMachine\My } | Sort-Object -Property NotAfter | Get-Unique | foreach {
If ($_.NotAfter -le $deadline) {$_ | Select Issuer, Subject, NotAfter, #{Label="Expires In (Days)";Expression={($_.NotAfter - (Get-Date)).Days}} }
}
You have to exclude the certificates that are already expired. This can be done as follows.
$threshold = 30; #Number of days to look for expiring certificates
$deadline = (Get-Date).AddDays($threshold); #Set expiration deadline date
$serverList = 'SERVER01.domain.com','SERVER02.domain.com';
$expired = Invoke-Command -ComputerName $serverList { Dir Cert:\LocalMachine\My } | Sort-Object -Property NotAfter | Get-Unique | foreach {
If ($_.NotAfter -le $deadline -and $_.NotAfter -gt (Get-Date).Days) {$_ | Select Issuer, Subject, NotAfter, #{Label="Expires In (Days)";Expression={($_.NotAfter - (Get-Date)).Days}} }
}
Related
I wrote a script to list all vendors in the azure ad to check if they are working or not. the script find the logged in users for the past day and if there is a record it should print, if there is no record and the vendor did not logged in or work it should print no login records. but my script is not working well any one can help?
###########################Here is the code ##################
#get azure ad users
$AzADUsers = get-azureaduser
#start for loop
foreach ($user in $AzADUsers){
#list attributes
$dp = $user.DisplayName
$company = $user.CompanyName
# list of contractors/vendors who didn't log in during the day.
if ($company -eq "Vendor Resource - companyname1" -or $company -eq "Vendor Resource - companyname2" -or $company -eq "Vendor Resource - companyname3") {
#check if they logged in the past 24 hours
$SetDate = (Get-Date).AddDays(-1);
$SetDate = Get-Date($SetDate) -format yyyy-MM-dd
$AllSiginLogs = Get-AzureADAuditSignInLogs -Filter "createdDateTime gt $SetDate"
$LoginRecord = $AllSiginLogs | Sort-Object CreatedDateTime -Descending
if($LoginRecord.Count -gt 0){
$lastLogin = $LoginRecord[0].CreatedDateTime
}
else{
$lastLogin = 'no login record | Sick'
}
Write-Host "Last logon time : " $lastLogin $dp $company
Write-Host " "
}
}
in addition to our discussion:
Currently you loop through the $AzAdUsers and query foreach the SignInLogs. But you do not filter the SignInLogs for the specific user, you query all the time the same information and select the latest entry from that log, but it has no relation to the current user.
You have to filter the SignInLog for the specific user, e.g.:
$AllSiginLogs = Get-AzureADAuditSignInLogs -filter "Id eq '$($user.Id)' and createdDateTime gt $SetDate"
After that you could do:
$attrsht = #{
userId=$User.id
DisplayName=$user.displayname
LastSignIn=$LoginRecord.CreatedDateTime
}
new-object -typename psobject -property $attrsht
Btw. the AzModule will be replaced by the microsoft.graph modules. So it might be the right time to do the switch, which you have to do in any case until 2024.
If you do so, you can directly get the lastSignInDateTime from the user object:
#Switch to beta API
select-mgprofile -name beta
$lastSignIn = get-mguser -userId $user.id -Property signinactivity
$lastSignIn.LastSignInDateTime
In regards to you latest comment:
once again, if you want to know the last signInDateTime for a specific user you have to filter for that user id. if you filter by companyname you will probably get several users back and then you have to loop over this array of users and query the signInLog foreach user. the problem you are facing is that you miss to specify consistensylevel and countvariable, e.g.:
$company = "MyCompanyName"
$users = Get-MgUser -filter "companyname eq '$company'" -ConsistencyLevel eventual -CountVariable $null -property Id,CompanyName,DisplayName
select-mgprofile -Name beta
$lastSignInDateTime = #(
foreach ($user in $users){
$LoginRecord = get-mguser -userId $user.id -Property signinactivity
$attrsht = #{
userId=$User.id
DisplayName=$user.displayname
CompanyName=$user.CompanyName
LastSignIn=$LoginRecord.signinactivity.LastSignInDateTime
}
new-object -typename psobject -property $attrsht
}
)
You need to have the MgGraph module installed to run the above mentioned cmdlets -> install-module microsoft.graph
More information in regards to consistensylevel:
https://devblogs.microsoft.com/microsoft365dev/build-advanced-queries-with-count-filter-search-and-orderby/
What my script does is get a list of Azure app registrations and then calculate how many days left until the secret expires. It works fine in the main, except that if an app registration has 2 secrets it falls over. Having 2 secretes isn't common, but we introduced a 2nd secret on one app registration just for a short period of testing.
After obtaining the list of app registrations (there are 10 in total), my script then goes through each of them to obtain the expiration date date and then calculate the number of days left. Below is a snippet ...
foreach ($app in $applications) {
$Appname = $app.displayName
$AppID = $app.Id
$ApplID = $app.AppId
$AppCreds = Get-AzADAppCredential -ObjectId $AppID | select StartDateTime, EndDateTime, Hint
$today = get-date
$StartDate = $AppCreds.StartDateTime
$EndDate = $AppCreds.EndDateTime
$operation = $EndDate - $today
$ODays = $operation.Days
# Check how many days are remaining for secret expiration
if ($ODays -le $Days -and $ODays -ge 0)
Once obtained it sends an e-mail if a secret is going to expire within 60 days.
When the script hits the app registration with two secrets it fails with ...
"Problem occurred: Method invocation failed because [System.Object[]] does not contain a method named 'op_Subtraction'."
Any ideas why this is happening?
The $AppCreds is array in case if you have more than app secret. Here is fully re-worked script to build the report:
function Get-AzADAppCredentialExpiration(){
$retArray = #()
$applications = Get-AzADApplication
$today = get-date
foreach($app in $applications){
$AppCreds = #(Get-AzADAppCredential -ObjectId $app.Id)
$AppCreds | %{
$retArray += [PSCustomObject]#{
AppName = $app.DisplayName;
ClientSecretId = $_.KeyId
SecretHint = $_.Hint
DaysLeft = ($_.EndDateTime - $today).Days
}
}
}
return $retArray
}
$report = Get-AzADAppCredentialExpiration
$report | ? {$_.DaysLeft -le 30 -and $_.DaysLeft -gt 0} | Group-Object -Property AppName | %{
Write-Host "Key for application $($_.Name) will be expired soon:" -ForegroundColor Yellow
$_.Group | %{
Write-Host "`t$($_.SecretHint) ($($_.ClientSecretId))" -ForegroundColor Yellow
}
}
$report | ? {$_.DaysLeft -le 0} | Group-Object -Property AppName | %{
Write-Host "Key for application $($_.Name) are expired:" -ForegroundColor Red
$_.Group | %{
Write-Host "`t$($_.SecretHint) ($($_.ClientSecretId))" -ForegroundColor Red
}
}
Old answer
The $AppCreds is array in case if you have more than app secret. So you should check if it array and then calculate accordingly:
foreach ($app in $applications) {
$Appname = $app.displayName
$AppID = $app.Id
$ApplID = $app.AppId
$AppCreds = Get-AzADAppCredential -ObjectId $AppID | select StartDateTime, EndDateTime, Hint
$today = get-date
if($AppCreds -is [Array]){
$AppCreds | %{
$StartDate = $_.StartDateTime
$EndDate = $_.EndDateTime
$operation = $EndDate - $today
#....
}
}
else{
$StartDate = $AppCreds.StartDateTime
$EndDate = $AppCreds.EndDateTime
$operation = $EndDate - $today
}
I am trying to get all the Azure AD Application secrets and certificates that will expire in the next 30 days. I'm using Get-AzADApplication piped to Get-AzADAppCredential to get the applications EndDate but it is not returning the correct results as it doesnt match the dates correctly even if I format them both exactly the same. The code below returns some apps that expire in 2025!
$todaysDate = (Get-Date -UFormat "%e/%m/%Y")
$expiryDate = Get-Date $(Get-Date).AddDays(30) -UFormat "%e/%m/%Y"
$aboutToExpire = Get-AzADApplication | ForEach-Object {
$app = $_
#(
Get-AzADAppCredential -ObjectId $_.ObjectId -ErrorAction SilentlyContinue
) | Where-Object { (Get-Date $_.EndDate -UFormat "%e/%m/%Y") -le $expiryDate -and (Get-Date $_.EndDate -UFormat "%e/%m/%Y") -gt $todaysDate} | ForEach-Object {
[PSCustomObject] #{
AppName = $app.DisplayName
ObjectID = $app.ObjectId
AppId = $app.ApplicationId
StartDate = $_.StartDate
EndDate = $_.EndDate
ExpiryDate = $expiryDate
}
}
}
$aboutToExpire
Here is what I'm using for searching expired secrets and certs. I believe you have an issue with the date comparison because of the not correct date format, please take a look at my example.
$apps = Get-AzADApplication
$xs = Get-Date
$ys = Get-Date (Get-Date).AddDays(+60)
$alertListExps = #()
$alertListExpd = #()
foreach ($app in $apps)
{
$secrets = Get-AzADAppCredential -ObjectId $app.ObjectId
if ($null -eq $secrets){}
else
{
foreach ($secret in $secrets)
{
$secretDate = [datetime]$secret.EndDate #::parseexact($secret.EndDate,'dd/MM/yyyy HH:mm:ss',$null)
if ($secretDate -le $xs)
{
$alertListExpd += "*App:* " + $app.DisplayName + " *exired:* " + $secret.EndDate + ' ' + '(' + $secret.Type + ')' | Out-String
}
elseif ($secretDate -le $ys)
{
$alertListExps += "*App:* " + $app.DisplayName + " *exires:* " + $secret.EndDate + ' ' + '(' + $secret.Type + ')' | Out-String
}
}
}
It was a date issue. The first issue was trying to parse the date. Thanks to #oleh-tarasenko for the parseexact code. The second issue was with the comparison operator trying to compare en-AU dates with en-US dates and either failing or outputting bad results. Trick was to provide the specific culture. Code below.
$CIDE = New-Object System.Globalization.CultureInfo("en-US")
$endDate = [DateTime]::parseexact($secret.EndDate, "d/MM/yyyy h:mm:ss tt", $CIDE)
I am extracting computers from our Azure portal and I am specifically looking for devices which have had no activity in over 120 days.
The issue every time I extract this info it only gives me the activity/logon of the initial registration for the device.
Some of our devices have multiple registrations as they are passed from user to user.
So when I extract the info it is not accurate.
I used the below which I thought should work but I still get the devices that have newer activity than my target date. I also see an error when I am running the script I have include that below beneath the code I have used.
Could someone assist I feel I am close.
clear-host
$maxDate = Get-Date '6/1/19'
#Create a hash table to remove dupes
$set = #{}
#create our final array
$cleanSet = #()
#load data
$data = Get-MsolDevice -All | select-object -Property ObjectID, ApproximateLastLogonTimestamp, DisplayName
#for each item in the pipeline, add it to our hash table
foreach($_ in $data) {
#if the item isn't in the hash table, add it
if(!$set.Contains($_.ObjectID)) {
$set.Add($_.ObjectID, $_)
}
else {
#if we have a more recent date for the item, update the date so we only have the most recent one
if((Get-Date $_.ApproximateLastLogonTimestamp) -gt (Get-Date $set[$_.ObjectId].ApproximateLastLogonTimestamp)) {
$set[$_.ObjectID].ApproximateLastLogonTimestamp = $_.ApproximateLastLogonTimestamp
}
}
}
#now that we have the most recent date for each item, remove ones newer than our target date.
$set.GetEnumerator() | ForEach-Object{
if((get-date $_.Value.ApproximateLastLogonTimestamp) -lt $maxDate) {
$cleanSet += $_.Value
}
}
$cleanSet | select-object -Property ObjectID, DisplayName | export-csv "C:\Users\tesyuser\Desktop\Project Work\Stale machine on Azure\Exported CSV\2HIE-Stale-Device-List.csv" -NoTypeInformation
error
Get-Date : Cannot bind parameter 'Date' to the target. Exception
setting "Date": "Cannot convert null to type "System.DateTime"." At
line:29 char:18
Hi So my code should now look like this?
$maxDate = Get-Date '6/1/19'
#Create a hash table to remove dupes
$set = #{}
#create our final array
$cleanSet = #()
#load data
$data = Get-MsolDevice -All | select-object -Property ObjectID, ApproximateLastLogonTimestamp, DisplayName
#for each item in the pipeline, add it to our hash table
$data | ForEach-Object {..} {
#if the item isn't in the hash table, add it
if(!$set.Contains($_.ObjectID)) {
$set.Add($_.ObjectID, $_)
}
else {
#if we have a more recent date for the item, update the date so we only have the most recent one
if((Get-Date $_.ApproximateLastLogonTimestamp) -gt (Get-Date $set[$_.ObjectId].ApproximateLastLogonTimestamp)) {
$set[$_.ObjectID].ApproximateLastLogonTimestamp = $_.ApproximateLastLogonTimestamp
}
}
}
#now that we have the most recent date for each item, remove ones newer than our target date.
$set.GetEnumerator() | ForEach-Object{
if((get-date $_.Value.ApproximateLastLogonTimestamp) -lt $maxDate) {
$cleanSet += $_.Value
}
}
$cleanSet | select-object -Property ObjectID, DisplayName | export-csv "C:\Users\birrelld\Desktop\Project Work\Stale machine on Azure\Exported CSV\3HIE-Stale-Device-List.csv" -NoTypeInformation
my script is now nearly finished. I use it to find big folders / subfolders etc..
i did not understand the format parameter -f yet, even though i checked the examples 3 times or even more :).
right now my script orders the sizes by strings. so 15 mb is smaller than 2 mb.
i have around 300 folders to check and it's better to convert that string to a number.
Thank you in advance!
here is my the part of my script which does this :
function Folders-Size($folders)
{
$directories = #()
foreach ($i in $folders)
{
$childItems = (Get-ChildItem $i.FullName -recurse | Measure-Object -property length -sum)
$size = "{0:N2}" -f ($childItems.sum / 1MB)
$name = $i.FullName
$data = New-Object PSObject -Property #{ Name=$name; Size=$size}
$directories += $data
}
$directories = $directories | Sort-Object Size -descending
$directories
}
try:
$directories | Sort-Object { [decimal]::parse($_.Size) } -descending