jgstew / tools

various scripts and tools
MIT License
24 stars 14 forks source link

Match agent version to running server (install_bigfix) #11

Open atlauren opened 8 years ago

atlauren commented 8 years ago

I suggest a -match option that explicitly installs the agent version that matches the running server. The server version is available in the HTTP Server header.

Server: BigFixHTTPServer/9.2.7.53

Affected Files:

atlauren commented 8 years ago

Whoops. I didn't attach this to the file. Will reopen.

atlauren commented 8 years ago

Reopening as I apparently misunderstand github.

Affected Files:

jgstew commented 8 years ago

Is this version available in the header returned by relays as well? I've never actually looked.

This is not a bad idea, but there is absolutely no reason that the agent and server versions must match. Newer or older is generally fine. I typically install the newest version available to new clients, even if I have no plans to upgrade the server version in the near future.

atlauren commented 8 years ago

The relay install fixlets only apply for the agent version that matches the running server. Ergo, if you intend the machine to be a relay (as I am building in a kickstart), matching the server version is valuable.

atlauren commented 8 years ago

I just checked one of my relays, and the header is there as well.

jgstew commented 8 years ago

This is a good point about relays. Technically client versions don't have to match the relays or the servers, and that should include relays themselves, but it does make sense that the relay itself should have the same version client as it has relay.

Are you going to make your code public? I have been thinking of making a relay kickstart script like this client one, which would probably incorporate this client install code as well. The idea would be to provide the parent relay as the location for the masthead file, and it would then install the client and relay on the system, with the parent relay set as the primary relay automatically.

Actually, if you are making a relay kickstart, then you would just set the version variable to the version from the header and it would just do its thing automatically. The relay kickstart shouldn't run this code, it would incorporate it so you would only need 1 script instead of 2.

atlauren commented 8 years ago

Putting stuff here while I noodle on this:

SERVERVERSION=`curl -sD - http://$RELAYFQDN:52311 | grep Server | awk -F/ '{print $2}'`
atlauren commented 8 years ago

My adaptation is below. This adds/changes:

Start/end the replace with the first and last lines, inclusive.

command_exists () {
  type "$1" &> /dev/null ;
}

function do_usage {
    echo "Usage: -fqdn ROOTSERVERORRELAY [-match y]"
    echo "  -fqdn  - FQDN for BigFix root server, or relay. Required."
    echo "  -match - Installs the agent version running on the server/relay. Optional."
    echo "         Ignored without parameter 'y'."
    echo "         (Default behavior installs the script's stored URLVERSION.)"
    exit 1
}

if [[ $# = 0 ]] ; then
    do_usage
fi

# - http://stackoverflow.com/a/14203146
while [[ $# > 0 ]]
do
key="$1"

case $key in
    -fqdn)
    FQDN="$2"
    echo $FQDN
    shift # past argument
    ;;
    -match)
    MATCH="$2"
    echo $MATCH
    shift # past argument
    ;;
    *)
esac
shift
done

if [[ -n $FQDN ]] ; then
    CURLRESULT=`curl -s -S http://$FQDN:52311 -o /dev/null 2>&1`
        if [[ -n $CURLRESULT ]] ; then
            echo "CONNECTION ERROR: "$CURLRESULT
            exit 1
        fi
    RELAYFQDN=$FQDN
    echo "RELAYFQDN="$RELAYFQDN
    MASTHEADURL="http://$RELAYFQDN:52311/masthead/masthead.afxm"
    echo "MASTHEADURL="$MASTHEADURL
else
    do_usage
fi

# these variables are used to determine which version of the BigFix agent should be downloaded
# these variables are typically set to the latest version of the BigFix agent
# URLMAJORMINOR is the first two integers of URLVERSION
#  most recent version# found here under `Agent`:  http://support.bigfix.com/bes/release/
if [[ $MATCH = "y" ]] ; then
    URLVERSION=`curl -s -D - http://$RELAYFQDN:52311 -o /dev/null | awk -F/ '/Server/ {print $2}' | tr -d "\r"`
    else
    URLVERSION=9.5.2.56
fi
echo "URLVERSION="$URLVERSION
URLMAJORMINOR=`echo $URLVERSION | awk '/./ {gsub(/\./, " "); print $1 $2}'`
echo "URLMAJORMINOR"=$URLMAJORMINOR

# check for x32bit or x64bit OS
atlauren commented 8 years ago

Reference for the switch splitting:

# - http://stackoverflow.com/a/1420
jgstew commented 8 years ago

That doesn't appear to be the correct reference for switch splitting.

I was just going to ask if you had references for some of this, in particular the switch stuff.

The bummer about the lack of git history for this is that I can't see all the steps... where you started, what you tried, and how you eventually got there. This is an important part of being able to understand this stuff.

It is very useful that most of the complexity added is at the top of the file.

atlauren commented 8 years ago

Correct link:

# - http://stackoverflow.com/a/14203146
jgstew commented 8 years ago

One problem with this proposed change is that it makes FQDN required, which I don't intend it to be if a masthead file is provided instead.

It would also be nice if the default argument was FQDN so it didn't have to be specified in a special way using the -fqdn switch. I'm not sure how to implement this at the moment, but this is common in some cases, like with wget.

I actually intend this script to have a default argument that is either the FQDN or a masthead file. If you give the default/unswitched argument to the script, then it will check if it is a file path by checking if the file exists. If so, it will assume it is the masthead file and use it as such... Otherwise it will assume it is a FQDN and it will attempt to download the masthead from it.

I also intend the switch to be used without any arguments provided at all by including a masthead file in the same directory as the script.

Obviously not all of this functionality has been included yet.

You can already provide a clientsettings.cfg file in the same directory as the script, and it will use that automatically, which means that you can specify the relays or tagging or other info that way.

I do like the match functionality. I think it makes sense, especially since the parent relay or root might have a NEWER version of the BigFix components than the script specifies if you have an old version of the script.

atlauren commented 8 years ago

I thought this was an easy way to integrate what I desired without overly impacting the existing work. I also generally prefer strict inputs over implicit behavior, so I went this way.

jgstew commented 8 years ago

I tend to prefer implicit behavior but with a way to change it through configuration. I tend to take the approach, how can I do the most with the least input.

What you did is definitely easier than what I hope to do. The match functionality requires FQDN even if the script otherwise wouldn't require it, so that would require more complex logic. If match used then there must bea FQDN available to use, but if match is not used, then FQDN is optional.

atlauren commented 8 years ago

I just realized, I left some stray echo statements in there that I'd used for debugging. Editing...

atlauren commented 8 years ago
command_exists () {
  type "$1" &> /dev/null ;
}

function do_usage {
    echo "Usage: -fqdn ROOTSERVERORRELAY [-match]"
    echo "  -fqdn  - FQDN for BigFix root server, or relay. Required."
    echo "  -match - Installs the agent version running on the server/relay. Optional."
    echo "         (Default behavior installs the script's stored URLVERSION.)"
    exit 1
}

if [[ $# = 0 ]] ; then
    do_usage
fi

while [[ $# > 0 ]]
do
key="$1"

case $key in
    -fqdn)
    FQDN="$2"
    shift # past argument
    ;;
    -match)
    MATCH=y
    shift # past argument
    ;;
    *)
esac
shift
done

if [[ -n $FQDN ]] ; then
    CURLRESULT=`curl -s -S http://$FQDN:52311 -o /dev/null 2>&1`
        if [[ -n $CURLRESULT ]] ; then
            echo "CONNECTION ERROR: "$CURLRESULT
            exit 1
        fi
    RELAYFQDN=$FQDN
    MASTHEADURL="http://$RELAYFQDN:52311/masthead/masthead.afxm"
else
    do_usage
fi

# these variables are used to determine which version of the BigFix agent should be downloaded
# these variables are typically set to the latest version of the BigFix agent
# URLMAJORMINOR is the first two integers of URLVERSION
#  most recent version# found here under `Agent`:  http://support.bigfix.com/bes/release/
if [[ $MATCH = "y" ]] ; then
    URLVERSION=`curl -s -D - http://$RELAYFQDN:52311 -o /dev/null | awk -F/ '/Server/ {print $2}' | tr -d "\r"`
    else
    URLVERSION=9.5.2.56
fi
URLMAJORMINOR=`echo $URLVERSION | awk '/./ {gsub(/\./, " "); print $1 $2}'`

# check for x32bit or x64bit OS
jgstew commented 8 years ago

This seems interesting: http://stackoverflow.com/a/24501190/861745

jgstew commented 8 years ago

Also, it seem like -match should be a boolean style switch. If not provided, it implies FALSE, if provided it implies TRUE. Not needing to provide -match y helps because you could have so many possibilities to imply TRUE: y,1,Y,Yes,TRUE

This would make the usage like the following items:

Having a masthead of actionsite file in the current working directory would always take precedence over all other options unless -match is specified because it implies that a URL or FQDN is required.

jgstew commented 8 years ago

There is also the possibility of have a switch -v or --version to provide a specific version of BigFix that should be installed.

jgstew commented 8 years ago

I just realized this code has curl hard coded within it to get the version of the parent relay, which will not work by default on all supported platforms because some only have wget, while some only have curl, while some have both.

I really like the idea behind the --match functionality, and this is a good first step, but I'm going to have to figure out how to handle this a bit more dynamically.

It does seem like the --match functionality could happen at the same time as the masthead download, but that would require moving that up or something.

atlauren commented 8 years ago

My second edit changes -match to be boolean.

I did consider the issue of hard-coding curl, but to properly handle the cases of detecting curl|wget and factor was more overhaul than I was looking for. ;)

atlauren commented 8 years ago

Poking around a bit, it appears that nc (nmap-ncat) is a great way to check for a remote open port. But, it's not something you can assume will be there.

atlauren commented 8 years ago

This bash one-liner looks like it'll work: </dev/tcp/$FQDN/52311 || echo closed

http://stackoverflow.com/a/35338529

atlauren commented 8 years ago
    CONTEST=`</dev/tcp/$FQDN/52311 || echo closed`
        if [[ -n $CONTEST ]] ; then
            echo $CONTEST
            exit 1
        fi
jgstew commented 8 years ago

I feel like the best way to check if it is valid is to just download the masthead, since that is what will be attempted anyway. It seems unnecessary to check to see if the domain is correct, then to later check that the masthead can be downloaded. This means changing up the order a bit.