Aug 18, 2015

OpsMgr: Where Are My Events?

Yeah. I know. We’re late to the party. We just got OpsMgr 2012 rolled out. If you want to skip the story time, just go to the TL;DR section.

So, one of the first times I opened the console, I realized there were some events I was looking for that I wasn’t able to find. After carefully combing the console (read: frantically clicking on crap) I came to the realization that no matter which event view I chose, it was restricted to one day.

After talking with one of my engineers, he suggested looking at this article http://www.opsman.co.za/how-to-search-for-more-then-500-objects-in-the-scom-console-group-and-report-add-objects-fields which seems to be referring to searching objects. It did, however, lead to a very useful registry key:

HKEY_CURRENT_USER\Software\Microsoft\Microsoft Operations Manager\3.0\Console\ConsoleUserSettings

I don’t know what most of these settings do and quite frankly don’t want to figure it out. There are, however, two registry values of particular interest:

  • AlertViewTimeSpan | 6048000000000
  • EventViewTimeSpan | 864000000000

image

They’re pretty self-explanatory -- at least the function. Out of the box, the in-console alerts display pretty much the whole range of what’s captured.

So far as I can tell and if the internet holds true:

  • 10,000,000 ticks in a 1 second
  • 86,400 seconds in 1 day

That means the Alert view value translates to 7 days, and the Event view value translates to 1 day. Eureka.

 

[ T L ; D R ]

All you have to do is take the existing QWORD value in the EventViewTimeSpan and multiple it by the number of days that you’re interested in. Keep in mind, this applies to all event views as there is no way to limit the date range for event views (that I know of.)

Aug 13, 2015

how to retrieve your ip address with powershell...

update: here is a new method using system.net.dns as noted here:

[system.net.dns]::gethostaddresses("").ipaddresstostring

 

update: this is how it’s performed in powershell v3 as demonstrated here.

(get-netadapter | get-netipaddress | ? addressfamily -eq 'IPv4').ipaddress

 

update: this is by far the easiest.

PS C:\temp> (gwmi Win32_NetworkAdapterConfiguration | ? { $_.IPAddress -ne $null }).ipaddress
192.168.1.101

 

 

are you laughing yet?  i know you probably find this topic amusing.  it's really interesting though.  whenever you get over it, i'll do this in the standard cmd.exe interpreter and then in powershell to show you what kind of coolness powershell does.

done?  okay, good.  this is an interpretation of a demo that bob wells did at our smug meeting.  hope you like it.

i should tell you, it's not as simple as the title would lead you to believe.  i like doing that little slight-of-hand thing since it gives the impression that i'm painting a very easy target on my back for your criticism (though it's probably true in other ways)!  the idea is that we want to retrieve just the ip address.  so here we go...

first of all, let's see how you'd get an ip address out of ipconfig.  since i can't get bob's method of regular expression to work, i created my own for this simple, little demo.  following is a series of commands and results to get to the final product. 

to start with, let's get the results of ipconfig and use findstr to pull out any lines that look like an ip address:

C:\temp>ipconfig | findstr [0-9].\.

   IPv4 Address. . . . . . . . . . . : 192.168.1.101
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : 192.168.1.1


alrighty, now we have a preliminary list of the addresses we want to use.  problem is, we need to strip it down to only the ip address, getting rid of the subnet mask and default gateway.  we can achieve this by passing the echoed statement back through findstr looking for the word address.  something like this:
C:\temp>for /f "delims=" %a in ('ipconfig ^| findstr [0-9].\.') do @echo %a | findstr "Address"

   IPv4 Address. . . . . . . . . . . : 192.168.1.101


so far, so good.  now let's get the ip address only.  we take the stuff from before and use it to the for command again to split everything with the delimiter ":", which gives us two tokens.  echoing the second one, we get the ip address:
C:\temp>for /f "delims=" %a in ('ipconfig ^| findstr [0-9].\.') do @for /f "tokens=1,2 delims=:" %i in ('@echo %a ^| findstr "Address"') do @echo %j

 192.168.1.101



ah crap!  see that?  there's a space we have to deal with!  to get rid of it, we'll pass it yet again through a for loop.  you see, the default delimiter of a for loop command is space and tab.  when we pass it back through, we just echo it back:

C:\temp>for /f "delims=" %a in ('ipconfig ^| findstr [0-9].\.') do @for /f "tokens=1,2 delims=:" %i in ('@echo %a ^| findstr "Address"') do @for /f %o in ('@echo %j') do @echo %o

192.168.1.101

 

and finally... we arrive at the results we were hoping for.  finally.

 

okay, let's do the same thing in powershell this time.  maybe we'll find it a little easier...

PS C:\temp> ipconfig | findstr [0-9].\.

   IPv4 Address. . . . . . . . . . . : 192.168.1.101
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : 192.168.1.1

 

so far the results look about the same.  unlike cmd.exe we're not just pushing around text.  in this case, the data is coming back as a string object.  when we run this through powershell, we can actually pull stuff out based on the index of the array.  since we know address is first, we can just call 0 like this:

PS C:\temp> (ipconfig | findstr [0-9].\.)[0]

   IPv4 Address. . . . . . . . . . . : 192.168.1.101

 

hmmm.  that was easy, but we're not done yet.  from here, we need to just retrieve the ip address.  the easiest way to do this is to split the contents (truncated it):

PS C:\temp> ((ipconfig | findstr [0-9].\.)[0]).Split()

IPv4
Address.
.
.
.
:
192.168.1.101

 

output is pretty ugly in that format, isn't it?  luckily, all we need is the last value.  just as 0 is the index which indicates the first member of an array, we can use -1 to indicate the very last one.  in this case, the split function moves the ip address to the very end.  now we can capture that array member and bring it back.  check it out:

PS C:\temp> ((ipconfig | findstr [0-9].\.)[0]).Split()[-1]

192.168.1.101

 

isn't that cool?

 

here's a couple of other things that bob demonstrated.  i'm sure you can figure them out on your own though.  no point in be boring you with my narrative:

[MATH]::Round(((Get-WmiObject win32_computersystem).totalphysicalmemory / 1gb),2)

foreach($file in Get-ChildItem){$size =+ $file.length}

Jul 14, 2015

Atlanta TechStravaganza 08.21.2015

Hey everyone!

If you haven’t heard the news, we are holding another Atlanta TechStravanganza event this year. Once again, the event will be held at the Georgia Tech conference center here in the heart of Atlanta.

Mark Minasi is heading down to kick it off as our keynote speaker. Pretty awesome right? We’re running three tracks (System Center, PowerShell, and Infrastructure) full of great content. On top of that, Tommy will be hanging around running a lab if you want to get some hands-on experience.

Your ticket also includes meals, entry into prize giveaways, and plenty of networking opportunity. Cost? FREE! Because we work with generous companies that love to support the community, this event never costs you a penny.

Ready to sign up? You should probably hurry. Half of the tickets are already gone. Head on over to our brand new site at http://atltechstravaganza.com. Hope to see you there! 37 days left!

May 19, 2015

Bind Response: InvalidCredentials

Sometimes I get the strangest things that come across my desk. As a manager, I don’t have a lot of time for troubleshooting so when I do get ahold of something, it’s fun to tear apart. I told my team about my findings. One of them asked how I arrived at the answer… so I thought I’d blog it just in case it interests anyone else.

As a favor to a coworker, I looked into an application configuration problem that was described as such:

  • Application is configured for LDAP.
  • All users can successfully log into the application except one person.
  • This one person is also the administrator of the application.

The app owner indicated they were seeing timeout errors in their logs. There was no denying it. The call was timing out:

Servlet.service() for servlet dispatcher threw exception
javax.naming.NamingException: LDAP response read timed out, timeout used:-1ms.; remaining name ''
                at com.sun.jndi.ldap.Connection.readReply(Connection.java:483)
                at com.sun.jndi.ldap.LdapClient.getSearchReply(LdapClient.java:639)
                at com.sun.jndi.ldap.LdapClient.search(LdapClient.java:562)
                at com.sun.jndi.ldap.LdapCtx.doSearch(LdapCtx.java:1985)
                at com.sun.jndi.ldap.LdapCtx.searchAux(LdapCtx.java:1847)
                at com.sun.jndi.ldap.LdapCtx.c_search(LdapCtx.java:1772)

To respond to that, the first thing we did was check the LDAP configuration to make sure it wasn’t misconfigured anywhere. I couldn’t tell if they what it was timing out to. A bind request? A search request? Who knows.

What little there was in the ldap.properties file looked appropriately set so they went back to scour more logs. I asked them to verify there was no application wonkiness by making someone else an admin and having them log on. Negative. All good. Now we’re getting somewhere.

Of course, you never find the log that tells you exactly what’s going on. I’m pretty sure this is why packet tracing became a thing. I asked for a trace. This is what the trace revealed:

image

Now we can confirm that indeed the user’s attempt to bind fails. He had no problem logging into other things though -- his workstation for example. I told the app team that the user was not providing his credentials properly, or it was an application problem. They weren’t sure where to go next. I figured it had to be the logon form, though, so I tried one more thing.404

I asked the user to tell me the character length of his password and verified the character length of the form. The form truncated at least two characters off his password. The password is masked and at such a length that you might not realize little dots weren’t continuing to show up. :o)

PROBLEM SOLVED! The LDAP response InvalidCredentials was indeed correct. Once you get the application logs out of the way and go straight down to the packet, you can see so much more. That’s my lesson of the day.

Mar 29, 2015

Embedding Expressions in Select-Objects

I had my first taste of using Select-Objects in a way more than just modifying values on output or to specifically pick a set of attributes to list.

When someone asks for a list of users and their managers, meh, no big deal. When they ask for the user, their manager, and their manager’s email address -- well, no big deal but not as much of a no big deal as the first one.

I found it a bit annoying that I had to write a script to do this every time I wanted to get this type of information so I did a bit of exploring. Turned out a little while ago, while experimenting in optimizing speed in a script, I had tried a method of using Select-Object to create a custom object.

 

Using Select-Object to Pull Manager Detail on the Fly
$myData | select 
    @{n='UserId';e={$_.samaccountname}}, 
    @{n='Created';e={$_.lastlogon}}, 
    @{n='Name';e={$_.name}}, 
    @{n='Manager';e={$_.manager}},
    @{n='Manager Email';e={ 
        (get-aduser $_.manager -properties mail).mail 
        }
    }

Hopefully this makes sense. I broke it out so it’s clearer to read. For my example, I already had a dataset with specific information in it. I just needed to pipe it out and get the manager email. I piped this to export-csv to create a file to look at.

The meaningful part here is that you can embed things in the expression -- like the Get-AdUser call.

 

Slightly More Challenging
$myData | select 
    @{n='UserId';e={$_.samaccountname}}, 
    @{n='Logon';e={$_.lastlogondate}}, 
    @{n='Name';e={$_.name}}, 
    @{n='Manager';e={ 
        (get-aduser $_.samaccountname -Properties manager).manager 
        }
    }, 
    @{n='Manager Email';e={ 
        (get-aduser $(get-aduser $_.samaccountname -Properties manager).manager -properties mail).mail 
        }
    }`

And again, I broke this out but in reality ran it on a single line. In this case, I didn’t have the manager value already so I had to run a command in both expressions -- manager and manager email.

This process isn’t going to scale well with a lot of data elements. This is just to show you something that might save you a little time if you’re just tooting around. :-)