Showing posts with label activenav. Show all posts
Showing posts with label activenav. Show all posts

Sunday, November 22, 2015

ActiveNav Update Plan

Despite having written several articles about it, I have still not released ActiveNav. That's because I don't feel that it's ready for serious use. I have been collecting things that need to be done before it is releasable, and here are some of the more easily definable ones that I frequently find myself wanting:

  • Change bind to automatically find a destination server and domain name if none are specified.
  • Allow binding to the Configuration and other non-primary Active Directory partitions.
  • Add useful in-program help for commands like find that have many subcommands.
  • Add support for invoking Active Directory actions (like SetPassword) on objects.
  • Make ce forgiving of case-sensitivity errors.
I would have some "writing" updates on the list, but expanding the scope from just reading will be a very big job.

Tuesday, November 17, 2015

Checking for the Presence of an Active Directory Attribute with ActiveNav

There are many Active Directory attributes that aren't present for every record of a certain type. For instance, I recently wanted to see how many users in an OU had a home directory mapped, so I needed to check each entry for the presence of a homeDirectory attribute. That can be accomplished with ActiveNav in two ways, both of which use the find command:

  1. find filter attribute like * finds all entries that have the attribute containing any value.
  2. find sort attribute str sorts the list of entries by the attribute, which has the side effect of removing entries that don't have the attribute from the result set.
I tested these on string values, but I'm not sure whether they'll work for System.__ComObject values.

Saturday, September 12, 2015

ActiveNav Scripting and Transcripting

Previously in this miniature series on the yet-unreleased ActiveNav tool, I mentioned "auto commands" and "transcripts." Those concepts are only tangentially related to each other, but they are both very simple, so I will cover them both in one post.

Passing a command-line parameter to ActiveNav will cause it to read commands as lines from that file and put them in the auto-command queue. That's the same queue that is accessible from ActiveNav extensions via IActiveNav.PushCommand. Therefore, each line in the script file will be executed before the user has a chance to type anything. I've found it very useful for my bind command.

Passing two command-line parameters results in the first being used as a script file and the second as a transcript (output) file. Every line written to the screen (except prompts and lines from misbehaving extensions) is also written to that file. The transcript file is recreated each time ActiveNav is run, but I might change that.

Friday, September 11, 2015

ActiveNav Extensions

I'll be out of communication when this goes live - this post is pre-scheduled.

ActiveNav, the command-line Active Directory browser, is extensible; third parties can write DLLs that interact with it and/or the user after being loaded with the "dll" command. This post is a reference for the extension API.

Extensions must be .NET class libraries referencing ActiveNav.exe and containing exactly one type that implements IActiveNavExtension and has a public parameterless constructor. After being constructed, the object will receive an IActiveNavExtension.Load(IActiveNav) call containing an ActiveNav controller object. IActiveNav has the following methods:

  • WriteLine(String) writes some text to the console window and to the transcript file if there is one. Use this instead of Console.WriteLine.
  • SetListener(IActiveNavExtension) causes all text that would be sent to the screen or to the transcript to be first send to the provided extension (usually the calling one) via an IActiveNavExtension.ListenerLine(String) call. Returning True from that function prevents the line from being printed. Only one extension can be the listener at a time, and the listener is cleared after each command finishes.
  • PushCommand(String) enqueues the given string as a command to be executed after the current command and any other auto-commands are finished.
  • RegisterCommand(String, Command) associates the given Command object with the given command name.
IActiveNav has the following events, which can be hooked in the IActiveNavExtension.Load method:
  • Exiting() is raised when the user issues the "exit" command. It is usually not raised when the command window containing ActiveNav is closed.
  • CommandString(String, ByRef Handled) is raised when the user enters some text as a command. If Handled is True when ActiveNav regains control, no attempt is made to interpret the text as an ActiveNav command. (It is assumed that the extension did something useful.)
  • CommandParsed(String, String(), ByRef Handled) is raised after the desired command (whose name is the first parameter) is identified but before it is invoked. The second parameter (the string array) is the array of arguments that would be passed to the command. Setting Handled to True causes ActiveNav to cancel the processing of the command.
  • CommandExecuting(String, String()) is raised after it is confirmed that the command will execute as a normal ActiveNav command but before any execution actually happens.
  • CommandFinished(String, String()) is raised after the given command is completed with the given arguments.
Adding new commands is done by inheriting Command, which has only two members:
  • Description (read-only property as String) is used to describe the command in the listing provided by the "help" command.
  • Run(String()) is invoked when the user runs the command with the given set of arguments.
Implementing IHelpSupport, while not required, allows the "help" command to give more detailed information on the command:
  • Arguments (read-only property as List(Of Tuple(Of String, String))) should be a collection of command arguments (the first entry in the tuple) and their respective description (the second entry).

Thursday, September 10, 2015

ActiveNav Find Reference

I'll be out of communication when this goes live - this post is pre-scheduled.

ActiveNav's "find" command is very powerful and very useful for finding entries in Active Directory that satisfy a certain set of predicates, but it is also far and away the most complicated command in the program. Since it's made of subcommands, the in-program help is not very useful, so I have trouble remembering how to use it. This entry will be useful to me and maybe to other people if/when I release ActiveNav in a completed state.

The "find" command is invoked as find subcommand [parameters...]. Each entry in this list is a subcommand, presented in what is hopefully a useful order.

  • load downloads all entries that are children - directly or indirectly - of the current entry, and prepares them for querying. No parameters. This will hit network utilization really hard if your Active Directory is big and you're at the root entry. Every other subcommand requires that a load has been issued.
  • list produces a list of entries currently in the result set, with result ID and entry name. No parameters.
  • go moves the current entry to the one in the result set with the numeric ID specified as the only parameter.
  • goname moves the current entry to the one in the result set with the name specified as the only parameter.
  • back moves the current entry to whatever it was before go or goname was used. No parameters.
  • filter narrows down the result set to only entries that match the predicate given as parameters. The first parameter after "filter" is the name of the object attribute being filtered on, the second is the verb/comparison (see the filter list below), and the third is the parameter to the verb. An exclamation mark before the verb inverts the filter so it leaves only entries that do not match it.
  • sort reorders the entries in the result set. The first parameter after "sort" is the name of the object attribute being compared, and the second is the comparison function (see below for sort verbs). An exclamation mark before the verb creates a descending sort.
  • flip reverses the order of the entries in the result set. No parameters.
  • cut leaves only the first N entries in the result set, with N being a number specified as the only parameter.
  • undo reverts the last change to the result set. "flip" changes do not count, and will be undone along with whatever was before them if they were the last change. There was a good reason for this, but I don't remember it. No parameters.
  • unfilter also puts the result set back to what it was before the last change, but "undo" can undo the unfiltering. No parameters.
  • clear removes everything from the result set, and clears the undo history.
Filter verbs:
  • is compares string values for equality.
  • like uses the Like (wildcard) comparison to compare string values for likeness.
  • = compares integer values for equality.
  • > checks whether the attribute is numerically greater than the parameter. Use !> for "less than or equal."
  • < checks whether the attribute is numerically lesser than the parameter. Use !< for "greater than or equal."
  • before checks whether the attribute is a date/time before the parameter.
  • after checks whether the attribute is a date/time after the parameter.
  • has checks whether the attribute is a list containing the parameter.
  • haslike checks whether the attribute is a list containing an entry that is wildcard-like the parameter.
  • cobefore is like before, but works on System.__ComObject entries that are actually dates.
  • coafter is to after as cobefore is to before.
  • bit checks whether the attribute has any of the bits that are set in the parameter.
  • and checks whether the attribute has all of the bits that are set in the parameter.
Sort verbs:
  • num compares values numerically.
  • str compares values alphabetically.
  • date compares dates.
  • codate compares System.__ComObject entries that are actually dates.
Special attribute names that work in "sort" and "filter":
  • . (a period) is the entry's name minus the LDAP cruft.
  • * (an asterisk) is the entry's non-fully-qualified name, but with the LDAP prefix.
  • ` (a backtick) is the entry's schema class name minus the LDAP prefix.
  • ~ (a tilde) is the entry's schema class name, including the LDAP prefix.

Tuesday, August 25, 2015

ActiveNav - Forgot Everything

I downloaded ActiveNav onto my reissued school laptop today (because it's a nice tool that I like to have around), and realized that despite having written it, I cannot remember how to use it. The help command was helpful for the basics (bind, ce, and meta), but it's almost completely useless for more complicated things like find. Fortunately, I have the source code to remind me what subcommands do interesting things.

I suppose I should, when I have time, put a little effort into improving the in-program documentation, since having to reference an external manual would be inconvenient. Another reasonable area of exploration is writing to the Active Directory; currently it only supports reading operations.

Tuesday, September 23, 2014

Introducing ActiveNav

Suppose you manage a domain (or want to poke around on one) and you want to browse the Active Directory. This is easy to do on a server or on a computer that has Remote Server Administration Tools installed, but impossible if you don't. RSAT also requires local admin to install, so that makes it a little bit more of a challenge to get running.

I have something more convenient: ActiveNav. ActiveNav is a console application for reading and navigating around Active Directory. It operates at the same level as the low-level ADSI Editor, but does some polishing to remove all the gross LDAP prefixes and stuff. It's designed to be like DOS, with LDAP servers as drives and entries as directories/files.

Another aspect of ActiveNav's design is to be scriptable and automatable. I already have some batch file-ish processing, but no branching or logic instructions. Also in development is an extension API for .NET programs to control the application. All the actual AD connection and browsing business is done and extensively tested. I want to do a little more scalability testing and development of the automation side before I release anything to the public, though.

Some things it can definitely do:

  • Connect to an AD-LDAP server with current or specified credentials
  • List the sub-entries of the current entry, with optional masking
  • Navigate inside OUs or container CN entries with relative or absolute paths
  • Display all properties or a specific property of the selected entry
  • Interpret the userAccountControl and sAMAccountType properties
  • Display group memberships and quickly navigate to members
  • Extract real data from byte array and COM object date properties
  • Find entries in the tree based on any property with various comparisons
  • Sort entries based on integer, string, date, or COM object date properties
Here are some things I have found it useful for:
  • Check whether a user has been locked out
  • Notify users after logon as to when their password was last misentered
  • Find users whose passwords never expire
  • Locate the OU where a user resides
Further developments and eventually a download coming soon!