scottdware / go-bigip Goto Github PK
View Code? Open in Web Editor NEWA Go package that interacts with F5 BIG-IP systems using the REST API.
License: MIT License
A Go package that interacts with F5 BIG-IP systems using the REST API.
License: MIT License
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 .
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.
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"}
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?
Hi! Sync-status is a useful maintenance index. But it seems that go-bigip's cm module doesn't support it. Is it in schedule?
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,
I would like to be able to call f5.RemoveMonitorFromPool(pool,monitor)
so that I can remove a specified monitor from a pool.
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)
}
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 a a persistence profile to a virtual server. 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.
ignore it.
Cannot find the parameter to set the priority algorithm?
I am trying to update pool using ModifyPool. My goal is to update slowramptime to 0seconds. However, it is not possible using current master.
https://gist.github.com/zetaab/2a0b7381f75e79c56173c6af56292ca7
I can setup any other value there than zero
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
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.
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:
fmt.Sprintf("mgmt/shared/authz/tokens/%s", aresp.Token.Token)
if current token is not expired yetWhen 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?
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.
VirtualServer.Enabled just can enable vs , but you can't disable vs.You should define a Disabled in VirtualServer
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?
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
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?
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:
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.
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?
We need support for the BGP instance and neighbor iControl REST API endpoints that have been introduced in BIG-IP 13.1, see Routing commands for BGP and BFD in ZebOS, tmsh, and iControl REST.
We can contribute this. Do you accept pull requests for such new features? Do you have any special requirements? I could not find a CONTRIBUTING
guide.
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:
The problem is, I can't see a way to just view the state of a node using the go-bigip package.
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....
Is it possible to attach an iRule to virtual server with your API ?
While using bigip.ModifyInternalDataGroupRecords()
we encountered a possible issue.
The steps to reproduce it are as follows:
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.
omitempty
tagModifyInternalDataGroupRecords()
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.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.
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.
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)
}
}
Hello!
when i run f5.ServerSSLProfiles()
I got a panic error.
json: cannot unmarshal string into Go struct field ServerSSLProfile.items.tmOptions of type []string
panic: runtime error: invalid memory address or nil pointer dereference
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:
ConfigOptions
liketype ConfigOptions struct {
APICallTimeout time.Duration
Transport *http.Transport
}
InsecureSkipVerify: true,
like hereWhat do you think about that?
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?
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?
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.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.