Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update infoblox client and fix infoblox cert pool #287

Merged
merged 1 commit into from
Nov 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ require (
github.com/go-openapi/strfmt v0.21.2
github.com/gophercloud/gophercloud v0.24.0
github.com/gophercloud/utils v0.0.0-20220307143606-8e7800759d16
github.com/infobloxopen/infoblox-go-client/v2 v2.0.0
github.com/infobloxopen/infoblox-go-client/v2 v2.1.0
github.com/miekg/dns v1.1.44
github.com/netlify/open-api v1.1.0
github.com/onsi/ginkgo/v2 v2.1.6
Expand Down Expand Up @@ -137,3 +137,6 @@ require (
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)

// need open PR https://github.com/infobloxopen/infoblox-go-client/pull/195
replace github.com/infobloxopen/infoblox-go-client/v2 => github.com/MartinWeindel/infoblox-go-client/v2 v2.0.0-20221122085954-b7d80ebb106b
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBp
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/MartinWeindel/infoblox-go-client/v2 v2.0.0-20221122085954-b7d80ebb106b h1:5ltgdUOqRohN2Z/Xg8D0XUq2/Dir5kHvutd8CIkMZis=
github.com/MartinWeindel/infoblox-go-client/v2 v2.0.0-20221122085954-b7d80ebb106b/go.mod h1:+lznx4ASBSUZ2i6qwlgyn0v3eKDxBHNU5aRJzghAFbw=
github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
Expand Down Expand Up @@ -501,8 +503,6 @@ github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/infobloxopen/infoblox-go-client/v2 v2.0.0 h1:SoGI4PkU2zxGU2SCtpZA7rhd2GyNPsVuE1Ydno6B0Y8=
github.com/infobloxopen/infoblox-go-client/v2 v2.0.0/go.mod h1:+lznx4ASBSUZ2i6qwlgyn0v3eKDxBHNU5aRJzghAFbw=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
Expand Down
42 changes: 18 additions & 24 deletions pkg/controller/provider/infoblox/access.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,8 @@
package infoblox

import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"strconv"
"strings"

Expand All @@ -34,17 +32,19 @@ import (

type access struct {
ibclient.IBConnector
metrics provider.Metrics
view string
requestBuilder ibclient.HttpRequestBuilder
metrics provider.Metrics
view string
}

var _ raw.Executor = (*access)(nil)

func NewAccess(client ibclient.IBConnector, view string, metrics provider.Metrics) *access {
func NewAccess(client ibclient.IBConnector, requestBuilder ibclient.HttpRequestBuilder, view string, metrics provider.Metrics) *access {
return &access{
IBConnector: client,
metrics: metrics,
view: view,
IBConnector: client,
requestBuilder: requestBuilder,
metrics: metrics,
view: view,
}
}

Expand Down Expand Up @@ -90,11 +90,11 @@ func (this *access) NewRecord(fqdn string, rtype string, value string, zone prov
if n, err := strconv.Unquote(value); err == nil && !strings.Contains(value, " ") {
value = n
}
record = (*RecordTXT)(ibclient.NewRecordTXT(ibclient.RecordTXT{
Name: fqdn,
Text: value,
View: this.view,
}))
r := ibclient.NewEmptyRecordTXT()
r.Name = fqdn
r.Text = value
r.View = this.view
record = (*RecordTXT)(r)
}
if record != nil {
record.SetTTL(int(ttl))
Expand All @@ -104,27 +104,21 @@ func (this *access) NewRecord(fqdn string, rtype string, value string, zone prov

func (this *access) GetRecordSet(dnsName, rtype string, zone provider.DNSHostedZone) (raw.RecordSet, error) {
this.metrics.AddZoneRequests(zone.Id().ID, provider.M_LISTRECORDS, 1)
c := this.IBConnector.(*ibclient.Connector)

if rtype != dns.RS_TXT {
return nil, fmt.Errorf("record type %s not supported for GetRecord", rtype)
}

execRequest := func(forceProxy bool) ([]byte, error) {
rt := ibclient.NewRecordTXT(ibclient.RecordTXT{})
urlStr := c.RequestBuilder.BuildUrl(ibclient.GET, rt.ObjectType(), "", rt.ReturnFields(), &ibclient.QueryParams{})
urlStr += "&name=" + dnsName
if forceProxy {
urlStr += "&_proxy_search=GM"
}
req, err := http.NewRequest("GET", urlStr, new(bytes.Buffer))
rt := ibclient.NewEmptyRecordTXT()
queryParams := ibclient.NewQueryParams(forceProxy, map[string]string{"name": dnsName, "view": this.view, "zone": zone.Key()})
req, err := this.requestBuilder.BuildRequest(ibclient.GET, rt, "", queryParams)
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/json")
req.SetBasicAuth(c.HostConfig.Username, c.HostConfig.Password)

return c.Requestor.SendRequest(req)
requestor := &ibclient.WapiHttpRequestor{}
return requestor.SendRequest(req)
}

resp, err := execRequest(false)
Expand Down
107 changes: 53 additions & 54 deletions pkg/controller/provider/infoblox/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,10 @@ package infoblox

import (
"context"
"crypto/x509"
"encoding/json"
"fmt"
"io/ioutil"
"net/url"
"os"
"strconv"

"github.com/gardener/controller-manager-library/pkg/logger"
Expand Down Expand Up @@ -115,9 +114,12 @@ func NewHandler(config *provider.DNSHandlerConfig) (provider.DNSHandler, error)
config.Logger.Infof("creating infoblox handler for %s", *infobloxConfig.Host)

hostConfig := ibclient.HostConfig{
Host: *infobloxConfig.Host,
Port: strconv.Itoa(*infobloxConfig.Port),
Version: *infobloxConfig.Version,
Host: *infobloxConfig.Host,
Port: strconv.Itoa(*infobloxConfig.Port),
Version: *infobloxConfig.Version,
}

authCfg := ibclient.AuthConfig{
Username: username,
Password: password,
}
Expand All @@ -127,25 +129,17 @@ func NewHandler(config *provider.DNSHandlerConfig) (provider.DNSHandler, error)
verify = strconv.FormatBool(*infobloxConfig.SSLVerify)
}

if infobloxConfig.CaCert != nil && verify == "true" {
tmpfile, err := ioutil.TempFile("", "cacert")
if err != nil {
return nil, fmt.Errorf("cannot create temporary file for cacert: %w", err)
}
defer os.Remove(tmpfile.Name())
if _, err := tmpfile.Write([]byte(*infobloxConfig.CaCert)); err != nil {
return nil, fmt.Errorf("cannot write temporary file for cacert: %w", err)
}
if err := tmpfile.Close(); err != nil {
return nil, fmt.Errorf("cannot close temporary file for cacert: %w", err)
}
verify = tmpfile.Name()
}
transportConfig := ibclient.NewTransportConfig(
verify,
*infobloxConfig.RequestTimeout,
*infobloxConfig.PoolConnections,
)
if infobloxConfig.CaCert != nil && verify == "true" {
transportConfig.CertPool, err = h.createCertPool([]byte(*infobloxConfig.CaCert))
if err != nil {
return nil, fmt.Errorf("cannot create cert pool for cacert: %w", err)
}
}
if infobloxConfig.ProxyURL != nil && *infobloxConfig.ProxyURL != "" {
u, err := url.Parse(*infobloxConfig.ProxyURL)
if err != nil {
Expand All @@ -154,17 +148,21 @@ func NewHandler(config *provider.DNSHandlerConfig) (provider.DNSHandler, error)
transportConfig.ProxyUrl = u
}

var requestBuilder ibclient.HttpRequestBuilder = &ibclient.WapiRequestBuilder{}
rb, err := ibclient.NewWapiRequestBuilder(hostConfig, authCfg)
if err != nil {
return nil, err
}
var requestBuilder ibclient.HttpRequestBuilder = rb
if infobloxConfig.MaxResults != 0 {
// wrap request builder which sets _max_results parameter on GET requests
requestBuilder = NewMaxResultsRequestBuilder(infobloxConfig.MaxResults, requestBuilder)
}
client, err := ibclient.NewConnector(hostConfig, transportConfig, requestBuilder, &ibclient.WapiHttpRequestor{})
client, err := ibclient.NewConnector(hostConfig, authCfg, transportConfig, requestBuilder, &ibclient.WapiHttpRequestor{})
if err != nil {
return nil, err
}

h.access = NewAccess(client, *h.infobloxConfig.View, config.Metrics)
h.access = NewAccess(client, requestBuilder, *h.infobloxConfig.View, config.Metrics)

h.ZoneCache, err = config.ZoneCacheFactory.CreateZoneCache(provider.CacheZonesOnly, config.Metrics, h.getZones, h.getZoneState)
if err != nil {
Expand All @@ -182,7 +180,7 @@ func (h *Handler) getZones(cache provider.ZoneCache) (provider.DNSHostedZones, e
h.config.Metrics.AddGenericRequests(provider.M_LISTZONES, 1)
obj := ibclient.NewZoneAuth(ibclient.ZoneAuth{})
err := h.access.GetObject(obj, "", &ibclient.QueryParams{}, &raw)
if err != nil {
if filterNotFound(err) != nil {
return nil, err
}

Expand All @@ -196,14 +194,10 @@ func (h *Handler) getZones(cache provider.ZoneCache) (provider.DNSHostedZones, e

h.config.Metrics.AddZoneRequests(z.Ref, provider.M_LISTRECORDS, 1)
var resN []RecordNS
objN := ibclient.NewRecordNS(
ibclient.RecordNS{
Zone: z.Fqdn,
View: *h.infobloxConfig.View,
},
)
err = h.access.GetObject(objN, "", &ibclient.QueryParams{}, &resN)
if err != nil {
objN := ibclient.NewRecordNS(ibclient.RecordNS{})
params := ibclient.NewQueryParams(false, map[string]string{"view": *h.infobloxConfig.View, "zone": z.Fqdn})
err = h.access.GetObject(objN, "", params, &resN)
if filterNotFound(err) != nil {
return nil, fmt.Errorf("could not fetch NS records from zone '%s': %s", z.Fqdn, err)
}
forwarded := []string{}
Expand All @@ -222,13 +216,12 @@ func (h *Handler) getZoneState(zone provider.DNSHostedZone, cache provider.ZoneC
state := raw.NewState()
rt := provider.M_LISTRECORDS

params := ibclient.NewQueryParams(false, map[string]string{"view": *h.infobloxConfig.View, "zone": zone.Key()})

h.config.Metrics.AddZoneRequests(zone.Id().ID, rt, 1)
var resA []RecordA
objA := ibclient.NewEmptyRecordA()
objA.Zone = zone.Key()
objA.View = *h.infobloxConfig.View
err := h.access.GetObject(objA, "", &ibclient.QueryParams{}, &resA)
if err != nil {
err := h.access.GetObject(ibclient.NewEmptyRecordA(), "", params, &resA)
if filterNotFound(err) != nil {
return nil, fmt.Errorf("could not fetch A records from zone '%s': %s", zone.Key(), err)
}
for _, res := range resA {
Expand All @@ -237,11 +230,8 @@ func (h *Handler) getZoneState(zone provider.DNSHostedZone, cache provider.ZoneC

h.config.Metrics.AddZoneRequests(zone.Id().ID, rt, 1)
var resAAAA []RecordAAAA
objAAAA := ibclient.NewEmptyRecordAAAA()
objAAAA.Zone = zone.Key()
objAAAA.View = *h.infobloxConfig.View
err = h.access.GetObject(objAAAA, "", &ibclient.QueryParams{}, &resAAAA)
if err != nil {
err = h.access.GetObject(ibclient.NewEmptyRecordAAAA(), "", params, &resAAAA)
if filterNotFound(err) != nil {
return nil, fmt.Errorf("could not fetch AAAA records from zone '%s': %s", zone.Key(), err)
}
for _, res := range resAAAA {
Expand All @@ -250,11 +240,8 @@ func (h *Handler) getZoneState(zone provider.DNSHostedZone, cache provider.ZoneC

h.config.Metrics.AddZoneRequests(zone.Id().ID, rt, 1)
var resC []RecordCNAME
objC := ibclient.NewEmptyRecordCNAME()
objC.Zone = zone.Key()
objC.View = *h.infobloxConfig.View
err = h.access.GetObject(objC, "", &ibclient.QueryParams{}, &resC)
if err != nil {
err = h.access.GetObject(ibclient.NewEmptyRecordCNAME(), "", params, &resC)
if filterNotFound(err) != nil {
return nil, fmt.Errorf("could not fetch CNAME records from zone '%s': %s", zone.Key(), err)
}
for _, res := range resC {
Expand All @@ -263,14 +250,8 @@ func (h *Handler) getZoneState(zone provider.DNSHostedZone, cache provider.ZoneC

h.config.Metrics.AddZoneRequests(zone.Id().ID, rt, 1)
var resT []RecordTXT
objT := ibclient.NewRecordTXT(
ibclient.RecordTXT{
Zone: zone.Key(),
View: *h.infobloxConfig.View,
},
)
err = h.access.GetObject(objT, "", &ibclient.QueryParams{}, &resT)
if err != nil {
err = h.access.GetObject(ibclient.NewEmptyRecordTXT(), "", params, &resT)
if filterNotFound(err) != nil {
return nil, fmt.Errorf("could not fetch TXT records from zone '%s': %s", zone.Key(), err)
}
for _, res := range resT {
Expand Down Expand Up @@ -325,3 +306,21 @@ func (h *Handler) DeleteRecordSet(logger logger.LogContext, zone provider.DNSHos
}
return nil
}

func (h *Handler) createCertPool(cert []byte) (*x509.CertPool, error) {
caPool := x509.NewCertPool()
if !caPool.AppendCertsFromPEM(cert) {
return nil, fmt.Errorf("cannot append certificate")
}
return caPool, nil
}

func filterNotFound(err error) error {
if err == nil {
return nil
}
if _, ok := err.(*ibclient.NotFoundError); ok {
return nil
}
return err
}
2 changes: 1 addition & 1 deletion pkg/controller/provider/infoblox/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func (r *RecordTXT) GetDNSName() string { return r.Name }
func (r *RecordTXT) GetSetIdentifier() string { return "" }
func (r *RecordTXT) GetValue() string { return raw.EnsureQuotedText(r.Text) }
func (r *RecordTXT) GetTTL() int { return int(r.Ttl) }
func (r *RecordTXT) SetTTL(ttl int) { r.Ttl = uint(ttl); r.UseTtl = ttl != 0 }
func (r *RecordTXT) SetTTL(ttl int) { r.Ttl = uint32(ttl); r.UseTtl = ttl != 0 }
func (r *RecordTXT) Copy() raw.Record { n := *r; return &n }
func (r *RecordTXT) PrepareUpdate() raw.Record { n := *r; n.Zone = ""; n.View = ""; return &n }

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading