F5 Automation with PowerShell - Part 3

Getting Started

Before jumping straight into the code, we should layout the activities that we will need to explore as well as the goal of this script as a composite. The basic objective will be to take a deployed F5 Big-IP that has only a management IP address and after completion be a fully deployed Big-IP with an example Virtual IP (VIP) and Pool. The configuration will be purposes terse, as the goal is less about complex configuration and more how to perform these actions with PowerShell. These objectives can be broken down as follows:

  • Collect username and password from the command line
  • Get an Authentication Token from the Big-IP
  • Verify the Authentication Token
  • Change the Password Policy
  • Change Passwords
  • Get the System Version with the Token
  • Upload the DO RPM
  • Upload the AS3 RPM
  • Install the DO Package
  • Install the AS3 Package
  • Upload a DO Configuration and Verify
  • Upload an AS3 Configuration and Verify

Part 3 of this series will cover the uploading the DO and AS3 RPMs.

You should keep the iControlREST API reference handy to refer to as you progress through this article for more details on the end points and options that are not discussed in the article. For convenience, here are some references to look at:

iControlREST Home 
This is the home for iControlREST and has links to other useful topics like Cookbooks and introductions to iControl.

iControl API Reference 
This is the API reference page for REST end points. As we discuss specific steps, we will refer to specific topics within this list, but you may want to refer to items outside the scope of this article.

Upload the DO RPM

In this task and the next task, we will upload a file to the Big-IP device. There are several familiar elements here and then a few new things that need to be considered to achieve the desired result. This is an important task in the process as a newly installed instance of Big-IP will not have DO or AS3 installed on it, and thus you would be unable to perform any declarative configurations on it. These steps will upload the appropriate RPMs and later we will install them.

Documentation for this end point can be found here: API - /mgmt/shared/file-transfer/uploads.  Note: for some reason, its only labeled as Big-IQ documentation and corresponding Big-IP documentation cannot be found.

 

 

# ================================================================================
# Upload DO RPM
# ================================================================================
Write-Output "==================================================================="
Write-Output "Uploading DO package"
Write-Output "==================================================================="
$file = "f5-declarative-onboarding-1.27.0-6.noarch.rpm"
$url = "{0}{1}{2}" -f $big_ip, "/mgmt/shared/file-transfer/uploads/", $file
$filelength = (Get-Item $file).length
$headers = @{
    'Content-Type' = 'application/octet-stream'
    'X-F5-Auth-Token' = $token
    'Content-Range' = "0-$($filelength-1)/$filelength"
}
# Sha256: 2aee4a29ac64b38ac5af7d41607a966cac063c99a339b228225ffa38f8f9a4cf  f5-declarative-onboarding-1.27.0-6.noarch.rpm

try {
    $result = Invoke-RestMethod -SkipCertificateCheck -SkipHeaderValidation -Method Post -Uri $url -Headers $headers -InFile $file

} catch [Exception] {
    # Can't capture the response code with Invoke-RestMethod, but can catch the exception and assume failure.
    Write-Host "StatusCode:" $_.Exception.Response.StatusCode.value__
    Write-Host "StatusDescription:" $_.Exception.Response.StatusDescription 
    
    Write-Host $_.Exception
    exit
}

Write-Output $result

 

 

This task starts out like the others with announcing the step we are on to the console. Next, we define the name of the binary that is going to be uploaded. This binary needs to be in the same directory as the script. Otherwise, a proper path needs to be specified so that the Invoke-RestMethod call can find it. The URL variable is then built, and the name of the file is attached to the end of it. This states what the destination and the destination file name will be, and we keep this consistent for simplicity. The destination directory will resolve to /var/config/rest/downloads on the target system. Next, we compute the file length of the binary which is used in our next step.

The headers object has a couple of new items in it to support the file upload. We pass along the authorization token as we have before. For the content-type, notice that this is now octet-stream. This allows for a generic binary transfer of bytes via HTTP and it is the destination’s systems responsibility to sort out what application or tool needs to be able to digest it. Next is the content-range. The syntax for content range is as follows (for the specific syntax we are using):

Content-Range: <unit> <range-start>-<range-end>/<size>

Content-Range is normally seen in response headers but is perfectly allowable in a request that provides a content body. This allows for providing a portion of the entity and then on subsequent calls, telling the server where the next partial entity should be merged into the entity. The REST API documentation states that this is a required header and that any file larger than 1Mb needs to be chunked with this header. In this example, we did not, and we did not include the size and start headers either. At this point, these are suggestions, but future revisions may enforce these restrictions more strictly. Here, the unit is omitted as HTTP1.1 only defines bytes and may ignore ranges using other units. This was discovered accidentally and functioned correctly. Other examples, the RFC, and some documentation specify the units as ‘bytes’. Since this function correctly, its left to the reader if they want to be more explicit with the header.

In the comments, the sha256 hash of the specific file and version used when constructing this code and article is provided. Good practice would be to verify this hash on the system after upload, but time didn’t permit completion of this check.

Finally, Invoke-RestMethod is invoked to upload the file to the system. Notice the last argument -InFile which passes the name (and path if required) of the file we are uploading. This is wrapped in a try/catch clause that will broadly catch any error and extract the status code and description, printing them both to the console and then exiting. If the upload cannot continue, then there is no reason to move forward with the script.

The last step is a brief announcement of success. Obviously, referring to the point about the sha256 hash, a more robust verification of a successful upload could be explored here.

Upload the AS3 RPM

Apart from the file, this is the same routine as the previous one, so a description is unnecessary.

 

 

# ================================================================================
# Upload AS3 RPM
# ================================================================================
Write-Output "==================================================================="
Write-Output "Uploading AS3 RPM package"
Write-Output "==================================================================="
$file = "f5-appsvcs-3.34.0-4.noarch.rpm"
$url = "{0}{1}{2}" -f $big_ip, "/mgmt/shared/file-transfer/uploads/", $file
$filelength = (Get-Item $file).length
$headers = @{
    'Content-Type' = 'application/octet-stream'
    'X-F5-Auth-Token' = $token
    'Content-Range' = "0-$($filelength-1)/$filelength"
}
# Sha256: 05a80ec0848dc5b8876b78a8fbee2980d5a1671d635655b3af604dc830d5fed4  f5-appsvcs-3.34.0-4.noarch.rpm

try {
    $result = Invoke-RestMethod -SkipCertificateCheck -SkipHeaderValidation -Method Post -Uri $url -Headers $headers -InFile $file

} catch [Exception] {
    # Can't capture the response code with Invoke-RestMethod, but can catch the exception and assume failure.
    Write-Host "StatusCode:" $_.Exception.Response.StatusCode.value__
    Write-Host "StatusDescription:" $_.Exception.Response.StatusDescription 
    
    Write-Host $_.Exception
    exit
}

Write-Output $result

 

 

 

Updated Mar 10, 2022
Version 2.0

Was this article helpful?

No CommentsBe the first to comment