Code Monkey home page Code Monkey logo

go-bigip's Introduction

go-bigip

GoDoc Travis-CI Go Report Card license

A Go package that interacts with F5 BIG-IP systems using the REST API.

Some of the tasks you can do are as follows:

  • Get a detailed list of all nodes, pools, vlans, routes, trunks, route domains, self IP's, virtual servers, monitors on the BIG-IP system.
  • Create/delete nodes, pools, vlans, routes, trunks, route domains, self IP's, virtual servers, monitors, etc.
  • Modify individual settings for all of the above.
  • Change the status of nodes and individual pool members (enable/disable).

Note: You must be on version 11.4+! For the features that deal with internal data groups, you must be running version 11.6+!

Examples & Documentation

Visit the GoDoc page for package documentation and examples.

Here's a blog post that goes a little more in-depth.

Contributors

A very special thanks to the following who have helped contribute to this software, especially:

go-bigip's People

Contributors

aburnett avatar aughr avatar danielb42 avatar dnaeon avatar fatmcgav avatar gliptak avatar ivey avatar jakauppila avatar kkloos1 avatar magliok-wwt avatar mch1307 avatar osankar avatar presbrey avatar rawmind0 avatar scottdware avatar stoyanr avatar ttekin avatar zbindenren avatar zetaab avatar zlesnr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

go-bigip's Issues

Authorization failed

Hi,

I'm getting the following error when I try running this. Am I missing something? Why is this output pointing to a localhost?

Error message:
Authorization failed: no user named admin found. Uri:http://localhost:8100/mgmt/tm/ltm/node Referer:null
Authorization failed: no user named admin found. Uri:http://localhost:8100/mgmt/tm/ltm/node Referer:null

package main

import (
"fmt"
"github.com/scottdware/go-bigip"
)

func main() {
// Connect to the BIG-IP system.
f5 := bigip.NewSession("10.19.127.123", "admin", "password", nil)
//nodes := ""
nodes, err := f5.Nodes()
if err != nil {
fmt.Println(err)
}
fmt.Println(f5.Nodes())
fmt.Println(nodes)

}

Support for fqdn nodes

Hello,

I have been using the terraform provider on f5devcentral (https://github.com/f5devcentral/terraform-provider-bigip) and have run into an issue with wanting to create fqdn based nodes. It seems that support is lacking in this library.

It also seems there is a divergent fork that f5devcentral is using, which of course does not track issues, so I am posting this here.

UpdatePoolMembers (replace-all-with) adds nodes with monitor up / sessions enabled

I'm honestly not sure if this is an issue with go-bigip or the iControl REST interface, but when I do a replace-all-with pool modification via tmsh, the new pool members have the following availability / states:

| Availability : unknown
| State : enabled
| Reason : Pool member service checking is enabled, but result is not available yet
| Monitor Status : checking
| Session Status : enabled

This is what I would expect; the BigIP hasn't performed a health check, yet. But for some reason when I do an UpdatePoolMembers via go-bigip, the new pool members have the following availability / states:

| Availability : available
| State : enabled
| Reason : Pool member is available
| Monitor Status : up
| Session Status : enabled

Is this expected? Why the difference?

View Pool Member State

Is there a way to view the status of a pool member without changing it?

I'm trying to write a script that does a failover. My general procedure is:

  1. Ensure there are exactly two members in the pool
  2. Ensure only one of them is enabled
  3. Disable the active member
  4. Sync the F5s
  5. Enable the previously disabled member
  6. Sync the F5s
  7. Ensure the end state looks like it should

The problem is, I can't see a way to just view the state of a node using the go-bigip package.

`ModifyVirtualServer` function `patch` instead `put`

Hey,

we are having some issues updating f5 bigip virtual servers on v12+, getting errors like
12/21/2018 9:33:53 AMtime="2018-12-21T15:33:53Z" level=error msg="f5 RemoveLBConfig: Error modifying virtual server: 0107028c:3: The source (::) and destination (10.3.5.143) addresses for virtual server (/Common/cos_vs_electrode_storefront_beta) must be be the same type (IPv4 or IPv6).\n".

The errors came from calling ModifyVirtualServer function https://github.com/rancher/external-lb/blob/master/providers/f5/f5_bigip.go#L196

Reading this post https://devcentral.f5.com/questions/script-to-modify-virtual-servers-default-pool, it seems that bigip API v12+ versions uses patch instead put for modifying virtual servers.

Taking a look to the code, ModifyVirtualServer function is still using put method https://github.com/scottdware/go-bigip/blob/master/ltm.go#L1818 . Are you planning to update it?? Could we contribute with a PR to address it??

Related rancher issue, rancher/rancher#13269

Thanks....

Adding a monitor to pool deletes all pool settings

When adding a monitor to pool with AddMonitorToPool(), all settings in the pool are removed.

f5 := bigip.NewSession("localhost", "admin", "password")
f5.CreatePool("test-pool")
pool, _ := f5.GetPool("test-pool")
pool.AllowSNAT = true
f5.ModifyPool("test-pool", pool)
f5.CreateMonitor("web_http_monitor", "http", 5, 16, "GET /\r\n", "200 OK")
err := f5.AddMonitorToPool("web_http_monitor", "test-pool")

After executing this, the value of the allowSNAT flag gets removed.

Feature request: support for asm/WAF module

If we have plan to support ASM/WAF module?
recently I planed to use this module to implement a monitor tool to gather the information about the attracts and blocks about ASM,but seems no ASM/WAF supported .

GetInternalDataGroupRecords - json: cannot unmarshal object into Go value of type []bigip.DataGroupRecord

Hi,
I tried to perform DataGroup manipulations with bigip 12.1.1 and have the subj issue.
Checking that with curl i found that the entity data that came in response is DataGroup and not []DataGroupRecord.
So changing the func from:

func (b *BigIP) GetInternalDataGroupRecords(name string) (*[]DataGroupRecord, error) {
	var dataGroupRecords []DataGroupRecord
	err, _ := b.getForEntity(&dataGroupRecords, uriLtm, uriDatagroup, uriInternal, name)
	if err != nil {
		return nil, err
	}

	return &dataGroupRecords, nil
}

to

func (b *BigIP) GetInternalDataGroupRecords(name string) (*[]DataGroupRecord, error) {
	var dataGroup DataGroup
	err, _ := b.getForEntity(&dataGroup, uriLtm, uriDatagroup, uriInternal, name)
	if err != nil {
		return nil, err
	}

	return &dataGroup.Records, nil
}

did the job.

Does the difference come from the new BigIP version?

How to import certificate and key?

System -> certificate management -> traffic certificate management -> ssl certificate list -> import

but i don't know how to import certificate by rest api, need help, thanks.

Token Refresh

Hi

We created a tool, that polls several Big IP devices with your library. Since this is a long running process, we would need the possibility to refresh the authentication. We use bigip.NewTokenSession method to authenticate to the device and the default timeout for the generated token is 1200s.

Would a Pull request be accepted, that implements that functionality.

My plan would be the following:

Modify:

	type authResp struct {
		Token struct {
			Token      string
		}
	}

to:

	type authResp struct {
		Token struct {
			Token      string
			Expiration int `json:"expirationMicros"`
			Timeout    int `json:"timeout"`
		}
	}

Then create a method:

func (b *BigIP) RefreshTokenSession() error {}

Which:

  • updates the token timeout with a patch to fmt.Sprintf("mgmt/shared/authz/tokens/%s", aresp.Token.Token) if current token is not expired yet
  • perform a new login, if token is expired or above patch returns with an error

Panic runtime / error

Hello!

I am using the following sample code

package main

import (
	"fmt"
    "bufio"
    "os"
    "github.com/scottdware/go-bigip"
)

func main() {

    // all_lbs.txt includes a list of F5 devices
    inFile, _ := os.Open("all_lbs.txt")

    scanner := bufio.NewScanner(inFile)
    for scanner.Scan() {
        line := scanner.Text()
        f5 := bigip.NewSession(line, "<credentials>", "<password>", nil)
        _ , err := f5.VirtualServers()
        if err != nil {
          fmt.Println(err)
          fmt.Println(line)
        }
    }

I notice a kernel panic error while iterating through a bunch of hosts.

Authorization failed: user=https://localhost/mgmt/shared/authz/users/<user>resource=/mgmt/tm/ltm/virtual verb=GET uri:http://localhost:8100/mgmt/tm/ltm/virtual referrer:10.220.112.195 sender:10.220.112.195
m0.llb001b.pod1.las1.as22023.net.
Authorization failed: user=https://localhost/mgmt/shared/authz/users/<user> resource=/mgmt/tm/ltm/virtual verb=GET uri:http://localhost:8100/mgmt/tm/ltm/virtual referrer:10.220.112.195 sender:10.220.112.195
m0.xlb001a.pod6.las1.as22023.net.
Authorization failed: user=https://localhost/mgmt/shared/authz/users/<user>
resource=/mgmt/tm/ltm/virtual verb=GET uri:http://localhost:8100/mgmt/tm/ltm/virtual referrer:10.220.112.195 sender:10.220.112.195
m0.xlb001b.pod6.las1.as22023.net.
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x38 pc=0x11e3892]

goroutine 1 [running]:
net/http.(*Request).SetBasicAuth(0x0, 0x129190a, 0x12, 0x12911f9, 0x10)
	/usr/local/go/src/net/http/request.go:882 +0x52
github.com/scottdware/go-bigip.(*BigIP).APICall(0xc420356000, 0xc420269da8, 0x0, 0x0, 0x0, 0x0, 0x0)
	/Users/<username>/go/src/github.com/scottdware/go-bigip/bigip.go:164 +0x7d0
github.com/scottdware/go-bigip.(*BigIP).getForEntity(0xc420356000, 0x1222660, 0xc420454340, 0xc420269e48, 0x2, 0x2, 0x2a, 0xc42039c2a0, 0xc420062000)
	/Users/<username>/go/src/github.com/scottdware/go-bigip/bigip.go:261 +0xe6
github.com/scottdware/go-bigip.(*BigIP).VirtualServers(0xc420356000, 0x22, 0x129190a, 0x12)
	/Users/<username>/go/src/github.com/scottdware/go-bigip/ltm.go:1754 +0x98
main.main()
	/Users/<username>/projects/lb_api/lb.go:18 +0x155
exit status 2

Can someone recommend if I need to revise my code to highlight whats causing the nil pointer dereference? or if there is a bug lurking someplace?

ClientTimeout exceeded while awaiting headers

I'm receiving the following error when trying to pull any Resource.
Get "https://<ipaddress>/mgmt/tm/ltm/virtual": context deadline exceeded (Client.Timeout exceeded while awaiting headers)

I'm fairly new to golang so this could very well be something on my side.

  • BigIP Version - 13.1.0.8
  • go-bigip version - latest commit

Code

package main

import (
        "fmt"
        "github.com/scottdware/go-bigip"
)

func main() {
        config := bigip.ConfigOptions{
                APICallTimeout: 10000,
        }
        f5 := bigip.NewSession("https://<ipaddress>", "user", "password", &config)

        vservers, err := f5.VirtualServers()
        if err != nil {
                fmt.Println("THERE WAS AN ERROR")
                fmt.Println(err)
        }

        fmt.Println(vservers)

        test, err := f5.GetVirtualServer("VS_NAME")
        if err != nil {
                fmt.Println("THERE WAS AN ERROR")
                fmt.Println(err)
        }
        fmt.Println(test)

        for _, vs := range vservers.VirtualServers {
               fmt.Printf("Name: %s\n", vs.Name)
         }
}

F5 partitions

Will this work if the F5 has partitions, i did not see any examples specifying a partition. If it does could you provide a brief example?

Decrease pressure on garbage collector

Hi

I observed that on each api call a http.Client is created: https://github.com/scottdware/go-bigip/blob/master/bigip.go#L119

I would like to refactor that code to initiate a http.Client in NewSession and use this client for each call.

To do that, the Transport has also to be created in NewSession. My plan:

  • move the Transport configuration to ConfigOptions like
type ConfigOptions struct {
	APICallTimeout time.Duration
        Transport *http.Transport
}
  • do not use InsecureSkipVerify: true, like here

What do you think about that?

ModifyServerSSLProfile and ModifyClientSSLProfile perform PUT instead of PATCH

When creating an SSL profile with the following body (below) the f5 inherits all properties from the parent profile when calling func (b *BigIP) ModifyClientSSLProfile and overrides their individual settings with checkboxes / explicit values. This is expected behavior for the f5 REST api, but I believe this is undesirable in general. I believe a PATCH should be executed instead of a PUT, which respects hierarchical inheritance of profile objects but only overrides properties with checkboxes that are explicitly listed in the JSON body. I'm not entirely sure how the JSON response from the f5 correlates to what is 'checked' in the UI as overridden; I'll have to research that more if what I'm stating here is not clear. But I am reasonably confident the behavior is not desired, at least in my common use cases. This is particularly true with terraform but also in general.

This changeset has the proposed changes (note that my branch has some extra logging that should be removed, so only merge this file if you accept the change):
hoffmanntravis@8240345

mgmt/tm/ltm/profile/server-ssl {"name":"terraform_test","defaultsFrom":"/Common/serverssl"}

Contributing?

Any docs on how to run test suite or maybe contribute?

I ask because I get the below when executing go test

$go test
HTTP 500 :: internal server error
{
  "token": "KZ44TOKEN7SNOTZNR7D7UP24SC",
  "name": "KZ44TOKEN7SNOTZNR7D7UP24SC",
  "userName": "a-user",
  "authProviderName": "tmos",
  "user": {
    "link": "https://localhost/mgmt/cm/system/authn/providers/tmos/1f44a60e-11a7-3c51-a49f-82983026b41b/users/40994460-44e3-3a09-8837-2189119665e5"
  },
  "timeout": 0,

Update ltm policy rules

I am looking for a way to update ltm policies with the lib but could not find relevant functions.
The process I am trying to implement would be:

  • Create draft from published policy
  • Add/Edit policy rules in the draft policy
  • Publish the draft policy (replacing the published one)

ModifyInternalDataGroupRecords won't update Big-IP records when records list is empty

While using bigip.ModifyInternalDataGroupRecords() we encountered a possible issue.
The steps to reproduce it are as follows:

  • There is only 1 record in a data group left;
  • Executing ModifyInternalDataGroupRecords() with an empty slice results with success;
  • Going to BIG-IP instance to check, the record is still there. For the BIG-IP system nothing is changed.

Reading the code and looking more specifically over the DataGroupRecord to dataGroupDTO structs, the Records field tag in dataGroupDTO is json:"records,omitempty". This leads to the behaviour described above. When passing empty/nil slice, the omitempty tag will remove the object from the json send to the BIG-IP system.

We are thinking of 2 possible solutions.

  • Removing the omitempty tag
    This will quickly solve the issue. As seen in the code, the ModifyInternalDataGroupRecords() function is the only one modifying the DataGroupRecord resource. However, if another modifying function is introduced in the future, this removed tag, can lead to overwritten data group records in BIG-IP.
  • Distinguishing between nil slice records and empty slice records
    This leads to modifying the marshal() function and adding case for nil/empty slices. The downside of this approach is that distinguishing between empty and nil slice is a bad practise by a lot of clean code guides.

Please feel free to share your opinion and guidance how we can handle this behaviour. Whatever is decided, we can contribute it.

UpdatePoolMembers should be PATCH rather than PUT

ltm.UpdatePoolMembers replaces existing pool member info correctly but also resets all other pool properties to default values. For example, if you had a health monitor applied to the pool before, after calling UpdatePoolMembers, membership is correct but monitor is now none. This would apparently be due to the call being a PUT rather than a PATCH.

Disable escaping of <, >, and & when using json.Marshal

When configuring a monitor with some special characters, json.Marshal will escape them so it doesn't get submitted to the appliance correctly.

f5.CreateMonitor("web_http_monitor", "http", 5, 16, "GET /test?x=1&y=2 \r\n", "200 OK")

Body before marshal
&{web_http_monitor 0 http 5 0 false 200 OK false GET /test?x=1&y=2 0 16 false 0 }

Body after marshal
{"name":"web_http_monitor","defaultsFrom":"http","interval":5,"manualResume":"disabled","recv":"200 OK","reverse":"disabled","send":"GET /test?x=1\u0026y=2 \\r\\n","timeout":16,"transparent":"disabled"}

String values encode as JSON strings coerced to valid UTF-8, replacing invalid bytes with the Unicode replacement rune. The angle brackets "<" and ">" are escaped to "\u003c" and "\u003e" to keep some browsers from misinterpreting JSON output as HTML. Ampersand "&" is also escaped to "\u0026" for the same reason. This escaping can be disabled using an Encoder that had SetEscapeHTML(false) called on it.
Source: https://golang.org/pkg/encoding/json/#Marshal

What would be the preferred approach for correcting this?

Support of System

Hello Scott,

thanks for your work. Great library.

Do you have already a version wich support the /System.
I need the System::Failover::get_failover_state and and System::ConfigSync::synchronize_to_group_v2 calls.

If not i will try to implement everything i needed for that.

Move repo to f5devcentral?

There looks to be diverging code between this repo and the f5devcentral. Is there interest in moving this code to F5 where there might be more community involvement?

F5devcentral has already forked. The code in both repos needs improvement to be fully functional. My team is considering contributing architectural changes to the community, but its unclear where we will get the most support, best review, etc. Some backwards incompatible changes we're thinking of may alter the architecture slightly in relation to the client and resources. If there is not interest in our work here, f5devcentral may be a good fit for it. If neither is a good home for our work, then perhaps yet another fork is in order.

I'd personally like to see one solid code base for this, rather than several semi-complete versions. What do you think?

Failure to read monitors with tcp parent

Given the .tf:

provider "bigip" {
  address = "${lookup(var.f5_host,var.domain))}"
  username = "${var.f5_user}"
  password = "${var.f5_pass}"
}

resource "bigip_ltm_monitor" "monitor" {
  name = "/Common/vtdevad-terraformtest-pool-monitor"
  parent = "/Common/tcp"
  timeout = "${var.monitor_timeout}"
  interval = "${var.monitor_interval}"
}

It appears that terraform will create the monitor but fail to read it:

...
bigip_ltm_monitor.monitor: Creating...
  interval:      "" => "5"
  ip_dscp:       "" => "0"
  manual_resume: "" => "false"
  name:          "" => "/Common/vtdevad-terraformtest-pool-monitor"
  parent:        "" => "/Common/tcp"
  reverse:       "" => "false"
  send:          "" => "GET /\\r\\n"
  time_until_up: "" => "0"
  timeout:       "" => "16"
  transparent:   "" => "false"
Error applying plan:

1 error(s) occurred:

* bigip_ltm_monitor.monitor: Couldn't find monitor %!(EXTRA string=/Common/vtdevad-terraformtest-pool-monitor)

Terraform does not automatically rollback in the face of errors.
Instead, your Terraform state file has been partially updated with
any resources that successfully completed. Please address the error
above and apply again to incrementally change your infrastructure.

I believe the cause of the error is actually occuring in go-bigip at https://github.com/scottdware/go-bigip/blob/master/ltm.go#L981. This only resolves monitors with specific parents - one of which is not tcp.

Any idea if there are complications (as in some monitors need specific fields defined that are not included in bigip_ltm_monitor) in adding every parent type to the available list in both this provider and go-bigip?

Support connection to F5 through HTTP Proxy

In some cases, the client will need to access the F5 APIs through an HTTP Proxy.
The go-bigip library should support this.

PR #113 adds this by adding the http.ProxyFromEnvironment in NewSession func. As a result, the caller can simply setup its HTTP Proxy config (http_proxy) as env var

Monitor parent appears to be incorrectly used in URL during CreateMonitor

In AddMonitor, the post adds the ParentMonitor to the end of the URL, which I don't think is correct. What looks to be missing here is a notion of what type of monitor is being created, but this information is not to be added to the JSON post, but only appended to the URL. This matches what the documentation in this project here:

CreateMonitor adds a new monitor to the BIG-IP system. <parent> must be one of "http", "https", "icmp", "gateway icmp", or "tcp".

So this should mean that if a MonitorType were an attribute of Monitor, it should be limited to the above http, https, icmp, etc, where the call url should be /monitor/http or /monitor/https. This is independent from the ParentMonitor which should be included as defaultsFrom in the JSON.

Any help here would be much appreciated. I took a stab at solving this locally, but I'm still getting familiar with the layout of this project. If someone can point me in the right direction, or if its quick patch the issue, I'd appreciate it.

Here is what I have locally.

diff --git a/ltm.go b/ltm.go
index fdd1acd..a4e024f 100644
--- a/ltm.go
+++ b/ltm.go
@@ -728,6 +728,7 @@ type Monitor struct {
        Interval       int
        IPDSCP         int
        ManualResume   bool
+       MonitorType    string
        Password       string
        ReceiveString  string
        ReceiveDisable string
@@ -1421,7 +1422,7 @@ func (b *BigIP) Monitors() ([]Monitor, error) {

 // CreateMonitor adds a new monitor to the BIG-IP system. <parent> must be one of "http", "https",
 // "icmp", "gateway icmp", or "tcp".
-func (b *BigIP) CreateMonitor(name, parent string, interval, timeout int, send, receive string) error {
+func (b *BigIP) CreateMonitor(name, parent string, interval, timeout int, send, receive, monitortype string) error {
        config := &Monitor{
                Name:          name,
                ParentMonitor: parent,
@@ -1429,6 +1430,7 @@ func (b *BigIP) CreateMonitor(name, parent string, interval, timeout int, send,
                Timeout:       timeout,
                SendString:    send,
                ReceiveString: receive,
+               MonitorType:   monitortype,
        }

        return b.AddMonitor(config)
@@ -1440,7 +1442,7 @@ func (b *BigIP) AddMonitor(config *Monitor) error {
                config.ParentMonitor = "gateway_icmp"
        }

-       return b.post(config, uriLtm, uriMonitor, config.ParentMonitor)
+       return b.post(config, uriLtm, uriMonitor, config.MonitorType)
 }

 // GetVirtualServer retrieves a monitor by name. Returns nil if the monitor does not exist

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.