package pkg import ( "errors" "strings" ) type ( HTTPEnforcement struct { ExcessClientHeaders string `json:"excess_client_headers"` ExcessServerHeaders string `json:"excess_server_headers"` KnownMethods []string `json:"known_methods"` MaxHeaderCount string `json:"max_header_count"` MaxHeaderSize string `json:"max_header_size"` MaxRequests string `json:"max_requests"` OversizeClientHeaders string `json:"oversize_client_headers"` OversizeServerHeaders string `json:"oversieze_server_headers"` Pipeline string `json:"pipeline"` TruncatedRedirects string `json:"truncated_redirects"` UnknownMethod string `json:"unknown_method"` } ExplicitProxy struct { BadRequestMessage string `json:"bad_request_message"` BadResponseMessage string `json:"bad_response_message"` ConnectErrorMessage string `json:"connect_error_message"` DefaultConnectHandling string `json:"default_connect_handling"` DNSErrorMessage string `json:"dns_error_message"` DNSResolver string `json:"dns_resolver"` HostNames string `json:"host_names"` RouteDomain string `json:"route_domain"` TunnelName string `json:"tunnel_name"` } HSTS struct { IncludeSubDomains string `json:"include_subdaomins"` MaximumAge string `json:"maximum_age"` Mode string `json:"mode"` } HTTPProfile struct { ProfileCommon AcceptXFF string `json:"accept_xff"` BasicAuthRealm string `json:"basic_auth_realm"` EncryptCookieSecret string `json:"encrypt_cookie_secret"` EncryptCookies string `json:"encrypt_cookies"` Enforcement HTTPEnforcement `json:"enforcement"` ExplicitProxy ExplicitProxy `json:"explicit_proxy"` FallbackHost string `json:"fallback_host"` FallbackStatusCodes string `json:"fallback_status_codes"` HeaderErase string `json:"header_erase"` HeaderInsert string `json:"header_insert"` HSTS HSTS `json:"hsts"` InsertXForwardedFor string `json:"insert_xforwarded_for"` LWSSeparator string `json:"lws_separator"` LWSWidth string `json:"lws_width"` OneconnectTransformations string `json:"oneconnect_transformations"` ProxyType string `json:"proxy_type"` RedirectRewrite string `json:"redirect_rewrite"` RequestChunking string `json:"request_chunking"` ResponseChunking string `json:"response_chunking"` ResponseHeadersPermitted string `json:"response_headers_permitted"` ServerAgentName string `json:"server_agent_name"` SFlow SFlow `json:"sflow"` ViaHostName string `json:"via_host_name"` ViaRequest string `json:"via_request"` ViaResponse string `json:"via_response"` XFFAlternativeNames string `json:"xff_alternative_names"` } SFlow struct { PollInterval string `json:"poll_interval"` PollIntervalGlobal string `json:"poll_interval_global"` SamplingRate string `json:"sampling_rate"` SamplingRateGlobal string `json:"sampling_rate_global"` } ) func ParseHTTPEnforcement(raw string) (p HTTPEnforcement) { p.KnownMethods = []string{} for _, line := range strings.Split(raw, "\n") { f := strings.Fields(line) if len(f) == 0 { continue } switch strings.ToLower(f[0]) { case "excess-client-headers": p.ExcessClientHeaders = strings.Join(f[1:], " ") case "excess-server-headers": p.ExcessServerHeaders = strings.Join(f[1:], " ") case "known-methods": if f[1] != "none" { p.KnownMethods = append(p.KnownMethods, f[2:len(f)-1]...) } case "max-header-count": p.MaxHeaderCount = strings.Join(f[1:], " ") case "max-header-size": p.MaxHeaderSize = strings.Join(f[1:], " ") case "max-requests": p.MaxRequests = strings.Join(f[1:], " ") case "oversize-client-headers": p.OversizeClientHeaders = strings.Join(f[1:], " ") case "oversize-server-headers": p.OversizeServerHeaders = strings.Join(f[1:], " ") case "pipeline": p.Pipeline = strings.Join(f[1:], " ") case "truncated-redirects": p.TruncatedRedirects = strings.Join(f[1:], " ") case "unknown-method": p.UnknownMethod = strings.Join(f[1:], " ") } } return } func ParseExplicitProxy(raw string) (p ExplicitProxy) { for _, line := range strings.Split(raw, "\n") { f := strings.Fields(line) if len(f) == 0 { continue } switch strings.ToLower(f[0]) { case "bad-request-message": p.BadRequestMessage = strings.Join(f[1:], " ") case "bad-response-message": p.BadResponseMessage = strings.Join(f[1:], " ") case "connect-error-message": p.ConnectErrorMessage = strings.Join(f[1:], " ") case "default-connect-handling": p.DefaultConnectHandling = strings.Join(f[1:], " ") case "dns-error-message": p.DNSErrorMessage = strings.Join(f[1:], " ") case "dns-resolver": p.DNSResolver = strings.Join(f[1:], " ") case "host-names": p.HostNames = strings.Join(f[1:], " ") case "route-domain": p.RouteDomain = strings.Join(f[1:], " ") case "tunnel-name": p.TunnelName = strings.Join(f[1:], " ") } } return } func ParseHSTS(raw string) (p HSTS) { for _, line := range strings.Split(raw, "\n") { f := strings.Fields(line) if len(f) == 0 { continue } switch strings.ToLower(f[0]) { case "include-subdomains": p.IncludeSubDomains = strings.Join(f[1:], " ") case "maximum-age": p.MaximumAge = strings.Join(f[1:], " ") case "mode": p.Mode = strings.Join(f[1:], " ") } } return } func ParseSFlow(raw string) (p SFlow) { for _, line := range strings.Split(raw, "\n") { f := strings.Fields(line) if len(f) == 0 { continue } switch strings.ToLower(f[0]) { case "poll-interval": p.PollInterval = strings.Join(f[1:], " ") case "poll-interval-global": p.PollIntervalGlobal = strings.Join(f[1:], " ") case "sampling-rate": p.SamplingRate = strings.Join(f[1:], " ") case "sampling-rate-global": p.SamplingRateGlobal = strings.Join(f[1:], " ") } } return } func ParseHTTPProfile(raw string) (*HTTPProfile, error) { p := new(HTTPProfile) split := strings.Split(raw, "\n") if !strings.Contains(split[0], "ltm profile http") { return nil, errors.New("not an http profile") } p.ProfileCommon = parseCommon(raw) var inSFlow, inHSTS, inExp, inEnf bool var sflow, hsts, exp, enf string for _, line := range split { if inSFlow { if line == " }" { inSFlow = false p.SFlow = ParseSFlow(sflow) sflow = "" continue } sflow = sflow + line + "\n" } if inHSTS { if line == " }" { inHSTS = false p.HSTS = ParseHSTS(hsts) hsts = "" continue } hsts = hsts + line + "\n" } if inEnf { if line == " }" { inEnf = false p.Enforcement = ParseHTTPEnforcement(enf) enf = "" continue } enf = enf + line + "\n" } if inExp { if line == " }" { inExp = false p.ExplicitProxy = ParseExplicitProxy(exp) exp = "" continue } exp = exp + line + "\n" } f := strings.Fields(line) switch strings.ToLower(f[0]) { case "accept-xff": p.AcceptXFF = strings.Join(f[1:], " ") case "basic-auth-realm": p.BasicAuthRealm = strings.Join(f[1:], " ") case "encrypt-cookie-secret": p.EncryptCookieSecret = strings.Join(f[1:], " ") case "encrypt-cookies": p.EncryptCookies = strings.Join(f[1:], " ") case "enforcement": inEnf = true case "explicit-proxy": inExp = true case "fallback-host": p.FallbackHost = strings.Join(f[1:], " ") case "fallback-status-codes": p.FallbackStatusCodes = strings.Join(f[1:], " ") case "header-erase": p.HeaderErase = strings.Join(f[1:], " ") case "header-insert": p.HeaderInsert = strings.Join(f[1:], " ") case "hsts": inHSTS = true case "insert-xforwarded-for": p.InsertXForwardedFor = strings.Join(f[1:], " ") case "lws-separator": p.LWSSeparator = strings.Join(f[1:], " ") case "lws-width": p.LWSWidth = strings.Join(f[1:], " ") case "oneconnect-transformations": p.OneconnectTransformations = strings.Join(f[1:], " ") case "proxy-type": p.ProxyType = strings.Join(f[1:], " ") case "redirect-rewrite": p.RedirectRewrite = strings.Join(f[1:], " ") case "request-chunking": p.RequestChunking = strings.Join(f[1:], " ") case "response-chunking": p.ResponseChunking = strings.Join(f[1:], " ") case "response-headers-permitted": p.ResponseHeadersPermitted = strings.Join(f[1:], " ") case "server-agent-name": p.ServerAgentName = strings.Join(f[1:], " ") case "sflow": inSFlow = true case "via-host-name": p.ViaHostName = strings.Join(f[1:], " ") case "via-request": p.ViaRequest = strings.Join(f[1:], " ") case "via-response": p.ViaResponse = strings.Join(f[1:], " ") case "xff-alternative-names": p.XFFAlternativeNames = strings.Join(f[1:], " ") } } return p, nil }