"}},"componentScriptGroups({\"componentId\":\"custom.widget.Beta_Footer\"})":{"__typename":"ComponentScriptGroups","scriptGroups":{"__typename":"ComponentScriptGroupsDefinition","afterInteractive":{"__typename":"PageScriptGroupDefinition","group":"AFTER_INTERACTIVE","scriptIds":[]},"lazyOnLoad":{"__typename":"PageScriptGroupDefinition","group":"LAZY_ON_LOAD","scriptIds":[]}},"componentScripts":[]},"component({\"componentId\":\"custom.widget.Tag_Manager_Helper\"})":{"__typename":"Component","render({\"context\":{\"component\":{\"entities\":[],\"props\":{}},\"page\":{\"entities\":[],\"name\":\"TagPage\",\"props\":{},\"url\":\"https://community.f5.com/tag/BIG-IP\"}}})":{"__typename":"ComponentRenderResult","html":" "}},"componentScriptGroups({\"componentId\":\"custom.widget.Tag_Manager_Helper\"})":{"__typename":"ComponentScriptGroups","scriptGroups":{"__typename":"ComponentScriptGroupsDefinition","afterInteractive":{"__typename":"PageScriptGroupDefinition","group":"AFTER_INTERACTIVE","scriptIds":[]},"lazyOnLoad":{"__typename":"PageScriptGroupDefinition","group":"LAZY_ON_LOAD","scriptIds":[]}},"componentScripts":[]},"component({\"componentId\":\"custom.widget.Consent_Blackbar\"})":{"__typename":"Component","render({\"context\":{\"component\":{\"entities\":[],\"props\":{}},\"page\":{\"entities\":[],\"name\":\"TagPage\",\"props\":{},\"url\":\"https://community.f5.com/tag/BIG-IP\"}}})":{"__typename":"ComponentRenderResult","html":""}},"componentScriptGroups({\"componentId\":\"custom.widget.Consent_Blackbar\"})":{"__typename":"ComponentScriptGroups","scriptGroups":{"__typename":"ComponentScriptGroupsDefinition","afterInteractive":{"__typename":"PageScriptGroupDefinition","group":"AFTER_INTERACTIVE","scriptIds":[]},"lazyOnLoad":{"__typename":"PageScriptGroupDefinition","group":"LAZY_ON_LOAD","scriptIds":[]}},"componentScripts":[]},"cachedText({\"lastModified\":\"1743097580000\",\"locale\":\"en-US\",\"namespaces\":[\"components/community/NavbarDropdownToggle\"]})":[{"__ref":"CachedAsset:text:en_US-components/community/NavbarDropdownToggle-1743097580000"}],"cachedText({\"lastModified\":\"1743097580000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/common/OverflowNav\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/common/OverflowNav-1743097580000"}],"cachedText({\"lastModified\":\"1743097580000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageView/MessageViewInline\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageView/MessageViewInline-1743097580000"}],"cachedText({\"lastModified\":\"1743097580000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/common/Pager/PagerLoadMore\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/common/Pager/PagerLoadMore-1743097580000"}],"cachedText({\"lastModified\":\"1743097580000\",\"locale\":\"en-US\",\"namespaces\":[\"components/customComponent/CustomComponent\"]})":[{"__ref":"CachedAsset:text:en_US-components/customComponent/CustomComponent-1743097580000"}],"cachedText({\"lastModified\":\"1743097580000\",\"locale\":\"en-US\",\"namespaces\":[\"components/users/UserLink\"]})":[{"__ref":"CachedAsset:text:en_US-components/users/UserLink-1743097580000"}],"cachedText({\"lastModified\":\"1743097580000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageSubject\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageSubject-1743097580000"}],"cachedText({\"lastModified\":\"1743097580000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageBody\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageBody-1743097580000"}],"cachedText({\"lastModified\":\"1743097580000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageTime\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageTime-1743097580000"}],"cachedText({\"lastModified\":\"1743097580000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/nodes/NodeIcon\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/nodes/NodeIcon-1743097580000"}],"cachedText({\"lastModified\":\"1743097580000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageUnreadCount\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageUnreadCount-1743097580000"}],"cachedText({\"lastModified\":\"1743097580000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageViewCount\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageViewCount-1743097580000"}],"cachedText({\"lastModified\":\"1743097580000\",\"locale\":\"en-US\",\"namespaces\":[\"components/kudos/KudosCount\"]})":[{"__ref":"CachedAsset:text:en_US-components/kudos/KudosCount-1743097580000"}],"cachedText({\"lastModified\":\"1743097580000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageRepliesCount\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageRepliesCount-1743097580000"}],"cachedText({\"lastModified\":\"1743097580000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/users/UserAvatar\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/users/UserAvatar-1743097580000"}]},"CachedAsset:pages-1743758597252":{"__typename":"CachedAsset","id":"pages-1743758597252","value":[{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"HowDoI.GetInvolved.MvpProgram","type":"COMMUNITY","urlPath":"/c/how-do-i/get-involved/mvp-program","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"BlogViewAllPostsPage","type":"BLOG","urlPath":"/category/:categoryId/blog/:boardId/all-posts/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"CasePortalPage","type":"CASE_PORTAL","urlPath":"/caseportal","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"CreateGroupHubPage","type":"GROUP_HUB","urlPath":"/groups/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"CaseViewPage","type":"CASE_DETAILS","urlPath":"/case/:caseId/:caseNumber","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"InboxPage","type":"COMMUNITY","urlPath":"/inbox","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"HowDoI.GetInvolved.AdvocacyProgram","type":"COMMUNITY","urlPath":"/c/how-do-i/get-involved/advocacy-program","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"HowDoI.GetHelp.NonCustomer","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help/non-customer","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"HelpFAQPage","type":"COMMUNITY","urlPath":"/help","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"HowDoI.GetHelp.F5Customer","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help/f5-customer","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"IdeaMessagePage","type":"IDEA_POST","urlPath":"/idea/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"IdeaViewAllIdeasPage","type":"IDEA","urlPath":"/category/:categoryId/ideas/:boardId/all-ideas/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"LoginPage","type":"USER","urlPath":"/signin","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"BlogPostPage","type":"BLOG","urlPath":"/category/:categoryId/blogs/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"HowDoI.GetInvolved","type":"COMMUNITY","urlPath":"/c/how-do-i/get-involved","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"HowDoI.Learn","type":"COMMUNITY","urlPath":"/c/how-do-i/learn","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1739501996000,"localOverride":null,"page":{"id":"Test","type":"CUSTOM","urlPath":"/custom-test-2","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"ThemeEditorPage","type":"COMMUNITY","urlPath":"/designer/themes","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"TkbViewAllArticlesPage","type":"TKB","urlPath":"/category/:categoryId/kb/:boardId/all-articles/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"OccasionEditPage","type":"EVENT","urlPath":"/event/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"OAuthAuthorizationAllowPage","type":"USER","urlPath":"/auth/authorize/allow","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"PageEditorPage","type":"COMMUNITY","urlPath":"/designer/pages","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"PostPage","type":"COMMUNITY","urlPath":"/category/:categoryId/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"ForumBoardPage","type":"FORUM","urlPath":"/category/:categoryId/discussions/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"TkbBoardPage","type":"TKB","urlPath":"/category/:categoryId/kb/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"EventPostPage","type":"EVENT","urlPath":"/category/:categoryId/events/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"UserBadgesPage","type":"COMMUNITY","urlPath":"/users/:login/:userId/badges","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"GroupHubMembershipAction","type":"GROUP_HUB","urlPath":"/membership/join/:nodeId/:membershipType","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"MaintenancePage","type":"COMMUNITY","urlPath":"/maintenance","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"IdeaReplyPage","type":"IDEA_REPLY","urlPath":"/idea/:boardId/:messageSubject/:messageId/comments/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"UserSettingsPage","type":"USER","urlPath":"/mysettings/:userSettingsTab","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"GroupHubsPage","type":"GROUP_HUB","urlPath":"/groups","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"ForumPostPage","type":"FORUM","urlPath":"/category/:categoryId/discussions/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"OccasionRsvpActionPage","type":"OCCASION","urlPath":"/event/:boardId/:messageSubject/:messageId/rsvp/:responseType","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"VerifyUserEmailPage","type":"USER","urlPath":"/verifyemail/:userId/:verifyEmailToken","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"AllOccasionsPage","type":"OCCASION","urlPath":"/category/:categoryId/events/:boardId/all-events/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"EventBoardPage","type":"EVENT","urlPath":"/category/:categoryId/events/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"TkbReplyPage","type":"TKB_REPLY","urlPath":"/kb/:boardId/:messageSubject/:messageId/comments/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"IdeaBoardPage","type":"IDEA","urlPath":"/category/:categoryId/ideas/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"CommunityGuideLinesPage","type":"COMMUNITY","urlPath":"/communityguidelines","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"CaseCreatePage","type":"SALESFORCE_CASE_CREATION","urlPath":"/caseportal/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"TkbEditPage","type":"TKB","urlPath":"/kb/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"ForgotPasswordPage","type":"USER","urlPath":"/forgotpassword","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"IdeaEditPage","type":"IDEA","urlPath":"/idea/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"TagPage","type":"COMMUNITY","urlPath":"/tag/:tagName","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"BlogBoardPage","type":"BLOG","urlPath":"/category/:categoryId/blog/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"OccasionMessagePage","type":"OCCASION_TOPIC","urlPath":"/event/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"ManageContentPage","type":"COMMUNITY","urlPath":"/managecontent","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"ClosedMembershipNodeNonMembersPage","type":"GROUP_HUB","urlPath":"/closedgroup/:groupHubId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"HowDoI.GetHelp.Community","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help/community","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"CommunityPage","type":"COMMUNITY","urlPath":"/","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"HowDoI.GetInvolved.ContributeCode","type":"COMMUNITY","urlPath":"/c/how-do-i/get-involved/contribute-code","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"ForumMessagePage","type":"FORUM_TOPIC","urlPath":"/discussions/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"IdeaPostPage","type":"IDEA","urlPath":"/category/:categoryId/ideas/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"BlogMessagePage","type":"BLOG_ARTICLE","urlPath":"/blog/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"RegistrationPage","type":"USER","urlPath":"/register","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"EditGroupHubPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"ForumEditPage","type":"FORUM","urlPath":"/discussions/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"ResetPasswordPage","type":"USER","urlPath":"/resetpassword/:userId/:resetPasswordToken","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"TkbMessagePage","type":"TKB_ARTICLE","urlPath":"/kb/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"HowDoI.Learn.AboutIrules","type":"COMMUNITY","urlPath":"/c/how-do-i/learn/about-irules","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"BlogEditPage","type":"BLOG","urlPath":"/blog/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"HowDoI.GetHelp.F5Support","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help/f5-support","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"ManageUsersPage","type":"USER","urlPath":"/users/manage/:tab?/:manageUsersTab?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"ForumReplyPage","type":"FORUM_REPLY","urlPath":"/discussions/:boardId/:messageSubject/:messageId/replies/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"PrivacyPolicyPage","type":"COMMUNITY","urlPath":"/privacypolicy","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"NotificationPage","type":"COMMUNITY","urlPath":"/notifications","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"UserPage","type":"USER","urlPath":"/users/:login/:userId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"HealthCheckPage","type":"COMMUNITY","urlPath":"/health","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"OccasionReplyPage","type":"OCCASION_REPLY","urlPath":"/event/:boardId/:messageSubject/:messageId/comments/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"ManageMembersPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId/manage/:tab?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"SearchResultsPage","type":"COMMUNITY","urlPath":"/search","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"BlogReplyPage","type":"BLOG_REPLY","urlPath":"/blog/:boardId/:messageSubject/:messageId/replies/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"GroupHubPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"TermsOfServicePage","type":"COMMUNITY","urlPath":"/termsofservice","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"HowDoI.GetHelp","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"HowDoI.GetHelp.SecurityIncident","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help/security-incident","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"CategoryPage","type":"CATEGORY","urlPath":"/category/:categoryId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"ForumViewAllTopicsPage","type":"FORUM","urlPath":"/category/:categoryId/discussions/:boardId/all-topics/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"TkbPostPage","type":"TKB","urlPath":"/category/:categoryId/kbs/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"GroupHubPostPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1743758597252,"localOverride":null,"page":{"id":"HowDoI","type":"COMMUNITY","urlPath":"/c/how-do-i","__typename":"PageDescriptor"},"__typename":"PageResource"}],"localOverride":false},"CachedAsset:text:en_US-components/context/AppContext/AppContextProvider-0":{"__typename":"CachedAsset","id":"text:en_US-components/context/AppContext/AppContextProvider-0","value":{"noCommunity":"Cannot find community","noUser":"Cannot find current user","noNode":"Cannot find node with id {nodeId}","noMessage":"Cannot find message with id {messageId}"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/common/Loading/LoadingDot-0":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/Loading/LoadingDot-0","value":{"title":"Loading..."},"localOverride":false},"User:user:-1":{"__typename":"User","id":"user:-1","uid":-1,"login":"Former Member","email":"","avatar":null,"rank":null,"kudosWeight":1,"registrationData":{"__typename":"RegistrationData","status":"ANONYMOUS","registrationTime":null,"confirmEmailStatus":false,"registrationAccessLevel":"VIEW","ssoRegistrationFields":[]},"ssoId":null,"profileSettings":{"__typename":"ProfileSettings","dateDisplayStyle":{"__typename":"InheritableStringSettingWithPossibleValues","key":"layout.friendly_dates_enabled","value":"false","localValue":"true","possibleValues":["true","false"]},"dateDisplayFormat":{"__typename":"InheritableStringSetting","key":"layout.format_pattern_date","value":"dd-MMM-yyyy","localValue":"MM-dd-yyyy"},"language":{"__typename":"InheritableStringSettingWithPossibleValues","key":"profile.language","value":"en-US","localValue":null,"possibleValues":["en-US"]}},"deleted":false},"Theme:customTheme1":{"__typename":"Theme","id":"customTheme1"},"CachedAsset:theme:customTheme1-1743758594774":{"__typename":"CachedAsset","id":"theme:customTheme1-1743758594774","value":{"id":"customTheme1","animation":{"fast":"150ms","normal":"250ms","slow":"500ms","slowest":"750ms","function":"cubic-bezier(0.07, 0.91, 0.51, 1)","__typename":"AnimationThemeSettings"},"avatar":{"borderRadius":"50%","collections":["custom"],"__typename":"AvatarThemeSettings"},"basics":{"browserIcon":{"imageAssetName":"JimmyPackets-512-1702592938213.png","imageLastModified":"1702592945815","__typename":"ThemeAsset"},"customerLogo":{"imageAssetName":"f5_logo_fix-1704824537976.svg","imageLastModified":"1704824540697","__typename":"ThemeAsset"},"maximumWidthOfPageContent":"1600px","oneColumnNarrowWidth":"800px","gridGutterWidthMd":"30px","gridGutterWidthXs":"10px","pageWidthStyle":"WIDTH_OF_PAGE_CONTENT","__typename":"BasicsThemeSettings"},"buttons":{"borderRadiusSm":"5px","borderRadius":"5px","borderRadiusLg":"5px","paddingY":"5px","paddingYLg":"7px","paddingYHero":"var(--lia-bs-btn-padding-y-lg)","paddingX":"12px","paddingXLg":"14px","paddingXHero":"42px","fontStyle":"NORMAL","fontWeight":"400","textTransform":"NONE","disabledOpacity":0.5,"primaryTextColor":"var(--lia-bs-white)","primaryTextHoverColor":"var(--lia-bs-white)","primaryTextActiveColor":"var(--lia-bs-white)","primaryBgColor":"var(--lia-bs-primary)","primaryBgHoverColor":"hsl(var(--lia-bs-primary-h), var(--lia-bs-primary-s), calc(var(--lia-bs-primary-l) * 0.85))","primaryBgActiveColor":"hsl(var(--lia-bs-primary-h), var(--lia-bs-primary-s), calc(var(--lia-bs-primary-l) * 0.7))","primaryBorder":"1px solid transparent","primaryBorderHover":"1px solid transparent","primaryBorderActive":"1px solid transparent","primaryBorderFocus":"1px solid var(--lia-bs-white)","primaryBoxShadowFocus":"0 0 0 1px var(--lia-bs-primary), 0 0 0 4px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","secondaryTextColor":"var(--lia-bs-gray-900)","secondaryTextHoverColor":"hsl(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), calc(var(--lia-bs-gray-900-l) * 0.95))","secondaryTextActiveColor":"hsl(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), calc(var(--lia-bs-gray-900-l) * 0.9))","secondaryBgColor":"var(--lia-bs-gray-400)","secondaryBgHoverColor":"hsl(var(--lia-bs-gray-400-h), var(--lia-bs-gray-400-s), calc(var(--lia-bs-gray-400-l) * 0.96))","secondaryBgActiveColor":"hsl(var(--lia-bs-gray-400-h), var(--lia-bs-gray-400-s), calc(var(--lia-bs-gray-400-l) * 0.92))","secondaryBorder":"1px solid transparent","secondaryBorderHover":"1px solid transparent","secondaryBorderActive":"1px solid transparent","secondaryBorderFocus":"1px solid transparent","secondaryBoxShadowFocus":"0 0 0 1px var(--lia-bs-primary), 0 0 0 4px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","tertiaryTextColor":"var(--lia-bs-gray-900)","tertiaryTextHoverColor":"hsl(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), calc(var(--lia-bs-gray-900-l) * 0.95))","tertiaryTextActiveColor":"hsl(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), calc(var(--lia-bs-gray-900-l) * 0.9))","tertiaryBgColor":"transparent","tertiaryBgHoverColor":"transparent","tertiaryBgActiveColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.04)","tertiaryBorder":"1px solid transparent","tertiaryBorderHover":"1px solid hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.08)","tertiaryBorderActive":"1px solid transparent","tertiaryBorderFocus":"1px solid transparent","tertiaryBoxShadowFocus":"0 0 0 1px var(--lia-bs-primary), 0 0 0 4px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","destructiveTextColor":"var(--lia-bs-danger)","destructiveTextHoverColor":"hsl(var(--lia-bs-danger-h), var(--lia-bs-danger-s), calc(var(--lia-bs-danger-l) * 0.95))","destructiveTextActiveColor":"hsl(var(--lia-bs-danger-h), var(--lia-bs-danger-s), calc(var(--lia-bs-danger-l) * 0.9))","destructiveBgColor":"var(--lia-bs-gray-300)","destructiveBgHoverColor":"hsl(var(--lia-bs-gray-300-h), var(--lia-bs-gray-300-s), calc(var(--lia-bs-gray-300-l) * 0.96))","destructiveBgActiveColor":"hsl(var(--lia-bs-gray-300-h), var(--lia-bs-gray-300-s), calc(var(--lia-bs-gray-300-l) * 0.92))","destructiveBorder":"1px solid transparent","destructiveBorderHover":"1px solid transparent","destructiveBorderActive":"1px solid transparent","destructiveBorderFocus":"1px solid transparent","destructiveBoxShadowFocus":"0 0 0 1px var(--lia-bs-primary), 0 0 0 4px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","__typename":"ButtonsThemeSettings"},"border":{"color":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.08)","mainContent":"NONE","sideContent":"NONE","radiusSm":"3px","radius":"5px","radiusLg":"9px","radius50":"100vw","__typename":"BorderThemeSettings"},"boxShadow":{"xs":"0 0 0 1px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.08), 0 3px 0 -1px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.08)","sm":"0 2px 4px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.06)","md":"0 5px 15px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.15)","lg":"0 10px 30px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.15)","__typename":"BoxShadowThemeSettings"},"cards":{"bgColor":"var(--lia-panel-bg-color)","borderRadius":"var(--lia-panel-border-radius)","boxShadow":"var(--lia-box-shadow-xs)","__typename":"CardsThemeSettings"},"chip":{"maxWidth":"300px","height":"30px","__typename":"ChipThemeSettings"},"coreTypes":{"defaultMessageLinkColor":"var(--lia-bs-primary)","defaultMessageLinkDecoration":"none","defaultMessageLinkFontStyle":"NORMAL","defaultMessageLinkFontWeight":"400","defaultMessageFontStyle":"NORMAL","defaultMessageFontWeight":"400","forumColor":"#0C5C8D","forumFontFamily":"var(--lia-bs-font-family-base)","forumFontWeight":"var(--lia-default-message-font-weight)","forumLineHeight":"var(--lia-bs-line-height-base)","forumFontStyle":"var(--lia-default-message-font-style)","forumMessageLinkColor":"var(--lia-default-message-link-color)","forumMessageLinkDecoration":"var(--lia-default-message-link-decoration)","forumMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","forumMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","forumSolvedColor":"#62C026","blogColor":"#730015","blogFontFamily":"var(--lia-bs-font-family-base)","blogFontWeight":"var(--lia-default-message-font-weight)","blogLineHeight":"1.75","blogFontStyle":"var(--lia-default-message-font-style)","blogMessageLinkColor":"var(--lia-default-message-link-color)","blogMessageLinkDecoration":"var(--lia-default-message-link-decoration)","blogMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","blogMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","tkbColor":"#C20025","tkbFontFamily":"var(--lia-bs-font-family-base)","tkbFontWeight":"var(--lia-default-message-font-weight)","tkbLineHeight":"1.75","tkbFontStyle":"var(--lia-default-message-font-style)","tkbMessageLinkColor":"var(--lia-default-message-link-color)","tkbMessageLinkDecoration":"var(--lia-default-message-link-decoration)","tkbMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","tkbMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","qandaColor":"#4099E2","qandaFontFamily":"var(--lia-bs-font-family-base)","qandaFontWeight":"var(--lia-default-message-font-weight)","qandaLineHeight":"var(--lia-bs-line-height-base)","qandaFontStyle":"var(--lia-default-message-link-font-style)","qandaMessageLinkColor":"var(--lia-default-message-link-color)","qandaMessageLinkDecoration":"var(--lia-default-message-link-decoration)","qandaMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","qandaMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","qandaSolvedColor":"#3FA023","ideaColor":"#F3704B","ideaFontFamily":"var(--lia-bs-font-family-base)","ideaFontWeight":"var(--lia-default-message-font-weight)","ideaLineHeight":"var(--lia-bs-line-height-base)","ideaFontStyle":"var(--lia-default-message-font-style)","ideaMessageLinkColor":"var(--lia-default-message-link-color)","ideaMessageLinkDecoration":"var(--lia-default-message-link-decoration)","ideaMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","ideaMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","contestColor":"#FCC845","contestFontFamily":"var(--lia-bs-font-family-base)","contestFontWeight":"var(--lia-default-message-font-weight)","contestLineHeight":"var(--lia-bs-line-height-base)","contestFontStyle":"var(--lia-default-message-link-font-style)","contestMessageLinkColor":"var(--lia-default-message-link-color)","contestMessageLinkDecoration":"var(--lia-default-message-link-decoration)","contestMessageLinkFontStyle":"ITALIC","contestMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","occasionColor":"#EE4B5B","occasionFontFamily":"var(--lia-bs-font-family-base)","occasionFontWeight":"var(--lia-default-message-font-weight)","occasionLineHeight":"var(--lia-bs-line-height-base)","occasionFontStyle":"var(--lia-default-message-font-style)","occasionMessageLinkColor":"var(--lia-default-message-link-color)","occasionMessageLinkDecoration":"var(--lia-default-message-link-decoration)","occasionMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","occasionMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","grouphubColor":"#491B62","categoryColor":"#949494","communityColor":"#FFFFFF","productColor":"#949494","__typename":"CoreTypesThemeSettings"},"colors":{"black":"#000000","white":"#FFFFFF","gray100":"#F7F7F7","gray200":"#F7F7F7","gray300":"#E8E8E8","gray400":"#D9D9D9","gray500":"#CCCCCC","gray600":"#949494","gray700":"#707070","gray800":"#545454","gray900":"#333333","dark":"#545454","light":"#F7F7F7","primary":"#0C5C8D","secondary":"#333333","bodyText":"#222222","bodyBg":"#F5F5F5","info":"#1D9CD3","success":"#62C026","warning":"#FFD651","danger":"#C20025","alertSystem":"#FF6600","textMuted":"#707070","highlight":"#FFFCAD","outline":"var(--lia-bs-primary)","custom":["#C20025","#081B85","#009639","#B3C6D7","#7CC0EB","#F29A36"],"__typename":"ColorsThemeSettings"},"divider":{"size":"3px","marginLeft":"4px","marginRight":"4px","borderRadius":"50%","bgColor":"var(--lia-bs-gray-600)","bgColorActive":"var(--lia-bs-gray-600)","__typename":"DividerThemeSettings"},"dropdown":{"fontSize":"var(--lia-bs-font-size-sm)","borderColor":"var(--lia-bs-border-color)","borderRadius":"var(--lia-bs-border-radius-sm)","dividerBg":"var(--lia-bs-gray-300)","itemPaddingY":"5px","itemPaddingX":"20px","headerColor":"var(--lia-bs-gray-700)","__typename":"DropdownThemeSettings"},"email":{"link":{"color":"#0069D4","hoverColor":"#0061c2","decoration":"none","hoverDecoration":"underline","__typename":"EmailLinkSettings"},"border":{"color":"#e4e4e4","__typename":"EmailBorderSettings"},"buttons":{"borderRadiusLg":"5px","paddingXLg":"16px","paddingYLg":"7px","fontWeight":"700","primaryTextColor":"#ffffff","primaryTextHoverColor":"#ffffff","primaryBgColor":"#0069D4","primaryBgHoverColor":"#005cb8","primaryBorder":"1px solid transparent","primaryBorderHover":"1px solid transparent","__typename":"EmailButtonsSettings"},"panel":{"borderRadius":"5px","borderColor":"#e4e4e4","__typename":"EmailPanelSettings"},"__typename":"EmailThemeSettings"},"emoji":{"skinToneDefault":"#ffcd43","skinToneLight":"#fae3c5","skinToneMediumLight":"#e2cfa5","skinToneMedium":"#daa478","skinToneMediumDark":"#a78058","skinToneDark":"#5e4d43","__typename":"EmojiThemeSettings"},"heading":{"color":"var(--lia-bs-body-color)","fontFamily":"Inter","fontStyle":"NORMAL","fontWeight":"600","h1FontSize":"30px","h2FontSize":"25px","h3FontSize":"20px","h4FontSize":"18px","h5FontSize":"16px","h6FontSize":"16px","lineHeight":"1.2","subHeaderFontSize":"11px","subHeaderFontWeight":"500","h1LetterSpacing":"normal","h2LetterSpacing":"normal","h3LetterSpacing":"normal","h4LetterSpacing":"normal","h5LetterSpacing":"normal","h6LetterSpacing":"normal","subHeaderLetterSpacing":"2px","h1FontWeight":"var(--lia-bs-headings-font-weight)","h2FontWeight":"var(--lia-bs-headings-font-weight)","h3FontWeight":"var(--lia-bs-headings-font-weight)","h4FontWeight":"var(--lia-bs-headings-font-weight)","h5FontWeight":"var(--lia-bs-headings-font-weight)","h6FontWeight":"var(--lia-bs-headings-font-weight)","__typename":"HeadingThemeSettings"},"icons":{"size10":"10px","size12":"12px","size14":"14px","size16":"16px","size20":"20px","size24":"24px","size30":"30px","size40":"40px","size50":"50px","size60":"60px","size80":"80px","size120":"120px","size160":"160px","__typename":"IconsThemeSettings"},"imagePreview":{"bgColor":"var(--lia-bs-gray-900)","titleColor":"var(--lia-bs-white)","controlColor":"var(--lia-bs-white)","controlBgColor":"var(--lia-bs-gray-800)","__typename":"ImagePreviewThemeSettings"},"input":{"borderColor":"var(--lia-bs-gray-600)","disabledColor":"var(--lia-bs-gray-600)","focusBorderColor":"var(--lia-bs-primary)","labelMarginBottom":"10px","btnFontSize":"var(--lia-bs-font-size-sm)","focusBoxShadow":"0 0 0 3px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","checkLabelMarginBottom":"2px","checkboxBorderRadius":"3px","borderRadiusSm":"var(--lia-bs-border-radius-sm)","borderRadius":"var(--lia-bs-border-radius)","borderRadiusLg":"var(--lia-bs-border-radius-lg)","formTextMarginTop":"4px","textAreaBorderRadius":"var(--lia-bs-border-radius)","activeFillColor":"var(--lia-bs-primary)","__typename":"InputThemeSettings"},"loading":{"dotDarkColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.2)","dotLightColor":"hsla(var(--lia-bs-white-h), var(--lia-bs-white-s), var(--lia-bs-white-l), 0.5)","barDarkColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.06)","barLightColor":"hsla(var(--lia-bs-white-h), var(--lia-bs-white-s), var(--lia-bs-white-l), 0.4)","__typename":"LoadingThemeSettings"},"link":{"color":"var(--lia-bs-primary)","hoverColor":"hsl(var(--lia-bs-primary-h), var(--lia-bs-primary-s), calc(var(--lia-bs-primary-l) - 10%))","decoration":"none","hoverDecoration":"underline","__typename":"LinkThemeSettings"},"listGroup":{"itemPaddingY":"15px","itemPaddingX":"15px","borderColor":"var(--lia-bs-gray-300)","__typename":"ListGroupThemeSettings"},"modal":{"contentTextColor":"var(--lia-bs-body-color)","contentBg":"var(--lia-bs-white)","backgroundBg":"var(--lia-bs-black)","smSize":"440px","mdSize":"760px","lgSize":"1080px","backdropOpacity":0.3,"contentBoxShadowXs":"var(--lia-bs-box-shadow-sm)","contentBoxShadow":"var(--lia-bs-box-shadow)","headerFontWeight":"700","__typename":"ModalThemeSettings"},"navbar":{"position":"FIXED","background":{"attachment":null,"clip":null,"color":"var(--lia-bs-white)","imageAssetName":null,"imageLastModified":"0","origin":null,"position":"CENTER_CENTER","repeat":"NO_REPEAT","size":"COVER","__typename":"BackgroundProps"},"backgroundOpacity":0.8,"paddingTop":"15px","paddingBottom":"15px","borderBottom":"1px solid var(--lia-bs-border-color)","boxShadow":"var(--lia-bs-box-shadow-sm)","brandMarginRight":"30px","brandMarginRightSm":"10px","brandLogoHeight":"30px","linkGap":"10px","linkJustifyContent":"flex-start","linkPaddingY":"5px","linkPaddingX":"10px","linkDropdownPaddingY":"9px","linkDropdownPaddingX":"var(--lia-nav-link-px)","linkColor":"var(--lia-bs-body-color)","linkHoverColor":"var(--lia-bs-primary)","linkFontSize":"var(--lia-bs-font-size-sm)","linkFontStyle":"NORMAL","linkFontWeight":"400","linkTextTransform":"NONE","linkLetterSpacing":"normal","linkBorderRadius":"var(--lia-bs-border-radius-sm)","linkBgColor":"transparent","linkBgHoverColor":"transparent","linkBorder":"none","linkBorderHover":"none","linkBoxShadow":"none","linkBoxShadowHover":"none","linkTextBorderBottom":"none","linkTextBorderBottomHover":"none","dropdownPaddingTop":"10px","dropdownPaddingBottom":"15px","dropdownPaddingX":"10px","dropdownMenuOffset":"2px","dropdownDividerMarginTop":"10px","dropdownDividerMarginBottom":"10px","dropdownBorderColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.08)","controllerBgHoverColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.1)","controllerIconColor":"var(--lia-bs-body-color)","controllerIconHoverColor":"var(--lia-bs-body-color)","controllerTextColor":"var(--lia-nav-controller-icon-color)","controllerTextHoverColor":"var(--lia-nav-controller-icon-hover-color)","controllerHighlightColor":"hsla(30, 100%, 50%)","controllerHighlightTextColor":"var(--lia-yiq-light)","controllerBorderRadius":"var(--lia-border-radius-50)","hamburgerColor":"var(--lia-nav-controller-icon-color)","hamburgerHoverColor":"var(--lia-nav-controller-icon-color)","hamburgerBgColor":"transparent","hamburgerBgHoverColor":"transparent","hamburgerBorder":"none","hamburgerBorderHover":"none","collapseMenuMarginLeft":"20px","collapseMenuDividerBg":"var(--lia-nav-link-color)","collapseMenuDividerOpacity":0.16,"__typename":"NavbarThemeSettings"},"pager":{"textColor":"var(--lia-bs-link-color)","textFontWeight":"var(--lia-font-weight-md)","textFontSize":"var(--lia-bs-font-size-sm)","__typename":"PagerThemeSettings"},"panel":{"bgColor":"var(--lia-bs-white)","borderRadius":"var(--lia-bs-border-radius)","borderColor":"var(--lia-bs-border-color)","boxShadow":"none","__typename":"PanelThemeSettings"},"popover":{"arrowHeight":"8px","arrowWidth":"16px","maxWidth":"300px","minWidth":"100px","headerBg":"var(--lia-bs-white)","borderColor":"var(--lia-bs-border-color)","borderRadius":"var(--lia-bs-border-radius)","boxShadow":"0 0.5rem 1rem hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.15)","__typename":"PopoverThemeSettings"},"prism":{"color":"#000000","bgColor":"#f5f2f0","fontFamily":"var(--font-family-monospace)","fontSize":"var(--lia-bs-font-size-base)","fontWeightBold":"var(--lia-bs-font-weight-bold)","fontStyleItalic":"italic","tabSize":2,"highlightColor":"#b3d4fc","commentColor":"#62707e","punctuationColor":"#6f6f6f","namespaceOpacity":"0.7","propColor":"#990055","selectorColor":"#517a00","operatorColor":"#906736","operatorBgColor":"hsla(0, 0%, 100%, 0.5)","keywordColor":"#0076a9","functionColor":"#d3284b","variableColor":"#c14700","__typename":"PrismThemeSettings"},"rte":{"bgColor":"var(--lia-bs-white)","borderRadius":"var(--lia-panel-border-radius)","boxShadow":" var(--lia-panel-box-shadow)","customColor1":"#bfedd2","customColor2":"#fbeeb8","customColor3":"#f8cac6","customColor4":"#eccafa","customColor5":"#c2e0f4","customColor6":"#2dc26b","customColor7":"#f1c40f","customColor8":"#e03e2d","customColor9":"#b96ad9","customColor10":"#3598db","customColor11":"#169179","customColor12":"#e67e23","customColor13":"#ba372a","customColor14":"#843fa1","customColor15":"#236fa1","customColor16":"#ecf0f1","customColor17":"#ced4d9","customColor18":"#95a5a6","customColor19":"#7e8c8d","customColor20":"#34495e","customColor21":"#000000","customColor22":"#ffffff","defaultMessageHeaderMarginTop":"14px","defaultMessageHeaderMarginBottom":"10px","defaultMessageItemMarginTop":"0","defaultMessageItemMarginBottom":"10px","diffAddedColor":"hsla(170, 53%, 51%, 0.4)","diffChangedColor":"hsla(43, 97%, 63%, 0.4)","diffNoneColor":"hsla(0, 0%, 80%, 0.4)","diffRemovedColor":"hsla(9, 74%, 47%, 0.4)","specialMessageHeaderMarginTop":"14px","specialMessageHeaderMarginBottom":"10px","specialMessageItemMarginTop":"0","specialMessageItemMarginBottom":"10px","__typename":"RteThemeSettings"},"tags":{"bgColor":"var(--lia-bs-gray-200)","bgHoverColor":"var(--lia-bs-gray-400)","borderRadius":"var(--lia-bs-border-radius-sm)","color":"var(--lia-bs-body-color)","hoverColor":"var(--lia-bs-body-color)","fontWeight":"var(--lia-font-weight-md)","fontSize":"var(--lia-font-size-xxs)","textTransform":"UPPERCASE","letterSpacing":"0.5px","__typename":"TagsThemeSettings"},"toasts":{"borderRadius":"var(--lia-bs-border-radius)","paddingX":"12px","__typename":"ToastsThemeSettings"},"typography":{"fontFamilyBase":"Atkinson Hyperlegible","fontStyleBase":"NORMAL","fontWeightBase":"400","fontWeightLight":"300","fontWeightNormal":"400","fontWeightMd":"500","fontWeightBold":"700","letterSpacingSm":"normal","letterSpacingXs":"normal","lineHeightBase":"1.3","fontSizeBase":"15px","fontSizeXxs":"11px","fontSizeXs":"12px","fontSizeSm":"13px","fontSizeLg":"20px","fontSizeXl":"24px","smallFontSize":"14px","customFonts":[],"__typename":"TypographyThemeSettings"},"unstyledListItem":{"marginBottomSm":"5px","marginBottomMd":"10px","marginBottomLg":"15px","marginBottomXl":"20px","marginBottomXxl":"25px","__typename":"UnstyledListItemThemeSettings"},"yiq":{"light":"#ffffff","dark":"#000000","__typename":"YiqThemeSettings"},"colorLightness":{"primaryDark":0.36,"primaryLight":0.74,"primaryLighter":0.89,"primaryLightest":0.95,"infoDark":0.39,"infoLight":0.72,"infoLighter":0.85,"infoLightest":0.93,"successDark":0.24,"successLight":0.62,"successLighter":0.8,"successLightest":0.91,"warningDark":0.39,"warningLight":0.68,"warningLighter":0.84,"warningLightest":0.93,"dangerDark":0.41,"dangerLight":0.72,"dangerLighter":0.89,"dangerLightest":0.95,"__typename":"ColorLightnessThemeSettings"},"localOverride":false,"__typename":"Theme"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/common/Loading/LoadingDot-1743097580000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/Loading/LoadingDot-1743097580000","value":{"title":"Loading..."},"localOverride":false},"CachedAsset:text:en_US-components/common/EmailVerification-1743097580000":{"__typename":"CachedAsset","id":"text:en_US-components/common/EmailVerification-1743097580000","value":{"email.verification.title":"Email Verification Required","email.verification.message.update.email":"To participate in the community, you must first verify your email address. The verification email was sent to {email}. To change your email, visit My Settings.","email.verification.message.resend.email":"To participate in the community, you must first verify your email address. The verification email was sent to {email}. Resend email."},"localOverride":false},"CachedAsset:text:en_US-pages/tags/TagPage-1743097580000":{"__typename":"CachedAsset","id":"text:en_US-pages/tags/TagPage-1743097580000","value":{"tagPageTitle":"Tag:\"{tagName}\" | {communityTitle}","tagPageForNodeTitle":"Tag:\"{tagName}\" in \"{title}\" | {communityTitle}","name":"Tags Page","tag":"Tag: {tagName}"},"localOverride":false},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bi04Ny0xOTQ1NWk4ODNCOUNEMkFDNDZCQjI0\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bi04Ny0xOTQ1NWk4ODNCOUNEMkFDNDZCQjI0","mimeType":"image/png"},"Category:category:CrowdSRC":{"__typename":"Category","id":"category:CrowdSRC","entityType":"CATEGORY","displayId":"CrowdSRC","nodeType":"category","depth":1,"title":"CrowdSRC","shortTitle":"CrowdSRC","parent":{"__ref":"Category:category:top"},"categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:top":{"__typename":"Category","id":"category:top","displayId":"top","nodeType":"category","depth":0,"title":"Top"},"Tkb:board:codeshare":{"__typename":"Tkb","id":"board:codeshare","entityType":"TKB","displayId":"codeshare","nodeType":"board","depth":2,"conversationStyle":"TKB","title":"CodeShare","description":"Have some code. Share some code.","avatar":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bi04Ny0xOTQ1NWk4ODNCOUNEMkFDNDZCQjI0\"}"},"profileSettings":{"__typename":"ProfileSettings","language":null},"parent":{"__ref":"Category:category:CrowdSRC"},"ancestors":{"__typename":"CoreNodeConnection","edges":[{"__typename":"CoreNodeEdge","node":{"__ref":"Community:community:zihoc95639"}},{"__typename":"CoreNodeEdge","node":{"__ref":"Category:category:CrowdSRC"}}]},"userContext":{"__typename":"NodeUserContext","canAddAttachments":false,"canUpdateNode":false,"canPostMessages":false,"isSubscribed":false},"boardPolicies":{"__typename":"BoardPolicies","canPublishArticleOnCreate":{"__typename":"PolicyResult","failureReason":{"__typename":"FailureReason","message":"error.lithium.policies.forums.policy_can_publish_on_create_workflow_action.accessDenied","key":"error.lithium.policies.forums.policy_can_publish_on_create_workflow_action.accessDenied","args":[]}},"canReadNode":{"__typename":"PolicyResult","failureReason":null}},"tkbPolicies":{"__typename":"TkbPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"shortTitle":"CodeShare","tagPolicies":{"__typename":"TagPolicies","canSubscribeTagOnNode":{"__typename":"PolicyResult","failureReason":{"__typename":"FailureReason","message":"error.lithium.policies.labels.action.corenode.subscribe_labels.allow.accessDenied","key":"error.lithium.policies.labels.action.corenode.subscribe_labels.allow.accessDenied","args":[]}},"canManageTagDashboard":{"__typename":"PolicyResult","failureReason":{"__typename":"FailureReason","message":"error.lithium.policies.labels.action.corenode.admin_labels.allow.accessDenied","key":"error.lithium.policies.labels.action.corenode.admin_labels.allow.accessDenied","args":[]}}}},"CachedAsset:quilt:f5.prod:pages/tags/TagPage:board:codeshare-1743758592913":{"__typename":"CachedAsset","id":"quilt:f5.prod:pages/tags/TagPage:board:codeshare-1743758592913","value":{"id":"TagPage","container":{"id":"Common","headerProps":{"removeComponents":["community.widget.bannerWidget"],"__typename":"QuiltContainerSectionProps"},"items":[{"id":"tag-header-widget","layout":"ONE_COLUMN","bgColor":"var(--lia-bs-white)","showBorder":"BOTTOM","sectionEditLevel":"LOCKED","columnMap":{"main":[{"id":"tags.widget.TagsHeaderWidget","__typename":"QuiltComponent"}],"__typename":"OneSectionColumns"},"__typename":"OneColumnQuiltSection"},{"id":"messages-list-for-tag-widget","layout":"ONE_COLUMN","columnMap":{"main":[{"id":"messages.widget.messageListForNodeByRecentActivityWidget","props":{"viewVariant":{"type":"inline","props":{"useUnreadCount":true,"useViewCount":true,"useAuthorLogin":true,"clampBodyLines":3,"useAvatar":true,"useBoardIcon":false,"useKudosCount":true,"usePreviewMedia":true,"useTags":false,"useNode":true,"useNodeLink":true,"useTextBody":true,"truncateBodyLength":-1,"useBody":true,"useRepliesCount":true,"useSolvedBadge":true,"timeStampType":"conversation.lastPostingActivityTime","useMessageTimeLink":true,"clampSubjectLines":2}},"panelType":"divider","useTitle":false,"hideIfEmpty":false,"pagerVariant":{"type":"loadMore"},"style":"list","showTabs":true,"tabItemMap":{"default":{"mostRecent":true,"mostRecentUserContent":false,"newest":false},"additional":{"mostKudoed":true,"mostViewed":true,"mostReplies":false,"noReplies":false,"noSolutions":false,"solutions":false}}},"__typename":"QuiltComponent"}],"__typename":"OneSectionColumns"},"__typename":"OneColumnQuiltSection"}],"__typename":"QuiltContainer"},"__typename":"Quilt"},"localOverride":false},"CachedAsset:quiltWrapper:f5.prod:Common:1743758507223":{"__typename":"CachedAsset","id":"quiltWrapper:f5.prod:Common:1743758507223","value":{"id":"Common","header":{"backgroundImageProps":{"assetName":"header.jpg","backgroundSize":"COVER","backgroundRepeat":"NO_REPEAT","backgroundPosition":"LEFT_CENTER","lastModified":"1702932449000","__typename":"BackgroundImageProps"},"backgroundColor":"transparent","items":[{"id":"custom.widget.Beta_MetaNav","props":{"widgetVisibility":"signedInOrAnonymous","useTitle":true,"useBackground":false,"title":"","lazyLoad":false},"__typename":"QuiltComponent"},{"id":"community.widget.navbarWidget","props":{"showUserName":false,"showRegisterLink":true,"style":{"boxShadow":"var(--lia-bs-box-shadow-sm)","linkFontWeight":"700","controllerHighlightColor":"hsla(30, 100%, 50%)","dropdownDividerMarginBottom":"10px","hamburgerBorderHover":"none","linkFontSize":"15px","linkBoxShadowHover":"none","backgroundOpacity":0.4,"controllerBorderRadius":"var(--lia-border-radius-50)","hamburgerBgColor":"transparent","linkTextBorderBottom":"none","hamburgerColor":"var(--lia-nav-controller-icon-color)","brandLogoHeight":"48px","linkLetterSpacing":"normal","linkBgHoverColor":"transparent","collapseMenuDividerOpacity":0.16,"paddingBottom":"10px","dropdownPaddingBottom":"15px","dropdownMenuOffset":"2px","hamburgerBgHoverColor":"transparent","borderBottom":"0","hamburgerBorder":"none","dropdownPaddingX":"10px","brandMarginRightSm":"10px","linkBoxShadow":"none","linkJustifyContent":"center","linkColor":"var(--lia-bs-primary)","collapseMenuDividerBg":"var(--lia-nav-link-color)","dropdownPaddingTop":"10px","controllerHighlightTextColor":"var(--lia-yiq-dark)","background":{"imageAssetName":"","color":"var(--lia-bs-white)","size":"COVER","repeat":"NO_REPEAT","position":"CENTER_CENTER","imageLastModified":""},"linkBorderRadius":"var(--lia-bs-border-radius-sm)","linkHoverColor":"var(--lia-bs-primary)","position":"FIXED","linkBorder":"none","linkTextBorderBottomHover":"2px solid #0C5C8D","brandMarginRight":"30px","hamburgerHoverColor":"var(--lia-nav-controller-icon-color)","linkBorderHover":"none","collapseMenuMarginLeft":"20px","linkFontStyle":"NORMAL","linkPaddingX":"10px","paddingTop":"10px","linkPaddingY":"5px","linkTextTransform":"NONE","dropdownBorderColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.08)","controllerBgHoverColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.1)","linkDropdownPaddingX":"var(--lia-nav-link-px)","linkBgColor":"transparent","linkDropdownPaddingY":"9px","controllerIconColor":"#0C5C8D","dropdownDividerMarginTop":"10px","linkGap":"10px","controllerIconHoverColor":"#0C5C8D"},"links":{"sideLinks":[],"mainLinks":[{"children":[{"linkType":"INTERNAL","id":"migrated-link-1","params":{"boardId":"TechnicalForum","categoryId":"Forums"},"routeName":"ForumBoardPage"},{"linkType":"INTERNAL","id":"migrated-link-2","params":{"boardId":"WaterCooler","categoryId":"Forums"},"routeName":"ForumBoardPage"}],"linkType":"INTERNAL","id":"migrated-link-0","params":{"categoryId":"Forums"},"routeName":"CategoryPage"},{"children":[{"linkType":"INTERNAL","id":"migrated-link-4","params":{"boardId":"codeshare","categoryId":"CrowdSRC"},"routeName":"TkbBoardPage"},{"linkType":"INTERNAL","id":"migrated-link-5","params":{"boardId":"communityarticles","categoryId":"CrowdSRC"},"routeName":"TkbBoardPage"}],"linkType":"INTERNAL","id":"migrated-link-3","params":{"categoryId":"CrowdSRC"},"routeName":"CategoryPage"},{"children":[{"linkType":"INTERNAL","id":"migrated-link-7","params":{"boardId":"TechnicalArticles","categoryId":"Articles"},"routeName":"TkbBoardPage"},{"linkType":"INTERNAL","id":"article-series","params":{"boardId":"article-series","categoryId":"Articles"},"routeName":"TkbBoardPage"},{"linkType":"INTERNAL","id":"security-insights","params":{"boardId":"security-insights","categoryId":"Articles"},"routeName":"TkbBoardPage"},{"linkType":"INTERNAL","id":"migrated-link-8","params":{"boardId":"DevCentralNews","categoryId":"Articles"},"routeName":"TkbBoardPage"}],"linkType":"INTERNAL","id":"migrated-link-6","params":{"categoryId":"Articles"},"routeName":"CategoryPage"},{"children":[{"linkType":"INTERNAL","id":"migrated-link-10","params":{"categoryId":"CommunityGroups"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"migrated-link-11","params":{"categoryId":"F5-Groups"},"routeName":"CategoryPage"}],"linkType":"INTERNAL","id":"migrated-link-9","params":{"categoryId":"GroupsCategory"},"routeName":"CategoryPage"},{"children":[],"linkType":"INTERNAL","id":"migrated-link-12","params":{"boardId":"Events","categoryId":"top"},"routeName":"EventBoardPage"},{"children":[],"linkType":"INTERNAL","id":"migrated-link-13","params":{"boardId":"Suggestions","categoryId":"top"},"routeName":"IdeaBoardPage"},{"children":[],"linkType":"EXTERNAL","id":"Common-external-link","url":"https://community.f5.com/c/how-do-i","target":"SELF"}]},"className":"QuiltComponent_lia-component-edit-mode__lQ9Z6","showSearchIcon":false},"__typename":"QuiltComponent"},{"id":"community.widget.bannerWidget","props":{"backgroundColor":"transparent","visualEffects":{"showBottomBorder":false},"backgroundImageProps":{"backgroundSize":"COVER","backgroundPosition":"CENTER_CENTER","backgroundRepeat":"NO_REPEAT"},"fontColor":"#222222"},"__typename":"QuiltComponent"},{"id":"community.widget.breadcrumbWidget","props":{"backgroundColor":"var(--lia-bs-primary)","linkHighlightColor":"#FFFFFF","visualEffects":{"showBottomBorder":false},"backgroundOpacity":60,"linkTextColor":"#FFFFFF"},"__typename":"QuiltComponent"}],"__typename":"QuiltWrapperSection"},"footer":{"backgroundImageProps":{"assetName":null,"backgroundSize":"COVER","backgroundRepeat":"NO_REPEAT","backgroundPosition":"CENTER_CENTER","lastModified":null,"__typename":"BackgroundImageProps"},"backgroundColor":"var(--lia-bs-body-color)","items":[{"id":"custom.widget.Beta_Footer","props":{"widgetVisibility":"signedInOrAnonymous","useTitle":true,"useBackground":false,"title":"","lazyLoad":false},"__typename":"QuiltComponent"},{"id":"custom.widget.Tag_Manager_Helper","props":{"widgetVisibility":"signedInOrAnonymous","useTitle":true,"useBackground":false,"title":"","lazyLoad":false},"__typename":"QuiltComponent"},{"id":"custom.widget.Consent_Blackbar","props":{"widgetVisibility":"signedInOrAnonymous","useTitle":true,"useBackground":false,"title":"","lazyLoad":false},"__typename":"QuiltComponent"}],"__typename":"QuiltWrapperSection"},"__typename":"QuiltWrapper","localOverride":false},"localOverride":false},"CachedAsset:text:en_US-components/common/ActionFeedback-1743097580000":{"__typename":"CachedAsset","id":"text:en_US-components/common/ActionFeedback-1743097580000","value":{"joinedGroupHub.title":"Welcome","joinedGroupHub.message":"You are now a member of this group and are subscribed to updates.","groupHubInviteNotFound.title":"Invitation Not Found","groupHubInviteNotFound.message":"Sorry, we could not find your invitation to the group. The owner may have canceled the invite.","groupHubNotFound.title":"Group Not Found","groupHubNotFound.message":"The grouphub you tried to join does not exist. It may have been deleted.","existingGroupHubMember.title":"Already Joined","existingGroupHubMember.message":"You are already a member of this group.","accountLocked.title":"Account Locked","accountLocked.message":"Your account has been locked due to multiple failed attempts. Try again in {lockoutTime} minutes.","editedGroupHub.title":"Changes Saved","editedGroupHub.message":"Your group has been updated.","leftGroupHub.title":"Goodbye","leftGroupHub.message":"You are no longer a member of this group and will not receive future updates.","deletedGroupHub.title":"Deleted","deletedGroupHub.message":"The group has been deleted.","groupHubCreated.title":"Group Created","groupHubCreated.message":"{groupHubName} is ready to use","accountClosed.title":"Account Closed","accountClosed.message":"The account has been closed and you will now be redirected to the homepage","resetTokenExpired.title":"Reset Password Link has Expired","resetTokenExpired.message":"Try resetting your password again","invalidUrl.title":"Invalid URL","invalidUrl.message":"The URL you're using is not recognized. Verify your URL and try again.","accountClosedForUser.title":"Account Closed","accountClosedForUser.message":"{userName}'s account is closed","inviteTokenInvalid.title":"Invitation Invalid","inviteTokenInvalid.message":"Your invitation to the community has been canceled or expired.","inviteTokenError.title":"Invitation Verification Failed","inviteTokenError.message":"The url you are utilizing is not recognized. Verify your URL and try again","pageNotFound.title":"Access Denied","pageNotFound.message":"You do not have access to this area of the community or it doesn't exist","eventAttending.title":"Responded as Attending","eventAttending.message":"You'll be notified when there's new activity and reminded as the event approaches","eventInterested.title":"Responded as Interested","eventInterested.message":"You'll be notified when there's new activity and reminded as the event approaches","eventNotFound.title":"Event Not Found","eventNotFound.message":"The event you tried to respond to does not exist.","redirectToRelatedPage.title":"Showing Related Content","redirectToRelatedPageForBaseUsers.title":"Showing Related Content","redirectToRelatedPageForBaseUsers.message":"The content you are trying to access is archived","redirectToRelatedPage.message":"The content you are trying to access is archived","relatedUrl.archivalLink.flyoutMessage":"The content you are trying to access is archived View Archived Content"},"localOverride":false},"CachedAsset:component:custom.widget.Beta_MetaNav-en-1743758613204":{"__typename":"CachedAsset","id":"component:custom.widget.Beta_MetaNav-en-1743758613204","value":{"component":{"id":"custom.widget.Beta_MetaNav","template":{"id":"Beta_MetaNav","markupLanguage":"HANDLEBARS","style":null,"texts":null,"defaults":{"config":{"applicablePages":[],"description":"MetaNav menu at the top of every page.","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"components":[{"id":"custom.widget.Beta_MetaNav","form":null,"config":null,"props":[],"__typename":"Component"}],"grouping":"CUSTOM","__typename":"ComponentTemplate"},"properties":{"config":{"applicablePages":[],"description":"MetaNav menu at the top of every page.","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"form":null,"__typename":"Component","localOverride":false},"globalCss":null,"form":null},"localOverride":false},"CachedAsset:component:custom.widget.Beta_Footer-en-1743758613204":{"__typename":"CachedAsset","id":"component:custom.widget.Beta_Footer-en-1743758613204","value":{"component":{"id":"custom.widget.Beta_Footer","template":{"id":"Beta_Footer","markupLanguage":"HANDLEBARS","style":null,"texts":null,"defaults":{"config":{"applicablePages":[],"description":"DevCentral´s custom footer.","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"components":[{"id":"custom.widget.Beta_Footer","form":null,"config":null,"props":[],"__typename":"Component"}],"grouping":"CUSTOM","__typename":"ComponentTemplate"},"properties":{"config":{"applicablePages":[],"description":"DevCentral´s custom footer.","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"form":null,"__typename":"Component","localOverride":false},"globalCss":null,"form":null},"localOverride":false},"CachedAsset:component:custom.widget.Tag_Manager_Helper-en-1743758613204":{"__typename":"CachedAsset","id":"component:custom.widget.Tag_Manager_Helper-en-1743758613204","value":{"component":{"id":"custom.widget.Tag_Manager_Helper","template":{"id":"Tag_Manager_Helper","markupLanguage":"HANDLEBARS","style":null,"texts":null,"defaults":{"config":{"applicablePages":[],"description":"Helper widget to inject Tag Manager scripts into head element","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"components":[{"id":"custom.widget.Tag_Manager_Helper","form":null,"config":null,"props":[],"__typename":"Component"}],"grouping":"CUSTOM","__typename":"ComponentTemplate"},"properties":{"config":{"applicablePages":[],"description":"Helper widget to inject Tag Manager scripts into head element","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"form":null,"__typename":"Component","localOverride":false},"globalCss":null,"form":null},"localOverride":false},"CachedAsset:component:custom.widget.Consent_Blackbar-en-1743758613204":{"__typename":"CachedAsset","id":"component:custom.widget.Consent_Blackbar-en-1743758613204","value":{"component":{"id":"custom.widget.Consent_Blackbar","template":{"id":"Consent_Blackbar","markupLanguage":"HTML","style":null,"texts":null,"defaults":{"config":{"applicablePages":[],"description":"","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"components":[{"id":"custom.widget.Consent_Blackbar","form":null,"config":null,"props":[],"__typename":"Component"}],"grouping":"TEXTHTML","__typename":"ComponentTemplate"},"properties":{"config":{"applicablePages":[],"description":"","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"form":null,"__typename":"Component","localOverride":false},"globalCss":null,"form":null},"localOverride":false},"CachedAsset:text:en_US-components/community/Breadcrumb-1743097580000":{"__typename":"CachedAsset","id":"text:en_US-components/community/Breadcrumb-1743097580000","value":{"navLabel":"Breadcrumbs","dropdown":"Additional parent page navigation"},"localOverride":false},"CachedAsset:text:en_US-components/tags/TagsHeaderWidget-1743097580000":{"__typename":"CachedAsset","id":"text:en_US-components/tags/TagsHeaderWidget-1743097580000","value":{"tag":"{tagName}","topicsCount":"{count} {count, plural, one {Topic} other {Topics}}"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageListForNodeByRecentActivityWidget-1743097580000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageListForNodeByRecentActivityWidget-1743097580000","value":{"title@userScope:other":"Recent Content","title@userScope:self":"Contributions","title@board:FORUM@userScope:other":"Recent Discussions","title@board:BLOG@userScope:other":"Recent Blogs","emptyDescription":"No content to show","MessageListForNodeByRecentActivityWidgetEditor.nodeScope.label":"Scope","title@instance:1706288370055":"Content Feed","title@instance:1743095186784":"Most Recent Updates","title@instance:1704317906837":"Content Feed","title@instance:1743095018194":"Most Recent Updates","title@instance:1702668293472":"Community Feed","title@instance:1743095117047":"Most Recent Updates","title@instance:1704319314827":"Blog Feed","title@instance:1743095235555":"Most Recent Updates","title@instance:1704320290851":"My Contributions","title@instance:1703720491809":"Forum Feed","title@instance:1743095311723":"Most Recent Updates","title@instance:1703028709746":"Group Content Feed","title@instance:VTsglH":"Content Feed"},"localOverride":false},"Category:category:Forums":{"__typename":"Category","id":"category:Forums","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Forum:board:TechnicalForum":{"__typename":"Forum","id":"board:TechnicalForum","forumPolicies":{"__typename":"ForumPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Forum:board:WaterCooler":{"__typename":"Forum","id":"board:WaterCooler","forumPolicies":{"__typename":"ForumPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:Articles":{"__typename":"Category","id":"category:Articles","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Tkb:board:TechnicalArticles":{"__typename":"Tkb","id":"board:TechnicalArticles","tkbPolicies":{"__typename":"TkbPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Tkb:board:DevCentralNews":{"__typename":"Tkb","id":"board:DevCentralNews","tkbPolicies":{"__typename":"TkbPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:GroupsCategory":{"__typename":"Category","id":"category:GroupsCategory","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:F5-Groups":{"__typename":"Category","id":"category:F5-Groups","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:CommunityGroups":{"__typename":"Category","id":"category:CommunityGroups","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Occasion:board:Events":{"__typename":"Occasion","id":"board:Events","boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"occasionPolicies":{"__typename":"OccasionPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Idea:board:Suggestions":{"__typename":"Idea","id":"board:Suggestions","boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"ideaPolicies":{"__typename":"IdeaPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Tkb:board:communityarticles":{"__typename":"Tkb","id":"board:communityarticles","tkbPolicies":{"__typename":"TkbPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Tkb:board:security-insights":{"__typename":"Tkb","id":"board:security-insights","tkbPolicies":{"__typename":"TkbPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Tkb:board:article-series":{"__typename":"Tkb","id":"board:article-series","tkbPolicies":{"__typename":"TkbPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Conversation:conversation:331689":{"__typename":"Conversation","id":"conversation:331689","topic":{"__typename":"TkbTopicMessage","uid":331689},"lastPostingActivityTime":"2025-03-28T00:40:57.103-07:00","solved":false},"User:user:313555":{"__typename":"User","uid":313555,"login":"Won-Soo","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/m_assets/avatars/custom/Frankenstack_01-1706132194138.svg?time=1706132284000"},"id":"user:313555"},"TkbTopicMessage:message:331689":{"__typename":"TkbTopicMessage","subject":"Proxy Protocol v2 Initiator","conversation":{"__ref":"Conversation:conversation:331689"},"id":"message:331689","revisionNum":1,"uid":331689,"depth":0,"board":{"__ref":"Tkb:board:codeshare"},"author":{"__ref":"User:user:313555"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":495},"postTime":"2024-07-16T18:49:22.067-07:00","lastPublishTime":"2024-07-16T18:49:22.067-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Problem this snippet solves: \n Proxy Protocol v1 related articles have already been posted on DevCentral, but there is no v2 support iRule code available. A customer wanted to support Proxy Protocol v2, so I wrote an iRule code for supporting v2. \n \n Proxy protocol for the BIG-IP (f5.com) \n \n How to use this snippet: \n Back-end server must handle Proxy header prior data exchange. \n Code : \n when CLIENT_ACCEPTED {\n\t# DEBUG On/Off \n\tset DEBUG 0\n\n\tset v2_proxy_header \"0d0a0d0a000d0a515549540a\"\n\t\n\t# v2 version and command : 0x21 - version 2 & PROXY command\n\tset v2_ver_command \"21\"\n\n\t# v2 address family and transport protocol : 0x11 - AF_INET (IPv4) & TCP protocol\n\tset v2_af_tp \"11\"\n\n\t# v2 Address Size : 0x000C - 12 bytes for IPv4 + TCP \n\tset v2_address_length \"000c\"\n\n\t# Get TCP port - 2 byte hexadecimal format\n\tset src_port [format \"%04x\" [TCP::client_port]]\n\tset dst_port [format \"%04x\" [TCP::local_port]]\n\n\t# Get Src Address and convert to 4 byte hexadecimal format\n\tforeach val [split [IP::client_addr] \".\"] {\n\t\tappend src_addr [format \"%02x\" $val]\n\t}\n\n\t# Get Dst Address and convert to 4 byte hexadecimal format\n\tforeach val [split [IP::local_addr] \".\"] {\n\t\tappend dst_addr [format \"%02x\" $val]\n\t}\n\n\t# Build proxy v2 data\n\tset proxy_data [binary format H* \"${v2_proxy_header}${v2_ver_command}${v2_af_tp}${v2_address_length}${src_addr}${dst_addr}${src_port}${dst_port}\"]\n\n\tif { $DEBUG } {\n\t\tbinary scan $proxy_data H* proxy_dump\n\t\tlog local0. \"[IP::client_addr]:[TCP::client_port]_[IP::local_addr]:[TCP::local_port] - proxy_data dump : $proxy_dump\"\n\t}\n}\n\nwhen SERVER_CONNECTED {\n\tTCP::respond $proxy_data\n} \n ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"1644","kudosSumWeight":2,"repliesCount":1,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}}},"Conversation:conversation:288311":{"__typename":"Conversation","id":"conversation:288311","topic":{"__typename":"TkbTopicMessage","uid":288311},"lastPostingActivityTime":"2025-02-21T07:28:02.936-08:00","solved":false},"User:user:278861":{"__typename":"User","uid":278861,"login":"Daniel_Tavernie","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/m_assets/avatars/default/avatar-12.svg?time=0"},"id":"user:278861"},"TkbTopicMessage:message:288311":{"__typename":"TkbTopicMessage","subject":"F5 iApp Automated Backup","conversation":{"__ref":"Conversation:conversation:288311"},"id":"message:288311","revisionNum":2,"uid":288311,"depth":0,"board":{"__ref":"Tkb:board:codeshare"},"author":{"__ref":"User:user:278861"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":21825},"postTime":"2018-01-24T15:35:17.000-08:00","lastPublishTime":"2022-02-15T13:09:52.083-08:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Problem this snippet solves: \n This is now available on GitHub! \n Please look on GitHub for the latest version, and submit any bugs or questions as an \"Issue\" on GitHub: \n (Note: DevCentral admin update - Daniel's project appears abandoned so it's been forked and updated to the link below. @damnski on github added some SFTP code that has been merged in as well.) \n https://github.com/f5devcentral/f5-automated-backup-iapp \n Intro \n Building on the significant work of Thomas Schockaert (and several other DevCentralites) I enhanced many aspects I needed for my own purposes, updated many things I noticed requested on the forums, and added additional documentation and clarification. As you may see in several of my comments on the original posts, I iterated through several 2.2.x versions and am now releasing v3.0.0. Below is the breakdown! \n Also, I have done quite a bit of testing (mostly on v13.1.0.1 lately) and I doubt I've caught everything, especially with all of the changes. Please post any questions or issues in the comments. \n Cheers! \n Daniel Tavernier (tabernarious) \n Related posts: \n \n Git Repository for f5-automated-backup-iapp (https://github.com/tabernarious/f5-automated-backup-iapp) \n https://community.f5.com/t5/technical-articles/f5-automated-backups-the-right-way/ta-p/288454 \n https://community.f5.com/t5/crowdsrc/complete-f5-automated-backup-solution/ta-p/288701 \n https://community.f5.com/t5/crowdsrc/complete-f5-automated-backup-solution-2/ta-p/274252 \n https://community.f5.com/t5/technical-forum/automated-backup-solution/m-p/24551 \n https://community.f5.com/t5/crowdsrc/tkb-p/CrowdSRC \n \n v3.2.1 (20201210) \n \n Merged v3.1.11 and v3.2.0 for explicit SFTP support (separate from SCP). \n Tweaked the SCP and SFTP upload directory handling; detailed instructions are in the iApp. \n Tested on 13.1.3.4 and 14.1.3 \n \n v3.1.11 (20201210) \n \n Better handling of UCS passphrases, and notes about characters to avoid. \n I successfully tested this exact passphrase in the 13.1.3.4 CLI (surrounded with single quote) and GUI (as-is): `~!@#$%^*()aB1-_=+[{]}:./? \n I successfully tested this exact passphrase in 14.1.3 (square-braces and curly-braces would not work): `~!@#$%^*()aB1-_=+:./? \n Though there may be situations these could work, avoid these characters (separated by spaces): \" ' & | ; < > \\ [ ] { } , \n Moved changelog and notes from the template to CHANGELOG.md and README.md. \n Replaced all tabs (\\t) with four spaces. \n \n v3.1.10 (20201209) \n \n Added SMB Version and SMB Security options to support v14+ and newer versions of Microsoft Windows and Windows Server. \n Tested SMB/CIFS on 13.1.3.4 and 14.1.3 against Windows Server 2019 using \"2.0\" and \"ntlmsspi\" \n \n v3.1.0: \n \n Removed \"app-service none\" from iCall objects. The iCall objects are now created as part of the Application Service (iApp) and are properly cleaned up if the iApp is redeployed or deleted. \n Reasonably tested on 11.5.4 HF2 (SMB worked fine using \"mount -t cifs\") and altered requires-bigip-version-min to match. \n Fixing error regarding \"script did not successfully complete: (can't read \"::destination_parameters__protocol_enable\": no such variable\" by encompassing most of the \"implementation\" in a block that first checks $::backup_schedule__frequency_select for \"Disable\". \n Added default value to \"filename format\". \n Changed UCS default value for $backup_file_name_extension to \".ucs\" and added $fname_noext. \n Removed old SFTP sections and references (now handled through SCP/SFTP). \n Adjusted logging: added \"sleep 1\" to ensure proper logging; added $backup_directory to log message. \n Adjusted some help messages. \n \n New v3.0.0 features: \n \n Supports multiple instances! (Deploy multiple copies of the iApp to save backups to different places or perhaps to keep daily backups locally and send weekly backups to a network drive.) \n Fully ConfigSync compatible! (Encrypted values now in $script instead of local file.) \n Long passwords supported! (Using \"-A\" with openssl which reads/writes base64 encoded strings as a single line.) \n Added $script error checking for all remote backup types! (Using 'catch' to prevent tcl errors when $script aborts.) \n Backup files are cleaned up after any $script errors due to new error checking. \n Added logging! (Run logs sent to '/var/log/ltm' via logger command which is compatible with BIG-IP Remote Logging configuration (syslog). Run logs AND errors sent to '/var/tmp/scriptd.out'. Errors may include plain-text passwords which should not be in /var/log/ltm or syslog.) \n Added custom cipher option for SCP! (In case BIG-IP and the destination server are not cipher-compatible out of the box.) \n Added StrictHostKeyChecking=no option. (This is insecure and should only be used for testing--lots of warnings.) \n Combined SCP and SFTP because they are both using SCP to perform the remote copy. (Easier to maintain!) \n \n Original v1.x.x and v2.x.x features kept (copied from an original post): \n \n It allows you to choose between both UCS or SCF as backup-types. (whilst providing ample warnings about SCF not being a very good restore-option due to the incompleteness in some cases) \n It allows you to provide a passphrase for the UCS archives (the standard GUI also does this, so the iApp should too) \n It allows you to not include the private keys (same thing: standard GUI does it, so the iApp does it too) \n It allows you to set a Backup Schedule for every X minutes/hours/days/weeks/months or a custom selection of days in the week \n It allows you to set the exact time, minute of the hour, day of the week or day of the month when the backup should be performed (depending on the usefulness with regards to the schedule type) \n It allows you to transfer the backup files to external devices using 4 different protocols, next to providing local storage on the device itself \n SCP (username/private key without password) \n SFTP (username/private key without password) \n FTP (username/password) \n SMB (now using TMOS v12.x.x compatible 'mount -t cifs', with username/password) \n Local Storage (/var/local/ucs or /var/local/scf) \n It stores all passwords and private keys in a secure fashion: encrypted by the master key of the unit (f5mku), rendering it safe to store the backups, including the credentials off-box \n It has a configurable automatic pruning function for the Local Storage option, so the disk doesn't fill up (i.e. keep last X backup files) \n It allows you to configure the filename using the date/time wildcards from the tcl [clock] command, as well as providing a variable to include the hostname \n It requires only the WebGUI to establish the configuration you desire \n It allows you to disable the processes for automated backup, without you having to remove the Application Service or losing any previously entered settings \n For the external shellscripts it automatically generates, the credentials are stored in encrypted form (using the master key) \n It allows you to no longer be required to make modifications on the linux command line to get your automated backups running after an RMA or restore operation \n It cleans up after itself, which means there are no extraneous shellscripts or status files lingering around after the scripts execute \n \n How to use this snippet: \n \n Find and download the latest iApp template on GitHub (e.g \"f5.automated_backup.v3.2.1.tmpl.tcl\"). \n Import the text file as an iApp Template in the BIG-IP GUI. \n Create an Application Service using the imported Template. \n Answer the questions (paying close attention to the help sections). \n Check /var/tmp/scriptd.out for general logs and errors. \n \n Tested this on version: \n 16.0 ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"7668","kudosSumWeight":5,"repliesCount":102,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}}},"Conversation:conversation:281983":{"__typename":"Conversation","id":"conversation:281983","topic":{"__typename":"TkbTopicMessage","uid":281983},"lastPostingActivityTime":"2025-01-22T21:53:02.801-08:00","solved":false},"User:user:58212":{"__typename":"User","uid":58212,"login":"jaikumar_f5","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/m_assets/avatars/default/avatar-11.svg?time=0"},"id":"user:58212"},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODE5ODMtMTUyOTZpODJCODQ1MUI3RThBNzExNw?revision=4\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0yODE5ODMtMTUyOTZpODJCODQ1MUI3RThBNzExNw?revision=4","title":"0151T000002dhuTQAQ.png","associationType":"BODY","width":1571,"height":292,"altText":null},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODE5ODMtMTA4NDFpRDgyNDhCQjk3MTU5NkYyRQ?revision=4\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0yODE5ODMtMTA4NDFpRDgyNDhCQjk3MTU5NkYyRQ?revision=4","title":"0151T000002dhuUQAQ.png","associationType":"BODY","width":1497,"height":291,"altText":null},"TkbTopicMessage:message:281983":{"__typename":"TkbTopicMessage","subject":"Export Virtual Server Configuration in CSV - tmsh cli script","conversation":{"__ref":"Conversation:conversation:281983"},"id":"message:281983","revisionNum":4,"uid":281983,"depth":0,"board":{"__ref":"Tkb:board:codeshare"},"author":{"__ref":"User:user:58212"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":9113},"postTime":"2020-05-02T19:41:18.000-07:00","lastPublishTime":"2023-10-24T07:42:47.195-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Problem this snippet solves: \n This is a simple cli script used to collect all the virtuals name, its VIP details, Pool names, members, all Profiles, Irules, persistence associated to each, in all partitions. A sample output would be like below, \n \n One can customize the code to extract other fields available too. The same logic can be allowed to pull information's from profiles stats, certificates etc. \n \n Update: 5th Oct 2020 \n \n Added Pool members capture in the code. After the Pool-Name, Pool-Members column will be found. \n If a pool does not have members - field not present: \"members\" will shown in the respective Pool-Members column. \n If a pool itself is not bound to the VS, then Pool-Name, Pool-Members will have none in the respective columns. \n \n Update: 21st Jan 2021 \n \n Added logic to look for multiple partitions & collect configs \n \n Update: 12th Feb 2021 \n \n Added logic to add persistence to sheet. \n \n Update: 26th May 2021 \n \n Added logic to add state & status to sheet. \n \n Update: 24th Oct 2023 \n Added logic to add hostname, Pool Status, Total-Connections & Current-Connections. \n Note: The codeshare has multiple version, use the latest version alone. The reason to keep the other versions is for end users to understand & compare, thus helping them to modify to their own requirements. Hope it helps. \n \n How to use this snippet: \n Login to the LTM, create your script by running the below commands and paste the code provided in snippet \n \n tmsh create cli script virtual-details \n \n So when you list it, it should look something like below, \n \n [admin@labltm:Active:Standalone] ~ # tmsh list cli script virtual-details\ncli script virtual-details {\nproc script::run {} {\n puts \"Virtual Server,Destination,Pool-Name,Profiles,Rules\"\n foreach { obj } [tmsh::get_config ltm virtual all-properties] {\n set profiles [tmsh::get_field_value $obj \"profiles\"]\n set remprof [regsub -all {\\n} [regsub -all \" context\" [join $profiles \"\\n\"] \"context\"] \" \"]\n set profilelist [regsub -all \"profiles \" $remprof \"\"]\n puts \"[tmsh::get_name $obj],[tmsh::get_field_value $obj \"destination\"],[tmsh::get_field_value $obj \"pool\"],$profilelist,[tmsh::get_field_value $obj \"rules\"]\"\n }\n}\n total-signing-status not-all-signed\n}\n[admin@labltm:Active:Standalone] ~ # \n \n \n And you can run the script like below, \n tmsh run cli script virtual-details > /var/tmp/virtual-details.csv \n \n And get the output from the saved file, \n cat /var/tmp/virtual-details.csv \n \n Old Codes: \n cli script virtual-details {\nproc script::run {} {\n puts \"Virtual Server,Destination,Pool-Name,Profiles,Rules\"\n foreach { obj } [tmsh::get_config ltm virtual all-properties] {\n set profiles [tmsh::get_field_value $obj \"profiles\"]\n set remprof [regsub -all {\\n} [regsub -all \" context\" [join $profiles \"\\n\"] \"context\"] \" \"]\n set profilelist [regsub -all \"profiles \" $remprof \"\"]\n puts \"[tmsh::get_name $obj],[tmsh::get_field_value $obj \"destination\"],[tmsh::get_field_value $obj \"pool\"],$profilelist,[tmsh::get_field_value $obj \"rules\"]\"\n }\n}\n total-signing-status not-all-signed\n}\n\n###===================================================\n###2.0\n###UPDATED CODE BELOW\n### DO NOT MIX ABOVE CODE & BELOW CODE TOGETHER\n###===================================================\n\ncli script virtual-details {\nproc script::run {} {\n puts \"Virtual Server,Destination,Pool-Name,Pool-Members,Profiles,Rules\"\n foreach { obj } [tmsh::get_config ltm virtual all-properties] {\n set poolname [tmsh::get_field_value $obj \"pool\"]\n set profiles [tmsh::get_field_value $obj \"profiles\"]\n set remprof [regsub -all {\\n} [regsub -all \" context\" [join $profiles \"\\n\"] \"context\"] \" \"]\n set profilelist [regsub -all \"profiles \" $remprof \"\"]\n if { $poolname != \"none\" }{\n set poolconfig [tmsh::get_config /ltm pool $poolname]\n foreach poolinfo $poolconfig {\n if { [catch { set member_name [tmsh::get_field_value $poolinfo \"members\" ]} err] } {\n set pool_member $err\n puts \"[tmsh::get_name $obj],[tmsh::get_field_value $obj \"destination\"],$poolname,$pool_member,$profilelist,[tmsh::get_field_value $obj \"rules\"]\"\n } else {\n set pool_member \"\"\n set member_name [tmsh::get_field_value $poolinfo \"members\" ]\n foreach member $member_name {\n append pool_member \"[lindex $member 1] \"\n }\n puts \"[tmsh::get_name $obj],[tmsh::get_field_value $obj \"destination\"],$poolname,$pool_member,$profilelist,[tmsh::get_field_value $obj \"rules\"]\"\n }\n }\n } else {\n puts \"[tmsh::get_name $obj],[tmsh::get_field_value $obj \"destination\"],$poolname,none,$profilelist,[tmsh::get_field_value $obj \"rules\"]\"\n }\n }\n}\n total-signing-status not-all-signed\n}\n\n\n###===================================================\n### Version 3.0\n### UPDATED CODE BELOW FOR MULTIPLE PARTITION \n### DO NOT MIX ABOVE CODE & BELOW CODE TOGETHER\n###===================================================\ncli script virtual-details {\nproc script::run {} {\n puts \"Partition,Virtual Server,Destination,Pool-Name,Pool-Members,Profiles,Rules\"\n foreach all_partitions [tmsh::get_config auth partition] {\n set partition \"[lindex [split $all_partitions \" \"] 2]\"\n tmsh::cd /$partition\n foreach { obj } [tmsh::get_config ltm virtual all-properties] {\n set poolname [tmsh::get_field_value $obj \"pool\"]\n set profiles [tmsh::get_field_value $obj \"profiles\"]\n set remprof [regsub -all {\\n} [regsub -all \" context\" [join $profiles \"\\n\"] \"context\"] \" \"]\n set profilelist [regsub -all \"profiles \" $remprof \"\"]\n if { $poolname != \"none\" }{\n set poolconfig [tmsh::get_config /ltm pool $poolname]\n foreach poolinfo $poolconfig {\n if { [catch { set member_name [tmsh::get_field_value $poolinfo \"members\" ]} err] } {\n set pool_member $err\n puts \"$partition,[tmsh::get_name $obj],[tmsh::get_field_value $obj \"destination\"],$poolname,$pool_member,$profilelist,[tmsh::get_field_value $obj \"rules\"]\"\n } else {\n set pool_member \"\"\n set member_name [tmsh::get_field_value $poolinfo \"members\" ]\n foreach member $member_name {\n append pool_member \"[lindex $member 1] \"\n }\n puts \"$partition,[tmsh::get_name $obj],[tmsh::get_field_value $obj \"destination\"],$poolname,$pool_member,$profilelist,[tmsh::get_field_value $obj \"rules\"]\"\n }\n }\n } else {\n puts \"$partition,[tmsh::get_name $obj],[tmsh::get_field_value $obj \"destination\"],$poolname,none,$profilelist,[tmsh::get_field_value $obj \"rules\"]\"\n }\n }\n }\n}\n total-signing-status not-all-signed\n}\n\n###===================================================\n### Version 4.0\n### UPDATED CODE BELOW FOR CAPTURING PERSISTENCE\n### DO NOT MIX ABOVE CODE & BELOW CODE TOGETHER\n###===================================================\ncli script virtual-details {\nproc script::run {} {\n puts \"Partition,Virtual Server,Destination,Pool-Name,Pool-Members,Profiles,Rules,Persist\"\n foreach all_partitions [tmsh::get_config auth partition] {\n set partition \"[lindex [split $all_partitions \" \"] 2]\"\n tmsh::cd /$partition\n foreach { obj } [tmsh::get_config ltm virtual all-properties] {\n set poolname [tmsh::get_field_value $obj \"pool\"]\n set profiles [tmsh::get_field_value $obj \"profiles\"]\n set remprof [regsub -all {\\n} [regsub -all \" context\" [join $profiles \"\\n\"] \"context\"] \" \"]\n set profilelist [regsub -all \"profiles \" $remprof \"\"]\n\t\t\tset persist [lindex [lindex [tmsh::get_field_value $obj \"persist\"] 0] 1]\n\t\t\tif { $poolname != \"none\" }{\n set poolconfig [tmsh::get_config /ltm pool $poolname]\n foreach poolinfo $poolconfig {\n if { [catch { set member_name [tmsh::get_field_value $poolinfo \"members\" ]} err] } {\n set pool_member $err\n puts \"$partition,[tmsh::get_name $obj],[tmsh::get_field_value $obj \"destination\"],$poolname,$pool_member,$profilelist,[tmsh::get_field_value $obj \"rules\"],$persist\"\n } else {\n set pool_member \"\"\n set member_name [tmsh::get_field_value $poolinfo \"members\" ]\n foreach member $member_name {\n append pool_member \"[lindex $member 1] \"\n }\n puts \"$partition,[tmsh::get_name $obj],[tmsh::get_field_value $obj \"destination\"],$poolname,$pool_member,$profilelist,[tmsh::get_field_value $obj \"rules\"],$persist\"\n }\n }\n } else {\n puts \"$partition,[tmsh::get_name $obj],[tmsh::get_field_value $obj \"destination\"],$poolname,none,$profilelist,[tmsh::get_field_value $obj \"rules\"],$persist\"\n }\n }\n }\n}\n total-signing-status not-all-signed\n}\n\n###===================================================\n### 5.0\n### UPDATED CODE BELOW\n### DO NOT MIX ABOVE CODE & BELOW CODE TOGETHER\n###===================================================\ncli script virtual-details {\nproc script::run {} {\nputs \"Partition,Virtual Server,Destination,Pool-Name,Pool-Members,Profiles,Rules,Persist,Status,State\"\nforeach all_partitions [tmsh::get_config auth partition] {\nset partition \"[lindex [split $all_partitions \" \"] 2]\"\ntmsh::cd /$partition\nforeach { obj } [tmsh::get_config ltm virtual all-properties] {\nforeach { status } [tmsh::get_status ltm virtual [tmsh::get_name $obj]] {\nset vipstatus [tmsh::get_field_value $status \"status.availability-state\"]\nset vipstate [tmsh::get_field_value $status \"status.enabled-state\"]\n}\nset poolname [tmsh::get_field_value $obj \"pool\"]\nset profiles [tmsh::get_field_value $obj \"profiles\"]\nset remprof [regsub -all {\\n} [regsub -all \" context\" [join $profiles \"\\n\"] \"context\"] \" \"]\nset profilelist [regsub -all \"profiles \" $remprof \"\"]\nset persist [lindex [lindex [tmsh::get_field_value $obj \"persist\"] 0] 1]\nif { $poolname != \"none\" }{\nset poolconfig [tmsh::get_config /ltm pool $poolname]\nforeach poolinfo $poolconfig {\nif { [catch { set member_name [tmsh::get_field_value $poolinfo \"members\" ]} err] } {\nset pool_member $err\nputs \"$partition,[tmsh::get_name $obj],[tmsh::get_field_value $obj \"destination\"],$poolname,$pool_member,$profilelist,[tmsh::get_field_value $obj \"rules\"],$persist,$vipstatus,$vipstate\"\n} else {\nset pool_member \"\"\nset member_name [tmsh::get_field_value $poolinfo \"members\" ]\nforeach member $member_name {\nappend pool_member \"[lindex $member 1] \"\n}\nputs \"$partition,[tmsh::get_name $obj],[tmsh::get_field_value $obj \"destination\"],$poolname,$pool_member,$profilelist,[tmsh::get_field_value $obj \"rules\"],$persist,$vipstatus,$vipstate\"\n}\n}\n} else {\nputs \"$partition,[tmsh::get_name $obj],[tmsh::get_field_value $obj \"destination\"],$poolname,none,$profilelist,[tmsh::get_field_value $obj \"rules\"],$persist,$vipstatus,$vipstate\"\n}\n}\n}\n}\ntotal-signing-status not-all-signed\n} \n Latest Code: \n \n cli script virtual-details {\nproc script::run {} {\nset hostconf [tmsh::get_config /sys global-settings hostname]\nset hostname [tmsh::get_field_value [lindex $hostconf 0] hostname]\nputs \"Hostname,Partition,Virtual Server,Destination,Pool-Name,Pool-Status,Pool-Members,Profiles,Rules,Persist,Status,State,Total-Conn,Current-Conn\"\nforeach all_partitions [tmsh::get_config auth partition] {\nset partition \"[lindex [split $all_partitions \" \"] 2]\"\ntmsh::cd /$partition\nforeach { obj } [tmsh::get_config ltm virtual all-properties] {\nforeach { status } [tmsh::get_status ltm virtual [tmsh::get_name $obj]] {\nset vipstatus [tmsh::get_field_value $status \"status.availability-state\"]\nset vipstate [tmsh::get_field_value $status \"status.enabled-state\"]\nset total_conn [tmsh::get_field_value $status \"clientside.tot-conns\"]\nset curr_conn [tmsh::get_field_value $status \"clientside.cur-conns\"]\n}\nset poolname [tmsh::get_field_value $obj \"pool\"]\nset profiles [tmsh::get_field_value $obj \"profiles\"]\nset remprof [regsub -all {\\n} [regsub -all \" context\" [join $profiles \"\\n\"] \"context\"] \" \"]\nset profilelist [regsub -all \"profiles \" $remprof \"\"]\nset persist [lindex [lindex [tmsh::get_field_value $obj \"persist\"] 0] 1]\nif { $poolname != \"none\" }{\nforeach { p_status } [tmsh::get_status ltm pool $poolname] {\nset pool_status [tmsh::get_field_value $p_status \"status.availability-state\"]\n}\nset poolconfig [tmsh::get_config /ltm pool $poolname]\nforeach poolinfo $poolconfig {\nif { [catch { set member_name [tmsh::get_field_value $poolinfo \"members\" ]} err] } {\nset pool_member $err\nputs \"$hostname,$partition,[tmsh::get_name $obj],[tmsh::get_field_value $obj \"destination\"],$poolname,$pool_status,$pool_member,$profilelist,[tmsh::get_field_value $obj \"rules\"],$persist,$vipstatus,$vipstate,$total_conn,$curr_conn\"\n} else {\nset pool_member \"\"\nset member_name [tmsh::get_field_value $poolinfo \"members\" ]\nforeach member $member_name {\nappend pool_member \"[lindex $member 1] \"\n}\nputs \"$hostname,$partition,[tmsh::get_name $obj],[tmsh::get_field_value $obj \"destination\"],$poolname,$pool_status,$pool_member,$profilelist,[tmsh::get_field_value $obj \"rules\"],$persist,$vipstatus,$vipstate,$total_conn,$curr_conn\"\n}\n}\n} else {\nputs \"$hostname,$partition,[tmsh::get_name $obj],[tmsh::get_field_value $obj \"destination\"],$poolname,none,none,$profilelist,[tmsh::get_field_value $obj \"rules\"],$persist,$vipstatus,$vipstate,$total_conn,$curr_conn\"\n}\n}\n}\n}\n} \n \n \n Tested this on version: \n 13.0 \n \n ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"14308","kudosSumWeight":9,"repliesCount":26,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDE","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODE5ODMtMTUyOTZpODJCODQ1MUI3RThBNzExNw?revision=4\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDI","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODE5ODMtMTA4NDFpRDgyNDhCQjk3MTU5NkYyRQ?revision=4\"}"}}],"totalCount":2,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}}},"Conversation:conversation:288887":{"__typename":"Conversation","id":"conversation:288887","topic":{"__typename":"TkbTopicMessage","uid":288887},"lastPostingActivityTime":"2025-01-09T05:35:13.957-08:00","solved":false},"User:user:172159":{"__typename":"User","uid":172159,"login":"Leon_Seng","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/images/dS0xNzIxNTktMjA5NDNpQTcyQThGQzE5NUQ0MzZFMg"},"id":"user:172159"},"TkbTopicMessage:message:288887":{"__typename":"TkbTopicMessage","subject":"TACACS+ External Monitor (Python)","conversation":{"__ref":"Conversation:conversation:288887"},"id":"message:288887","revisionNum":2,"uid":288887,"depth":0,"board":{"__ref":"Tkb:board:codeshare"},"author":{"__ref":"User:user:172159"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":1268},"postTime":"2021-09-15T16:22:58.000-07:00","lastPublishTime":"2025-01-09T05:35:13.957-08:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Problem this snippet solves: \n This script is an external monitor for TACACS+ that simulates a TACACS+ client authenticating a test user, and marks the status of a pool member as up if the authentication is successful. If the connection is down/times out, or the authentication fails due to invalid account settings, the script marks the pool member status as down. \n \n This is heavily inspired by the Radius External Monitor (Python) by AlanTen. \n How to use this snippet: \n Prerequisite \n \n This script uses the TACACS+ Python client by Ansible (tested on version 2.6). \n \n \n Create the directory /config/eav/tacacs_plus on BIG-IP \n Copy all contents from tacacs_plus package into /config/eav/tacacs_plus. \n \n \n You may also need to download six.py from https://raw.githubusercontent.com/benjaminp/six/master/six.py and place it in /config/eav/tacacs_plus. \n You will need to have a test account provisioned on the TACACS+ server for the script to perform authentication. \n \n \n Installation \n On BIG-IP, import the code snippet below as an External Monitor Program File. \n \n Monitor Configuration \n Set up an External monitor with the imported file, and configure it with the following environment variables: \n \n KEY: TACACS+ server secret \n USER: Username for test account \n PASSWORD: Password for test account \n MOD_PATH: Path to location of Python package tacacs_plus, default: /config/eav \n TIMEOUT: Duration to wait for connectivity to TACACS server to be established, default: 3 \n \n Troubleshooting \n SSH to BIG-IP and run the script locally \n $ cd /config/filestore/files_d/Common_d/external_monitor_d/\n\n# Get name of uploaded file, e.g.:\n$ ls -la\n...\n-rwxr-xr-x. 1 tomcat tomcat 1883 2021-09-17 04:05 :Common:tacacs-monitor_39568_7\n\n# Run the script with the corresponding variables\n$ KEY=<my_tacacs_key> USER=<testuser> PASSWORD=<supersecure> python <external program file, e.g.:Common:tacacs-monitor_39568_7> <TACACS+ server IP> <TACACS+ server port>\n \n \n Code : \n #!/usr/bin/env python\n#\n# Filename : tacacs_plus_mon.py\n# Author : Leon Seng\n# Version : 1.2\n# Date : 2021/09/21\n# Python ver: 2.6+\n# F5 version: 12.1+\n# \n# ========== Installation\n# Import this script via GUI:\n# System > File Management > External Monitor Program File List > Import...\n# Name it however you want.\n# Get, modify and copy the following modules:\n\n# ========== Required modules\n# -- six --\n# https://pypi.org/project/six/\n# Copy six.py into /config/eav\n#\n# -- tacacs_plus --\n# https://pypi.org/project/tacacs_plus/ | https://github.com/ansible/tacacs_plus\n# Copy tacacs_plus directory into /config/eav\n\n# ========== Environment Variables\n# NODE_IP - Supplied by F5 monitor as first argument\n# NODE_PORT - Supplied by F5 monitor as second argument\n# KEY - TACACS+ server secret\n# USER - Username for test account\n# PASSWORD - Password for test account\n# MOD_PATH - Path to location of Python package tacacs_plus, default: /config/eav\n# TIMEOUT - Duration to wait for connectivity to TACACS server to be established, default: 3\n\nimport os\nimport socket\nimport sys\n\nif os.environ.get('MOD_PATH'):\n sys.path.append(os.environ.get('MOD_PATH'))\nelse:\n sys.path.append('/config/eav')\n\n# https://github.com/ansible/tacacs_plus\nfrom tacacs_plus.client import TACACSClient\n\nnode_ip = sys.argv[1]\nnode_port = int(sys.argv[2])\nkey = os.environ.get(\"KEY\")\nuser = os.environ.get(\"USER\")\npassword = os.environ.get(\"PASSWORD\")\ntimeout = int(os.environ.get(\"TIMEOUT\", 3))\n\n# Determine if node IP is IPv4 or IPv6\nfamily = None\ntry:\n socket.inet_pton(socket.AF_INET, node_ip)\n family = socket.AF_INET\nexcept socket.error: # not a valid address\n try:\n socket.inet_pton(socket.AF_INET6, node_ip)\n family = socket.AF_INET6\n except socket.error:\n sys.exit(1)\n\n# Authenticate against TACACS server\nclient = TACACSClient(node_ip, node_port, key, timeout=timeout, family=family)\ntry:\n auth = client.authenticate(user, password)\n if auth.valid:\n print \"up\"\nexcept socket.error:\n # EAV script marks node as DOWN when no output is present\n pass \n Tested this on version: \n 12.1 ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"4351","kudosSumWeight":1,"repliesCount":0,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}}},"Conversation:conversation:280706":{"__typename":"Conversation","id":"conversation:280706","topic":{"__typename":"TkbTopicMessage","uid":280706},"lastPostingActivityTime":"2024-12-04T01:11:59.356-08:00","solved":false},"User:user:84431":{"__typename":"User","uid":84431,"login":"Dario_Garrido","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/m_assets/avatars/default/avatar-9.svg?time=0"},"id":"user:84431"},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODA3MDYtNjIxN2kzRURDRkI2QTNCRDFFMkMy?revision=1\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0yODA3MDYtNjIxN2kzRURDRkI2QTNCRDFFMkMy?revision=1","title":"0151T000003d9F7QAI.jpg","associationType":"BODY","width":501,"height":311,"altText":null},"TkbTopicMessage:message:280706":{"__typename":"TkbTopicMessage","subject":"Especial Load Balancing Active-Passive Scenario (I)","conversation":{"__ref":"Conversation:conversation:280706"},"id":"message:280706","revisionNum":1,"uid":280706,"depth":0,"board":{"__ref":"Tkb:board:codeshare"},"author":{"__ref":"User:user:84431"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":2483},"postTime":"2019-03-14T11:07:52.000-07:00","lastPublishTime":"2019-03-14T11:07:52.000-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Problem this snippet solves: This code was written to solve this issue \n REF - https://devcentral.f5.com/s/feed/0D51T00006i7jWpSAI \n \n Specification: \n 2 clusters with 2 nodes each one. each cluster will be served as active-passive method. each node in the cluster will be served as round robin. when a cluster changes to active, it will keep this status although the initial active cluster change back to up status. Only one BIG-IP device. \n There are many topics suggesting to use \"Manual Resume\" trying to goal this specifications, but this requires to manually restore each node when is back online. My initial idea was to have an unattended virtual server. \n To do so, I use a combination of persistence and an internal virtual server loadbalancing (Vip-targeting-Vip in the same device). How to use this snippet: This scenario is composed by the next set of objects: \n 4 nodes (Node1, Node2, Node3, Node4) 1 additional node called \"internal_node\" (which represents the VIP used on VIP-Targeting-VIP) 2 pools called \"ClusterA_pool\" and \"ClusterB_pool\" (which points to each pair of nodes) 1 additional pool called \"MyPool\" (which points the two internal VIP) 2 virtual servers called \"ClusterA_vs\" and \"ClusterB_vs\" (which use RoundRobin to the pools of the same name) 1 virtual server called \"MyVS\" (which is the visible VS and points to \"MyPool\") \n By the way, I use a \"Slow Ramp Time\" of 0 to reduce the failover time. \n Following you can find an example of configuration: ----------------- \n ltm virtual MyVS { destination 10.130.40.150:http ip-protocol tcp mask 255.255.255.255 persist { universal { default yes } } pool MyPool profiles { tcp { } } rules { MyRule } source 0.0.0.0/0 translate-address enabled translate-port enabled vs-index 53 } ltm virtual ClusterA_vs { destination 10.130.40.150:1001 ip-protocol tcp mask 255.255.255.255 pool ClusterA_pool profiles { tcp { } } source 0.0.0.0/0 translate-address enabled translate-port enabled vs-index 54 } ltm virtual ClusterB_vs { destination 10.130.40.150:1002 ip-protocol tcp mask 255.255.255.255 pool ClusterB_pool profiles { tcp { } } source 0.0.0.0/0 translate-address enabled translate-port enabled vs-index 55 } ltm pool ClusterA_pool { members { Node1:http { address 10.130.40.201 session monitor-enabled state up } Node2:http { address 10.130.40.202 session monitor-enabled state up } } monitor tcp slow-ramp-time 0 } ltm pool ClusterB_pool { members { Node3:http { address 10.130.40.203 session monitor-enabled state up } Node4:http { address 10.130.40.204 session monitor-enabled state up } } monitor tcp slow-ramp-time 0 } ltm node local_node { address 10.130.40.150 } ----------------- Code : when CLIENT_ACCEPTED {\n set initial 0\n set entry \"\"\n}\n\nwhen LB_SELECTED {\n incr initial\n # Checks if persistence entry exists\n catch { set entry [persist lookup uie [virtual name]] }\n # Loadbalancing selection base on persistence\n if { $entry eq \"\" } {\n set selection [LB::server port]\n } else {\n set selection [lindex [split $entry \" \"] 2]\n set status [LB::status pool MyPool member [LB::server addr] $selection]\n if { $status ne \"up\" } {\n catch { [persist delete uie [virtual name]] }\n set selection [LB::server port]\n }\n }\n # Adds a new persistence entry\n catch { persist add uie [virtual name] }\n # Applies the selection\n switch $selection {\n # This numbers represents the ports used at the VIP-targeting-VIP\n \"1001\" {\n LB::reselect virtual ClusterA_vs\n }\n \"1002\" {\n LB::reselect virtual ClusterB_vs\n }\n }\n} Tested this on version: 12.1","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"5155","kudosSumWeight":0,"repliesCount":1,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDE","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODA3MDYtNjIxN2kzRURDRkI2QTNCRDFFMkMy?revision=1\"}"}}],"totalCount":1,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}}},"Conversation:conversation:286400":{"__typename":"Conversation","id":"conversation:286400","topic":{"__typename":"TkbTopicMessage","uid":286400},"lastPostingActivityTime":"2024-05-16T02:07:12.059-07:00","solved":false},"User:user:162426":{"__typename":"User","uid":162426,"login":"CarloS1","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/m_assets/avatars/default/avatar-11.svg?time=0"},"id":"user:162426"},"TkbTopicMessage:message:286400":{"__typename":"TkbTopicMessage","subject":"Automated backup F5 configuration to remote server","conversation":{"__ref":"Conversation:conversation:286400"},"id":"message:286400","revisionNum":2,"uid":286400,"depth":0,"board":{"__ref":"Tkb:board:codeshare"},"author":{"__ref":"User:user:162426"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":8230},"postTime":"2018-06-08T12:23:51.000-07:00","lastPublishTime":"2023-06-05T22:00:29.437-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Problem this snippet solves: Hi, \n I made simple script that auto backup SCF and UCF files to the remote server. \n I read great article about autobackup based on the iApp (https://devcentral.f5.com/codeshare/f5-iapp-automated-backup-1114), but I wonder is that way to make it simplest. \nI don't think that my script is better, but only simple. This scritp based on TFTP communication so it isn't secure. \n What you have to do is: \n \n Create a script file on every f5 and place it for example on directory /var/tmp/. I named file script_backup.sh. Change IP address TFTP_SERVER to your remote server \n \n Change mod of file to execute: \n chmod 755 ./script_backup.sh \n \n Add line to the CRONTAB to run this script every X time \n Edit crontab: \n crontab -e \n Add line like this. Of course you can change the time when you want start script, it's only example: \n 30 0 * * 6 /var/tmp/script_backup.sh \n \n That's all. I hope you enjoy this script. \n I also wonder why f5 don't have native mechanism to auto backup on the remote server. It's the most basic function in other systems. Code : TFTP_SERVER=10.0.0.0\nDATETIME=\"`date +%Y%m%d%H%M`\"\nOUT_DIR='/var/tmp'\nFILE_UCS=\"f5_lan_${HOSTNAME}.ucs\"\nFILE_SCF=\"f5_lan_${HOSTNAME}.scf\"\nFILE_CERT=\"f5_lan_${HOSTNAME}.cert.tar\"\ncd ${OUT_DIR}\ntmsh save /sys ucs \"${OUT_DIR}/${FILE_UCS}\"\ntmsh save /sys config file \"${OUT_DIR}/${FILE_SCF}\" no-passphrase\ntar -cf \"${OUT_DIR}/${FILE_CERT}\" /config/ssl\ntftp $TFTP_SERVER <<-END 1>&2\nmode binary\nput ${FILE_UCS}\nput ${FILE_SCF}\nput ${FILE_CERT}\nquit\nEND\nrm -f \"${FILE_UCS}\"\nrm -f \"${FILE_SCF}\"\nrm -f \"${FILE_CERT}\"\nrm -f \"${FILE_SCF}.tar\"\nRTN_CODE=$?\nexit $RTN_COD ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"1676","kudosSumWeight":0,"repliesCount":6,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}}},"Conversation:conversation:274348":{"__typename":"Conversation","id":"conversation:274348","topic":{"__typename":"TkbTopicMessage","uid":274348},"lastPostingActivityTime":"2024-03-22T11:36:24.729-07:00","solved":false},"User:user:50559":{"__typename":"User","uid":50559,"login":"Joshua_Bines_12","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/m_assets/avatars/default/avatar-11.svg?time=0"},"id":"user:50559"},"TkbTopicMessage:message:274348":{"__typename":"TkbTopicMessage","subject":"New F5 Visio Stencil","conversation":{"__ref":"Conversation:conversation:274348"},"id":"message:274348","revisionNum":1,"uid":274348,"depth":0,"board":{"__ref":"Tkb:board:codeshare"},"author":{"__ref":"User:user:50559"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":1328},"postTime":"2016-10-10T21:47:42.000-07:00","lastPublishTime":"2016-10-10T21:47:42.000-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Problem this snippet solves: Helps make our documentation look and feel the way it should be... Code : 71206 ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"114","kudosSumWeight":0,"repliesCount":10,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}}},"Conversation:conversation:281880":{"__typename":"Conversation","id":"conversation:281880","topic":{"__typename":"TkbTopicMessage","uid":281880},"lastPostingActivityTime":"2023-09-05T08:52:24.548-07:00","solved":false},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODE4ODAtNjU5N2lDRTU3RjY4NEI1QUE0Qjkw?revision=2\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0yODE4ODAtNjU5N2lDRTU3RjY4NEI1QUE0Qjkw?revision=2","title":"0151T000003d9F6QAI.jpg","associationType":"BODY","width":517,"height":327,"altText":null},"TkbTopicMessage:message:281880":{"__typename":"TkbTopicMessage","subject":"TMSH Cli Script - Virtual Server, State, Status, Pool Name Report in CSV","conversation":{"__ref":"Conversation:conversation:281880"},"id":"message:281880","revisionNum":2,"uid":281880,"depth":0,"board":{"__ref":"Tkb:board:codeshare"},"author":{"__ref":"User:user:58212"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":1231},"postTime":"2019-03-07T07:13:37.000-08:00","lastPublishTime":"2023-06-05T21:48:55.201-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Problem this snippet solves: The below is a simple code to get a report on Virtuals present in the BigIP, with its name, state, status and the pool name associated to it. \n Should be helpful in building reports for management or auditing.\nThe output can be seen in console (if needed) or can be written to a file with csv format, so when opened in excel it would look like below snapshot. \n The output file will be save in /var/tmp/virtual_stats-output.csv \n How to use this snippet: In the console, \n tmsh \n create cli script virtual_stats \n and paste the below code and save. Code : create script virtual_stats {\nproc script::run {} {\n exec echo Virtual,State,Status,Pool, > /var/tmp/virtual_stats-output.csv\nforeach { obj } [tmsh::get_status ltm virtual] {\n set l1 [tmsh::get_field_value $obj \"name\"]\n set l2 [tmsh::get_field_value $obj \"status.enabled-state\"]\n set l3 [tmsh::get_field_value $obj \"status.availability-state\"]\n set l4 [tmsh::get_config ltm virtual $l1 pool ]\n set poolname [lindex [split [lindex [split $l4 \"\\n\"] 1] \" \"] 5]\n ###the below line can be commented to stop displaying output in console\n puts \"$l1,$l2,$l3,$poolname\"\n exec echo \"$l1,$l2,$l3,$poolname\" >> /var/tmp/virtual_stats-output.csv\n}\n}\n} Tested this on version: 13.0","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"1312","kudosSumWeight":0,"repliesCount":2,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDE","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODE4ODAtNjU5N2lDRTU3RjY4NEI1QUE0Qjkw?revision=2\"}"}}],"totalCount":1,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}}},"Conversation:conversation:285011":{"__typename":"Conversation","id":"conversation:285011","topic":{"__typename":"TkbTopicMessage","uid":285011},"lastPostingActivityTime":"2023-06-06T12:24:40.050-07:00","solved":false},"User:user:322278":{"__typename":"User","uid":322278,"login":"PeteWhite","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/m_assets/avatars/default/avatar-5.svg?time=0"},"id":"user:322278"},"TkbTopicMessage:message:285011":{"__typename":"TkbTopicMessage","subject":"Radware config translation","conversation":{"__ref":"Conversation:conversation:285011"},"id":"message:285011","revisionNum":3,"uid":285011,"depth":0,"board":{"__ref":"Tkb:board:codeshare"},"author":{"__ref":"User:user:322278"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":2168},"postTime":"2018-03-08T03:41:00.000-08:00","lastPublishTime":"2023-06-06T12:24:40.050-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Problem this snippet solves: This is a simple Python script that translates Radware text configuration file and outputs as config snippet and certificate files. \n $ ./rad2f5\nUsage: rad2f5 <filename> [partition]\n \n\n Example: \n ./rad2f5 radwareconfig.txt MyPartition\nUsing partition /MyPartition/\nIP routes:46\nNon-floating IP interfaces:26\nFloating IP interfaces:19\nMonitors:349\nVirtual Servers:430\nPools:152\nCertificates: 31\nSSL profiles: 17\nWARNING! Found L7 Regular Expression at \"appdirector l7 farm-selection method-table setCreate l7Rule-Redirect\"\nLayer 7 rules:12\nLayer 7 policies:4\n\n!! Copy all certificate files to BIG-IP /var/tmp and use load_certs.sh to load\n!!\n# Configuration\n#--------------------------------------#\nltm policy /MyPartition/l7rule-Redirect {\n controls { forwarding }\n requires { http }\n rules {\n Redirect {\n actions {\n 0 {\n forward\n select\n pool SORRYPOOL\n }\n\n }\n ordinal 1\n }\n }\nnet route /MyPartition/10.20.30.40_32 {\n network 10.20.30.40/32\n gateway 10.1.1.1\n}\n How to use this snippet: This includes translation of routes and non-floating self-IPs, monitors, pools, virtual servers, certificates, SSL profiles and some layer 7 rules. \n To install, either download the file attached here, extract and run it or use pip: \n pip install rad2f5\n \n\n To load the configuration to the f5 device, output to a file eg ./rad2f5 filename>newcfg.txt , remove the statistics header from the file with a text editor, upload the file into /var/tmp on the BIG-IP and test loading with tmsh load sys config merge file /var/tmp/<filename> verify . Fix any issues and load with tmsh load sys config merge file /var/tmp/<filename> \n The script will also output the certificates and keys which should be uploaded to the BIG-IP /var/tmp directory and run file check_certs.sh and load_certs.sh to check and load the certs and keys. \n Works with Python v2 and v3. \n If you want something to be added then message me with details of the text and i will try to add it. \n Feel free to add or change anything Code : #!/usr/bin/env python\n# v1.1 14/3/2018 Deal with lack of text in monitors ( line 157 )\n# v2 3/1/2019 Updated after changes suggested by Avinash Piare\n# v3 6/11/2019 Updated to deal with \\\\r\\n at the end of the line\n# v3.1 6/11/2019 Minor changes to handle VS names with spaces\n# 3.4 18/4/2020 Fixed minor issues\n# Peter White 6/11/2019\n# usage ./rad2f5 [partition]\nimport sys\nimport re\nimport textwrap\nimport ipaddress\n\nprint (\"Running with Python v\" + sys.version)\n\n# Set debug to true to output the workings of the script ie the arrays etc\ndebug = False\n\ndef parse_options(options):\n # Function to split options and return a dict containing option and value\n # Example: -pl 27 -v 123 -pa 172.28.1.234\n # Return: { 'pl':'27', 'v':'123', 'pa':'172.28.1.234' }\n output = dict()\n # Deal with non-quotes eg -b 12345\n for r in re.finditer(r'-(\\w{1,3}) (\\S+)',options):\n output[r.group(1)] = r.group(2)\n # Deal with quotes eg -u \"User Name\"\n for v in re.finditer(r'-(\\w{1,3}) (\".+\")',options):\n output[v.group(1)] = v.group(2)\n return output\n\ndef splitvars(vars):\n # Split a string on | and then =, return a dict of ABC=XYZ\n # eg HDR=User-Agent|TKN=Googlebot-Video/1.0|TMATCH=EQ|\n # Return is { 'HDR':'User-Agent','TKN': 'Googlebot-Video/1.0', 'TMATCH': 'EQ' }\n vlist = vars.split(\"|\")\n o = {}\n for v in vlist:\n if v == '':\n continue\n w = v.split(\"=\")\n if len(w) > 1:\n o[w[0]] = w[1]\n else:\n o[w[0]] = ''\n return o \n \ndef array_add(a,d):\n # Function to safely add to an array\n #global a\n if not len(a):\n a = [ d ]\n else:\n a.append( d )\n return a\n \ndef setup_pools(name):\n global pools\n if not name in pools:\n pools[name] = { 'destinations': [], 'member-disabled': [], 'member-ids': [], 'priority-group': [] }\n else:\n if not 'destinations' in pools[name]:\n pools[name]['destinations'] = []\n if not 'member-disabled' in pools[name]:\n pools[name]['member-disabled'] = []\n if not 'member-ids' in pools[name]:\n pools[name]['member-ids'] = []\n if not 'priority-group' in pools[name]:\n pools[name]['priority-group'] = [] \n\ndef getVsFromPool(poolname):\n # This retrieves the names of virtual servers that use a specific pool\n global farm2vs\n if poolname in farm2vs:\n return farm2vs[poolname]\n else:\n return False\n\ndef is_ipv6(ip):\n if ':' in ip:\n return True\n else:\n return False\n\n# Check there is an argument given\nif not len(sys.argv) > 1:\n exit(\"Usage: rad2f5 [partition]\")\nif len(sys.argv) > 2:\n # Second command-line variable is the partition\n partition = \"/\" + sys.argv[2] + \"/\"\n print (\"Using partition \" + partition)\nelse:\n partition = \"/Common/\"\n \n# Check input file\nfh = open(sys.argv[1],\"r\")\nif not fh:\n exit(\"Cannot open file \" + argv[1])\nrawfile = fh.read()\n\n# v2\n# Remove any instances of slash at the end of line\n# eg health-monitoring check create\\\n# HC_DNS -id 5 -m DNS -p 53 -a \\\n#HOST=ns.domain.com|ADDR=1.1.1.1| -d 2.2.2.2\n#file = re.sub('^security certificate table\\\\\\\\\\n','',rawfile)\nfile = re.sub('\\\\\\\\\\n','',rawfile)\nfile = re.sub('\\\\\\\\\\r\\n','',file)\n\n################ LACP trunks ##########################\n#\n#\n#\n#############################################################\n#net linkaggr trunks set T-1 -lap G-13,G-14 -lam Manual -lat Fast -law 3 -laa 32767\ntrunks = {}\nfor r in re.finditer(r'net linkaggr trunks set (\\S+) (.+)',file):\n name = r.group(1)\n options = parse_options(r.group(2))\n if 'lap' in options:\n # Manage interfaces\n ints = options['lap'].split(',')\n trunks[name] = { 'interfaces': ints } \nprint (\"LACP trunks:\" + str(len(trunks)))\nif debug:\n print('DEBUG LACP trunks: ' + str(trunks))\n\n################ IP routes ##########################\n#\n#\n#\n#############################################################\nroutes = {}\nfor r in re.finditer(r'net route table create (\\S+) (\\S+) (\\S+) (\\S+)',file):\n if r.group(1) == '0.0.0.0':\n name = 'default'\n else:\n name = r.group(1) + \"_\" + r.group(2)\n routes[name] = { 'network': r.group(1), 'mask': r.group(2), 'gateway': r.group(3), 'interface': r.group(4)} \nprint (\"IP routes:\" + str(len(routes)))\nif debug:\n print('DEBUG routes: ' + str(routes))\n\n################ Non-floating self-IPs ###############\n#\n#\n#\n# \n#############################################################\nselfIpNonFloating = {}\nfor s in re.finditer(r'net ip-interface create (\\S+) (\\S+) (.+)',file):\n output = { 'interface': s.group(2) }\n opts = parse_options(s.group(3))\n if 'pl' in opts:\n output['mask'] = opts['pl']\n if 'v' in opts:\n output['vlan'] = opts['v']\n if 'pa' in opts:\n output['peerAddress'] = opts['pa']\n selfIpNonFloating[s.group(1)] = output\nprint (\"Non-floating IP interfaces:\" + str(len(selfIpNonFloating)))\nif debug:\n print(\"DEBUG non-floating IPs: \" + str(selfIpNonFloating))\n\n\n################ Floating self-IPs ###################\n#\n#\n# \n#############################################################\nselfIpFloating = {}\nfor s in re.finditer(r'redundancy vrrp virtual-routers create (\\S+) (\\S+) (\\S+) (.+)',file):\n output = { 'version': s.group(1),'interface': s.group(3), 'ipAddresses': []}\n opts = parse_options(s.group(4))\n #if 'as' in opts:\n # Enabled - assume all are enabled\n if 'pip' in opts:\n output['peerIpAddress'] = opts['pip']\n selfIpFloating[s.group(2)] = output\n\n# Retrieve IP addresses for Floating self-IPs\n#\nfor s in re.finditer(r'redundancy vrrp associated-ip create (\\S+) (\\S+) (\\S+) (\\S+)',file):\n selfIpFloating[s.group(2)]['ipAddresses'] = array_add(selfIpFloating[s.group(2)]['ipAddresses'],s.group(4))\nprint (\"Floating IP interfaces:\" + str(len(selfIpFloating)))\nif debug:\n print(\"DEBUG Floating IPs: \" + str(selfIpFloating))\n\n\n################ Monitors ###########################\n#\n# -m XYZ is the monitor type may or may not be present ( not present for icmp type )\n# -id is the monitor ID, -p is the port, -d is the destination\n# \n#############################################################\nmonitors = {}\nfor m in re.finditer(r'health-monitoring check create (\\S+) (.+)',file):\n output = { 'name': m.group(1) }\n opts = parse_options(m.group(2))\n if 'id' in opts:\n id = opts['id']\n else:\n print (\"No ID for monitor \" + m.group(1))\n continue\n if 'm' in opts:\n output['type'] = opts['m']\n else:\n output['type'] = 'icmp'\n if 'a' in opts:\n output['text'] = opts['a']\n else:\n # Added in v2\n output['text'] = ''\n if 'p' in opts:\n output['port'] = opts['p']\n else:\n output['port'] = ''\n monitors[id] = output\n\nprint (\"Monitors:\" + str(len(monitors)))\nif debug:\n print(\"DEBUG Monitors:\" + str(monitors))\n\n################ Virtual Servers #####################\n#\n# 0 = name, 1= IP, 2=protocol, 3=port, 4=source 5=options\n# -ta = type, -ht = http policy, -fn = pool name, -sl = ssl profile name, -ipt = translation?\n# -po = policy name\n# \n#############################################################\nfarm2vs = {}\nvirtuals = {}\nsnatPools = {}\nfor v in re.finditer(r'appdirector l4-policy table create (\\S+) (\\S+) (\\S+) (\\S+) (\\S+) (.*)',file):\n # Puke if VS has quotes\n if v.group(1).startswith('\"'):\n name = v.group(1).strip('\"').replace(' ','_') + v.group(2).strip('\"').replace(' ','_')\n address,protocol,port = v.group(3),v.group(4),v.group(5)\n source = v.group(6).split(' ')[0]\n options = ' '.join(v.group(6).split(' ')[1:])\n else:\n name,address,protocol,port,source,options = v.group(1),v.group(2),v.group(3),v.group(4),v.group(5),v.group(6)\n opts = parse_options(options)\n # Get rid of ICMP virtual servers\n if protocol == 'ICMP':\n continue\n \n print (\"Name \" + name + \" has quotes, address: \" + address + \" protocol: \" + protocol)\n if port == 'Any':\n port = '0'\n output = {'source': source, 'destination': address + \":\" + port, 'protocol': protocol, 'port': port }\n if 'fn' in opts:\n output['pool'] = opts['fn']\n if not opts['fn'] in farm2vs:\n farm2vs[opts['fn']] = []\n farm2vs[opts['fn']].append(name)\n output['port'] = port\n if 'po' in opts:\n output['policy'] = opts['po']\n if 'ipt' in opts:\n output['snat'] = 'snatpool_' + opts['ipt']\n if not 'snatpool_' + opts['ipt'] in snatPools:\n #Create snatpool\n snatPools['snatpool_' + opts['ipt']] = { 'members': [opts['ipt']] }\n \n # Set the correct profiles\n profiles = []\n # Layer 4\n if protocol == \"TCP\" or protocol == \"UDP\":\n profiles.append(protocol.lower())\n else:\n profiles.append('ipother')\n # http\n if port == '80' or port == '8080':\n profiles.append('http')\n profiles.append('oneconnect')\n\n # ftp\n if port == '21':\n profiles.append('ftp')\n\n # RADIUS\n if port == '1812' or port == '1813':\n profiles.append('radius')\n\n # SSL\n if 'sl' in opts:\n profiles.append(opts['sl'])\n profiles.append('http')\n profiles.append('oneconnect')\n output['profiles'] = profiles\n # \n virtuals[name] = output\n \nprint (\"Virtual Servers:\" + str(len(virtuals)))\nif debug:\n print(\"DEBUG Virtual Servers:\" + str(virtuals))\n #print(\"DEBUG Farm to VS Mapping:\" + str(farm2vs))\n\n \n\n################ Pools ###############################\n#\n# Pools config options are distributed across multiple tables\n# This sets the global config such as load balancing algorithm\n# -dm This sets the distribution method. cyclic = Round Robin, Fewest Number of Users = least conn, Weighted Cyclic = ratio, Response Time = fastest\n# -as this is the admin state\n# -cm is the checking method ie monitor\n# -at is the activation time\n#############################################################\npools = {}\nfor p in re.finditer(r'appdirector farm table setCreate (\\S+) (.*)',file):\n name = p.group(1)\n setup_pools(name)\n opts = parse_options(p.group(2))\n output = {}\n # Admin state\n output['poolDisabled'] = False\n if 'as' in opts:\n if opts['as'] == 'Disabled':\n output['poolDisabled'] = True \n # Deal with distribution methods\n method = 'round-robin'\n if 'dm' in opts:\n if opts['dm'] == '\"Fewest Number of Users\"':\n method = 'least-conn'\n elif opts['dm'] == 'Hashing':\n method = 'hash'\n else:\n method = 'round-robin'\n output['lbMethod'] = method\n \n if 'at' in opts:\n output['slowRamp'] = opts['at']\n pools[name] = output\n# This sets the pool members\n# 0=name, 1=node, 2=node address, 3=node port, 4=? -id =id -sd ? -as admin state eg Disable, -om operation mode eg Backup ( fallback server ), -rt backup server address 0.0.0.0\nfor p in re.finditer(r'appdirector farm server table create (\\S+) (\\S+) (\\S+) (\\S+) (\\S+) (.*)',file):\n name,node,node_address,node_port,node_hostname = p.group(1),p.group(2),p.group(3),p.group(4),p.group(5)\n opts = parse_options(p.group(6))\n setup_pools(name)\n if node_port == 'None':\n node_port = '0'\n pools[name]['destinations'] = array_add(pools[name]['destinations'],node_address + \":\" + node_port)\n # Manage monitor\n if node_port == '80' or node_port == '8080':\n monitor = 'http'\n elif node_port == '443':\n monitor = 'https'\n elif node_port == '53':\n monitor = 'dns'\n elif node_port == '21':\n monitor = 'ftp'\n elif node_port == '0':\n monitor = 'gateway-icmp'\n else:\n monitor = 'tcp'\n pools[name]['monitor'] = monitor\n \n # Retrieve pool member ID\n if 'id' in opts:\n pools[name]['member-ids'] = array_add(pools[name]['member-ids'],opts['id'])\n else:\n print (\"ID not found for pool \" + name)\n \n # Check if member is disabled\n if 'as' in opts and opts['as'] == 'Disabled':\n # This pool member is disabled\n pools[name]['member-disabled'] = array_add(pools[name]['member-disabled'],True)\n else:\n pools[name]['member-disabled'] = array_add(pools[name]['member-disabled'],False)\n \n # Check if member is backup ie Priority Groups\n if 'om' in opts and opts['om'] == 'Backup':\n pools[name]['priority-group'] = array_add(pools[name]['priority-group'],20)\n else:\n pools[name]['priority-group'] = array_add(pools[name]['priority-group'],0)\n\n \n \nprint (\"Pools:\" + str(len(pools)) )\nif debug:\n print(\"DEBUG pools: \" + str(pools))\n\n################ SSL certificates ###################\n#\n#\n#Name: certificate_name \\\n#Type: certificate \\\n#-----BEGIN CERTIFICATE----- \\\n#MIIEcyFCA7agAwIAAgISESFWs9QGF\n# \n#############################################################\ncerts = {}\nfor r in re.finditer(r'Name: (\\S+) Type: (\\S+) (-----BEGIN CERTIFICATE-----.+?-----END CERTIFICATE-----)',file):\n name,type,text = r.group(1),r.group(2),r.group(3)\n certs[name] = { 'type': type,'text': text.replace(' \\\\\\r\\n','') }\n # Print out to file or something\nprint (\"SSL Certificates: \" + str(len(certs)))\nif debug:\n print(\"DEBUG certs: \" + str(certs))\n \n################ SSL Keys ###################\n#\n#\n#Name: New_Root_Cert Type: key Passphrase: -----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: [key] [key] -----END RSA PRIVATE KEY----- \\\n# \n#############################################################\nkeys = {}\n# Keys with passphrase\nfor r in re.finditer(r'Name: (\\S+) Type: key Passphrase: (\\S+) (-----BEGIN RSA PRIVATE KEY-----.+?-----END RSA PRIVATE KEY-----)',file):\n name,passphrase,text = r.group(1),r.group(2),r.group(3)\n keys[name] = { 'passphrase': passphrase,'text': text.replace(' \\\\\\r\\n','') }\n# Keys without passphrase\nfor r in re.finditer(r'Name: (\\S+) Type: key (-----BEGIN RSA PRIVATE KEY-----.+?-----END RSA PRIVATE KEY-----)',file):\n name,text = r.group(1),r.group(2)\n keys[name] = { 'text': text.replace(' \\\\\\r\\n','') }\nprint (\"SSL Keys: \" + str(len(keys)))\nif debug:\n print(\"DEBUG SSL keys: \" + str(keys))\n\n################ SSL profiles ########################\n#\n# -c is cert, -u is ciphers, -t is chain cert, -fv - versions\n##############################################################\nsslProfiles = {}\nfor s in re.finditer(r'^appdirector l4-policy ssl-policy create (\\S+) (.+)',file.replace('\\\\\\r\\n',''),re.MULTILINE):\n name = s.group(1)\n output = {}\n opts = parse_options(s.group(2))\n if 'c' in opts:\n # Certificate\n output['certificate'] = opts['c']\n if 't' in opts:\n # Chain cert\n output['chaincert'] = opts['t']\n if 'fv' in opts:\n # TLS Version\n output['version'] = opts['fv']\n if 'u' in opts:\n # User-defined Ciphers\n output['cipher'] = opts['u']\n if 'lp' in opts:\n # ?\n output['lp'] = opts['lp']\n if 'pa' in opts:\n # ?\n output['pa'] = opts['pa']\n if 'cb' in opts:\n # ?\n output['cb'] = opts['cb']\n if 'i' in opts:\n # Backend SSL Cipher -> Values: Low, Medium, High, User Defined\n output['i'] = opts['i']\n if 'bs' in opts:\n # Backend SSL in use ie serverSSL\n output['serverssl'] = opts['bs']\n \n sslProfiles[name] = output\nprint (\"SSL profiles: \" + str(len(sslProfiles)))\nif debug:\n print(\"DEBUG SSL Profiles: \" + str(sslProfiles))\n \n################ SNAT pools ##########################\n# \n# Note that this only works for addresses in the same /24 subnet\n#############################################################\n\nfor s in re.finditer(r'appdirector nat client address-range create (\\S+) (\\S+)',file):\n name = s.group(1)\n if sys.version.startswith('2'):\n start = ipaddress.ip_address(unicode(name,'utf_8'))\n end = ipaddress.ip_address(unicode(s.group(2),'utf_8'))\n else:\n start = ipaddress.ip_address(name)\n end = ipaddress.ip_address(s.group(2))\n current = start\n ipAddresses = []\n while current <= end:\n ipAddresses.append(str(current))\n current += 1\n snatPools['snatpool_' + name] = { 'members': ipAddresses }\nprint (\"SNAT Pools:\" + str(len(snatPools)))\nif debug:\n print(\"DEBUG SNAT Pools: \" + str(snatPools))\n####################################################################\n\n\n\n################ Layer 7 functions ##########################\n#\n# \n####################################################################\nl7rules = { }\nfor r in re.finditer(r'appdirector l7 farm-selection method-table setCreate (\\S+) (.+)',file):\n name = r.group(1)\n l7rules[name] = { 'match': [], 'action': [] }\n opts = parse_options(r.group(2))\n if 'cm' in opts and opts['cm'] == '\"Header Field\"' and 'ma' in opts:\n # This is a rule to insert a header\n params = splitvars(opts['ma'])\n if 'HDR' in params and 'TKN' in params:\n if params['TKN'] == \"$Client_IP\":\n params['TKN'] = '[IP::client_addr]'\n l7rules[name]['action'].append(\"http-header\\ninsert\\nname \" + params['HDR'] + \"\\nvalue \" + params['TKN'])\n \n if 'cm' in opts and opts['cm'] == 'URL' and 'ma' in opts:\n # This does a match on Host and URL\n params = splitvars(opts['ma'])\n if 'HN' in params:\n l7rules[name]['match'].append(\"http-host\\nhost\\nvalues { \" + params['HN'] + \" }\")\n if 'P' in params:\n l7rules[name]['match'].append(\"http-uri\\npath\\nvalues { \" + params['P'] + \" }\")\n \n if 'cm' in opts and opts['cm'] == '\"Regular Expression\"' and 'ma' in opts:\n params = splitvars(opts['ma'])\n if 'EXP' in params and params['EXP'] == '.':\n # This is a regex which matches everything\n print (\"REGEX: \" + name)\n else:\n print (\"WARNING! Found L7 Regular Expression at \\\"appdirector l7 farm-selection method-table setCreate \" + name + \"\\\". Manually set the match in output config.\")\n\n# Note that there can be multiple entries ie multiple rules per policy\nl7policies = {}\nfor p in re.finditer(r'appdirector l7 farm-selection policy-table setCreate (\\S+) (\\d+) (.+)',file):\n name = p.group(1)\n precedence = p.group(2)\n opts = parse_options(p.group(3))\n \n if 'fn' in opts:\n farm = opts['fn']\n else:\n farm = ''\n if 'm1' in opts:\n rule = opts['m1']\n if 'pa' in opts:\n # Retain HTTP Persistency (PRSST)-If the argument is ON (or undefined), AppDirector maintains HTTP 1.1\n # HTTP Redirect To (RDR)-Performs HTTP redirection to the specified name or IP address.\n # HTTPS Redirect To (RDRS)-AppDirector redirects the HTTP request to the specified name or IP address and modifies the request to a HTTPS request.\n # Redirection Code (RDRC)-Defines the code to be used for redirection.\n # RDRC=PRMN stand for Permanent I assume , as in HTTP 301\n # SIP Redirect To (RDRSIP)-Performs SIP redirection to the specified name or IP address.\n \n params = splitvars(opts['pa'])\n if 'RDR' in params:\n url = 'http://' + params['RDR']\n elif 'RDRS' in params:\n url = 'https://' + params['RDRS']\n else:\n url = ''\n \n if not name in l7policies:\n l7policies[name] = []\n if rule in l7rules:\n if farm != '':\n l7rules[rule]['action'].append(\"forward\\nselect\\npool \" + farm)\n elif url != '':\n l7rules[rule]['action'].append(\"http-redirect\\nhost \" + url)\n l7policies[name].append({ 'precedence': precedence, 'farm': farm, 'rule': rule })\n\nprint (\"Layer 7 rules:\" + str(len(l7rules)))\nprint (\"Layer 7 policies:\" + str(len(l7policies)))\n\nif debug:\n print(\"DEBUG L7 rules: \" + str(l7rules))\n print(\"DEBUG L7 policies: \" + str(l7policies))\n\n#\n# We have retrieved the required configuration from the input file \n# Now start outputting the config\n\n\n\n\n################# output SSL certificates import script ######################\n#\n#\n########################################################################\nif len(certs):\n print (\"-- Creating SSL certs and keys --\")\n with open(\"load_certs.sh\",'w') as loadScript:\n loadScript.write(\"#!/bin/bash\\n# Script to load SSL certs and keys from /var/tmp\\n\")\n ##### Manage Certificates ########\n for cert in certs:\n # Write certs to load_certs.sh\n if certs[cert]['type'] == 'certificate' or certs[cert]['type'] == 'interm':\n loadScript.write(\"tmsh install sys crypto cert \" + partition + cert + \".crt from-local-file /var/tmp/\" + cert + \".crt\\n\")\n \n # Create the certificate files\n with open(cert + \".crt\",\"w\") as certFile:\n for m in re.finditer(r'(-----BEGIN CERTIFICATE-----)\\s?(.+)\\s?(-----END CERTIFICATE-----)',certs[cert]['text']):\n certFile.write(m.group(1) + \"\\n\")\n certFile.write(textwrap.fill(m.group(2),64) + \"\\n\")\n certFile.write(m.group(3) + \"\\n\")\n print (\"Created SSL certificate file \" + cert + \".crt\")\n ##### Manage Keys #################\n for key in keys:\n # Write keys to load_certs.sh\n loadScript.write(\"tmsh install sys crypto key \" + partition + key + \".key\")\n if 'passphrase' in keys[key]:\n loadScript.write(\" passphrase \" + keys[key]['passphrase'])\n loadScript.write(\" from-local-file /var/tmp/\" + key + \".key\\n\")\n \n \n # Create the key files\n with open(key + \".key\",\"w\") as keyFile:\n for n in re.finditer(r'(-----BEGIN RSA PRIVATE KEY-----)(.+)(-----END RSA PRIVATE KEY-----)',keys[key]['text']):\n keyFile.write(n.group(1) + \"\\n\")\n if 'Proc-Type:' in n.group(2) and 'DEK-Info:' in n.group(2):\n # File is encrypted, separate the first lines\n for o in re.finditer(r'(Proc-Type: \\S+) (DEK-Info: \\S+) (.+)',n.group(2)):\n keyFile.write(o.group(1) + \"\\n\")\n keyFile.write(o.group(2) + \"\\n\\n\")\n keyFile.write(textwrap.fill(o.group(3),64) + \"\\n\")\n else:\n # File is not encrypted, output as it is\n keyFile.write(textwrap.fill(n.group(2),64) + \"\\n\")\n keyFile.write(n.group(3) + \"\\n\")\n print (\"Created SSL key file \" + key + \".key\")\n print (\"-- Finished creating SSL certs and keys --\")\n print (\"!! Copy all .crt and .key SSL files to BIG-IP /var/tmp and use load_certs.sh to load !!\" )\n #######################################################################\n\n ################# output SSL certificates checking script ######################\n #\n #\n ########################################################################\n with open(\"check_certs.sh\",'w') as checkScript:\n checkScript.write(\"#!/bin/bash\\n# Script to check SSL certs and keys\\n\")\n checkScript.write(\"\\n# Check SSL Certs\\n\")\n for cert in certs:\n if certs[cert]['type'] == 'certificate' or certs[cert]['type'] == 'interm':\n checkScript.write(\"openssl x509 -in \" + cert + \".crt -noout || echo \\\"Error with file \" + cert + \".crt\\\"\\n\")\n \n checkScript.write(\"\\n# Check SSL Keys\\n\")\n for key in keys:\n checkScript.write(\"openssl rsa -in \" + key + \".key -check || echo \\\"Error with file \" + key + \".key\\\"\\n\")\n \n print (\"!! Run the check_certs.sh script to check the certificates are valid !!\" )\n#######################################################################\n\n#\n#\n#\n#\n#\n#\n#\n#\nprint (\"\\n\\n\\n\\n\\n\\n# Configuration \\n#--------------------------------------#\")\n################# output policy config #####################\n#\n#\n#############################################################\n#print (\"L7 rules: \" + str(l7rules))\nfor i in l7policies.keys():\n output = \"ltm policy \" + partition + i + \" {\\n\\tcontrols { forwarding }\\n\\trequires { http }\\n\\t\"\n output += \"rules {\\n\\t\"\n ordinal = 1\n for j in l7policies[i]:\n output += \"\\t\" + j['rule'] + \" { \\n\"\n if len(l7rules[j['rule']]['match']):\n # Deal with conditions\n output += \"\\t\\t\\tconditions { \\n\"\n l = 0\n for k in l7rules[j['rule']]['match']:\n output += \"\\t\\t\\t\\t\" + str(l) + \" { \\n\\t\\t\\t\\t\\t\" + k.replace('\\n','\\n\\t\\t\\t\\t\\t')\n l += 1\n output += \"\\n\\t\\t\\t\\t }\\n\"\n output += \"\\n\\t\\t\\t }\\n\"\n if len(l7rules[j['rule']]['action']):\n # Deal with actions\n output += \"\\t\\t\\tactions { \\n\"\n m = 0\n for n in l7rules[j['rule']]['action']:\n output += \"\\t\\t\\t\\t\" + str(m) + \" { \\n\\t\\t\\t\\t\\t\" + n.replace('\\n','\\n\\t\\t\\t\\t\\t') \n m += 1\n output += \"\\n\\t\\t\\t\\t }\\n\"\n output += \"\\n\\t\\t\\t }\\n\"\n output += \"\\t\\tordinal \" + str(ordinal)\n output += \"\\n\\t\\t}\\n\\t\"\n ordinal += 1\n output += \"\\n\\t}\\n}\\n\"\n print (output)\n\n\n################# output LACP trunk config ##############\n#\n#\n#############################################################\nfor trunk in trunks.keys():\n output = \"net trunk \" + partition + trunk + \" {\\n\"\n if 'interfaces' in trunks[trunk]:\n output += \"\\tinterfaces {\\n\"\n for int in trunks[trunk]['interfaces']:\n output += \"\\t\\t\" + int + \"\\n\"\n output += \"\\t}\\n\"\n output += \"}\\n\"\n print (output)\n \n################# output vlan config ##############\n#\n#\n#############################################################\n \nfor ip in selfIpNonFloating.keys():\n output = \"\"\n if 'vlan' in selfIpNonFloating[ip]:\n vlanName = \"VLAN-\" + selfIpNonFloating[ip]['vlan']\n output += \"net vlan \" + partition + vlanName + \" {\\n\"\n if 'interface' in selfIpNonFloating[ip]:\n output += \"\\tinterfaces {\\n\"\n output += \"\\t\\t\" + selfIpNonFloating[ip]['interface'] + \" {\\n\"\n output += \"\\t\\t\\ttagged\\n\\t\\t}\\n\"\n output += \"\\t}\\n\"\n output += \"\\ttag \" + selfIpNonFloating[ip]['vlan'] + \"\\n}\\n\"\n print(output)\n \n################# output non-floating self-ip config #######\n#\n#\n#############################################################\nfor ip in selfIpNonFloating.keys():\n output = \"\"\n if 'mask' in selfIpNonFloating[ip]:\n mask = \"/\" + selfIpNonFloating[ip]['mask']\n else:\n if is_ipv6(ip):\n mask = \"/64\"\n else:\n mask = \"/32\"\n if 'vlan' in selfIpNonFloating[ip]:\n vlanName = \"VLAN-\" + selfIpNonFloating[ip]['vlan']\n else:\n continue\n\n output += \"net self \" + partition + \"selfip_\" + ip + \" {\\n\\taddress \" + ip + mask + \"\\n\\t\"\n output += \"allow-service none\\n\\t\"\n output += \"traffic-group traffic-group-local-only\\n\"\n output += \"\\tvlan \" + vlanName + \"\\n\"\n output += \"}\\n\"\n print (output)\n \n################# output network route config ##############\n#\n#\n#############################################################\nfor route in routes.keys():\n network,mask,gateway = routes[route]['network'],routes[route]['mask'],routes[route]['gateway']\n output = \"net route \" + partition + route + \" {\\n\\tnetwork \" + network + \"/\" + mask + \"\\n\\t\"\n output += \"gateway \" + gateway + \"\\n}\"\n print (output)\n \n################# output SSL profiles config ##########################\n#\n#\n########################################################################\nfor s in sslProfiles:\n #print (str(sslProfiles[s]))\n output = \"ltm profile client-ssl \" + partition + s + \" {\\n\"\n output += \"\\tcert-key-chain { \" + s + \" { cert \"\n output += sslProfiles[s]['certificate'] + \".crt \"\n output += \" key \"\n output += sslProfiles[s]['certificate'] + \".key \"\n if 'chaincert' in sslProfiles[s]:\n output += \"chain \" + sslProfiles[s]['chaincert']\n output += \" }\\n\\tdefaults-from /Common/clientssl\\n}\\n\"\n print (output)\n if 'serverssl' in sslProfiles[s]:\n print(\"WARNING: VSs using Client SSL profile \" + s + \" should have Server SSL profile assigned\")\n \n################# output monitor config ####################\n#\n#\n#############################################################\nfor m in monitors.keys():\n if monitors[m]['type'] == '\"TCP Port\"':\n output = \"ltm monitor tcp \" + partition + monitors[m]['name'] + \" {\\n\\tdefaults-from /Common/tcp\\n}\\n\"\n if monitors[m]['type'] == '\"UDP Port\"':\n output = \"ltm monitor udp \" + partition + monitors[m]['name'] + \" {\\n\\tdefaults-from /Common/udp\\n}\\n\"\n if monitors[m]['type'] == 'HTTP':\n '''\n https://webhelp.radware.com/AppDirector/v214/214Traffic%20Management%20and%20Application%20Acceleration.03.001.htm\n https://webhelp.radware.com/AppDirector/v214/HM_Checks_Table.htm\n Arguments:\n Host name - HOST=10.10.10.53\n path - PATH=/hc.htm\n HTTP Header\n HTTP method - MTD=G (G/H/P)\n send HTTP standard request or proxy request - PRX=N\n use of no-cache - NOCACHE=N\n text for search within a HTTP header and body, and an indication whether the text appears\n Username and Password for basic authentication\n NTLM authentication option - AUTH=B\n Up to four valid HTTP return codes - C1=200\n -a PATH=/hc.htm|C1=200|MEXIST=Y|MTD=G|PRX=N|NOCACHE=N|AUTH=B|\n '''\n output = \"ltm monitor http \" + partition + monitors[m]['name'] + \" {\\n\\tdefaults-from /Common/http\\n\"\n vars = splitvars(monitors[m]['text'])\n output += \"\\tsend \\\"\"\n if 'MTD' in vars:\n if vars['MTD'] == 'G':\n output += \"GET \"\n elif vars['MTD'] == 'P':\n output += \"POST \"\n elif vars['MTD'] == 'H':\n output += \"HEAD \"\n else:\n output += \"GET \"\n if 'PATH' in vars:\n output += vars['PATH'] + ' HTTP/1.0\\\\r\\\\n\\\\r\\\\n\"\\n'\n if 'C1' in vars:\n output += \"\\trecv \\\"^HTTP/1\\.. \" + vars['C1'] + \"\\\"\\n\"\n output += \"}\\n\"\n if monitors[m]['type'] == 'HTTPS':\n output = \"ltm monitor https \" + partition + monitors[m]['name'] + \" {\\n\\tdefaults-from /Common/https\\n\"\n vars = splitvars(monitors[m]['text'])\n output += \"\\tsend \\\"\"\n if 'MTD' in vars:\n if vars['MTD'] == 'G':\n output += \"GET \"\n elif vars['MTD'] == 'P':\n output += \"POST \"\n elif vars['MTD'] == 'H':\n output += \"HEAD \"\n else:\n output += \"GET \"\n if 'PATH' in vars:\n output += vars['PATH'] + ' HTTP/1.0\\\\r\\\\n\\\\r\\\\n\"\\n'\n output += \"}\\n\"\n if monitors[m]['type'] == 'LDAP':\n '''\n The Health Monitoring module enhances the health checks for LDAP servers by allowing performing searches in the LDAP server. Before Health Monitoring performs the search, it issues a Bind request command to the LDAP server.\n After performing the search, it closes the connection with the Unbind command. A successful search receives an answer from the server that includes a \"searchResultEntry\" message. An unsuccessful search receives an answer that only includes only a \"searchResultDone\" message.\n Arguments:\n Username A user with privileges to search the LDAP server.\n Password The password of the user.\n Base Object The location in the directory from which the LDAP search begins.\n Attribute Name The attribute to look for. For example, CN - Common Name.\n Search Value The value to search for.\n Search scope baseObject, singleLevel, wholeSubtree\n Search Deref Aliases neverDerefAliases, dereflnSearching, derefFindingBaseObj, derefAlways\n USER=cn=healthcheck,dc=domain|PASS=1234|BASE=dc=domain|ATTR=cn|VAL=healthcheck|SCP=1|DEREF=3|\n '''\n output = \"ltm monitor ldap \" + partition + monitors[m]['name'] + \" {\\n\\tdefaults-from /Common/ldap\\n\"\n vars = splitvars(monitors[m]['text'])\n if 'BASE' in vars:\n output += \"\\tbase \\\"\" + vars['BASE'] + \"\\\"\\n\"\n if 'USER' in vars:\n output += \"\\tusername \\\"\" + vars['USER'] + \"\\\"\\n\"\n if 'PASS' in vars:\n output += \"\\tpassword \\\"\" + vars['PASS'] + \"\\\"\\n\"\n output += \"}\\n\"\n if monitors[m]['type'] == 'icmp':\n output = \"ltm monitor gateway-icmp \" + partition + monitors[m]['name'] + \" {\\n\\tdefaults-from /Common/gateway-icmp\\n}\\n\"\n if monitors[m]['type'] == 'DNS':\n output = \"ltm monitor dns \" + partition + monitors[m]['name'] + \" {\\n\\tdefaults-from /Common/dns\\n\"\n vars = splitvars(monitors[m]['text'])\n if 'HOST' in vars:\n output += \"\\tqname \\\"\" + vars['HOST'] + \"\\\"\\n\"\n if 'ADDR' in vars:\n output += \"\\trecv \\\"\" + vars['ADDR'] + \"\\\"\\n\"\n output += \"}\\n\"\n if monitors[m]['type'] == '\"Radius Accounting\"':\n output = \"ltm monitor radius-accounting \" + partition + monitors[m]['name'] + \" {\\n\\tdefaults-from /Common/radius-accounting\\n\"\n vars = splitvars(monitors[m]['text'])\n if 'USER' in vars:\n output += \"\\tusername \\\"\" + vars['USER'] + \"\\\"\\n\"\n #if 'PASS' in vars:\n if 'SECRET' in vars:\n output += \"\\tsecret \\\"\" + vars['SECRET'] + \"\\\"\\n\"\n output += \"}\\n\"\n if monitors[m]['type'] == '\"Radius Authentication\"':\n output = \"ltm monitor radius \" + partition + monitors[m]['name'] + \" {\\n\\tdefaults-from /Common/radius\\n\"\n vars = splitvars(monitors[m]['text'])\n if 'USER' in vars:\n output += \"\\tusername \\\"\" + vars['USER'] + \"\\\"\\n\"\n #if 'PASS' in vars:\n if 'SECRET' in vars:\n output += \"\\tsecret \\\"\" + vars['SECRET'] + \"\\\"\\n\"\n output += \"}\\n\"\n print (output)\n \n################# output SNAT pool config ######################\n#\n#\n#############################################################\nfor s in snatPools.keys():\n output = \"ltm snatpool \" + partition + s + \" {\\n\\t\"\n output += \"members {\\n\"\n #run through pool range and add members as individual IP addresses below each other\n for member in snatPools[s]['members']:\n output += \"\\t \" + member + \"\\n\"\n output += \"\\t}\"\n output += \"\\n}\"\n print (output) \n################# output pool config ######################\n#\n#\n#############################################################\nfor p in pools.keys():\n output = \"ltm pool \" + partition + p + \" {\\n\\t\" \n if 'monitor' in pools[p]:\n output += \"monitor min 1 of { \" + pools[p]['monitor'] + \" }\\n\\t\"\n if 'lbMethod' in pools[p]:\n output += \"load-balancing-mode \" + pools[p]['lbMethod'] + \"\\n\\t\"\n output += \"members {\\n\"\n if 'destinations' in pools[p] and len(pools[p]['destinations']):\n for i,v in enumerate(pools[p]['destinations']):\n d = re.sub(':\\d+$','',v)\n output += \"\\t\\t\" + v + \" {\\n\\t\\t\\taddress \" + d + \"\\n\"\n if pools[p]['member-disabled'][i]:\n output += \"\\t\\t\\tstate down\\n\"\n output += \"\\t\\t\\tpriority-group \" + str(pools[p]['priority-group'][i]) + \"\\n\"\n output += \"\\t\\t}\\n\"\n output += \"\\t}\\n}\" \n print (output)\n################# output virtual server config ######################\n#\n#\n######################################################################\nfor v in virtuals:\n output = \"ltm virtual \" + partition + v + \" {\\n\"\n output += \"\\tdestination \" + virtuals[v]['destination'] + \"\\n\"\n output += \"\\tip-protocol \" + virtuals[v]['protocol'].lower() + \"\\n\"\n if 'pool' in virtuals[v] and virtuals[v]['pool']:\n output += \"\\tpool \" + virtuals[v]['pool'] + \"\\n\"\n if 'profiles' in virtuals[v] and len(virtuals[v]['profiles']):\n output += \"\\tprofiles {\\n\"\n for p in virtuals[v]['profiles']:\n output += \"\\t\\t\" + p + \" { }\\n\"\n output += \"\\t}\\n\"\n if 'snat' in virtuals[v]:\n output += \"\\tsource-address-translation {\\n\\t\"\n if virtuals[v]['snat'] == 'automap':\n output += \"\\ttype automap\\n\\t\"\n else:\n output += \"\\ttype snat\\n\\t\"\n output += \"\\tpool \" + virtuals[v]['snat'] + \"\\n\\t\"\n output += \"}\\n\"\n if 'policy' in virtuals[v]:\n output += \"\\tpolicies {\\n\\t\"\n output += \"\\t\" + virtuals[v]['policy'] + \" { }\\n\\t}\\n\"\n output += \"}\"\n print (output) Tested this on version: 12.0","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"39331","kudosSumWeight":0,"repliesCount":30,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}}},"Conversation:conversation:278231":{"__typename":"Conversation","id":"conversation:278231","topic":{"__typename":"TkbTopicMessage","uid":278231},"lastPostingActivityTime":"2023-06-05T22:58:12.122-07:00","solved":false},"User:user:66262":{"__typename":"User","uid":66262,"login":"raj_77723","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/m_assets/avatars/default/avatar-4.svg?time=0"},"id":"user:66262"},"TkbTopicMessage:message:278231":{"__typename":"TkbTopicMessage","subject":"Rewriting the URL for specific pool members","conversation":{"__ref":"Conversation:conversation:278231"},"id":"message:278231","revisionNum":2,"uid":278231,"depth":0,"board":{"__ref":"Tkb:board:codeshare"},"author":{"__ref":"User:user:66262"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":228},"postTime":"2016-02-16T00:04:53.000-08:00","lastPublishTime":"2023-06-05T22:58:12.122-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" How to use this snippet: when RULE_INIT { \n set static::new_app_nodes \"1.1.1.1 443 2.2.2.2 443 3.3.3.3 443\" \n \n\n } \n when HTTP_REQUEST_SEND { \n if { $static::new_app_nodes contains \"[LB::server addr] [LB::server port]\" } then {\n\n log -noname local0.debug \"Match! [members -list $static::new_app_nodes] contains [LB::server addr] [LB::server port]\"\n\n clientside {\n\n HTTP::uri \"/uri\"\n\n }\n\n} else {\n\n log -noname local0.debug \"Don't match! [members -list $static::new_app_nodes] contains [LB::server addr] [LB::server port]\"\n\n}\n \n\n } Code : when RULE_INIT {\n\n set static::new_app_nodes \"1.1.1.1 443 2.2.2.2 443 3.3.3.3 443\" \n\n}\n\nwhen HTTP_REQUEST_SEND {\n\n if { $static::new_app_nodes contains \"[LB::server addr] [LB::server port]\" } then {\n\n log -noname local0.debug \"Match! [members -list $static::new_app_nodes] contains [LB::server addr] [LB::server port]\"\n\n clientside {\n\n HTTP::uri \"/uri\"\n\n }\n\n } else {\n\n log -noname local0.debug \"Don't match! [members -list $static::new_app_nodes] contains [LB::server addr] [LB::server port]\"\n\n }\n\n} Tested this on version: 11.4","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"1150","kudosSumWeight":0,"repliesCount":0,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}}},"CachedAsset:text:en_US-components/community/Navbar-1743097580000":{"__typename":"CachedAsset","id":"text:en_US-components/community/Navbar-1743097580000","value":{"community":"Community Home","inbox":"Inbox","manageContent":"Manage Content","tos":"Terms of Service","forgotPassword":"Forgot Password","themeEditor":"Theme Editor","edit":"Edit Navigation Bar","skipContent":"Skip to content","migrated-link-9":"Groups","migrated-link-7":"Technical Articles","migrated-link-8":"DevCentral News","migrated-link-1":"Technical Forum","migrated-link-10":"Community Groups","migrated-link-2":"Water Cooler","migrated-link-11":"F5 Groups","Common-external-link":"How Do I...?","migrated-link-0":"Forums","article-series":"Article Series","migrated-link-5":"Community Articles","migrated-link-6":"Articles","security-insights":"Security Insights","migrated-link-3":"CrowdSRC","migrated-link-4":"CodeShare","migrated-link-12":"Events","migrated-link-13":"Suggestions"},"localOverride":false},"CachedAsset:text:en_US-components/community/NavbarHamburgerDropdown-1743097580000":{"__typename":"CachedAsset","id":"text:en_US-components/community/NavbarHamburgerDropdown-1743097580000","value":{"hamburgerLabel":"Side Menu"},"localOverride":false},"CachedAsset:text:en_US-components/community/BrandLogo-1743097580000":{"__typename":"CachedAsset","id":"text:en_US-components/community/BrandLogo-1743097580000","value":{"logoAlt":"Khoros","themeLogoAlt":"Brand Logo"},"localOverride":false},"CachedAsset:text:en_US-components/community/NavbarTextLinks-1743097580000":{"__typename":"CachedAsset","id":"text:en_US-components/community/NavbarTextLinks-1743097580000","value":{"more":"More"},"localOverride":false},"CachedAsset:text:en_US-components/authentication/AuthenticationLink-1743097580000":{"__typename":"CachedAsset","id":"text:en_US-components/authentication/AuthenticationLink-1743097580000","value":{"title.login":"Sign In","title.registration":"Register","title.forgotPassword":"Forgot Password","title.multiAuthLogin":"Sign In"},"localOverride":false},"CachedAsset:text:en_US-components/nodes/NodeLink-1743097580000":{"__typename":"CachedAsset","id":"text:en_US-components/nodes/NodeLink-1743097580000","value":{"place":"Place {name}"},"localOverride":false},"CachedAsset:text:en_US-components/tags/TagSubscriptionAction-1743097580000":{"__typename":"CachedAsset","id":"text:en_US-components/tags/TagSubscriptionAction-1743097580000","value":{"success.follow.title":"Following Tag","success.unfollow.title":"Unfollowed Tag","success.follow.message.followAcrossCommunity":"You will be notified when this tag is used anywhere across the community","success.unfollowtag.message":"You will no longer be notified when this tag is used anywhere in this place","success.unfollowtagAcrossCommunity.message":"You will no longer be notified when this tag is used anywhere across the community","unexpected.error.title":"Error - Action Failed","unexpected.error.message":"An unidentified problem occurred during the action you took. Please try again later.","buttonTitle":"{isSubscribed, select, true {Unfollow} false {Follow} other{}}","unfollow":"Unfollow"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageListTabs-1743097580000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageListTabs-1743097580000","value":{"mostKudoed":"{value, select, IDEA {Most Votes} other {Most Likes}}","mostReplies":"Most Replies","mostViewed":"Most Viewed","newest":"{value, select, IDEA {Newest Ideas} OCCASION {Newest Events} other {Newest Topics}}","newestOccasions":"Newest Events","mostRecent":"Most Recent","noReplies":"No Replies Yet","noSolutions":"No Solutions Yet","solutions":"Solutions","mostRecentUserContent":"Most Recent","trending":"Trending","draft":"Drafts","spam":"Spam","abuse":"Abuse","moderation":"Moderation","tags":"Tags","PAST":"Past","UPCOMING":"Upcoming","sortBymostRecent":"Sort By Most Recent","sortBymostRecentUserContent":"Sort By Most Recent","sortBymostKudoed":"Sort By Most Likes","sortBymostReplies":"Sort By Most Replies","sortBymostViewed":"Sort By Most Viewed","sortBynewest":"Sort By Newest Topics","sortBynewestOccasions":"Sort By Newest Events","otherTabs":" Messages list in the {tab} for {conversationStyle}","guides":"Guides","archives":"Archives"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/common/QueryHandler-1743097580000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/QueryHandler-1743097580000","value":{"title":"Query Handler"},"localOverride":false},"CachedAsset:text:en_US-components/community/NavbarDropdownToggle-1743097580000":{"__typename":"CachedAsset","id":"text:en_US-components/community/NavbarDropdownToggle-1743097580000","value":{"ariaLabelClosed":"Press the down arrow to open the menu"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/common/OverflowNav-1743097580000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/OverflowNav-1743097580000","value":{"toggleText":"More"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageView/MessageViewInline-1743097580000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageView/MessageViewInline-1743097580000","value":{"bylineAuthor":"{bylineAuthor}","bylineBoard":"{bylineBoard}","anonymous":"Anonymous","place":"Place {bylineBoard}","gotoParent":"Go to parent {name}"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/common/Pager/PagerLoadMore-1743097580000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/Pager/PagerLoadMore-1743097580000","value":{"loadMore":"Show More"},"localOverride":false},"CachedAsset:text:en_US-components/customComponent/CustomComponent-1743097580000":{"__typename":"CachedAsset","id":"text:en_US-components/customComponent/CustomComponent-1743097580000","value":{"errorMessage":"Error rendering component id: {customComponentId}","bannerTitle":"Video provider requires cookies to play the video. Accept to continue or {url} it directly on the provider's site.","buttonTitle":"Accept","urlText":"watch"},"localOverride":false},"CachedAsset:text:en_US-components/users/UserLink-1743097580000":{"__typename":"CachedAsset","id":"text:en_US-components/users/UserLink-1743097580000","value":{"authorName":"View Profile: {author}","anonymous":"Anonymous"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageSubject-1743097580000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageSubject-1743097580000","value":{"noSubject":"(no subject)"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageBody-1743097580000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageBody-1743097580000","value":{"showMessageBody":"Show More","mentionsErrorTitle":"{mentionsType, select, board {Board} user {User} message {Message} other {}} No Longer Available","mentionsErrorMessage":"The {mentionsType} you are trying to view has been removed from the community.","videoProcessing":"Video is being processed. Please try again in a few minutes.","bannerTitle":"Video provider requires cookies to play the video. Accept to continue or {url} it directly on the provider's site.","buttonTitle":"Accept","urlText":"watch"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageTime-1743097580000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageTime-1743097580000","value":{"postTime":"Published: {time}","lastPublishTime":"Last Update: {time}","conversation.lastPostingActivityTime":"Last posting activity time: {time}","conversation.lastPostTime":"Last post time: {time}","moderationData.rejectTime":"Rejected time: {time}"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/nodes/NodeIcon-1743097580000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/nodes/NodeIcon-1743097580000","value":{"contentType":"Content Type {style, select, FORUM {Forum} BLOG {Blog} TKB {Knowledge Base} IDEA {Ideas} OCCASION {Events} other {}} icon"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageUnreadCount-1743097580000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageUnreadCount-1743097580000","value":{"unread":"{count} unread","comments":"{count, plural, one { unread comment} other{ unread comments}}"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageViewCount-1743097580000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageViewCount-1743097580000","value":{"textTitle":"{count, plural,one {View} other{Views}}","views":"{count, plural, one{View} other{Views}}"},"localOverride":false},"CachedAsset:text:en_US-components/kudos/KudosCount-1743097580000":{"__typename":"CachedAsset","id":"text:en_US-components/kudos/KudosCount-1743097580000","value":{"textTitle":"{count, plural,one {{messageType, select, IDEA{Vote} other{Like}}} other{{messageType, select, IDEA{Votes} other{Likes}}}}","likes":"{count, plural, one{like} other{likes}}"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageRepliesCount-1743097580000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageRepliesCount-1743097580000","value":{"textTitle":"{count, plural,one {{conversationStyle, select, IDEA{Comment} OCCASION{Comment} other{Reply}}} other{{conversationStyle, select, IDEA{Comments} OCCASION{Comments} other{Replies}}}}","comments":"{count, plural, one{Comment} other{Comments}}"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/users/UserAvatar-1743097580000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/users/UserAvatar-1743097580000","value":{"altText":"{login}'s avatar","altTextGeneric":"User's avatar"},"localOverride":false}}}},"page":"/tags/TagPage/TagPage","query":{"nodeId":"board:codeshare","tagName":"BIG-IP"},"buildId":"q_bLpq2mflH0BeZigxpj6","runtimeConfig":{"buildInformationVisible":false,"logLevelApp":"info","logLevelMetrics":"info","openTelemetryClientEnabled":false,"openTelemetryConfigName":"f5","openTelemetryServiceVersion":"25.2.0","openTelemetryUniverse":"prod","openTelemetryCollector":"http://localhost:4318","openTelemetryRouteChangeAllowedTime":"5000","apolloDevToolsEnabled":false,"inboxMuteWipFeatureEnabled":false},"isFallback":false,"isExperimentalCompile":false,"dynamicIds":["./components/customComponent/CustomComponent/CustomComponent.tsx","./components/community/Navbar/NavbarWidget.tsx","./components/community/Breadcrumb/BreadcrumbWidget.tsx","./components/tags/TagsHeaderWidget/TagsHeaderWidget.tsx","./components/messages/MessageListForNodeByRecentActivityWidget/MessageListForNodeByRecentActivityWidget.tsx","./components/tags/TagSubscriptionAction/TagSubscriptionAction.tsx","./components/customComponent/CustomComponentContent/TemplateContent.tsx","../shared/client/components/common/List/ListGroup/ListGroup.tsx","./components/messages/MessageView/MessageView.tsx","./components/messages/MessageView/MessageViewInline/MessageViewInline.tsx","../shared/client/components/common/Pager/PagerLoadMore/PagerLoadMore.tsx","./components/customComponent/CustomComponentContent/HtmlContent.tsx","./components/customComponent/CustomComponentContent/CustomComponentScripts.tsx"],"appGip":true,"scriptLoader":[]}