TMOS

17 Topics
"}},"componentScriptGroups({\"componentId\":\"custom.widget.Beta_MetaNav\"})":{"__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.Beta_Footer\"})":{"__typename":"Component","render({\"context\":{\"component\":{\"entities\":[],\"props\":{}},\"page\":{\"entities\":[],\"name\":\"TagPage\",\"props\":{},\"url\":\"https://community.f5.com/tag/TMOS\"}}})":{"__typename":"ComponentRenderResult","html":"
 
 
 
 
 

\"F5 ©2024 F5, Inc. All rights reserved.
Trademarks Policies Privacy California Privacy Do Not Sell My Personal Information
"}},"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/TMOS\"}}})":{"__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/TMOS\"}}})":{"__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\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"components/community/NavbarDropdownToggle\"]})":[{"__ref":"CachedAsset:text:en_US-components/community/NavbarDropdownToggle-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageListTabs\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageListTabs-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageView/MessageViewInline\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageView/MessageViewInline-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/common/Pager/PagerLoadMore\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/common/Pager/PagerLoadMore-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"components/customComponent/CustomComponent\"]})":[{"__ref":"CachedAsset:text:en_US-components/customComponent/CustomComponent-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/common/OverflowNav\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/common/OverflowNav-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"components/users/UserLink\"]})":[{"__ref":"CachedAsset:text:en_US-components/users/UserLink-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageSubject\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageSubject-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageBody\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageBody-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageTime\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageTime-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/nodes/NodeIcon\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/nodes/NodeIcon-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageUnreadCount\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageUnreadCount-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageViewCount\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageViewCount-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"components/kudos/KudosCount\"]})":[{"__ref":"CachedAsset:text:en_US-components/kudos/KudosCount-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageRepliesCount\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageRepliesCount-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/users/UserAvatar\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/users/UserAvatar-1744046271000"}]},"Theme:customTheme1":{"__typename":"Theme","id":"customTheme1"},"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","es-ES"]},"repliesSortOrder":{"__typename":"InheritableStringSettingWithPossibleValues","key":"config.user_replies_sort_order","value":"DEFAULT","localValue":"DEFAULT","possibleValues":["DEFAULT","LIKES","PUBLISH_TIME","REVERSE_PUBLISH_TIME"]}},"deleted":false},"CachedAsset:pages-1745486768810":{"__typename":"CachedAsset","id":"pages-1745486768810","value":[{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"HowDoI.GetInvolved.MvpProgram","type":"COMMUNITY","urlPath":"/c/how-do-i/get-involved/mvp-program","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"BlogViewAllPostsPage","type":"BLOG","urlPath":"/category/:categoryId/blog/:boardId/all-posts/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"CasePortalPage","type":"CASE_PORTAL","urlPath":"/caseportal","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"CreateGroupHubPage","type":"GROUP_HUB","urlPath":"/groups/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"CaseViewPage","type":"CASE_DETAILS","urlPath":"/case/:caseId/:caseNumber","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"InboxPage","type":"COMMUNITY","urlPath":"/inbox","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"HowDoI.GetInvolved.AdvocacyProgram","type":"COMMUNITY","urlPath":"/c/how-do-i/get-involved/advocacy-program","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"HowDoI.GetHelp.NonCustomer","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help/non-customer","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"HelpFAQPage","type":"COMMUNITY","urlPath":"/help","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"HowDoI.GetHelp.F5Customer","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help/f5-customer","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"IdeaMessagePage","type":"IDEA_POST","urlPath":"/idea/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"IdeaViewAllIdeasPage","type":"IDEA","urlPath":"/category/:categoryId/ideas/:boardId/all-ideas/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"LoginPage","type":"USER","urlPath":"/signin","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"BlogPostPage","type":"BLOG","urlPath":"/category/:categoryId/blogs/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"HowDoI.GetInvolved","type":"COMMUNITY","urlPath":"/c/how-do-i/get-involved","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"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":1745486768810,"localOverride":null,"page":{"id":"ThemeEditorPage","type":"COMMUNITY","urlPath":"/designer/themes","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"TkbViewAllArticlesPage","type":"TKB","urlPath":"/category/:categoryId/kb/:boardId/all-articles/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"OccasionEditPage","type":"EVENT","urlPath":"/event/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"OAuthAuthorizationAllowPage","type":"USER","urlPath":"/auth/authorize/allow","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"PageEditorPage","type":"COMMUNITY","urlPath":"/designer/pages","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"PostPage","type":"COMMUNITY","urlPath":"/category/:categoryId/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"ForumBoardPage","type":"FORUM","urlPath":"/category/:categoryId/discussions/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"TkbBoardPage","type":"TKB","urlPath":"/category/:categoryId/kb/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"EventPostPage","type":"EVENT","urlPath":"/category/:categoryId/events/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"UserBadgesPage","type":"COMMUNITY","urlPath":"/users/:login/:userId/badges","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"GroupHubMembershipAction","type":"GROUP_HUB","urlPath":"/membership/join/:nodeId/:membershipType","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"MaintenancePage","type":"COMMUNITY","urlPath":"/maintenance","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"IdeaReplyPage","type":"IDEA_REPLY","urlPath":"/idea/:boardId/:messageSubject/:messageId/comments/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"UserSettingsPage","type":"USER","urlPath":"/mysettings/:userSettingsTab","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"GroupHubsPage","type":"GROUP_HUB","urlPath":"/groups","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"ForumPostPage","type":"FORUM","urlPath":"/category/:categoryId/discussions/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"OccasionRsvpActionPage","type":"OCCASION","urlPath":"/event/:boardId/:messageSubject/:messageId/rsvp/:responseType","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"VerifyUserEmailPage","type":"USER","urlPath":"/verifyemail/:userId/:verifyEmailToken","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"AllOccasionsPage","type":"OCCASION","urlPath":"/category/:categoryId/events/:boardId/all-events/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"EventBoardPage","type":"EVENT","urlPath":"/category/:categoryId/events/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"TkbReplyPage","type":"TKB_REPLY","urlPath":"/kb/:boardId/:messageSubject/:messageId/comments/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"IdeaBoardPage","type":"IDEA","urlPath":"/category/:categoryId/ideas/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"CommunityGuideLinesPage","type":"COMMUNITY","urlPath":"/communityguidelines","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"CaseCreatePage","type":"SALESFORCE_CASE_CREATION","urlPath":"/caseportal/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"TkbEditPage","type":"TKB","urlPath":"/kb/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"ForgotPasswordPage","type":"USER","urlPath":"/forgotpassword","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"IdeaEditPage","type":"IDEA","urlPath":"/idea/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"TagPage","type":"COMMUNITY","urlPath":"/tag/:tagName","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"BlogBoardPage","type":"BLOG","urlPath":"/category/:categoryId/blog/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"OccasionMessagePage","type":"OCCASION_TOPIC","urlPath":"/event/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"ManageContentPage","type":"COMMUNITY","urlPath":"/managecontent","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"ClosedMembershipNodeNonMembersPage","type":"GROUP_HUB","urlPath":"/closedgroup/:groupHubId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"HowDoI.GetHelp.Community","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help/community","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"CommunityPage","type":"COMMUNITY","urlPath":"/","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"HowDoI.GetInvolved.ContributeCode","type":"COMMUNITY","urlPath":"/c/how-do-i/get-involved/contribute-code","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"ForumMessagePage","type":"FORUM_TOPIC","urlPath":"/discussions/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"IdeaPostPage","type":"IDEA","urlPath":"/category/:categoryId/ideas/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"BlogMessagePage","type":"BLOG_ARTICLE","urlPath":"/blog/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"RegistrationPage","type":"USER","urlPath":"/register","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"EditGroupHubPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"ForumEditPage","type":"FORUM","urlPath":"/discussions/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"ResetPasswordPage","type":"USER","urlPath":"/resetpassword/:userId/:resetPasswordToken","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"TkbMessagePage","type":"TKB_ARTICLE","urlPath":"/kb/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"HowDoI.Learn.AboutIrules","type":"COMMUNITY","urlPath":"/c/how-do-i/learn/about-irules","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"BlogEditPage","type":"BLOG","urlPath":"/blog/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"HowDoI.GetHelp.F5Support","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help/f5-support","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"ManageUsersPage","type":"USER","urlPath":"/users/manage/:tab?/:manageUsersTab?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"ForumReplyPage","type":"FORUM_REPLY","urlPath":"/discussions/:boardId/:messageSubject/:messageId/replies/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"PrivacyPolicyPage","type":"COMMUNITY","urlPath":"/privacypolicy","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"NotificationPage","type":"COMMUNITY","urlPath":"/notifications","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"UserPage","type":"USER","urlPath":"/users/:login/:userId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"HealthCheckPage","type":"COMMUNITY","urlPath":"/health","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"OccasionReplyPage","type":"OCCASION_REPLY","urlPath":"/event/:boardId/:messageSubject/:messageId/comments/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"ManageMembersPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId/manage/:tab?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"SearchResultsPage","type":"COMMUNITY","urlPath":"/search","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"BlogReplyPage","type":"BLOG_REPLY","urlPath":"/blog/:boardId/:messageSubject/:messageId/replies/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"GroupHubPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"TermsOfServicePage","type":"COMMUNITY","urlPath":"/termsofservice","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"HowDoI.GetHelp","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"HowDoI.GetHelp.SecurityIncident","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help/security-incident","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"CategoryPage","type":"CATEGORY","urlPath":"/category/:categoryId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"ForumViewAllTopicsPage","type":"FORUM","urlPath":"/category/:categoryId/discussions/:boardId/all-topics/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"TkbPostPage","type":"TKB","urlPath":"/category/:categoryId/kbs/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"localOverride":null,"page":{"id":"GroupHubPostPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1745486768810,"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}","userBanned":"We're sorry, but you have been banned from using this site.","userBannedReason":"You have been banned for the following reason: {reason}"},"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},"CachedAsset:theme:customTheme1-1745486311603":{"__typename":"CachedAsset","id":"theme:customTheme1-1745486311603","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","defaultMessageFontFamily":"var(--lia-bs-font-family-base)","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-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/Loading/LoadingDot-1744046271000","value":{"title":"Loading..."},"localOverride":false},"CachedAsset:text:en_US-components/common/EmailVerification-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/common/EmailVerification-1744046271000","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-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-pages/tags/TagPage-1744046271000","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}},"theme":{"__ref":"Theme:customTheme1"},"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-1745486309711":{"__typename":"CachedAsset","id":"quilt:f5.prod:pages/tags/TagPage:board:codeshare-1745486309711","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:text:en_US-components/common/ActionFeedback-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/common/ActionFeedback-1744046271000","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:quiltWrapper:f5.prod:Common:1745486251318":{"__typename":"CachedAsset","id":"quiltWrapper:f5.prod:Common:1745486251318","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.GainsightShared","props":{"widgetVisibility":"signedInOnly","useTitle":true,"useBackground":false,"title":"","lazyLoad":false},"__typename":"QuiltComponent"},{"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:component:custom.widget.GainsightShared-en-us-1745486333270":{"__typename":"CachedAsset","id":"component:custom.widget.GainsightShared-en-us-1745486333270","value":{"component":{"id":"custom.widget.GainsightShared","template":{"id":"GainsightShared","markupLanguage":"HTML","style":null,"texts":{},"defaults":{"config":{"applicablePages":[],"description":"Shared functions for Gainsight integration","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"components":[{"id":"custom.widget.GainsightShared","form":null,"config":null,"props":[],"__typename":"Component"}],"grouping":"TEXTHTML","__typename":"ComponentTemplate"},"properties":{"config":{"applicablePages":[],"description":"Shared functions for Gainsight integration","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"form":null,"__typename":"Component","localOverride":false},"globalCss":null,"form":null},"localOverride":false},"CachedAsset:component:custom.widget.Beta_MetaNav-en-us-1745486333270":{"__typename":"CachedAsset","id":"component:custom.widget.Beta_MetaNav-en-us-1745486333270","value":{"component":{"id":"custom.widget.Beta_MetaNav","template":{"id":"Beta_MetaNav","markupLanguage":"HANDLEBARS","style":null,"texts":{},"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-us-1745486333270":{"__typename":"CachedAsset","id":"component:custom.widget.Beta_Footer-en-us-1745486333270","value":{"component":{"id":"custom.widget.Beta_Footer","template":{"id":"Beta_Footer","markupLanguage":"HANDLEBARS","style":null,"texts":{},"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-us-1745486333270":{"__typename":"CachedAsset","id":"component:custom.widget.Tag_Manager_Helper-en-us-1745486333270","value":{"component":{"id":"custom.widget.Tag_Manager_Helper","template":{"id":"Tag_Manager_Helper","markupLanguage":"HANDLEBARS","style":null,"texts":{},"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-us-1745486333270":{"__typename":"CachedAsset","id":"component:custom.widget.Consent_Blackbar-en-us-1745486333270","value":{"component":{"id":"custom.widget.Consent_Blackbar","template":{"id":"Consent_Blackbar","markupLanguage":"HTML","style":null,"texts":{},"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-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/community/Breadcrumb-1744046271000","value":{"navLabel":"Breadcrumbs","dropdown":"Additional parent page navigation"},"localOverride":false},"CachedAsset:text:en_US-components/tags/TagsHeaderWidget-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/tags/TagsHeaderWidget-1744046271000","value":{"tag":"{tagName}","topicsCount":"{count} {count, plural, one {Topic} other {Topics}}"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageListForNodeByRecentActivityWidget-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageListForNodeByRecentActivityWidget-1744046271000","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:287886":{"__typename":"Conversation","id":"conversation:287886","topic":{"__typename":"TkbTopicMessage","uid":287886},"lastPostingActivityTime":"2024-04-18T13:57:03.073-07:00","solved":false},"User:user:261033":{"__typename":"User","uid":261033,"login":"Stanislas_Piro2","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/m_assets/avatars/default/avatar-2.svg?time=0"},"id":"user:261033"},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODc4ODYtMTAwNzJpNTdFQzg2ODQxMEVGQkI0MQ?revision=2\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0yODc4ODYtMTAwNzJpNTdFQzg2ODQxMEVGQkI0MQ?revision=2","title":"0151T000003d9EkQAI.png","associationType":"BODY","width":1079,"height":539,"altText":null},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODc4ODYtMjYxOGkwMjlCQzQ4RkJCMkQxQ0Uy?revision=2\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0yODc4ODYtMjYxOGkwMjlCQzQ4RkJCMkQxQ0Uy?revision=2","title":"0151T000003d9ElQAI.png","associationType":"BODY","width":1086,"height":607,"altText":null},"TkbTopicMessage:message:287886":{"__typename":"TkbTopicMessage","subject":"TLS server_name extension based routing without clientssl profile","conversation":{"__ref":"Conversation:conversation:287886"},"id":"message:287886","revisionNum":2,"uid":287886,"depth":0,"board":{"__ref":"Tkb:board:codeshare"},"author":{"__ref":"User:user:261033"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":3800},"postTime":"2018-02-08T09:35:21.000-08:00","lastPublishTime":"2023-06-05T22:04:41.461-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Problem this snippet solves: Some configuration requires to not decrypt SSL traffic on F5 appliances to select pool based on HTTP Host header. \n I found a useful irule and this code keeps the structure and most of binary commands of it. I'm not sure if the first author was Kevin Stewart or Colin Walker. thanks both of them to have provided such code. \n I worked to understand it reading TLS 1.2 RFC 5246 and TLS 1.3 draft-23 and provided some enhancements and following description with irule variables references. According to TLS 1.3 draft-23, this code will still be valid with next TLS version. \n the following network diagram shows one use cases where this code will help. \n \n This diagram show how this code works based on the tls_servername_routing_dg Datagroup values and detected server name and TLS versions detected in the CLIENT_HELLO packet. \n \n For performances reasons, only the first TCP data packet is analyzed. \n Versions : \n 1.1 : Updated to support TLS version detection and SSL offload feature. (05/03/2018) \n 1.2 : Updated to support TLS Handshake Failure Messages instead of reject. (09/03/2018) \n 1.3 : Updated to support node forwarding, logs only for debug (disabled with static variable), and changed the Datagroup name to tls_servername_routing_dg . (16/03/2018) \n 1.4 : Added 16K handshake length limit defined in RFC 1.2 in variable payload. (13/04/2018) \n 1.5 : Added supported version extension recursion, to bypass unknown TLS version if a known and allowed version is in the list. This correct an issue with Google chrome which include not documented TLS version on top of the list. (30/04/2018) How to use this snippet: create a virtual server with following configuration: \n type : Standard SSL Profile (client) : Only if you want to enable SSL offload for some pools irule : code bellow \n create all objects used in following datagroup (virtual servers, pools) \n create a data-group named tls_servername_routing_dg. \n if you want to forward to pool, add the value pool NameOfPool if you want to forward to pool and enable SSL Offload (ClientSSL profile must be enabled on virtual server), add the value pool NameOfPool ssl_offload if you want to forward to virtual server, add the value virtual NameOfVirtual if you want to forward to an IP address, add the value node IPOfServer , backend server will not be translated if you want to reject the connection with RFC compliant handshake_failure message, add the value handshake_failure if you want to reject the connection, add the value reject if you want to drop the connection, add the value drop \n The default value keyword is search if there is no TLS server name extension or if TLS server name extension is not found in the data group.\nhere is an example: \n ltm data-group internal tls_servername_routing_dg {\n records {\n app1.company.com {\n data \"virtual vs_app1.company.com\"\n }\n app2.company.com {\n data \"pool p_app2\"\n }\n app3.company.com {\n data \"pool p_app3 ssl_offload\"\n }\n app4.company.com {\n reject\n }\n default {\n data \"handshake_failure\"\n }\n }\n type string\n}\n Code : when RULE_INIT {\n set static::sni_routing_debug 0\n}\n \nwhen CLIENT_ACCEPTED {\n if { [PROFILE::exists clientssl] } {\n # We have a clientssl profile attached to this VIP but we need\n # to find an SNI record in the client handshake. To do so, we'll\n # disable SSL processing and collect the initial TCP payload.\n set ssldisable \"SSL::disable\"\n set sslenable \"SSL::enable\"\n eval $ssldisable\n } \n TCP::collect\n set default_pool [LB::server pool]\n set tls_servername \"\"\n set tls_handshake_prefered_version \"0000\"\n}\nwhen CLIENT_DATA {\n # Store TCP Payload up to 2^14 + 5 bytes (Handshake length is up to 2^14)\n set payload [TCP::payload 16389]\n set payloadlen [TCP::payload length]\n \n # - Record layer content-type (1 byte) --> variable tls_record_content_type\n # Handshake value is 22 (required for CLIENT_HELLO packet)\n # - SSLv3 / TLS version. (2 byte) --> variable tls_version\n # SSLv3 value is 0x0300 (doesn't support SNI, not valid in first condition)\n # TLS_1.0 value is 0x0301\n # TLS_1.1 value is 0x0302, 0x0301 in CLIENT_HELLO handskake packet for backward compatibility (not specified in RFC, that's why the value 0x0302 is allowed in condition)\n # TLS_1.2 value is 0x0303, 0x0301 in CLIENT_HELLO handskake packet for backward compatibility (not specified in RFC, that's why the value 0x0303 is allowed in condition)\n # TLS_1.3 value is 0x0304, 0x0301 in CLIENT_HELLO handskake packet for backward compatibility (explicitly specified in RFC)\n # TLS_1.3 drafts values are 0x7FXX (XX is the hexadecimal encoded draft version), 0x0301 in CLIENT_HELLO handskake packet for backward compatibility (explicitly specified in RFC)\n # - Record layer content length (2 bytes) : must match payload length --> variable tls_recordlen\n # - TLS Hanshake protocol (length defined by Record layer content length value)\n # - Handshake action (1 byte) : CLIENT_HELLO = 1 --> variable tls_handshake_action\n # - handshake length (3 bytes)\n # - SSL / TLS handshake version (2 byte)\n # In TLS 1.3 CLIENT_HELLO handskake packet, TLS hanshake version is sent whith 0303 (TLS 1.2) version for backward compatibility. a new TLS extension add version negociation.\n # - hanshake random (32 bytes)\n # - handshake sessionID length (1 byte) --> variable tls_handshake_sessidlen\n # - handshake sessionID (length defined by sessionID length value, max 32-bit)\n # - CipherSuites length (2 bytes) --> variable tls_ciphlen\n # - CipherSuites (length defined by CipherSuites length value)\n # - Compression length (2 bytes) --> variable tls_complen\n # - Compression methods (length defined by Compression length value)\n # - Extensions \n # - Extension length (2 bytes) --> variable tls_extension_length\n # - list of Extensions records (length defined by extension length value)\n # - extension record type (2 bytes) : server_name = 0, supported_versions = 43--> variable tls_extension_type\n # - extension record length (2 bytes) --> variable tls_extension_record_length\n # - extension data (length defined by extension record length value)\n #\n # TLS server_name extension data format:\n # - SNI record length (2 bytes)\n # - SNI record data (length defined by SNI record length value)\n # - SNI record type (1 byte)\n # - SNI record value length (2 bytes)\n # - SNI record value (length defined by SNI record value length value) --> variable tls_servername\n #\n # TLS supported_version extension data format (added in TLS 1.3):\n # - supported version length (1 bytes) --> variable tls_supported_versions_length\n # - List of supported versions (2 bytes per version) --> variable tls_supported_versions\n \n \n \n # If valid TLS 1.X CLIENT_HELLO handshake packet\n if { [binary scan $payload cH4Scx3H4x32c tls_record_content_type tls_version tls_recordlen tls_handshake_action tls_handshake_version tls_handshake_sessidlen] == 6 && \\\n ($tls_record_content_type == 22) && \\\n ([string match {030[1-3]} $tls_version]) && \\\n ($tls_handshake_action == 1) && \\\n ($payloadlen == $tls_recordlen+5)} {\n \n # store in a variable the handshake version\n set tls_handshake_prefered_version $tls_handshake_version\n \n # skip past the session id\n set record_offset [expr {44 + $tls_handshake_sessidlen}]\n \n # skip past the cipher list\n binary scan $payload @${record_offset}S tls_ciphlen\n set record_offset [expr {$record_offset + 2 + $tls_ciphlen}]\n \n # skip past the compression list\n binary scan $payload @${record_offset}c tls_complen\n set record_offset [expr {$record_offset + 1 + $tls_complen}]\n \n # check for the existence of ssl extensions\n if { ($payloadlen > $record_offset) } {\n # skip to the start of the first extension\n binary scan $payload @${record_offset}S tls_extension_length\n set record_offset [expr {$record_offset + 2}]\n # Check if extension length + offset equals payload length\n if {$record_offset + $tls_extension_length == $payloadlen} {\n # for each extension\n while { $record_offset < $payloadlen } {\n binary scan $payload @${record_offset}SS tls_extension_type tls_extension_record_length\n if { $tls_extension_type == 0 } {\n # if it's a servername extension read the servername\n # SNI record value start after extension type (2 bytes), extension record length (2 bytes), record type (2 bytes), record type (1 byte), record value length (2 bytes) = 9 bytes\n binary scan $payload @[expr {$record_offset + 9}]A[expr {$tls_extension_record_length - 5}] tls_servername\n set record_offset [expr {$record_offset + $tls_extension_record_length + 4}]\n \n } elseif { $tls_extension_type == 43 } {\n # if it's a supported_version extension (starting with TLS 1.3), extract supported version in a list\n binary scan $payload @[expr {${record_offset} + 4}]cS[expr {($tls_extension_record_length -1)/2}] tls_supported_versions_length tls_supported_versions\n set tls_handshake_prefered_version [list]\n foreach version $tls_supported_versions {\n lappend tls_handshake_prefered_version [format %04X [expr { $version & 0xffff }] ]\n }\n if {$static::sni_routing_debug} {log local0. \"[IP::remote_addr] : prefered version list : $tls_handshake_prefered_version\"}\n set record_offset [expr {$record_offset + $tls_extension_record_length + 4}]\n } else {\n # skip over other extensions\n set record_offset [expr {$record_offset + $tls_extension_record_length + 4}]\n }\n }\n }\n }\n } elseif { [binary scan $payload cH4 ssl_record_content_type ssl_version] == 2 && \\\n ($tls_record_content_type == 22) && \\\n ($tls_version == 0300)} {\n # SSLv3 detected\n set tls_handshake_prefered_version \"0300\"\n } elseif { [binary scan $payload H2x1H2 ssl_version handshake_protocol_message] == 2 && \\\n ($ssl_version == 80) && \\\n ($handshake_protocol_message == 01)} {\n # SSLv2 detected\n set tls_handshake_prefered_version \"0200\"\n }\n unset -nocomplain payload payloadlen tls_record_content_type tls_recordlen tls_handshake_action tls_handshake_sessidlen record_offset tls_ciphlen tls_complen tls_extension_length tls_extension_type tls_extension_record_length tls_supported_versions_length tls_supported_versions\n \n foreach version $tls_handshake_prefered_version {\n switch -glob -- $version {\n \"0200\" {\n if {$static::sni_routing_debug} {log local0. \"[IP::remote_addr] : SSLv2 ; connection is rejected\"}\n reject\n return\n }\n \"0300\" -\n \"0301\" {\n if {$static::sni_routing_debug} {log local0. \"[IP::remote_addr] : SSL/TLS ; connection is rejected (0x$version)\"}\n # Handshake Failure packet format:\n #\n # - Record layer content-type (1 byte) --> variable tls_record_content_type\n # Alert value is 21 (required for Handshake Failure packet)\n # - SSLv3 / TLS version. (2 bytes) --> from variable tls_version\n # - Record layer content length (2 bytes) : value is 2 for Alert message\n # - TLS Message (length defined by Record layer content length value)\n # - Level (1 byte) : value is 2 (fatal)\n # - Description (1 bytes) : value is 40 (Handshake Failure)\n TCP::respond [binary format cH4Scc 21 $tls_version 2 2 40]\n after 10\n TCP::close\n #drop\n #reject\n return\n }\n \"030[2-9]\" -\n \"7F[0-9A-F][0-9A-F]\" {\n # TLS version allowed, do nothing\n break\n }\n \"0000\" {\n if {$static::sni_routing_debug} {log local0. \"[IP::remote_addr] : No SSL/TLS protocol detected ; connection is rejected (0x$version)\"}\n reject\n return\n }\n default {\n if {$static::sni_routing_debug} {log local0. \"[IP::remote_addr] : Unknown CLIENT_HELLO TLS handshake prefered version : 0x$version\"}\n }\n }\n }\n \n if { $tls_servername equals \"\" || ([set sni_dg_value [class match -value [string tolower $tls_servername] equals tls_servername_routing_dg]] equals \"\")} {\n set sni_dg_value [class match -value \"default\" equals tls_servername_routing_dg]\n }\n \n switch [lindex $sni_dg_value 0] {\n \"virtual\" {\n if {[catch {virtual [lindex $sni_dg_value 1]}]} {\n if {$static::sni_routing_debug} {log local0. \"[IP::remote_addr] : TLS server_name value = ${tls_servername} ; TLS prefered version = 0x${tls_handshake_prefered_version} ; Virtual server [lindex $sni_dg_value 1] doesn't exist\"}\n } else {\n if {$static::sni_routing_debug} {log local0. \"[IP::remote_addr] : TLS server_name value = ${tls_servername} ; TLS prefered version = 0x${tls_handshake_prefered_version} ; forwarded to Virtual server [lindex $sni_dg_value 1]\"}\n }\n }\n \"pool\" {\n if {[catch {pool [lindex $sni_dg_value 1]}]} {\n if {$static::sni_routing_debug} {log local0. \"[IP::remote_addr] : TLS server_name value = ${tls_servername} ; TLS prefered version = 0x${tls_handshake_prefered_version} ; Pool [lindex $sni_dg_value 1] doesn't exist\"}\n } else {\n if {$static::sni_routing_debug} {log local0. \"[IP::remote_addr] : TLS server_name value = ${tls_servername} ; TLS prefered version = 0x${tls_handshake_prefered_version} ; forwarded to Pool [lindex $sni_dg_value 1]\"}\n }\n if {[lindex $sni_dg_value 2] equals \"ssl_offload\" && [info exists sslenable]} {\n eval $sslenable\n }\n }\n \"node\" {\n if {[catch {node [lindex $sni_dg_value 1]}]} {\n if {$static::sni_routing_debug} {log local0. \"[IP::remote_addr] : TLS server_name value = ${tls_servername} ; TLS prefered version = 0x${tls_handshake_prefered_version} ; Invalid Node value [lindex $sni_dg_value 1]\"}\n } else {\n if {$static::sni_routing_debug} {log local0. \"[IP::remote_addr] : TLS server_name value = ${tls_servername} ; TLS prefered version = 0x${tls_handshake_prefered_version} ; forwarded to Node [lindex $sni_dg_value 1]\"}\n }\n }\n \"handshake_failure\" {\n if {$static::sni_routing_debug} {log local0. \"[IP::remote_addr] : TLS server_name value = ${tls_servername} ; TLS prefered version = 0x${tls_handshake_prefered_version} ; connection is rejected (with Handshake Failure message)\"}\n TCP::respond [binary format cH4Scc 21 $tls_handshake_prefered_version 2 2 40]\n after 10\n TCP::close\n return\n }\n \"reject\" {\n if {$static::sni_routing_debug} {log local0. \"[IP::remote_addr] : TLS server_name value = ${tls_servername} ; TLS prefered version = 0x${tls_handshake_prefered_version} ; connection is rejected\"}\n reject\n return\n }\n \"drop\" {\n if {$static::sni_routing_debug} {log local0. \"[IP::remote_addr] : TLS server_name value = ${tls_servername} ; TLS prefered version = 0x${tls_handshake_prefered_version} ; connection is dropped\"}\n drop\n return\n }\n }\n TCP::release\n} ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"16659","kudosSumWeight":6,"repliesCount":10,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDE","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODc4ODYtMTAwNzJpNTdFQzg2ODQxMEVGQkI0MQ?revision=2\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDI","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODc4ODYtMjYxOGkwMjlCQzQ4RkJCMkQxQ0Uy?revision=2\"}"}}],"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: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":2211},"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:286346":{"__typename":"Conversation","id":"conversation:286346","topic":{"__typename":"TkbTopicMessage","uid":286346},"lastPostingActivityTime":"2023-06-05T22:57:49.333-07:00","solved":false},"User:user:130914":{"__typename":"User","uid":130914,"login":"Walter_Kacynski","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/images/dS0xMzA5MTQtWHN5SkU0?image-coordinates=0%2C0%2C256%2C256"},"id":"user:130914"},"TkbTopicMessage:message:286346":{"__typename":"TkbTopicMessage","subject":"AppDynamics EUM JavaScript Injection for Selective URLs","conversation":{"__ref":"Conversation:conversation:286346"},"id":"message:286346","revisionNum":2,"uid":286346,"depth":0,"board":{"__ref":"Tkb:board:codeshare"},"author":{"__ref":"User:user:130914"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":684},"postTime":"2016-02-18T04:26:03.000-08:00","lastPublishTime":"2023-06-05T22:57:49.333-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Problem this snippet solves: This code allows for the adrum.js agent to be dynamically injected into an application to support collecting EUM metrics. With this code, you can select from any number of HTTP Request headers and/or POST parameters. \n Additional EUM features in use: \n Custom GeoIP mappings based on a DataGroup User Data for Browser Snapshots, currently APM SID and Username How to use this snippet: This sample iRule assumes that the TCL variables $username and $sid have been previously created to support the UserData injection. If you don't have this information or APM available then these lines should be commented out or changed to meet your needs. \n Import the ltm profiles and iRule via \n tmsh load sys config merge <from-terminal>\n \n\n On your virtual, attache the Head-HTML profile as well as the iRule. Code : LTM Profiles Required:\n\nltm html-rule tag-raise-event HTMLEvent-HeadStart-HTMLRule {\n description \"Match an HTML tag for \"\n match {\n tag-name head\n }\n}\nltm profile html Head-HTML {\n app-service none\n content-detection disabled\n content-selection { text/html text/xhtml }\n defaults-from html\n description none\n rules {\n HTMLEvent-HeadStart-HTMLRule\n }\n}\n\niRule to be attached to the Virtual:\nltm rule SND-AppDynamics-HTML-Rule {\n\nwhen CLIENT_ACCEPTED {\n set APPDYNAMICS_EUM_DEBUG 0;\n}\n\nwhen HTTP_REQUEST {\n set APPDYNAMICS_EUM_APP_ID \"AD-xxx-xxx-xxx-xxx\"\n if { $APPDYNAMICS_EUM_DEBUG > 0 } {set uri [HTTP::uri]}\n \n if {[HTTP::uri] starts_with \"/my/HomePage.do\"} {\n # set enableEum 1\n if { [HTTP::header Content-Type] eq \"application/x-www-form-urlencoded\" } {\n # HTTP::collect [HTTP::header Content-Length]\n # Only collect the first 200 bytes which should be enough to capture eventSource\n HTTP::collect 200\n } else {\n if {[HTTP::uri] starts_with \"/my/defaultPage\"} {\n set enableEum 1\n }\n }\n } elseif {[HTTP::uri] starts_with \"/app1\"} {\n set enableEum 1\n } elseif {[HTTP::uri] starts_with \"/app2\"} {\n set enableEum 1\n}\n\nwhen HTTP_REQUEST_DATA {\n set namevals [split [HTTP::payload] \"&\"]\n for {set i 0} {$i < [llength $namevals]} {incr i} {\n set params [split [lindex $namevals $i] \"=\"]\n # log local0. \" [lindex $params 0] : [lindex $params 1]\"\n if {[lindex $params 0] equals \"eventSource\"} {\n switch -glob [lindex $params 1] {\n \"PostParm1\" -\n \"PostParm2\" -\n \"PostParm3\" {\n set enableEum 1\n if { $APPDYNAMICS_EUM_DEBUG > 0 } { log local0. \"FOUND HTTP DATA [lindex $params 1] TO ENABLE APPDYNAMICS EUM\"; }\n }\n }\n break;\n }\n unset params\n }\n unset namevals\n}\n\nwhen HTTP_RESPONSE {\n if {[info exists enableEum]} {\n if { ($enableEum == 1) && ([HTTP::header \"Content-Type\"] starts_with \"text/html\") } {\n HTML::enable\n set enableEum 0\n } else {\n HTML::disable\n }\n } else {\n HTML::disable\n }\n}\n\nwhen HTML_TAG_MATCHED {\n if { $APPDYNAMICS_EUM_DEBUG > 0 } { log local0. \"uri = $uri element = [HTML::tag name] attribute id = [HTML::tag attribute id]\"}\n \n switch [HTML::tag name] {\n \"head\" {\n if { $APPDYNAMICS_EUM_DEBUG > 0 } { log local0. \"$uri info username [info exists username] info sid [info exists sid]\"}\n if {([info exists username]) && ([info exists sid])} {\n # Send custom GeoIP Data to with the adrum beacon if we are on the private network\n set geoData [split [class match -value [IP::client_addr] equals Branch-Address-DataGroup ] \"/\"]\n if { $geoData != \"\" } {\n HTML::tag append [subst {\n \n window\\[\"adrum-app-key\"\\] = \"$APPDYNAMICS_EUM_APP_ID\";\n window\\[\"adrum-start-time\"\\] = new Date().getTime();\n window\\[\"adrum-geo-resolver-url\"\\] = \"thisdoesnotmatter\";\n window\\[\"adrum-config\"\\] = {\n geo: {\n \"country\": \"United States\",\n \"region\": \"[lindex $geoData 0]\",\n \"city\": \"[lindex $geoData 1]\",\n \"localIP\": \"[IP::client_addr]\"\n }\n };\n \n \n \n if (ADRUM)\n { ADRUM.command (\"addUserData\", \"User\", \"$username\"); }\n { ADRUM.command (\"addUserData\", \"LastMRH_Session\", \"$sid\"); }\n \n } ]\n } else {\n HTML::tag append [subst {\n \n window\\[\"adrum-app-key\"\\] = \"$APPDYNAMICS_EUM_APP_ID\";\n window\\[\"adrum-start-time\"\\] = new Date().getTime();\n \n \n \n if (ADRUM)\n { ADRUM.command (\"addUserData\", \"User\", \"$username\"); }\n { ADRUM.command (\"addUserData\", \"LastMRH_Session\", \"$sid\"); }\n \n } ]\n }\n unset geoData\n }\n }\n }\n}\n} Tested this on version: 11.5","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"4977","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}}},"Conversation:conversation:287908":{"__typename":"Conversation","id":"conversation:287908","topic":{"__typename":"TkbTopicMessage","uid":287908},"lastPostingActivityTime":"2023-06-05T22:02:08.134-07:00","solved":false},"TkbTopicMessage:message:287908":{"__typename":"TkbTopicMessage","subject":"Use F5 LTM as HTTP Proxy","conversation":{"__ref":"Conversation:conversation:287908"},"id":"message:287908","revisionNum":2,"uid":287908,"depth":0,"board":{"__ref":"Tkb:board:codeshare"},"author":{"__ref":"User:user:261033"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":11010},"postTime":"2018-05-04T09:52:24.000-07:00","lastPublishTime":"2023-06-05T22:02:08.134-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Problem this snippet solves: LTM product can be used as a HTTP Proxy for servers and PC. \n This code explains minimum requirements to configure proxy feature without SWG module (configurations from Explicit Forward Proxy documentation without documentation ) and without explicit proxy iApp. How to use this snippet: All these commands must be run in bash shell. \n Create HTTP PROXY VIRTUAL SERVER \n Configure variables used in next commands \n Variable HTTPBaseName is used to create : \n Resolver object : RESOLVER_${HTTPBaseName} HTTP profile : http_${HTTPBaseName} virtual server : VS_${HTTPBaseName} \n \n HTTPBaseName=\"HTTP_FORWARD_PROXY\"\nVS_IP=\"192.168.2.80\"\nVS_PORT=\"8080\"\n \n\n create DNS resolver with your DNS server (1.1.1.1 is for demo using cloudflare) \n tmsh create net dns-resolver RESOLVER_${HTTPBaseName} { forward-zones replace-all-with { . { nameservers replace-all-with { 1.1.1.1:domain { } } } } route-domain 0 }\n \n\n create HTTP profile type explicit, using DNS resolver. \n The parameter default-connect-handling allow enables HTTPS connections without SSL inspection \n tmsh create ltm profile http http_${HTTPBaseName} { defaults-from http-explicit explicit-proxy { default-connect-handling allow dns-resolver RESOLVER_${HTTPBaseName} } proxy-type explicit }\n \n\n create HTTP proxy Virtual server \n tmsh create ltm virtual VS_${HTTPBaseName} { destination ${VS_IP}:${VS_PORT} ip-protocol tcp mask 255.255.255.255 profiles replace-all-with { http_${HTTPBaseName} { } tcp } source 0.0.0.0/0 source-address-translation { type automap } translate-address enabled translate-port enabled}\n \n\n ENABLE SSL FORWARD PROXY \n This section is not required to forward HTTPS requests but only to enable SSL inspection on HTTPS requests. Note : Following configuration requires SSL, Forward Proxy License. \n Configure variables used in next commands \n Variable SSLBaseName is used to create : \n certificate / key pair : ${SSLBaseName} Client SSL profile : clientssl_${SSLBaseName} Server SSL profile : serverssl_${SSLBaseName} virtual server : VS_${SSLBaseName} \n \n SSLBaseName=\"SSL_FORWARD_PROXY\"\ndirname=\"/var/tmp\"\nCASubject=\"/C=FR/O=DEMO\\ COMPANY/CN=SSL\\ FORWARD\\ PROXY\\ CA\"\n \n\n Create self-signed certificate for CA purpose (not available in WebUI) \n Self-signed certificates created in WebUI doesn't have CA capability required for SSL FORWARD PROXY. \n openssl genrsa -out ${dirname}/${SSLBaseName}.key 4094\nopenssl req -sha512 -new -x509 -days 3650 -key ${dirname}/${SSLBaseName}.key -out ${dirname}/${SSLBaseName}.crt -subj \"${CASubject}\"\n \n\n Import certificates in TMOS \n tmsh install sys crypto key ${SSLBaseName}.key from-local-file ${dirname}/${SSLBaseName}.key; \ntmsh install sys crypto cert ${SSLBaseName}.crt from-local-file ${dirname}/${SSLBaseName}.crt; \n \n\n After CA Certificate is imported, browse in WebUI, retrieve it and import it in client browsers trusted CA \n Create SSL profiles for SSL FORWARD PROXY \n tmsh create ltm profile client-ssl clientssl_${SSLBaseName} { cert-lookup-by-ipaddr-port disabled defaults-from clientssl mode enabled proxy-ca-cert ${SSLBaseName}.crt proxy-ca-key ${SSLBaseName}.key ssl-forward-proxy enabled }\ntmsh create ltm profile server-ssl serverssl_${SSLBaseName} { defaults-from serverssl ssl-forward-proxy enabled }\n \n\n create SSL FORWARD PROXY Virtual server \n tmsh create ltm virtual VS_${SSLBaseName} { destination 0.0.0.0:https ip-protocol tcp profiles replace-all-with { clientssl_${SSLBaseName} { context clientside } serverssl_${SSLBaseName} { context serverside } http { } tcp { } } source 0.0.0.0/0 translate-address disabled translate-port disabled vlans replace-all-with { http-tunnel } vlans-enabled }\n \n\n Change HTTP EXPLICIT PROXY Default Connect Handling to Deny \n tmsh modify ltm profile http http_${HTTPBaseName} explicit-proxy { default-connect-handling deny }\n \n\n Note : These commands were tested in both 12.1 and 13.1 versions. Code : No Code ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"3979","kudosSumWeight":1,"repliesCount":24,"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:276213":{"__typename":"Conversation","id":"conversation:276213","topic":{"__typename":"TkbTopicMessage","uid":276213},"lastPostingActivityTime":"2022-08-04T08:53:46.232-07:00","solved":false},"User:user:117259":{"__typename":"User","uid":117259,"login":"Kiozs_131042","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/m_assets/avatars/default/avatar-8.svg?time=0"},"id":"user:117259"},"TkbTopicMessage:message:276213":{"__typename":"TkbTopicMessage","subject":"BIGIP LTM Automated Pool Monitor Flap Troubleshooting Script in Bash","conversation":{"__ref":"Conversation:conversation:276213"},"id":"message:276213","revisionNum":1,"uid":276213,"depth":0,"board":{"__ref":"Tkb:board:codeshare"},"author":{"__ref":"User:user:117259"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":992},"postTime":"2015-06-17T21:40:40.000-07:00","lastPublishTime":"2015-06-17T21:40:40.000-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Problem this snippet solves: A bash script is mainly for collecting data when F5 BIG-IP LTM pool member monitor flaps in a period of time and help determine the Root Cause of BIGIP monitor health check failure; \nScript will monitor the LTM logs, if new pool member down message event occurs, script will perform following functions:\n1. Turn on LTM bigd debug ;\n2. Start to tcpdump capture to capture relevant traffics; \n3. Turn off bigd debug and terminate tcpdump process when timer elapse (timer is configurable) \n4. Generate qkview (optinal)\n5. Tar ball full logs files under /var/log/ directory (optinal) \n Script has been tested on v11.x Code : #!/usr/bin/bash\n##########identify the log file that script is monitoring \nfilename=\"/var/log/ltm\"\n##########identify the period of time that debug and tcpdump are running, please change it according to the needs;\ntimer=60\n##########IP address of pool member flaps \npoolMemberIP=\"10.10.10.229\"\n##########self IP address of LTM is usd to send LTM Health Monitor traffics\nltmSelfip=\"10.10.10.248\"\n##########pool member service port number\npoolMemberPort=\"443\"\n##########TMOS command to turn on bigd debug \nturnonBigdDebug=\"tmsh modify sys db bigd.debug value enable\"\n##########TMOS command to turn off bigd debug \nturnoffBigdDebug=\"tmsh modify sys db bigd.debug value disable\"\n##########BASH command to tar BIGIP log files \ntarLogs=\"tar -czpf /var/tmp/logfiles.tar.gz /var/log/*\"\n\n\n\n####### function file check: following code will check if /var/log/ltm exist on the system, \n####### if it exists, script will be running and perform subsequent functions \nif [ -f $filename ]\nthen\n echo \"/var/log/ltm exists and program is running to collect data when BG-IP pool member flaps\"\nelse\n####### if it does not exist, programe will be terminated and log following message \n echo \"no /var/log/ltm file found and program is terminated\"\nexit 0\nfi\n####### function file check ends\n\n###### write timestap to /var/log/ltm for tracking purpose\necho \"$(date) monitoring the log\" >> $filename\n\n###### start to monitor the /var/log/ltm for new events \ntail -f -n 0 $filename | while read -r line\ndo\n\n###### counter for pool down message appears\nhit=$(echo \"$line\" | grep -c \"$poolMemberIP:$poolMemberPort monitor status down\")\n\n#echo $hit\n###### \nif [ \"$hit\" == \"1\" ];\n then\n###### diplay the pool down log event in file /var/log/ltm \n echo $line\n###### show timestamp of debug is on \n echo \"$(date) Turning on system bigddebug\"\n###### turn on bigd debug \n echo $($turnonBigdDebug)\n###### turn on tcpdump capture \n echo $(tcpdump -ni 0.0:nnn -s0 -w /var/tmp/Monitor.pcap port $poolMemberPort and \\(host $poolMemberIP and host $ltmSelfip\\)) &\n###### running timer \n sleep $timer\n###### show timestamp of debug is off \n echo \"$(date) Truning off system bigddebug\"\n###### turn off bigd debug \n echo $($turnoffBigdDebug)\n###### terminate tcpdump process \n echo $(killall tcpdump)\n###### generate qkview, it's an optional function, enable it by remove \"#\" sign\n #echo $(qkview)\n###### tar log files, it's an optional function, enable it by remove \"#\" sign\n #echo $($tarLogs)\n break\n\n#else\n #echo \"Monitor in progress\"\nfi\ndone\n###### show message that programe is end \necho \"$(date) exiting from programe\"\n\n###### exit from the program \nexit 0 Tested this on version: 11.6","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"3351","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:291469":{"__typename":"Conversation","id":"conversation:291469","topic":{"__typename":"TkbTopicMessage","uid":291469},"lastPostingActivityTime":"2021-06-30T02:52:56.000-07:00","solved":false},"User:user:305752":{"__typename":"User","uid":305752,"login":"Nikoolayy1","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/images/dS0zMDU3NTItd2tMWnln?image-coordinates=3%2C3%2C176%2C176"},"id":"user:305752"},"TkbTopicMessage:message:291469":{"__typename":"TkbTopicMessage","subject":"Knowledge sharing: Ways to trigger and schedule scripts on the F5 BIG-IP devices.","conversation":{"__ref":"Conversation:conversation:291469"},"id":"message:291469","revisionNum":1,"uid":291469,"depth":0,"board":{"__ref":"Tkb:board:codeshare"},"author":{"__ref":"User:user:305752"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":1278},"postTime":"2021-06-30T02:52:56.000-07:00","lastPublishTime":"2021-06-30T02:52:56.000-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Problem this snippet solves: Available script and rest-api options for f5 automatic configurations. How to use this snippet: Code : I think that it is interesting to share how on F5 different scripts can be run at different times and states.\n\n \n\n \n\n1.You can use the cron job like on any linux device to run a script. As I have used this to restart the tomcat and httpd each night with \"bigstart restart \" or \"tmsh restart /sys service \" (https://support.f5.com/csp/article/K89999342), because of a bug till I upgade the devices (https://support.f5.com/csp/article/K25554628 ).\n\n \n\n \n\nhttps://support.f5.com/csp/article/K03108954\n\n \n\n \n\n \n\n \n\n \n\n2.Newer versions of F5 also have anacron tool that can add some randomness to the timframe when a script is run and many F5 default scripts use this and not the crontab:\n\n \n\n \n\nhttps://support.f5.com/csp/article/K33730915\n\n \n\n \n\n \n\n3.You can even trigger scripts on the F5 device if the state changes from active to standby or from standby to active by adding the scripts under /config/failover/ . For example if you have a bug for a critical process that causes a failover ( you can use the command show /sys ha-status all-properties to check for this https://support.f5.com/csp/article/K20060182 ) but the device does not reboot or fix the process you can run a script to when the device becomes standby to restart the process.\n\n \n\n \n\nhttps://support.f5.com/csp/article/K6008\n\n \n\n \n\n \n\n \n\n \n\n4.You afcource can run scripts at the F5 start time (startup/bootup):\n\n \n\n \n\nhttps://support.f5.com/csp/article/K11948\n\n \n\n \n\n \n\n \n\n \n\n5.The final thing thing I can think of is to run a script at the backround that monitors the log and for example when there is a specific message in /var/log/ltm to trigger a tcpdump (in some cases better than creating a rotating tcpdum to catch an issue as per https://support.f5.com/csp/article/K65251607 ). The script can be a bash script with \"tail -f\" command that is run on the backround or better use the F5 intergrated \"icall\" feature.\n\n \n\n \n\nBash:\n\n \n\nhttps://www.thegeekstuff.com/2010/12/5-ways-to-execute-linux-command/\n\n \n\n \n\nIcall:\n\n \n\nhttps://devcentral.f5.com/s/articles/what-is-icall-27404\n\n \n\nhttps://devcentral.f5.com/s/articles/run-tcpdump-on-event\n\n \n\n \n\n \n\n \n\n \n\n5.You can use utility \"logger -p\" to generate manually log messages in the F5 device's log for testing of your scripts as this is used also for SNMP custom alarm traps tests (for more about SNMP https://support.f5.com/csp/article/K3727 )\n\n \n\n \n\nhttps://support.f5.com/csp/article/K86480148\n\n \n\n \n\n \n\n6.You can also trigger scripts from an BIG-IQ device bt you still can't schedule them when to run:\n\n \n\nhttps://clouddocs.f5.com/training/community/big-iq-cloud-edition/html/class5/module1/lab6.html\n\n \n\n \n\n \n\n \n\n7.Of course the final option is to use ansible or python SDK that uses the F5 rest-api to execute commands on the F5 devices.\n\n \n\n \n\nhttps://f5-sdk.readthedocs.io/en/latest/\n\n \n\n \n\n \n\n \n\n \n\n \n\n8. You can even use TCP expect and bash for automations using SSH connection but this is really old way to do things:\n\n \n\n \n\nhttps://devcentral.f5.com/s/articles/f5-automation-tcl-amp-bash-921\n\n \n\n https://f5-sdk.readthedocs.io/en/latest/userguide/ltm_pools_members_code_example.html\n\n \n\n \n\n \n\n \n\n \n\n \n\n9.F5 is well integrated with Ansible and it is better than REST-API Python SDK or TCL for me as even the declarative AS3 interface is supported:\n\n \n\n \n\nhttps://clouddocs.f5.com/products/orchestration/ansible/devel/\n\n \n\n https://clouddocs.f5.com/products/orchestration/ansible/devel/\n\n \n\n \n\nhttps://www.f5.com/partners/technology-alliances/ansible\n\n \n\n \n\nImperative:\n\n \n\nhttps://support.f5.com/csp/article/K42420223\n\n \n\nhttps://clouddocs.f5.com/products/orchestration/ansible/devel/usage/playbook_tutorial.html\n\n \n\nDeclaritive:\n\n \n\nhttps://www.f5.com/company/blog/f5-as3-and-red-hat-ansible-automation\n\n \n\nhttps://clouddocs.f5.com/training/fas-ansible-workshop-101/3.0-as3-intro.html\n\n \n\n \n\n \n\n \n\n \n\n10.For some automations without rest-api better use the F5 native cli scripts than bash with tmsh commands:\n\n \n\n \n\nhttps://clouddocs.f5.com/cli/tmsh-reference/v14/modules/cli/cli_script.html\n\n \n\n \n\nhttps://clouddocs.f5.com/api/tmsh/script__run.html Tested this on version: No Version Found","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"4269","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:289125":{"__typename":"Conversation","id":"conversation:289125","topic":{"__typename":"TkbTopicMessage","uid":289125},"lastPostingActivityTime":"2020-12-22T01:57:52.000-08:00","solved":false},"User:user:175623":{"__typename":"User","uid":175623,"login":"Lee_Sutcliffe","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:175623"},"TkbTopicMessage:message:289125":{"__typename":"TkbTopicMessage","subject":"Quick and dirty shell script to find unused certificates","conversation":{"__ref":"Conversation:conversation:289125"},"id":"message:289125","revisionNum":1,"uid":289125,"depth":0,"board":{"__ref":"Tkb:board:codeshare"},"author":{"__ref":"User:user:175623"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":1913},"postTime":"2019-05-16T00:24:13.000-07:00","lastPublishTime":"2019-05-16T00:24:13.000-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Problem this snippet solves: This has been edited quite a bit since I first posted so it's probably not as quick and dirty as it was before. This in response to a question regarding removing unused certificates https://devcentral.f5.com/questions/how-to-find-the-unused-ssl-certificates-63166 The following bash script will output any installed certificate names to a file, then iterate over each line. If the certificate is not referenced in bigip.conf in either the /config/ or within a partition folder, then it can be reasonably assumed it is not in use and can be safely deleted. The script will give you the option to delete any certs that are not in use and save a UCS archive (just in case) If there are any keys associated with the certificate, this will be deleted too. As the moment, the script will not look for keys without an equivalent cert, e.g. my-cert.key and my-cert.crt. So you many still end up with rouge keys. I'll look to get this updated eventually. There is an array called ignoreCerts ignoreCerts=(\"f5-irule.crt\" \"ca-bundle.crt\")\n Here you can add certificates you may want to ignore. For example, f5-irule.crt is used to sign F5 provided iRules and bigip.conf does not reference it. Add any additional certs to this array to ensure they are not deleted Script can be downloaded directly from GitLab using the link below https://gitlab.com/stratalabs/f5-devcental/snippets/1863498/raw?inline=false How to use this snippet: paste into vi chmod +x myScript.sh ./myScript.sh Code : #!/bin/sh\n\nfunction buildInstalledCertsArray {\n tmsh save sys config partitions all\n tmsh list sys file ssl-cert | awk '/crt/ {print $4}' | sed '/^[[:space:]]*$/d' > /var/tmp/installedCerts.tmp\n\n # iterate over tmp file to create array of used certificates\n while read line; do\n for i in \"${!ignoreCerts[@]}\"; do\n if [[ $line = ${ignoreCerts[$i]} ]]; then\n ignore=\"true\"\n else\n if [[ $ignore != \"true\" ]];then\n ignore=\"\"\n else\n # do not add cert to array if already added\n if [[ ! \" ${instCertsArr[@]} \" =~ \" ${line} \" ]]; then\n instCertsArr+=(\"$line\")\n fi\n fi\n fi\n done\n done /dev/null 2>&1)\n if ! [ -z \"$hasKey\" ];then\n deleteKeys+=(\"${cert%.*}.key\")\n fi\n done\n}\n\nfunction deleteUnusedCerts {\n\n if [ ${#deleteCerts[@]} -eq 0 ]; then\n echo \"-------------------------------------------------------------------------\"\n echo \"There are no unused certificates to delete, existing\"\n echo \"-------------------------------------------------------------------------\"\n exit 0\n else\n echo \"-------------------------------------------------------------------------\"\n echo \"The following keys are not in use can can be deleted:\"\n for cert in \"${deleteCerts[@]}\"; do\n echo \" ${cert}\"\n done\n echo \"-------------------------------------------------------------------------\"\n read -p \"would you like to delete these unused certificates? (y/n)?\" answer\n case ${answer:0:1} in\n y|Y )\n createUcsArchive\n echo \"-------------------------------------------------------------------------\"\n echo \"deleting certs...\"\n for cert in \"${deleteCerts[@]}\"; do\n delete sys file ssl-key $cert\n echo \" $cert\"\n done\n\n if [ ${#deleteKeys[@]} -eq 0 ]; then\n echo \"-------------------------------------------------------------------------\"\n echo \"no associated keys to delete, exiting\"\n exit 0\n else\n echo \"-------------------------------------------------------------------------\"\n echo \"deleting keys...\"\n for key in \"${deleteKeys[@]}\"; do\n delete sys file ssl-key $cert\n echo \"$key\"\n exit 0\n done\n fi\n ;;\n * )\n exit 0\n ;;\n esac\n fi\n}\n\nfunction createUcsArchive {\n echo\n today=`date +%Y-%m-%d.%H.%M.%S`\n echo \"Creating UCS archive auto.${today}.ucs\"\n tmsh save sys ucs ${today}.ucs\n}\n\n# initialise vars\ninstCertsArr=()\ndeleteCerts=()\n\n# ignore certs defined here - f5-irile.crt is used to sign F5 iRules\nignoreCerts=(\"f5-irule.crt\" \"ca-bundle.crt\")\n\n# build installed certificates array - excluding certs to ignore\nbuildInstalledCertsArray\n\n# check if installed certs are used in bigip.conf (including partitions) - ltm sys files are exluded from results\nbuildDeleteCertsArray\n\n# build list of associated keys (not all certs will have keys)\nbuildDeleteKeysArray\n\n# optionally delete unused certs\ndeleteUnusedCerts Tested this on version: No Version Found","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"5078","kudosSumWeight":3,"repliesCount":7,"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:274252":{"__typename":"Conversation","id":"conversation:274252","topic":{"__typename":"TkbTopicMessage","uid":274252},"lastPostingActivityTime":"2020-12-14T08:34:23.000-08:00","solved":false},"User:user:62704":{"__typename":"User","uid":62704,"login":"MAG_114141","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:62704"},"TkbTopicMessage:message:274252":{"__typename":"TkbTopicMessage","subject":"Complete F5 Automated Backup Solution #2","conversation":{"__ref":"Conversation:conversation:274252"},"id":"message:274252","revisionNum":1,"uid":274252,"depth":0,"board":{"__ref":"Tkb:board:codeshare"},"author":{"__ref":"User:user:62704"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":2169},"postTime":"2016-08-21T04:56:06.000-07:00","lastPublishTime":"2016-08-21T04:56:06.000-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Problem this snippet solves: On TMOS 12.1 smbclient do not exist any more.\nBut mount.cifs still exist. \n In attachment you can find modified original iApp by Thomas Schockaert\nwhich use mount.cifs. Code : 70074 Tested this on version: 12.0","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"244","kudosSumWeight":0,"repliesCount":17,"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:290824":{"__typename":"Conversation","id":"conversation:290824","topic":{"__typename":"TkbTopicMessage","uid":290824},"lastPostingActivityTime":"2020-05-06T05:53:26.000-07:00","solved":false},"User:user:321935":{"__typename":"User","uid":321935,"login":"SamL","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:321935"},"TkbTopicMessage:message:290824":{"__typename":"TkbTopicMessage","subject":"f5-admin Python API Release","conversation":{"__ref":"Conversation:conversation:290824"},"id":"message:290824","revisionNum":1,"uid":290824,"depth":0,"board":{"__ref":"Tkb:board:codeshare"},"author":{"__ref":"User:user:321935"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":850},"postTime":"2020-01-01T20:01:54.000-08:00","lastPublishTime":"2020-01-01T20:01:54.000-08:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Problem this snippet solves: A complete F5 Admin API Python package. This is built for F5 security administrators. It works by providing a direct hook to the F5 TMOS Command Line Interface. Then you can manage F5 configuration objects by using your Python-Fu. Furthermore, the security admin can go to the next level of the playing field, by custom buildout the automation procedures in the full-stack capable, object-oriented Python programming language from there. Real world examples developed to solve my daily F5 secure admin chores can be found under the 'src/bin' folder. Enjoy. How to use this snippet: # !/usr/bin/env python # Let's build a tool together\nimport f5_admin # First we need to let Python know we're going to use the API\nf5_node = \"xx-rhwebdev1\" # The F5 node we want to connect to.\nf5_command = \"show sys software\" # The F5 command we want to run\nwith f5_admin.F5Client(None,None,None) as client:\n client.load(f5_node) # Now we're ready to open a remote connection\n result=client.ssh_command(client.ssh_connect(),f5_command,\"\")\n for line in result: # line print the F5 command result in the console\n print(line)\n\n# Congratulation. You just build an automation tool with the API!\n Test Run the Tool Copy the above code block in a text editor. Then save it into a file name 'test.py'. Or Download it as raw file. Then you can test run the tool as below: $ python test.py\nLoading cache_config: /Library/Python/2.7/site-packages/f5_admin-1.0.0-py2.7.egg/f5_admin/conf/xx-rhwebdev1/xx-rhwebdev1.txt\nLoading complete\nSetting up remote SSH session to host: xx-rhwebdev1\nPlease enter the F5 user name:\nPlease enter the F5 password:\nExecution on the remote SSH host: show sys software\nCommand execution complete.\n\n\n\n----------------------------------------------------------\n\nSys::Software Status\n\nVolume Slot Product Version Build Active Status\n\n\n Congratulation! You just build your first tool using this Python package. Please use the url below for more usage guidelines: https://github.com/yangsec888/f5-admin/blob/master/API.md Tested this on version: 13.0","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"2204","kudosSumWeight":0,"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:289137":{"__typename":"Conversation","id":"conversation:289137","topic":{"__typename":"TkbTopicMessage","uid":289137},"lastPostingActivityTime":"2020-04-23T10:04:14.000-07:00","solved":false},"User:user:181046":{"__typename":"User","uid":181046,"login":"Leonardo_Souza","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/m_assets/avatars/default/avatar-1.svg?time=0"},"id":"user:181046"},"TkbTopicMessage:message:289137":{"__typename":"TkbTopicMessage","subject":"External Monitor Templates","conversation":{"__ref":"Conversation:conversation:289137"},"id":"message:289137","revisionNum":1,"uid":289137,"depth":0,"board":{"__ref":"Tkb:board:codeshare"},"author":{"__ref":"User:user:181046"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":1014},"postTime":"2020-04-23T10:04:14.000-07:00","lastPublishTime":"2020-04-23T10:04:14.000-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Problem this snippet solves: Use the following scripts as templates to create your own BIG-IP external monitors. How to use this snippet: Tested this on version: No Version Found","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"186","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-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/community/Navbar-1744046271000","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-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/community/NavbarHamburgerDropdown-1744046271000","value":{"hamburgerLabel":"Side Menu"},"localOverride":false},"CachedAsset:text:en_US-components/community/BrandLogo-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/community/BrandLogo-1744046271000","value":{"logoAlt":"Khoros","themeLogoAlt":"Brand Logo"},"localOverride":false},"CachedAsset:text:en_US-components/community/NavbarTextLinks-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/community/NavbarTextLinks-1744046271000","value":{"more":"More"},"localOverride":false},"CachedAsset:text:en_US-components/authentication/AuthenticationLink-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/authentication/AuthenticationLink-1744046271000","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-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/nodes/NodeLink-1744046271000","value":{"place":"Place {name}"},"localOverride":false},"CachedAsset:text:en_US-components/tags/TagSubscriptionAction-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/tags/TagSubscriptionAction-1744046271000","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-shared/client/components/common/QueryHandler-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/QueryHandler-1744046271000","value":{"title":"Query Handler"},"localOverride":false},"CachedAsset:text:en_US-components/community/NavbarDropdownToggle-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/community/NavbarDropdownToggle-1744046271000","value":{"ariaLabelClosed":"Press the down arrow to open the menu"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageListTabs-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageListTabs-1744046271000","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-components/messages/MessageView/MessageViewInline-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageView/MessageViewInline-1744046271000","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-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/Pager/PagerLoadMore-1744046271000","value":{"loadMore":"Show More"},"localOverride":false},"CachedAsset:text:en_US-components/customComponent/CustomComponent-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/customComponent/CustomComponent-1744046271000","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-shared/client/components/common/OverflowNav-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/OverflowNav-1744046271000","value":{"toggleText":"More"},"localOverride":false},"CachedAsset:text:en_US-components/users/UserLink-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/users/UserLink-1744046271000","value":{"authorName":"View Profile: {author}","anonymous":"Anonymous"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageSubject-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageSubject-1744046271000","value":{"noSubject":"(no subject)"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageBody-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageBody-1744046271000","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-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageTime-1744046271000","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-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/nodes/NodeIcon-1744046271000","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-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageUnreadCount-1744046271000","value":{"unread":"{count} unread","comments":"{count, plural, one { unread comment} other{ unread comments}}"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageViewCount-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageViewCount-1744046271000","value":{"textTitle":"{count, plural,one {View} other{Views}}","views":"{count, plural, one{View} other{Views}}"},"localOverride":false},"CachedAsset:text:en_US-components/kudos/KudosCount-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/kudos/KudosCount-1744046271000","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-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageRepliesCount-1744046271000","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-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/users/UserAvatar-1744046271000","value":{"altText":"{login}'s avatar","altTextGeneric":"User's avatar"},"localOverride":false}}}},"page":"/tags/TagPage/TagPage","query":{"messages.widget.messagelistfornodebyrecentactivitywidget-tab-main-messages-list-for-tag-widget-0":"mostRecent","nodeId":"board:codeshare","tagName":"TMOS"},"buildId":"ISAhs0UxT148eG089lpQq","runtimeConfig":{"buildInformationVisible":false,"logLevelApp":"info","logLevelMetrics":"info","openTelemetryClientEnabled":false,"openTelemetryConfigName":"f5","openTelemetryServiceVersion":"25.3.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":[]}